1.5(Spring MVC学习笔记) 拦截器(Interceptor)
一、拦截器
1.1拦截器简介
Spring中的拦截器类似Servlet中的过滤器(Filter),主要用于拦截用户请求,
并进行一定的处理操作(如验证权限、记录日志、设置编码方式等)。
1.2拦截器实现
SpringMVC实现拦截器主要通过实现HandlerInterceptor接口,
或者是继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来实现。
HandlerInterceptor接口中有三个方法:
public boolean preHanlder(){...}:该方法在执行控制类方法之前执行,
如果该方法返回值为false后续执行终止(拦截器,处理器,控制类都终止)。
public void postHandler(){...}:该方法在控制类中方法执之后执行。
public void afterCompletion(){...}:该方法最后执行,在视图渲染结束后执行。
例如用户发送一个请求执行控制类中某个方法,首先执行preHanlder方法。
然后判断preHandler方法的返回值为true则继续执行,为false则中止。
接着当控制类中方法执行完后,执行拦截器中的postHandler方法。
接着执行后续的视图解析器,渲染视图,最后执行拦截器中的afterCompletion().
1.3拦截器配置
定义好拦截器类后,在xml文件中配置即可。
配置元素:
<mvc:interceptors>:所有拦截器都配置在该元素下。
子元素为<mvc:interceptors>,一个子元素代表一个拦截器,
可配置多个
<mvc:interceptor>:配置单个拦截器
<mvc:mapping>:指定拦截器需要拦截的路径。
<mvc:exclude-mapping>:指定拦截器不需要拦截的路径。
path属性作用于<mvc:mapping><mvc:exclude-mapping>,
用于指定拦截路径。
<bean>:代表具体拦截器的实现类。
在<mvc:interceptors>中配置<bena>,则该拦截器为全局拦截器会拦截所有请求。
在<mvc:interceptor>元素中配置,为拦截指定的路径。
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置在interceptors中为全局拦截器 -->
<bean class = "com.springmvc.interceptor.CustomInterceptor"/>
<!-- 单个拦截器 -->
<mvc:interceptor>
<!-- 配置拦截内容,拦截所有内容 -->
<mvc:mapping path="/**"/>
<!-- 配置不拦截内容 -->
<mvc:exclude-mapping path=""/>
<!-- 对应的拦截器 -->
<bean class = "xxx.xxx.xxx"/>
</mvc:interceptor>
</mvc:interceptors>
下面看一个拦截器的例子
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_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>SpringMVC</display-name> <!-- 配置前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class >
org.springframework.web.servlet.DispatcherServlet
</servlet-class> <!-- 初始化时加载配置文件,该配置文件是在src目录下创建的。 -->
<!-- <init-param> 该选项不配置,则做会自动寻找WEB-INF下名为springmvc-servlet.xml的文件。-->
<!-- <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>
CustomInterceptor.java(拦截器)
import java.io.PrintStream; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; public class CustomInterceptor implements HandlerInterceptor{
//在HadlerAdapter之前执行(简单的看就是在访问控制类之前执行)
PrintStream out = System.out;
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
out.println("preHandle...");
return true;
} //在控制器方法调用后,视图解析器之前执行。
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
out.println("postHandle...");
} //最后执行,
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
out.println("afterCompletionHandle...");
} }
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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.springmvc.*"></context:component-scan>
<!-- testJson -->
<!-- 配置注解驱动 -->
<mvc:annotation-driven/>
<!-- 指定某些文件不被前端控制器拦截,直接访问静态文件。 -->
<!-- 设置视图处理器及其前缀后缀 -->
<bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value = "/WEB-INF/jsp/"></property>
<property name="suffix" value = ".jsp"></property>
</bean> <!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置在interceptors中为全局拦截器 -->
<bean class = "com.springmvc.interceptor.CustomInterceptor"/>
</mvc:interceptors> </beans>
控制类
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class InterceptorsControl {
@RequestMapping("/testInterceptor")
public String handler() {
System.out.println("handler");
return "success";
}
}
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.springmvc.binderList.*" %>
<!DOCTYPE html> <html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
success <br/> </body>
</html>


1.4多个过滤器
多个过滤器配置与上述类似,只是在<mvc:interceptors>中配置多个<mvc:interceptor>即可。
关键是多个过滤器的执行顺序。

假设有拦截器1~n,
执行顺序为: pre(1) pre(2)....pre(n) post(n) post(n-1)....post(1) after(n)after(n-1)...after(1)
先将上述CustomInterceptor中的所有打印语句中添加一个数字1。
System.out.println("perHadler1")
在将Customlnterceptor.java文件复制,并改名为CustomInterceptor2.java
并将其中数字1改为2.
修改springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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.springmvc.*"></context:component-scan>
<!-- testJson -->
<!-- 配置注解驱动 -->
<mvc:annotation-driven/> <bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value = "/WEB-INF/jsp/"></property>
<property name="suffix" value = ".jsp"></property>
</bean> <!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 拦截器1 -->
<mvc:interceptor>
<mvc:mapping path="/testInterceptor"/>
<bean class = "com.springmvc.interceptor.CustomInterceptor"/>
</mvc:interceptor>
<!-- 拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/testInterceptor"/>
<bean class = "com.springmvc.interceptor.CustomInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors> </beans>

二、拦截器登录注册案例
User.java(POJO类)
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;
}
}
Validate.java(拦截器)
拦截所有请求进行判断,
如果是去往登录页面或是登录验证放行,
如果已登录放行,
其它则跳转到登录页面。
未登录情况下无法任何资源页面,只能访问登录页面
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; public class Validate implements HandlerInterceptor{ @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub } @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub } @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("into interceptor");
String url = request.getRequestURI();
HttpSession session = request.getSession();
//去往登录页面放行 或者是登录验证放行
if(url.indexOf("/login") > 0 || url.indexOf("/checkLogin") > 0)
return true;
//已登录放行
if(session.getAttribute("user") != null)
return true;
//既不是去登录页面,同时未登录则跳转到登录页面,并提升未登录,请登录。
request.setAttribute("msg", "未登录,请登录");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
} }
UserController.java(控制类)
import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class UserController {
//登录验证
@RequestMapping("/checkLogin")
public String checkLogin(User user, Model model, HttpSession session) {
String userName = user.getUserName();
String password = user.getPassword();
//模拟数据查询
if(userName != null && password != null &&
userName.equals("hcf") && password.equals("123456")) {
//登录成功后设置session用于记录登录状态
session.setAttribute("user", user);
return "main";
}
model.addAttribute("msg", "用户名或密码错误或为空!");
return "login";
} //跳转main
@RequestMapping("/main")
public String toMain() {
return "main";
} //跳转登录页面
@RequestMapping("/login")
public String login() {
return "login";
} //注销用户,即销毁session
@RequestMapping("/loginOut")
public String loginOut(HttpSession session) {
session.invalidate();
return "login";
}
}
login.jsp (登录页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
${msg}<br> <!--表达提交后进行登录验证-->
<form action = "${pageContext.request.contextPath}/checkLogin" method = "post">
用户名:<input type = "text" name = "userName"/><br/> <!--name属性的值要和POJO类中属性名相同才可自动填充-->
密 码:<input type = "text" name = "password"/><br/>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>
main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body> weclome:<br>
${sessionScope.user.userName}
<a href = "${pageContext.request.contextPath}/loginOut">注销</a> </body>
</html>
用户请求访问main.jsp,会被拦截,判断是否登录。
如果登录则放行,执行控制类中的跳转主页方法。
如果未登录则设置msg值,并跳转登录页面。
用户访问登录页面直接放行。
登录页面提交表单后也会被拦截,拦截器判断为登录检查放行。
控制类中会对用户名及密码进行检查。
密码正确设置session保持登录状态,并跳转到main.jsp.
密码错误则设置msg值,并跳转到登录页面。

1.5(Spring MVC学习笔记) 拦截器(Interceptor)的更多相关文章
- struts2学习笔记--拦截器(Interceptor)和登录权限验证Demo
理解 Interceptor拦截器类似于我们学过的过滤器,是可以在action执行前后执行的代码.是我们做web开发是经常使用的技术,比如权限控制,日志.我们也可以把多个interceptor连在一起 ...
- Spring MVC 学习 之 - 拦截器
public class GlobalInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletR ...
- Spring MVC中的拦截器Interceptor
谈谈spring中的拦截器 在web开发中,拦截器是经常用到的功能.它可以帮我们验证是否登陆.预先设置数据以及统计方法的执行效率等等.今天就来详细的谈一下spring中的拦截器.spring中拦截器主 ...
- spring MVC 学习(四)---拦截器,视图解析器
1.接口HandlerInterceptor 该接口包含3个方法,分别是preHandle,postHandle,afterCompletion,分别代表着执行前,执行后,执行完成要执行的方法,其中p ...
- Spring MVC 学习笔记一 HelloWorld
Spring MVC 学习笔记一 HelloWorld Spring MVC 的使用可以按照以下步骤进行(使用Eclipse): 加入JAR包 在web.xml中配置DispatcherServlet ...
- Spring MVC 学习笔记1 - First Helloworld by Eclipse【& - java web 开发Tips集锦】
Spring MVC 学习笔记1 - First Helloworld by Eclipse reference:http://www.gontu.org 1. 下载 Spring freamwork ...
- spring mvc中的拦截器小结 .
在spring mvc中,拦截器其实比较简单了,下面简单小结并demo下. preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Control ...
- Spring MVC 学习笔记12 —— SpringMVC+Hibernate开发(1)依赖包搭建
Spring MVC 学习笔记12 -- SpringMVC+Hibernate开发(1)依赖包搭建 用Hibernate帮助建立SpringMVC与数据库之间的联系,通过配置DAO层,Service ...
- Spring MVC 学习笔记11 —— 后端返回json格式数据
Spring MVC 学习笔记11 -- 后端返回json格式数据 我们常常听说json数据,首先,什么是json数据,总结起来,有以下几点: 1. JSON的全称是"JavaScript ...
随机推荐
- Equal Sums (map的基本应用) 多学骚操作
C. Equal Sums time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- HTML5 视频直播
目前视频直播,尤其是移动端的视频直播已经火到不行了,基本上各大互联网公司都有了自己的直播产品,所以对于直播的一些基本知识和主要技术点也要有所了解,本次分享就向大家介绍一下其中的奥秘. 内容大体框架: ...
- 入门级:GitHub和Git超超超详细使用教程!
GitHub和Git入门 考虑到大家以前可能对版本控制工具和Linux命令行工具都不了解,我写了一个简单的博客来让大家学会入门使用方法. GitHub的简单使用 第一步 创建GitHub账号 1. 打 ...
- Python基础(1)_初识Python
一.为什么要编程 解放人力:让机器按照人们事先为其编写好的程序自发地去工作 二.什么是编程语言 编程语言就是程序员与计算机之间沟通的介质:程序员把自己想说的话用编程语言写到文件里,这其实就开发了一个程 ...
- 【BZOJ】1593: [Usaco2008 Feb]Hotel 旅馆
[算法]线段树(经典线段树上二分) [题意]n个房间,m个询问,每次订最前的连续x个的空房间,或退订从x开始y个房间,求每次订的最左房间号. [题解]关键在于找连续x个空房间,经典二分. 线段树标记s ...
- Java环境变量配置以及作用、JDK与JRE区别以及命令行引入jar包
在配置环境变量中: 设置JAVA_HOME: 一是为了方便引用,比如,JDK安装在C:\jdk1.6.0目录里,则设置JAVA_HOME为该目录路径, 那么以后要使用这个路径的时候, 只需输入%JAV ...
- 使用dd命令克隆整个系统
神奇的ghost的原理是什么呢?不就是数据复制吗?Linux下的dd命令不就是最强大的数据复制工具! 既然如此,我为什么要使用g4l这样复杂的工具呢?一条dd命令不就可以帮我实现任意 ...
- vnc无法显示桌面
转载 以下是我的正确配置,解决上述问题,附带说明: 修改后的~/.vnc/xstartup #!/bin/sh # Uncomment the following two lines for n ...
- python基础===文件对象的访问模式,以及计数循环的使用方法
案例一: 一个几M的文本文件,需要每隔100行写到新的文件中. 代码实现如下: with open(r'f:\book.txt','rb') as f1: with open(r'f:\book2.t ...
- 非旋转Treap——普通平衡树
扔板跑…… #include<bits/stdc++.h> #define N 100010 #define mp make_pair using namespace std; typed ...