返回实体类

一、自定义返回对象

在工作中,接手项目上看到项目中使用的返回对象是自己封装的,虽然拓展性并不是很高,但是在实际开发过程中使用也够用,状态码通过map中进行返回,前端解析返回的数据带的是什么状态码。、

弊端:

​ 1.不支持泛型,有可能出现类型转换异常

​ 2.返回状态码目前没有定义枚举,需要有经验的程序员充分理解状态码,而达到对项目状态码返回的统一,(例 代码执行错误,有些返回500,有些人会返回501等等)

​ 3.不能支持对请求头的修改

package com.msdw.tms.common.utils;

import org.apache.http.HttpStatus;

import java.util.HashMap;
import java.util.Map;

/**
 * 返回数据
 *
 * @author Mark sunlightcs@gmail.com
 */
public class R extends HashMap<String, Object> {
	private static final long serialVersionUID = 1L;
	
	public R() {
		put("status", 200);
		put("errmessage", "success");
	}
	
	public static R error() {
		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
	}
	
	public static R error(String msg) {
		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
	}
	
	public static R error(int code, String msg) {
		R r = new R();
		r.put("status", code);
		r.put("errmessage", msg);
		return r;
	}

	public static R ok(String msg) {
		R r = new R();
		r.put("errmessage", msg);
		return r;
	}
	
	public static R ok(Map<String, Object> map) {
		R r = new R();
		r.putAll(map);
		return r;
	}
	
	public static R ok() {
		return new R();
	}

	public R put(String key, Object value) {
		super.put(key, value);
		return this;
	}
}

二、MybatisPlus R

MybatisPuls 也有自带ApiController,可以作为项目的通用规范,但是由于使用度较低,在3.5.0的版本中就将其移除

package com.baomidou.mybatisplus.extension.api;

import java.io.Serializable;
import java.util.Optional;

import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;

import lombok.Data;
import lombok.experimental.Accessors;

/**
 * REST API 返回结果
 *
 * @author hubin
 * @since 2018-06-05
 */
@Data
@Accessors(chain = true)
public class R<T> implements Serializable {

    /**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1L;
	
	/**
     * 业务错误码
     */
    private long code;
    /**
     * 结果集
     */
    private T data;
    /**
     * 描述
     */
    private String msg;

    public R() {
        // to do nothing
    }

    public R(IErrorCode errorCode) {
        errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.FAILED);
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
    }

    public static <T> R<T> ok(T data) {
        ApiErrorCode aec = ApiErrorCode.SUCCESS;
        if (data instanceof Boolean && Boolean.FALSE.equals(data)) {
            aec = ApiErrorCode.FAILED;
        }
        return restResult(data, aec);
    }

    public static <T> R<T> failed(String msg) {
        return restResult(null, ApiErrorCode.FAILED.getCode(), msg);
    }

    public static <T> R<T> failed(IErrorCode errorCode) {
        return restResult(null, errorCode);
    }

    public static <T> R<T> restResult(T data, IErrorCode errorCode) {
        return restResult(data, errorCode.getCode(), errorCode.getMsg());
    }

    private static <T> R<T> restResult(T data, long code, String msg) {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }

    public boolean ok() {
        return ApiErrorCode.SUCCESS.getCode() == code;
    }

    /**
     * 服务间调用非业务正常,异常直接释放
     */
    public T serviceData() {
        if (!ok()) {
            throw new ApiException(this.msg);
        }
        return data;
    }
}

三、Spring ResponseEntity

新项目的开展,项目返回实体类我申请使用ResponseEntity作为项目的返回实体,可以充分解决原公司使用实体不好拓展的情况,并且更加安全可靠。

接下来贴出源码中的五个构造方法

public class ResponseEntity<T> extends HttpEntity<T> {

   private final Object status;


   /**
    * Create a new {@code ResponseEntity} with the given status code, and no body nor headers.
    * @param status the status code
    */
   public ResponseEntity(HttpStatus status) {
      this(null, null, status);
   }

   /**
    * Create a new {@code ResponseEntity} with the given body and status code, and no headers.
    * @param body the entity body
    * @param status the status code
    */
   public ResponseEntity(@Nullable T body, HttpStatus status) {
      this(body, null, status);
   }

   /**
    * Create a new {@code HttpEntity} with the given headers and status code, and no body.
    * @param headers the entity headers
    * @param status the status code
    */
   public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus status) {
      this(null, headers, status);
   }

   /**
    * Create a new {@code HttpEntity} with the given body, headers, and status code.
    * @param body the entity body
    * @param headers the entity headers
    * @param status the status code
    */
   public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
      super(body, headers);
      Assert.notNull(status, "HttpStatus must not be null");
      this.status = status;
   }

   /**
    * Create a new {@code HttpEntity} with the given body, headers, and status code.
    * Just used behind the nested builder API.
    * @param body the entity body
    * @param headers the entity headers
    * @param status the status code (as {@code HttpStatus} or as {@code Integer} value)
    */
   private ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, Object status) {
      super(body, headers);
      Assert.notNull(status, "HttpStatus must not be null");
      this.status = status;
   }

这里设计有意思的是,不管走那个构造方法都会调用到父类的方法 super(body, headers);中

public class HttpEntity<T> {

   /**
    * The empty {@code HttpEntity}, with no body or headers.
    */
   public static final HttpEntity<?> EMPTY = new HttpEntity<>();


   private final HttpHeaders headers;

   @Nullable
   private final T body;


   /**
    * Create a new, empty {@code HttpEntity}.
    */
   protected HttpEntity() {
      this(null, null);
   }

   /**
    * Create a new {@code HttpEntity} with the given body and no headers.
    * @param body the entity body
    */
   public HttpEntity(T body) {
      this(body, null);
   }

   /**
    * Create a new {@code HttpEntity} with the given headers and no body.
    * @param headers the entity headers
    */
   public HttpEntity(MultiValueMap<String, String> headers) {
      this(null, headers);
   }

   /**
    * Create a new {@code HttpEntity} with the given body and headers.
    * @param body the entity body
    * @param headers the entity headers
    */
   public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) {
      this.body = body;
      HttpHeaders tempHeaders = new HttpHeaders();
      if (headers != null) {
         tempHeaders.putAll(headers);
      }
      this.headers = HttpHeaders.readOnlyHttpHeaders(tempHeaders);
   }

通过调用父类的方法,将body跟请求头headers返回的内容保存,而ResponseEntity只是对父类进行拓展,增加状态码status,而spring对状态码也有封装(spring就是贴心)做到开箱即用。以下贴出部分方法。

public enum HttpStatus {

   // 1xx Informational

   /**
    * {@code 100 Continue}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.2.1">HTTP/1.1: Semantics and Content, section 6.2.1</a>
    */
   CONTINUE(100, "Continue"),
   /**
    * {@code 101 Switching Protocols}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.2.2">HTTP/1.1: Semantics and Content, section 6.2.2</a>
    */
   SWITCHING_PROTOCOLS(101, "Switching Protocols"),
   /**
    * {@code 102 Processing}.
    * @see <a href="https://tools.ietf.org/html/rfc2518#section-10.1">WebDAV</a>
    */
   PROCESSING(102, "Processing"),
   /**
    * {@code 103 Checkpoint}.
    * @see <a href="https://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal">A proposal for supporting
    * resumable POST/PUT HTTP requests in HTTP/1.0</a>
    */
   CHECKPOINT(103, "Checkpoint"),

   // 2xx Success

   /**
    * {@code 200 OK}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">HTTP/1.1: Semantics and Content, section 6.3.1</a>
    */
   OK(200, "OK"),
   /**
    * {@code 201 Created}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.2">HTTP/1.1: Semantics and Content, section 6.3.2</a>
    */
   CREATED(201, "Created"),
   /**
    * {@code 202 Accepted}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.3">HTTP/1.1: Semantics and Content, section 6.3.3</a>
    */
   ACCEPTED(202, "Accepted"),
   /**
    * {@code 203 Non-Authoritative Information}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.4">HTTP/1.1: Semantics and Content, section 6.3.4</a>
    */
   NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
   /**
    * {@code 204 No Content}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.5">HTTP/1.1: Semantics and Content, section 6.3.5</a>
    */
   NO_CONTENT(204, "No Content"),
   /**
    * {@code 205 Reset Content}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.6">HTTP/1.1: Semantics and Content, section 6.3.6</a>
    */
   RESET_CONTENT(205, "Reset Content"),
   /**
    * {@code 206 Partial Content}.
    * @see <a href="https://tools.ietf.org/html/rfc7233#section-4.1">HTTP/1.1: Range Requests, section 4.1</a>
    */
   PARTIAL_CONTENT(206, "Partial Content"),
   /**
    * {@code 207 Multi-Status}.
    * @see <a href="https://tools.ietf.org/html/rfc4918#section-13">WebDAV</a>
    */
   MULTI_STATUS(207, "Multi-Status"),
   /**
    * {@code 208 Already Reported}.
    * @see <a href="https://tools.ietf.org/html/rfc5842#section-7.1">WebDAV Binding Extensions</a>
    */
   ALREADY_REPORTED(208, "Already Reported"),
   /**
    * {@code 226 IM Used}.
    * @see <a href="https://tools.ietf.org/html/rfc3229#section-10.4.1">Delta encoding in HTTP</a>
    */
   IM_USED(226, "IM Used"),

   // 3xx Redirection

   /**
    * {@code 300 Multiple Choices}.
    * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.1">HTTP/1.1: Semantics and Content, section 6.4.1</a>
    */
   MULTIPLE_CHOICES(300, "Multiple Choices"),

记录以下对返回实体类的研究,对ResponseEntity的用法,返回有俩种方式。一种是采用静态方法

@GetMapping("/list")
    @ApiOperation(value = " 列表", response = GpAgLishihangqing.class)
    public ResponseEntity listByEntity() {
        List<GpAgLishihangqing> list = service.list();
        return ResponseEntity.status(HttpStatus.OK).body(list);
    }

另一种是new一个实体类对象

@GetMapping("/list")
@ApiOperation(value = " 列表", response = GpAgLishihangqing.class)
public ResponseEntity listByEntity() {
    List<GpAgLishihangqing> list = service.list();
    return new ResponseEntity<>(list, HttpStatus.OK);
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

Nacos配置管理 Previous
Java8Stream流 Next