Spring MVC拦截器概述、执行流程和应用例子

1 拦截器概述

  Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),主要用于拦截用户请求并作相应的处理。拦截器可以进行全限验证、记录请求信息的日志、判断用户是否登录等。

1.1 拦截器的定义

  1. 通过实现HandlerInterceptor接口,或者继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
  2. 通过实现WebRequestInterceptor接口,或者继承WebRequestInterceptor接口的实现类来定义。

以实现HandlerInterceptor接口方式为例:

1.2 拦截器的配置

  在Spring MVC的配置文件中进行配置:

2 拦截器的执行流程

  在程序运行过程中,拦截器的执行是由顺序的,这个顺序和拦截器的定义顺序有关。

2.1 单个拦截器执行顺序

2.1.1 举个例子

  • springmvc-config.xml中配置拦截器
<!-- 拦截器配置 -->
<mvc:interceptors>
	<bean class="cn.edu.ujn.ch15.interceptor.CustomerInterceptor"></bean>
</mvc:interceptors>
  • HelloController.java
package cn.edu.ujn.ch15.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
	@RequestMapping("/hello")
	public String hello() {
		System.out.println("hello!");
		return "success";
	}

	@RequestMapping("/find")
	public String find() {
		System.out.println("Find!");
		return "success";

	}
}
  • CustomerInterceptor.java
package cn.edu.ujn.ch15.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class CustomerInterceptor implements HandlerInterceptor {

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--preHandle");
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--postHandle");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--afterCompletion");
	}

}

  • 测试结果:

2.2 多个拦截器执行顺序

2.2.1 举个例子

  • springmvc-config.xml中配置拦截器:
	<!-- 拦截器配置 -->
	<mvc:interceptors>
		<bean class="cn.edu.ujn.ch15.interceptor.CustomerInterceptor"></bean>
		<mvc:interceptor>
			<mvc:mapping path="/hello" />
			<bean class="cn.edu.ujn.ch15.interceptor.Interceptor2"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

  • HelloController.java
package cn.edu.ujn.ch15.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
	@RequestMapping("/hello")
	public String hello() {
		System.out.println("hello!");
		return "success";
	}
	@RequestMapping("/find")
	public String find() {
		System.out.println("Find!");
		return "success";
	}
}
  • 拦截器1(CustomerInterceptor.java)
package cn.edu.ujn.ch15.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class CustomerInterceptor implements HandlerInterceptor {

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--preHandle");
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--postHandle");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomerInterceptor--afterCompletion");
	}
}
  • 拦截器2(Interceptor2.java)
package cn.edu.ujn.ch15.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class Interceptor2 implements HandlerInterceptor {
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2--preHandle");
		return true;
	}
	
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2--postHandle");
	}
	
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2--afterCompletion");
	}
}
  • 测试结果

3 应用案例-实现用户登录权限验证

3.1 案例说明

  • 登录验证:只有登录成功后的用户才可以访问系统中的主页面
  • 未登录:拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息
  • 登录未成功:在登录页面给出相应的提示信息
  • 退出登录:系统同样会回到登录页面

3.2 流程图

3.3 实现代码

3.3.1 User.java

package cn.edu.ujn.ch15.model;

public class User {
	private int id;
	private String username;
	private String password;

	public int getId() {
		return id;
	}

	public void setId(int 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 + "]";
	}

}

3.3.2 UserController.java

package cn.edu.ujn.ch15.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 cn.edu.ujn.ch15.model.User;

@Controller
public class UserController {
	// 以GET方式请求
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String toLogin() {
		return "login";
	}

	// 以POST方式请求
	// User接受页面传递来的用户名和密码
	// Model向页面返回错误信息的
	// 登录成功后需要向session中写入User对象
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String login(User user, Model model, HttpSession session) {
		// 用户名为A
		if ("A".equals(user.getUsername())) {
			session.setAttribute("USER_SESSION", user);
			return "redirect:main";
		}
		model.addAttribute("msg", "用户名或密码错误,请重新登录!");
		return "login";
	}

	@RequestMapping("/main")
	public String toMain() {
		return "main";
	}

	// 退出则清空session
	@RequestMapping("/logout")
	public String logout(HttpSession session) {
		// 清空session
		session.invalidate();
		return "redirect:login";
	}
}

3.3.3 LoginInterceptor.java

package cn.edu.ujn.ch15.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;

import cn.edu.ujn.ch15.model.User;

public class LoginInterceptor implements HandlerInterceptor {
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// login这个请求不要拦截,不然没办法登录
		String url = request.getRequestURI();
		// 判断url中是否有“login”
		if (url.indexOf("/login") >= 0)
			return true;
		HttpSession session = request.getSession();
		// 获取User对象
		User user = (User) session.getAttribute("USER_SESSION");
		// 判断user是否为空
		if (user != null)
			return true;
		// 为空就显示提示信息
		request.setAttribute("msg", "被拦截,您还没有登录,不能访问页面!");
		// 转发到login.jsp页面
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		return false;
	}
}

3.3.4 配置拦截器(springmvc-config.xml)

<mvc:interceptor>
	<!-- 所有请求都拦截 -->
	<mvc:mapping path="/**" />
	<bean class="cn.edu.ujn.ch15.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
	

3.3.5 login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<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"/><br />&nbsp;&nbsp;&nbsp;码:
                 <input type="password" name="password"/><br />
		<input type="submit" value="登录" />
	</form>
</body>
</html>

3.3.6 main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>系统主页</title>
</head>
<body>
    当前用户:${USER_SESSION.username}  
    <a href="${pageContext.request.contextPath }/logout">退出</a>  
</body>
</html>

3.4 测试结果

  • 登录不成功,无法访问main.jsp页面
  • 登录成功

声明:
若本人发布的作品涉及版权或存在其他问题,请联系我删除。
谢谢浏览!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC拦截器是一种可插拔的组件,它可以在求到达控制器之前或者返回视图之前对求进行处理。Spring MVC 支持单个拦截器或者多个拦截器,下面分别介绍它们的工作流程。 1. 单个拦截器的工作流程 单个拦截器的工作流程如下: - 当一个求到达 DispatcherServlet 时,DispatcherServlet 会创建一个 HandlerExecutionChain 对象,该对象包含了一个或多个处理器拦截器和一个处理器(即控制器)。 - 在执行处理器之前,DispatcherServlet 会调用拦截器的 preHandle 方法,如果该方法返回 true,则继续执行下一个拦截器或者执行处理器。 - 在执行完处理器之后,DispatcherServlet 会调用拦截器的 postHandle 方法,该方法可以修改 ModelAndView 对象,但不能改变视图。 - 当视图渲染完成后,DispatcherServlet 会调用拦截器的 afterCompletion 方法,该方法可以进行一些资源清理操作。 2. 多个拦截器的工作流程 多个拦截器的工作流程类似于单个拦截器的工作流程,只是多了一些拦截器的调用。 - 当一个求到达 DispatcherServlet 时,DispatcherServlet 会创建一个 HandlerExecutionChain 对象,该对象包含了多个处理器拦截器和一个处理器(即控制器)。 - 在执行处理器之前,DispatcherServlet 会按照拦截器的声明顺序调用每个拦截器的 preHandle 方法,如果有任何一个拦截器的 preHandle 方法返回 false,则停止拦截器执行,并返回错误视图。 - 在执行完处理器之后,DispatcherServlet 会按照拦截器的声明顺序倒序调用每个拦截器的 postHandle 方法,该方法可以修改 ModelAndView 对象,但不能改变视图。 - 当视图渲染完成后,DispatcherServlet 会按照拦截器的声明顺序倒序调用每个拦截器的 afterCompletion 方法,该方法可以进行一些资源清理操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值