spring mvc 异常统一处理方式
springMVC提供的异常处理主要有两种方式:
- 一种是直接实现自己的HandlerExceptionResolver;
- 另一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。
1、实现自己的HandlerExceptionResolver,HandlerExceptionResolver是一个接口,springMVC本身已经对其有了一个自身的实现——DefaultExceptionResolver,该解析器只是对其中的一些比较典型的异常进行了拦截处理。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView; public class ExceptionHandler implements HandlerExceptionResolver { @Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
// TODO Auto-generated method stub
return new ModelAndView("exception");
} }
上述的resolveException的第4个参数表示对哪种类型的异常进行处理,如果想同时对多种异常进行处理,可以把它换成一个异常数组。
定义了这样一个异常处理器之后就要在applicationContext中定义这样一个bean对象,如:
<bean id="exceptionResolver" class="com.tiantian.xxx.web.handler.ExceptionHandler"/>
2、使用@ExceptionHandler进行处理
使用@ExceptionHandler进行处理有一个不好的地方是进行异常处理的方法必须与出错的方法在同一个Controller里面
如:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping; import com.tiantian.blog.web.servlet.MyException; @Controller
public class GlobalController { /**
* 用于处理异常的
* @return
*/
@ExceptionHandler({MyException.class})
public String exception(MyException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return "exception";
} @RequestMapping("test")
public void test() {
throw new MyException("出错了!");
} }
这里在页面上访问test方法的时候就会报错,而拥有该test方法的Controller又拥有一个处理该异常的方法,这个时候处理异常的方法就会被调用
当发生异常的时候,上述两种方式都使用了的时候,第一种方式会将第二种方式覆盖
http://gaojiewyh.iteye.com/blog/1297746
最近使用spring mvc开发一个web系统,发现在controller里发生未捕获异常时不出日志。
分析DispatcherServlet,初始化handlerExceptionResolvers
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize
* further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
// 初始化异常处理支持器
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
} // 进入初始化处理方法,具体内容就不贴了,主要是先到上下文中搜寻我们自己定义的ExceptionResolvers,如果没有自定义的resolvers,从默认配置中读取。
private void initHandlerExceptionResolvers(ApplicationContext context) // 从默认策略中取得默认配置,从DispatcherServlet.properties文件中取得相关的配置策略,但是在spring2.5的mvc jar包中properties文件中没有HandlerExceptionResolver的默认配置,返回一个EmptyList给handlerExceptionResolvers
protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface)
分析DispatcherServlet,分发处理请求
// 从dispatch方法中看到,系统对请求进行具体的逻辑处理部分被catch住了一次exception,然后会使用servlet持有的ExceptionResolver进行处理
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1; // Expose current LocaleResolver and request as LocaleContext.
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable); // Expose current RequestAttributes to current thread.
RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable); if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
} try {
ModelAndView mv = null;
boolean errorView = false; try {
processedRequest = checkMultipart(request); // Determine handler for the current request.
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Apply preHandle methods of registered interceptors.
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
} // Actually invoke the handler.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
} // Apply postHandle methods of registered interceptors.
if (interceptors != null) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
// 这里catch住controller抛出的异常,使用持有的ExceptionResolver处理,当没有配置自己的处理器时,程序会将异常继续往上抛出,最终交给我们的容器处理
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
} // Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" +
getServletName() + "': assuming HandlerAdapter completed request handling");
}
} // Trigger after-completion for successful outcome.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}
// 当没有配置ExceptionResolver时,异常将到达这里,最终抛出
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
} finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
} // Reset thread-bound context.
RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);
LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable); // Clear request attributes.
requestAttributes.requestCompleted();
if (logger.isTraceEnabled()) {
logger.trace("Cleared thread-bound request context: " + request);
}
}
}
http://fancyboy2050.iteye.com/blog/1300037
- 此段代码ZZ from http://tdcq.iteye.com/blog/890957
- <!-- 全局异常配置 start -->
- <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <property name="exceptionMappings">
- <props>
- <prop key="java.lang.Exception">errors/error</prop>
- <prop key="java.lang.Throwable">errors/err</prop>
- </props>
- </property>
- <property name="statusCodes">
- <props>
- <prop key="errors/error">500</prop>
- <prop key="errors/404">404</prop>
- </props>
- </property>
- <!-- 设置日志输出级别,不定义则默认不输出警告等错误日志信息 -->
- <property name="warnLogCategory" value="WARN"></property>
- <!-- 默认错误页面,当找不到上面mappings中指定的异常对应视图时,使用本默认配置 -->
- <property name="defaultErrorView" value="errors/error"></property>
- <!-- 默认HTTP状态码 -->
- <property name="defaultStatusCode" value="500"></property>
- </bean>
- <!-- 全局异常配置 end -->
用spring mvc做了个项目,但是出现异常的情况下居然没有日志输出,然后各种尝试。。。正如上面介绍的:设置日志输出级别,不定义则默认不输出警告等错误日志信息!!【当然,try catch的异常没问题】
敬请留意。
spring mvc 异常统一处理方式的更多相关文章
- 【Java Web开发学习】Spring MVC异常统一处理
[Java Web开发学习]Spring MVC异常统一处理 文采有限,若有错误,欢迎留言指正. 转载:https://www.cnblogs.com/yangchongxing/p/9271900. ...
- Spring MVC异常统一处理(包括普通请求异常以及ajax请求异常)
通常SpringMVC对异常的配置都是返回某个jsp视图给用户,但是通过ajax方式发起请求,即使发生异常,前台也无法获得任何异常提示信息.因此需要对异常进行统一的处理,对于普通请求以及ajax请求的 ...
- Spring MVC异常统一处理的三种方式
Spring 统一异常处理有 3 种方式,分别为: 使用 @ ExceptionHandler 注解 实现 HandlerExceptionResolver 接口 使用 @controlleradvi ...
- spring mvc异常统一处理(ControllerAdvice注解)
首先我的项目是一个为移动端提供的json数据的,当后台报错时如果为移动端返回一个错误页面显得非常不友好,于是通过ControllerAdvice注解返回json数据. 首先创建一个异常处理类: pac ...
- Spring MVC异常统一处理
package com.shzq.common.exception; import java.io.PrintWriter;import java.io.StringWriter;import jav ...
- spring mvc 异常统一处理
摘自: http://gaojiewyh.iteye.com/blog/1297746
- Spring MVC 前后端 Json 方式交互和处理
众所周知,在mvc中,数据是在各个层次之间进行流转是一个不争的事实. 而这种流转,也就会面临一些困境,这些困境,是由于数据在不同世界中的表现形式不同而造成的. 数据在页面上是一个扁平的,不带数据类 ...
- Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法
Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...
- Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志
在使用SimpleMappingExceptionResolver实现统一异常处理后(参考Spring MVC的异常统一处理方法), 发现出现异常时,log4j无法在控制台输出错误日志.因此需要自定义 ...
随机推荐
- ubuntu下搭建cocos2dx编程环境-上
这大半年一直在开发flash游戏,用到的编程语言是actionscript和c++.所以这次公司决定开发手游端的话,C++不是很生疏,这是个好消息.坏消息是由于现在网页游戏还没有上线,所以公司 ...
- WordPress定位当前使用模版
把下面代码插入到wp-includes/template-loader.php,66行 if($_GET[tpl]=='die'){ die($template); } 浏览任意页面,在网址后加上&a ...
- CentOS7修改服务器主机名方法
CentOS7下修改主机名 第一种:hostname 主机名 01.hostname 主机名称 这种方式,只能修改临时的主机名,当重启机器后,主机名称又变回来了. 第二种:hostnamectl se ...
- MVC+EF+Spring.Net代码生成器
最近研究学习了MVC.EF等相关技术,写了一套项目架构.只要更改EF模型,生成数据库并转换T4模版.数据层和业务层就可以自动生成了. 主要用到的技术: 1.EF实体框架. 2.Spring.Net依赖 ...
- struts2与struts1整合,java.lang.InstantiationException, Exception occurred during processing request: null
做了2个action,其中一个运行没有问题,另一个报错,看下面的报错信息,再看了看struts.xml,因为没有给GetBooks这个action配置actionform,所以就导致报null.下面是 ...
- 【Cocosd2d实例教程二】地图编辑器Tiled的安装使用
(转载请注明出处:http://blog.csdn.net/buptgshengod) 我们知道cocos2d是一个基于2d效果的游戏引擎,那么如果制作一个2d手机游戏我们需要创建相应的游戏画面,而c ...
- Uubuntu 14.04 LTS反编译apk
使用apktool反编译apk 1.安装apktool apktool是Google提供的APK编译工具,能够反编译及回编译apk,需要Java环境的支持(在此不再赘述Java的安装与配置,详见< ...
- MySQL工具:管理员必备的10款MySQL工具
MySQL是一个复杂的的系统,需要许多工具来修复,诊断和优化它.幸运的是,对于管理员,MySQL已经吸引了很多软件开发商推出高品质的开源工具来解决MySQL的系统的复杂性,性能和稳定性,其中大部分是免 ...
- 19.allegro过孔设置[原创]
一.根据线宽设置过孔 在规则管理器下 --- --- ---- --- --- 二.设置原点 法1: -- -- 法二: 然后鼠标点选 ---option栏目在哪? --- 三:过孔问题1 当一个过孔 ...
- iTunes获取下载的安装包
打开iTunes, 偏好设置,选择高级,即可找到文件路径