前期准备
首先创建一个web项目,并整合lombok。可以参考之前的文章SpringBoot快速构建web项目-多模块项目
定义返回格式与返回状态码
返回状态码
@ToString
@Getter
public enum ResultStatus {
SUCCESS(HttpStatus.OK, 200, "OK"),
BAD_REQUEST(HttpStatus.BAD_REQUEST, 400, "Bad Request"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 500, "Internal Server Error"),;
/**
* 返回的HTTP状态码, 符合http请求
*/
private HttpStatus httpStatus;
/**
* 业务异常码
*/
private Integer code;
/**
* 业务异常信息描述
*/
private String message;
ResultStatus(HttpStatus httpStatus, Integer code, String message) {
this.httpStatus = httpStatus;
this.code = code;
this.message = message;
}
}
统一返回格式
@Getter
@ToString
public class Result<T> {
/**
* 业务错误码
*/
private final Integer code;
/**
* 信息描述
*/
private final String message;
/**
* 返回参数
*/
private final T data;
private Result(ResultStatus resultStatus, T data) {
this.code = resultStatus.getCode();
this.message = resultStatus.getMessage();
this.data = data;
}
/**
* 业务成功返回业务代码和描述信息
* @return Result
*/
public static Result<Void> success() {
return new Result<Void>(ResultStatus.SUCCESS, null);
}
/**
* 业务成功返回业务代码,描述和返回的参数
* @param data data
* @param <T> data
* @return Result
*/
public static <T> Result<T> success(T data) {
return new Result<T>(ResultStatus.SUCCESS, data);
}
/**
* 业务成功返回业务代码,描述和返回的参数
* @param resultStatus resultStatus
* @param data data
* @param <T> data
* @return Result
*/
public static <T> Result<T> success(ResultStatus resultStatus, T data) {
if (resultStatus == null) {
return success(data);
}
return new Result<T>(resultStatus, data);
}
/**
* 业务异常返回业务代码和描述信息
* @param <T> data
* @return Result
*/
public static <T> Result<T> failure() {
return new Result<T>(ResultStatus.INTERNAL_SERVER_ERROR, null);
}
/**
* 业务异常返回业务代码,描述和返回的参数
* @param resultStatus resultStatus
* @param <T> data
* @return Result
*/
public static <T> Result<T> failure(ResultStatus resultStatus) {
return failure(resultStatus, null);
}
/**
* 业务异常返回业务代码,描述和返回的参数
* @param resultStatus resultStatus
* @param data data
* @param <T> data
* @return Result
*/
public static <T> Result<T> failure(ResultStatus resultStatus, T data) {
if (resultStatus == null) {
return new Result<T>(ResultStatus.INTERNAL_SERVER_ERROR, null);
}
return new Result<T>(resultStatus, data);
}
}
标识需要统一返回结果的注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@ResponseBody
public @interface ResponseResultBody {
}
自定义异常类
@Getter
public class ResultException extends Exception {
/**
* 业务异常信息信息
*/
ResultStatus resultStatus;
public ResultException() {
this(ResultStatus.INTERNAL_SERVER_ERROR);
}
public ResultException(ResultStatus resultStatus) {
super(resultStatus.getMessage());
this.resultStatus = resultStatus;
}
}
配置类
@Slf4j
@RestControllerAdvice
public class ResponseResultBodyAdvice implements ResponseBodyAdvice<Object> {
private static final Class<? extends Annotation> ANNOTATION_TYPE = ResponseResultBody.class;
/**
* 判断类或者方法是否使用了 @ResponseResultBody
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ANNOTATION_TYPE)
|| returnType.hasMethodAnnotation(ANNOTATION_TYPE);
}
/**
* 当类或者方法使用了 @ResponseResultBody 就会调用这个方法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof String) {
ObjectMapper om = new ObjectMapper();
try {
return om.writeValueAsString(Result.success(body));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
// 防止重复包裹的问题出现
if (body instanceof Result) {
return body;
}
return Result.success(body);
}
/**
* 提供对标准Spring MVC异常的处理
*
* @param ex the target exception
* @param request the current request
*/
@ExceptionHandler(Exception.class)
public final ResponseEntity<Result<?>> exceptionHandler(Exception ex, WebRequest request) {
log.error("ExceptionHandler: {}", ex.getMessage());
HttpHeaders headers = new HttpHeaders();
if (ex instanceof ResultException) {
return this.handleResultException((ResultException) ex, headers, request);
}
return this.handleException(ex, headers, request);
}
/** 对ResultException类返回返回结果的处理 */
protected ResponseEntity<Result<?>> handleResultException(ResultException ex, HttpHeaders headers, WebRequest request) {
Result<?> body = Result.failure(ex.getResultStatus());
HttpStatus status = ex.getResultStatus().getHttpStatus();
return this.handleExceptionInternal(ex, body, headers, status, request);
}
/** 异常类的统一处理 */
protected ResponseEntity<Result<?>> handleException(Exception ex, HttpHeaders headers, WebRequest request) {
Result<?> body = Result.failure();
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return this.handleExceptionInternal(ex, body, headers, status, request);
}
/**
* org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler#handleExceptionInternal(java.lang.Exception, java.lang.Object, org.springframework.http.HttpHeaders, org.springframework.http.HttpStatus, org.springframework.web.context.request.WebRequest)
* <p>
* A single place to customize the response body of all exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
*/
protected ResponseEntity<Result<?>> handleExceptionInternal(
Exception ex, Result<?> body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<>(body, headers, status);
}
}
业务类
实体类
@Data
public class Salesbill {
private long id;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
private long customerID;
private long categoryID;
private double price;
private double grossWeight;
private double tareWeight;
private String remack;
private long address;
private String createName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
控制器
@RestController
@RequestMapping("Salesbill")
@ResponseResultBody
public class SalesbillController {
@GetMapping("{id}")
public Salesbill getSalesbillById(@PathVariable("id") long id){
int num= 10/0;//测试报错
return new Salesbill();
}
@PostMapping
public Salesbill insert(@RequestBody Salesbill salesbill){
return salesbill;
}
@PutMapping
public Salesbill update(@RequestBody Salesbill salesbill){
return salesbill;
}
@DeleteMapping("{ids}")
public boolean deleteById(@PathVariable("ids") Long[] ids){
return true;
}
}
返回结果
成功结果
{
"code": 200,
"message": "OK",
"data": {
"id": 0,
"date": "2020-11-21",
"customerID": 2,
"categoryID": 2,
"price": 2,
"grossWeight": 10,
"tareWeight": 2,
"remack": "测试",
"address": 1,
"createName": "樊光瑞",
"createTime": "2020-11-21 10:00:00"
}
}
报错结果
{
"code": 500,
"message": "Internal Server Error",
"data": null
}