Springmvc 异常处理

Springmvc 异常处理

1. 异常分类

系统中异常包括两类:编译期异常和运行时异常

  • 编译期异常:继承java.lang.Exception,通过捕获异常(try-catch)从而获取异常信息
  • 运行时异常:继承java.lang.RuntimeException,通过规范代码开发、测试通过手段减少运行时异常的发生

2. SpringMVC的异常处理机制

系统中的三层架构(dao、service、controller)都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图

Springmvc 异常处理_第1张图片

3. 异常模拟过程

3.1 maven依赖

<dependencies>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-coreartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-beansartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-contextartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-expressionartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aopartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aspectsartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>

    
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>javax.servlet.jspgroupId>
      <artifactId>jsp-apiartifactId>
      <version>2.1version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>jstlartifactId>
      <version>1.2version>
    dependency>

    
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-coreartifactId>
      <version>2.9.5version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.5version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-annotationsartifactId>
      <version>2.9.5version>
    dependency>
dependencies>

3.2 SpringMVC配置

web.xml


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    
    <filter>
        <filter-name>CharacterEncodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>HttpPutFormContentFilterfilter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>HttpPutFormContentFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <servlet>
        <servlet-name>springmvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:springmvc.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>springmvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    <welcome-file-list>
        <welcome-file>/views/index.jspwelcome-file>
    welcome-file-list>
web-app>

springmvc.xml


<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    
    <context:component-scan base-package="com.newcapec"/>

    
    <mvc:annotation-driven/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/views/"/>
        <property name="suffix" value=".jsp"/>
    bean>

    
    <mvc:default-servlet-handler/>
beans>

3.3 自定义异常类

BusinessExeption.java

public class BusinessExeption extends Exception {
     
    public BusinessExeption(){
     
        super("商务异常");
    }
}

CustomException.java

public class CustomException extends Exception  {
     
    public CustomException(){
     
        super("客户异常");
    }
}

3.4 dao

接口

public interface DemoDao {
     
    void insert(String name) throws Exception;
}

实现类

@Repository("demoDao")
public class DemoDaoImpl implements DemoDao {
     
    @Override
    public void insert(String name) throws Exception {
     
        System.out.println("dao执行了..." + name);
        //模拟异常
        if("null".equals(name)){
     
            System.out.println("空指针异常出现...");
            String s = null;
            s.trim();
        }else if("business".equals(name)){
     
            System.out.println("商务异常出现...");
            throw new BusinessExeption();
        }else if("custom".equals(name)){
     
            System.out.println("客户异常出现...");
            throw new CustomException();
        }else{
     
            System.out.println("未出现异常,程序正常...");
        }
    }
}

3.5 service

接口

public interface DemoService {
     
    void add(String name) throws Exception;
}

实现类

@Service("demoService")
public class DemoServiceImpl implements DemoService {
     

    @Autowired
    private DemoDao demoDao;

    @Override
    public void add(String name) throws Exception {
     
        System.out.println("service执行了...");
        demoDao.insert(name);
    }
}

3.6 controller

@Controller
@RequestMapping("/demo")
public class DemoController {
     

    @Autowired
    private DemoService demoService;

    @RequestMapping("/add")
    public String add(String name) throws Exception {
     
        System.out.println("controller执行了...");
        //在controller中调用业务逻辑层
        demoService.add(name);
        return "success";
    }
}

3.7 页面

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center">
        <h1>异常处理h1>
        <form action="demo/add" method="post">
            <p>数据:<input type="text" name="name">p>
            <p><button>提交button>p>
        form>
    div>
body>
html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center;">
        <h1>跳转成功!!!h1>
    div>
body>
html>

4. SpringMVC的异常处理

4.1 自带异常处理器

使用springmvc提供的简单异常处理器SimpleMappingExceptionResolver,在springmvc.xml配置如下:


<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    
    <property name="defaultErrorView" value="error"/>
    
    <property name="exceptionAttribute" value="ex"/>
    
    <property name="exceptionMappings">
        <props>
            
            <prop key="com.newcapec.myexception.BusinessExeption">error_busprop>
            <prop key="com.newcapec.myexception.CustomException">error_custprop>
        props>
    property>
bean>

异常跳转页面如下:

error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center">
        <h1 style="color: red;">系统故障,请联系管理员!h1>
        <p>异常信息:${ex}p>
        <p>自定义信息:${msg}p>
    div>
body>
html>

error_bus.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center;">
        <h1>商务异常出现后的跳转页面h1>
        <p>异常信息:${ex}p>
        <p>自定义信息:${msg}p>
    div>
body>
html>

error_cust.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center;">
        <h1>客户异常出现后的跳转页面h1>
        <p>异常信息:${ex}p>
        <p>自定义信息:${msg}p>
    div>
body>
html>

4.2 自定义异常处理器

实现SpringMVC的异常处理接口HandlerExceptionResolver定义自己的异常处理器,代码如下:

/**
 * 自定义全局异常处理器
 * 1.实现HandlerExceptionResolver接口并实现其中抽象方法
 * 2.将异常处理器对象放入ioc容器中
 */
@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
     
    /**
     * 处理异常的方法
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 处理器对象
     * @param ex 抛出的异常对象
     * @return ModelAndView对象
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                         Object handler, Exception ex) {
     
        ModelAndView mav = new ModelAndView();
        // 根据不同异常向不同的页面跳转
        if(ex instanceof BusinessExeption){
     
            request.setAttribute("msg", "message for business exception");
            mav.setViewName("error_bus");
        }else if(ex instanceof CustomException){
     
            request.setAttribute("msg", "message for custom exception");
            mav.setViewName("error_cust");
        }else {
     
            request.setAttribute("msg", "message for other exception");
            mav.setViewName("error");
        }
        return mav;
    }
}

4.3 注解式异常处理器

4.3.1 局部异常处理

在Controller中使用@ExceptionHandler注解实现异常处理

@Controller
@RequestMapping("/other")
public class OtherController {
     

    @RequestMapping("/add")
    public String add() throws Exception {
     
        System.out.println("其他处理器中的异常...");
        //模拟异常
        Class.forName("abc");
        return "success";
    }

    /**
     * 在Controller中定义一个处理异常的方法
     * 方法的如果是String类型,表示异常跳转的路径视图名
     *
     * @ExceptionHandler
     * 位置:方法
     * 作用:使当前方法可处理异常
     * 属性:value = 当前方法将要处理异常的类型(异常的Class类型)
     *
     * 注意:如果@ExceptionHandler使用在某个Controller,那么它只能处理该Controller抛出的异常
     */
    @ExceptionHandler(Exception.class)
    public String handleException(Model model){
     
        model.addAttribute("msg", "注解式异常处理");
        return "error";
    }
}

注意:进行异常处理的方法必须与抛出异常的方法在同一个Controller里面,不能全局控制异常

4.3.2 全局异常处理

使用@ControllerAdvice + @ExceptionHandler注解实现全局异常处理

/**
 * @ControllerAdvice
 * 位置:类
 * 作用:注解式全局异常处理器
 */
@ControllerAdvice
public class MyControllerAdvice {
     
    @ExceptionHandler(BusinesException.class)
    public String handleBusinesException(Model model){
     
        model.addAttribute("msg", "注解式异常处理的商务异常");
        return "error_bus";
    }
    @ExceptionHandler(CustomException.class)
    public String handleCustomException(Model model){
     
        model.addAttribute("msg", "注解式异常处理的客户异常");
        return "error_cust";
    }

    @ExceptionHandler(Exception.class)
    public String handleException(Model model){
     
        model.addAttribute("msg", "注解式异常处理的其他异常");
        return "error";
    }
}

4.3.3 异步异常处理

在异常处理的方法中,使用@ResponseBody注解响应客户端即可

Controller中的方法:

@ResponseBody
@RequestMapping("/get")
public String get(String id) throws Exception {
     
    System.out.println("处理异步请求的方法执行了...");
    //模拟异常
    int i = Integer.parseInt(id);
    System.out.println("编号:" + i);
    return "success";
}

处理异常的方法:

/**
 * 处理异步请求中出现的异常
 */
@ResponseBody
@ExceptionHandler(value = NumberFormatException.class)
public String handleAsyncException(){
     
    return "error";
}

页面中的异步请求:

<script type="text/javascript" src="js/jquery-3.3.1.min.js">script>
<script type="text/javascript">
    function get() {
      
        $.ajax({
      
            url : "demo/get",
            type : "get",
            data : {
      id : "10"},
            success : function (data) {
      
                alert(data);
            }
        });
    }
script>

<p><a href="javascript:get()">异步请求a>p>

你可能感兴趣的:(springmvc,spring,springmvc,异常处理,java)