首页 > Java开发 > spring3.0异常处理进阶

spring3.0异常处理进阶

spring3.0开发不可避免要遇到异常处理,如果只有jsp请求能捕获到异常,是不足够的, 有时候AJAX返回json数据时遇到异常。这时候默认的处理方式不能满足了, 需要自定义的方式支持同步和ajax异步异常处理。

 

或许大家都知道spring3的异常处理方法有:

1   以配置文件的方式进行异常管理

在配置dispacher-servlet.xml

 

[xhtml] view plaincopy

  1. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  2.     <property name="defaultErrorView">
  3.       <value>jsonView</value>
  4.     </property>
  5.    <property name="exceptionMappings">
  6.       <props>
  7.     <prop key="java.lang.Exception">/common/error.jsp</prop>
  8.       </props>
  9.     </property>
  10.   </bean>

 

配置多个异常处理的地方

 

2  以注解的方式配置异常管理

为了方便阅读, 把代码的地方发全一点

 

[java] view plaincopy

  1. @Controller
  2. public class ExceptionHandlerController
  3. {
  4.     private final Logger log = LoggerFactory.getLogger(getClass());
  5.     @ExceptionHandler(ManagerSecurityException.class)
  6.     public ModelAndView handleManagerSecurityException(ManagerSecurityException e,
  7.             HttpServletResponse response)
  8.     throws IOException
  9.     {
  10.         log.info("Manager exception handler " + e.getMessage());
  11.         response.sendError(HttpServletResponse.SC_FORBIDDEN,
  12.             e.getMessage());
  13.          return new ModelAndView("viewName",new HashMap());
  14.     }
  15. }

 

这样的配置处理jstl请求jsp没有问题,

如果是jquery的 $.post的方法请求, 那么如果还是返回   error.jsp  , 那在  js的success函数里则不能很好地输出显示了。

 

问题又来了:  如果在 handleManagerSecurityException方法的上面打上注解 @ResponeBody

那么这样又只能返回 json格式串的异常处理, 你想同步请求跳到到error.jsp又不行啦!

 

解决办法是这样的:定制化异常处理

 

 

[xhtml] view plaincopy

  1. <bean id="exceptionResolver" class="com.wsd.core.web.servlet.handle.CustomSimpleMappingExceptionResolver">
  2.         <property name="defaultErrorView">
  3.             <value>/common/error.jsp</value>
  4.         </property>
  5.     <property name="exceptionMappings">
  6.         <props>
  7.             <prop key="java.lang.Exception">/common/error.jsp</prop>
  8.         </props>
  9.     </property>
  10.     </bean>

 

 

下面我们来看看CustomSimpleMappingExceptionResolver.java是如何做到支持JSP和JSON格式返回的异常错误的

 

 

[java] view plaincopy

  1. @Override
  2. protected ModelAndView doResolveException(HttpServletRequest request,
  3.         HttpServletResponse response,
  4.         Object handler,
  5.         Exception ex) {
  6.     // Expose ModelAndView for chosen error view.
  7.     String viewName = determineViewName(ex, request);
  8.     if (viewName != null) {//JSP格式返回
  9.         if(!(request.getHeader("accept").indexOf("application/json")>-1 || request.getHeader("X-Requested-With").indexOf("XMLHttpRequest")>-1)){//如果不是异步请求
  10.             // Apply HTTP status code for error views, if specified.
  11.             // Only apply it if we're processing a top-level request.
  12.             Integer statusCode = determineStatusCode(request, viewName);
  13.             if (statusCode != null) {
  14.                 applyStatusCodeIfPossible(request, response, statusCode);
  15.                 return getModelAndView(viewName, ex, request);
  16.             }
  17.         }else{//JSON格式返回
  18.             Map<String, Object> model=new HashMap<String, Object>();
  19.             if(this.logger.isDebugEnabled()){
  20.                 model.put("debug", true);
  21.             }//exception
  22.             model.put(ConfigConstants.RESULT, ex.getMessage());
  23.             model.put("failure", true);
  24.             try {
  25.                 response.getWriter().write("有异常啦!");
  26.             } catch (IOException e) {
  27.                 e.printStackTrace();
  28.             }
  29.             return new ModelAndView();
  30.         }
  31.         return null;
  32.     }
  33.     else {
  34.         return null;
  35.     }
  36. }

 

 

这里判断了request.getHeader("accept").indexOf("application/json")是不是异步请求

下面给出同步和异步请求的Header

同步的text/html

=== MimeHeaders ===
host = localhost:8888
user-agent = Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
accept = text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-language = en,zh;q=0.7,en-gb;q=0.3
accept-encoding = gzip,deflate
accept-charset = ISO-8859-1,utf-8;q=0.7,*;q=0.7
keep-alive = 115
connection = keep-alive
cookie = JSESSIONID=BB7441E4B481FF64A5BCC8E6F596C330

 

异步的application/json
=== MimeHeaders ===
host = localhost:8888
user-agent = Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
accept = application/json, text/javascript, */*
accept-language = en,zh;q=0.7,en-gb;q=0.3
accept-encoding = gzip,deflate
accept-charset = ISO-8859-1,utf-8;q=0.7,*;q=0.7
keep-alive = 115
connection = keep-alive
content-type = application/x-www-form-urlencoded
x-requested-with = XMLHttpRequest
referer = http://localhost:8888/auth/auth/dictionary/dictionaryForm.html
cookie = JSESSIONID=A4B59EA87C9B83B71C0D455634746411

 

请注意

try {
response.getWriter().write("有异常啦!");
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();

 

关键就在最后这1句   return new ModelAndView();

为什么不写 return null;   或者  return new ModelAndView('jsonView', model); 呢?

 

因为spring3的源码里这样写着了

 

[java] view plaincopy

  1. protected ModelAndView processHandlerException(HttpServletRequest request,
  2.         HttpServletResponse response,
  3.         Object handler,
  4.         Exception ex) throws Exception {
  5.     // Check registerer HandlerExceptionResolvers...
  6.     ModelAndView exMv = null;
  7.     for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
  8.         exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
  9.         if (exMv != null) {
  10.             break;
  11.         }
  12.     }
  13.     if (exMv != null) {
  14.         if (exMv.isEmpty()) {
  15.             return null;
  16.         }
  17.         if (logger.isDebugEnabled()) {
  18.             logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv,
  19.                     ex);
  20.         }
  21.         WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
  22.         return exMv;
  23.     }
  24.     throw ex;
  25. }

 

 

注意看

if (exMv != null) {
if (exMv.isEmpty()) {
return null;
}

这句和最后一句:  throw ex;

 

如果你写 respone.getWriter().write("有异常啦");   你也要  new一个空的ModelAndView,

上面的代码表明, 如果你 return null;  它就跑出异常  throw ex;    如果没人接收, 则会调用你配置的默认异常处理器

或者中断不做任何输出。

 

好了, 这样可以同时支持同步和AJAX异步请求异常处理了。

 

下面附上截图, 以免误人子弟~

 


本文固定链接: http://www.devba.com/index.php/archives/531.html | 开发吧

报歉!评论已关闭.