Servlet技术规范 描述三种技术 : Servlet(服务器小程序) 、Filter(过滤器) 、Listener(监听器) 
 
Filter运行在服务器端,对服务器端web资源的访问 进行拦截,起到过滤的作用  
 
Servlet API中 定义接口 Filter,用户只需要编写程序实现Filter接口,完成过滤器编写  
 
Filter快速入门 
1、编写类 实现 Filter接口 
2、在服务器端注册 Filter (配置拦截哪个web资源) ----- web.xml  
  <!-- 注册过滤器 --> 
  <filter> 
          <filter-name>Filter1</filter-name> 
          <filter-class>cn.itcast.filter.Filter1</filter-class> 
  </filter>         
  <!-- 配置过滤器去拦截哪个资源 --> 
  <filter-mapping> 
          <filter-name>Filter1</filter-name> 
          <url-pattern>/hello.jsp</url-pattern> 
  </filter-mapping>         
 
3、客户端访问被拦截目标资源之前,服务器调用Filter的doFilter方法 ,执行过滤 
4、Filter的doFilter方法中传入 FilterChain, 如果调用FilterChain的doFilter 就会执行目标资源,否则目标资源不会执行  
chain.doFilter(request, response); 
 
FilterChain 
在客户端访问服务器web资源时,服务器端为一个web资源,配置多个过滤器拦截 ,这多个过滤器,就会组成过滤器链 FilterChain, 调用FilterChain的doFilter 表示要执行过滤器链下一个资源,如果当前过滤器已经是链上最后一个过滤器,就会执行目标资源  
 
* web服务器根据Filter在web.xml文件中的注册顺序<mapping>,决定先调用哪个Filter 
 
Filter生命周期 init(FilterConfig) doFilter(request,response,filterChain) destroy()  
1、Filter对象在tomcat服务器启动时 创建,调用init方法  (只会创建一个对象,init方法执行一次) 
2、doFilter 每次拦截目标资源时,执行 
3、destroy 服务器关闭时执行  
 
FilterConfig 作用和 ServletConfig 类似,用来在Filter初始化阶段,将参数传递给过滤器 
1、通过  String getInitParameter(String name)  获得过滤器初始化参数  
2、通过 ServletContext getServletContext() 获得ServletContext对象  
* FilterConfig 提供参数,是Filter类私有参数,Filter2的初始化参数,不能在Filter1 中进行获取  
* 配置全局参数,<context-param> 进行配置,通过ServletContext 获得  
 
<filter-mapping> 过滤器拦截配置 
1、如果连接目标资源是一个Servlet,可以选择url和servlet名称两种配置方式  
<!-- 拦截/hello是Servlet 路径 --> 
<url-pattern>/hello</url-pattern> 
<!-- 拦截Servlet 还可以通过Servlet 名称进行拦截 --> 
<servlet-name>HelloServlet</servlet-name> 
2、url-pattern 和 Servlet中路径写法一样,有三种 : 完全匹配、目录匹配、扩展名匹配 
3、<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式 
容器调用服务器端资源 有四种方式  
REQUEST、FORWARD、INCLUDE、ERROR 
 
========================================================================================================================================= 
Filter应用  
 
应用一:统一全站字符编码过滤器  
案例:编写jsp 输入用户名,在Servlet中获取用户名,将用户名输出到浏览器上  
 
处理请求post乱码代码 
request.setCharacterEncoding("utf-8"); 
设置响应编码集代码 
response.setContentType("text/html;charset=utf-8"); 
 
经常会使用,而过滤器可以在目标资源之前执行,将很多程序中处理乱码公共代码,提取到过滤器中 ,以后程序中不需要处理编码问题了  
 
应用二:禁止浏览器缓存动态页面的过滤器 
因为动态页面数据,是由程序生成的,所以如果有缓存,就会发生,客户端查看数据不是最新数据情况 ,对于动态程序生成页面,设置浏览器端禁止缓存页面内容  
 
response.setDateHeader("Expires",-1); 
response.setHeader("Cache-Control","no-cache"); 
response.setHeader("Pragma","no-cache"); 
 
将禁用缓存代码,提起到过滤器中,通过url配置,禁用所有JSP页面的缓存  
 
应用三:控制浏览器缓存静态web资源 
Tomcat缓存策略  
 
对于服务器端经常不变化文件,设置客户端缓存时间,在客户端资源缓存时间到期之前,就不会去访问服务器获取该资源 -------- 比tomcat内置缓存策略更优手段  
* 减少服务器请求次数,提升性能  
 
设置静态资源缓存时间,需要设置 Expires 过期时间 ,在客户端资源没有过期之前,不会产生对该资源的请求的  
* 设置Expires 通常使用 response.setDateHeader 进行设置 设置毫秒值  
 
=============================================================================================================================================== 
应用四:自动登陆过滤器 
在访问一个站点,登陆时勾选自动登陆(三个月内不用登陆),操作系统后,关闭浏览器;过几天再次访问该站点时,直接进行登陆后状态  
 
在数据库中创建 user表 
 
create table user ( 
   id int primary key auto_increment, 
   username varchar(20), 
   password varchar(40), 
   role varchar(10) 
); 
 
insert into user values(null,'admin','123','admin'); 
insert into user values(null,'aaa','123','user'); 
insert into user values(null,'bbb','123','user'); 
 
自动登陆 :未登录、存在自动登陆信息、自动登陆信息正确  
 
在用户完成登陆后,勾选自动登陆复选框,服务器端将用户名和密码 以Cookie形式,保存在客户端 。当用户下次访问该站点,AutoLoginFilter 过滤器从Cookie中获取 自动登陆信息  
1、判断用户是否已经登陆,如果已经登陆,没有自动登陆的必要 
2、判断Cookie中是否含有自动登陆信息 ,如果没有,无法完成自动登陆 
3、使用cookie用户名和密码 完成自动登陆  
 
如果将用户密码保存在cookie文件中,非常不安全的 ,通常情况下密码需要加密后才能保存到客户端  
* 使用md5算法对密码进行加密  
* md5 加密算法是一个单向加密算法 ,支持明文---密文 不支持密文解密  
 
MySQL数据库中提供md5 函数,可以完成md5 加密 
mysql> select md5('123');  
+----------------------------------+ 
| md5('123')                       | 
+----------------------------------+ 
| 202cb962ac59075b964b07152d234b70 | 
+----------------------------------+ 
解密后结果是32位数字 16进制表示  
 
Java中提供类 MessageDigest 完成MD5加密 
 
------------------------------------------------------------------ 
将数据表中所有密码 变为密文 update user set password = md5(password) ; 
在Demo4Servlet 登陆逻辑中,对密码进行md5 加密  
在AutoLoginFilter 因为从Cookie中获得就是加密后密码,所以登陆时无需再次加密  
 
 
------------------------------------------------------------------ 
MD5 在2004 年被王小云破解,md5算法是多对一加密算法,出现两个加密后相同密文的明文很难发现 ,王小云并没有研究出md5 解密算法,研究出一种提高碰撞概率的算法  
 
------------------------------------------------------------------- 
应用五:过滤器实现URL级别权限认证 
系统中存在很多资源,将需要进行权限控制的资源,放入特殊路径中,编写过滤器管理访问特殊路径的请求,如果没有相应身份和权限,控制无法访问  
 
认证:who are you ? 用户身份的识别 ------------ 登陆功能 
权限:以认证为基础 what can you do ? 您能做什么? 必须先登陆,才有身份,有了身份,才能确定可以执行哪些操作  
 
===================================================================================================================================================== 
Filter高级应用 
 
Decorator模式  
1、包装类需要和被包装对象 实现相同接口,或者继承相同父类 
2、包装类需要持有 被包装对象的引用  
在包装类中定义成员变量,通过包装类构造方法,传入被包装对象  
3、在包装类中,可以控制原来那些方法需要加强 
不需要加强 ,调用被包装对象的方法 
需要加强,编写增强代码逻辑  
 
ServletRequestWrapper 和 HttpServletRequestWrapper 提供对request对象进行包装的方法,但是默认情况下每个方法都是调用原来request对象的方法,也就是说包装类并没有对request进行增强  
 
在这两个包装类基础上,继承HttpServletRequestWrapper ,覆盖需要增强的方法即可  
 
应用六:完全解决get和post乱码的过滤器  
在Filter中,对request对象进行包装,增强获得参数的方法  
getParameter  
getParameterValues 
getParameterMap  
 
 
ServletResponseWrapper 和 HttpServletResponseWrapper 提供了对response 对象包装,继承 HttpServletResponseWrapper ,覆盖需要增强response的方法  
 
应用七:增强Response对象,对响应数据进行压缩 
复习:Tomcat服务器内,提供对响应压缩 配置实现  
在conf/server.xml 中  
<Connector port="80" protocol="HTTP/1.1"  
               connectionTimeout="20000"  
               redirectPort="8443"/> 添加 compressableMimeType 和 compression 
没有压缩 :  00:00:00.000        0.063        7553        GET        200        text/html        http://localhost/ 
 
<Connector port="80" protocol="HTTP/1.1"  
               connectionTimeout="20000"  
               redirectPort="8443" compressableMimeType="text/html,text/xml,text/plain" compression="on"/> 
 
压缩后 :  00:00:00.000        0.171        2715        GET        200        text/html        http://localhost/  
Content-Encoding: gzip 
Content-Length : 2715 
 
实际开发中,很多情况下,没有权限配置server.xml  ,无法通过tomcat配置开启gzip 压缩 
 
编写过滤器对响应数据进行gzip压缩  
 
flush 方法 
只有没有缓冲区字节流,FileOutputStream 不需要flush  
而字节数组ByteArrayOutputStream、字节包装流、字符流 需要flush ----- 这些流在调用close方法时都会自动flush  
 
================================================================================================================== 
过滤器  
1、过滤器编写步骤   
2、全局编码、禁用缓存、设置过期时间 过滤器  
3、自动登陆/URL级别权限控制 --- 必须掌握 *****  
4、通用get/post乱码过滤器和响应压缩过滤器  ------------ 理解实现过程 ,保存起来会使用  
 
客户信息系统增删改查必备  
掌握分页查询原理  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 |   
        
 
    
    
    
     
 
 |