- 拦截器就是动态的实现拦截Action调用的对象.他提供了一种机制可以使开发者可以定义在一个action 执行的前后的执行代码,也可以在一个action执行之前阻止其执行;
- 在AOP中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作;拦截器是AOP的一种实现;
- 很多时候,拦截器都是通过代理的方式来调用的,Struts2也有拦截器.只是其实现相对简单,他是在当请求发送到Struts 2 的DispatcherServlet 时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,组成一个列表,最后调用表中的拦截器;
拦截器与过滤器的区别:
- 拦截器是SpringMVC框架自己的,只有在使用了SpringMVC的框架才可以使用拦截器;
- interceptor 只会拦截控制器(controller)中的方法,如果访问的是资源文件或者页面,interceptor将不会有任何的作用;
- interceptor是基于java反射机制的,而过滤器是基于函数回调的;
- 过滤器依赖一servlet容器,而interceptor则不依赖;
- interceptor 只会对 action 起作用,而过滤器几乎可以对所有的请求发挥作用;
- interceptor可以访问 action 上下文,以及栈的对象,但是过滤器则不能;
- interceptor 可以进行多次的调用,但是过滤器只能在程序启动时过滤一次;
如何自定义一个拦截器:
自定义一个拦截器只需以下三步即可:
- 自定义实现一个 interceptor 接口(或者继承了abstractinterceptor)的类;
- 配置文件,配置拦截器,及拦截的内容;
- 在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
1.自定义实现一个interceptor的接口
package com.zhang.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
/*
interceptor在请求处理的方法之前执行;
如果返回的是true,执行下一个拦截器;
如果返回的是false,就不执行下一个拦截器;
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("========处理前=======");
return true;
}
//在请求处理方法执行之后执行
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("========处理后=======");
}
//在DispatcherServlet执行后处理,做清理工作;
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("========清理=======");
}
}
2.编写配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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">
<context:component-scan base-package="com.zhang.controller"/>
<!--静态资源过滤:Spring不处理静态资源,html,js,css,jpg,....-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<!--配置拦截器interceptors,复数,可以配置多个拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/所请求的当前路径不会拦截器子请求-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--拦截器的bean-->
<bean class="com.zhang.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
3.index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<a href="${pageContext.request.contextPath}/Test1">拦截测试</a>
</form>
</body>
</html>
4.编写Controller类
package com.zhang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class InterceptorController {
@RequestMapping("/Test1")
@ResponseBody
public String Test1() {
System.out.println("控制器中的方法执行了");
return "good";
}
}
5.以上代码编译运行的结果如下图所示:
实例:认证用户登录问题
实现步骤:
- 设置一个登录页面,编写controller访问页面;
- 在登录页面提交表单后,需要在controller类中处理,对用户进行判断,如果是用户名和密码都是正确的,则向session会话中写入用户信息,再返回登录成功;
- 拦截用户请求,对用户是否登录进行判断;如果用户登录成功,就通过,否则返回登录页面;
编写controller类
package com.zhang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user")
public class UseController {
//跳转到登陆页面
@RequestMapping("/tologin")
public String Tologin(){
return "login";
}
//跳转到成功页面
@RequestMapping("/tosuccess")
public String tosuccess(){
return "success";
}
//登录提交
@RequestMapping("/login")
public String login(HttpSession session,String username,String pwd){
//向session记录用户信息
System.out.println("接收前端"+username);
session.setAttribute("user",username);
return "success";
}
//退出登录
@RequestMapping("/logout")
public String logout(HttpSession session){
//session过期
session.invalidate();
return "login";
}
}
编写拦截器:
package com.zhang.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class UseInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果是登录页面就放行
System.out.println("uri"+ request.getRequestURI());
if (request.getRequestURI().contains("login")){
return true;
}
HttpSession session = request.getSession();
//如果用户已经登录也放行
if (session.getAttribute("user")!=null){
return true;
}
//如果用户没有登录调到登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
编写配置文件:
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!--拦截器的bean-->
<bean id="useInterceptor" class="com.zhang.interceptor.UseInterceptor"/>
</mvc:interceptor>
编写登录页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/user/login">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="pwd"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
编写成功页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注销</title>
</head>
<body>
${user}
<a href="${pageContext.request.contextPath}/user/logout">注销</a>
</form>
</body>
</html>
编写前端页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<%--登录--%>
<a href="${pageContext.request.contextPath}/user/tologin">登录</a>
<a href="${pageContext.request.contextPath}/user/tosuccess">成功页面</a>
</body>
</html>
测试:
登录页面
登录成功的页面
以上代码编译运行的过程如下图所示:
测试拦截OK;