1、Filter 什么是过滤器

1、Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
2、Filter 过滤器它是 JavaEE 的规范。也就是接口
3、Filter 过滤器它的作用是:拦截请求过滤响应
拦截请求常见的应用场景有:
1、权限检查
2、日记操作
3、事务管理
……等等

2、Filter 的初体验

要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必 须是用户登录之后才允许访问。

思考:根据之前我们学过内容。我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以要检查用户是否登录,可以判断 Session 中否包含有用户登录的信息即可!!!

  1. <%
  2. Object user = session.getAttribute("user");
  3. if (user==null){
  4. request.getRequestDispatcher("/login.jsp").forward(request,response);
  5. return;
  6. }
  7. %>

Filter 的工作流程图:
QQ截图20220411183218.png
注意是:import javax.servlet.*;中的Filter接口

  1. package com.atguigu.filter;
  2. import javax.servlet.*;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpSession;
  5. import java.io.IOException;
  6. public class AdminFilter implements Filter {
  7. @Override
  8. public void init(FilterConfig filterConfig) throws ServletException {
  9. }
  10. /**
  11. * doFilter方法,专门用来拦截请求。可以做权限检查
  12. * @param servletRequest
  13. * @param servletResponse
  14. * @param filterChain
  15. * @throws IOException
  16. * @throws ServletException
  17. */
  18. @Override
  19. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  20. HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
  21. HttpSession session = httpServletRequest.getSession();
  22. Object user = session.getAttribute("user");
  23. // 如果等于 null,说明还没有登录
  24. if (user==null) {
  25. servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest, servletResponse);
  26. return;
  27. }else {
  28. // 让程序继续往下访问用户的目标资源,很重要,不能省略!!!
  29. filterChain.doFilter(servletRequest,servletResponse);
  30. }
  31. }
  32. @Override
  33. public void destroy() {
  34. }
  35. }
  1. <!--filter 标签用于配置一个 Filter 过滤器-->
  2. <filter>
  3. <!--给 filter 起一个别名-->
  4. <filter-name>AdminFilter</filter-name>
  5. <!--配置 filter 的全类名-->
  6. <filter-class>com.atguigu.filter.AdminFilter</filter-class>
  7. </filter>
  8. <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
  9. <filter-mapping>
  10. <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
  11. <filter-name>AdminFilter</filter-name>
  12. <!--url-pattern 配置拦截路径
  13. / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
  14. /admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
  15. *表示全部
  16. -->
  17. <url-pattern>/admin/*</url-pattern>
  18. </filter-mapping>

Filter 过滤器的使用步骤:
1、编写一个类去实现 Filter 接口
2、实现过滤方法 doFilter()
3、到 web.xml 中去配置 Filter 的拦截路径

3、Filter 的生命周期

Filter 的生命周期包含几个方法
1、构造器方法
2、init 初始化方法
第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)
3、doFilter 过滤方法
第 3 步,每次拦截到请求,就会执行
4、destroy 销毁
第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)

4、FilterConfig 类

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。
FilterConfig 类的作用是获取 filter 过滤器的配置内容
1、获取 Filter 的名称 filter-name 的内容
2、获取在 Filter 中配置的 init-param 初始化参数
3、获取 ServletContext 对象
QQ截图20220412113512.png

5、FilterChain 过滤器链

Filter 过滤器
Chain 链,链条
FilterChain 就是过滤器链(多个过滤器如何一起工作)
QQ截图20220412114029.png

6、Filter 的拦截路径

—精确匹配

<url-pattern>/target.jsp</url-pattern>
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp

—目录匹配

<url-pattern>/admin/</url-pattern>
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/

—后缀名匹配

<url-pattern>.html</*url-pattern>
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

<url-pattern>.do</*url-pattern>
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

<url-pattern>.action</*url-pattern>
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!

7、书城第八阶段:

1、使用 Filter 过滤器拦截/pages/manager/所有内容,实

现权限检查

  1. <filter>
  2. <filter-name>ManagerFilter</filter-name>
  3. <filter-class>com.atguigu.filter.ManagerFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>ManagerFilter</filter-name>
  7. <url-pattern>/pages/manager/*</url-pattern>
  8. <url-pattern>/manager/bookServlet</url-pattern>
  9. </filter-mapping>

2、ThreadLocal 的使用

ThreadLocal 的作用,它可以解决多线程的数据安全问题。
ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
ThreadLocal 的特点:
1、ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
2、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据, 就 需要使用多个ThreadLocal 对象实例。
3、每个 ThreadLocal 对象实例定义的时候,一般都是 static 类型
4、ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放。
深挖ThreadLocal
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。所以ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。
数据隔离的秘诀其实是这样的,Thread有个TheadLocalMap类型的属性,叫做threadLocals,该属性用来保存该线程本地变量。这样每个线程都有自己的数据,就做到了不同线程间数据的隔离,保证了数据安全。

  1. package com.atguigu.threadlocal;
  2. import com.sun.org.apache.xpath.internal.objects.XObject;
  3. import java.util.*;
  4. import java.util.concurrent.ConcurrentHashMap;
  5. import java.util.concurrent.ConcurrentMap;
  6. public class ThreadLocalTest {
  7. // public final static Map<String, Object> data = new Hashtable<>();
  8. public static ThreadLocal<Object> threadLocal=new ThreadLocal<Object>();
  9. private static Random random = new Random();
  10. public static class Task implements Runnable{
  11. @Override
  12. public void run() {
  13. Integer i = random.nextInt(1000)+1;
  14. String name = Thread.currentThread().getName();
  15. System.out.println("线程["+name+"]生成的随机数是:" + i);
  16. // data.put(name,i);
  17. threadLocal.set(i);
  18. try {
  19. Thread.sleep(3000);
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. new OrderService().createOrder();
  24. Object o = threadLocal.get();
  25. System.out.println("在线程["+name+"]快结束时取出关联的数据是:" + o);
  26. }
  27. }
  28. public static void main(String[] args) {
  29. for (int i = 0; i < 3; i++) {
  30. new Thread(new Task()).start();
  31. }
  32. }
  33. }

ThreadLocal可以这样理解:每个ThreadLocal类对象可以参与多个线程,每个对象中有一个Map集合,每一个线程都只能使用Map中的一个键值对(键:当前线程;值:存入的数据)。如果想要每个线程使用多个键值对,则要多声明几个ThreadLocal类对象。

3、使用 Filter 和 ThreadLocal 组合管理事务

3.1、使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完

原理分析图:
QQ截图20220414110230.png
ThreadLocal类对象在通过set()和get()方法储存和取值时,会自动识别当前线程作为键,对值进行操作。
conns.remove();一定要执行remove()操作,否则就会出错。(因为 Tomcat 服务器底层使用了线程池技术)
try{}catch(){}的catch中也可以抛异常throw new RuntimeException(e);

3.2、使用 Filter 过滤器统一给所有的 Service 方法都加上 try-catch。来进行实现的管理。

原理分析图:
QQ截图20220414155811.png

3.3、将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息页面。

在 web.xml 中我们可以通过错误页面配置来进行管理。

  1. <!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
  2. <error-page>
  3. <!--error-code 是错误类型-->
  4. <error-code>500</error-code>
  5. <!--location 标签表示。要跳转去的页面路径-->
  6. <location>/pages/error/error500.jsp</location>
  7. </error-page>
  8. <!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
  9. <error-page>
  10. <!--error-code 是错误类型-->
  11. <error-code>404</error-code>
  12. <!--location 标签表示。要跳转去的页面路径-->
  13. <location>/pages/error/error404.jsp</location>
  14. </error-page>

15尚硅谷_Filter过滤器王振国 - 课堂笔记.pdf