Servlet规范:Servlet Filter Listener
1.Filter
可以拦截对资源的访问
一个过滤器可以拦截多个资源,一个资源也可能被多个过滤器所拦截
所谓的拦截就是将代表请求的request对象和代表响应的response对象拦截下来
拦截下来后可以控制是否允许访问资源,或在资源访问之前或之后做一些额外的操作
2.开发过滤器的步骤
写一个类实现Filter接口
当服务器启动web应用加载后会立即创建出当前web应用中的所有过滤器对象,创建出来后立即调用init方法执行初始化的操作,从此以后驻留在内存中为后续的拦截服务,每次拦截都会造成dofilter方法的执行。直到服务器关闭或web应用移除出容器时,随着应用的销毁,过滤器被销毁,销毁之前调用destory方法执行善后工作。
init(FilterConfig config)
FilterConfig:代表当前过滤器在web.xml中的配置信息
获取过滤器的初始化参数
获取ServletContext对象
dofilter(request,response,FilterChain chain)
FilterChain:代表拦截当前资源的过滤器链对象,一个资源可能被多个过滤器所拦截,拦截的顺序取决于Filter的<filter-mapping>的配置顺序。那么按照过滤器的拦截顺序,就组成一个拦截的链,按照顺序取连接资源。
FilterChain提供了一个叫doFilter的方法,一旦调用就表示放行当前过滤器,执行过滤器链的下一个节点,如果下一个节点仍然是一个过滤器,则接着进行过滤器,如果后续没有其他过滤器放行到最重要访问的资源。
需要注意的是放行资源有点像方法调用,之后的代码仍然会执行。
destory
在web.xml中配置过滤器
<filter> -- 配置一个过滤器
<filter-name>FirstFilter</filter-name> -- 过滤器的名字
<filter-class>com.tarena.filter.FirstFilter</filter-class> -- 过滤器的类
</filter>
<filter-mapping> -- 过滤器的拦截路径配置,可以配置多个
<filter-name>FirstFilter</filter-name> -- 为哪个名字的过滤器配置
<url-pattern>/*</url-pattern> -- 拦截哪个路径资源可以配置多个
<servlet-name>XxxServlet</servlet-name> -- 拦截哪个名字的Servlet
<dispatcher></dispatcher> -- 指定过滤器拦截哪种方式对资源的访问,可以取值为REQUEST FORWARD INCLUDE ERROR,如果不配置,默认只拦截REQUEST方式的访问。可以配置多个。
</filter-mapping>
3.过滤器的应用场景一:全站乱码解决过滤器
4.30天内自动登录过滤器
5.MD5 - 加密 - 数据摘要(数据指纹)算法
任意长度的二进制数据经过md5加密算法的计算,将会得到一个128位的二进制数一般转为32位16进制数来表示
原文不相同算出的md5一定不相同
原文相同算出md5一定相同
只能从原文算成密文,密文永远也算不回原文
********************************************************************************************
========================================================
=======================================================
1. Filter
1.1. 过滤器概念
1.1.1. 过滤器的基本概念
Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
1.1.2. 过滤器的功能
如图-1所示:
图-1
(1)过滤器可以拦截对资源的访问
(2)一个过滤器可以拦截多个资源,一个资源也可能被多个过滤器拦截
(3)所谓的拦截是根据访问的URL地址来确定访问的是哪个资源,确定是否拦截
(4)所谓的拦截其实就是拦截下来代表请求的request和响应的response
(5)拦截后:控制是否允许访问、访问之前和之外做一些额外操作
1.2. 过滤器开发入门
1.2.1. 开发过滤器的两个步骤
想要开发一个过滤器,需要如下两个步骤。
(1)写一个类实现Filter接口
(2)在web.xml中配置过滤器
1.2.2. 写一个类实现javax.servlet.Filter接口
如图-2所示:
图-2
init为初始化方法,在Filter对象被创建出来时,Servlet容器会调用该方法对filter进行初始化。
destory为销毁的方法,在过滤器对象被销毁之前,服务器会调用这个方法执行善后工作。
doFilter为过滤器中最核心的方法,当过滤器拦截到对资源的访问时,服务器会自动调用该方法执行过滤代码。 我们只需要在这个方法中设计过滤器的逻辑代码即可。
其中FilterConfig代表当前过滤器在web.xml中的配置。
FilterChain代表过滤器链。
一个资源可能被多个过滤器所拦截,拦截的顺序是按照这些过滤器的<filter-mapping>在web.xml中的配置顺序所决定
所有拦截当前资源的过滤器按照拦截顺序就组成了一个拦截器链,filterchain,代表的就是当前拦截器链.filterchain对象提供了一个dofilter的方法,一旦执行这个方法,表明当前过滤器放行,执行过滤器链的下一个节点,如果下一个节点没有过滤器了,就执行真正要访问的资源。
1.2.3. 在web.xml中配置一下过滤器
<filter> --- 配置过滤器
<filter-name>FirstFilter</filter-name>
---为过滤器起一个名字
<filter-class>com.itheima.filter.FirstFilter</filter-class>
---过滤器类的全路径名
<init-param>
--- 可选的 可以配置多个 过滤器的初始化参数 可以在过滤器中通过FilterConfig对象来获取
<param-name>name1</param-name>
<param-value>value1</param-value>
</init-param>
</filter>
<filter-mapping>
--- 配置过滤器的拦截路径 ,一个<Filter>可以配置多个<filter-mappint>
<filter-name>FirstFilter</filter-name>
---为哪个过滤器进行配置
<url-pattern>/*</url-pattern>
--- 拦截哪个路径 其中url-pattern的写法和学习Serlvet时的url-pattern的写法相同 这个url-pattern可以配置多个
<servlet-name>Demo1Servlet</servlet-name>
---拦截哪个名字的Servlet 可以配置多个
<dispatcher>REQUEST</dispatcher>
--- 配置拦截哪种类型的对资源的访问,可选的值有REQUEST FORWARD INCLUDE ERROR,如果不配置默认只拦截REQUEST方式,如果具体配置了就拦截具体配置的方式的对资源的访问,此标签可以配置多个
</filter-mapping>
1.3. Filter的生命周期
1.3.1. Filter的生命周期
当服务器启动,web应用加载后,立即创建出这个web应用中的所有过滤器对象,创建出来后立即调用过滤器的init方法执行初始化操作.从此这些过滤器对象驻留在内存中为后续的拦截进行服务.每当拦截到资源时,都会导致dofilter方法执行.最终直到服务器关闭或web应用移除出容器时,随着web应用的销毁,过滤器对象销毁,销毁之前调用destory方法执行善后工作。
1.4. FilterConfig接口
1.4.1. Filterconfig接口
用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。
1.4.2. Filterconfig接口提供的方法
FilterConfig提供的方法:
String getFilterName():得到filter的名称。
String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
public ServletContext getServletContext():返回Servlet上下文对象的引用。
1.5. EasyMall全站乱码解决过滤器
1.5.1. 全站乱码过滤器
我们可以开发一个Filter,拦截所有的动态web资源,在动态web资源执行之前,解决好乱码,从而一劳永逸的解决全站乱码问题。
对于响应数据乱码,只需要设置Content-Type即可解决乱码。
对于请求参数乱码,如果是POST提交,可以一行代码解决,如果是GET提交需要手动的编解码解决乱码。
1.5.2. 代码实现
如图-3所示:
图-3
<filter>
<description>全站乱码过滤器</description>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.itheima.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.6. EasyMall实现30天内自动登录
1.6.1. 30天自动登录
想要实现自动登录,需要通过Cookie保存用户名密码在客户端,然后通过过滤器拦截请求,对于未登录而带有自动登录cookie且自动登录cookie中保存的用户名密码都正确则在放行资源之前做自动登录操作。
如图-4所示:
图-4
<filter>
<description>自动登录过滤器</description>
<filter-name>AutologinFilter</filter-name>
<filter-class>com.itheima.filter.AutologinFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutologinFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.7. MD5
1.7.1. MD5概述
用户名密码保存在客户端是一种十分危险的行为。所以需要进行加密后保存。
其中MD5就是一种比较常用的加密算法。
与其说MD5算法是一种加密算法,不如说是一种数据指纹(数据摘要)算法。
其特点如下:
任意大小的二进制数经过MD5计算后都能得到一个独一无二的128位二进制数。
不同的数据算出的MD5绝对不相同。
相同的数据算出的MD5一定相同。
只能有明文算出密文,密文是永远也无法算成明文的。
MD5大量应用于计算机中。如数据库中保存的密码通常都是经过MD5加密后的数据。如用户下载文件时可以进行MD5校验防止数据被篡改。
在记住用户名案例中,我们可以使用MD5进行加密后再保存在客户端,从而保证数据安全。
在数据库中保存的密码也不宜直接存储为明文。也要经过MD5加密后存储。
1.7.2. JAVA实现MD5加密
/** * 使用md5的算法进行加密 */ public static String md5(String plainText) { byte[] secretBytes = null; try { secretBytes = MessageDigest.getInstance("md5").digest( plainText.getBytes()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("没有md5这个算法!"); } String md5code = new BigInteger(1, secretBytes).toString(16); for (int i = 0; i < 32 - md5code.length(); i++) { md5code = "0" + md5code; } return md5code; }
2. Listener
1.
2.
2.1. Servlet监听器概述
1.
2.
2.1.
2.1.1. Servlet监听器概述
JavaEE中提供了八大监听器,用来监听Servlet中指定事件。
2.1.2. Servlet事件监听器步骤
实现web开发中的事件监听功能需要两个步骤:
(1)写一个类实现对应接口。
(2)在将写好的监听器类注册到web.xml中。
1.
2.
2.1.
2.2. 监听三个作用域对象创建和销毁的监听器
2.2.
2.2.1. ServletContextListener 详解
ServletContextListener 监听器用于监听 ServletContext 对象的创建和销毁。
ServletContext域的生命周期:
服务器启动,web应用加载后,立即创建代表当前web应用的ServletContext对象,从此驻留在内存中,直到服务器关闭或web应用被移除出容器时,ServletContext对象被销毁。
2.2.2. HttpSessionListener详解
HttpSessionListener监听器用于监听HttpSession对象的创建和销毁。
HttpSession域的生命周期:
在第一次调用request.getSession()方法时创建。
超时过30分钟没人用(此时间可以在web.xml中修改)被销毁。
调用session.invalidate()方法被销毁。
服务器非正常关闭时销毁。
那么,当如果服务器是正常关闭,session会如何处置呢?
未超时的session会以文件的形式保存在服务器中,这个过程叫做session的钝化。在下一次服务器正常启动时,session还可以恢复回来,这个过程叫做session的活化。
*注意:想要随着session被钝化(活化)的对象,他的类必须实现Serializable接口。
作用范围:整个会话范围。
2.2.3. ServletRequestListener 详解
ServletRequestListener监听器用于监听ServletRequest对象的创建和销毁。
ServletRequest对象的生命周期:
请求开始,服务器创建代表这次请求的reuqest对象.
请求结束,服务器销毁代表请求的request对象。
1.
2.
2.1.
2.2.
2.3. 监听域属性变化的监听器
2.3.1. 监听域属性变化的监听器
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。
2.3.2. 监听域属性变化的监听器中的方法
(1)attributeAdded 方法
当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象。
(2)attributeRemoved 方法
当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行相应。
(3)attributeReplaced 方法
当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应。
1.
2.
2.1.
2.2.
2.3.
2.4. 监听JAVABEAN在Session域中状态变化的监听器
2.4.1. Javabean在Session中的状态
保存在 Session 域中的对象可以有多种状态:
(1)绑定到 Session 中。
(2)从Session 域中解除绑定。
(3)随Session 被钝化
(4)随Session被活化
2.4.2. 监听JAVABEAN在Session域中状态变化的监听器
Servlet 规范中定义了两个特殊的监听器来使javabean感知自己在Session域中状态的变化:
(1)HttpSessionBindingListener接口
实现了HttpSessionBindingListener接口的 JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件。
//当对象被绑定到 HttpSession 对象中时触发
void valueBound(HttpSessionBindingEvent event)
//当对象从 HttpSession 对象中解除绑定时触发
void valueUnbound(HttpSessionBindingEvent event)
(2)HttpSessionActivationListener接口
实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件。
//当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被钝化时触发
sessionWillPassivate(HttpSessionBindingEvent event)
//当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被活化时触发
void sessionDidActive(HttpSessionBindingEvent event)方法。