可以对调用servlet容器的过程进行拦截,用于在servlet进行响应前后进行实现一些特殊功能。
实例
servlet程序
代码语言:javascript复制import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/servlet")
public class servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("this is servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("this is servlet");
}
}
filter程序
代码语言:javascript复制import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class filter implements Filter{
// 初始化时被调用
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter out = servletResponse.getWriter();
out.println("this is filter");
}
// 销毁时调用
@Override
public void destroy() {
}
}
index.jsp
代码语言:javascript复制<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>filter</title>
</head>
<body>
<jsp:forward page="servlet" />
</body>
</html>
最后在web.xml文件中配置filter拦截的servlet容器,还可以使用通配符拦截用户请求的所有资源。
代码语言:javascript复制<filter>
<filter-name>filter</filter-name>
<filter-class>filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/servlet</url-pattern>
</filter-mapping>
运行之后在首页显示的是this is servlet,这种情况下好像并没有拦截请求。直接访问servlet时显示的时this is filter完成了拦截。因为使用forward()方式访问,而web.xml中并没有配置filter拦截的servlet资源被调用的方式。
拦截不同方式的请求
那么如何让filter拦截forward()方式的资源请求呢?
在filter-mapping元素中有一个特殊的子元素dispatcher,指定被拦截servlet资源的请求方式。修改web.xml的配置
代码语言:javascript复制<filter>
<filter-name>filter</filter-name>
<filter-class>filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/servlet</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
再次访问index.jsp,可以看到显示的是this is filter
,成功拦截了forward()方式的资源请求。
dispatcher元素的值有四个
- REQUEST :Request.Dispathcer.include()和Request.Dispathcer.forward()方法调用将不会使用过滤器
- INCLUDE:Request.Dispathcer.include()方法调用
- FORWARD:Request.Dispathcer.forward()方法调用
- ERROR:声明异常处理机制调用
Filter链
当多个Filter链对同一个url进行请求过滤时,这些Filter就组成了一个过滤器链。
在上面的实例增加一个filter2程序
代码语言:javascript复制import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class filter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter out = servletResponse.getWriter();
out.println("before<br>");
filterChain.doFilter(servletRequest, servletResponse);
out.println("after<br>");
}
@Override
public void destroy() {
}
}
修改filter程序
代码语言:javascript复制import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class filter implements Filter{
// 初始化时被调用
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter out = servletResponse.getWriter();
out.println("this is filter<br>");
filterChain.doFilter(servletRequest, servletResponse);
}
// 销毁时调用
@Override
public void destroy() {
}
}
配置web.xml
代码语言:javascript复制<filter>
<filter-name>filter</filter-name>
<filter-class>filter</filter-class>
</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/servlet</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/servlet</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
在web.xml中,filte的filter-mapping声明在filter2前面,因此在filter链当中filter首先被调用。用户的请求首先被filter拦截,再被filter2拦截。
程序的执行结果如下
首先调用了filter,然后调用filter2输出before,filter2再放行请求,调用了filter2上层的servlet容器,最后filter2输出了after。
FilterConfig接口
用于获取Filter程序在web.xml中的配置信息
声明 | 描述 |
---|---|
String getFilterName() | 返回web.xml中设置的filter-name |
String getInitParameter(String name) | 返回web.xml中设置的某个初始化参数 |
Enumeration getInitParameterNames() | 返回web.xml中设置的所有初始化参数名称的集合 |
ServletContext getServletContext () | 返回FilterConfig对象中封装的ServletContext对象 |