Spring MVC 拦截器

拦截器概述

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: interceptor>元素的子元素< mvc:mapping>用于配置拦截器作用的路径,该路径在其属性path中定义。如上述代码中path的属性值“/**”表示拦截所有路径,“/hello”表示拦截所有以“hello”结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过< mvc:exclude-mapping>元素进行配置。
注意:< 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 />
		密&nbsp;&nbsp;&nbsp;&nbsp;码:
           <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.运行





posted @ 2020-06-26 16:21  曾强  阅读(65)  评论(0编辑  收藏