ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring MVC学习总结(九):拦截器与异常处理

2021-02-03 19:04:32  阅读:101  来源: 互联网

标签:Exception 拦截器 Spring 视图 MVC 方法 public


一、拦截器

1、拦截器的介绍

Spring MVC 的拦截器(Interceptor)与Java Servlet的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:一种是通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类来定义;另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。本文以第二种方式进行演示。

在HandlerInterceptor有三个方法,其描述如下:

  • preHandle 方法:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。
  • postHandle 方法:该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
  • afterCompletion 方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。

拦截器和过滤器的区别如下表:

 过滤器(Filter)拦截器(Interceptor)
使用范围不同Servlet规范规定的,只能用于Web程序中既可用于Web程序,又可用于Applicaiont、Swing程序中
规范不同Servlet规范的补一份,任何Web工程都可以使用Spring 框架自己的,只有使用了Spring MVC框架的工程才可以使用
使用的资源不同过滤器不行

拦截器是Spring的组件,归Spring管理,配置在Spring文件中,能使用Spring里的任何资源、对象,如:Service对象、数据源、事务管理等

深度不同过滤器只在Servlet前后起作用。拦截器能够深入到方法前后、异常抛出前后等,具有更大的弹性。
拦截的资源不同在url-pattern中配置了/*之后,过滤器会对所有要访问的资源拦截拦截器只拦截访问的控制器方法,如果访问的是jsp、html、css、image、js等,则不会拦截

 

2、单个拦截器的执行流程

在配置文件中如果只定义了一个拦截器,程序将首先执行拦截器类中的 preHandle 方法,如果该方法返回 true,程序将继续执行控制器中处理请求的方法,否则中断执行。如果 preHandle 方法返回 true,并且控制器中处理请求的方法执行后、返回视图前将执行 postHandle 方法,返回视图后才执行 afterCompletion 方法。

(1)配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--  指定Spring MVC配置文件的位置    -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--   字符编码过滤器  -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--  encoding:指定一个具体的字符集  -->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <!-- forceEncoding:处理 response中的字符编码  -->
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>

  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


</web-app>

(2)创建控制器类

@Controller
public class InterceptorController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
        System.out.println("我是testInterceptor方法");
        return "interceptorPage";
    }
}

(3)创建拦截器类

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("我是preHandle方法---在控制器的处理请求方法调用之后,解析视图之前执行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("我是postHandle方法---在控制器的处理请求方法调用之后,解析视图之前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("我是afterCompletion方法---在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");
    }
}

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

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置一个全局拦截器,拦截所有请求 -->
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <!-- 配置不需要拦截作用的路径 -->
<!--            <mvc:exclude-mapping path="" />-->
            <!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
            <bean class="com.yht.example1.interceptor.MyInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

在上述示例代码中,<mvc:interceptors> 元素用于配置一组拦截器,其子元素 <bean> 定义的是全局拦截器,即拦截所有的请求。

<mvc:interceptor> 元素中定义的是指定路径的拦截器,其子元素 <mvc:mapping> 用于配置拦截器作用的路径,该路径在其属性 path 中定义。

如上述示例代码中,path 的属性值“/**”表示拦截所有路径,“/**”表示拦截所有的路径。如果在请求路径中包含不需要拦截的内容,可以通过 <mvc:exclude-mapping> 子元素进行配置。

需要注意的是,<mvc:interceptor> 元素的子元素必须按照 <mvc:mapping.../>、<mvc:exclude-mapping.../>、<bean.../> 的顺序配置。 

(5)创建interceptorPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
视图
<%System.out.println("视图渲染结束。"); %>
</body>
</html>

(6)启动 Tomcat 服务器,然后通过地址“http://localhost:8080/SpringMVCStudy02_war/testInterceptor”测试拦截器。输出结果如下:

3、多个拦截器的执行流程

在 Web 应用中通常需要有多个拦截器同时工作,这时它们的 preHandle 方法将按照配置文件中拦截器的配置顺序执行,而它们的 postHandle 方法和 afterCompletion 方法则按照配置顺序的反序执行。如下图:

(1)创建拦截器类TestInterceptor。

public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("我是preHandle方法---TestInterceptor类");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("我是postHandle方法---TestInterceptor类");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("我是afterCompletion方法---TestInterceptor类");
    }
}

(2)在springmvc.xml中配置TestInterceptor。

<!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <bean class="com.yht.example1.interceptor.MyInterceptor" />
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <bean class="com.yht.example1.interceptor.TestInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

(3)启动 Tomcat 服务器,然后通过地址“http://localhost:8080/SpringMVCStudy02_war/testInterceptor”测试拦截器。输出结果如下:

注意:

在preHandle中如果返回false,则表示不放行,那么此时我们可以通过request.getRequestDispatcher("/WEB-INF/pages/页面名").forward(request,response);跳转至某页面。 

二、异常处理

在 Spring MVC 应用的开发中,不管是对底层数据库操作,还是业务层或控制层操作,都会不可避免地遇到各种可预知的、不可预知的异常需要处理。HandlerExceptionResolver 接口用于解析请求处理过程中所产生的异常。

(1)自定义异常类SystemException。

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)在pages下创建error.jsp。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h4>这是错误页面</h4>
${msg}
</body>
</html>

(3)创建一个 HandlerExceptionResolver 接口的实现类SystemExceptionHandler

public class SystemExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        SystemException systemException = null;
        if(e instanceof  SystemException){
            systemException = (SystemException) e;
        }else{
            e = new SystemException("系统异常");
        }
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        mv.addObject("msg", e.getMessage());
        return mv;
    }
}

(4)创建控制器

@Controller
public class ExceptionController {
    @RequestMapping("/testException")
    public String testException() throws Exception{
        System.out.println("我是testException方法");
        int num = Integer.parseInt("a123");
        return "success";
    }
}

(5)在springmvc.xml中配置SystemExceptionHandler

    <bean class="com.yht.example1.handler.SystemExceptionHandler"></bean>

(6)启动 Tomcat 服务器,然后通过地址“http://localhost:8080/SpringMVCStudy02_war/testException”测试拦截器。界面结果如下:

标签:Exception,拦截器,Spring,视图,MVC,方法,public
来源: https://blog.csdn.net/weixin_47382783/article/details/113615558

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有