版本:idea2020.1.1 jdk1.8 maven3.6.3
注:本文章摘自Java EE企业级应用开发教程,黑马程序员/编著,仅用于记录学习笔记,分享学习经历。
Tomcat配置参考:https://mp.csdn.net/editor/html/114296147
一、拦截器(Interceptor)
拦截用户请求并做响应的处理,例如可以进行权限验证,记录请求信息的日志,判断用户是否登录等。
1、定义
(1)通过实现HandlerInterceptor接口或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义
(2)实现WebRequestInterceptor接口或继承WebRequestInterceptor接口的实现类来定义
例:实现HandlerInterceptor接口
public class InterceptorDemo implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
方法名 | 说明 |
---|---|
perHandler() | 在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等) |
postHandle() | 在控制器方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。 |
afterCompletion() | 在整个请求完成,即视图渲染结束之后执行,可以通过此方法实现一些资源清理、记录日志等工作。 |
2、配置
<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求-->
<bean class="com.jc.Interceptro.InterceptorDemo"/>
<!--拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**"/>
<!--配置不需要拦截器作用的路径-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>下面的,表示对匹配路径的请求才进行拦截-->
<bean class="com.jc.Interceptro.InterceptorDemo"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<!--拦截所有以hello结尾的路径-->
<mvc:mapping path="/hello"/>
<bean class="com.jc.Interceptro.InterceptorDemo"/>
</mvc:interceptor>
...
</mvc:interceptors>
二、执行流程
1、单个拦截器
首先执行拦截器中的preHandle()方法,如果返回true,将继续执行,否则终止执行。在控制器Controller类处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应,在DispatcherServlet处理完请求后执行afterCompletion()方法
创建HelloController ——> 创建CustomInterceptor ——> 编辑springmvc-config.xml ——> 创建success.jsp并测试
@Controller
public class HelloController {
//页面跳转
@RequestMapping("/hello")
public String Hello() {
System.out.println("hello!");
return "success";
}
}
public class CustomInterceptor 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");
}
}
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--指定需要扫描的包-->
<context:component-scan base-package="com.jc.controller"/>
<!--定义视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<!--拦截所有请求-->
<bean class="com.jc.Interceptro.CustomInterceptor"/>
</mvc:interceptors>
</beans>
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/12
Time: 上午 10:12
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '' starting page</title>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body>
This is my JSP page. <br>
ok
</body>
</html>
2、多个拦截器
创建Interceptor1 ——> 创建Interceptor2 ——> 修改springmvc-config.xml ——>运行测试
public class Interceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle1");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle1");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion1");
}
}
public class Interceptro2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle2");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle2");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion2");
}
}
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--指定需要扫描的包-->
<context:component-scan base-package="com.jc.controller"/>
<!--定义视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<!--拦截器1-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.jc.Interceptro.Interceptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.jc.Interceptro.Interceptro2"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
三、案例——用户登录权限验证
只有登录后的用户才能访问系统中的主页,没有登录直接访问的拦截器会将请求拦截,并转发到登录页面,同时在登录页面给出提示信息,如果密码错误同样会给出提示信息。点击退出时,会返回到登录页面。
导入maven依赖 ——> 创建User ——> 创建UserController ——> 创建LoginInterceptor ——> 创建springmvc-config.xml ——> 编辑web.xml ——> 创建main.jsp ——> 创建login.jsp ——> 测试
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring dao依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring web依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring test依赖:方便做单元测试和集成测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!--json-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.4</version>
</dependency>
</dependencies>
public class User {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
@Controller
public class UserController {
//向用户登录页面跳转
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String toLogin() {
return "login";
}
//用户登录
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(User user, Model model, HttpSession session) {
//获取用户名和密码
String username = user.getUsername();
String password = user.getPassword();
//模拟从数据库中获取用户名和密码进行判断
if (username != null && username.equals("jiangchao") && password != null && password.equals("1234")) {
//将用户对象添加到session
session.setAttribute("user",user);
//重定向到主页的跳转方法
return "redirect:main";
}
model.addAttribute("msg","用户名或密码错误,请重新登录!");
return "login";
}
//向用户主页面跳转
@RequestMapping(value = "/main")
public String toMain() {
return "main";
}
//退出登录
@RequestMapping(value = "/logout")
public String logout(HttpSession session) {
//清除session
session.invalidate();
//重定向到登录页面的跳转方法
return "redirect:login";
}
}
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//获取请求的URL
String url = httpServletRequest.getRequestURI();
//URL:除了login.jsp是可以公开访问的,其他URL都进行拦截控制
if (url.indexOf("/login")>=0) {
return true;
}
//获取session
HttpSession session = httpServletRequest.getSession();
User user = (User) session.getAttribute("user");
//判断session中是否有用户数据,如果有,则返回true,继续向下执行
if (user != null) {
return true;
}
//不符合条件的给出提示信息,并转发到登录页面
httpServletRequest.setAttribute("msg","您还没有登录,请先登录!");
httpServletRequest.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(httpServletRequest,httpServletResponse);
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--指定需要扫描的包-->
<context:component-scan base-package="com.jc.controller"/>
<!--定义视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<!--拦截器1-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.jc.Interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
<?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_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!--配置编码过滤器-->
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<!--配置前端过滤器-->
<servlet-name>springmvc</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>springmvc</servlet-name>
<!--拦截所有url-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/13
Time: 下午 12:10
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>系统主页</title>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body>
<%@ page isELIgnored="false" %>
当前用户:${user.username}
<a href="${pageContext.request.contextPath }/logout">退出</a>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/13
Time: 下午 12:13
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>用户登录</title>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body>
<%@ page isELIgnored="false" %>
${msg}
<form action="${pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>