SpringBoot里面Filter讲解

73 篇文章 0 订阅
52 篇文章 0 订阅

filter简单理解:

          过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理。

大概流程图如下:

应用场景:

  • 自动登录
  • 统一设置编码格式
  • 访问权限控制
  • 敏感字符过滤等

SpringBoot启动默认加载的Filter

  •             characterEncodingFilter
  •             hiddenHttpMethodFilter
  •             httpPutFormContentFilter
  •             requestContextFilter

                

Filter优先级

  •             Ordered.HIGHEST_PRECEDENCE
  •             Ordered.LOWEST_PRECEDENCE

            低位值意味着更高的优先级 Higher values are interpreted as lower priority
            自定义Filter,避免和默认的Filter优先级一样,不然会冲突

            注册Filter的bean FilterRegistrationBean
            同模块里面有相关默认Filter
                web->servlet->filter


自定义Filter

package net.xdclass.demo.Filter;

import net.xdclass.demo.controller.FileController;

import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//拦截所有的api请求
@WebFilter(urlPatterns = "/api/*",filterName = "loginFilter")
public class LoginFilter implements Filter {

    //容器加载的时候调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        System.out.println("init loginfilter");
    }

    //请求拦截的时候调用
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter loginFilter");
        HttpServletRequest request =(HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        /*
        获取用户名密码,进行判断是否正确
         */
        String username = request.getParameter("username");
        if("xdclass".equals(username)){
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            return;
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

    //容器被销毁的时候被调用
    @Override
    public void destroy() {
        System.out.println("destroy loginFilter");
    }
    
}

 

  •             使用Servlet3.0的注解进行配置
  •             启动类里面增加 @ServletComponentScan,进行扫描
  •             新建一个Filter类,implements Filter,并实现对应的接口
  •             @WebFilter 标记一个类为filter,被spring进行扫描
  •                 urlPatterns:拦截规则,支持正则
  •             控制chain.doFilter的方法的调用,来实现是否通过放行
                   不放行,web应用resp.sendRedirect("/index.html");
                   场景:权限控制、用户登录(非前端后端分离场景)等

            

    官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners

使用 Servlet3.0的注解自定义原生Servlet和Listener

自定义原生Servlet
@WebServlet(name = "userServlet",urlPatterns = "/test/customs")
public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("custom sevlet");
        /*
        清空缓冲区数据,就是说你用读写流的时候,其实数据是先被读到了内存中,
        然后用数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,
        因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了 close()方法关闭了读写流,
        那么这部分数据就会丢失,所以应该在关闭读写流之前先flush(),先清空数据。
         */
        resp.getWriter().flush();
        resp.getWriter().close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

Servlet3.0的注解自定义原生Listener监听器

           监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

           常用的监听器 servletContextListener、httpSessionListener、servletRequestListener

  • ServletContext是一个全局的储存信息的空间,其监听器从服务器启动调用contextInitialized方法到服务器停止contextDestoryed方法,对于一个web项目,ServletContext对象只能有一个,而ServletContextListener却可以有多个。ServletContext主要用于定时器和全局属性对象。
  • HttpSession监听器在一次会话发生时被调用sessionCreated方法会话结束时调用sessionDestoryed方法。在一个web项目中可以有多个HttpSession对象,1个HttpSession可以注册多个HttpSessionListener。HttpSession常用于记录访问人数和访问日志。
  • ServletRequest监听器在客户端请求事件发生时被调用requestInitialized方法事件完成时requestDestoryed方法。一个ServletRequest同样可以注册多个ServletRequestListener,ServletRequest常用于读取参数和记录访问历史。
自定义Listener
			@WebListener
			public class RequestListener implements ServletRequestListener {

			@Override
			public void requestDestroyed(ServletRequestEvent sre) {
				// TODO Auto-generated method stub
				System.out.println("======requestDestroyed========");
			}

			@Override
			public void requestInitialized(ServletRequestEvent sre) {
				System.out.println("======requestInitialized========");
				
			}

SpringBoot2.X拦截器使用

    1、@Configuration
        继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)

        SpringBoot2.X 新版本配置拦截器 implements WebMvcConfigurer

    2、自定义拦截器 HandlerInterceptor

  •         preHandle:调用Controller某个方法之前
  •         postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法
  •         afterCompletion:不管有没有异常,这个afterCompletion都会被调用,用于资源清理

    

package net.xdclass.demo.intecpter;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginIntercepter implements HandlerInterceptor {
    //进入controller方法之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("======preHandle======");
        /*
        判断用户是否登录,是否拥有权限
         */
//        String token = request.getParameter("access_token");
//        response.getWriter().print("fail");
        return HandlerInterceptor.super.preHandle(request,response,handler);
    }

    //调用完controller之后,视图渲染之前
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("======postHandle======");
        HandlerInterceptor.super.postHandle(request,response,handler,modelAndView);
    }

    //整个完成之后,通常用于资源清理
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        System.out.println("======afterCompletion======");
        HandlerInterceptor.super.afterCompletion(request,response,handler,ex);
    }
}


    3、按照注册顺序进行拦截,先注册,先被拦截

package net.xdclass.demo.intecpter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CustomerWebMvcConfiguer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**");
        registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/v1/*/**");
        WebMvcConfigurer.super.addInterceptors(registry);
        //拦截全部/*/**/***
        //若拦截test.action类动作则/*.*
    }
}

    拦截器不生效常见问题:
        1)是否有加@Configuration
        2)拦截路径是否有问题 **  和 *
        3)拦截器最后路径一定要 “/**”, 如果是目录的话则是 /*/

    Filter
        是基于函数回调 doFilter(),而Interceptor则是基于AOP思想

        Filter在只在Servlet前后起作用,而Interceptor够深入到方法前后、异常抛出前后等

        依赖于Servlet容器即web应用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境。   

        在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。       

        Filter和Interceptor的执行顺序:        
        过滤前->拦截前->action执行->拦截后->过滤后


过滤器和拦截器的区别:

  ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值