Spring MVC 处理异常的3种方式
使用Spring MVC开发的博客网站时,遇到了如何处理业务层抛出的异常的问题,查阅到了spring官方博客-spring MVC中异常的处理,以下将会以登录模块为示例。
愚蠢的处理方式
处理异常遵循“早抛出,晚捕获"的原则,在controller中统一处理异常,调用业务逻辑service时使用try-catch包围。

然而这样需要每个controller方法中会编写模版代码,自然Spring MVC的设计者也会想到这个问题!于是去查阅资料。
优雅的解决方案
Spring MVC提供的3类处理方式,实现在控制层controller的外围处理异常,大概示意图如下:

- 基于异常类(自定义),即针对某类异常;
- 基于控制器(
controller),即针对某个控制器; - 全局异常处理;
Spring MVC异常处理
LoginController控制器中处理登录的方法login,代码如下:
/**
* 登录
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public LuoblogResult<Author> login(String username, String password, HttpSession session) {
// 登录的业务逻辑
// 当用户名或密码错误将抛出异常
Author author = authorService.login(username, password);
return new LuoblogResult<Author>(true, author);
}
为了和Spring异常处理产生对比,这里不使用任何异常处理,浏览器中输入不存在的用户,执行结果如下:

注:作者名不存在,业务层会抛出BusinessException异常;
1.基于自定异常类处理
是时候让我们尝尝Spring异常处理这个香饽饽,只需要使用@ResponseState注解对自定义异常类进行标注,Spring在处理异常的时候会利用反射对该注解标记的异常特殊处理(个人推测):
/**
* 业务异常
* Created by luokaiqiongmou on 2016/12/6.
*/
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "业务异常,伪装为错误请求")
public class BusinessException extends RuntimeException{
// 一些内容
}
现在再来登录一次,输入不存在的用户名,执行结果如下:

巧妙的将原本的500错误,修改为400错误,那这有什么用了,这样你就可以控制对应异常发生时转化为其他的状态码,便于前端处理。
2.基于控制器,处理异常
现在我们可以针对某个控制器处理异常,只需要在控制器中增加一个异常处理方法,并使用@ExceptionHandler标注:
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "业务异常,针对控制器处理")
@ExceptionHandler(BusinessException.class)
public void conflict() {
// 不做任何事或者可以做任何事
}
同样登录一次,结果如下:

注:@ExceptionHandler标注的方法,方法签名灵活、多变。被@ResponseStatus注解的方法将会修改相应状态码,而使用@ResponseBody可以返回json格式的数据,再供前端处理。参考:示例
3. 全局的异常处理
针对某个控制器处理异常的方式会造成代码入侵
方式一:使用注解
现在创建一个专门处理异常的类,并添加@ControllerAdvice注解,如下:
/**
* 异常处理
* Created by luokaiqiongmou on 2016/12/17.
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(BusinessException.class)
@ResponseBody
public LuoblogResult<Object> handle(BusinessException e) {
logger.warn("GloabalExceptionHandler handing a Exception: " + e.getMessage());
// 业务失败返回
return new LuoblogResult<Object>(false, e.getDescription());
}
}
再次登录,效果如下:

方式二:实现HandlerExceptionResolver,并注入到spring容器中
创建一个类实现HandlerExceptionResolver,并在配置文件中注入bean,参考:自定义异常处理器,以下方式未做测试
Spring已经为我们预定义了一个处理异常的解析类SimpleMappingExceptionResolve,添加如下配置文件即可:
<bean id="simpleMappingExceptionResolver" class=
"org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<map>
<!-- key:异常类别(非全称), 视图名称 -->
<entry key="DatabaseException" value="databaseError"/>
<entry key="InvalidCreditCardException" value="creditCardError"/>
</map>
</property>
<!-- 默认的错误处理页面,异常的名称 -->
<property name="defaultErrorView" value="error"/>
<property name="exceptionAttribute" value="ex"/>
<!-- Name of logger to use to log exceptions. Unset by default,
so logging is disabled unless you set a value. -->
<property name="warnLogCategory" value="example.MvcLogger"/>
</bean>
总结
三种异常处理方式,主要涉及3个注解和1个接口,@ExceptionHandler标注的方法被定义为处理指定类型异常;@ResponseStatus标注的方法执行,会修改响应头中的状态码;Spring会把@ControllerAdvice的类内部使用@ExceptionHandler方法应用到所有的 @RequestMapping注解的方法上。
- 基于异常的处理方式,第一种无法实现json数据返回
- 基于控制器的方式
- 全局的方式!
Spring MVC 处理异常的3种方式的更多相关文章
- Spring MVC处理异常的4种方式
http://blog.csdn.net/ufo2910628/article/details/40399539 http://my.oschina.net/CandyDesire/blog/3333 ...
- spring mvc 处理映射的几种方式
1.Spring MVC bean的nameurl处理映射 <bean class="org.springframework.web.servlet.view.InternalReso ...
- Spring MVC处理异常有3种方法
1.使用 SimpleMappingExceptionResolver 实现异常处理 <bean class="org.springframework.web.servlet.hand ...
- 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比
[原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...
- spring mvc绑定参数之 类型转换 有三种方式:
spring mvc绑定参数之类型转换有三种方式: 1.实体类中加日期格式化注解(上次做项目使用的这种.简单,但有缺点,是一种局部的处理方式,只能在本实体类中使用.方法三是全局的.) @DateTim ...
- C# MVC 实现登录的5种方式
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷. 学无止境,精益求精 小弟之前做过三月的MVC,后来又一直webFo ...
- ASP.NET中处理异常的几种方式
1.程序中使用try catch 对于预知会发生异常的代码段使用try catch主动捕获异常,适用于提示给用户或跳转到错误页面,或者通过其它方式处理异常(日志.通知等). int i = 10; i ...
- (转载)MVC + JQUERY + AJAX的几种方式
MVC + JQUERY + AJAX的几种方式 // 传过去一个简单值,获取一个简单值 $.ajax({ type: "GET", url: ...
- MVC日期格式化的2种方式
原文:MVC日期格式化的2种方式 假设有这样的一个类,包含DateTime类型属性,在编辑的时候,如何使JoinTime显示成我们期望的格式呢? using System; using System. ...
随机推荐
- canvas绘制圆形进度条(或显示当前已浏览网页百分比)
使用canvas绘制圆形进度条,或者是网页加载进度条 或者是显示你浏览了本网页多少-- 由于个浏览器的计算差异,打开浏览器时 初始值有所不同,但是当拉倒网页底部时,均显示100%. 兼容性:测试浏览器 ...
- php引入文件(include 和require的区别)
引入文件: 首先需要一个php文件: <?php class shao//类名必须和文件名相同!!! { public $xxx="666"; } $shili = new ...
- jQuery_第五章_事件和动画
Jquery中的事件与动画 一.window.onload和$(document).read()的细微差别 (1)执行时机 window.onload:所有元素(包括元素的所有关联文件)完全加载到浏览 ...
- Spring Mvc + Easyui中根据查询结果导出文件
项目是典型的SpringMvc + Easyui,需求是前台页面根据查询条件导出生成CSV文件. 基本流程是:前台页面通过表单提交的方式,请求后台,后台接受到查询参数,根据查询参数查询到数据集合,最后 ...
- 简单说说Markdown语法
# 简单说说 MarkDown 语法 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr ...
- jQuery DataTable 删除数据后重新加载
问题描述: 利用jQuery Datatable和artTemplate组合来做的表格.但是当删除数据时,需要重新加载table里的数据.但是问题是datatable并没有直接的重新渲染,反而给数据累 ...
- linux-网络数据包抓取-tcpdump
用法格式: tcpdump [-i 网卡] [选项] '表达式' 选项说明如下: -i:interface 监听的网卡. -nn:表示以ip和port的方式显示来源主机和目的主机,而不是用主机名和 ...
- 转:Apache 与 Nginx 比较
Nginx 轻量级,采用 C 进行编写,同样的 web 服务,会占用更少的内存及资源 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apa ...
- 应用控制台应用程序开发批量导入EXEL程序。
一.最近一直在调整去年以及维护去年开发的项目,好久没有在进行个人的博客了.每天抽了一定的时间在研究一些开源的框架,Drapper 以及NHibernate以及当前比较流行的SqlSuper框架 并进行 ...
- bash之重定向
标准输入 stdin:代码为0,使用< 或 <& ...