Spring异常处理@ExceptionHandler
最近学习Spring时,认识到Spring异常处理的强大。之前处理工程异常,代码中最常见的就是try-catch-finally,有时一个try,多个catch,覆盖了核心业务逻辑:
try{
..........
}catch(Exception1 e){
..........
}catch(Exception2 e){
...........
}catch(Exception3 e){
...........
}
Spring能够较好的处理这种问题,核心如下,文章主要关注前两个:
- @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
- @ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开;其是对Controller层进行拦截
- @ResponseStatus:可以将某种异常映射为HTTP状态码
@ExceptionHandler
源码如下:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}
该注解作用对象为方法,并且在运行时有效,value()可以指定异常类。由该注解注释的方法可以具有灵活的输入参数(详细参见Spring API):
- 异常参数:包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。
- 请求或响应对象 (Servlet API or Portlet API): 你可以选择不同的类型,如ServletRequest/HttpServletRequest或PortleRequest/ActionRequest/RenderRequest
。
- Session对象(Servlet API or Portlet API): HttpSession或PortletSession。
- WebRequest或NativeWebRequest
- Locale
- InputStream/Reader
- OutputStream/Writer
Model
方法返回值可以为:
- ModelAndView对象
- Model对象
- Map对象
- View对象
- String对象
- 还有@ResponseBody、HttpEntity<?>或ResponseEntity<?>,以及void
@ControllerAdvice
源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {}; @AliasFor("value")
String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] assignableTypes() default {}; Class<? extends Annotation>[] annotations() default {};
}
该注解作用对象为TYPE,包括类、接口和枚举等,在运行时有效,并且可以通过Spring扫描为bean组件。其可以包含由@ExceptionHandler、@InitBinder 和@ModelAttribute标注的方法,可以处理多个Controller类,这样所有控制器的异常可以在一个地方进行处理。
实例
异常类:
public class CustomGenericException extends RuntimeException{
private static final long serialVersionUID = 1L; private String errCode;
private String errMsg; public String getErrCode() {
return errCode;
} public void setErrCode(String errCode) {
this.errCode = errCode;
} public String getErrMsg() {
return errMsg;
} public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
} public CustomGenericException(String errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
}
控制器:
@Controller
@RequestMapping("/exception")
public class ExceptionController { @RequestMapping(value = "/{type}", method = RequestMethod.GET)
public ModelAndView getPages(@PathVariable(value = "type") String type) throws Exception{
if ("error".equals(type)) {
// 由handleCustomException处理
throw new CustomGenericException("E888", "This is custom message");
} else if ("io-error".equals(type)) {
// 由handleAllException处理
throw new IOException();
} else {
return new ModelAndView("index").addObject("msg", type);
}
}
}
异常处理类:
@ControllerAdvice
public class ExceptionsHandler { @ExceptionHandler(CustomGenericException.class)//可以直接写@ExceptionHandler,不指明异常类,会自动映射
public ModelAndView customGenericExceptionHnadler(CustomGenericException exception){ //还可以声明接收其他任意参数
ModelAndView modelAndView = new ModelAndView("generic_error");
modelAndView.addObject("errCode",exception.getErrCode());
modelAndView.addObject("errMsg",exception.getErrMsg());
return modelAndView;
} @ExceptionHandler(Exception.class)//可以直接写@EceptionHandler,IOExeption继承于Exception
public ModelAndView allExceptionHandler(Exception exception){
ModelAndView modelAndView = new ModelAndView("generic_error");
modelAndView.addObject("errMsg", "this is Exception.class");
return modelAndView;
}
}
JSP页面:
正常页面index.jsp:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Spring MVC @ExceptionHandler Example</h2> <c:if test="${not empty msg}">
<h2>${msg}</h2>
</c:if> </body>
</html>
异常处理页面generic_error.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body> <c:if test="${not empty errCode}">
<h1>${errCode} : System Errors</h1>
</c:if> <c:if test="${empty errCode}">
<h1>System Errors</h1>
</c:if> <c:if test="${not empty errMsg}">
<h2>${errMsg}</h2>
</c:if> </body>
</html>
测试运行如下:
正常情况:
CustomGenericException异常情况:
IOException异常情况:
总结
- @ExceptionHandler和@ControllerAdvice能够集中异常,使异常处理与业务逻辑分离
- 本文重点理解两种注解方式的使用
参考:
- Spring API:http://docs.spring.io/spring/docs/current/javadoc-api/
- 《Spring in Action》
- Spring MVC @ExceptionHandler Example
Spring异常处理@ExceptionHandler的更多相关文章
- Spring 异常处理三种方式 @ExceptionHandler
异常处理方式一. @ExceptionHandler 异常处理方式二. 实现HandlerExceptionResolver接口 异常处理方式三. @ControllerAdvice+@Excepti ...
- spring异常处理
http://cgs1999.iteye.com/blog/1547197 1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到 ...
- Unit06: Spring对JDBC的 整合支持 、 Spring+JDBC Template、Spring异常处理
Unit06: Spring对JDBC的 整合支持 . Spring+JDBC Template .Spring异常处理 1. springmvc提供的异常处理机制 我们可以将异常抛给spring框架 ...
- Spring的@ExceptionHandler和@ControllerAdvice统一处理异常
之前敲代码的时候,避免不了各种try..catch, 如果业务复杂一点, 就会发现全都是try…catch try{ ..........}catch(Exception1 e){ ......... ...
- Spring MVC 异常处理 - ExceptionHandler
通过HandlerExceptionResolver 处理程序异常,包括Handler映射, 数据绑定, 以及目标方法执行时的发生的异常 实现类如下 /** * 1. 在 @ExceptionHand ...
- 统一异常处理@ExceptionHandler
异常处理功能中用到的注解是:@ExceptionHandler(异常类型.class). 这个注解的功能是:自动捕获controller层出现的指定类型异常,并对该异常进行相应的异常处理. 比如我要在 ...
- Spring @ControllerAdvice @ExceptionHandler 全局处理异常
对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来, ...
- spring 异常处理的方式?
一.使用SimpleMappingExceptionResolver解析器 1.1在mvc中进行 配置. <?xml version="1.0" encoding=" ...
- Spring @ControllerAdvice @ExceptionHandler
先来两个连接: Spring3.2新注解@ControllerAdvice Spring 注解学习手札(八)补遗——@ExceptionHandler @Controller Class中如果有@Ex ...
随机推荐
- Windows2000源代码 200+MB
全球最大的软件制造商微软2月12日警告公众称其一部分珍贵的Windows NT和Windows 2000操作系统源代码被泄漏到了一些在线文件共享网络中. 微软称被泄漏的代码只是整个程序的一小部分,但这 ...
- mysql数据库插入数据获取自增主键的三种方式(jdbc PreparedStatement方式、mybatis useGeneratedKeys方式、mybatis selectKey方式)
通常来说对于mysql数据库插入数据获取主键的方法是采用selectKey的方式,特别是当你持久层使用mybatis框架的时候. 本文除此之外介绍其它两种获取主键的方式. 为了方便描述我们先建一张my ...
- tensorflow MNIST新手教程
官方教程代码如下: import gzip import os import tempfile import numpy from six.moves import urllib from six.m ...
- springMVC学习总结(二)路径映射和请求方法限定
springMVC学习总结(二)路径映射和请求方法限定 一.路径映射 无参数的访问路径 对springmvc项目的访问路径,是由根路径和子路径组成:在注解式开发中,根路径标注在类名之上,子路径标注在方 ...
- HDoj-1042 大数阶乘
N! Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- hdu 5635 LCP Array(BC第一题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5635 LCP Array Time Limit: 4000/2000 MS (Java/Others) ...
- pthread线程属性介绍
线程属性 创建线程函数 int pthread_create (pthread_t* restrictthread, const pthread_attr_t* restrictattr,void* ...
- or1200处理器的异常处理类指令介绍
下面内容摘自<步步惊芯--软核处理器内部设计分析>一书 我们在计算机体系结构的学习中知道:中断实质上包含由外部事件引起的硬中断(又称外中断)和由内部预先安排的特定指令或内部异常引起的软中断 ...
- Python笔记·第四章—— 细数Python中的数据类型以及他们的方法
一.数据类型的种类及主要功能 1.数字类型 数字类型主要是用来计算,它分为整数类型int和浮点类型float 2.布尔类型 布尔类型主要是用于判断,它分为真True和False两种 3.字符串类型 字 ...
- Activiti 基本操作之“受理人变量”
在 Activiti 流程引擎中,尽管通过 setAssignee(taskId, userId) 可以设置受理人,但这毕竟要先把下一步的任务查出来才能设置,比较繁琐:借助 Activiti 的 ac ...