开发者

springboot项目controller统一返回对象格式以及全局自定义异常方式

目录
  • 一、需求背景
  • 二、方法
    • 解决方法
  • 三、具体实现
    • 四、遇到的问题
      • 当项目中使用swagger时,会拦截swagger的相关请求
    • 总结

      一、需求背景

      1.在web接口开发时,每个模块接口返回数据格式需做封装,如果每个模块的返回格式不同,前端需要最不同数据格式的适配,使得整个项目很杂乱。如果对接口的返回数据做统一封装就解决此类问题。

      2.项目的运行时异常,例如用户名错误此类的提示性异常,需要对此类异常做统一性封装。

      二、方法

      解决方法

      问题一:使用@ControllerAdvice注解,以及实现ResponseBodyAdvice接口,从而实现拦截后再封装逻辑

      问题二:使用@ControllandroiderAdvice和@ExceptionHandler注解配合使用,从而捕获自定义异常类,实现逻辑的再处理。

      三、具体实现

      /**
      *封装的接口统一返回对象
      */
      @Data
      public class ResultPo<T> {
          private int code;
          private String msg;
          private T data;
      
          public static<T> ResultPo<T> success(T t){
              ResultPo<T> resultPo = new ResultPo<>();
              resultPo.setCode(ResponseCodeEnum.SUCCESS.getCode());
              resultPo.setMsg(ResponseCodeEnum.SUCCESS.getMessage());
              resultPo.setData(t);
           编程客栈   return resultPo;
          }
      
          public static ResultPo error(int code,String msg){
              ResultPo resultPo = new ResultPo();
              resultPo.setCode(code);
              resultPo.setMsg(msg);
              return resultPo;
          }
      }
      
      // 自定义异常类
      @Getter
      public class BusinessException extends RuntimeException{
          private String msg;
          private int code;
      
          public  BusinessException(String msg){
              super(msg);
              this.msg =msg;
              this.code = ResponseCodeEnum.FAIL.getCode();
          }
      
          public  BusinessException(String msg,int code){
              super(msg);
              this.msg =msg;
              this.code = code;
          }
      }
      
      
      @ResponseBody
      @ControllerAdvice
      public class ResponseAdvice implements ResponseBodyAdvice<Object> {
      
          Logger log = LoggerFactory.getLogger(ResponseAdvice.class);
      
      	// 自定义异常捕获
          @ExceptionHandler(BusinessException.class)
          public ResultPo customExceptiophpn(BusinessException bs){
              ResultPo resultPo = new ResultPo();
              resultPo.setCode(bs.getCode());
              resultPo.setMsg(bs.getMsg());
              resultPo.setData(null);
              return resultPo;
          }
      	
      	/**
      	*return turn 代表此接口会进入beforeBodyWrite方法,进行逻辑处理
      	*/
          @Override
          public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
              return !returnType.getDeclaringClass().getName().contains("springfox");
      //        return true;
          }
      
          @Nullable
          @Override
          public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequpythonest request, ServerHttpResponse response) {
          	// 如果接口返回为string类型,则需要单独处理
              if(returnType.getGenericParameterType().equals(String.class)){
                  ObjectMapper objectMapper = new ObjectMapper();
                  try {
                      HttpHeaders hejavascriptaders = response.getHeaders();
                      headers.setContentType(MediaType.APPLICATION_jsON);
                      return objectMapper.writeValueAsString(ResultPo.success(body));
                  } catch (JsonProcessingException e) {
                      e.printStackTrace();
                  }
              }
              // 接口出现自定义异常,已被customException方法捕获,则无需再次封装
              if(returnType.getGenericParameterType().equals(ResultPo.class)){
                  return body;
              }
              return ResultPo.success(body);
          }
      }
      

      四、遇到的问题

      当项目中使用swagger时,会拦截swagger的相关请求

      出现的原因:@ControllerAdvice注解会拦截@Controller以及@RestController标记的接口,而swagger的接口是web接口,也是带有@RestController相关接口

      解决方法:

      1.对swagger进行放行,就是上面代码中那样,放行带有springfox字样的接口

      @Override
          public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
              return !returnType.getDeclaringClass().getName().contains("springfox");
      //        return true;
          }
      

      2.自定义一个注解,在需要统一返回值的接口上添加上自定义注解,然后@ControllerAdvice根据自定义注解进行拦截

      // ResponseResult为自定义注解
      @ControllerAdvice(annotations = ResponseResult.class)
      

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜