spring 全局异常处理

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

       Spring3.0中对异常的处理方法一共提供了两种:一种是使用HandlerExceptionResolver接口;一种是在Controller类内部使用@ExceptionHandler注解。使用第一种方式可以实现全局异常控制,并且Spring已经提供了一个默认的实现类SimpleMappingExceptionResolver;使用第二种方式可以在Controller内部实现更个性化的异常处理方式,灵活性更高。一般来说,项目中只需要采用第一种方式就可以了,每个人都自己定义异常的展现方式,太过个性不统一。

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

在配置dispacher-servlet.xml

配置多个异常处理的地方。


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

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

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

这样的配置处理jstl请求jsp没有问题, 如果是jquery的 $.post的方法请求, 那么如果还是返回  error.jsp ,那在  js的success函数里则不能很好地输出显示。

问题又来了:  如果在 handleManagerSecurityException方法的上面打上注解 @ResponeBody 那么这样又只能返回 json格式串的异常处理, 你想同步请求跳到到error.jsp又不行啦!

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


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

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

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


注意看

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

这句和最后一句:  throw ex;

如果你写 respone.getWriter().write("有异常啦");   你也要  new一个空的ModelAndView,上面的代码表明, 如果你 return null;  它就跑出异常  throw ex;    如果没人接收, 则会调用你配置的默认异常处理器 或者中断不做任何输出。


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


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9399028/viewspace-1820428/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/9399028/viewspace-1820428/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架中,可以通过全局异常处理机制来统一处理应用程序中的异常情况,避免异常信息直接暴露给用户,提高用户体验和系统的健壮性。以下是一个简单的示例来说明如何实现全局异常处理。 首先,创建一个自定义的全局异常处理器类,该类需要实现`HandlerExceptionResolver`接口。可以通过继承`AbstractHandlerExceptionResolver`类来简化实现。 ```java import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class GlobalExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 处理异常逻辑 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("error"); // 设置错误页面 modelAndView.addObject("errorMsg", ex.getMessage()); // 将异常信息传递给错误页面 return modelAndView; } } ``` 接下来,需要在Spring配置文件中注册该全局异常处理器: ```xml <bean id="globalExceptionHandler" class="com.example.GlobalExceptionHandler" /> ``` 最后,可以在控制器中抛出异常,在全局异常处理器中进行统一处理: ```java @Controller public class UserController { @RequestMapping("/user/{id}") public String getUser(@PathVariable("id") int id) { // 模拟抛出异常 if (id <= 0) { throw new IllegalArgumentException("Invalid user ID"); } // ... } } ``` 当控制器方法中抛出异常时,全局异常处理器会捕获该异常并执行相应的处理逻辑。在上述示例中,异常会被处理并渲染到名为"error"的错误页面中。 这样,无论在哪个控制器方法中发生异常,都可以通过全局异常处理器进行统一的异常处理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值