返回实体类
一、自定义返回对象
在工作中,接手项目上看到项目中使用的返回对象是自己封装的,虽然拓展性并不是很高,但是在实际开发过程中使用也够用,状态码通过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 协议 ,转载请注明出处!