本文想法是在Controller最外层返回时封装一个结构,减少冗余代码。
本文涉及技术点:枚举,范型,重写框架ResponseBody返回代码 2020.1.2—1.0 初版 对于controller类返回统一封装 2020.1.2—1.1 对异常情况处理,利用aop切面实现
一、前提背景
1、Controller代码如下
@Controllerpublic class TestController {@GetMapping("/test")@ResponseBody //当类使用RestController可以不需要此标注public String test() {String text = "do something";System.out.println(text);return text;}}
2、此时postman测试调用后发现结果不美观
3、发生错误时,返回信息也没有进行封装。
二、设计思路
1、构建一个配置类实现InitializingBean接口,
2、在创建bean时修改HandlerMethodReturnValueHandler中RequestResponseBodyMethodProcessor代码
3、封装一个统一返回结果
4、封装一个自定义异常类,继承RuntimeException异常,结合返回枚举。
5、处理类利用@ControllerAdvice切面处理,方法使用@ExceptionHandler,@ResponseBody直接返回前台
三、代码演示
1、回参信息枚举类
package com.vvvv.util.returnHandler;/*** 返回信息枚举*/public enum ReturnInfoEnum {SUCCESS(0,"success"),ERROR(-1,"error"),NET_ERROR(-9001,"network error."),UNKNOWN_ERROR(-9999,"unknow error."),;private Integer code;private String msg;ReturnInfoEnum(int code, String msg) {this.code = code;this.msg = msg;}public int getCode() {return code;}public String getMsg() {return msg;}}
2、统一返回类方法封装
package com.vvvv.util.returnHandler;import lombok.Data;/*** @ClassName Return* @Description 返回类方法封装* @Author vvvv* @Date 2021/1/2 19:37* @Version V1.0*/@Datapublic class Return<T> {private Integer code;private String msg;private T data;private Return(Integer code, String msg) {this.code = code;this.msg = msg;}private Return(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public static <T> Return<T> success() {return new Return<T>(ReturnInfoEnum.SUCCESS.getCode(),ReturnInfoEnum.SUCCESS.getMsg());}public static <T> Return<T> success(T data) {return new Return<>(ReturnInfoEnum.SUCCESS.getCode(),ReturnInfoEnum.SUCCESS.getMsg(), data);}public static <T> Return<T> error(Integer code, String msg) {return new Return<>(code, msg);}}
3、构建配置类 RenturnHandlerAdapter
/*** @ClassName RenturnHandlerAdapter* @Description 接口返回统一处理配置类* @Author vvvv* @Date 2021/1/2 19:41* @Version V1.0*/@Configuration // 声明是spring配置,创建bean@RequiredArgsConstructor // 构建有参构造函数public class RenturnHandlerAdapter implements InitializingBean {// 获取到RequestMappingHandlerAdapter的结果private final RequestMappingHandlerAdapter handlerAdapter;@Overridepublic void afterPropertiesSet() {// 根据适配器拿到返回处理集合List<HandlerMethodReturnValueHandler> returnValueHandlers =handlerAdapter.getReturnValueHandlers();List<HandlerMethodReturnValueHandler> newList = new ArrayList<>();// RequestResponseBodyMethodProcessor// 构建新类实现HandlerMethodReturnValueHandler接口// 重写接口,完成Objects.requireNonNull(returnValueHandlers).forEach(t -> {if (t instanceof RequestResponseBodyMethodProcessor)newList.add(new ReturnHandlerAdaptProxy(t));else newList.add(t);});// 将新处理集合放回适配器中handlerAdapter.setReturnValueHandlers(newList);}}
4、接口返回统一处理类 ReturnHandlerAdaptProxy
/*** @ClassName ReturnHandlerAdaptProxy* @Description 接口返回统一处理类* @Author vvvv* @Date 2021/1/2 19:49* @Version V1.0*/public class ReturnHandlerAdaptProxy implements HandlerMethodReturnValueHandler {private final HandlerMethodReturnValueHandler proxyObject;public ReturnHandlerAdaptProxy(HandlerMethodReturnValueHandler proxyObject) {this.proxyObject = proxyObject;}@Overridepublic boolean supportsReturnType(MethodParameter returnType) {return proxyObject.supportsReturnType(returnType);}@Overridepublic void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,NativeWebRequest webRequest) throws Exception {Return result =returnValue == null ? Return.success() : Return.success(returnValue);// 此处对Object进行封装返回即可proxyObject.handleReturnValue(result, returnType, mavContainer, webRequest);}}
5、自定义异常类
@Getter //lombok getter注解//继承RuntimeExceptionpublic class VurxException extends RuntimeException {//错误编码private final Integer code;public VurxException(ReturnInfoEnum resultEnum) {// 调用父类构造方法,将错误信息写入super(resultEnum.getMsg());// 补充错误编码this.code = resultEnum.getCode();}}
6、异常处理类
@ControllerAdvice // 环绕controller切面@Slf4j // lombok注解public class ExceptionHandle {// !!!抛出异常自动进入该方法!!!@ExceptionHandler(value = Exception.class)@ResponseBody // 返回前台结果public Return<Object> handle(Exception e) {log.error("======ERROR=========================================================================", e);// 异常类型属于自定义异常时封装返回前台if (e instanceof VurxException) {VurxException vurxException = (VurxException) e;return Return.error(vurxException.getCode(), vurxException.getMessage());}// 其他异常抛出未知异常return Return.error(ReturnInfoEnum.UNKNOWN_ERROR.getCode(), e.getMessage());}}
四、测试代码
1、统一返回测试
a、测试controller
@Controllerpublic class TestController {@GetMapping("/test")@ResponseBody //当类使用RestController可以不需要此标注public String test() {String text = "do something";System.out.println(text);return text;}}
b、成功结果
2、异常测试
a、Controller类
@Controllerpublic class TestController {@GetMapping("/test")@ResponseBodypublic String test() {String text = "do something";if (text.startsWith("do")) {throw new VurxException(ReturnInfoEnum.NET_ERROR);} else {return text;}}}
b、效果演示

