在Spring 4的许多新功能中,我发现了@ControllerAdvice的改进。 @ControllerAdvice是@Component的特殊化,用于定义适用于所有@RequestMapping方法的@ ExceptionHandler,@ InitBinder和@ModelAttribute方法。 在Spring 4之前,@ ControllerAdvice在同一Dispatcher Servlet中协助了所有控制器。 在Spring 4中,它已经发生了变化。 从Spring 4开始,可以将@ControllerAdvice配置为支持定义的控制器子集,而仍可以使用默认行为。

@ControllerAdvice协助所有控制器

假设我们要创建一个错误处理程序,它将向用户显示应用程序错误。 我们假设这是一个基本的Spring MVC应用程序,其中Thymeleaf作为视图引擎,并且我们有一个ArticleController,它具有以下@RequestMapping方法:

package pl.codeleak.t.articles;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("article")
class ArticleController {@RequestMapping("{articleId}")String getArticle(@PathVariable Long articleId) {throw new IllegalArgumentException("Getting article problem.");}
}

如我们所见,我们的方法抛出了一个假想异常。 现在,使用@ControllerAdvice创建一个异常处理程序。 (这不仅是Spring中处理异常的可能方法)。

package pl.codeleak.t.support.web.error;import com.google.common.base.Throwables;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;@ControllerAdvice
class ExceptionHandlerAdvice {@ExceptionHandler(value = Exception.class)public ModelAndView exception(Exception exception, WebRequest request) {ModelAndView modelAndView = new ModelAndView("error/general");modelAndView.addObject("errorMessage", Throwables.getRootCause(exception));return modelAndView;}
}

该课程不是公开的,不是公开的。 我们添加了@ExceptionHandler方法,该方法将处理所有类型的Exception,并将返回“错误/常规”视图:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head><title>Error page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="@{/resources/css/bootstrap.min.css}"/><link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="@{/resources/css/core.css}"/>
</head>
<body>
<div class="container" th:fragment="content"><div th:replace="fragments/alert :: alert (type='danger', message=${errorMessage})"> </div>
</div>
</body>
</html>

为了测试解决方案,我们可以运行服务器,或者(最好)使用Spring MVC Test模块创建一个测试。 由于我们使用Thymeleaf,因此可以验证渲染的视图:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {RootConfig.class, WebMvcConfig.class})
@ActiveProfiles("test")
public class ErrorHandlingIntegrationTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void before() {this.mockMvc = webAppContextSetup(this.wac).build();}@Testpublic void shouldReturnErrorView() throws Exception {mockMvc.perform(get("/article/1")).andDo(print()).andExpect(content().contentType("text/html;charset=ISO-8859-1")).andExpect(content().string(containsString("java.lang.IllegalArgumentException: Getting article problem.")));}
}

我们期望内容类型为text / html,并且视图包含带有错误消息HTML片段。 但是,它并不是真正的用户友好型。 但是测试是绿色的。

使用上述解决方案,我们提供了一种处理所有控制器错误的通用机制。 如前所述,我们可以使用@ControllerAdvice:做更多的事情。 例如:

@ControllerAdvice
class Advice {@ModelAttributepublic void addAttributes(Model model) {model.addAttribute("attr1", "value1");model.addAttribute("attr2", "value2");}@InitBinderpublic void initBinder(WebDataBinder webDataBinder) {webDataBinder.setBindEmptyMultipartFiles(false);}
}

@ControllerAdvice协助选定的控制器子集

从Spring 4开始,可以通过批注(),basePackageClasses(),basePackages()方法来自定义@ControllerAdvice,以选择控制器的一个子集来提供帮助。 我将演示一个简单的案例,说明如何利用此新功能。

假设我们要添加一个API以通过JSON公开文章。 因此,我们可以定义一个新的控制器,如下所示:

@Controller
@RequestMapping("/api/article")
class ArticleApiController {@RequestMapping(value = "{articleId}", produces = "application/json")@ResponseStatus(value = HttpStatus.OK)@ResponseBodyArticle getArticle(@PathVariable Long articleId) {throw new IllegalArgumentException("[API] Getting article problem.");}
}

我们的控制器不是很复杂。 如@ResponseBody批注所示,它返回Article作为响应正文。 当然,我们要处理异常。 而且我们不希望以text / html的形式返回错误,而是以application / json的形式返回错误。 然后创建一个测试:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {RootConfig.class, WebMvcConfig.class})
@ActiveProfiles("test")
public class ErrorHandlingIntegrationTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void before() {this.mockMvc = webAppContextSetup(this.wac).build();}@Testpublic void shouldReturnErrorJson() throws Exception {mockMvc.perform(get("/api/article/1")).andDo(print()).andExpect(status().isInternalServerError()).andExpect(content().contentType("application/json")).andExpect(content().string(containsString("{\"errorMessage\":\"[API] Getting article problem.\"}")));}
}

测试是红色的。 我们能做些什么使其绿色? 我们需要提出另一个建议,这次仅针对我们的Api控制器。 为此,我们将使用@ControllerAdvice注解()选择器。 为此,我们需要创建一个客户或使用现有注释。 我们将使用@RestController预定义注释。 带有@RestController注释的控制器默认情况下采用@ResponseBody语义。 我们可以通过将@Controller替换为@RestController并从处理程序的方法中删除@ResponseBody来修改我们的控制器:

@RestController
@RequestMapping("/api/article")
class ArticleApiController {@RequestMapping(value = "{articleId}", produces = "application/json")@ResponseStatus(value = HttpStatus.OK)Article getArticle(@PathVariable Long articleId) {throw new IllegalArgumentException("[API] Getting article problem.");}
}

我们还需要创建另一个将返回ApiError(简单POJO)的建议:

@ControllerAdvice(annotations = RestController.class)
class ApiExceptionHandlerAdvice {/*** Handle exceptions thrown by handlers.*/@ExceptionHandler(value = Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ResponseBodypublic ApiError exception(Exception exception, WebRequest request) {return new ApiError(Throwables.getRootCause(exception).getMessage());}
}

这次运行测试套件时,两个测试均为绿色,这意味着ExceptionHandlerAdvice辅助了“标准” ArticleController,而ApiExceptionHandlerAdvice辅助了ArticleApiController。

摘要

在以上场景中,我演示了如何轻松利用@ControllerAdvice批注的新配置功能,希望您像我一样喜欢所做的更改。

参考文献

  • SPR-10222
  • @RequestAdvice注释文档
参考: @ControllerAdvice在我们Spring的JCG合作伙伴 Rafal Borowiec的Codeleak.pl博客上的改进 。

翻译自: https://www.javacodegeeks.com/2013/11/controlleradvice-improvements-in-spring-4.html

Spring 4中@ControllerAdvice的改进相关推荐

  1. Spring MVC中@ControllerAdvice注解实现全局异常拦截

    Spring MVC中@ControllerAdvice注解实现全局异常拦截 参考文章: (1)Spring MVC中@ControllerAdvice注解实现全局异常拦截 (2)https://ww ...

  2. spring 2.2 改进_Spring 4中@ControllerAdvice的改进

    spring 2.2 改进 在Spring 4的许多新功能中,我发现了@ControllerAdvice的改进. @ControllerAdvice是@Component的特殊化,用于定义适用于所有@ ...

  3. spring boot中@ControllerAdvice的用法,全局异常处理,全局数据绑定,全局数据预处理

    1: @ControllerAdvice理解 @ControllerAdvice是spring 3.2提供的新注解,他是一个controller增强器,加了@ControllerAdvice的类为那些 ...

  4. java基础巩固-宇宙第一AiYWM:为了维持生计,Spring全家桶_Part1-1(Spring左膀右臂中的左膀IOC第一篇~全是概念,Spring为啥辣么6)~整起

    我Java学的好好的,为什么要学spring框架呀[一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合]?或者说,成天喊简化开发,spring是如何简化开发的?或 ...

  5. Spring Boot中Web应用的统一异常处理

    为什么80%的码农都做不了架构师?>>>    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛 ...

  6. Spring Boot 中如何实现 HTTP 认证?

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:在滴滴和头条干了 2 年后端开发,太真实-个人原创100W+访问量博客:点击前往,查看更多 HttpBasic ...

  7. boot spring 接口接收数据_在 Spring Boot 中使用 Dataway 配置数据查询接口

    Dataway介绍 Dataway 是基于 DataQL 服务聚合能力,为应用提供的一个接口配置工具.使得使用者无需开发任何代码就配置一个满足需求的接口. 整个接口配置.测试.冒烟.发布.一站式都通过 ...

  8. exceptionhandler注解_SpringMVC 中 @ControllerAdvice 注解的三种使用场景!

    @ControllerAdvice ,很多初学者可能都没有听说过这个注解,实际上,这是一个非常有用的注解,顾名思义,这是一个增强的 Controller.使用这个 Controller ,可以实现三个 ...

  9. Spring Bootstrap中具有配置元数据的高级配置

    在简要介绍了配置元数据并涵盖了我之前的文章< 在Spring Boot中使用配置元数据Pimp您的配置>中的基础知识之后,现在该看看如何进一步执行此步骤并进一步自定义配置. 在这篇文章中, ...

最新文章

  1. vs报错 已经在 helpers.obj 中定义
  2. JavaScript 读取、写入Txt文档
  3. Java BufferedReader skip()方法与示例
  4. 传统POS/终端/银联POS简介
  5. index mysql_mysql 原理~ index的详解
  6. 哪个工厂不用加班,工资也不低?
  7. Halcon PDF文档(hdevelop_users_guide)学习总结之三——关于变量窗口的小知识
  8. [oracle] 设置PL/SQL Developer 字符集
  9. linux firefox 插件开发教程,火狐(firefox)浏览器插件开发简明教程
  10. iQOO Neo6 SE什么时候发布 iQOO Neo6 SE配置如何
  11. Xshell免密登录
  12. dns按来路ip智能解析_云解析实现智能解析
  13. 【渝粤题库】陕西师范大学180108 有效教学的理论与实践
  14. ⭐程序员必备软件图鉴⭐(建议收藏)
  15. C#——获取银行卡所属银行,验证银行卡号是否正确
  16. Widget中的一些基本概念
  17. List对象集合属性处理
  18. 需求调研注意事项-第一篇--如何组织调研工作
  19. Webkit模块介绍
  20. iOS中 支付宝钱包详解

热门文章

  1. 三星系统和鸿蒙系统,又一设备直升鸿蒙系统,现有操作系统被抛弃,和三星的想法一样!...
  2. python 随机排序_Python 如何随机打乱列表(List)排序
  3. xrkmonitor监控mysql_xrkmonitor字符云监控系统
  4. centos上安装jdk
  5. java开发课程表_展示Java开发人员课程包
  6. java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!
  7. java关闭窗口函数_2016年将是Java终于拥有窗口函数的那一年!
  8. primefaces_PrimeFaces:在动态生成的对话框中打开外部页面
  9. TellDontAsk的扩展
  10. Eclipse GlassFish 5.1就在这里!