拦截器的介绍
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理,可以通过自定义拦截器来实现特定的功能。
过滤器与拦截器的区别:拦截器是AOP思想的具体应用
过滤器:
-
servlet规范中的一部分,任何java web工程都可以使用
-
在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截过滤
拦截器:
-
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
-
拦截器只会拦截访问的控制器方法(Controller层被注解@Controller标注的类), 如果访问的是jsp/html/css/image/js是不会进行拦截的
自定义拦截器
-
SpringMVC实现拦截器必须实现HandleIntercepter接口
-
配置web.xml和Springmvc.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">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置字符编码过滤器-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<!-- /*处理所有请求-->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<?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:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启mvc注解驱动-->
<mvc:annotation-driven>
<!-- 配置json类型编码为UTF-8-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--让Spring MVC不处理静态资源-->
<mvc:default-servlet-handler/>
<!--自动扫描包,让指定包下的注解生效,由SpringIOC容器统一管理 -->
<context:component-scan base-package="com.chenhui.controller"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
- 编写自定义拦截器类
package com.chenhui.controller.config;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Auther Sunshine
* @Date 2021/3/11 21:29
*/
public class MyInterceptor implements HandlerInterceptor {
//在业务处理器处理请求之前被调用
//预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
//返回值:true表示继续流程(如调用下一个拦截器或处理器);
//false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
@Override
//在请求处理的Controller类方法之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("处理前");
return true;
}
//在业务处理器处理请求完成之后,生成视图之前执行
//后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
@Override
//在请求处理方法执行之后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理后");
}
// 在DispatcherServlet完全处理完请求之后被调用,可用于清理资源
//整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finall
//但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("清理");
}
}
- 在springmvc.xml配置文件中配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/下面一个目录的所有路径 , /admin/*/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<!--注册拦截器交给SpringIOC管理-->
<bean class="com.chenhui.controller.config.MyInterceptor" id="myInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- 编写Controller类
@ResponseBody
@RequestMapping("/interceptor")
public String interceptor(){
System.out.println("interceptor方法执行了");
return "ok";
}
- 启动Tomcat测试结果:
测试二:验证用户是否登录才放行(认证用户)
实现步骤:
-
有一个登录页面,需要写一个Controller类访问页面
-
登陆页面有一提交表单的动作。需要在controller中处理。判断用户名密码是否正确。如果正确,向session中写入用户信息,返回登陆成功。
-
拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面 。
-
编写一个登录页面login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="get" action="${pageContext.request.contextPath}/user/login">
用户名: <input type="text" name="username">
密码: <input type="text" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
- 编写一个controller类处理请求
package com.chenhui.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @Auther Sunshine
* @Date 2021/3/11 22:37
*/
@Controller
@RequestMapping("/user")
public class UserController {
//跳转到登陆页面
@RequestMapping("/goLogin")
public String goLogin(HttpSession session){
//如果session存入了userInfo则证明用户已认证,进入主页
if (session.getAttribute("userInfo")!=null){
return "main";
}else {
//否则跳转到登录页
return "login";
}
}
//登录表单提交请求
@RequestMapping("/login")
public String login(String username, String password, HttpSession session){
//向session中存入用户身份信息
session.setAttribute("userInfo",username);
//返回登录成功主页面
return "main";
}
//跳转到登录成功主页面
@RequestMapping("/main")
public String main(){
return "main";
}
//退出登录
@RequestMapping("/goOut")
public String goOut(HttpServletRequest request){
//将用户存入session中的值移除
HttpSession session = request.getSession();
session.removeAttribute("userInfo");
//跳转到登录页面
return "login";
}
}
- 编写一个登录成功页面的主页面main.jsp
<%--
Created by IntelliJ IDEA.
User: LEGION
Date: 2021/3/11
Time: 22:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>首页</h1>
${
userInfo}
<a href="${pageContext.request.contextPath}/user/goOut">注销</a>
</body>
</html>
- 编写用户登录拦截器
package com.chenhui.controller.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Auther Sunshine
* @Date 2021/3/11 22:38
*/
//拦截器需要实现HandlerInterceptor接口
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果请求是/xxxgoLogin则证明去登录页面,不用拦截,放行
if (request.getRequestURI().contains("goLogin")){
return true;
}
//如果请求是提交表单请求时,不用拦截,放行,否则用户信息无法通过后台存储用户的session信息
if (request.getRequestURI().contains("login")){
return true;
}
//如果用户登录成功后,也不拦截,放行
if (request.getSession().getAttribute("userInfo")!=null){
return true;
}
//其他请求用户没有权限,则全部拦截,返回登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
- 在springMVC的配置文件中注册拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--配置拦截请求,如果请求路径为/user/**子路径的所有请求都会被拦截器拦截-->
<mvc:mapping path="/user/**"/>
<!--将自定义拦截器交给SpringIOC容器管理-->
<bean class="com.chenhui.controller.config.UserInterceptor" id="userInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- 启动Tomcat测试
当访问主页面时,没有登录认证则直接跳转到登录页面
当登录成功后进入主页
当注销用户后跳转到登录页面