spring 2.2 改进

在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在我们的JCG合作伙伴 Rafal Borowiec的Spring 4中的改进,来自Codeleak.pl博客。

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

spring 2.2 改进

spring 2.2 改进_Spring 4中@ControllerAdvice的改进相关推荐

  1. Spring 4中@ControllerAdvice的改进

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

  2. spring 事物的级别_Spring 事务中的隔离级别有哪几种?

    答: TransactionDefinition 接口中定义了五个表示隔离级别的常量: 1.TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级 ...

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

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

  4. spring 测试demo乱码_spring框架的入门学习:AOP和面向切面的事务

    使用注解配置spring,需要以下几个步骤: 需要导入一个包: 步骤1:需要为主配置文件引入新的命名空间(约束),和之前介绍的一样,导入新的约束: 然后在application.xml的Design中 ...

  5. 如何将spring源码作为导入eclipse中,变成一个普通的项目(git、github)

    引子: 怎么查看spring-framework的源码?是不是用压缩软件解压jar包,然后用编辑软件看?高端一点的,是在eclipse上面,按住Ctrl键跳转着看?这里我给大家介绍更加高端一点的方法. ...

  6. eclipse中tomcat启动不了_Spring Boot中Tomcat是怎么启动的

    Spring Boot一个非常突出的优点就是不需要我们额外再部署Servlet容器,它内置了多种容器的支持.我们可以通过配置来指定我们需要的容器. 本文以我们平时最常使用的容器Tomcat为列来介绍以 ...

  7. spring mvc mysql配置_spring mvc配置数据库连接

    ACM 配置中心实战:Spring + MyBatis + Druid + ACM 很多基于 Spring MVC 框架的 Web 开发中,Spring + MyBatis + Druid 是一个黄金 ...

  8. Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获

    Spring boot异常统一处理方法:@ControllerAdvice注解的使用.全局异常捕获.自定义异常捕获 参考文章: (1)Spring boot异常统一处理方法:@ControllerAd ...

  9. spring 托管bean_在非托管对象中使用Spring托管Bean

    spring 托管bean 即使我们想使用现有的最佳和最新技术,我们也必须处理遗留代码. 想象一下,新代码是用Spring框架的最新技术编写的,而旧代码根本不是用Spring编写的. 然后,在非托管S ...

最新文章

  1. 对RPM软件包的查询操作
  2. NOIP2017 列队
  3. perl学习笔记——目录操作
  4. SQL Server 兼容模式
  5. php去数组中的数据库,php 数据库 取出数组
  6. 深入浅出 - 公钥、私钥和数字签名最通俗的理解
  7. cocos2d-x中CCEditbox导出到lua
  8. Windows Azure系列公开课 - 第二课:为什么选择Windows Azure(下)
  9. mysql 绑定 cpu 节点_MySQL Cluster(MySQL集群)配置
  10. php模拟post提交
  11. radasm相关问题
  12. 常见的负载均衡器(一)
  13. 自动驾驶技术(5)视觉与激光雷达对比
  14. 【JAVA秒会技术之Joda-Time】满足你所有关于日期的处理
  15. 【从零开始的Java开发】1-5-4 ArrayList、HashSet、HashMap 概述与案例
  16. 3d可视化虚拟建模vr展示三维模型方案
  17. gts250 linux驱动下载,下载:NVIDIA显卡Linux驱动190.32测试版
  18. 前端渲染和后端渲染,要说的都在这里?
  19. python3解两数之和
  20. react 3d模型_制作3D React Carousel

热门文章

  1. 【动态规划】石子合并 (ssl 2863)
  2. 传送门(最短路树+可并堆)
  3. art-template 入门(二)之安装
  4. java 为什么需要常量池 1
  5. 高级 Java 必须突破的 10 个知识点
  6. CSS3的几个变形案例……
  7. css解决li边框重合问题
  8. python一图带你精通time类型转换
  9. 用数组模拟队列的实现
  10. #{} vs ${}