【SpringMVC】拦截器运行原理的学习与总结

笔记大纲
  • 拦截器简介
  • 单个拦截器
  • 两个拦截器preHandle()方法测试
  • 小结
  • 图解

拦截器简介

   Spring MVC可使用拦截器对请求进行拦截处理,用户也可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter 适配器类 。

在这里插入图片描述

HandlerInterceptor接口中主要实现的方法:

主要方法说明
preHandle()在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。
如果该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;反之不需要再调用其他的组件去处理请求,则返回false
postHandle ()在业务处理器处理完请求后(没有渲染视图),但是DispatcherServle 向客户端返回响
应前被调用 ,也是对用户请求request进行处理。
afterCompletion ()DispatcherServlet完全处理完请求后被调用(已经渲染了视图) ,可方法中进行一些资源清理的操作。
1.单个拦截器

(1)工程结构

在这里插入图片描述

(2)MyFirstInterceptor拦截器

@Component`注解表明是拦截器组件!

preHandle()方法返回return true;

package com.codinglin.springmvc.interceptors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/*
 * 拦截器案例
 */
@Component
public class MyFirstInterceptor implements HandlerInterceptor {
	/*
	 *  在 DispatcherServlet完全处理完请求后被调用
	 */
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println(this.getClass().getName()+"========测试afterCompletion============");
		
	}
	/*
	 * 在业务处理器处理请求之后被调用
	 */
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println(this.getClass().getName()+"========测试postHandle============");
		
	}
	/*
	 * 在业务处理器处理请求之前被调用
	 */
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// return true;表示请求继续提交     return false;表示请求不再提交
		System.out.println(this.getClass().getName()+"========测试preHandle============");
		return true;
	}
}

(3)TestController处理器

package com.codinglin.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TestController {
	@RequestMapping("test")
	public String test() {
		System.out.println("调用test处理器的方法");
		return "success";
	}

}

(4)测试入口页面index.jsp

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试入口页面</title>
</head>
<body>
	<a href="${pageContext.request.contextPath}/test">拦截器测试器</a>
</body>
</html>

(4)WEB-INF下web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <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>
    <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>
  <filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

(5)类路径下的spring-mvc.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		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-4.0.xsd">
	<!-- 组件扫描 -->
	<context:component-scan base-package="com.codinglin.springmvc"/>
	
	<!-- 视图解析器 -->
	<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
	<!-- 注册拦截器 -->
	<mvc:interceptors>
	<!-- 拦截通过中央调度器过滤所有请求 -->
		<bean id="myFirstInterceptor" 
			class="com.codinglin.springmvc.interceptors.MyFirstInterceptor">
		<!-- <ref bean="myFirstInterceptor"/> -->
		</bean>
	</mvc:interceptors>

</beans>

运行效果:

在这里插入图片描述

注意:如果MyFirstInterceptor没有标记注解,则报错!

在这里插入图片描述

2.多个拦截器

(1)新建MySecondInterceptor拦截器

@Component注解表明是拦截器组件!

preHandle()方法返回return true;

package com.codinglin.springmvc.interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class MySecondInterceptor implements HandlerInterceptor {

	/*
	 *  在 DispatcherServlet完全处理完请求后被调用
	 */
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println(this.getClass().getName()+"========测试afterCompletion02============");
		
	}
	/*
	 * 在业务处理器处理请求之后被调用
	 */
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println(this.getClass().getName()+"========测试postHandle02============");
		
	}
	/*
	 * 在业务处理器处理请求之前被调用
	 */
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// return true;表示请求继续提交     return false;表示请求不再提交
		System.out.println(this.getClass().getName()+"========测试preHandle02============");
		return true;
	}
}

(2)修改类路径下的spring-mvc.xml文件

拦截器注册时先后顺序会影响preHandle()调用的顺序!

	<!-- 注册拦截器 -->
	<mvc:interceptors>
	<!-- 拦截通过中央调度器过滤所有请求 -->
		<bean id="myFirstInterceptor" class="com.codinglin.springmvc.interceptors.MyFirstInterceptor" />	
		<!-- <ref bean="myFirstInterceptor"/> 用注解方式替换-->
		
		<!-- 配置拦截器,指定拦截请求 -->
		<mvc:interceptor>
			<!-- 一定要指定拦截谁 ,注意先后顺序!!!-->
			<mvc:mapping path="/test"/>
			<!-- <mvc:exclude-mapping path=""/> -->
			<bean id="mySecondInterceptor" class="com.codinglin.springmvc.interceptors.MySecondInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

运行效果:

MyFirstInterceptor和MySecondInterceptor类中的preHandle()方法都返回的true

在这里插入图片描述

3.两个拦截器preHandle()方法返回值测试

(1)一个true,一个false
在这里插入图片描述

(2)一个false,一个true

在这里插入图片描述

(3)一个false,一个false
在这里插入图片描述

4.日常小结

多个拦截器的执行顺序及方法的执行情况:

​    (1)多个拦截器的执行顺序 : 根据配置顺序来决定,先配置的先执行;

​    (2)方法的执行情况:

​       ①preHanle: 与拦截器的执行顺序一致

​       ②postHandle: 与拦截器的执行顺序相反

​       ③afterCompletion: 与拦截器的执行顺序相反

preHandle()方法的返回值:

​    (1)返回true代表请求可以正常往后执行

​    (2)返回false,代表请求被拦截住,不能继续往后执行

​       ①如果是第一个拦截器的preHandle返回false,则后续的操作都不执行;

​       ②如果不是第一个拦截器的preHandle返回false, 之前拦截器的preHandle以及afterCompletion都会执行。

5.图解

第一种情况:
在这里插入图片描述
第二种情况:
在这里插入图片描述


 ☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!

☞本人博客:https://coding0110lin.blog.csdn.net/  欢迎转载,一起技术交流吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值