Unified exception handling @ExceptionHandler (spring comes with)

exception handling

 

Exceptions are thrown from the bottom layer to the Controller for processing. The client's request first goes to the controller and then to the dao. The exception encountered at the time of the request, the exception encountered by the lower layer such as the dao will be thrown in the return result of the controller, so the exception is handled uniformly. All in the controller layer

 

1. @ExceptionHandler does not need to be written on the target method, but on the notification processing method

 

2. @ExceptionHandler automatically intercepts the set exception. The scope of this control class---in this case, a parent class is generally defined, and then each controller can inherit

 refer to:

http://yuhuiblog6338999322098842.iteye.com/blog/2312438

 

3. @ExceptionHandler combined with @ControllerAdvice will automatically intercept exceptions in all controller classes.

 

1. How to set global exception handling
With @RequestBody, @ResponseBody, JSon automatic binding is solved with little effort.
Then I found that if you encounter a RuntimeException, you need to give a default return JSON. There are three ways:

1. When an exception occurs in any method in this Controller, it will be intercepted by this method. Then, output the log. Encapsulate Map and return (Json), the status is false on the page.

code show as below:

copy code
1 @Controller  
 2 public class AccessController {  
 3   
 4     /**
 5 * Exception page control
 6      *  
 7      * @param runtimeException
 8      * @return
 9      */  
10     @ExceptionHandler(RuntimeException.class)  
11     public @ResponseBody  
12     Map<String,Object> runtimeExceptionHandler(RuntimeException runtimeException) {  
13         logger.error(runtimeException.getLocalizedMessage());  
14   
15         Map model = new TreeMap();  
16         model.put("status", false);  
17         return model;  
18     }  
19   
20 }
copy code

2. Return to the error interface

code show as below:

copy code
1     @Controller  
 2     public class AccessController {  
 3         /**
 4 * Exception page control
 5          *  
 6          * @param runtimeException
 7          * @return
 8          */  
 9         @ExceptionHandler(RuntimeException.class)  
10         public String runtimeExceptionHandler(RuntimeException runtimeException,  
11 ModelMap modelMap) {  
12             logger.error(runtimeException.getLocalizedMessage());  
13       
14             modelMap.put("status", IntegralConstant.FAIL_STATUS);  
15             return "exception";  
16         }  
17     }  
copy code

3.使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。

代码如下:

copy code
    @ControllerAdvice  
    public class SpringExceptionHandler{  
      /** 
         * 全局处理Exception 
         * 错误的情况下返回500 
         * @param ex 
         * @param req 
         * @return 
         */  
        @ExceptionHandler(value = {Exception.class})  
        public ResponseEntity<Object> handleOtherExceptions(final Exception ex, final WebRequest req) {  
            TResult tResult = new TResult();  
            tResult.setStatus(CodeType.V_500);  
            tResult.setErrorMessage(ex.getMessage());  
            return new ResponseEntity<Object>(tResult,HttpStatus.OK);  
        }  
      
    }  

二、@ExceptionHandler注解

 

直接在Controller里面加上用@ExceptionHandler标注一个处理异常的方法像下面这样子

@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void processMethod(MissingServletRequestParameterException ex,HttpServletRequest request ,HttpServletResponse response) throws IOException {
    System.out.println("抛异常了!"+ex.getLocalizedMessage());
    logger.error("抛异常了!"+ex.getLocalizedMessage());
    response.getWriter().printf(ex.getMessage());
    response.flushBuffer();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这样,Controller里面的方法抛出了MissingServletRequestParameterException异常就会执行上面的这个方法来进行异常处理。 
如下面的代码:

@RequestMapping("/index")
public String index(@MyUser User user,@RequestParam String id,ModelMap modelMap){
    return "login";
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

如果我没有传入id值,那么就会抛出MissingServletRequestParameterException的异常,就会被上面的异常处理方法处理。

上面的@ExceptionHandler(MissingServletRequestParameterException.class)这个注解的value的值是一个Class[]类型的,这里的ExceptionClass是你自己指定的,你也可以指定多个需要处理的异常类型,比如这样@ExceptionHandler(value = {MissingServletRequestParameterException.class,BindException.class}),这样就会处理多个异常了。

但这个只会是在当前的Controller里面起作用,如果想在所有的Controller里面统一处理异常的话,可以用@ControllerAdvice来创建一个专门处理的类。如一中的3所述。

三、@ControllerAdvice注解

 

@ControllerAdvice,是Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强。让我们先看看@ControllerAdvice的实现:

write picture description here

没什么特别之处,该注解使用@Component注解,这样的话当我们使用<context:component-scan>扫描时也能扫描到。

再一起看看官方提供的comment。

write picture description here

大致意思是:

  • @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。

  • Spring4之前,@ControllerAdvice在同一调度的Servlet中协助所有控制器。Spring4已经改变:@ControllerAdvice支持配置控制器的子集,而默认的行为仍然可以利用。

  • 在Spring4中, @ControllerAdvice通过annotations(), basePackageClasses(), basePackages() 方法定制用于选择控制器子集。

不过据经验之谈,只有配合@ExceptionHandler最有用,其它两个不常用。

 

write picture description here

SpringMVC重要注解(一)@ExceptionHandler和@ResponseStatus我们提到,如果单使用@ExceptionHandler,只能在当前Controller中处理异常。但当配合@ControllerAdvice一起使用的时候,就可以摆脱那个限制了。

write picture description here

@Controller
@RequestMapping(value = "exception")
public class ExceptionHandlerController {

    @RequestMapping(value = "e2/{id}", method = { RequestMethod.GET })
    @ResponseBody
    public String testExceptionHandle2(@PathVariable(value = "id") Integer id) {
        List<String> list = Arrays.asList(new String[]{"a","b","c","d"});
        return list.get(id-1);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

当我们访问http://localhost:8080/SpringMVC/exception/e2/5的时候会抛出ArrayIndexOutOfBoundsException异常,这时候定义在@ControllerAdvice中的@ExceptionHandler就开始发挥作用了。

如果我们想定义一个处理全局的异常

write picture description here

At first glance, there is no problem, but there is a flaw here. Since Exception is the parent class of exceptions, if you use @ResponseStatus in custom exceptions in your project, your original intention is to encounter that custom exception. Response to the corresponding status code, and this controller enhanced processing class will enter first and return directly, there will be no more @ResponseStatus thing, here in order to solve this flaw, I provide a solution.

write picture description here

If you encounter a custom exception with @ResponseStatus added, continue to throw it, so that the custom exception will not lose the original intention of adding @ResponseStatus.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326013164&siteId=291194637