博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Spring MVC的@ControllerAdvice注解做Json的异常处理
阅读量:5138 次
发布时间:2019-06-13

本文共 4417 字,大约阅读时间需要 14 分钟。

一,本文介绍Spring MVC的自定义异常处理,即在Controller中抛出自定义的异常时,客户端收到更友好的JSON格式的提示。而不是常见的报错页面。

二,场景描述:实现公用API,验证API key的逻辑,放在拦截器中判断(等同于在Controller中)并抛出异常,用户收到类似下图的提示:

其中,Http状态Code也能自由控制。

 

三,解决方案:

1,在RateLimitInterceptor.java拦截器中抛出异常:

1 public class RateLimitInterceptor extends HandlerInterceptorAdapter{ 2   3     @Autowired private RedisService rs; 4   5     /** 6      * 流量控制检查入口 7      */ 8     @Override 9     public boolean preHandle(HttpServletRequest request,10             HttpServletResponse response, Object handler) throws RequiredParameterException, SignException, RateLimitException,Exception {11         super.preHandle(request, response, handler);12         String appKey = request.getParameter("appKey");13         //判断appKey是否为空或是否合法14         if(appKey == null){15             throw new RequiredParameterException("");16         }else if(AppKeyUtils.isFormatCorrect(appKey) || !rs.isExist(appKey)){17             18             throw new SignException();19             20         }else {21             try {22                 AppCall appCall = AppCall.create(appKey, AppKeyUtils.getPlanDetails(appKey));23                 appCall.decrease();24                 rs.save(appCall);25                 System.out.println("RateLimitInterceptor pass.");26             } catch (RateLimitException e) {27                 //抛出超限异常28                 throw new RateLimitException();29             }30         }31         return true;32     }33  34 }

当代码走到(具体怎样走到,需考虑具体业务逻辑,上述代码使用AppCall类来封装,这是后话)

1 throw new SignException();

时,Spring将自动捕获这个异常。然后做一些处理。这是正常的流程。那么Spring如何自动不火

2,使用Spring MVC的@ControllerAdvice,在GlobalExceptionHandler.java类中实现全局的异常处理类:

1 @ControllerAdvice 2 public class GlobalExceptionHandler { 3   4     @ExceptionHandler(SQLException.class) 5     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 6     @ResponseBody 7     public ExceptionResponse handleSQLException(HttpServletRequest request, Exception ex) { 8         String message = ex.getMessage(); 9         return ExceptionResponse.create(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);10     }11      12     @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="IOException occured")13     @ExceptionHandler(IOException.class)14     @ResponseBody15     public void handleIOException(){16         //returning 404 error code17     }18     19     @ResponseStatus(HttpStatus.BAD_REQUEST)20     @ResponseBody21     @ExceptionHandler(SignException.class)22     public ExceptionResponse signException(SignException ex) {23         return ex.getEr();24     }25  26 }

在方法的头上注解:

1 @ExceptionHandler(SignException.class)

即表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。

注解:

1 @ResponseBody

即表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。

注解:

1 @ResponseStatus(HttpStatus.BAD_REQUEST)

表示设置状态码。如果应用级别的错误,此处其实永远返回200也是可以接受的,但是要在你自定义的异常串和异常码中做好交代。

本文的方案自定义了一个ExceptionResponse.java类,如下:

1 /** 2  * 返回的json数据 3  * @author craig 4  * 5  */ 6 public class ExceptionResponse { 7      8     private String message; 9     private Integer code;10     11     /**12      * Construction Method13      * @param code14      * @param message15      */16     public ExceptionResponse(Integer code, String message){17         this.message = message;18         this.code = code;19     }20     21     public static ExceptionResponse create(Integer code, String message){22         return new ExceptionResponse(code, message);23     }24     25     public Integer getCode() {26         return code;27     }28     public String getMessage() {29         return message;30     }31     32 }

如你所知,这个类就是最后传到用户面前的一个异常类,code和message根据业务定义并让用户知晓。而自定义的SignException.java实际上起到了一个桥梁的作用。Spring把SignException对象捕获到,转成相应的ExceptionResponse对象,剩下的就是如何优雅实现的问题了。 如下是SignException.java的实现:

1 /** 2  * 签名异常 3  * @author tuxiao.czz 4  * 5  */ 6 public class SignException extends Exception { 7   8     private static final long serialVersionUID = 4714113994147018010L; 9     private String message = "AppKey is not correct, please check.";10     private Integer code = 10002;11         12     private ExceptionResponse er;13     14     public SignException() {15         er = ExceptionResponse.create(code, message);16     }17     18     public ExceptionResponse getEr() {19         return er;20     }21     22 }

所有关于这个异常的code和message都写在这个类里,个人感觉还是可以接受。当然还有另外一种实现,就是只拦截、定义一种Exception类,然后传不同的code和message进去,然后做相应的处理。这些都是比较灵活的。

以上便是实现“自定义异常json化处理”的相关代码和说明。

转载于:https://www.cnblogs.com/yuandluck/p/9509646.html

你可能感兴趣的文章
NAT地址转换
查看>>
Nhibernate 过长的字符串报错 dehydration property
查看>>
Deque - leetcode 【双端队列】
查看>>
gulp插件gulp-ruby-sass和livereload插件
查看>>
免费的大数据学习资料,这一份就足够
查看>>
clientWidth、clientHeight、offsetWidth、offsetHeight以及scrollWidth、scrollHeight
查看>>
企业级应用与互联网应用的区别
查看>>
itext jsp页面打印
查看>>
Perl正则表达式匹配
查看>>
DB Change
查看>>
nginx --rhel6.5
查看>>
Eclipse Python插件 PyDev
查看>>
selenium+python3模拟键盘实现粘贴、复制
查看>>
网站搭建(一)
查看>>
Spring JDBCTemplate
查看>>
Radon变换——MATLAB
查看>>
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>