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) {
-
- 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 {
-
-
-
- @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
-
- protected void initStrategies(ApplicationContext context) {
- initMultipartResolver(context);
- initLocaleResolver(context);
- initThemeResolver(context);
- initHandlerMappings(context);
- initHandlerAdapters(context);
- initHandlerExceptionResolvers(context);
- initRequestToViewNameTranslator(context);
- initViewResolvers(context);
- }
-
- private void initHandlerExceptionResolvers(ApplicationContext context)
-
- protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface)
分析DispatcherServlet,分发处理请求
- protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
- HttpServletRequest processedRequest = request;
- HandlerExecutionChain mappedHandler = null;
- int interceptorIndex = -1;
-
-
- LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
- LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable);
-
-
- 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);
-
-
- mappedHandler = getHandler(processedRequest, false);
- if (mappedHandler == null || mappedHandler.getHandler() == null) {
- noHandlerFound(processedRequest, response);
- return;
- }
-
-
- HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
- if (interceptors != null) {
- for (int i = 0; i < interceptors.length; i++) {
- HandlerInterceptor interceptor = interceptors;
- if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
- triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
- return;
- }
- interceptorIndex = i;
- }
- }
-
-
- HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
-
-
- if (mv != null && !mv.hasView()) {
- mv.setViewName(getDefaultViewName(request));
- }
-
-
- if (interceptors != null) {
- for (int i = interceptors.length - 1; i >= 0; i--) {
- HandlerInterceptor interceptor = interceptors;
- interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
- }
- }
- }
- catch (ModelAndViewDefiningException ex) {
- logger.debug("ModelAndViewDefiningException encountered", ex);
- mv = ex.getModelAndView();
- }
- catch (Exception ex) {
- Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
- mv = processHandlerException(processedRequest, response, handler, ex);
- errorView = (mv != null);
- }
-
-
- 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");
- }
- }
-
-
- triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
- }
- catch (Exception ex) {
-
- triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
- throw ex;
- }
- catch (Error err) {
- ServletException ex = new NestedServletException("Handler processing failed", err);
-
- triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
- throw ex;
- }
-
- finally {
-
- if (processedRequest != request) {
- cleanupMultipart(processedRequest);
- }
-
-
- RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);
- LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable);
-
-
- requestAttributes.requestCompleted();
- if (logger.isTraceEnabled()) {
- logger.trace("Cleared thread-bound request context: " + request);
- }
- }
- }
http://fancyboy2050.iteye.com/blog/1300037
spring mvc异常设置,
-
- 此段代码ZZ from http:
- <!-- 全局异常配置 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的过程中,想自定义异常页面的话,我们可以使用DispatcherServlet来指定异常页面,具体的做法很简单:
下面看我曾经的一个项目的spring配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?
xml
version="1.0" encoding="UTF-8" ?>
<
context:component-scan
base-package="com.xxx.training.spring.mvc"/>
<
bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
<
bean
id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<
property
name="exceptionMappings">
<
props
>
<
prop
key="java.sql.SQLException">outException</
prop
>
<
prop
key="java.io.IOException">outException</
prop
>
</
props
>
</
property
>
</
bean
>
</
beans
>
|
上面的定义异常处理部分的解释为:只要发生了SQLException或者IOException异常,就会自动跳转到WEB-INF/views/outException.jsp页面。
一般情况下我们的outException.jsp页面的代码为:
1
2
3
4
5
6
7
8
9
10
11
|
<%@ page contentType=
"text/html;charset=UTF-8"
language=
"java"
%>
<html>
<head>
<title>异常处理页面</title>
</head>
<body>
<% Exception ex = (Exception) request.getAttribute(
"Exception"
);%>
<H2>Exception:<%=ex.getMessage()%>
</H2>
</body>
</html>
|
当然你也可以修改样式,这个就看个人喜好了、
另外记得要在web.xml也使用类似下面的方式处理异常哦。:
1
2
3
4
5
6
7
8
9
|
<
error-page
>
<
error-code
>404</
error-code
>
<
location
>/WEB-INF/pages/404.jsp</
location
>
</
error-page
>
<
error-page
>
<
exception-type
>java.lang.Exception</
exception-type
>
<
location
>/WEB-INF/pages/exception.jsp</
location
>
</
error-page
>
|
因为这两个异常处理的维度是不一样的,简单说,spring的resolver是spring内部使用的,而web。xml里的是整个webapp共同使用的。
建议两个都配置上,
因为spring的resolver可以和spring结合的更紧密,可扩展的更多。
|