Filter总结
简介
Filter中文意思为过滤器。顾名思义,过滤器可在浏览器以及目标资源之间起到一个过滤的作用,是JavaWeb的三大web组件之一:Servlet、Filter、Listener。当服务器收到特定的请求后,会先将请求交给过滤器,程序员可以在过滤器中对请求信息进行读取修改等操作,然后将请求信息再发送给目标资源。目标资源作出响应后,服务器会再次将响应转交给过滤器,在过滤器中同样可以对响应信息做一些操作,然后再将响应发送给服务器。在一个WEB应用中可以部署多个过滤器,多个过滤器就组成了一个过滤器链,请求和响应必须在经过多个过滤器后才能到达目标。
Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:在客户端的请求访问后端资源之前,拦截这些请求;在服务器的响应发送回客户端之前,处理这些响应。过滤器的使用场景有:身份验证过滤器;敏感词汇过滤;数据压缩过滤;加密过滤;触发资源访问事件过滤;图像转换过滤;日志记录和审核过滤;MIME-TYPE 链过滤;标记化过滤;XSL/T 过滤
Filter使用
右键–>new–>Filter,结构如下
@WebFilter(filterName = "Filter")
public class Filter implements javax.servlet.Filter {
public void destroy() { //销毁
}
//该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException { //初始化
}
}
注解配置Filter
使用value或者urlPatterns配置Filter的拦截资源:
1)拦截具体资源路径:/index.jsp
2)拦截目录:/user/*
3)后缀名拦截:*.jsp 访问后缀名为jsp的资源时过滤器被执行
4)拦截所有资源:/ * (没有空格)
urlPatterns = "/*"
initParams:配置初始化参数
initParams = {
@WebInitParam(name = "key",value = "value")
}
dispatcherTypes:配置拦截的类型,可配置多个,默认为DispatcherType.REQUEST,表示拦截直接请求的资源,DispatcherType.FORWARD表示拦截转发请求的资源,若要直接请求和转发请求的资源都拦截则把两个属性都写进来。
dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD}
web.xml配置Filter
<filter>
<filter-name>Filter</filter-name>
<filter-class>demo.Filter</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>tom</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Filter链
多个Filter组成Filter链,在注解中的执行顺序为比较类名字符串大小,小的先执行,在web.xml中按照filter-mapping的先后顺序执行。
Filter案例
验证登录
验证是否登录,如果登录了,直接放行,如果没有登录,则跳转到登录页面,提示用户登录。
package demo;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "Filter",urlPatterns = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class Filter implements javax.servlet.Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//强转
HttpServletRequest request = (HttpServletRequest) req;
//获取资源请求路径
String requestURI = request.getRequestURI();
//判断是否包含登录相关资源路径,要注意排除掉css/js/图片/验证码等资源
if (requestURI.contains("/login.jsp") || requestURI.contains("/loginServlet") || requestURI.contains("/css/") || requestURI.contains("/js/") || requestURI.contains("/fonts/") || requestURI.contains("/checkCodeServlet")) {
chain.doFilter(req, resp);
}else {
Object user = request.getSession().getAttribute("user");
if (user != null) {
chain.doFilter(req,resp);
}else {
request.setAttribute("login_msg","您尚未登录,请登录");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
}
}
// chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
过滤敏感词汇
对录入的词汇进行敏感词过滤,敏感词汇参考《敏感词汇.txt》,如果是敏感词汇,替换为****。
分析: 要使用动态代理对request对象进行增强。
package sensitivewords;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* 敏感词汇过滤器
*/
@WebFilter(filterName = "SensitiveWordsFilter",urlPatterns = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class SensitiveWordsFilter implements javax.servlet.Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//创建代理对象,增强getParameter方法
ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强getParameter方法
//判断是否是getParameter方法
if (method.equals("getParameter")) {
//增强返回值
//获取返回值
String value = (String) method.invoke(req,args);
if (value != null) {
for (String str : list) {
if (value.contains(str)) {
value = value.replaceAll(str,"****");
}
}
}
return value;
}
return method.invoke(req,args);
}
});
chain.doFilter(proxy_req, resp);
}
private List<String> list = new ArrayList<>();
public void init(FilterConfig config) throws ServletException {
try {
//加载文件
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
//读取文件
// BufferedReader br = new BufferedReader(new FileReader(realPath));
InputStreamReader isr = new InputStreamReader(new FileInputStream(realPath),"UTF-8");
BufferedReader br = new BufferedReader(isr);
//将文件的每一行数据添加到list中
String line = null;
while ((line = br.readLine()) != null) {
list.add(line);
}
br.close();
System.out.println(list);
}catch (Exception e){
e.printStackTrace();
}
}
}
测试servlet:
package sensitivewords;
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;
@WebServlet(urlPatterns = "/testServlet")
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response.setCharacterEncoding("UTF-8");
// response.setContentType("text/html;charset=UTF-8");
String name = request.getParameter("name");
String msg = request.getParameter("msg");
System.out.println(name+":"+msg);
response.getWriter().write(name+":"+msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}