不久前,我写了一个博客,概述了如何将Spring示例代码升级到3.2版,并演示了其中的一些小“陷阱”。 从那以后,我一直在仔细阅读Spring 3.2的新功能列表,尽管它不包含任何革命性的新更改,但我怀疑Spring的家伙正在为版本4保存,它确实包含了一些简洁的升级。 引起我注意的第一个是新的@ControllerAdvice批注,它似乎巧妙地填补了Spring 3功能的空白。 让我解释…
如果您看一下我关于Spring 3 MVC异常处理程序的博客,您会看到该示例代码包含一个带有请求处理程序方法的易碎控制器,该请求处理程序方法抛出
IOException
。 IOException
然后由同一方法中的另一个方法处理 带有@ExceptionHandler(IOException.class)
注释的控制器。 问题是,用@ExceptionHandler(IOException.class)
注释的方法只能处理其包含的控制器抛出的IOException
。 如果要创建一个全局异常处理程序来处理所有控制器抛出的异常,则必须还原到诸如Spring 2的SimpleMapingExceptionHandler和一些XMLconfiguration之类的内容 。 现在情况有所不同。 为了演示@ControllerAdvice
的用法,我创建了一个简单的Spring 3.2 MVC应用程序,您可以在github上找到它。 该应用程序的主页表面上允许用户显示其地址或信用卡详细信息,
…除非用户尝试执行此操作,否则关联的控制器将抛出一个
IOException
,应用程序显示以下错误页面:
生成异常的控制器非常简单,并在下面列出:
@Controller
public class UserCreditCardController {private static final Logger logger = LoggerFactory.getLogger(UserCreditCardController.class);/*** Whoops, throw an IOException*/@RequestMapping(value = "userdetails", method = RequestMethod.GET)public String getCardDetails(Model model) throws IOException {logger.info("This will throw an IOException");boolean throwException = true;if (throwException) {throw new IOException("This is my IOException");}return "home";}}
@Controller
public class UserAddressController {private static final Logger logger = LoggerFactory.getLogger(UserAddressController.class);/*** Whoops, throw an IOException*/@RequestMapping(value = "useraddress", method = RequestMethod.GET)public String getUserAddress(Model model) throws IOException {logger.info("This will throw an IOException");boolean throwException = true;if (throwException) {throw new IOException("This is my IOException");}return "home";}}
如您所见,此代码所做的全部工作就是将userdetails
和useraddress
映射到getCardDetails(...)
和getUserAddress(...)
方法。 当这些方法之一抛出IOException
,以下类将捕获该异常:
@ControllerAdvice
public class MyControllerAdviceDemo {private static final Logger logger = LoggerFactory.getLogger(MyControllerAdviceDemo.class);@Autowiredprivate UserDao userDao;/*** Catch IOException and redirect to a 'personal' page.*/@ExceptionHandler(IOException.class)public ModelAndView handleIOException(IOException ex) {logger.info("handleIOException - Catching: " + ex.getClass().getSimpleName());return errorModelAndView(ex);}/*** Get the users details for the 'personal' page*/private ModelAndView errorModelAndView(Exception ex) {ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("error");modelAndView.addObject("name", ex.getClass().getSimpleName());modelAndView.addObject("user", userDao.readUserName());return modelAndView;}
}
上面的类由新的@ControllerAdvice
注释注释,并且包含单个公共方法handleIOException(IOException.class)
。 此方法捕获上面的控制器抛出的所有IOException,生成包含一些相关用户信息的模型,然后显示和错误页面。 这样做的好处是,无论您的应用程序包含多少个控制器,当任何一个控制器抛出IOException
,它将由MyControllerAdviceDemo
异常处理程序进行处理。
@ModelAttribute
和@InitBinder
要记住的最后一件事是,尽管ControllerAdvice
批注对于处理异常很有用,但也可以在全局处理@ModelAttribute
和@InitBinder
批注时使用它。 ControllerAdvice
和@ModelAttribute
的组合使您能够在一处为所有控制器设置模型对象,同样, ControllerAdvice
和@InitBinder
的组合使您可以在同一位置将相同的自定义验证器附加到所有控制器。
参考:来自Captain Debug博客博客的JCG合作伙伴 Roger Hughes 提供的Spring 3.2 @ControllerAdvice注释的异常处理 。
翻译自: https://www.javacodegeeks.com/2013/03/exception-handling-with-the-spring-3-2-controlleradvice-annotation.html