第十九次课
什么是过滤器
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
实现第一个Filter程序
创建MyServlet
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out=response.getWriter();
out.print("Hello MyServlet ");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
创建MyFilter
用配置文件(web.xml)实现filter
1.先创建一个Filter类,该类要实现Filter接口
在idea中,点右键,新建Filter,输入文件名MyFilter1
MyFilter1:
public class MyFilter1 implements Filter {
public void destroy() {
//过滤器对象在销毁时自动调用,释放资源
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用
PrintWriter out=resp.getWriter();
out.write("HelloMyFilter");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//过滤器对象在初始化时调用,可以配置一些初始化参数
}
}
web.xml
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>filter.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
根元素用于注册一个Filter
<filter-name>
子元素用于设置Filter名称
<filter-class>
子元素用于设置Filter类的完整名称
<filter-mapping>
根元素用于设置一个过滤器所拦截的资源
<filter-name>
子元素必须 与中的子元素相同。
<url-pattern>
子元素用于匹配用户请求的URL.例如”/MyServlet”,这个URL还可以使用通配符””来表示,例如:“.do”适用于所有 以”.do” 结尾的Servlet路径。
运行http://localhost:8080/MyServlet
结果:HelloMyFilterHello MyServlet
用注解实现filter
@WebFilter("/MyServlet")
public class MyFilter2 implements Filter {
public void destroy() {
//过滤器对象在销毁时自动调用,释放资源
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用
PrintWriter out=resp.getWriter();
out.write("HelloMyFilter");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//过滤器对象在初始化时调用,可以配置一些初始化参数
}
}
Filter映射
使用通配符“*”拦截用户的所有请求
<url-pattern>
子元素用于匹配用户请求的URL.例如”/MyServlet”,这个URL还可以使用通配符””来表示,例如:“.do”适用于所有 以”.do” 结尾的Servlet路径。在注解中修改
@WebFilter("*.do")
public class MyFilter2 implements Filter {
public void destroy() {
//过滤器对象在销毁时自动调用,释放资源
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用
PrintWriter out=resp.getWriter();
out.write("HelloMyFilter2");
// chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//过滤器对象在初始化时调用,可以配置一些初始化参数
}
}
Filter链
在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以针对某一个URL进行拦截。如果多个Filter程序都对同一个URL进行拦截,那么这些Filter就会组成一个Filter链(也叫过滤器链)。Filter链用FilterChain对象来表示,FilterChain对象中有一个doFilter()方法,该方法的作用就是让Filter链上的当前过滤器允许,请求进入下一个Filter。
MyFilter01.java
public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {
//用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用
PrintWriterout=response.getWriter();
out.write("HelloMyFilter01<br/>");
chain.doFilter(request,response);
}
MyFilter02.java
public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {
//用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用
PrintWriterout=response.getWriter();
out.write("MyFilter02 Before<br/>");
chain.doFilter(request,response);
out.write("MyFilter02 After<br/>");
}
Web.xml
<filter>
<display-name>MyFilter01</display-name>
<filter-name>MyFilter01</filter-name>
<filter-class>cn.lctvu.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
<display-name>MyFilter02</display-name>
<filter-name>MyFilter02</filter-name>
<filter-class>cn.lctvu.filter.MyFilter02</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
注意:Filter链中各个Filter的拦截顺序与它们在Web.xml文件中元素的映射顺序一致,由于MyFilter01的元素位于MyFilter02的元素前面,因此用户的访问请求首先会被MyFilter01拦截,然后再被MyFilter02拦截。
在3.0之后新增@WebFilter注解,当使用注解配置多个Filter时,用户无法控制其执行顺序,此时Filter过滤的顺序是按照Filter的类名来控制的,按自然排序的规则。
FilterConfig接口
为了获取Filter程序在web.xml文件中的配置信息,Servlet API提供了一个FilterConfig接口,该接口封装了Filter程序在web.xml中的所有注册信息,并且提供了一系列获取这些配置信息的方法。
MyFilter03
public class MyFilter03 implements Filter {
private String characterEncoding;
FilterConfig fc;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 输出参数信息
characterEncoding=fc.getInitParameter("encoding");
System.out.println("encoding初始化参数值:"+characterEncoding);
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
this.fc=config;
}
}