首页 > 其他分享 >过滤器拦截器,Interceptor+Filter 理解

过滤器拦截器,Interceptor+Filter 理解

时间:2023-08-02 17:55:33浏览次数:46  
标签:filter 拦截器 void request Filter doFilter 过滤器 Interceptor public

在我们springMVC项目中,一个客户端请求到达DispatcherServlet前会依次经过过滤器(Filter)和拦截器(Interceptor),所以有必要了解下过滤器和拦截器分别做了啥以及项目中该如何配置。

  一. Filter package javax.servlet   1. 三个方法 1.1 init(): 初始化参数,在创建Filter调用,当我们需要设置初始化参数可以写到该方法中。 1.2 doFilter(): 拦截到要执行的请求时调用,写我们对请求和响应的处理。如果有多个过滤器,则过滤器链继续调doFilter()方法。 1.3 destroy(): 在销毁Filter时调用。   2. 生命周期     Filter的创建和销毁由web服务器控制。服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次。服务器关闭时,web服务器销毁Filter的实例对象。   3. 作用 Filter和Interceptor都可以用来做权限校验,参数校验,限流等前处理。但一般都放在拦截器里做,过滤器这里我们常用的就是设置字符集编码。   4. 写法 通常有配置文件写法和注解写法,这里只介绍注解写法。 4.1 springboot启动类上加@ServletComponentScan注解   4.2 自定义过滤器,实现Filter,重写doFilter方法 加@WebFilter注解,设置配置,如配置匹配的url(/* 表示所有的请求都需要经过该过滤器) 我举例里定义了两个过滤器,主要为了看下执行顺序
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter doFilter before filter");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("MyFilter doFilter after filter");
}

@Override
public void destroy() {
}
}
 
@WebFilter(urlPatterns = "/*")
public class MyFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter2 doFilter before filter");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("MyFilter2 doFilter after filter");
}

@Override
public void destroy() {

}
}
  这时如果有请求过来,那么执行的顺序为 MyFilter doFilter before filter MyFilter2 doFilter before filter 执行业务逻辑 MyFilter2 doFilter after filter MyFilter doFilter after filter   可以看到doFiliter里有个参数FilterChain,这是设计模式中责任链模式的一种变形使用。首先一个请求有多个多虑器处理对象,这时可以将所有的过滤器都初始化到过滤器链当中,当当前的过滤器执行完业务后,直接丢到责任链当中,由责任链维护接下去的执行流程。   二. 拦截器 包:org.springframework.web.servlet 1. 三个方法
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}

default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}

default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
  preHandle():业务处理前被调用,同过滤器一样,一般用在权限校验,参数校验,限流等预处理 postHandle():在业务处理器处理请求执行完成后,生成视图之前执行 afterCompletion():在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 一般来说,实际业务场景中,我们只需要重写preHandle()方法就够了。   2. 写法 有配置写法和注解写法,这里与时俱进,仅介绍注解写法。
//自定义拦截器,要结合MyWebConfig使用
@Component
public class CookieInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(CookieInterceptor.class);

/**
* 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("CookieInterceptor preHandle");
// String requestURI = request.getRequestURI();
// Cookie[] cookies = request.getCookies();
// //1.如果是登录接口,则设置cookie
// if (requestURI.contains("/loginInfo/login")) {
// response.addCookie(new Cookie("hasLogined", "true"));
// //2.如果不是登录接口,则校验有无cookie
// } else {
// boolean flag = false;
// if (cookies != null) {
// for (Cookie cookie : cookies) {
// if (cookie.getName().equals("hasLogined")) {
// flag = true;
// break;
// }
// }
// }
// if (!flag) {
// LOGGER.error("please login first");
// return false;
// }
// }
return true;
}

/**
* 在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ;
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView)
{
System.out.println("MyInterceptor postHandle.");
}

/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
{
System.out.println("MyInterceptor afterCompletion.");
}
}
@Component
public class SessionInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SessionInterceptor.class);

private Set<String> sessionIds = Sets.newHashSet();
/**
* 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SessionInterceptor preHandle");
// String requestURI = request.getRequestURI();
// //1.如果是登录接口,则设置session
// if (requestURI.contains("/loginInfo/login")) {
// // 用户登陆时如果携带了sessionid,则先将session做invalid处理
// HttpSession session = request.getSession(false);
// if (null != session) {
// session.invalidate();
// }
// // ture,则如果获取不到session,会生成一个;因为上面已失效,所以这里会新生成一个
// session = request.getSession(true);
// String sessionId = session.getId();
// System.out.println("preHandle sessionId=" + sessionId);
// //可以将sessionID存到数据库,redis,内存中;分布式场景中一般会存到redis;此处存在内存中
// sessionIds.add(sessionId);
//
// //额外业务
// InfoVO infoVO = new InfoVO();
// infoVO.setName("libai");
// session.setAttribute("myKey",infoVO);
// } else {
// String sessionId = request.getSession().getId();
// System.out.println("request sessionId = " + sessionId);
//
// if (!sessionIds.contains(sessionId)) {
// LOGGER.error("please login first");
// return false;
// }
//
// //额外业务
// HttpSession session = request.getSession();
// InfoVO myKey =(InfoVO) session.getAttribute("myKey");
// System.out.println(myKey);
// }
return true;
}

/**
* 在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ;
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView)
{
System.out.println("MyInterceptor2 postHandle.");
}

/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
{
System.out.println("MyInterceptor2 afterCompletion.");
}
}
@Configuration
public class MyWebConfig implements WebMvcConfigurer {

@Autowired
private CookieInterceptor cookieInterceptor;

@Autowired
private SessionInterceptor sessionInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(cookieInterceptor)
.addPathPatterns("/**/loginInfo/**")
.order(1);

registry.addInterceptor(sessionInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/loginInfo/**", "/RM/Login")
.order(2);
}
}
这时有匹配的请求过来的,执行顺序如下 MyFilter doFilter before filter MyFilter2 doFilter before filter CookieInterceptor preHandle SessionInterceptor preHandle 执行业务逻辑 MyFilter2 doFilter after filter MyFilter doFilter after filter   order越小越靠前   三. 总结 两者的包不同,filter属于servlet,interceptor属于MVC框架 执行顺序过滤器在前,拦截器在后 过滤器能做的,拦截器也能做,并且更加灵活,比如可以在业务执行前,执行后处理。一般的预处理会选择在拦截器里执行

标签:filter,拦截器,void,request,Filter,doFilter,过滤器,Interceptor,public
From: https://www.cnblogs.com/zeenzhou/p/17601379.html

相关文章

  • ActionFilterAttribute执行了2次问题
    问题描述:最近搭建了一个.NETCoreWebApi,用ActionFilterAttribute来处理token和权限问题,结果每次调用接口都执行2次OnActionExecuting或者OnActionExecutionAsync。问题分析:网络上有说是和浏览器有关系,说谷歌浏览器的jsonview的问题啥的,经过测试并没有关系。最后仔细分析了一下......
  • netfilter中,有哪些类型的表?
    在netfilter的框架中,每个数据包的梳理阶段,都可以挂接不同的规则,这些规则也可以分为不同的类型,主要有下面的类型: 在Netfilter中,有五种主要类型的表(table),每种表都有其特定的用途和功能。这些表是: filter表:这是Netfilter默认的表,也是最常用的表。它用于实现数据包过滤和网络......
  • netfilter中有哪些挂载点(hook points)?
    5个挂载点,挂载点有各种数据包处理的规则。 分别是:PREROUTINGINPUTFORWAROUTPUTPOSTROUTING 这些挂接点(hookpoints),是数据包处理的不同的阶段。 每个挂节点上,都可以挂载不同的包的处理规则,从而实现对数据包的处理和过滤。 ......
  • 拦截器-初探HandlerInterceptor
    HandlerInterceptor接口是Spring框架中提供的一种拦截器(Interceptor),它用于在处理器方法执行前后,以及请求处理完成后进行拦截和增强处理。拦截器是SpringMVC框架的一个重要组件,它可以用于在请求被处理前后进行预处理和后处理。拦截器可以用来实现诸如权限验证、日志记录、性......
  • Python高级过滤器:掌握filter函数从入门到精通
    简介在Python中,filter()是一个非常有用的内置函数,它能够根据指定的函数来筛选出可迭代对象中满足条件的元素,返回一个迭代器。filter()函数的使用能够简化代码,并提高程序的可读性。本文将从入门到精通,全面介绍filter()函数的用法和相关知识点。1.filter()函数的基本用法filter(......
  • vs(visual stuiod)中vc++工程的Filter和Folder及vcxproj知识
    vs中创建Filter在一个新项目中右键-Add-New,默认只有一选项NewFilter。创建出来的Filter可以理解为是VS的过滤器(虚拟目录),它不会在本地的磁盘上新建目录,而是修改了.filters文件,把这种目录关系记录在.filters文件中。新建一个vc++project,默认有这几种Filter,当然在实际的......
  • J2EE开发中Filter的奇妙作用
    Servlet2.3Filter1、ServletFilter概述凡是开发过J2EE的webapplication的人员都知道,经常需要处理以下几种情况:访问特定资源(Web页、JSP页、servlet)时的身份认证应用程序级的访问资源的审核和记录应用程序范围内对资源的加密......
  • springMVC Interceptor 拦截器
    1.springMVCInterceptor拦截器2.Filter和Interceptor比对3.HandlerInterceptor接口方法的作用及其参数、返回值详解4.springMVC拦截器执行顺序 ......
  • Android setColorFilter
    AndroidsetColorFilter详解在Android开发中,我们经常需要对图片进行处理以实现特定的效果。其中,setColorFilter函数是一个非常常用的方法之一,可以用来改变图片的颜色以及应用各种滤镜效果。本文将详细介绍setColorFilter方法的用法和示例代码,帮助读者了解如何使用该方法。setColo......
  • Java 连接redis at java.io.FilterOutputStream.flush(FilterOutputStream.java:1
    了解RedisRedis(REmoteDIctionaryServer)是一个开源的、基于内存的数据结构存储系统,它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。Redis提供了丰富的功能和高性能的数据操作,使其成为一个流行的数据库和缓存解决方案。Redis提供了多种语言的客户端库,使开发人员......