2.12 Filter介绍
使用Filter完整的流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后
Filter再对服务器响应进行后处理。
用处:
1.在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest.
2.根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
3.在HttpServletResponse到达客户端之前,拦截HttpServletResponse.
4.根据需要HttpServletResponse,也可以修改HttpServletResponse头和数据。

种类:
用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
日志Filter:详细记录某些特殊的用户请求。
负责解码的Filter:包括对非标准编码的请求编码。
能改变XML内容的XSLT Filter等
Filter可负责拦截多个请求或响应;一个请求或响应也可被多个Filter拦截。

步骤:
创建Filter处理类。
web.xml文件中配置Filter.

2.12.1 创建Filter类
创建Filter必须实现javax.servlet.Filter接口。
> void init(FilterConfig config);
> void destroy();
> void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);

ex:
@WebFilter(filtName="log", urlPatterns={"/*"})
public class LogFilter implements Filter{
   //FilterConfig可用于访问Filter的配置信息
   private FilterConfig config;
   //实现初始化方法
   public void init(FilterConfig config){
       this.config = config;
   }
   //实现销毁方法
   public void destroy(){
       this.config = null;
   }
   //执行过滤的核心方法
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throw IOException, ServletExceptioin{
       //----下面代码用于对用户请求执行预处理----
       //获取ServletContext对象,用于记录日志
       ServletContext context = this.config.getServletContext();
       long before = System.currentTimeMillis();
       //将请求转换成HttpServletRequest请求
       HttpServletRequest hrequest = (HttpServletRequest)request;
       //输出提示信息
       System.out.println("Filter已经截获到用户的请求的地址: "+
                          hrequest.getServletPath());
       //Filter只是链式处理,请求依然放行到目的地址
       chain.doFilter(request, response);
       //----下面代码用于对服务器响应执行后处理----
       long after =  System.currentTimeMillis();
       //输出提示信息
       System.out.println("过滤结束");
       //输出提示信息
       System.out.println("请求被定位到"+hrequest.getRequestURI()+" 所花的时间为:
                           "+(after-before));
   }
}

2.12.2 配置Filter
配置两个部分:
>配置Filter名
>配置Filter拦截URL模式。

配置可以使用两种方式:
>在Filter类中通过Annotation进行配置
>在web.xml文件中通过配置文件进行配置

@WebFilter常用属性:
asyncSupported
dispatchTypes
displayName
filterName
initParams
servletNames
urlPatterns/value

web.xml:
<filter>
   <filter-name>log</filter-name>
   <filter-class>lee.LogFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>log</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

2.12.3 使用URL Rewrite实现网站伪静态
可以通过Filter拦截所有发向*.html请求,然后按某种规则将请求forward到实际的*.jsp页面即可。
具体信息参考http://tuckey.org/urlrewrite/

2.13 Listener介绍
ServletAPI提供了大量监听器来监听Web应用的内部事件,从而允许Web内部事件发生时回调事件监听器内的方法。
步骤:
定义Listener实现类。
通过Annotation或在web.xml文件中配置Listener.

2.13.1 实现Listener类
Web事件监听器接口:
ServletContextListener:监听Web应用的启动和关闭
ServletContextAttributeListener:application范围内属性的变化
ServletRequestListener:监听用户请求
ServletRequestAttributeListener:监听request内属性的改变
HttpSessionListener:监听用户session的开始和结束
HttpSessionAttributeListener:监听session范围内属性的变化

ServletContextListener:
contextInitialized(ServletContextEvent sce);
contextDestroyed(ServletContextEvent sce);

2.13.2 配置Listener
方式:
使用@WebListener修饰Listener实现类即可。
在web.xml文档中使用<listener.../>元素进行配置。

<listener>
   <listener-class>lee.GetConnListener</listener-class>
</listener>

2.13.3 使用ServletContextAttributeListener
attributeAdded(ServletContextAttributeEvent event);
attributeRemoved(ServletContextAttributeEvent event);
attributeReplaced(ServletContextAttributeEvent event);

2.13.4 使用ServletRequestListener和ServletRequestAttributeListener
ServletRequestListener:
requestInitialized(ServletRequestEvent sre);
requestDestroyed(ServletRequestEvent sre);

ServletRequestAttributeListener:
attributeAdded(ServletRequestAttributeEvent event);
attributeRemoved(ServletRequestAttributeEvent event);
attributeReplaced(ServletRequestAttributeEvent event);

2.13.5 使用HttpSessionListener和HttpSessionAttributeListener
HttpSessionListener:
sessionCreated(HttpSessionEvent se);
sessionDestroyed(HttpSessionEvent se);

HttpSessionAttributeListener:
attributeAdded
attributeRemoved
attributeReplaced

2.14 JSP2特性
新特性:
直接配置JSP属性
表达式语言
简化的自定义标签API
Tag文件语法

2.14.1 配置JSP属性
<jsp-property-group/>
是否允许使用表达式语法:<el-ignored/>
是否允许使用JSP脚本:<script-invalid/>
声明JSP页面的编码:<page-encoding/>
使用隐式包含:<include-prelude/>和<include-coda/>
ex:
<?xml version="1.0" encoding="GBK"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   version="3.0">
   <!-- 关于JSP的配置信息 -->
   <jsp-config>
       <jsp-property-group>
           <!-- 对哪些文件应用配置 -->
           <url-pattern>/noscript/*</url-pattern>
           <!-- 忽略表达式语法 -->
           <el-ignored>true</el-ignored>
           <!-- 页面编码的字符集 -->
           <page-encoding>GBK</page-encoding>
           <!-- 不允许使用java脚本 -->
           <scripting-invalid>true</scripting-invalid>
           <!-- 隐式导入页面头  -->
           <include-prelude>/inc/top.jspf</include-prelude>
           <!-- 隐式导入页面尾 -->
           <include-coda>/inc/bottom.jspf</include-coda>
       </jsp-property-group>
       <jsp-property-group>
           <!-- 对哪些文件应用配置 -->
           <url-pattern>*.jsp</url-pattern>
           <el-ignored>false</el-ignored>
           <!-- 页面编码字符集 -->
           <page-encoding>GBK</page-encoding>
           <!-- 允许使用java脚本 -->            
           <scripting-invalid>false</scripting-invalid>
       </jsp-property-group>
       <jsp-property-group>
           <!-- 对哪些文件应用配置 -->
           <url-pattern>/inc/*</url-pattern>
           <el-ignored>false</el-ignored>
           <!-- 页面编码字符集 -->
           <page-encoding>GBK</page-encoding>
           <scripting-invalid>true</scripting-invalid>
       </jsp-property-group>
   </jsp-config>

   <context-param>
       <param-name>author</param-name>
       <param-value>yeeku</param-value>
   </context-param>

</web-app>

2.14.2 表达式语言
数据访问语言
${expression}
1.表达式语言支持的算术运算符和逻辑运算符
+-*/% div mod == ?:
< lt > gt >= ge <= le == eq != ne
2.表达式的内置对象
pageContext:代表该页面的pageContext对象
pageScope:用于获取page范围的属性值
requestScope:用于获取request范围的属性值
sessionScope:用于获取session范围的属性值
applicationScope:用于获取application范围的属性值
param:用于获取请求的参数值
paramValues:获取属性值为数组的属性值
header:用于获取请求头的属性值
headerValues:获取属性值为数组的属性值
initParam:用于获取请求Web应用的初始化参数
cookie:用于获取指定的Cookie值

3.表达式语言的自定义函数
开发步骤:
>开发函数处理类:若干个静态方法,每个静态方法可以定义为一个函数
public class Function{
   public static String reverse(String text){
       return new StringBuffer(text).reverse().toString().  
   }
   public static int countChar(String text){
       return text.length();
   }
}
>使用标签库定义函数:
ex:
<function>
   <name>reverse</name>
   <function-class>lee.Functions</function-class>
   <function-signature>java.lang.String reverse(java.lang.String)</function-signature>
</function>
>在JSP页面的EL中使用函数:
<%@taglib prefix="crazyit" uri="http://www.crazy.org/tags"%>
${crazyit:reverse(param["name"])}

整个过程类似于自定义标签。

2.14.3 Tag File支持
TagFile是自定义标签的简化用法,使用Tag File可以无须定义标签处理类和标签库文件,但仍然可以在JSP页面中
使用自定义标签。
建立一个迭代器标签步骤:
1.建立Tag文件,格式类似于JSP文件。
Tag File具有5个指令:
taglib:导入其他标签库
include:导入其他JSP或者静态页面
tag:类似于JSP中的page指令
attribute:标签属性
variable:设置自定义标签的变量,这些变量传给JSP页面使用。
ex:
<%@ tag pageEncoding="GBK" import="java.util.List" %>
<%@ attribute name="bgColor"%>
<%@ attribute name="cellColor" %>
<%@ attribute name="title" %>
<%@ attribute name="bean" %>
<table border="1" bgcolor="${bgColor}">
<tr>
<td><b>${title}</b></td>
</tr>
<% List<String> list=(List<String>)request.getAttribute("a");
  for(Object ele : list) { %>
  <tr>
  <td bgcolor="${cellColor}" >
  <%=ele%>
  </td>
  </tr>
<%}%>
</table>

2.在页面中使用自定义标签是,需先导入标签库,在使用标签。
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
</tags:iterator bgColor="#99dd99" cellColor="#9999cc"
               title="迭代器标签" bean="a" />

Tag File只有以下内置对象:
request
response
session
application
config
out

2.15 Servlet 3.0新特性
2.15.1 Servlet3.0的Annotation
@WebServlet
@WebInitParam
@WebListener
@WebFilter
@MultipartConfig:修饰Servlet,指定Servlet将会负责处理multipart/form-data类型的请求(主要用于文件上传)
@ServletSecurity:JAAS,安全与授权控制
@HttpConstraint:和ServletSecurity一起使用。
@HttpMethodConstraint:和ServletSecurity一起使用。

2.15.2 Servlet3.0的Web模块支持
<webModule>.jar
   |--META-INFO
   |      |--web-fragment.xml
   |--Web模块所用的类文件、资源文件等。
web-fragment.xml文件:
<name.../>:指定Web模块的名称
<ordering.../>:用于指定加载Web模块的相对顺序

2.15.3 Servlet3.0提供的异步处理
Servlet3.0的异步处理是通过AsyncContext类来处理的,Servlet可通过ServletRequest的如下两个方法开启异步
调用、创建AsyncContext对象。
AsyncContext startAsync()
AsyncContext startAsync(ServletRequest, ServletResponse);

ex:
@WebServlet(urlPatterns="/async", asyncSupported=true)

AsyncContext actx = request.startAsync();
actx.setTimeout(30*1000);
actx.start(new Execute(actx));

当Servlet启动异步调用的线程之后,该线程的执行对开发者是透明的。
可借助AyncListener来监听。
onStartAsync(AsyncEvent event);
onComplete(AsyncEvent event);
onError(AysncEvent event);
onTimeout(AsyncEvent event);
注册使用:
actx.addListener(new MyAsyncListener());

2.15.4 改进的Servlet API
1.HttpServletRequest增加了对文件上传的支持。
Part getPart(String name)
Collection<Part> getParts()
表单结构:
<form method="post" action="upload" enctype="multipart/form-data">
文件名:<input type="text" id="name" name="name"/><br/>
选择文件:<input type="file" id="file" name="file"/><br/>
<input type="submit" value="上传"/><br/>
</form>

2.ServletContext允许通过编程的方式动态注册Servlet、Filter。
ServletContext提供了如下方法来动态的注册Servlet, Filter, 并允许动态设置Web应用的初始化参数。
addServlet
addFilter
addListener
setInitParameter(String name, String value)