持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
在Filter的学习前,我们要先了解什么是Filter,Filter的作用是什么及是如何实现的,接下来就一起来学习!
一、Filter的定义
Filter拦截请求和响应,以便查看、提取或以某种方式操作正在客户端和服务器之间交换的数据。Filter可以改变一个请求(Request)或者是修改响应(Response)。Filter与Servlet的关联由Web应用的配置描述文件或注解来明确。用户发送请求给Servlet时,在Servlet处理请求之前,与此Servlet关联的Filter首先执行,然后才是Servlet的执行,Servlet执行完毕又会回到Filter。如果一个Servlet有多个Filter,则根据配置的先后次序依次执行。
二、Filter的应用
(1)访问特定资源(Web页、JSP页、Servlet)时的身份验证。
(2)访问资源的记录跟踪。
(3)访问资源的转换。
三、Filter的实现
一个Filter必须实现javax.Servlet.Filter接口,即实现下面的三个方法
(1)doFilter(ServletRequest, ServletResponse, FilterChain)。用来实现过滤行为的方法。引入的FilterChain对象提供了后续Filter所要调用的信息。
(2)init(FilterConfig)。由容器所调用的Filter初始化方法。容器确保在第一次调用doFilter方法前调用此方法,一般用来获取在web.xml文件中指定的初始化参数。
(3)destroy()。容器在破坏Filter实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。
四、实例
···
@WebFilter("/Main")
public class TimeTrackFilter implements Filter {
private static final boolean debug = true;
// The filter configuration object we are associated with. If
// this value is null, this filter instance is not currently
// configured.
private FilterConfig filterConfig = null;
/**
* Default constructor.
*/
public TimeTrackFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Date startTime, endTime;
double totalTime;
StringWriter sw = new StringWriter();
System.out.println("我在Filter中");
startTime = new Date();
chain.doFilter(request, response);
endTime = new Date();
totalTime = endTime.getTime() - startTime.getTime();
totalTime = totalTime;
System.out.println("我在Filter中");
PrintWriter writer = new PrintWriter(sw);
System.out.println("===============");
System.out.println("耗时: " + totalTime + " 毫秒");
System.out.println("===============");
// filterConfig.getServletContext().log(sw.getBuffer().toString());
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("init");
this.filterConfig = filterConfig;
if (filterConfig != null) {
if (debug) {
log("TimeTrackFilter:Initializing filter");
}
}
}
private void sendProcessingError(Throwable t, ServletResponse response) {
String stackTrace = getStackTrace(t);
if (stackTrace != null && !stackTrace.equals("")) {
try {
response.setContentType("text/html");
PrintStream ps = new PrintStream(response.getOutputStream());
PrintWriter pw = new PrintWriter(ps);
pw.print("<html>\n<head>\n<title>Error</title>\n</head>\n<body>\n"); // NOI18N
// PENDING! Localize this for next official release
pw.print("<h1>The resource did not process correctly</h1>\n<pre>\n");
pw.print(stackTrace);
pw.print("</pre></body>\n</html>"); // NOI18N
pw.close();
ps.close();
response.getOutputStream().close();
} catch (Exception ex) {
}
} else {
try {
PrintStream ps = new PrintStream(response.getOutputStream());
t.printStackTrace(ps);
ps.close();
response.getOutputStream().close();
} catch (Exception ex) {
}
}
}
public static String getStackTrace(Throwable t) {
String stackTrace = null;
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
sw.close();
stackTrace = sw.getBuffer().toString();
} catch (Exception ex) {
}
return stackTrace;
}
public void log(String msg) {
filterConfig.getServletContext().log(msg);
}
/**
* Return a String representation of this object.
*/
@Override
public String toString() {
if (filterConfig == null) {
return ("TimeTrackFilter()");
}
StringBuffer sb = new StringBuffer("TimeTrackFilter(");
sb.append(filterConfig);
sb.append(")");
return (sb.toString());
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public static boolean isDebug() {
return debug;
}
}
···
以上通过对Filter的实例学习,可以看到Filter是包裹在Servlet组件外面的一层防护网。在请求到达Servlet前后都会经过Filter的处理。