概述
Spring MVC的拦截器(Interceptor)主要用于拦截用户的请求并做相应的处理,通常应用在全选验证,判断用户是否登录等功能上。
在SpringMVC框架中定义一个拦截器需要对拦截器进行定义和配署,定义一个拦截器可以通过两种方式:一种是通过实现HandlerInterceptor接口或继承HandlerInterceptor接口的实现类来定义;另一种是通过实现WebRequestInterceptor接口或继承WebRequestInterceptor接口的实现类来定义。
以实现HandlerInterceptor接口为例:
package springmvcdemo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
// preHandle方法在控制器的处理请求方法执行之前执行
// 返回true表示继续向下执行,返回false表示中断后续操作
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
// postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
// afterCompletion方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行
}
}
实现接口中的3个方法:
- preHandle:preHandle方法在控制器的处理请求方法执行之前执行,返回true表示继续向下执行,返回false表示中断后续操作。
- postHandle:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行
- afterCompletion:afterCompletion方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行
使用拦截器需要在springmvc的配置文件中进行配置
<!--配置拦截器-->
<!--<mvc:interceptor>元素的子元素必须按照如下的顺序进行配置-->
<mvc:interceptors>
<!--配置一个全局拦截器,拦截所有请求-->
<!--子元素<bean>定义的是全局拦截器,即拦截所有请求-->
<bean class="springmvcdemo.interceptor.TestInterceptor"/>
<!--<mvc:interceptor>元素中定义的是指定路径的拦截器,其子元素<mvc:mapping>用于配置拦截器作用的路径,该路径在其属性path中定义-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<!--path的属性值为”/**“表示拦截所有路径-->
<mvc:mapping path="/**" />
<!--如果在请求路径中包含不需要拦截的内容,通过<mvc:exclude-mapping>子元素进行配置-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截-->
<bean class="springmvcdemo.interceptor.FirstInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<!--path的属性值为”/goto“表示拦截所有以”goto“结尾的路径-->
<mvc:mapping path="/goto" />
<!--如果在请求路径中包含不需要拦截的内容,通过<mvc:exclude-mapping>子元素进行配置-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截-->
<bean class="springmvcdemo.interceptor.FirstInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
实例
通过拦截器实现一个用户登录权限验证,只有成功登录的用户才能访问系统的主页面main.jsp,而没有成功登录而直接访问主页面将被拦截器拦截,并转发到登录页面login.jsp。当成功登录的用户在系统主页面单击“退出”超链接时回到登录页面。
创建springmvc项目并按下图创建文件及文件夹:
各文件的代码如下:
StudentController.java
package springmvcdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import springmvcdemo.pojo.Student;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/student")
public class StudentController {
@RequestMapping("/initLogin")
public String initLogin() {
return "login";
}
@RequestMapping("/login")
public String login(Student student, Model model, HttpSession session) {
if ("hello".equals(student.getUsername()) && "world".equals(student.getPassword())) {
// 登录成功将用户信息保存到session对象中
session.setAttribute("student", student);
//重定向到主页面的跳转方法
return "redirect:/student/main";
}
model.addAttribute("errorMsg", "用户名或密码错误!");
return "login";
}
/**
* 跳转到主页面
*/
@RequestMapping("/main")
public String main() {
// 跳转到main.jsp页面
return "main";
}
/**
* 退出登录
*/
@RequestMapping("logout")
public String logout(HttpSession session) {
// 清除session
session.invalidate();
// 并跳转到登录页面
return "login";
}
}
LoginInterceptor.java
package springmvcdemo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
// 获取请求的URL
StringBuffer url = request.getRequestURL();
// login.jsp或登录请求放行,不进行拦截
if (url.indexOf("/student/initLogin") >= 0 || url.indexOf("/student/login") >= 0) {
return true;
}
// 获取session
HttpSession session = request.getSession();
Object student = session.getAttribute("student");
// 如果用户已经登录则放行不进行拦截
if (student != null) {
return true;
}
// 没有登录且不是登录页面则转发到登录页面,并给出错误提示
request.setAttribute("errorMsg", "还没登录,请先登录!");
// 转发到login.jsp
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
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 {
}
}
Student.java
package springmvcdemo.pojo;
public class Student {
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;
}
}
springmvc-servlet.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"
xsi:schemaLocation="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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--使用扫描机制扫描控制器类,控制器类都在controller包及其子包下-->
<context:component-scan base-package="springmvcdemo.controller"/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--配置拦截器的路径-->
<mvc:mapping path="/**"/>
<bean class="springmvcdemo.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!--配置视图解析器-->
<!--配置视图解析器成功后,RegisterController和LoginController控制器类的视图路径仅需提供register和login,视图解析器将会自动添加前缀和后缀-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<%--显示错误提示信息--%>
<span style="color: red">${errorMsg}</span>
<form action="/student/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
main.jsp
<%@ page import="springmvcdemo.pojo.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<%
Student student = (Student)session.getAttribute("student");
%>
当前用户:<%=student.getUsername()%><br>
<a href="/student/logout">退出</a>
</body>
</html>
web.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">
<!--部署DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载Spring MVC的配置文件,配置文件可以放在项目目录的任意位置,使用init-param元素加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--配置文件的位置-->
<param-value>/WEB-INF/config/springmvc-config/springmvc-servlet.xml</param-value>
</init-param>
<!--表示容器在启动时立即加载servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<!--处理所有URL-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--避免中文乱码-->
<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>
</web-app>
index.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>Hello World!</h1>
<a href="/student/initLogin">登录</a>
</body>
</html>
运行效果如下:
点击【登录】超链接跳转到login.jsp页面。
在地址栏输入地址:http://localhost:8080/student/main
由于登录拦截器的拦截,没有登录的用户只能被拦截然后转发到login.jsp。
登录成功的用户为:【用户名:hello;密码:world】
点击【登录】按钮,访问main.jsp页面成功
点击【退出】超链接退出登录,再次转发到login.jsp
如果对完整源码有兴趣。
可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。
注意:在公众号后台回复【CSDN201911161424】可获取本节源码。