使用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种方式的更多相关文章

  1. Spring MVC处理异常的4种方式

    http://blog.csdn.net/ufo2910628/article/details/40399539 http://my.oschina.net/CandyDesire/blog/3333 ...

  2. spring mvc 处理映射的几种方式

    1.Spring MVC bean的nameurl处理映射 <bean class="org.springframework.web.servlet.view.InternalReso ...

  3. Spring MVC处理异常有3种方法

    1.使用 SimpleMappingExceptionResolver 实现异常处理 <bean class="org.springframework.web.servlet.hand ...

  4. 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比

    [原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...

  5. spring mvc绑定参数之 类型转换 有三种方式:

    spring mvc绑定参数之类型转换有三种方式: 1.实体类中加日期格式化注解(上次做项目使用的这种.简单,但有缺点,是一种局部的处理方式,只能在本实体类中使用.方法三是全局的.) @DateTim ...

  6. C# MVC 实现登录的5种方式

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷.  学无止境,精益求精    小弟之前做过三月的MVC,后来又一直webFo ...

  7. ASP.NET中处理异常的几种方式

    1.程序中使用try catch 对于预知会发生异常的代码段使用try catch主动捕获异常,适用于提示给用户或跳转到错误页面,或者通过其它方式处理异常(日志.通知等). int i = 10; i ...

  8. (转载)MVC + JQUERY + AJAX的几种方式

    MVC + JQUERY + AJAX的几种方式 // 传过去一个简单值,获取一个简单值 $.ajax({            type: "GET",         url: ...

  9. MVC日期格式化的2种方式

    原文:MVC日期格式化的2种方式 假设有这样的一个类,包含DateTime类型属性,在编辑的时候,如何使JoinTime显示成我们期望的格式呢? using System; using System. ...

随机推荐

  1. Eval与Bind的区别

    bind和eval都是ASP.NET中的函数,而且都有对将数据获取到Html中的功能.那么,它们在使用的时候有什么区别呢?在我们编程的时候,在某种情况下,用哪个函数更加合适呢? 区别 用法: 1. b ...

  2. 11G内存设置一例

    11G的内存设置参数有memory_target.memory_max_target.sga_target.pga_aggregate_target等. 一个特别繁忙的数据库,前期内存设置较低,物理内 ...

  3. java中静态代码块,构造代码块,以及构造方法的执行顺序

    写了许久的代码,却把一些基础的东西都给忘了,今天无聊就顺手写了个,然后测试下,发现跟我记忆中的竟然有些出入,作为一个两年的开发,我感觉自己很失败啊. 父类pojo: public class Pojo ...

  4. option触发事件两种方法总结

    代码如下: <!doctype html> <html> <head> <meta charset="UTF-8"> <tit ...

  5. MINA、Netty、Twisted一起学(十一):SSL/TLS

    什么是SSL/TLS 不使用SSL/TLS的网络通信,一般都是明文传输,网络传输内容在传输过程中很容易被窃听甚至篡改,非常不安全.SSL/TLS协议就是为了解决这些安全问题而设计的.SSL/TLS协议 ...

  6. webpack(四)处理 css\less\sass 样式

    (一) 处理普通的.css 文件,需要安装 css-loader,style-loader .less 文件,需要安装 less-loader .sass 文件,需安装  less-loader np ...

  7. 第21篇 js四种继承方式

    js是一个很自由的语言,没有强类型的语言的那种限制,实现一个功能往往有很多做法.继承就是其中的一个,在js中继承大概可以分为四大类,上面一篇文章也提及过一些,下面开始详细说说js的继承. 1.原型继承 ...

  8. MySQL中的完整性约束条件(主键、外键、唯一、非空)

    数据库的完整性约束用来防止对数据的意外破坏,来保证数据的安全性和一致性. 主键 1.创建表时候指定主键 创建表user(id, username, age),并且id字段非空自增. CREATE TA ...

  9. Eclipse:The selection cannot be launched,and there are no recent launches

    刚刚装上eclipse,于是就想写个Java程序来试试.结果写好之后不管是点击 run  还是  debug 结果都会弹出一个窗口,内容为: The selection cannot be launc ...

  10. Eclipse添加tomcat出现 The Apache Tomcat installation at this directory is version 8.5.6. A Tomcat 8.0 installation is expected.

    打开tomcat安装目录:apache-tomcat-8.5.6\lib 找到catalina.jar 用解压缩工具打开 org/apache/catalina/util/ServerInfo.pro ...