springBoot的过滤器,监听器,拦截器

概述

  在开发中,我们经常要考虑一些问题,对敏感词进行过滤,用户是否已经登录,是否需要对他的请求进行拦截,或者领导问现在在线人数有多少人?我们如何实现这些功能哪

@WebFilter

package com.xmlxy.firstspringbootproject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "customFilter",urlPatterns = "/*")
public class CustomFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("===========拦截器初始化==========");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        log.info("doFilter请求处理");
    }

    @Override
    public void destroy() {
        log.info("fifter销毁");
    }
}

在application类中添加@ServletComponentScan注解

package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.PropertySource;

@SpringBootApplication
@ServletComponentScan
@PropertySource(value = "classpath:jdbc.properties",encoding = "utf-8")
public class FirstSpringbootProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(FirstSpringbootProjectApplication.class, args);
    }

}

运行结果

(笔误,应该是过滤器初始化)过滤器已经生效,但若有多个过滤器,无法指定执行顺序,我们可以通过Java类的名称,从A-L,按顺序执行。但这种方式毕竟不大靠谱,所以,有第二种写法,它提供setOrder函数,为filter设置排序值。

package com.xmlxy.service;

import com.xmlxy.firstspringbootproject.CustomFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebFilterConfig
{
    @Bean
    public FilterRegistrationBean someFilterRegistration1()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        System.out.println("我执行了。。。。。。。");
        registration.setFilter(new CustomFilter());
        registration.addUrlPatterns("/*");
     registration.setOrder(1);
     return registration; } }

我们尝试写个demo,验证一下过滤器是否执行。

用户登录对象

User.java

package com.xmlxy.bean;

import lombok.Data;
import org.springframework.stereotype.Component;

@Data
@Component
public class User {
    private String user;
    private String pwd;
}

登录控制

LoginController.java

package com.xmlxy.firstspringbootproject;

import com.xmlxy.bean.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@RestController
public class LoginController {

    @RequestMapping(value = "login",method = RequestMethod.GET)
    public String login(HttpServletRequest request)
    {
        String user = request.getParameter("user");
        String pwd = request.getParameter("pwd");
        HttpSession session = request.getSession();
        if ("admin".equals(user) && "admin".equals(pwd))
        {
            User user1 = new User();
            user1.setUser(user);
            user1.setPwd(pwd);
            session.setAttribute("user",user1);
            return "登录成功";
        }
        return "密码错误,登录失败";
    }
  @RequestMapping(value = "test",method = RequestMethod.GET)  public String test()  {      return "test接口";  }
}

过滤器

CustomFilter.java

package com.xmlxy.firstspringbootproject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//@WebFilter(filterName = "customFilter",urlPatterns = "/*")
public class CustomFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);

    String includes[] = {"/login","register"};

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("===========过滤器初始化==========");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
    {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        HttpSession session = request.getSession(false);
        String uri = request.getRequestURI();
        boolean flag = isNeedFilter(uri);
        if (!flag)
        {
            filterChain.doFilter(servletRequest,servletResponse);
            System.err.printf("登录成功");
        }else {
            if (session != null && session.getAttribute("user") != null)
            {
                filterChain.doFilter(servletRequest,servletResponse);
            }else {
                System.err.printf("暂时未登录");
            }
        }

        log.info("doFilter请求处理");
    }
    public boolean isNeedFilter(String uri)
    {
        for (String include:includes)
        {
            if (include.equals(uri))
            {
                return false;
            }
        }
        return true;
    }
    @Override
    public void destroy() {
        log.info("fifter销毁");
    }
}

过滤器配置

WebFilterConfig

package com.xmlxy.service;

import com.xmlxy.firstspringbootproject.CustomFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebFilterConfig
{
    @Bean
    public FilterRegistrationBean someFilterRegistration1()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        System.out.println("我执行了。。。。。。。");
        registration.setFilter(new CustomFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }
}

运行测试。。访问 127.0.0.1/test  控制台

访问  http://127.0.0.1:8080/login?user=admin&pwd=admin,可以看到登录成功

在次访问 127.0.0.1/test 页面显示

所以,我们的过滤器成功过滤未登录的用户

监听器

正在你为自己会了过滤用户自鸣得意时,你的组长过来了,小明,你看下我们平台的在线用户有多少人。如果不知道监听器童鞋,是否会在登录接口处每次登录成功都+1,然而这种统计结果是不准确的,因为用户如果反复登录退出,那这个在值就远远大于实际值,最后就面临着,加班在加班的悲惨下场。

CustomLister.java

package com.xmlxy.firstspringbootproject;

import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebFilter
public class CustomLister implements HttpSessionListener
{
    public static int online = 0;

    @Override
    public void sessionCreated(HttpSessionEvent sessionEvent)
    {
        System.out.println("创建session,统计在线人数");
        online ++;
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent sessionEvent)
    {
        System.out.println("session已经销毁");
    }
}

配置监听器配置,在刚才的WebFilterConfig.java添加

@Bean
    public ServletListenerRegistrationBean listenerRegistrationBean()
    {
        ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
        srb.setListener(new CustomLister());
        System.out.println("");
        return srb;
    }

添加一个访问在线人数的接口

@RequestMapping(value = "onLinePerson",method = RequestMethod.GET)
    public String onLinePerson()
    {
        StringBuffer stringBuffer = new StringBuffer("");
        stringBuffer.append(" 在线人数 ");
        stringBuffer.append(CustomLister.online);
        stringBuffer.append(" 个人 ");
        return stringBuffer.toString();
    }

访问127.0.0.1/onLinePerson,发现被拦截器拦截了,我们先登录。在查看接口

换个浏览器,调用下login接口,在查看

拦截器

拦截器,个人理解,在web上有些像是过滤器的补充,它能更精确的控制拦截哪些函数或者字段,在拦截之前或之后做一些操作。我们现在做一个敏感词的拦截,其实这个操作放在过滤器操作也是可以的,但lz因为刚才把拦截用户的操作放在过滤器了,在大规模更改,lz觉得没必要,因为都是大同小异。

CustomInterceptor.java

package com.xmlxy.firstspringbootproject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

public class CustomInterceptor implements HandlerInterceptor
{
    private static final Logger log = LoggerFactory.getLogger(CustomInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
        log.info("=======拦截器被调用=====");
        String url = request.getRequestURI();
        if (url != null && url.indexOf("seqing") != -1)
        {
            PrintWriter printWriter = response.getWriter();
            printWriter.write("ming gan ci");
            return false;
        }
        log.info("返回false 则中断请求");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    {
        log.info("请求后调用");
    }

    @Override
    public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception e)
    {
        log.info("视图渲染完回调");
    }
}

配置拦截

package com.xmlxy.service;

import com.xmlxy.firstspringbootproject.CustomFilter;
import com.xmlxy.firstspringbootproject.CustomInterceptor;
import com.xmlxy.firstspringbootproject.CustomLister;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
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 WebFilterConfig implements WebMvcConfigurer
{
    @Bean
    public FilterRegistrationBean someFilterRegistration1()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        System.out.println("我执行了。。。。。。。");
        registration.setFilter(new CustomFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }

    @Bean
    public ServletListenerRegistrationBean listenerRegistrationBean()
    {
        ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
        srb.setListener(new CustomLister());
        return srb;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        /*拦截规则*/
        registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/*");
    }

}

现在测试访问127.0.0.1/seqing,被过滤,要求先登录。我们调用登录接口后,再次调用,发现被拦截了

看下日志调用,可以发现,拦截器是在访问接口前被调用的

过滤器,拦截器区别

这里主要说下拦截器和过滤器的区别和使用场景,通过demo可以发现,它们都能实现权限的检查,日志记录这些功能,主要说下它们的区别

  1. 过滤器和拦截器触发的时机是不同的,在进入servlet之前,过滤器就进行预处理了。而拦截器是在调用Controller之前才触发执行,过滤器的范围较广,对所有的请求都起作用,而拦截起只 对action起作用

  2.拦截器可以获取IOC容器的各个bean,而过滤器就不行。因为拦截器是spring提供管理的,也因此拦截器可以使用spring的任何资源。

  3.拦截器是利用Java反射机制实现,过滤器是函数的回调。因此实现方式是不同的。

三者使用场景

  监听器常用统计在线用户,统计网站的访问量,记录用户的访问路径

  过滤器:过滤敏感词,权限访问控制

  拦截器:权限验证,判断用户是否登录等

原文地址:https://www.cnblogs.com/dslx/p/11275958.html

时间: 2024-07-29 20:54:24

springBoot的过滤器,监听器,拦截器的相关文章

JavaWeb过滤器.监听器.拦截器-?原理&amp;区别

1.拦截器是基于java的反射机制,过滤器是基于函数回调 2.拦截器不依赖与servlet容器,过滤器依赖与servlet容器3.拦截器只能对action请求起作用,过滤器则可以对几乎所有的请求起作用 4.拦截器可以访问action上下文.值栈里的对象,而过滤器不能 5.在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,

SpringBoot(十一)过滤器和拦截器

在做web开发的时候,过滤器(Filter)和拦截器(Interceptor)很常见,通俗的讲,过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西:拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇. 过滤器依赖于servlet容器,是JavaEE标准,是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理.在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初

关于过滤器,拦截器,监听器

链接:https://www.zhihu.com/question/35225845 过滤器(Filter): 过滤器换一种表达就是预处理(pre processing)或者后处理(post processing),你说到的依赖于servlet容器,我觉得这是狭隘层次上的定义,你用米进行煮饭前要做什么,要用水先对米进行清洗,浸泡一下,这就是预处理:你榨完果汁后是直接喝吗,不,还要用筛子将果渣过滤掉,这就是后处理,对数据进行预处理或者后处理就是过滤器要做的工作,常见的应用有将请求中的数据进行转码,

springBoot之配置文件的读取以及过滤器和拦截器的使用

前言 在之前的学习springBoot中,成功的实现了Restful风格的基本服务.但是想将之前的工程作为一个项目来说,那些是仅仅不够的.可能还需要获取自定义的配置以及添加过滤器和拦截器.至于为什么将这些写在一起,只是因为这些比较简单而且也会经常用到,所以干脆就一起写出来了. 读取配置文件 在使用maven项目中,配置文件会放在resources根目录下. 我们的springBoot是用Maven搭建的,所以springBoot的默认配置文件和自定义的配置文件都放在此目录. springBoot

springboot环境下配置过滤器和拦截器

以前我们在配置过滤器和拦截器的时候,都是一个类继承一个接口,然后在xml中配置一下就ok 但是,但是,这是springboot的环境,没有xml的配置.所以我们还要继续学习啊啊啊啊啊~~~~~ 先简单大致说明一下,过滤器我们可以直接在类上加上@Component注解实现,但是有些参数啥的还是不好配置,还是需要一个配置文件来搞,所以,spring给我们提供了一个注解,就相当于xml,然后每个方法返回一个对象用@Bean来标注,相当于<bean></bean>注解   看代码吧 Tim

过滤器、拦截器、监听器

原文:https://www.zhihu.com/question/35225845/answer/61876681 从设计模式的角度分析它们的不同. 过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西.定义这些要求的工具,就是过滤器. 拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情. 监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程

Java中的过滤器,拦截器,监听器---------简单易懂的介绍

过滤器: 过滤器其主要特点在于:取你需要的东西,忽视那些不需要的东西!在程序中,你希望选择中篇文章中的所有数字,你就可以针对性的挑选数字! 拦截器: 拦截器其主要特点在于:针对你不要的东西进行拦截,比如说,在一个BBS里面你希望人家不要留“小乌鸦”的这个词,那你就可能采用拦截器! 监听器: 是一个事件处理过程,这个过程的取舍,可以让你的代码成为过滤器,还是成为拦截器~~~比如,你想监听一段用户的数据中有没有1有的话就打印111!这就需要程序都监听用户输入的东西了!if(***..equls('1

【java web】过滤器、拦截器、监听器的区别

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

java-过滤器-监听器-拦截器

1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request.Response)统一设置编码,简化操作:同时还可进行逻辑判断,如用户是否已经登陆.有没有权限访问该页面等等工作.它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用

Java 过滤器和拦截器的区别

昨天晚上做梦,梦见面试官问我过滤器和拦截器的区别... 过滤器和拦截器的区别:1.过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的. 请求结束返回也是,是在servlet处理完后,返回给前端之前.2.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的, spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑. 而过滤器是JavaEE标准,只需依赖servlet api ,不