JavaWeb学习|Filter与ThreadLocal

学习材料声明

所有知识点都来自互联网,进行总结和梳理,侵权必删。
引用来源:尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版

Filter

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

1.情景实践(要求未登录情况,浏览器不能访问admin目录下的所有文件)

设置filter类,继承Filter,编写doFilter
在web.xml里面配置filter的url。
在这里插入图片描述
Filter:

public class AdminFilter implements Filter {/*** doFilter 方法,专门用于拦截请求。可以做权限检查*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChainfilterChain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;HttpSession session = httpServletRequest.getSession();Object user = session.getAttribute("user");// 如果等于 null,说明还没有登录if (user == null) {servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);return;} else {// 让程序继续往下访问用户的目标资源filterChain.doFilter(servletRequest,servletResponse);}}
}

配置:

<!--filter 标签用于配置一个 Filter 过滤器-->
<filter><!--给 filter 起一个别名--><filter-name>AdminFilter</filter-name><!--配置 filter 的全类名--><filter-class>com.atguigu.filter.AdminFilter</filter-class>
</filter>
<!--filter-mapping 配置 Filter 过滤器的拦截路径-->
<filter-mapping><!--filter-name 表示当前的拦截路径给哪个 filter 使用--><filter-name>AdminFilter</filter-name><!--url-pattern 配置拦截路径/ 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录/admin/* 表示请求地址为:http://ip:port/工程路径/admin/*--><url-pattern>/admin/*</url-pattern>
</filter-mapping>

2.Filter过滤的整个生命周期

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

3.Filter的一些配置

和servlet一样,filter也可以配置一些东西。

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

web.xml里面配置初始化参数

<!--filter 标签用于配置一个 Filter 过滤器-->
<filter><!--给 filter 起一个别名--><filter-name>AdminFilter</filter-name><!--配置 filter 的全类名--><filter-class>com.atguigu.filter.AdminFilter</filter-class><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>url</param-name><param-value>jdbc:mysql://localhost3306/test</param-value></init-param>
</filter>

如何在filter类里面获取:

@Override
public void init(FilterConfig filterConfig) throws ServletException {System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化");// 1、获取 Filter 的名称 filter-name 的内容System.out.println("filter-name 的值是:" + filterConfig.getFilterName());// 2、获取在 web.xml 中配置的 init-param 初始化参数System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));// 3、获取 ServletContext 对象System.out.println(filterConfig.getServletContext());
}

4.FilterChain 过滤器链

整个过滤器流程,同时,在web.xml里面的配置顺序代表了整个过滤流程的顺序。
在这里插入图片描述

5.拦截路径

精确匹配
/target.jsp
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp

目录匹配
/admin/
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/

后缀名匹配
.html
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到
.do
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到
*.action
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到
Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!
请记住,可以同时配置多个。

ThreadLocal

ThreadLocal 的作用,它可以解决多线程的数据安全问题。
ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
ThreadLocal 的特点:
1、ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
2、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个
ThreadLocal 对象实例。
3、每个 ThreadLocal 对象实例定义的时候,一般都是 static 类型
4、ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放。

1.一个小实践

//创建
public static ThreadLocal threadLocal = new ThreadLocal();
//绑定
threadLocal.set(i);
//获取
Object o = threadLocal.get();

public class ThreadLocalTest {// public static Map<String,Object> data = new Hashtable<String,Object>();//创建public static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();private static Random random = new Random();public static class Task implements Runnable {@Overridepublic void run() {// 在 Run 方法中,随机生成一个变量(线程要关联的数据),然后以当前线程名为 key 保存到 map 中Integer i = random.nextInt(1000);// 获取当前线程名String name = Thread.currentThread().getName();System.out.println("线程["+name+"]生成的随机数是:" + i);// data.put(name,i);//绑定threadLocal.set(i);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}new OrderService().createOrder();// 在 Run 方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作// Object o = data.get(name);//获取Object o = threadLocal.get();System.out.println("在线程["+name+"]快结束时取出关联的数据是:" + o);}}public static void main(String[] args) {for (int i = 0; i < 3; i++){new Thread(new Task()).start();}}
}

2.书城项目是要求利用Filter和ThreadLocal是组合管理事务。

这里涉及线程的知识,啊啊啊,忘得差不多了。
使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成。
主要的改动在JDBC,然后设置Filter来统一处理提交和回滚。同时要记得千万要抛出异常,才能实现回滚。
在这里插入图片描述
JDBC里改动,要创建ThreadLocal绑定conn。然后设置提交和回滚。

public class JdbcUtils {private static DruidDataSource dataSource;private static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();static {try {Properties properties = new Properties();// 读取 jdbc.properties 属性配置文件InputStream inputStream =JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");// 从流中加载数据properties.load(inputStream);// 创建 数据库连接 池dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取数据库连接池中的连接* @return 如果返回 null,说明获取连接失败<br/>有值就是获取连接成功*/public static Connection getConnection(){Connection conn = conns.get();if (conn == null) {try {conn = dataSource.getConnection();//从数据库连接池中获取连接conns.set(conn); // 保存到 ThreadLocal 对象中,供后面的 jdbc 操作使用conn.setAutoCommit(false); // 设置为手动管理事务} catch (SQLException e) {e.printStackTrace();}}return conn;}/*** 提交事务,并关闭释放连接*/public static void commitAndClose(){Connection connection = conns.get();if (connection != null) { // 如果不等于 null,说明 之前使用过连接,操作过数据库try {connection.commit(); // 提交 事务} catch (SQLException e) {e.printStackTrace();} finally {try {connection.close(); // 关闭连接,资源资源} catch (SQLException e) {e.printStackTrace();}}}// 一定要执行 remove 操作,否则就会出错。(因为 Tomcat 服务器底层使用了线程池技术)conns.remove();}/*** 回滚事务,并关闭释放连接*/public static void rollbackAndClose(){Connection connection = conns.get();if (connection != null) { // 如果不等于 null,说明 之前使用过连接,操作过数据库try {connection.rollback();//回滚事务} catch (SQLException e) {e.printStackTrace();} finally {try {connection.close(); // 关闭连接,资源资源} catch (SQLException e) {e.printStackTrace();}}}// 一定要执行 remove 操作,否则就会出错。(因为 Tomcat 服务器底层使用了线程池技术)conns.remove();}
}

其他部分Dao

catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);
}

利用FIlter:给所有的 Service 方法都加上 try-catch。来进行实现的管理。
在这里插入图片描述

public class TransactionFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {try {filterChain.doFilter(servletRequest,servletResponse);JdbcUtils.commitAndClose();// 提交事务} catch (Exception e) {JdbcUtils.rollbackAndClose();//回滚事务e.printStackTrace();}}
}
在 web.xml 中的配置:
<filter><filter-name>TransactionFilter</filter-name><filter-class>com.atguigu.filter.TransactionFilter</filter-class>
</filter>
<filter-mapping><filter-name>TransactionFilter</filter-name><!-- /* 表示当前工程下所有请求 --><url-pattern>/*</url-pattern>
</filter-mapping> 

BaseServlet 中的异常往外抛给 Filter 过滤器

public abstract class BaseServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {doPost(req, resp);}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {// 解决 post 请求中文乱码问题// 一定要在获取请求参数之前调用才有效req.setCharacterEncoding("UTF-8");String action = req.getParameter("action");try {// 获取 action 业务鉴别字符串,获取相应的业务 方法反射对象Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class,HttpServletResponse.class);// System.out.println(method);// 调用目标业务 方法method.invoke(this, req, resp);} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);// 把异常抛给 Filter 过滤器}}
}

友好的错误代码展示

也是在xml文件中配置。

<!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
<error-page><!--error-code 是错误类型--><error-code>500</error-code><!--location 标签表示。要跳转去的页面路径--><location>/pages/error/error500.jsp</location>
</error-page>
<!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
<error-page><!--error-code 是错误类型--><error-code>404</error-code><!--location 标签表示。要跳转去的页面路径--><location>/pages/error/error404.jsp</location>
</error-page>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/469457.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

专业140+总分420+东北大学841通信专业基础考研经验东大电子信息与通信工程,真题,大纲,参考书。

今年考研顺利上岸&#xff0c;被东北大学通信工程录取&#xff0c;其中专业课841通信专业基础140&#xff0c;数二140&#xff0c;总分420&#xff0c;整体每门课都还是比较均衡&#xff0c;刚开始考研前也和大家一样&#xff0c;焦虑&#xff0c;紧张&#xff0c;面对考研怕失…

人工智能时代

一、人工智能发展历史:从概念到现实 人工智能(Artificial Intelligence,简称AI)是计算机科学领域中一门旨在构建能够执行人类智能任务的系统的分支。其发展历程充满曲折,从概念的提出到如今的广泛应用,是技术、理论和实践相互交织的产物。 1. 起源(20世纪中期) 人工智…

【C++函数探幽】内联函数inline

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1. 前言2.概念3.特性…

计算机网络概述习题拾遗

学习目标&#xff1a; 自下而上第一个提供端到端服务的层次 路由器、交换机、集线器实现的功能层 TCP/IP体系结构的网络接口层对应OSI体系结构的哪两个层次 分组数量对总时延的影响 如果这篇文章对您有帮助&#xff0c;麻烦点赞关注支持一下动力猿吧&#xff01; 学习内容…

力扣hot3--并查集+哈希

第一想法是排个序然后遍历一遍&#xff0c;but时间复杂度就超啦 并查集居然与哈希结合了&#xff08;&#xff09; 已经好久没用过并查集了&#xff0c;&#xff0c;&#xff0c;我们用哈希表f_node中来记录原结点的父节点&#xff0c;其中key是原结点&#xff0c;value是父节点…

CFS三层靶机

参考博客&#xff1a; CFS三层内网靶场渗透记录【详细指南】 - FreeBuf网络安全行业门户 CFS三层靶机搭建及其内网渗透【附靶场环境】 | TeamsSix CFS三层网络环境靶场实战 - PANDA墨森 - 博客园 (cnblogs.com) CFS三层靶机实战--内网横向渗透 - 知乎 (zhihu.com) CFS靶机…

【STM32 CubeMX】STM32中断体系结构

文章目录 前言一、中断体系的比喻二、中断的内部结构2.1 EXTI触发方式 2.2 NVIC2.3 cpu与中断2.4 外部中断控制器框图上升沿触发选择寄存器屏蔽/使能寄存器等待处理寄存器 2.5 中断优先级 总结 前言 一、中断体系的比喻 STM32中断体系如下图所示&#xff1a; 一座大型建筑物…

【计算机网络】链路层

透明传输&#xff1a; 指的是链路层首部尾部定位时为防止数据中有相同数据导致错误判定&#xff0c;所以使用转义字符&#xff0c;对于用户察觉不到转义字符的存在。 信道分类&#xff1a; 1.广播信道 广播信道为避免冲突&#xff0c;使用两种方式进行协调&#xff0c;一是信道…

PyTorch深度学习快速入门教程 - 【小土堆学习笔记】

小土堆Pytorch视频教程链接 声明&#xff1a; 博主本人技术力不高&#xff0c;这篇博客可能会因为个人水平问题出现一些错误&#xff0c;但作为小白&#xff0c;还是希望能写下一些碰到的坑&#xff0c;尽力帮到其他小白 1 环境配置 1.1 pycharm pycharm建议使用2020的&…

高中生护眼台灯怎么选?教育部认可护眼灯品牌

随着孩子步入更高的年级&#xff0c;学业压力也会越来越繁重&#xff0c;随之带来的也是更长时间的用眼和高近视率。众所周知&#xff0c;高中是孩子学业最繁忙的一段时期&#xff0c;同时也是青少年近视的重灾区&#xff0c;不少学生因为每天过度用眼&#xff0c;再加上缺少户…

MySQL主从环境,主库改端口后,从库如何操作?

主库&#xff1a;mysql-111 从库&#xff1a;mysql-112 主库由3306端口修改成3307后&#xff0c; 从库执行如下命令 mysql> stop slave; mysql> change master to master_port3307; mysql> CHANGE MASTER TO MASTER_HOST192.168.10.111,MASTER_USERbeifen,MASTER_PA…

【Win10 触摸板】在插入鼠标时禁用触摸板,并在没有鼠标时自动启用触摸板。取消勾选连接鼠标时让触摸板保持打开状态,但拔掉鼠标后触摸板依旧不能使用

出现这种问题我的第一反应就是触摸板坏了&#xff0c;但是无意间我换了一个账户发现触摸板可以用&#xff0c;因此推断触摸板没有坏&#xff0c;是之前的账户问题&#xff0c;跟系统也没有关系&#xff0c;不需要重装系统。 解决办法&#xff1a;与鼠标虚拟设备有关 然后又从知…