过滤器
过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse 进行处理的一个对象。过滤器可以用于登录,加密和解密,会话检查,图片转换等等。过滤器可以配置为拦截一个或多个资源。
过滤器配置可以通过注解或者部署描述符来完成。如果同一个资源或同一组资源中应用了多个过滤器,则其调用顺序有时候显得比较重要,这时候就需要用到部署描述符。
核心接口/类:
Filter,FilterConfig,FilterChain。
过滤器类必须实现Filter接口;接口定义了三个方法:init,doFilter,destroy。
void init(FilterConfig filterConfig)
当过滤器启动时,比如应用程序启动时,Servlet容器就会调用init方法。不用等到调用与过滤器相关的资源之后,才调用init方法。这个方法只调用一次,并且应该包含该过滤器的初始化代码。
void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)
每次调用与过滤器相关的资源时,Servlet容器都会调用Filter实例的doFilter 方法。该方法会收到一个ServletRequest,ServletResponse和FilterChain。
doFilter的实现可以访问 ServletRequest和ServletResponse。因此,可以在ServletRequest中添加属性,或者在ServletResponse中添加一个标头。甚至可以对ServletRequest或者ServletResponse进行修改,改变他们的行为。doFilter方法实现的最后一行代码应该是调用FilterChain(作为doFilter方法的第三个参数)中的doFilter方法:
filterChain.doFilter(request,response)
一个资源可以与多个过滤器(更专业地说,是一条过滤器链)关联,FilterChain.doFilter()通常会引发调用链中的下一个过滤器被调用。在链中的最后一个过滤器中调用FilterChain.doFilter会引发资源本身被调用。如果没有在Filter.doFilter方法实现代码的最后调用FilterChain.doFilter方法,那么程序的处理将会在这个地方停止,并且不会调用请求。
注意,doFilter方法是FilterChain接口中唯一的方法。它与Filter中的doFilter方法稍有不同。在FilterChain中,doFilter只有两个参数,而不是三个。
除非一个过滤器类在部署描述符的多个filter元素中进行了申明,否则Servlet容器将只给每一类过滤器创建一个实例。由于Servlet/JSP应用程序通常是多用户的应用程序,因此可以同时通过多个线程访问一个过滤器实例,但你必须谨慎处理好多线程的问题。
过滤器的配置
配置过滤器的目标如下:
-
确定过滤器要拦截哪些资源
-
要传给过滤器init方法的启动初始值。
-
给过滤器起个名字
FilterConfig 接口允许通过其getServletContext方法访问ServletContext
ServletContext getServletContext();
String getFilterName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
配置过滤器有两种方法。一种是利用WebFilter注解类型,一种通过部署描述符注册来配置。
范例如下:
package cn.com.yuns.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* 日志过滤器
*
* @author wsq
* @version LoggingFilter.java 2020/7/30 上午8:28 下午
*/
@WebFilter(filterName = "LoggingFilter", urlPatterns = {"/*"}, initParams = {
@WebInitParam(name = "logFileName", value = "log.txt"),
@WebInitParam(name = "prefix", value = "URI: ")
})
public class LoggingFilter implements Filter {
private PrintWriter logger;
private String prefix;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String prefix = filterConfig.getInitParameter("prefix");
this.prefix = prefix;
String logFileName = filterConfig.getInitParameter("logFileName");
String appPath = filterConfig.getServletContext().getRealPath("/");
System.out.println("logFileName:" + logFileName);
try {
logger = new PrintWriter(new File(appPath, logFileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new ServletException(e.getMessage());
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LoggingFilter doFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURI());
logger.flush();
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("destroy File");
if (logger != null) {
logger.close();
}
}
}
package cn.com.yuns.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "ImageProtectorFilter", urlPatterns = {"*.png", "*.jpg", "*.gif","*.jpeg"})
public class ImageProtectorFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("ImageProtectorFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String referer = httpServletRequest.getHeader("referer");
System.out.println("referer:" + referer);
if (referer != null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
throw new ServletException("Image not Available");
}
}
}
package cn.com.yuns.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author wsq
* @version DownloadCounterFilter.java 2020/7/30 上午9:50 下午
*/
@WebFilter(filterName = "DownloadCounterFilter", urlPatterns = {"/*"})
public class DownloadCounterFilter implements Filter {
ExecutorService executors = Executors.newSingleThreadExecutor();
Properties downloadLog;
File logFile;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DownloadCounterFilter");
String appPath = filterConfig.getServletContext().getRealPath("/");
logFile = new File(appPath, "downloadLog.txt");
if (!logFile.exists()) {
try {
logFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
downloadLog = new Properties();
try {
downloadLog.load(new FileReader(logFile));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
final String uri = httpServletRequest.getRequestURI();
executors.execute(new Runnable() {
@Override
public void run() {
String propertie = downloadLog.getProperty(uri);
if (null == propertie) {
downloadLog.setProperty(uri, "1");
} else {
int count = 0;
try {
count = Integer.parseInt(propertie);
} catch (Exception e) {
}
count++;
downloadLog.setProperty(uri, Integer.toString(count));
try {
downloadLog.store(new FileWriter(logFile), "");
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
executors.shutdown();
}
}
<%--
Created by IntelliJ IDEA.
User: wsq
Date: 2020/7/30
Time: 9:24 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Image</title>
</head>
<body>
<a href="image/888.png">程序代码</a><br><br>
<a href="image/linyin.jpeg">凛音桃花1</a><br><br>
<a href="image/520.jpeg">凛音桃花1</a><br><br>
<a href="image/sx.jpeg">松下纱荣子</a><br><br>
</body>
</html>
过滤器的顺序
如果多个过滤器应用于同一个资源,那么调用顺序就很重要,必须用部署描述符管理应该先调用哪一个过滤器。假如Filter1必须在Filter2之前调用,那么在部署描述符中,Filter 的 申明就要放在 Filter2的申明之前。
<filter>
<filter-name>Filter1</filter-name>
<filter-class>Filter1</filter-class>
<init-param>
<param-name>qqqq</param-name>
<param-value>qqq</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>Filter2</filter-class>
<init-param>
<param-name>www</param-name>
<param-value>wwwww</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
网友评论