3.17.4 @ControllerAdvice注解
org.springframework.web.bind.annotation.Controlleradvice
注解是Spring3.2
提供的新注解,它是一个控制器增强功能注解。该注解源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Target(ElementType.TYPERE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface ControllerAdvice { @AliasFor("basePackages") String[] value() default{}; @AliasFor("value") String[] basePackages() default{}; Class<?>[] basePackageClasses() default{}; Class<?>[] assignableTypes() default{}; Class<? extends Annotation>[] annotations() default{} }
|
该注解使用@Component
注解,也就是说可以使用<context: component-scan>
扫描该注解。 Spring
官方文档说明,扫描到@Controlleradvice
注解之后,会将@ControllerAdvice
注解修饰的类的内部使用@ExceptionHandler
、@InitBinder
、@ModelAttribute
注解的方法应用到所有的请求处理方法上。
在实际开发中@ExceptionHandler
注解的功能最强大,另外两个用处不大。
示例 @ControllerAdvice处理异常
新建一个项目ControllerAdviceTest
,加入所需的jar
文件,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>异常处理示例</title> <script type="text/javascript" src="js/jquery-1.11.0.min.js"></script> <script type="text/javascript"> $(function() { $("#search").click( function() { $.post("${pageContext.request.contextPath}/search", null, function(data) { if (data.message) { alert("与服务器交互出现异常:" + data.message); } else {
} }, "json"); }); }) </script> </head> <body> <br> <a href="find">@ControllerAdvice异常处理</a> <hr> <button id="search">查询订单(返回JSON)</button> </body> </html>
|
需要注意id=" search"
的按钮,使用jQuery
进行异步査询订单时,如果抛岀异常,则获取返回的JSON
数据并提示错误
BookController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;
@Controller public class BookController { @GetMapping("/find") public String find() throws Exception { @SuppressWarnings("unused") int i = 5 / 0; return "success"; } }
|
BookController
处理"find"
请求,在请求处理方法中简单地模拟了一个异常。 BookController
中并没有@ExceptionHandler
注解修饰的方法,抛出的异常会由@Controlleradvice
注解修饰的类中的@ExceptionHandle
注解修饰的方法进行处理。
OrderException.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package org.fkit.controller;
public class OrderException extends RuntimeException { private static final long serialVersionUID = 6857573209047095609L; public OrderException() { super(); }
public OrderException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } public OrderException(String message, Throwable cause) { super(message, cause); }
public OrderException(String message) { super(message); }
public OrderException(Throwable cause) { super(cause); } }
|
OrderException
是一个自定义异常类型,继承自RuntimeException
.
OrderController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping;
@Controller public class OrderController { @PostMapping("/search") public String search() throws Exception { try { @SuppressWarnings("unused") int i = 5 / 0; return "success"; } catch (Exception e) { e.printStackTrace(); throw new OrderException("订单查询失败!"); } } }
|
OrderController
处理"search"
请求,在请求处理方法中简单地模拟了一个异常,被捕捉后抛出OrderException
自定义异常类型。
GlobalExceptionHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package org.fkit.controller;
import java.util.HashMap; import java.util.Map; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = Exception.class) public ModelAndView globalErrorHandler(Exception e) throws Exception { ModelAndView mav = new ModelAndView(); mav.addObject("ex", e); mav.setViewName("error"); return mav; } @ExceptionHandler(value = OrderException.class) @ResponseBody public Object OrderErrorHandler(Exception e) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("code", 100); map.put("message", e.getMessage()); map.put("data", "请求失败"); return map; } }
|
GlobalExceptionHandler
类使用了@ControllerAdvice
注解来修饰,则该类会被<context: component-scan>
扫描,该类中使@ExceptionHandler
注解修饰的方法将被应用到所有
请求处理方法上。
GlobalExceptionHandler
类中定义了两个方法:
- 第一个方法
globalErrorHandler
使用@ExceptionHandler
注解修饰,value=Exception.class
属性表示该方法处理所有Exception
类型的异常,处理方式和之前一致,将异常信息对象保存到Model
,并返回异常处理页面error.jsp
;
- 第二个方法
OrderErrorHandler
使用@ExceptionHandler
注解修饰,value=OrderException.class
表示该方法处理OrderException
自定义类型的异常,此处的处理方式和之前不同,这里创建一个Map
对象保存信息并返回,由于方法使用了@ResponseBody
注解,返回的Map
对象会被转成JSON
数据。
部署ControllAdviceTest
这个Web
应用,在浏览器中输入如下URL
来测试应用:
1
| http://localhost:8080/ControllerAdviceTest/
|
- 单击
"@ControllerAdvice异常处理"
超链接,发送"find"
请求, BookController
的find()
方法处理请求,抛出异常,异常被@ControllerAdvice
注解修饰的GlobalExceptionHandler
类中@ExceptionHandler(value = Exception.class)
注解修饰的globalErrorHandler
方法捕获,处理之后跳转到error.jsp
页面.
- 再次请求
index.jsp
页面,单击"查询订单(返回JSON)"
按钮,发送"search"
请求,OrderController
的search()
方法处理请求,抛出自定义异常OrderException
,该异常被@ControllerAdvice
注解修饰的GlobalExceptionHandler
类中@ExceptionHandler(value = OrderException.class)
注解修饰的OrderErrorHandler
方法捕获,返回JSON
信息.