springboot,使用自定义的格式向前端返回异常信息的json

springboot,使用自定义的格式向前端返回异常信息的json

 

最近进入了一家公司,这个公司使用的是完全前后端分离的架构,没有使用任何Java模板引擎,使用纯粹的js来渲染从后台传过来的数据。

这样的架构让人耳目一新,因为后台工作者完全不用涉及前端的东西。而且这样的框架有利于实现系统的高可用。

可是要搭建这样的框架,要解决的小问题有很多。例如,springboot默认返回的异常的格式是这样的:

<html>

    <body>

        <h1>Whitelabel Error Page</h1>

        <p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>

        <div id='created'>Mon Apr 23 06:30:37 CST 2018</div>

        <div>There was an unexpected error (type=Internal Server Error, status=500).</div>

        <div>/ by zero</div>

    </body>

</html>

仔细一看,发现springboot默认返回给前端的是一个html页面,这样前端就不能够定制异常显示页面了,只能把springboot默认返回的html页面显示给前端。这显然是不符合要求的。于是spring提供了一个@ControllerAdvice注解。

接下来我会向兄弟们详细介绍@ControllerAdvice注解。

该注解的基本格式是这样的:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component  //表明这个类会被spring的自动扫描机制所捕获,并被spring容器所维护。

public @interface ControllerAdvice {}

@ControllerAdvice有这几个关键点:

1.默认情况下,@ControllerAdvice类中的方法可以被所有的@Controller类所访问,但是可以使用选择器annotations(),basePackageClasses(),basePackages()来精细化目标@Controller类。

如果同时使用了多种选择器,它们之间的逻辑关系为“或”。注意:选择器验证是在运行时执行的,所以使用太多的选择器会影响性能。

2.可以定义多个@ControllerAdvice,它们被@Controller类访问的顺序默认由系统决定的。但是可以使用@Order注解改变。这个特性就叫@ControllerAdvice优先级。

3.对于异常处理,系统会选择第一个通知中的(优先级最高的那个@ControllerAdvice类)异常类型匹配的那个@ExceptionHandler方法。@ModelAttribute@InitBinder方法是同样的道理,举一反三就可以了。

接下来就贴代码,看看实际应用中是如何应用@ControllerAdvice@ExceptionHandler的。

@ControllerAdvice
public class ExceptionHandlerAdvice {
 private static final Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);
 
 @ExceptionHandler(IllegalArgumentException.class)
 @ResponseBody
 public String handleIllegal(IllegalArgumentException e){
  logger.error("非法参数",e);
  //使用fastjson的响应对象格式
  return ResponseJson.ResponseInfo(ApiResponse.INVALID_PARAM);
 }
 
 @ExceptionHandler(AuthenticationFailureException.class)
 @ResponseBody
 public String handleAuthenticationFailureException(AuthenticationFailureException e) {
  return ResponseJson.ResponseInfo(ApiResponse.AUTHENTICATION_FAILURE);
 }
 
 @ExceptionHandler(DuplicateKeyException.class)
 @ResponseBody
 public String handlerDuplicateKeyException(DuplicateKeyException e){
  logger.error("重复的唯一key", e);
    return ResponseJson.ResponseInfo(ApiResponse.DUPLICATE);
 }
 
 @ExceptionHandler(BusinessException.class)
 @ResponseBody
 public String handleBusinessException(BusinessException e){
  logger.error(e.message);
    return ResponseJson.ResponseInfo(new ApiResponse(e));
 }
 
 @ExceptionHandler(MobileVerificationCodeErrorException.class)
 @ResponseBody
 public String handleMobileVerificationCodeErrorException(MobileVerificationCodeErrorException e) {
  logger.error("验证码错误", e);
    return ResponseJson.ResponseInfo(ApiResponse.VERIFICATION_CODE_ERROR);
 }
 
 @ExceptionHandler(LoginFailureException.class)
 @ResponseBody
 public String handleLoginFailureException(LoginFailureException e) {
  logger.error("登录失败", e);
    return ResponseJson.ResponseInfo(ApiResponse.LOGIN_FAILURE);
 }
 
 @ExceptionHandler(NoHandlerFoundException.class)
 @ResponseBody
 public String handleNoHandlerFoundException(NoHandlerFoundException e) {
  logger.error("地址请求异常:", e);
    return ResponseJson.ResponseInfo(ApiResponse.EXCEPTION);
 }
 
 @ExceptionHandler(Exception.class)
 @ResponseBody
 public String handleException(Exception e) {
  logger.error("Unhandled exception", e);
    return ResponseJson.ResponseInfo(ApiResponse.EXCEPTION);
 }
}
接下来,我会介绍springmvc处理异常的过程:

在处理器映射器找到对应的处理器并执行里面的方法的过程中如果出现了异常,DispatcherServlet就会委派HandlerExceptionResolver解析器链来捕获和处理这些异常。
配置HandlerExceptionResolver的方式有:

1.@Controller类中的@ExceptionHandler方法。
2.@ControllerAdvice类中的@ExceptionHandler方法。

3.@ControllerAdvice类,并且该类是ResponseEntityExceptionHandler类的子类

猜你喜欢

转载自blog.csdn.net/jiaweicheng77/article/details/80059682