0


【SpringMVC】下篇,拦截器(一步到位学会它)

✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。
🍎个人主页:Hhzzy99
🍊个人信条:坚持就是胜利!
💞当前专栏:【Spring】
🥭本文内容:SpringMVC的后半部分内容-拦截器

SpringMVC


文章目录


前言

在上一篇文章中讲完了SpringMVC的大部分知识,此篇文章中主要讲解拦截器。上一篇文章🚩
拦截器的使用是非常普遍的。例如在 OA系统中通过拦截器可以拦截未登录的用户,或者使用它来验证己登录用户是否有相应的操作权限等。

SpringMVC

中提供了拦截器功能,通过配置即可对请求进行拦截处理。


拦截器概述

SpringMVC 中的拦截器 (

Interceptor

)类似于 Servlet 中的过滤器(

Filter

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

拦截器的定义

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

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

实现

HandlerInterceptor

接口的定义方式为例,自定义拦截器类的代码如下所示:

publicclassUserInterceptorimplementsHandlerInterceptor{publicbooleanpreHandle(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler)throwsException{System.out.println("UserInterceptor...preHandle");//对拦截的请求进行放行处理(true为放行,false为不放行)returntrue;}publicvoidpostHandle(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{System.out.println("UserInterceptor...postHandle");}publicvoidafterCompletion(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler,Exception ex)throwsException{System.out.println("UserInterceptor...afterCompletion");}}

从上述代码可以看出,自定义的拦截器类实现了

HandlerInterceptor

接口,并实现了接口中的3 个方法。关于这3个方法的具体描述如下:

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

拦截器的配置

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

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

在上述代码中,

<mvc:interceptors>

元素用于配置一组拦截器,其子元素

<bean>

中定义的是全局拦截器,它会拦截所有的请求;而

<mvc:interceptor>

元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。

<mvc:interceptor>

元素的子元素

<mvc:mapping>

用于配置拦截器作用的路径,该路径在其属性

path 

中定义。如上述代码中

path

的属性值

“/**”

表示拦截所有路径

“/hello”

表示拦截所有以

“hello”

结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过

<mvc:exclude-mapping>

元素进行配置。

拦截器的执行流程

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

单个拦截器的执行流程

如果在项目中只定义了一个拦截器,那么该拦截器在程序中的执行流程如下图所示。从中可以看出,程序首先会执行拦截器类中的

preHandle()

方法,如果该方法的返回值为

true

,则程序就会继续向下执行处理器中的方法,否则将不再向下执行:在业务处理器(即控制器

Controller

类)处理完请求后,会执行

postHandle()

方法,然后通过

DispatcherServlet

向客户端返回响应;在

DispatcherServlet

处理完请求后,才会执行

afterCompletion()

方法。
单个拦截器
简单的案例
web.xml中配置SpringMVC的前端过滤器和初始化加载配置文件等信息。

<?xml version="1.0" encoding="UTF-8"?><web-appxmlns="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

,

@ControllerpublicclassHelloController{@RequestMapping("/hello")publicStringhello(){System.out.println("Hello");return"success";}}

在src下创建com.hzy.interceptor包,并在里面创建拦截器类

UserInterceptor

,该类需要实现

HandlerInterceptor

接口。

publicclassUserInterceptorimplementsHandlerInterceptor{publicbooleanpreHandle(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler)throwsException{System.out.println("UserInterceptor...preHandle");//对拦截的请求进行放行处理(true为放行,false为不放行)returntrue;}publicvoidpostHandle(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{System.out.println("UserInterceptor...postHandle");}publicvoidafterCompletion(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response,Object handler,Exception ex)throwsException{System.out.println("UserInterceptor...afterCompletion");}}

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

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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-scanbase-package="com.hzy.controller"/><!--定义视图解析器--><beanid="internalResourceViewResolve"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--设置前缀--><propertyname="prefix"value="/WEB-INF/jsp/"/><!--设置后缀--><propertyname="suffix"value=".jsp"/></bean><mvc:annotation-driven/><!--配置拦截器--><mvc:interceptors><!--使用bean直接定义在<mvc:interceptor>下面的Interceptor 将拦截所有请求--><beanclass="com.hzy.interceptor.UserInterceptor"/></mvc:interceptors></beans>

在WEB-INF目录下创建一个jsp文件夹,并在里面创建一个页面文件success.jsp,然后在

<body>

里面显示任意信息。发布并启动项目,访问

http://localhost:8080/springMvc_SSM/hello 

(注意你的访问路径可能和我不一样哦)
结果:
在这里插入图片描述
控制台
在这里插入图片描述

多个拦截器的执行流程

在大型项目中,通常会定义很多拦截器来实现不同的功能。多个拦截器的执行顺序如图所示。这里假设有两个拦截器

Interceptor1

Interceptor2

,并且在配置文件中,

Interceptor1

拦截器配置在前。
在这里插入图片描述
从图上可以看出,当有多个拦截器同时工作时,它们的

preHandle()

方法会按照配置文件中拦截器的配置顺序执行,而它们的

postHandle()

方法和

afterCompletion()

方法则会按照配置顺序的反序执行。
下为了验证上述描述,下面就修改上面的代码来演示多个拦截器的执行。
在com.hzy.interceptor包中创建两个拦截器类Interceptor1和Interceptor2。
Interceptor1.java

publicclassInterceptor1implementsHandlerInterceptor{publicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{System.out.println("Interceptor1...preHandle");returntrue;}publicvoidpostHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{System.out.println("Interceptor1...postHandle");}publicvoidafterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throwsException{System.out.println("Interceptor1...afterCompletion");}}

Interceptor2.java

publicclassInterceptor2implementsHandlerInterceptor{publicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{System.out.println("Interceptor2...preHandle");returntrue;}publicvoidpostHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{System.out.println("Interceptor2...postHandle");}publicvoidafterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throwsException{System.out.println("Interceptor2...afterCompletion");}}

springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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-scanbase-package="com.hzy.controller"/><!--定义视图解析器--><beanid="internalResourceViewResolve"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--设置前缀--><propertyname="prefix"value="/WEB-INF/jsp/"/><!--设置后缀--><propertyname="suffix"value=".jsp"/></bean><mvc:annotation-driven/><!--配置拦截器--><mvc:interceptors><!--使用bean直接定义在<mvc:interceptor>下面的Interceptor 将拦截所有请求--><beanclass="com.hzy.interceptor.UserInterceptor"/><!--拦截器1--><mvc:interceptor><!--配置拦截器作用的路径--><mvc:mappingpath="/**"/><!--配置不需要拦截器作用的路径--><!--            <mvc:exclude-mapping path=""/>--><!--定义在<mvc:interceptor>下面,表示对匹配路径的请求才进行拦截--><beanclass="com.hzy.interceptor.Interceptor1"/></mvc:interceptor><!--拦截器2--><mvc:interceptor><mvc:mappingpath="/hello"/><beanclass="com.hzy.interceptor.Interceptor2"/></mvc:interceptor></mvc:interceptors></beans>

上述拦截器的配置代码中,第一个拦截器会作用于所有路径下的请求,而第二个拦截器会作用于

“/hello”

结尾的请求。运行项目得到结果:
页面输出跟前面一样。
控制台输出:
在这里插入图片描述
从图中可以看出,程序先执行了前面两个拦截器类中的

preHandle()

方法,这两个方法的执行顺序与配置文件中定义的顺序相同;然后执行了控制器中类中的

hello()

方法;最后执行了两个拦截器类中的

postHandle()

方法和

afterCompletion()

方法,且这两个方法的执行顺序与配置文件中所定义的拦截器顺序相反。


结语

以上就是今天要讲的内容,主要是对上一篇文章的补充,拦截器的详细讲解,希望大家有所收获。

如果各位大哥大姐对我所写的内容觉得还行的话,希望可以点个关注,点个收藏,您的支持就是我最大的动力,非常感谢您的阅读(❁´◡`❁)

标签: servlet java spring

本文转载自: https://blog.csdn.net/XUHUANGHOST/article/details/128406785
版权归原作者 Hhzzy99 所有, 如有侵权,请联系我们删除。

“【SpringMVC】下篇,拦截器(一步到位学会它)”的评论:

还没有评论