概述

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

 @WebFilterpackage com.net.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);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("===========拦截器初始化==========");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {servletRequest.setCharacterEncoding("utf-8");servletResponse.setCharacterEncoding("utf-8");filterChain.doFilter(servletRequest,servletResponse);log.info("doFilter请求处理");}@Overridepublic 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.net.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
{@Beanpublic 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.net.bean;import lombok.Data;
import org.springframework.stereotype.Component;@Data
@Component
public class User {private String user;private String pwd;
}

登录控制

LoginController.java

package com.net.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.net.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"};@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("===========过滤器初始化==========");}@Overridepublic 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;}@Overridepublic void destroy() {log.info("fifter销毁");}
}

过滤器配置

WebFilterConfig

package com.net.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
{@Beanpublic 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 页面显示

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

监听器

先写个HttpSessionListener 监听器。count  是session的数量(人数),session 创建的时候,会触发监听器的sessionCreated 方法,session销毁的时候,会触发监听器的sessionDestroyed 方法。 在监听器中计算完人数count,把他放进servletContext(可以理解为一个仓库,任意请求可以存储和获取里面的属性)。

注意监听器加上@WebListener,这样就不用配置。

@WebListenerpublic class CustomLister implements HttpSessionListener {public int count=0;//记录session的数量//监听session的创建,synchronized 防并发bugpublic synchronized void sessionCreated(HttpSessionEvent arg0) {System.out.println("【HttpSessionListener监听器】count++  增加");count++;arg0.getSession().getServletContext().setAttribute("count", count);}@Overridepublic synchronized void sessionDestroyed(HttpSessionEvent arg0) {//监听session的撤销System.out.println("【HttpSessionListener监听器】count--  减少");count--;arg0.getSession().getServletContext().setAttribute("count", count);}
}

接着写一个查询session 数量的controller,我开始的时候是像下面这样写的,是错误的!

从servletContext 中取出count ,把count返回前端。

@RequestMapping("/count")
@ResponseBody
public String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){Object count=httpServletRequest.getServletContext().getAttribute("count");return "count : "+count;}

这样是错误的,测试你会发现,页面看到count  是null ,因为没有创建session,没有触发监听器的统计方法。于是改一下:

@Controller
public class IndexController {@RequestMapping("/count")@ResponseBodypublic String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){HttpSession session = httpServletRequest.getSession();Object count=session.getServletContext().getAttribute("count");return "count : "+count;}
}

HttpSession session = httpServletRequest.getSession();  作用:该用户如果没有sesision则创建session ,有则取得session不创建。

改成这样测试,看起来是对的,但是有个问题。一个浏览器对应一个session,你打开2个浏览器,看到count是2 ,是对的。但是你关了一个浏览器,再打开,应该是2不变才对,但是变成3 了,原因是session销毁的方法没有执行,重新打开时,服务器找不到用户原来的session ,重新创建了一个session,于是有3个session了,但是浏览器只有2个,也就是模拟应该是只有2个人在线上。

有2个方法可以解决这个问题,一个是在关闭网页的时候,前端去调用一个方法把session销毁。另一个更好的方法是,让服务器记得原来那个session,即把原来的sessionId 记录在浏览器,下次打开时,把这个sessionId发送过去,这样服务器就不会重新创建。

代码修改如下:

@Controller
public class IndexController {@RequestMapping("/count")@ResponseBodypublic String number(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){try{  //把sessionId记录在浏览器Cookie c = new Cookie("JSESSIONID", URLEncoder.encode(httpServletRequest.getSession().getId(), "utf-8"));c.setPath("/");//先设置cookie有效期为2天,不用担心,session不会保存2天c.setMaxAge( 48*60 * 60);httpServletResponse.addCookie(c);}catch (Exception e){e.printStackTrace();}HttpSession session = httpServletRequest.getSession();Object count=session.getServletContext().getAttribute("count");return "count : "+count;}
}

测试达到效果。

监听器的另一种配置方式

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

拦截器

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

CustomInterceptor.java

package com.net.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);@Overridepublic 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;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){log.info("请求后调用");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception e){log.info("视图渲染完回调");}
}

配置拦截

package com.net.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
{@Beanpublic FilterRegistrationBean someFilterRegistration1(){FilterRegistrationBean registration = new FilterRegistrationBean<>();System.out.println("我执行了。。。。。。。");registration.setFilter(new CustomFilter());registration.addUrlPatterns("/*");return registration;}@Beanpublic ServletListenerRegistrationBean listenerRegistrationBean(){ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();srb.setListener(new CustomLister());return srb;}@Overridepublic 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反射机制实现,过滤器是函数的回调。因此实现方式是不同的。

三者使用场景

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

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

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

附:前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,分享一下给大家。点击跳转到教程。

--- end ---

springBoot的过滤器,监听器,拦截器相关推荐

  1. SpringBoot实现过滤器、拦截器与切片

    作者:七印miss juejin.im/post/5c6901206fb9a049af6dcdcf Q:使用过滤器.拦截器与切片实现每个请求耗时的统计,并比较三者的区别与联系 过滤器Filter 过滤 ...

  2. springBoot之过滤器和拦截器的使用

    在springBoot中,过滤器和拦截器的使用. 过滤器 概述 过滤器是什么? 简单的来说,过滤器就是过滤的作用,在web开发中过滤一些我们指定的url. 过滤器主要做什么? 过滤掉一些不需要的东西, ...

  3. SpringBoot实现过滤器、拦截器与切片源码分析

    过滤器Filter 过滤器概念 Filter是J2E中来的,可以看做是Servlet的一种"加强版",它主要用于对用户请求进行预处理和后处理,拥有一个典型的处理链.Filter也可 ...

  4. 过滤器-监听器-拦截器对比

    1,拦截器的概念     java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action 执行前阻止其执行,同时也提 ...

  5. SpringBoot整合过滤器、拦截器

    目录 过滤器.拦截器的区别 过滤器.拦截器的使用场景 同时存在过滤器.拦截器时的执行流程 springboot整合过滤器 编写过滤器 配置过滤器 springboot整合拦截器 编写拦截器 配置拦截器 ...

  6. springBoot 2.x过滤器--监听器--拦截器

    springboot 2.x过滤器 1.什么是 springboot 2.x过滤器 类似于检票员,检验游客的门票 2.springboot里的过滤器 ApplicationContextHeaderF ...

  7. 【学习笔记】springboot的过滤器与拦截器的使用 springboot的事件驱动模型

    文章目录 过滤器 使用过滤器实现访问控制 拦截器 事件驱动模型 过滤器 在实际的开发过程中,可能会遇到这样一类需求:统计在线用户.敏感词过滤或者基于URL进行访问控制.这些需求有一个共同点--在每个接 ...

  8. SpringBoot配置过滤器和拦截器

    一.概念 1简介 过滤器是JavaEE中Servlet规范的一个组件,通过Filter技术,可以实现用户访问某个资源前,对访问的请求和响应进行拦截 拦截器(Interceptor)类似于Servlet ...

  9. springboot配置监听器、过滤器和拦截器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  10. 过滤器、拦截器、监听器的区别与使用

    一.拦截器与过滤器的区别 过滤器 (Filter) 过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法 ...

最新文章

  1. web性能优化——关键渲染路径(上)
  2. 197. 阶乘分解【数论】
  3. 【Spring学习】spring开发包介绍
  4. MYSQL中的空格及大小写问题
  5. Sentinel降级_RT_分布式系统集群限流_线程数隔离_削峰填谷_流量控制_速率控制_服务熔断_服务降级---微服务升级_SpringCloud Alibaba工作笔记0039
  6. 开玩笑呢?学习KMP算法能改变自我认知? | 原力计划
  7. 今天心情好,发首我喜欢的歌---天黑黑
  8. JAVA程序员面试32问(附答案)(转载)
  9. 5个冷门的MacOS快捷键,小众但好用
  10. esp8266oled做时钟python_ESP8266实战一——带OLED显示屏电子时钟
  11. mysql 内存 优化_MySQL核心参数优化(内存优化)
  12. 国家数据字典mysql_数据字典 · MySQL DBA · 看云
  13. 公众号改名了,聊聊我的思考
  14. 深度学习——深度学习基础概念
  15. 详解B2B、B2C、C2B、C2C、O2O的含义及区别
  16. 微信消息提醒python实现
  17. 食堂团餐预定小程序开发制作功能介绍
  18. 惯性导航系统、加速度计、陀螺仪原理
  19. 基于红外遥控的智能语音芯片在空调中的应用
  20. ps油画滤镜,消失点,camera row,查找边缘,等高线

热门文章

  1. BIND9手册【转】
  2. The Forty-first Of Word-Day
  3. 热插拔技术详解(下)
  4. varchar与char有什么区别
  5. 欧盟通用数据保护条例GDPR.docx数据摘要 导读:GDPR通用数据保护条例中文版由中国政法大学互联网金融法律研究院组织翻译, 新法案由11章共99条组成。 GDPR的通过意味着欧盟对个人信息保
  6. c语言循环单链表实现约瑟夫环问题
  7. 10个无版权限制的免费图片素材资源网站
  8. python绝对值编程_python中取绝对值简单方法总结
  9. 【linux命令】我常用的Linux命令
  10. 发明计算机作文300字,发明作文300字