SpringMVC一步到位精通 *

作者:Hhzzy99 时间:2023-11-25 01:47:45 

前言

在上一篇文章中讲完了SpringMVC的大部分知识,此篇文章中主要讲解 * 。上一篇文章🚩

* 的使用是非常普遍的。例如在 OA系统中通过 * 可以拦截未登录的用户,或者使用它来验证己登录用户是否有相应的操作权限等。SpringMVC 中提供了 * 功能,通过配置即可对请求进行拦截处理。

* 概述

SpringMVC 中的 * (Interceptor)类似于 Servlet 中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理。例如通过 * 可以进行权限验证、判断用户是否己登录等。

* 的定义

要使用SpringMVC中的 * ,就需要对 * 类进行定义和配置。通常 * 类可以通过两种方式来定义:

  • 一种是通过实现 HandlerInterceptor 接口或者继承 HandlerInterceptor 接口的实现类(如 HandlerInterceptorAdapter)来定义。

  • 另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。

实现HandlerInterceptor接口的定义方式为例,自定义 * 类的代码如下所示:

public class UserInterceptor implements HandlerInterceptor {
   public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
       System.out.println("UserInterceptor...preHandle");
       //对拦截的请求进行放行处理(true为放行,false为不放行)
       return true;
   }
   public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("UserInterceptor...postHandle");
   }
   public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("UserInterceptor...afterCompletion");
   }
}

从上述代码可以看出,自定义的 * 类实现了 HandlerInterceptor 接口,并实现了接口中的3 个方法。关于这3个方法的具体描述如下:

  • preHandle()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true 时,表示继续向下执行; 当其返回值为false 时,会中断后续的所有操作(包括调用下一个 * 和控制器类中的方法执行等)。

  • postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。

  • afterCompletion()方法:该方法在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

* 的配置

要使自定义的 * 类生效,需要在SpringMVC的配置文件中进行配置,配置代码如下:

<!--配置 * -->
   <mvc:interceptors>
       <!--使用bean直接定义在<mvc:interceptor>下面的Interceptor 将拦截所有请求-->
       <bean class="com.hzy.interceptor.UserInterceptor"/>
       <!-- * 1-->
       <mvc:interceptor>
           <!--配置 * 作用的路径-->
           <mvc:mapping path="/**"/>
           <!--配置不需要 * 作用的路径-->
           <mvc:exclude-mapping path=""/>
           <!--定义在<mvc:interceptor>下面,表示对匹配路径的请求才进行拦截-->
           <bean class="com.hzy.interceptor.Interceptor1"/>
       </mvc:interceptor>
       <!-- * 2-->
       <mvc:interceptor>
           <mvc:mapping path="/hello"/>
           <bean class="com.hzy.interceptor.Interceptor2"/>
       </mvc:interceptor>
           ......
   </mvc:interceptors>

在上述代码中, <mvc:interceptors>元素用于配置一组 * ,其子元素<bean>中定义的是全局 * ,它会拦截所有的请求;而<mvc:interceptor>元素中定义的是指定路径的 * ,它会对指定路径下的请求生效。<mvc:interceptor>元素的子元素<mvc:mapping>用于配置 * 作用的路径,该路径在其属性 path 中定义。如上述代码中 path 的属性值 &ldquo;/**&rdquo;表示拦截所有路径, &ldquo;/hello&rdquo;表示拦截所有以&ldquo;hello&rdquo;结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过 <mvc:exclude-mapping>元素进行配置。

* 的执行流程

* 的执行是有一定顺序的,该顺序与配置文件中所定义的 * 的顺序相关。

单个 * 的执行流程

如果在项目中只定义了一个 * ,那么该 * 在程序中的执行流程如下图所示。从中可以看出,程序首先会执行 * 类中的 preHandle()方法,如果该方法的返回值为 true,则程序就会继续向下执行处理器中的方法,否则将不再向下执行:在业务处理器(即控制器Controller 类)处理完请求后,会执行 postHandle()方法,然后通过 DispatcherServlet 向客户端返回响应;在 DispatcherServlet 处理完请求后,才会执行 afterCompletion()方法。

SpringMVC一步到位精通 *

简单的案例

web.xml中配置SpringMVC的前端过滤器和初始化加载配置文件等信息。

<?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_3_1.xsd"
        version="3.1">
   <servlet>
       <!--配置前端过滤器-->
       <servlet-name>spring-mvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--初始化时加载配置文件-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-config.xml</param-value>
       </init-param>
       <!--表示容器在启动时立即加载Servlet-->
       <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
       <servlet-name>spring-mvc</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>
</web-app>

在src下创建com.hzy.controller包,并在里面创建控制器类HelloController,

@Controller
public class HelloController {
   @RequestMapping("/hello")
   public String hello(){
       System.out.println("Hello");
       return "success";
   }
}

在src下创建com.hzy.interceptor包,并在里面创建 * 类UserInterceptor,该类需要实现HandlerInterceptor接口。

public class UserInterceptor implements HandlerInterceptor {
   public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
       System.out.println("UserInterceptor...preHandle");
       //对拦截的请求进行放行处理(true为放行,false为不放行)
       return true;
   }
   public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("UserInterceptor...postHandle");
   }
   public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("UserInterceptor...afterCompletion");
   }
}

在resources目录下创建springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:mvc="http://www.springframework.org/schema/mvc"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      https://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/mvc
      https://www.springframework.org/schema/mvc/spring-mvc.xsd">
   <!--指定需要扫描的包-->
   <context:component-scan base-package="com.hzy.controller"/>
   <!--定义视图解析器-->
   <bean id="internalResourceViewResolve"
         class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <!--设置前缀-->
       <property name="prefix" value="/WEB-INF/jsp/"/>
       <!--设置后缀-->
       <property name="suffix" value=".jsp"/>
   </bean>
   <mvc:annotation-driven/>
   <!--配置 * -->
   <mvc:interceptors>
       <!--使用bean直接定义在<mvc:interceptor>下面的Interceptor 将拦截所有请求-->
       <bean class="com.hzy.interceptor.UserInterceptor"/>
   </mvc:interceptors>
</beans>

在WEB-INF目录下创建一个jsp文件夹,并在里面创建一个页面文件success.jsp,然后在<body>里面显示任意信息。发布并启动项目,访问http://localhost:8080/springMvc_SSM/hello (注意你的访问路径可能和我不一样哦)

结果:

SpringMVC一步到位精通 *

控制台

SpringMVC一步到位精通 *

多个 * 的执行流程

在大型项目中,通常会定义很多 * 来实现不同的功能。多个 * 的执行顺序如图所示。这里假设有两个 * Interceptor1Interceptor2,并且在配置文件中,Interceptor1 * 配置在前。

SpringMVC一步到位精通 *

从图上可以看出,当有多个 * 同时工作时,它们的preHandle()方法会按照配置文件中 * 的配置顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置顺序的反序执行。

下为了验证上述描述,下面就修改上面的代码来演示多个 * 的执行。

在com.hzy.interceptor包中创建两个 * 类Interceptor1和Interceptor2。

Interceptor1.java

public class Interceptor1 implements HandlerInterceptor {
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("Interceptor1...preHandle");
       return true;
   }
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("Interceptor1...postHandle");
   }
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("Interceptor1...afterCompletion");
   }
}

Interceptor2.java

public class Interceptor2 implements HandlerInterceptor {
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("Interceptor2...preHandle");
       return true;
   }
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("Interceptor2...postHandle");
   }
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("Interceptor2...afterCompletion");
   }
}

springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:mvc="http://www.springframework.org/schema/mvc"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      https://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/mvc
      https://www.springframework.org/schema/mvc/spring-mvc.xsd">
   <!--指定需要扫描的包-->
   <context:component-scan base-package="com.hzy.controller"/>
   <!--定义视图解析器-->
   <bean id="internalResourceViewResolve"
         class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <!--设置前缀-->
       <property name="prefix" value="/WEB-INF/jsp/"/>
       <!--设置后缀-->
       <property name="suffix" value=".jsp"/>
   </bean>
   <mvc:annotation-driven/>
   <!--配置 * -->
   <mvc:interceptors>
       <!--使用bean直接定义在<mvc:interceptor>下面的Interceptor 将拦截所有请求-->
       <bean class="com.hzy.interceptor.UserInterceptor"/>
       <!-- * 1-->
       <mvc:interceptor>
           <!--配置 * 作用的路径-->
           <mvc:mapping path="/**"/>
           <!--配置不需要 * 作用的路径-->
<!--            <mvc:exclude-mapping path=""/>-->
           <!--定义在<mvc:interceptor>下面,表示对匹配路径的请求才进行拦截-->
           <bean class="com.hzy.interceptor.Interceptor1"/>
       </mvc:interceptor>
       <!-- * 2-->
       <mvc:interceptor>
           <mvc:mapping path="/hello"/>
           <bean class="com.hzy.interceptor.Interceptor2"/>
       </mvc:interceptor>
   </mvc:interceptors>
</beans>

上述 * 的配置代码中,第一个 * 会作用于所有路径下的请求,而第二个 * 会作用于&ldquo;/hello&rdquo;结尾的请求。运行项目得到结果:

页面输出跟前面一样。

控制台输出:

SpringMVC一步到位精通 *

从图中可以看出,程序先执行了前面两个 * 类中的preHandle()方法,这两个方法的执行顺序与配置文件中定义的顺序相同;然后执行了控制器中类中的hello()方法;最后执行了两个 * 类中的postHandle()方法和afterCompletion()方法,且这两个方法的执行顺序与配置文件中所定义的 * 顺序相反。

来源:https://blog.csdn.net/XUHUANGHOST/article/details/128406785

标签:SpringMVC, , ,Interceptor
0
投稿

猜你喜欢

  • android利用handler实现倒计时功能

    2021-10-19 07:36:59
  • Java 反射机制实例详解

    2023-11-28 03:49:47
  • IDEA的Mybatis Generator驼峰配置问题

    2023-03-24 02:21:32
  • unity实现玻璃效果

    2023-03-17 07:08:28
  • 通过与Java功能上的对比来学习Go语言

    2023-02-18 02:04:53
  • unity实现手游虚拟摇杆

    2021-11-23 07:16:44
  • 使用java实现猜拳小游戏

    2023-11-25 17:30:16
  • 详解Java匿名内部类

    2023-04-30 14:51:28
  • 三道java新手入门面试题,通往自由的道路--多线程

    2023-05-24 23:12:51
  • java项目中的绝对路径和相对路径用法说明

    2023-11-27 22:08:44
  • Android zip文件下载和解压实例

    2023-12-17 01:11:17
  • redisson实现分布式锁原理

    2023-11-29 00:00:00
  • SpringIOC BeanDefinition的加载流程详解

    2023-11-25 18:06:22
  • SpringBoot项目的logback日志配置(包括打印mybatis的sql语句)

    2021-08-24 02:15:22
  • Java spring 通过注解方式创建对象的示例详解

    2023-07-03 01:18:05
  • Android自定义View实现BMI指数条

    2021-08-28 18:12:12
  • Windows下Java环境配置的超详细教程

    2021-12-18 19:19:16
  • C#对二进制数据进行base64编码的方法

    2023-09-02 23:26:12
  • 注解处理器(APT)是什么

    2021-09-29 09:03:30
  • 如何使用Java调用Linux系统命令

    2021-12-24 20:45:31
  • asp之家 软件编程 m.aspxhome.com