拦截器概述
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器( Filter),它主要用于拦截用户请求并做相应的处理。例如通过拦截器可以进行权限验证、判断用户是否已登录等。
拦截器的定义
要使用 Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义。一种是通过实现 HandlerInterceptor接口,或者继承 HandlerInterceptor接口的实现类(如 HandlerInterceptorAdapter)来定义;另一种是通过实现 WebRequestInterceptor接口,或继承 WebRequestInterceptor接口的实现类来定义。
public class UserInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2)
throws Exception {
return false;
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
ModelAndView arg3) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
Exception arg3) throws Exception {
}
}
从上述代码可以看出,自定义的拦截器类实现了HandlerInterceptor接口,并实现了接口中的三个方法。关于这三个方法的具体描述如下。
preHandle()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。
postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
afterCompletion()方法:该方法在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
拦截器的配置
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求 -->
<bean class="com.ssm.interceptor.UserInterceptor" />
<!-- 拦截器1 -->
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**" />
<!-- 配置不需要拦截器作用的路径 -->
<mvc:exclude-mapping path="" />
<!-- 定义在<mvc:interceptor下面的,表示对匹配路径的请求才进行拦截 -->
<bean class="com.ssm.interceptor.Interceptor1" />
</mvc:interceptor>
<!-- 拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/hello" />
<bean class="com.ssm.interceptor.Interceptor2" />
</mvc:interceptor>
......
</mvc:interceptors>
在上述代码中,mvc:interceptors元素用于配置一组拦截器,其子元素
注意:< mvc: interceptor>中的子元素必须按照上述代码的配置顺序进行编写,即< mvc: mapping…/>→< mvc: exclude-mapping…/>→<bean…/>的顺序,否则文件会报错。
拦截器的执行流程
单个拦截器的执行流程
多个拦截器的执行流程
应用案例:用户登录权限验证
1.导入所需jar包
2.编写配置文件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_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>spring mvc</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置前端控制器 -->
<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-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.实体类User.java
package com.ssm.po;
public class User {
private String username;
private String password;
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 [username=" + username + ", password=" + password + "]";
}
}
3.控制器方法UserController.java
package com.ssm.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.ssm.po.User;
@Controller
public class UserController {
/*
* 向用户登录页面跳转
*/
@RequestMapping(value = "/toLogin", 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("zq")) {
if (password != null && password.equals("123456")) {
session.setAttribute("user_session", 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.invalidate();
return "redirect:toLogin";
}
}
4.过滤器LoginInterceprot.java
package com.ssm.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.ssm.po.User;
@Controller
public class UserController {
/*
* 向用户登录页面跳转
*/
@RequestMapping(value = "/toLogin", 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("zq")) {
if (password != null && password.equals("123456")) {
session.setAttribute("user_session", 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.invalidate();
return "redirect:toLogin";
}
}
5.springmvc配置文件
<?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-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!--指定需要扫描的包 -->
<context:component-scan base-package="com.ssm.controller" />
<!-- 定义视图解析器 -->
<bean id="viewResoler"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 设置前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 设置后缀 -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求 -->
<!-- <bean class="com.ssm.interceptor.UserInterceptor" /> -->
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**" />
<!-- 定义在<mvc:interceptor下面的,表示对匹配路径的请求才进行拦截 -->
<bean class="com.ssm.interceptor.LoginInterceptor" />
</mvc:interceptor>
<!-- 拦截器1 -->
<!-- <mvc:interceptor>
配置拦截器作用的路径
<mvc:mapping path="/**" />
定义在<mvc:interceptor下面的,表示对匹配路径的请求才进行拦截
<bean class="com.ssm.interceptor.Interceptor1" />
</mvc:interceptor> -->
<!-- 拦截器2 -->
<!-- <mvc:interceptor>
<mvc:mapping path="/hello" />
<bean class="com.ssm.interceptor.Interceptor2" />
</mvc:interceptor> -->
</mvc:interceptors>
</beans>
6.前端页面(login.jsp,main.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
${msg}
<form action="${pageContext.request.contextPath}/login" method="post">
登录名:<input type="text" name="username" id="username" /> <br />
密 码:
<input type="password" name="password" id="password" /> <br />
<input type="submit" value="登录" />
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>管理主页</title>
</head>
<body>
${msg}
当前用户信息:${user_session.username}
<a href="${pageContext.request.contextPath}/logout">退出</a>
</body>
</html>
7.运行