- 浏览: 1036617 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
繁星水:
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 4339并发数 并发数和2个因 ... -
使用Hystrix守护应用(3)
2015-01-02 22:04 12876监控HystrixCommand 除了隔离依赖服务的调用外,H ... -
使用Hystrix守护应用(2)
2014-12-30 14:35 16817接上篇(http://ningandjiao.iteye.co ... -
使用Hystrix守护应用(1)
2014-12-30 14:28 15285Hystrix(https://github.com/Netf ... -
Mac下同时安装多个版本的JDK
2014-04-14 21:42 33241JDK8 GA之后,小伙伴们喜大普奔,纷纷跃跃欲试,想体验一下 ... -
性能测试工具之Gatling
2014-01-15 19:27 17298Gatling一直是久闻其名但 ... -
JavaMail测试工具之GreenMail
2014-01-08 19:13 7368不管现在各种Mock框架的运用有多广,我个人在写单元测试的时候 ... -
定制一个Gradle Plugin --- project-structure
2014-01-03 21:23 8496最近在项目中遇到一个 ... -
Restful Spring MVC应用的Request验证
2013-12-26 15:05 23369在开放平台的时候,尤其是坐Rest服务的时候,因为用户可以给你 ... -
Spring 4.0升级小贴士
2013-12-22 19:40 11440随着Spring4.0的发布,很多同志估计都在考虑升级的事情了 ... -
Spring4.0给我们带来什么?
2013-12-22 17:13 45033JDK8 对JDK8的支持,这个目前来说还是探索性质,毕竟Ja ... -
RESTful API版本控制策略
2013-12-15 19:51 31741做RESTful开放平台,一方面其API变动越少, 对API调 ... -
对象转换利器之Dozer
2013-12-14 22:46 19880在Java的世界中,经常会 ... -
基于Spring-WS的Restful API的集成测试
2013-11-28 19:41 9070在很多Java企业级应用中,Spring占据了非常重要的位置, ... -
TDD Of Spring JMS
2013-11-25 19:53 1760不知何时养成了习惯,在没有一个可运行的测试的时候,个人完全没有 ... -
Micro Service工具集之Swagger:可测试的样式化API文档
2013-09-28 19:55 44742在我之前的一篇博文中,介绍了Yammer开发团队贡献的开源微服 ... -
进击的Java开发
2013-07-14 20:48 5913今天在公司的邮件组中看到一组很有趣的讨论,这是我最喜欢目前公司 ... -
说说SpringBatch的领域概念
2013-06-21 20:32 3625谈到Spring Batch,会谈到 ... -
做项目时需要考虑的安全性问题
2013-04-16 20:20 4787在开发一个项目的时候,大家经常会忽略项目的安全性问题,有很多的 ... -
使用Gradle部署jar包到Maven中央库
2013-04-12 16:15 24165Maven作为目前Java界最好的Dependency管理系统 ...
相关推荐
在异常处理中,记录详细的错误信息至关重要。你可以使用`Logger`对象来记录异常堆栈跟踪和其他相关信息,以便于后续的调试和问题定位。 7. **异常转换** 有时,你可能希望将特定的异常转换为其他类型,以便更好地...
spring mvc统一处理异常,通过@ControllerAdvice+@ExceptionHandler
Spring MVC 中异常处理的三种方式 Spring MVC 框架为我们提供了三种方式来处理异常,分别是实现 HandlerExceptionResolver、使用 @ControllerAdvice 和 @ExceptionHandler 注解、使用 ErrorController。下面我们将...
在Spring MVC框架中,异常处理是一项关键任务,它确保了应用程序在遇到错误或异常时能够优雅地响应。本文将深入探讨Spring MVC中的异常处理机制,包括如何配置、自定义异常处理器以及异常转换策略。 首先,Spring ...
十一、Spring MVC如何实现全局的异常处理:提供了实现全局异常处理器的方式,让开发者能够捕获所有控制器抛出的异常,统一处理。 十二、Spring MVC如何把全局异常记录到日志中:讲述了如何将异常信息记录到日志文件...
错误处理和异常处理也是Spring MVC中的重要部分,通过@ControllerAdvice和@ExceptionHandler可以全局处理异常,提供统一的错误页面。 最后,测试是任何应用程序开发的重要环节。Spring MVC提供了MockMVC,可以在不...
6. **异常处理**:通过定义全局异常处理器,可以统一处理应用程序中的异常,提高代码的整洁性和可维护性。 7. **多视图解析器**:Spring MVC支持多种视图解析器,如JSP、FreeMarker、Thymeleaf等,可以根据项目需求...
除此之外,Spring MVC还支持数据绑定、验证、本地化、主题、异常处理等功能。例如,使用@ModelAttribute注解可以将请求参数绑定到Controller方法的参数上,@Valid用于进行数据验证,Validator接口可以自定义验证逻辑...
异常处理** 通过自定义异常处理器,Spring MVC允许优雅地处理运行时异常,提供了统一的错误页面和异常信息。 **7. RESTful支持** Spring MVC支持构建RESTful服务,通过HTTP方法如GET、POST、PUT、DELETE等,实现...
在Spring MVC 4.0版本中,它引入了许多改进和新特性,以提升开发效率和应用程序的性能。 1. **依赖注入**:Spring MVC 4.0继续支持Spring框架的核心功能,依赖注入(DI),允许开发者通过配置来管理对象及其依赖...
- **@ExceptionHandler 注解**:用于声明异常处理方法。 - **处理一般的 Spring MVC 异常**:Spring MVC 自身的一些异常可以在这里统一处理。 - **使用 @ResponseStatus 注解业务异常**:为自定义异常添加 HTTP 状态...
下面我们将深入探讨Spring MVC 5.0.3中的关键知识点。 1. **DispatcherServlet**: 作为Spring MVC的核心组件,DispatcherServlet负责接收HTTP请求,然后根据配置的映射规则将请求分发到相应的处理器(Controller)...
`org.springframework.web-3.1.1.RELEASE.jar` 包含了Spring框架对Web应用的支持,如过滤器、异常处理和请求映射等。 `javassist-3.12.0.GA.jar` 是Java编程辅助工具,它在运行时可以动态修改类和创建新的类,常...
Spring MVC 提供了丰富的功能,包括请求处理、视图解析、数据绑定、异常处理等,旨在简化 Web 开发流程。 1. **Spring MVC 概述**:Spring MVC 是基于 Spring 框架构建的,它遵循 MVC 设计模式,将业务逻辑、数据和...
十一、spring mvc 如何实现全局的异常处理? 十二、spring mvc 如何把全局异常记录到日志中? 十三、如何给spring3 MVC中的Action做JUnit单元测试? 十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求 ...
Spring MVC提供了一种优雅的异常处理机制,可以使用@ControllerAdvice和@ExceptionHandler注解定义全局异常处理器。此外,还可以自定义错误页面,提高用户体验。 8. **数据绑定和验证** Spring MVC支持自动的数据...
13. **异常处理**: 通过@ControllerAdvice和@ExceptionHandler,可以全局捕获并处理应用程序中的异常,提供统一的错误页面或JSON响应。 14. **Internationalization (i18n) & Localization (l10n)**: Spring MVC ...