转载: http://blog.csdn.net/m13321169565/article/details/7641978

http://blog.csdn.net/ethan_fu/article/details/44624171

在使用web开发和API 开发都使用到异常的处理,web 异常后跳到指定的错误页面,那么API或AJAX调用需要返回JSON的错误信息,所以我们需要一个统一的异常处理机制来管理这些异常!

1.定义自己的异常处理类

  1. import java.io.IOException;
  2. import java.lang.reflect.Method;
  3. import java.util.Collections;
  4. import java.util.List;
  5. import java.util.Map;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import org.springframework.core.annotation.AnnotationUtils;
  10. import org.springframework.http.HttpInputMessage;
  11. import org.springframework.http.HttpOutputMessage;
  12. import org.springframework.http.HttpStatus;
  13. import org.springframework.http.MediaType;
  14. import org.springframework.http.converter.HttpMessageConverter;
  15. import org.springframework.http.server.ServletServerHttpRequest;
  16. import org.springframework.http.server.ServletServerHttpResponse;
  17. import org.springframework.util.StringUtils;
  18. import org.springframework.web.bind.annotation.ResponseBody;
  19. import org.springframework.web.bind.annotation.ResponseStatus;
  20. import org.springframework.web.method.HandlerMethod;
  21. import org.springframework.web.servlet.ModelAndView;
  22. import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
  23. /**
  24. * 不必在Controller中对异常进行处理,抛出即可,由此异常解析器统一控制。<br>
  25. * ajax请求(有@ResponseBody的Controller)发生错误,输出JSON。<br>
  26. * 页面请求(无@ResponseBody的Controller)发生错误,输出错误页面。<br>
  27. * 需要与AnnotationMethodHandlerAdapter使用同一个messageConverters<br>
  28. * Controller中需要有专门处理异常的方法。
  29. *
  30. * @author dongjian
  31. *
  32. * */
  33. public class AnnotationHandlerMethodExceptionResolver extends ExceptionHandlerExceptionResolver {
  34. private String defaultErrorView;
  35. public String getDefaultErrorView() {
  36. return defaultErrorView;
  37. }
  38. public void setDefaultErrorView(String defaultErrorView) {
  39. this.defaultErrorView = defaultErrorView;
  40. }
  41. /***
  42. * 异常后跳转到页面
  43. */
  44. protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
  45. if (handlerMethod == null) {
  46. return null;
  47. }
  48. Method method = handlerMethod.getMethod();
  49. if (method == null) {
  50. return null;
  51. }
  52. ModelAndView returnValue = super.doResolveHandlerMethodException(request, response, handlerMethod, exception);
  53. ResponseBody responseBodyAnn = AnnotationUtils.findAnnotation(method, ResponseBody.class);
  54. if (responseBodyAnn != null) {
  55. try {
  56. ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(method, ResponseStatus.class);
  57. if (responseStatusAnn != null) {
  58. HttpStatus responseStatus = responseStatusAnn.value();
  59. String reason = responseStatusAnn.reason();
  60. if (!StringUtils.hasText(reason)) {
  61. response.setStatus(responseStatus.value());
  62. } else {
  63. try {
  64. response.sendError(responseStatus.value(), reason);
  65. } catch (IOException e) { }
  66. }
  67. }
  68. return handleResponseBody(returnValue, request, response);
  69. } catch (Exception e) {
  70. return null;
  71. }
  72. }
  73. if(returnValue.getViewName() == null){
  74. returnValue.setViewName(defaultErrorView);
  75. }
  76. return returnValue;
  77. }
  78. /**
  79. * 异常后 返回json
  80. * @param returnValue
  81. * @param request
  82. * @param response
  83. * @return
  84. * @throws ServletException
  85. * @throws IOException
  86. */
  87. @SuppressWarnings({ "unchecked", "rawtypes" })
  88. private ModelAndView handleResponseBody(ModelAndView returnValue, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  89. Map value = returnValue.getModelMap();
  90. HttpInputMessage inputMessage = new ServletServerHttpRequest(request);
  91. List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
  92. if (acceptedMediaTypes.isEmpty()) {
  93. acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
  94. }
  95. MediaType.sortByQualityValue(acceptedMediaTypes);
  96. HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
  97. Class<?> returnValueType = value.getClass();
  98. List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();
  99. if (messageConverters != null) {
  100. for (MediaType acceptedMediaType : acceptedMediaTypes) {
  101. for (HttpMessageConverter messageConverter : messageConverters) {
  102. if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
  103. messageConverter.write(value, acceptedMediaType, outputMessage);
  104. return new ModelAndView();
  105. }
  106. }
  107. }
  108. }
  109. if (logger.isWarnEnabled()) {
  110. logger.warn("Could not find HttpMessageConverter that supports return type [" + returnValueType + "] and " + acceptedMediaTypes);
  111. }
  112. return null;
  113. }
  114. }

2.在spring MVC 配置中添加如下配置

  1. <!--  ResponseBody 的类型 -->
  2. <bean
  3. id="messageConverters" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
  4. <property name="supportedMediaTypes">
  5. <list>
  6. </value>
  7. </list>
  8. </property>
  9. </bean>
  10. <bean id="handlerAdapter"
  11. class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  12. <property name="cacheSeconds" value="0" />
  13. <property name="messageConverters" ref="messageConverters" />
  14. </bean>
  15. <!-- 设置自定义异常处理 -->
  16. <bean id="handlerExceptionResolver" class="com.chengkun.base.exception.AnnotationHandlerMethodExceptionResolver">
  17. <property name="defaultErrorView" value="error.jsp"/><!-- 错误页面 -->
  18. <property name="messageConverters" ref="messageConverters"/> <!--JSON 处理的messageConverters->
  19. </bean>

3.修改web.xml 禁止自动注册,让其使用我们自定义的类

  1. <servlet>
  2. <servlet-name>spring-mvc</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath:spring/spring-mvc.xml</param-value>
  7. </init-param>
  8. <!-- 取消其自动注册的异常解析器 -->
  9. <init-param>
  10. <param-name>detectAllHandlerExceptionResolvers</param-name>
  11. <param-value>false</param-value>
  12. </init-param>
  13. </load-on-startup>
  14. </servlet>

4.在BaseController 中加入异常控制,所有controller必须继承BaseController

  1. /**
  2. * 异常控制,可以根据不同的异常类型 在此定义不同的错误消息和操作
  3. * */
  4. @ExceptionHandler(Exception.class)
  5. @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
  6. public ModelAndView handleException(Exception ex, HttpServletRequest request) {
  7. ));
  8. }

spring MVC 统一异常处理(webapi和web分开处理)的更多相关文章

  1. Spring MVC 统一异常处理

    Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...

  2. 使用Spring MVC统一异常处理实战

    1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...

  3. 使用Spring MVC统一异常处理实战<转>

    1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...

  4. 使用Spring MVC统一异常处理实战(转载)

    原文地址:http://blog.csdn.net/ufo2910628/article/details/40399539 种方式: (1)使用Spring MVC提供的简单异常处理器SimpleMa ...

  5. Spring MVC统一异常处理

    实际上Spring MVC处理异常有3种方式: (1)一种是在Controller类内部使用@ExceptionHandler使用注解实现异常处理: 可以在Controller内部实现更个性化点异常处 ...

  6. spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)

    spring 封装了非常强大的异常处理机制.本文选取@ControllerAdvice + @ExceptionHandler 这种零配置(全注解),作为异常处理解决方案! @ControllerAd ...

  7. 【转】使用Spring MVC统一异常处理实战

    方法一:使用SimpleMappingExceptionResolver实现异常处理 //在Spring的配置文件applicationContext.xml中增加以下内容: <bean cla ...

  8. 从零开始学 Java - Spring MVC 统一异常处理

    看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或者你已经练功到了孤独求败,等了半辈子 ...

  9. 使用Spring MVC统一异常处理

    http://blog.csdn.net/ufo2910628/article/details/40399539

随机推荐

  1. jqgrid 在表格底部添加自定义按钮

    往往我们需要在jqgrid底部的分页行中添加一些自定义按钮,效果如下: 上图中,三个按钮均是自定义添加上的. 1.要新增自定义按钮在表格底部,仍离不开分页div,需要给jqgrid绑定分页方法 2.由 ...

  2. DM9161 和 STM32F107 和 FreeRTOS 和 LWIP

    1.首先移植 FreeRTOS到  107上 可以正常运行. 可以到群下载移植好的,文件名称:STM32F107VC+FreeRTOS V8.2.3+kfifo(巧夺天工)! 2.第二步 :ST 官方 ...

  3. scala-数组操作

    package com.bigdata import scala.collection.mutable.ArrayBuffer object ArrayO { def main(args: Array ...

  4. 20155320 Exp6 信息搜集与漏洞扫描

    20155320 Exp6 信息搜集与漏洞扫描 [实验后回答问题] (1)哪些组织负责DNS,IP的管理. 全球根服务器均由美国政府授权的ICANN统一管理,负责全球的域名根服务器.DNS和IP地址管 ...

  5. 汇编 REPNE/REPNZ 指令,SCASB 指令

    知识点: REPNE/REPNZ 指令 SCASB 指令 一.SCASB 指令 cmp byte ptr [edi],al //对标志位的影响相当于sub指令 //同时还会修改寄存器EDI的值:如 ...

  6. metasploit-smb扫描获取系统信息

    1.msfconsle 2.use auxiliary/scanner/smb/smb_version 3. msf auxiliary(smb_version) > set RHOSTS 17 ...

  7. idea 开启 tomcat 访问日志记录

    all 为 设置为 查看所有类型的请求 (包括ajax)

  8. 【Android UI设计与开发】第01期:引导界面(一)ViewPager介绍和使用详解

    做Android开发加起来差不多也有一年多的时间了,总是想写点自己在开发中的心得体会与大家一起交流分享.共同进步,刚开始写也不知该如何下手,仔细想了一下,既然是刚开始写,那就从一个软件给人最直观的感受 ...

  9. fastDFS教程Ⅱ-文件服务器迁移

    在实际的项目应用中,由于服务器替换或项目变更难免会存在fastDFS文件服务器迁移的工作.本文重点介绍fastDFS文件系统在不同情况下的文件迁移处理方案. 1.迁移时IP地址不变 通过文件服务器存储 ...

  10. 这可能是最详细的Python文件操作

    删除 # ==================删除==================# 只能删除文件,若为目录则报错# 若文件正在使用,Windows下会直接报错,Linux下会在目录表中删除记录, ...