先导Spring的各种基本依赖,这里就不再说明
一、使用@ControllerAdvice和@ExceptionHandler注解的方式
1、自定义的异常类
package com.json.exception; public class BookException extends RuntimeException { public BookException() { } public BookException(String message) { super(message); } public BookException(String message, Throwable cause) { super(message, cause); } public BookException(Throwable cause) { super(cause); } public BookException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
2、通过@ControllerAdvice和@ExceptionHandler来配置异常处理
注意@ControllerAdvice注解一定要在<context:component-scan>中扫描到
package com.json.exception; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.Map; /*@ControllerAdvice会被<context:component-scan>扫描;该类使用@ExceptionHandler注解修饰的方法将 会应用到所有请求处理方法上*/ @ControllerAdvice public class GlobalExceptionHandler { //处理Exception类型异常 @ExceptionHandler(value = Exception.class) public ModelAndView globalErrorHandler(Exception e) throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("ex",e); mv.setViewName("error"); return mv; } //处理OrderException类型异常 @ResponseBody @ExceptionHandler(value = BookException.class) public Object bookErrorHandler(Exception e) throws Exception{ //创建返回对象map并设置属性,其会被@ResponseBody注解转换为json返回 Map<String,Object> map = new HashMap<>(); map.put("code",100); map.put("message",e.getMessage()); map.put("data","请求失败"); return map; } }
3、测试的controller
package com.json.controller; import com.json.exception.BookException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * 测试springmvc的自定义返回异常并返回页面 */ @Controller public class ExceptionController { @RequestMapping("find") public String find(String name){ if (name == null){ throw new NullPointerException("用户名不存在"); } return "success"; } @RequestMapping("delete") public String delete(){ try { int x = 5/0; return "success"; }catch (Exception e){ e.printStackTrace(); throw new BookException("删除图书失败"); //自定义异常处理 } } }
4、定制jsp进行访问测试
exceptionTest.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>springmvc异常处理测试</title> <script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery.js"></script> <script type="text/javascript"> $(function () { $("#delete").click(function () { $.post("${pageContext.request.contextPath}/delete",null, function (data) { //处理异常 if (data.message){ alert("与服务器交互出现异常:"+data.message); } else { //获取服务器响应,处理数据 } } ) }) }) </script> </head> <body> <a href="${pageContext.request.contextPath}/find">全局异常处理后放回错误页面</a> <button id="delete">点击此按钮,得到自定义异常处理(返回json)</button> </body> </html>
error.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>异常页面</title> </head> <body> <h1>异常页面</h1> 异常信息:${requestScope.ex.message} </body> </html>
5、访问exceptionTest.jsp
得到全局异常后的页面:
得到自定义异常后的页面:
二、使用SimpleMappingExceptionResolver实现集成异常处理
1、在SpringMVC的配置文件l中增加SimpleMappingExceptionResolver配置:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 定义默认的异常处理页面,当该异常类型的注册时使用 --> <property name="defaultErrorView" value="error"></property> <!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception --> <property name="exceptionAttribute" value="ex"></property> <!-- 定义需要特殊处理的异常,用全路径类名作为key,异常处理页面名作为值(跳转至页面时会把excepiton带上) --> <property name="exceptionMappings"> <props> <prop key="cn.basttg.core.exception.BookException">book-error</prop> <prop key="cn.basttg.core.exception.UserException">user-error</prop> <!-- 这里还可以继续扩展对不同异常类型的处理 --> </props> </property> </bean>
使用SimpleMappingExceptionResolver进行异常处理,具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。
三、未捕获异常的处理
对于Unchecked Exception而言,由于代码不强制捕获,往往被忽略,如果运行期产生了Unchecked Exception,而代码中又没有进行相应的捕获和处理,则我们可能不得不面对尴尬的404、500……等服务器内部错误提示页面。
我们需要一个全面而有效的异常处理机制。目前大多数服务器也都支持在Web.xml中通过<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)节点配置特定异常情况的显示页面。修改web.xml文件,增加以下内容:
<!-- 出错页面定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page> <!-- 这里可继续增加服务器错误号的处理及对应显示的页面 -->