- 浏览: 1028812 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
繁星水:
Useful!!
Object-C之(Null)与(Bool) -
pacer123:
请问注解@ApiModelProperty 在哪个jar包下面 ...
Micro Service工具集之Swagger:可测试的样式化API文档 -
sucheng2016:
这东东真的好用么/
对象转换利器之Dozer -
zzq0324:
http://git.oschina.net/zzq0324/ ...
基于Spring-WS的Restful API的集成测试 -
lrz0534:
你好,我在maven上面下载了swagger-springmv ...
Micro Service工具集之Swagger:可测试的样式化API文档
在一个良好的Rest架构的应用中,所有的异常都应该有对应的Http Status Code来表示具体的异常类型,这样可以客户端可以基于对应的Status Code做出最有利于自己的处理。
在Spring MVC中,异常处理机制有3个选项:
在我之前的文章(http://ningandjiao.iteye.com/blog/1982635)中,搭建了一个基于Spring4.0的Restful服务,下面就来为这个服务添加Error Handling机制,
基于Exception的异常处理
通常情况下,在应用中抛出的未被捕获的异常,最后会以500(HttpStatus.INTERNAL_SERVER_ERROR)返回客户端,但是,有时服务器的异常是由于客户端发送的请求不合规范导致,这时,我们就需要应该400(BAD_REQUEST)的status code。在Spring MVC中,做到这点非常容易,只需要在对应的Exception上加上@ResponseStatus注解即可。栗子:
测试代码:
实现代码:
这个方式有很大的局限性:
1. 只能处理自己写的Exception
2. 不能定制Response的消息体。
基于Controller的异常处理
在每个Controller中,可以定义处理各种异常的方法,在该方法添加@ExceptionHandler定义该方法处理的Exception(所有的Exception都支持),添加@ResponseStatus定义该Exception应该返回的Http Status Code,方法的返回值可以是定制化的异常信息, 这就解决了上面Exception方式的局限性。 栗子:
测试代码:
实现代码:
这种处理方式其它都好,就是有个最大的弊端,只能处理一个Controller的异常,对于又多个Controller的情况就会搞出很多的重复代码。
基于Application的异常处理
我个人觉得一个好的异常处理机制应该是这样的,有一个集中的处理点负责所有的异常处理,在真正的业务逻辑的处理过程中,我只会关心正常的业务流程,一旦遇到异常,我只管抛出对应的异常和相关的信息就行了。幸运的是,Spring MVC就提供了这样的机制,开发者可以自己定义一个ExceptionHandler类处理所有的异常,在这个类上加上@ControllerAdvice注解,这个类就以AOP的形式注册到SpringMVC的处理链条中了,在应用任何地方抛出Exception,最后都会调用到这个handler中的方法上,在Handler类中,可以和上面一样使用@ExceptionHandler注解来区别对待不同的Exception。栗子:
测试代码:
同上:但是需要注意一点,使用@ControllerAdvice是以AOP的形式做了一个切面处理异常,因此,你必须模拟整个Web处理过程该注解才能起效。因此在Integration测试类中,你需要加上@WebAppConfiguration注解,同时使用WebApplicationContext构建MockMvc,使用基于Controller的standaloneSetup是不能达到想要的效果的。
实现代码:
你的spring配置文件中需要添加annotation-driven的配置,告诉Spring容器根据Annotation加载。。
有用就好,我的例子是基于Spring4.0的,在Controller上使用的annotation是@RestController而不是@Controller, @RestController和@Controller的区别就是会为Controller的每个@RequestMapping方法加上@ResponseBody的annotation。
在Spring MVC中,异常处理机制有3个选项:
- 基于Exception的,即只处理某个异常
- 基于Controller的,即处理某个Controller中抛出的异常。
- 基于Application的,即处理该Application抛出的所有异常
在我之前的文章(http://ningandjiao.iteye.com/blog/1982635)中,搭建了一个基于Spring4.0的Restful服务,下面就来为这个服务添加Error Handling机制,
基于Exception的异常处理
通常情况下,在应用中抛出的未被捕获的异常,最后会以500(HttpStatus.INTERNAL_SERVER_ERROR)返回客户端,但是,有时服务器的异常是由于客户端发送的请求不合规范导致,这时,我们就需要应该400(BAD_REQUEST)的status code。在Spring MVC中,做到这点非常容易,只需要在对应的Exception上加上@ResponseStatus注解即可。栗子:
测试代码:
@Test public void shouldGetStatus404WhenRquestIdBiggerThan10() throws Exception { mockMvc.perform(get("/requests/11") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .param("userId", "xianlinbox") ) .andExpect(status().isBadRequest()); }
实现代码:
@RequestMapping(value = "/requests/{requestId}", method = RequestMethod.GET) public Request get(@PathVariable int requestId, @RequestParam(value = "userId") String userId) { if (requestId > 10) { throw new InvalidRequestIdException("Request id must less than 10"); } return new Request(userId, requestId, "GET"); } @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Request id must less than 10") public class InvalidRequestIdException extends RuntimeException { public InvalidRequestIdException(String message) { super(message); } }
这个方式有很大的局限性:
1. 只能处理自己写的Exception
2. 不能定制Response的消息体。
基于Controller的异常处理
在每个Controller中,可以定义处理各种异常的方法,在该方法添加@ExceptionHandler定义该方法处理的Exception(所有的Exception都支持),添加@ResponseStatus定义该Exception应该返回的Http Status Code,方法的返回值可以是定制化的异常信息, 这就解决了上面Exception方式的局限性。 栗子:
测试代码:
@Test public void shouldGetStatus404WhenRquestIdBiggerThan10() throws Exception { mockMvc.perform(get("/requests/11") .param("userId", "xianlinbox") ) .andExpect(status().isBadRequest()) .andExpect(content().string("Request id must less than 10")); } @Test public void shouldGetStatus500WhenUnexpectedErrorHappen() throws Exception { mockMvc.perform(get("/requests/100") .param("userId", "xianlinbox") ) .andExpect(status().isInternalServerError()) .andExpect(content().string("Unexpected Server Error")); }
实现代码:
@ExceptionHandler(InvalidRequestIdException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public String handleInvalidRequestError(InvalidRequestIdException ex) { return ex.getMessage(); } @ExceptionHandler(RuntimeException.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public String handleUnexpectedServerError(RuntimeException ex) { return ex.getMessage(); }
这种处理方式其它都好,就是有个最大的弊端,只能处理一个Controller的异常,对于又多个Controller的情况就会搞出很多的重复代码。
基于Application的异常处理
我个人觉得一个好的异常处理机制应该是这样的,有一个集中的处理点负责所有的异常处理,在真正的业务逻辑的处理过程中,我只会关心正常的业务流程,一旦遇到异常,我只管抛出对应的异常和相关的信息就行了。幸运的是,Spring MVC就提供了这样的机制,开发者可以自己定义一个ExceptionHandler类处理所有的异常,在这个类上加上@ControllerAdvice注解,这个类就以AOP的形式注册到SpringMVC的处理链条中了,在应用任何地方抛出Exception,最后都会调用到这个handler中的方法上,在Handler类中,可以和上面一样使用@ExceptionHandler注解来区别对待不同的Exception。栗子:
测试代码:
同上:但是需要注意一点,使用@ControllerAdvice是以AOP的形式做了一个切面处理异常,因此,你必须模拟整个Web处理过程该注解才能起效。因此在Integration测试类中,你需要加上@WebAppConfiguration注解,同时使用WebApplicationContext构建MockMvc,使用基于Controller的standaloneSetup是不能达到想要的效果的。
@WebAppConfiguration public class ApiControllerIntegrationTest { @Autowired private WebApplicationContext webApplicationContext; private MockMvc mockMvc; @Before public void setUp() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } ...
实现代码:
@ControllerAdvice public class ApiExceptionHandler { @ExceptionHandler(InvalidRequestIdException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public String handleInvalidRequestError(InvalidRequestIdException ex) { return ex.getMessage(); } @ExceptionHandler(RuntimeException.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public String handleUnexpectedServerError(RuntimeException ex) { return ex.getMessage(); } }
评论
6 楼
sqz10200
2016-04-14
博主写的不错, 思想和写的代码都挺好 我平时都是看老外的写的例子, 你这个写的确实不错. 我原本是想把web.xml中的error-page这快内容放到java代码内实现的, 我想去掉web.xml内所有的配置. 之前在google上查过找到http://stackoverflow.com/questions/10813993/using-spring-mvc-3-1-webapplicationinitializer-to-programatically-configure-ses
老外的这片文章和你的解决方法是一样的. 我这里有一个问题 对于这个error是基于spring的aop去实现的. 那么和之前写在web.xml的有什么区别呢? 其实这个注解也应该是基于原生的做的扩展吧...如果我不想用spring 方式 而是基于WebApplicationInitializer 这个是不是也可以实现呢?
老外的这片文章和你的解决方法是一样的. 我这里有一个问题 对于这个error是基于spring的aop去实现的. 那么和之前写在web.xml的有什么区别呢? 其实这个注解也应该是基于原生的做的扩展吧...如果我不想用spring 方式 而是基于WebApplicationInitializer 这个是不是也可以实现呢?
5 楼
whhwkm
2016-01-17
好文来顶,nice
4 楼
ningandjin
2014-10-17
sulibra 写道
不用再配置文件里写些什么吗?
你的spring配置文件中需要添加annotation-driven的配置,告诉Spring容器根据Annotation加载。。
3 楼
sulibra
2014-10-16
不用再配置文件里写些什么吗?
2 楼
ningandjin
2014-03-30
sachxp 写道
非常感谢楼主,写的非常详细,很棒。拜读之后收益颇丰。
基于Controller的异常处理那段示例代码里漏了 @ResponseBody annotation,会导致Response无视 @ResponseStatus 的设置永远返回400错误。
查了一会儿才发现问题。
基于Controller的异常处理那段示例代码里漏了 @ResponseBody annotation,会导致Response无视 @ResponseStatus 的设置永远返回400错误。
查了一会儿才发现问题。
有用就好,我的例子是基于Spring4.0的,在Controller上使用的annotation是@RestController而不是@Controller, @RestController和@Controller的区别就是会为Controller的每个@RequestMapping方法加上@ResponseBody的annotation。
1 楼
sachxp
2014-03-27
非常感谢楼主,写的非常详细,很棒。拜读之后收益颇丰。
基于Controller的异常处理那段示例代码里漏了 @ResponseBody annotation,会导致Response无视 @ResponseStatus 的设置永远返回400错误。
查了一会儿才发现问题。
基于Controller的异常处理那段示例代码里漏了 @ResponseBody annotation,会导致Response无视 @ResponseStatus 的设置永远返回400错误。
查了一会儿才发现问题。
发表评论
-
关于并发的思考
2015-02-08 22:33 4256并发数 并发数和2个因 ... -
使用Hystrix守护应用(3)
2015-01-02 22:04 12812监控HystrixCommand 除了隔离依赖服务的调用外,H ... -
使用Hystrix守护应用(2)
2014-12-30 14:35 16744接上篇(http://ningandjiao.iteye.co ... -
使用Hystrix守护应用(1)
2014-12-30 14:28 15172Hystrix(https://github.com/Netf ... -
Mac下同时安装多个版本的JDK
2014-04-14 21:42 33081JDK8 GA之后,小伙伴们喜大普奔,纷纷跃跃欲试,想体验一下 ... -
性能测试工具之Gatling
2014-01-15 19:27 17215Gatling一直是久闻其名但 ... -
JavaMail测试工具之GreenMail
2014-01-08 19:13 7313不管现在各种Mock框架的运用有多广,我个人在写单元测试的时候 ... -
定制一个Gradle Plugin --- project-structure
2014-01-03 21:23 8396最近在项目中遇到一个 ... -
Restful Spring MVC应用的Request验证
2013-12-26 15:05 23283在开放平台的时候,尤其是坐Rest服务的时候,因为用户可以给你 ... -
Spring 4.0升级小贴士
2013-12-22 19:40 11382随着Spring4.0的发布,很多同志估计都在考虑升级的事情了 ... -
Spring4.0给我们带来什么?
2013-12-22 17:13 44940JDK8 对JDK8的支持,这个目前来说还是探索性质,毕竟Ja ... -
RESTful API版本控制策略
2013-12-15 19:51 31588做RESTful开放平台,一方面其API变动越少, 对API调 ... -
对象转换利器之Dozer
2013-12-14 22:46 19762在Java的世界中,经常会 ... -
基于Spring-WS的Restful API的集成测试
2013-11-28 19:41 8895在很多Java企业级应用中,Spring占据了非常重要的位置, ... -
TDD Of Spring JMS
2013-11-25 19:53 1695不知何时养成了习惯,在没有一个可运行的测试的时候,个人完全没有 ... -
Micro Service工具集之Swagger:可测试的样式化API文档
2013-09-28 19:55 44634在我之前的一篇博文中,介绍了Yammer开发团队贡献的开源微服 ... -
进击的Java开发
2013-07-14 20:48 5842今天在公司的邮件组中看到一组很有趣的讨论,这是我最喜欢目前公司 ... -
说说SpringBatch的领域概念
2013-06-21 20:32 3572谈到Spring Batch,会谈到 ... -
做项目时需要考虑的安全性问题
2013-04-16 20:20 4712在开发一个项目的时候,大家经常会忽略项目的安全性问题,有很多的 ... -
使用Gradle部署jar包到Maven中央库
2013-04-12 16:15 24073Maven作为目前Java界最好的Dependency管理系统 ...
相关推荐
spring mvc统一处理异常,通过@ControllerAdvice+@ExceptionHandler
spring mvc异常处理,详细参考http://blog.csdn.net/xiejx618/article/details/41918611
主要给大家介绍了关于Spring MVC中异常处理的三种方式,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring MVC具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
spring mvc让servlet容器直接处理异常.详细看:http://blog.csdn.net/xiejx618/article/details/41695255
十一、spring mvc 如何实现全局的异常处理? 十二、spring mvc 如何把全局异常记录到日志中? 十三、如何给spring3 MVC中的Action做JUnit单元测试? 十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求 ...
十一、spring mvc 如何实现全局的异常处理? 十二、spring mvc 如何把全局异常记录到日志中? 十三、如何给spring3 MVC中的Action做JUnit单元测试? 十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求 ...
第3篇是Spring MVC技术入门,包括Spring MVC的背景介绍、架构整体剖析、环境搭建、处理器与映射器的讲解、前端控制器的源码分析、多种视图解析器的介绍、请求映射与参数绑定的介绍、Validation校验与异常处理和拦截...
1.创建第一个 Spring MVC 程序案例 2.Spring MVC @RequestMapping 注解案例 3.Spring MVC 请求参数的获取案例 4.Spring MVC 域对象共享数据案例 5.Spring MVC @ModelAttribute 注解案例 ...15.Spring MVC 异常处理案例
NULL 博文链接:https://cgs1999.iteye.com/blog/1547197
十一、spring mvc 如何实现全局的异常处理? 十二、spring mvc 如何把全局异常记录到日志中? 十三、如何给spring3 MVC中的Action做JUnit单元测试? 十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求...
NULL 博文链接:https://gaojiewyh.iteye.com/blog/1297746
Spring 异常处理 Spring MVC 有两个主要方式来处理在调用 MVC 控制器(译注:Controller,下文统一为控制器)时抛出的异常:HandlerExceptionResolver 和 @ExceptionHandler 注解。 ...
本篇文章主要介绍了详解使用Spring MVC统一异常处理实战,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Spring MVC--9.自定义拦截器、异常处理
那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的。下面将介绍使用Spring MVC统一处理异常的解决和实现过程。
《Spring MVC 3.0实战指南》,参考《Spring 3.x企业应用开发实战》。 内容简介: 1、Spring MVC框架简介 2、HTTP请求地址映射 3、HTTP请求数据的绑定 4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7...
因为在 REST APIs 中并没有直接的 UI 概念,那么你该如何使用 Spring MVC 简单直观的表示异常或问题呢? 本文是系列文章两部分中的第一部分。在本文中,我们将涉及 RESTful 异常报告的佳实践。第二部分将会通过一...
本篇文章主要介绍了Spring MVC全局异常处理和单元测试,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
problem-spring-web, 在 spring Web MVC中,处理问题的库 Web站点MVC问题 问题 spring 是一个库,它使得从 spring 应用程序中生成 application/problem json 响应变得容易。 工具填补了一个利基,它将问题库和mvc...