SpringMVC框架的异常处理及拦截器

上一篇:SpringMVC框架的实现文件上传

文章目录

  • 0、测试环境搭建
  • 1、SpringMVC的异常处理
    • 1.1、异常处理的思路
    • 1.2、异常演示
    • 1.3、自定义异常处理步骤
  • 2、SpringMVC的拦截器
    • 2.1、拦截器的作用
    • 2.2、自定义拦截器的步骤
    • 2.3、多个拦截器的执行顺序

0、测试环境搭建

  (1)pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atlantis</groupId>
    <artifactId>exception</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>exception Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- 版本锁定 -->
        <spring.version>5.0.2.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>exception</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

  (2)web.xml

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- 配置过滤器,解决中文乱码的问题 -->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!-- 指定字符集 -->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*
  

  
  
    DispatcherServlet
    org.springframework.web.servlet.DispatcherServlet
    
    
      contextConfigLocation
      classpath:springmvc.xml
    
    
    1
  
  
    DispatcherServlet
    /
  

  (3)springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="com.atlantis"/>

    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 设置静态资源不被拦截 -->
    <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
    <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
    <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->

    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven />
</beans>

1、SpringMVC的异常处理

1.1、异常处理的思路

  系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
  系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图:
SpringMVC框架的异常处理及拦截器_第1张图片

1.2、异常演示

SpringMVC框架的异常处理及拦截器_第2张图片
  可以发现,若不进行异常处理的话,异常信息会直接抛出到页面显示。这对用户而言是很不友好的,我们也不希望这种异常错误的页面被用户看到。因此下面我们来对异常进行处理,设置友好的页面来代替这些异常信息页面。

1.3、自定义异常处理步骤

  (1)编写自定义异常类

/**
 * 自定义异常类
 */
public class SystemException extends Exception {
    private String message; // 提示信息

    public SystemException(String message) {
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

  (2)修改控制器方法中异常捕获

    @RequestMapping(value = "/testException")
    public String testException() throws SystemException {
        try {
            // 模拟异常
            int i = 2/0;
        } catch (Exception e) {
            // 控制台打印异常信息
            e.printStackTrace();
            // 抛出自定义异常信息
            throw new SystemException("除数不能为0");
        }
        return "success";
    }

  (3)编写异常处理器,实现HandlerExceptionResolver接口

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 异常处理器
 */
public class SystemExceptionResolver implements HandlerExceptionResolver {

    /**
     * 处理异常的业务逻辑
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        // 获取异常对象
        SystemException ex = null;
        if(ex instanceof SystemException) {
            e = (SystemException) ex;
        }else {
            e = new SystemException("系统繁忙...");
        }
        ModelAndView mv = new ModelAndView();
        // 存入错误的提示信息
        mv.addObject("message", e.getMessage());
        // 跳转的Jsp页面
        mv.setViewName("error");
        return mv;
    }
}

  (4)在springmvc.xml中配置异常处理器

    <!-- 配置异常处理器 -->
    <bean id="systemExceptionResolver" class="com.atlantis.exception.SystemExceptionResolver"/>

  (5)编写error.jsp错误页面
  可以自己做一个美观的错误提示页面,这里只为演示效果,所以简陋些。

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>error</title>
</head>
<body>
    异常信息:${message}
</body>
</html>

2、SpringMVC的拦截器

2.1、拦截器的作用

  SpringMVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理后处理。用户可以自己定义一些拦截器来实现特定的功能。
  SpringMVC 的拦截器是 AOP 思想的具体应用,要想自定义拦截器, 要求必须实现 HandlerInterceptor 接口。

  什么叫预处理和后处理?当浏览器或客户端的请求被拦截器拦截后,拦截器会先执行放行之前代码(预处理代码),然后把该请求放行给 Controller 或下一个拦截器,直到最后 Controller 响应浏览器或客户端时,又会被拦截器拦截,执行放行之后代码(后处理代码)。
SpringMVC框架的异常处理及拦截器_第3张图片

  谈到拦截器,还要向大家提一个词 —— 拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
  说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来就说说它们的区别:
  过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
  拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
  过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
  拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image,js 等静态资源则不会进行拦截。

2.2、自定义拦截器的步骤

(1)编写自定义拦截器类,实现HandlerInterceptor接口
  preHandle 方法是 controller 方法执行前执行:可以使用 request 或 response 跳转到指定的页面;return true放行,执行下一个拦截器,如果没有拦截器,执行 controller 中的方法。return false不放行,不会执行 controller 中的方法。
  postHandle 方法是在 controller 方法执行后执行,在 jsp 视图执行前:可以使用 request 或者 response 跳转到指定的页面;如果指定了跳转的页面,那么 controller 方法跳转的页面将不会显示。
  afterCompletion 方法是在 jsp 执行后执行:request 或 response 不能再跳转页面。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器类
 */
public class MyInterceptor implements HandlerInterceptor {
    /**
     * 预处理,Controller方法执行前执行。
     * 返回值为false时不放行,不会执行后面任何代码。
     * 返回值为true时放行,执行下一个拦截器,若没有则执行Controller方法。
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor:preHandle()...预处理");
        //request.getRequestDispatcher("WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor:postHandle()...后处理");
    }

    /**
     * success.jsp页面执行后,该方法会被执行
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor:afterCompletion()...最后处理");
    }
}

(2)在springmvc.xml中配置拦截器类

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 要拦截的具体方法 -->
            <mvc:mapping path="/testInterceptor"/>
            <!-- 不要拦截的具体方法 -->
            <!--<mvc:exclude-mapping path=""/>-->
            <!-- 配置拦截器对象 -->
            <bean class="com.atlantis.interceptor.MyInterceptor" />
        </mvc:interceptor>
        
        <!-- 可配置多个拦截器,按顺序执行 -->
    </mvc:interceptors>

2.3、多个拦截器的执行顺序

你可能感兴趣的:(SSM,Spring,SpringMVC)