Javaweb学习笔记(拦截器)

本文介绍了Spring MVC中的拦截器,包括拦截器的定义、配置和执行流程。详细阐述了拦截器如何实现用户登录权限验证,通过实例展示了拦截器的使用方法和配置。同时,解释了单个和多个拦截器的执行顺序,并提供了创建拦截器和配置的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拦截器概述

Spring MVC中的拦截器类似于Servlet中的过滤器,主要用于拦截用户请求并做出相应的处理。

拦截器的定义

通常拦截器类可以通过两种方式来定义,一种是通过实现HandlerInterceptor接口,或者继承HandlerInterceptor接口的实现类;另一种是实现WebRequestInterceptor接口或者WebRequestInterceptor接口的实现类来定义
示例:实现接口HandlerInterceptor

public class CustoomInterceptor implements HandlerInterceptor
	@Override
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwException{
	return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,ModelAndView modeAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
}
}

自定义额拦截器实现了HandlerInterceptor接口,并实现了其中的三各方法
preHandler()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作,返回值是true时,表示继续向下执行;当其返回值为false时会中断后续的所有操作。
postHandle():该方法会在控制器方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图做出进一步的修改
afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行,刻通过此方法实现一些资源清理、记录日志信息的工作

拦截器的配置

拦截器配置代码如下所示:

<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interors>下面Interceptor将拦截所有请求-->
<bean class="com.itheima.interceptor.CustomerInterceptor"/>
<!-拦截器1-->
		<mvc:interceptor>
		<!--配置拦截器作用的路径-->
			<mvc:mapping path="/**"/>
		<!--配置不需要拦截器作用的路径-->
			<mvc:exclude-mapping path=""/>
			<!--定义在<mvc:interceptor>下面的,表示对匹配路径的请求才进行拦截-->
			<bean class="com.itheima.interceptor.Interceptor1"/>
		</mvc:interceptor>
		<!-拦截器2-->
		<mvc:interceptor>
			<mvc:mapping path="/hello"/>
			<bean class="com.itheima.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->的顺序,否则文件会报错。

拦截器的执行流程

单个拦截器的执行流程

拦截器的执行是有一些顺序的,首先会先执行拦截器类中的preHandle()方法,如果返回值为true会向下执行处理器的方法,否则不再向下执行,在业务处理器(即控制器Controller类)处理完所有的请求后,会执行postHandle()方法,然后通过DispatcherServlet向客户端返回响应;在DispatcherServlet处理完请求后,才会执行afterCompletetion()方法。
示例:
(1)在Eclipse中创建一个名为lanjie的Web项目,将SpringMVC所需的包导入
(2)在Web.xml中配置SpringMVC的前端过滤器和初始化加载配置文件等信息
(3)在src目录下创建com.itheima.controller包,创建控制器类

package com.itheima.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目录下创建一个com.itheima.interceptor包,并在包中创建拦截器类

package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class CustomerInterceptor implements HandlerInterceptor{

	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CustomInterceptor...afterCompletion");
	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Customer...postHandle");
	}

	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Customer...preHandle");
		return true;
	}

}

(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"
	xmlns:tx="http://www.springframework.org/schema/tx"
    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
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-mvc.xsd">
    <context:component-scan base-package="com.itheima.controller"/>
   	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!--设置前缀-->
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<!--设置后缀-->
	<property name="suffix" value=".jsp"/>
	</bean>
	<!-- 配置拦截器 -->
	<mvc:interceptors>
		<bean class="com.itheima.interceptor.CustomerInterceptor"/>
	</mvc:interceptors>
</beans>

(6)在WEB-INF中创建一个jsp文件夹,文件夹中创建一个success.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>Insert title here</title>
</head>
<body>
ok
</body>
</html>

(7)启动tomcat,将项目发布到tomcat上。访问地址http://localhost:9090/lanjie/hello
在这里插入图片描述
在这里插入图片描述

多个拦截器的执行流程

当有多个拦截器同时工作时,他们的preHandle()方法会按照配置文件中的拦截器顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置反序执行。
示例:
(1)在com.itheima.interceptor包中创建两个拦截器类Interceptore1和Interceptor2
Interceptore1

package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class Interceptor1 implements HandlerInterceptor{

	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor1...afterCompletion");
	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor1...postHandle");
	}

	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor1...preHandle");
		return true;
	}

}

Interceptor2

package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class Interceptor2 implements HandlerInterceptor{

	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2...afterCompletion");
	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2...postHandle");
	}

	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Interceptor2...preHandle");
		return true;
	}

}

(2)配置文件spring-config.xml中的< mvc:interceptors>中的元素

<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.itheima.interceptor.Interceptor1"/>
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/hello"/>
			<bean class="com.itheima.interceptor.Interceptor2"/>
		</mvc:interceptor>
	</mvc:interceptors>

(3)启动tomcat,访问地址http://localhost:9090/lanjie/hello
在这里插入图片描述
在这里插入图片描述

案例:实现用户登录权限验证

(1)在src目录下创建一个com.itheima.po的包,创建一个User类。

package com.itheima.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)在com.itheima.controller包中创建控制器类UserController,并在类中定义向主页跳转

package com.itheima.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.itheima.po.User;;
@Controller
public class UserController {
	@RequestMapping(value="/login",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("root")&&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:login";
	}
}

(3)创建拦截器类LoginInterceptor

package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
import com.itheima.po.*;
public class LoginInterceptor implements HandlerInterceptor{

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		String url=request.getRequestURI();
		if(url.indexOf("/login")>=0){
			return true;
		}
		HttpSession session=request.getSession();
		User user=(User) session.getAttribute("USER_SESSION");
		if(user!=null){
			return true;
		}
		request.setAttribute("msg", "你还没有登录,请先登录!");
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		return false;
	}

}

(4)在配置文件中配置自定义拦截器信息

<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.itheima.interceptor.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

(5)创建两个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>
	当前用户:${USER_SESSION.username}
	<a href="${pageContext.request.contextPath }/logout">退出</a>
</body>
</html>

login.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>Insert title here</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>

(6)启动tomcat访问地址http://localhost:9090/lanjie/login
在这里插入图片描述
在这里插入图片描述
点击退出后返回登录页面
在这里插入图片描述
输入密码错误后
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值