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 ...
随机推荐
- @Resource注解完成自动装配
@Resource注解是通过名字来自动装配的.在spring中自动装配的模式如果是通过名字来自动装配那么必须保证bean的名字和pojo 的属性名一直. 下面是详细代码:说明了@Resource注解是 ...
- ios上传图片显示方向错误问题
IOS 上传图片方向显示错误问题 问题描述 在使用苹果手机上传图片的时候,发现传完的图片显示出来方向是错误的,竖着的图片会变成横着显示(少部分安卓手机也存在这个问题) 产生原因 ios 相机加入了方向 ...
- webpack 的第三方库分离并持久化缓存
我们常常需要在浏览器缓存一些稳定的资源,如第三方库等.要达到这个目标,只需要两步: 1.提取出“稳定的资源”: 2.提供稳定的文件hash . 处理后的出的文件就像这样子: app.1w3ad4q4. ...
- vue遇到的坑(一)——数组更新
最近在项目中遇到个问题,数组已经更新了,但是页面中的DOM并没有触发变化.我一直以来的想法就是: 既然vue实现的实时数据双向绑定,那么在model层发生了变化之后为什么就没有在view层更新呢? 在 ...
- HDU2544最短路---(Dijkstra)
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- [bzoj3994][SDOI2015]约数个数和-数论
Brief Description 计算\(\sum_{i\leqslant n}\sum_{j\leqslant m}\sigma_0(ij)\). Algorithm Design 首先证明一个结 ...
- Emmet 也有快速生成文件头的功能
输入下边加粗的缩写,然后Tab,就OK了http://docs.emmet.io/cheat-sheet/ html:4t <!DOCTYPE HTML PUBLIC "-//W3C/ ...
- Linux 查看文件和文件夹大小
当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力. du可以查看文件及文件夹的大小. ...
- 算法题之Climbing Stairs(leetcode 70)
题目: You are climbing a stair case. It takes n steps to reach to the top. Each time you can either cl ...
- 我的一次安装oracle的过程
1.在装oracle之前,先安装.net3.5 2.然后正常安装oracle,一直next 3.装完oracle后,安装plsql dev工具,打开工具,发现没有connect as,是需要进行一些配 ...