spring mvc 全局处理异常
spring框架支持很多种全局处理异常的方式
一、Spring MVC处理异常有4种方式:
(1)使用Spring-MVC提供的SimpleMappingExceptionResolver;
(2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
(3)使用@ExceptionHandler注解实现异常处理;
(4)使用@ControllerAdvice方式
二、分别介绍这三种异常处理的实现方式:
(1)使用SimpleMappingExceptionResolver实现异常处理
只需要在Spring的配置文件applicationContext.xml中增加以下内容:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定义默认的异常处理页面,当该异常类型的注册时使用 -->
<property name="defaultErrorView" value="error"></property>
<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
<property name="exceptionAttribute" value="ex"></property>
<!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常以页名作为值 -->
<property name="exceptionMappings">
<props>
<!-- 创建自己所要自定义的异常类 -->
<prop key="com.core.exception.BusinessException">business_error</prop>
<prop key="com.core.exception.ParameterException">parameter_error</prop>
<!-- 还可以继续扩展对不同异常类型的处理 -->
</props>
</property>
</bean>
(2) 实现HandlerExceptionResolver 接口自定义异常处理器
首先增加HandlerExceptionResolver 接口的实现类MyExceptionHandler,代码如下:
public class MyExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("ex", ex);
// 根据不同错误转向不同页面
if(ex instanceof BusinessException) {
return new ModelAndView("business_error", model);
}else if(ex instanceof ParameterException) {
return new ModelAndView("parameter_error", model);
} else {
return new ModelAndView("error", model);
}
}
}
然后在Spring的配置文件applicationContext.xml中增加以下内容:
<bean id="exceptionHandler" class="com.core.exception.MyExceptionHandler"/>
(3)使用@ExceptionHandler注解实现异常处理
首先要增加BaseController类,并在类中使用@ExceptionHandler注解声明异常处理,代码如下:
public class BaseController {
/** 基于@ExceptionHandler异常处理 */
@ExceptionHandler
public String exp(HttpServletRequest request, Exception ex) {
request.setAttribute("ex", ex);
// 根据不同错误转向不同页面
if(ex instanceof BusinessException) {
return "business_error";
}else if(ex instanceof ParameterException) {
return "parameter_error";
} else {
return "error";
}
}
}
然后需要修改现有代码,使所有需要异常处理的Controller都继承该类,如下所示:
public class TestController extends BaseController (4) 使用@ControllerAdvice
@ControllerAdvice(annotations = Controller.class)
public class GlobalExceptionHandler { @ExceptionHandler(SQLException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public RespBody handleSQLException(HttpServletRequest request, Exception ex) {
String message = ex.getMessage();
return RespBody.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
}
@ExceptionHandler(Exception.class)
@ResponseBody
public WapRespBody handleActivityException(HttpServletRequest request, Exception ex) {
writeLog(ex,request);
return WapRespBody.error();
} }
自定义返回类RespBody、异常类、异常枚举等 首先自定义返回类:
//作用于类或属性上,被用来在序列化/反序列化时为该对象或字段添加一个对象识别码,通常是用来解决循环嵌套的问题
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = "@code")
public class WapRespBody { private String state; private String message; //正常数据
private Object data; private WapRespBody() { } private WapRespBody(String code, String message) {
this.state = code;
this.message = message;
} private WapRespBody(String statusCode, Object data) {
this.state = statusCode;
this.data = data;
} private WapRespBody(String statusCode, String message, Object data) {
this.state = statusCode;
this.message = message;
this.data = data;
} public static WapRespBody ok() {
return new WapRespBody("200", "");
} public static WapRespBody ok(Object data) {
return new WapRespBody("200", data);
} public static WapRespBody ok(String code, String message) {
return new WapRespBody(code, message);
} public static WapRespBody error() {
return new WapRespBody("-1", "");
} public static WapRespBody error(Object data) {
return new WapRespBody("-1", data);
} public static WapRespBody error(String code, String msg) {
return new WapRespBody(code, msg);
} public String getState() {
return state;
} public void setState(String state) {
this.state = state;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} public Object getData() {
return data;
} public void setData(Object data) {
this.data = data;
}
}
自定义异常信息
package com.yunqiandai.common.exception; import com.yunqiandai.common.constant.ActivityEnum; /**
* Created with IntelliJ IDEA.
*
* @author: zhaojc
* @date: 16/12/13
* @Time: 上午11:41
* @description:
*/
public class ActivityException extends Exception { private String errorCode; private String errorMessage; public ActivityException() { } public ActivityException(String code, String message) {
this.errorCode = code;
this.errorMessage = message;
} public ActivityException(ActivityEnum activityEnum) {
this.errorCode = activityEnum.getStatus();
this.errorMessage = activityEnum.getMessage();
} public String getErrorCode() {
return errorCode;
} public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
} public String getErrorMessage() {
return errorMessage;
} public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
自定义枚举
package com.yunqiandai.common.constant; /**
* Created with IntelliJ IDEA.
* @author: zhaojc
* @date: 16/12/1
* @Time: 上午10:19
* @description: 活动常量
*/
public enum ActivityEnum { //用户未登录
USER_NO_LOGIN("201","用户未登录"), //活动已开始
ACTIVITY_IS_START("202","活动已开始"), //活动未开始
ACTIVITY_NO_START("203","活动未开始"), //参数错误
ACTIVITY_PARAM_ERROR("204","参数错误"), //页面返回正常
RESULT_CODE_OK("00",""),
//页面返回失败
RESULT_CODE_ERROR("01",""),
//系统繁忙、发送失败
RESULT_STATE_ERROR("0","系统繁忙、发送失败!"),
//请先绑定手机号、请重新登录
RESULT_STATE_ERR("-1","请先绑定手机号、请重新登录!"),
//state正常
RESULT_STATE_OK("1",""); private String status; private String message; ActivityEnum(String status,String message) {
this.status = status;
this.message=message;
} public String getStatus() {
return status;
} public void setStatus(String status) {
this.status = status;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
}
}
三、未捕获异常的处理 :
对于Unchecked Exception而言,由于代码不强制捕获,往往被忽略,如果运行期产生了UncheckedException,而代码中又没有进行相应的捕获和处理,则我们可能不得不面对尴尬的404、500……等服务器内部错误提示页面。
我们需要一个全面而有效的异常处理机制。目前大多数服务器也都支持在Web.xml中通过<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)节点配置特定异常情况的显示页面。
实现方式如下:
修改web.xml文件,增加以下内容:
<!-- 出错页面定义 -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<!-- 可继续增加服务器错误号的处理及对应显示页面 -->
四、比较异常处理方式的优缺点:
Spring MVC集成异常处理3种方式都可以达到统一异常处理的目标。从4种方式的优缺点比较,若只需要简单的集成异常处理,推荐使用SimpleMappingExceptionResolver即可;若需要集成的异常处理能够更具个性化,提供给用户更详细的异常信息,推荐自定义实现HandlerExceptionResolver接口的方式;若不喜欢Spring配置文件或要实现“零配置”,且能接受对原有代码的适当入侵,则建议使用@ExceptionHandler注解方式。
如果异常处理配置在项目后期的话,需要看下项目是否用到过以上方式统一管理异常,否则会出现配置后失效的问题。
spring mvc 全局处理异常的更多相关文章
- Spring MVC全局异常后返回JSON异常数据
问题: 当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发.后台服务与手机端交互是发送JSON数据.如果后台发生异常,会直接返回异常页面,显示异常内 ...
- Spring MVC 全局异常处理&文件上传
Spring MVC 全局异常处理 使用SimpleMappingExceptionResolver实现异常处理 在welcome-servlet.xml进行如下配置: <bean class= ...
- Spring MVC全局异常处理与拦截器校检
在使用Spring MVC进行开发时,总是要对系统异常和用户的异常行为进行处理,以提供给用户友好的提示,也可以提高系统的安全性. 拦截系统响应错误 首先是拦截系统响应错误,这个可以在web.xml中配 ...
- spring MVC中定义异常页面
如果我们在使用Spring MVC的过程中,想自定义异常页面的话,我们可以使用DispatcherServlet来指定异常页面,具体的做法很简单: 下面看我曾经的一个项目的spring配置文件: 1 ...
- spring MVC中的异常统一处理
1.spring MVC中定义了一个标准的异常处理类SimpleMappingExceptionResolver 该类实现了接口HandlerExceptionResolver 2.看下SimpleM ...
- spring mvc实现登录+异常
登录页面login.jsp在webroot下 <body> <form action="user/login" method="post"&g ...
- spring MVC 全局的异常处理
1.使用SimpleMappingExceptionResolver实现异常处理 在Spring的配置文件applicationContext.xml中增加以下内容: <bean class=& ...
- spring mvc 全局异常处理
package com.tool; public class MyException extends Exception{ public String Msg; public String ErrCo ...
- Spring MVC全局异常处理
继承HandlerExceptionResolver接口实现自己的处理方法,如: public class MyHandlerExceptionResolver implements HandlerE ...
随机推荐
- when case group by 的用法集合
1.用那个以前大家都熟悉的例子,要求是依旧下面的表格求每个大洲的人口总和 国家(countrcoungry) 人口(population) 中国 600 美国 100 加拿大 100 英国 200 法 ...
- 漫游kafka实战篇之搭建Kafka开发环境(3)
上篇文章中我们搭建了kafka的服务器,并可以使用Kafka的命令行工具创建topic,发送和接收消息.下面我们来搭建kafka的开发环境. 添加依赖 搭建开发环境需要引入kafka的jar包 ...
- Linux系统下MySQL数据库的备份和恢复
当我们MySQL数据库保存重要数据的时候,备份工作极为重要.本文介绍如何使用mysqldump备份和恢复数据,使用该方法,可以将数据库中的数据备份成一个文本文件,也可将备份好的数据库迁移到另一台的服务 ...
- mysql更改utf8编码方式
方法1: 一.查看数据库编码格式 1 mysql> show variables like 'character_set_database'; 二.查看数据表的编码格式 1 mysql> ...
- MathType二次偏导怎么表示
求导以及求偏导运算在数学中是很重要的一个部分,尤其是在高等数学中,基本都由函数的导数与偏导组成,很多公式定理也是关于这方面的,如果少了这一部分,数学将会黯然失色.因此在文档中涉及到这些内容时,必然会少 ...
- Java线程之CompletionService批处理任务
如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果,怎么办呢? 为此你可以保存与每个任务相关联的Future,然后不断地调用 timeout为零的get,来检验Future是否 ...
- Visual Studio 32位64位的问题和如何编译32位64位工程的问题
Visual Studio自身没有32位和64位的分别,对于某一个特定的版本只有一个版本安装文件(即不存在32位版本的VS2015安装文件和64位版本的VS2015安装文件) 对于自己开发的工程,编译 ...
- Android无线测试之—UiAutomator UiScrollable API介绍五
滑动区域校准常量设置与获取 一.校准概念 校准常量指的是:滑动操作坐标时的偏移量,用来取偏移比例 二.相关API 返回值 API 描述 double getSwipeDeadZonePercentag ...
- mybatis 控制台打印出来的sql 执行结果为空 但是将sql放到mysql执行有数据
mybatis中的sql如下 select airln_Cd airlnCd,city_coordinate_j cityCoordinateJ,city_coordinate_w cityCoord ...
- c++ const(不断跟新)
1.把一个 const 对象的地址赋给一个普通的.非 const 对象的指针也会导致编译时的错误: const double pi = 3.14; double *ptr = π // error: ...