JAVA 使用 Spring MVC 无侵入式的统一接口格式返回
1,创建 Result 类
@Getter
@ToString
public class Result<T> {
/**
* 业务错误吗
*/
private Integer code;
private String message;
private T data;
private Result(ResultStatus resultStatus, T data) {
this.code = resultStatus.getCode();
this.message = resultStatus.getMessage();
this.data = data;
}
/** 业务成功返回业务代码和描述信息 */
private static Result<Void> success(){
return new Result<Void>(ResultStatus.SUCCESS,null);
}
/** 业务成功返回业务代码,描述和返回的参数 */
public static <T> Result<T> success(T data) {
return new Result<T>(ResultStatus.SUCCESS, data);
}
/** 业务成功返回业务代码,描述和返回的参数 */
public static <T> Result<T> success(ResultStatus resultStatus, T data) {
if (resultStatus == null) {
return success(data);
}
return new Result<T>(resultStatus, data);
}
/** 业务异常返回业务代码和描述信息 */
public static <T> Result<T> failure() {
return new Result<T>(ResultStatus.INTERNAL_SERVER_ERROR, null);
}
/** 业务异常返回业务代码,描述和返回的参数 */
public static <T> Result<T> failure(ResultStatus resultStatus) {
return failure(resultStatus, null);
}
/** 业务异常返回业务代码,描述和返回的参数 */
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);
}
2,创建 定义状态码 Result Status 枚举类
@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;
}
}
3,创建一个 标记 在类和方法上可以 自动化生成 result 返回格式 注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@ResponseBody
public @interface ResponseResultBody {
}
4,创建 Result Excrption 返回 异常
@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;
}
}
5,创建一个 Advice 通知类 统一处理
/**
* 统一异常处理
* @ProjectName: quartz
* @Package: com.weng.quartz.advice
* @ClassName: ResponseResultBodyAdvice
* @Author: wym
* @Date: 2020/9/9 10:46
* @Version: 1.0
*/
@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 Result) {
return body;
}
//默认返回 SUCCESS
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) {
HttpHeaders headers = new HttpHeaders();
if (ex instanceof ResultException) {
return this.handleResultException((ResultException) ex, headers, request);
}
// TODO: 2019/10/05 galaxy 这里可以自定义其他的异常拦截
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);
}
}
测试方法:
@RestController
@RequestMapping("/helloResult")
@ResponseResultBody
public class HelloResultController {
private static final HashMap<String, Object> INFO;
static {
INFO = new HashMap<String, Object>();
INFO.put("name", "galaxy");
INFO.put("age", "70");
}
@GetMapping("hello")
public HashMap<String, Object> hello() {
return INFO;
}
/** 测试重复包裹 */
@GetMapping("result")
public Result<Map<String, Object>> helloResult() {
return Result.success(INFO);
}
@GetMapping("helloError")
public HashMap<String, Object> helloError() throws Exception {
throw new Exception("helloError");
}
@GetMapping("helloMyError")
public HashMap<String, Object> helloMyError() throws Exception {
throw new ResultException();
}
}
自动将其包含 在date 中