ResponseEntity 标识整个 http 相应:状态码、头部信息以及相应体内容。因此我们可以使用其对 http 响应实现完整配置。
目前打算使用 ResponseEntity 替代自定义实体响应对象。请教下如何有效的使用 ResponseEntity,比如@ResponseEntity
如何自定义返回业务的错误码?以及推荐使用 ResponseEntity 作为返回对象吗?
之前都是通过自定义code,msg,data
属性对象,通过@ResponseBody
返回给前端。
spring 封装了很多好用的东西,所以打算尝试下@ResponseEntity
:
@GetMapping("{id}")
public ResponseEntity<UserInfo> getUserById(@PathVariable("id") Long id) {
UserInfo user = userInfoService.getById(id);
boolean flag = ObjectUtils.isEmpty(user);
if (flag) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
上面的根据 id 查询用户,查询到内容就返回 200 状态码,查询不到就返回 404 。
但是有些业务有多个错误类型,这时用 ResponseEntity,只能返回 http 状态码就显得有些不足。
如果再封装个返回类型,ResponseResult 对象,里面存msg,code,data
。
@Data
@NoArgsConstructor
public class ResponseResult<T> {
@NonNull
private Integer code;
@NonNull
private String msg;
private T data;
}
然后再用ResponseEntity<ResponseResult>
封装返回给前端。
@GetMapping("{id}")
public ResponseEntity<ResponseResult<UserInfo>> getUserById(@PathVariable("id") Long id) {
UserInfo user = userInfoService.getById(id);
boolean flag = ObjectUtils.isEmpty(user);
if (flag) {
return ResponseEntity.notFound().build();
}
ResponseResult<UserInfo> userResult = new ResponseResult();
userResult.setData(user);
return ResponseEntity.ok(userResult);
}
这样会不会多此一举,不如直接用@ResponseBody
返回ResponseResult
就可以了。
当然,ResponseEntity 好处是可以返回 404 这些浏览器状态码。
1
hantsy 2020-06-24 11:06:20 +08:00
这种封装 ResponseResult 是脱了裤子放屁。
|
2
Oktfolio 2020-06-24 11:11:45 +08:00 1
package com.oktfolio.tero.common;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.google.common.base.Strings; import com.oktfolio.tero.common.enums.ResultCode; import com.oktfolio.tero.common.enums.ResultCodeEnum; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.time.LocalDateTime; import java.util.Objects; /** * @author oktfolio [email protected] * @date 2020/06/08 */ @JsonInclude(JsonInclude.Include.NON_NULL) public class ResultEntity<T> { protected String code; protected String message; protected T data; protected HttpStatus status; @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") protected LocalDateTime datetime; public String getCode() { return code; } public String getMessage() { return message; } public T getData() { return data; } public HttpStatus getStatus() { return status; } public LocalDateTime getDatetime() { return datetime; } private ResultEntity() { } public ResultEntity(String code, String message, T data, HttpStatus status, LocalDateTime datetime) { this.code = code; this.message = message; this.data = data; this.status = status; this.datetime = datetime; } public static Builder builder() { return new Builder(); } public static class Builder { protected String code; protected String message; protected HttpStatus status; protected LocalDateTime datetime; public Builder code(String code) { this.code = code; return this; } public Builder message(String message) { this.message = message; return this; } public Builder datetime(LocalDateTime datetime) { this.datetime = datetime; return this; } public Builder status(@Nonnull HttpStatus status) { this.status = status; return this; } public <T> ResultEntity<T> data(@Nullable T data) { return new ResultEntity<>(code, message, data, status, datetime); } public <T> ResultEntity<T> build() { return this.data(null); } } public static <T> ResultEntity<T> ok() { return ResultEntity.builder() .status(HttpStatus.OK) .build(); } public static <T> ResultEntity<T> created() { return ResultEntity.builder() .status(HttpStatus.CREATED) .build(); } public static <T> ResultEntity<T> noContent() { return ResultEntity.builder() .status(HttpStatus.NO_CONTENT) .build(); } public static <T> ResultEntity<T> ok(T data) { return ResultEntity.builder() .status(HttpStatus.OK) .datetime(LocalDateTime.now()) .data(data); } public static <T> ResultEntity<T> created(T data) { return ResultEntity.builder() .status(HttpStatus.CREATED) .data(data); } public static <T> ResultEntity<T> of(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(resultCode.status()) .code(resultCode.value()) .message(resultCode.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> error() { return ResultEntity.builder() .status(ResultCodeEnum.ERROR.status()) .code(ResultCodeEnum.ERROR.value()) .message(ResultCodeEnum.ERROR.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> error(@Nonnull HttpStatus status, @Nonnull String message) { return ResultEntity.builder() .status(status) .code(ResultCodeEnum.ERROR.value()) .message(message) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> notFound(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.NOT_FOUND) .code(resultCode.value()) .message(resultCode.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> badRequest(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.BAD_REQUEST) .code(resultCode.value()) .message(resultCode.message()) .build(); } public static <T> ResultEntity<T> unauthorized(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.UNAUTHORIZED) .code(resultCode.value()) .message(resultCode.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> unauthorized(String message) { return ResultEntity.builder() .status(HttpStatus.UNAUTHORIZED) .code(ResultCodeEnum.ERROR.value()) .message(message) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> forbidden(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.FORBIDDEN) .code(resultCode.value()) .message(resultCode.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> created(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.CREATED) .code(resultCode.value()) .message(resultCode.message()) .build(); } public static <T> ResultEntity<T> internalServerError() { return ResultEntity.builder() .status(ResultCodeEnum.INTERNAL_SERVER_ERROR.status()) .code(ResultCodeEnum.INTERNAL_SERVER_ERROR.value()) .message(ResultCodeEnum.INTERNAL_SERVER_ERROR.message()) .datetime(LocalDateTime.now()) .build(); } public static <T> ResultEntity<T> internalServerError(@Nonnull ResultCode resultCode) { return ResultEntity.builder() .status(HttpStatus.INTERNAL_SERVER_ERROR) .code(resultCode.value()) .message(resultCode.message()) .datetime(LocalDateTime.now()) .build(); } public ResponseEntity<Object> responseEntity() { if (Objects.isNull(this.data) && Strings.isNullOrEmpty(this.code) && Strings.isNullOrEmpty(this.message) && !Objects.isNull(this.status)) { return new ResponseEntity<>(this.getStatus()); } else { return new ResponseEntity<>(this, this.getStatus()); } } } 我是这么玩的。 |
3
hantsy 2020-06-24 11:15:12 +08:00 2
业务中所有正常路径直接返回,全部需要 Http Status 标志。如 200,201,204 。
使用 Spring 时,所有的异常路径可以封装成 Exception,集成处理。 Exception 处理除了要反应正确的 Http Status (常见的,除了一些安全框架 401,403 外,如 404,400,409,422 等),还可以带常见的辅助信息。如果非常要一个所谓的业务异常代码,在异常处理中加入。 https://github.com/hantsy/spring-microservice-sample/blob/master/post-service/src/main/java/com/hantsylabs/sample/springmicroservice/post/PostExceptionHandler.java#L31 |