当前位置:网站首页>验证拦截器的执行流程

验证拦截器的执行流程

2022-08-11 09:13:00 无忧#


活动地址:CSDN21天学习挑战赛

目录

 单个拦截器的执行流程

多个拦截器的执行流程 

 应用案例——用户登录权限验证


 单个拦截器的执行流程

  如果在项目中只定义了一个拦截器,那么该拦截器在程序中的执行流程如图所示。

 1.在eclipse中创建动态web项目,将Spring MVC依赖的包复制到lib目录下,如下图:

 2.在web.xml中配置Spring MVC的前端过滤器和初始化加载配置文件等信息

<?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"
		 id="WebApp_ID" version="4.0">
	<!-- 配置前端控制器 -->
	<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>

 3.在src目录下创建一个controller包,并在包中创建控制器类HelloController类

package 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";
	}
}

 4.在src目录下创建interceptor包,在包内创建拦截器类UserInterceptor类。该类要实现HandlerInterceptor接口,并且在实现方法中需要编写输出语句来输出信息。

package 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 UserInterceptor implements HandlerInterceptor{
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("UserInterceptor...preHandle");
		//对拦截的请求放行处理
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("UserInterceptor...postHandle");
	}
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("UserInterceptor...afterCompletion");
	}
}

 5.在src目录下创建并配置springmvc-config.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: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.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	<!--指定需要扫描的包 -->
	<context:component-scan base-package="controller" />
	<!-- 定义视图解析器 -->
	<bean id="viewResoler"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 设置前缀 -->
		<property name="prefix" value="/" />
		<!-- 设置后缀 -->
		<property name="suffix" value=".jsp" />
	</bean>
	<!-- 配置拦截器 -->
	<mvc:interceptors>
		<!-- 使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求 -->
		 <bean class="interceptor.UserInterceptor" />
	</mvc:interceptors>
</beans>

 6.在webapp目录下创建success.jsp用于显示信息。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>拦截器</title>
</head>
<body>
	ok,执行成功!
</body>
</html>

 7.运行结果:

访问:localhost:8848/chapter14/hello

 控制台消息:

 由此可以看出,程序先执行了preHandle()方法,然后执行了控制器中的hello()方法,最后执行了拦截器类中的postHandle()方法和afterCompletion()方法,和前文描述一致。

多个拦截器的执行流程 

 在大型项目中,通常会定义很多拦截器来实现不同的功能。多个拦截器的执行顺序如图所示。

 

 1.在interceptor包中创建两个拦截器类Interceptor1和Interceptor2类,在这两个类中均实现了HandlerInterceptor接口。

package 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 Interceptor1 implements HandlerInterceptor{
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("UserInterceptor1...preHandle");
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("UserInterceptor1...postHandle");
	}
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("UserInterceptor1...afterCompletion");
	}
}
package 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{
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("UserInterceptor2...preHandle");
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("UserInterceptor2...postHandle");
	}
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("UserInterceptor2...afterCompletion");
	}
}

2.在配置文件springmvc-config.xml文件中配置上面定义的两个拦截器


		<!-- 拦截器1 -->
		<mvc:interceptor>
			<mvc:mapping path="/**" />
			<bean class="interceptor.Interceptor1" />
		</mvc:interceptor>
		<!-- 拦截器2 -->
		<mvc:interceptor>
			<mvc:mapping path="/hello" />
			<bean class="interceptor.Interceptor2" />
		</mvc:interceptor>

 3.运行结果:

访问:localhost:8848/chapter14/hello

 控制台消息:

 可以看出,程序先执行了两个拦截器的preHandle()方法,这两个方法的执行顺序与配置文件中定义的顺序相同;然后执行了控制器的hello()方法,然后执行了拦截器的postHandle()和afterCompletion()方法,且这两个方法的执行顺序与配置文件中所定义的拦截器顺序相反。

 应用案例——用户登录权限验证

 通过拦截器来完成一个用户登录权限验证的案例。该案例的整个执行流程如图所示。

 

 从流程图看出,只有登录后的用户才能访问管理主页,如果没有登录而直接访问主页,则拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息。如果用户名或密码错误,也会在登录页面给出相应的提示信息。当已登录的用户在管理主页中单击“退出”链接时,同样会回到登录页面。

 1.在src目录下创建po包,在包内创建User类

package po;
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;
	}
}

2.在controller包中创建控制器类UserController,并在该类中定义向主页跳转,向登陆页面跳转。执行用户登录等操作的方法

package 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 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("zyy")){
			if(password!=null && password.equals("123456")){
				//用户存在,将用户信息保存到session中,并复位向到主页
				session.setAttribute("user_session", user);
				return "redirect:main";
			}
		}
		//用户不存在将错误信息到model中,并跳转到登陆页面
		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";
	}
}

3.在interceptor包中创建拦截器类LoginInterceptor

package interceptor;
import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import po.User;
public class LoginInterceptor implements HandlerInterceptor{
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		//获取请求的URL
		String url=request.getRequestURI();
		//允许公开访问"/toLogin"
		if(url.indexOf("/toLogin")>=0){
			return true;
		}
		//允许公开访问"/Login"
		if(url.indexOf("/login")>=0){
			return true;
		}
		//获取session
		HttpSession session=request.getSession();
		User user=(User)session.getAttribute("user_session");
		//如果user不为空,表示已经登录
		if(user!=null){
			return true;
		}
		request.setAttribute("msg","请先登录");
		request.getRequestDispatcher("/login.jsp").forward(request, response);
		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 {
	}
}

4.在配置文件中配置自定义的登录拦截器信息

		<mvc:interceptor>
			<!-- 配置拦截器作用的路径 -->
			<mvc:mapping path="/**" />
			<!-- 定义在<mvc:interceptor下面的,表示对匹配路径的请求才进行拦截 -->
			<bean class="interceptor.LoginInterceptor" />
		</mvc:interceptor>

5.在webapp目录下创建管理主页面main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<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>

6.在webapp目录下创建登陆页面login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
	<font style="color:Red;">${msg }</font>
	<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>

7.运行结果

运行localhost:8848/chapter14/main

 输入正确的账号密码(zyy,123456)后会跳转到管理主页面

 如果输入错误,会提醒用户或密码输入错误

项目源码:

链接:https://pan.baidu.com/s/1-J6eiunkWVG7NxqSxRgO4A?pwd=r5za
提取码:r5za

原网站

版权声明
本文为[无忧#]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_52473454/article/details/126275951