作者:海向

出处:www.cnblogs.com/haixiang/p/12000685.html

过滤器

过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术。

如同它的名字一样,过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作 Session 校验,判断用户权限,如果不符合设定条件,则会被拦截到特殊的地址或者基于特殊的响应。

过滤器的使用

首先需要实现 Filter接口然后重写它的三个方法

  • init 方法:在容器中创建当前过滤器的时候自动调用

  • destory 方法:在容器中销毁当前过滤器的时候自动调用

  • doFilter 方法:过滤的具体操作

我们先引入 Maven 依赖,其中 lombok 是用来避免每个文件创建 Logger 来打印日志

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

我们首先实现接口,重写三个方法,对包含我们要求的四个请求予以放行,将其它请求拦截重定向至/online,只要在将MyFilter实例化后即可,我们在后面整合代码中一起给出。

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;@Log4j2
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("初始化过滤器");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);String requestUri = request.getRequestURI();log.info("请求地址是:"+requestUri);if (requestUri.contains("/addSession")|| requestUri.contains("/removeSession")|| requestUri.contains("/online")|| requestUri.contains("/favicon.ico")) {filterChain.doFilter(servletRequest, response);} else {wrapper.sendRedirect("/online");}}@Overridepublic void destroy() {//在服务关闭时销毁log.info("销毁过滤器");}
}

拦截器

Java中的拦截器是动态拦截 action 调用的对象,然后提供了可以在 action 执行前后增加一些操作,也可以在 action 执行前停止操作,功能与过滤器类似,但是标准和实现方式不同。

  • 登录认证:在一些应用中,可能会通过拦截器来验证用户的登录状态,如果没有登录或者登录失败,就会给用户一个友好的提示或者返回登录页面,当然大型项目中都不采用这种方式,都是调单点登录系统接口来验证用户。

  • 记录系统日志:我们在常见应用中,通常要记录用户的请求信息,比如请求 ip,方法执行时间等,通过这些记录可以监控系统的状况,以便于对系统进行信息监控、信息统计、计算 PV、性能调优等。

  • 通用处理:在应用程序中可能存在所有方法都要返回的信息,这是可以利用拦截器来实现,省去每个方法冗余重复的代码实现。

使用拦截器

我们需要实现 HandlerInterceptor 类,并且重写三个方法:

  • preHandle:在 Controoler 处理请求之前被调用,返回值是 boolean类型,如果是true就进行下一步操作;若返回false,则证明不符合拦截条件,在失败的时候不会包含任何响应,此时需要调用对应的response返回对应响应。

  • postHandler:在 Controoler 处理请求执行完成后、生成视图前执行,可以通过ModelAndView对视图进行处理,当然ModelAndView也可以设置为 null。

  • afterCompletion:在 DispatcherServlet 完全处理请求后被调用,通常用于记录消耗时间,也可以对一些资源进行处理。

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
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;@Log4j2
@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("【MyInterceptor】调用了:{}", request.getRequestURI());request.setAttribute("requestTime", System.currentTimeMillis());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {if (!request.getRequestURI().contains("/online")) {HttpSession session = request.getSession();String sessionName = (String) session.getAttribute("name");if ("haixiang".equals(sessionName)) {log.info("【MyInterceptor】当前浏览器存在 session:{}",sessionName);}}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {long duration = (System.currentTimeMillis() - (Long)request.getAttribute("requestTime"));log.info("【MyInterceptor】[{}]调用耗时:{}ms",request.getRequestURI(), duration);}
}

监听器

监听器通常用于监听 Web 应用程序中对象的创建、销毁等动作的发送,同时对监听的情况作出相应的处理,最常用于统计网站的在线人数、访问量等。关注公众号互联网架构师回复2T可以获取更多系列 Spring Boot 教程。

监听器大概分为以下几种:

  • ServletContextListener:用来监听 ServletContext 属性的操作,比如新增、修改、删除。

  • HttpSessionListener:用来监听 Web 应用种的 Session 对象,通常用于统计在线情况。

  • ServletRequestListener:用来监听 Request 对象的属性操作。

监听器的使用

我们通过 HttpSessionListener来统计当前在线人数、ip等信息,为了避免并发问题我们使用原子int来计数。

ServletContext,是一个全局的储存信息的空间,它的生命周期与Servlet容器也就是服务器保持一致,服务器关闭才销毁。

request,一个用户可有多个;

session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。

因此我们这里用ServletContext来存储在线人数sessionCount最为合适。

我们下面来统计当前在线人数:

import lombok.extern.log4j.Log4j2;import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.concurrent.atomic.AtomicInteger;@Log4j2
public class MyHttpSessionListener implements HttpSessionListener {public static AtomicInteger userCount = new AtomicInteger(0);@Overridepublic synchronized void sessionCreated(HttpSessionEvent se) {userCount.getAndIncrement();se.getSession().getServletContext().setAttribute("sessionCount", userCount.get());log.info("【在线人数】人数增加为:{}",userCount.get());//此处可以在ServletContext域对象中为访问量计数,然后传入过滤器的销毁方法//在销毁方法中调用数据库入库,因为过滤器生命周期与容器一致}@Overridepublic synchronized void sessionDestroyed(HttpSessionEvent se) {userCount.getAndDecrement();se.getSession().getServletContext().setAttribute("sessionCount", userCount.get());log.info("【在线人数】人数减少为:{}",userCount.get());}
}

过滤器、拦截器、监听器注册

实例化三器

import com.anqi.tool.sanqi.filter.MyFilter;
import com.anqi.tool.sanqi.interceptor.MyInterceptor;
import com.anqi.tool.sanqi.listener.MyHttpRequestListener;
import com.anqi.tool.sanqi.listener.MyHttpSessionListener;
import org.springframework.beans.factory.annotation.Autowired;
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 WebConfig implements WebMvcConfigurer {@AutowiredMyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor);}/*** 注册过滤器* @return*/@Beanpublic FilterRegistrationBean filterRegistrationBean(){FilterRegistrationBean filterRegistration = new FilterRegistrationBean();filterRegistration.setFilter(new MyFilter());filterRegistration.addUrlPatterns("/*");return filterRegistration;}/*** 注册监听器* @return*/@Beanpublic ServletListenerRegistrationBean registrationBean(){ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean();registrationBean.setListener(new MyHttpRequestListener());registrationBean.setListener(new MyHttpSessionListener());return registrationBean;}
}

测试

import com.anqi.tool.sanqi.listener.MyHttpSessionListener;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@RestController
public class TestController {@GetMapping("addSession")public String addSession(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("name", "haixiang");return "当前在线人数" + session.getServletContext().getAttribute("sessionCount") + "人";}@GetMapping("removeSession")public String removeSession(HttpServletRequest request) {HttpSession session = request.getSession();session.invalidate();return "当前在线人数" + session.getServletContext().getAttribute("sessionCount") + "人";}@GetMapping("online")public String online() {return "当前在线人数" + MyHttpSessionListener.userCount.get() + "人";}}

以下是监听请求的监听器

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;public class MyHttpRequestListener implements ServletRequestListener {@Overridepublic void requestDestroyed(ServletRequestEvent sre) {System.out.println("request 监听器被销毁");}@Overridepublic void requestInitialized(ServletRequestEvent sre) {HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();String requestURI = req.getRequestURI();System.out.println(requestURI+"--"+"被调用");}
}

拦截器与过滤器的区别

1.参考标准

  • 过滤器是 JavaEE 的标准,依赖于 Servlet 容器,生命周期也与容器一致,利用这一特性可以在销毁时释放资源或者数据入库。

  • 拦截器是SpringMVC中的内容,依赖于web框架,通常用于验证用户权限或者记录日志,但是这些功能也可以利用 AOP 来代替。

2.实现方式

  • 过滤器是基于回调函数实现,无法注入 ioc 容器中的 bean。

  • 拦截器是基于反射来实现,因此拦截器中可以注入 ioc 容器中的 bean,例如注入 Redis 的业务层来验证用户是否已经登录。

关微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBook发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别

9、2T架构师学习资料干货分享

Spring Boot 如何使用拦截器、过滤器、监听器?相关推荐

  1. java过滤器原理,拦截器,过滤器,监听器 区别及执行顺序

    本文引用该作者(花开半夏)著作内容,觉得写的很好,记录一下便于回看防止失踪,更多详情请查看原作者. 同时还搜罗了其他便于理解的博文感兴趣的可以看看促进理解 拦截器,过滤器,监听器执行顺序(被拦截个人过 ...

  2. Spring Boot 实现登录拦截器,这才是正确的姿势!!

    原文:https://blog.csdn.net/qq_27198345/article/details/111401610 对于管理系统或其他需要用户登录的系统,登录验证都是必不可少的环节,在Spr ...

  3. Spring MVC中的拦截器/过滤器HandlerInterceptorAdapter的使用

    转载自 https://www.cnblogs.com/EasonJim/p/7704740.html 一般情况下,对来自浏览器的请求的拦截,是利用Filter实现的 而在Spring中,基于Filt ...

  4. Spring Boot实战:拦截器与过滤器

    一.拦截器与过滤器 在讲Spring boot之前,我们先了解一下过滤器和拦截器.这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的.在分析两者的区别之前,我们先理解一下AOP的概念,A ...

  5. java中拦截器 过滤器 监听器都有什么区别

    过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts2的action进行业务逻辑,比如过滤掉非法u ...

  6. 拦截器 过滤器 监听器 的区别

    面试的时候突然被问了这么个问题 本来知道点啥的 脑子一热 啥也没说出来总结一下 以下内容均摘自网络 但是 读完之后 应该会对它们有更清晰的认识.1.1 什么是拦截器: 拦截器,在AOP(Aspect- ...

  7. Spring Boot笔记-设置拦截器为false时返回的Body

    以preHandle拦截器为例: @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse ...

  8. Java拦截器,过滤器,监听器(三大器)对比

    https://blog.csdn.net/baidu_20876831/article/details/80405515

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

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

  10. java ssh过滤器_SSH中的过滤器,拦截器,监听器的一些基本认识

    今天被一个朋友问起在SSH的项目中,过滤器.拦截器.监听器都分别是什么,又都是干什么用的.结合目前学习到的和自己应用的体会,大概有以下几个方面. 1.过滤器:顾名思义就是过滤请求内容的,所谓的过滤就是 ...

最新文章

  1. Redis configuration
  2. Hadoop入门(十五)Mapreduce的数据排序程序
  3. Python 也能干大事 —— 解方程
  4. Java中IDEA,Springboot实现手机获取验证码和倒计时
  5. 手把手教你实现热更新功能,带你了解 Arthas 热更新背后的原理
  6. 内存映射过程之paging_init
  7. 银江股份:全面布局持续并购打造智慧城市生态圈
  8. carmaker的弱智算法
  9. 统计通话次数和时间的软件_通话时间统计app下载-通话时间统计下载 2.2.2 安卓版 - 河东软件园...
  10. wps桌面图标不显示问题
  11. 都说IT行业有前景,请问凭什么?
  12. C# 解析种子文件(bt文件)
  13. linux CPU占用率高
  14. Ubuntu连接IKEv2
  15. Merriam-Webster's Vocabulary Builder 学习笔记 Unit 18
  16. IT技术人员 35岁 (转)
  17. MySQL数据库实际应用中,需求分析阶段需要做什么?
  18. Linux Ubuntu18.04系统 USB转串口驱动安装,查看串口号
  19. 如何点击连接直接下载.txt文本文件
  20. 【Unity3D读取数据】(一)Txt文档操作(创建、读取、写入、修改)

热门文章

  1. [FATAL] [DBT-10317] Specified SID Name (lhr122) already exists.
  2. asp.net mvc 如何调用微信jssdk接口:分享到微信朋友(圈)| 分享到qq空间
  3. 感谢你遇到的问题(2)
  4. 使用javamail通过代理发送邮件
  5. 用于 Domino Web Access 的 Notes.ini 变量
  6. 459B Pashmak and Flowers
  7. Illustrator中文版教程,如何在 Illustrator 中使用自由变换工具?
  8. [MAC] 小技巧– 取消屏幕缩放功能,以免不小心误触
  9. Xcode之developer tools access
  10. 1Password 7:Mac的密码管理工具