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. ...
随机推荐
- 关于hibernate注解的简单应用
@Override 用途:重写父类的同名方法 单元测试注解 @Test 用途:用于测试 @Before 用途:单测方法走之前执行 @After 用途:单测方法走之后执行 注解的目标:替换小配置.替换h ...
- apache的用户认证
1. 限制用户访问的方式: 1. 限制访问服务的客户端主机 2. 需要用户名和密码 2. 行为用户验证需要两步: 1. 创建一个包含用户名和密码的文件 2. 服务器上的哪些资源需要保护,哪些用户可以进 ...
- phpcmsV9静态页面替换动态步骤
1.先在www目录下找到 phpcms + install_package + phpcms + templates在templates 文件夹里创建个自己的文件夹我弄得是 ceshi 文件夹,在 c ...
- Linux-7.2+LNMP+zabbix-3.2.1
LNMP+zabbix-3.2.1 一.zabbix服务端部署 1.解压 yum –y install bzip2 tar -xf nginx-1.10.1.tar.gz tar -xf php-5. ...
- .NET Core跨平台:使用.NET Core开发一个初心源商城总括
1..NET Core基本介绍 a 作为一个.NET的开发者,在以前的开发中,我们开发的项目基本都是部署在windows服务器上,但是在windows服务器上的话某些比较流行的解决访问量的方案基本都是 ...
- 漂亮的代码3:flatten 一个数组
看到一个题目: flatten([1,2,3]) // => [1,2,3] flatten([[1,2,3],["a","b","c" ...
- 禁止Linux系统被 ping
echo "net.ipv4.icmp_echo_ignore_all=1" >> /etc/sysctl.conf sysctl -p 生效 开启ping功能: 删除 ...
- 高精度模板 Luogu P1932 A+B & A-B & A*B & A/B Problem
P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...
- MyBatis 的小细节问题
mybatis Result Maps collection already contains value 这是个小功能,我当时没有怎么在意,后来发到了测试环境的时候测试提出了bug,我才慌忙查看原因 ...
- 结合prototype和xmlhttprequest封装ajax请求
由于拖延症的严重以及年前准备年会(借口*^__^*) 导致这个小的的思考 现在才算完成 再怎么说也算是上班以来带我的前辈第一次这么正式的给我出题 不管是出于尊重还是自我要求我都决定把它简要的记下来 ...