Filter概述

Filter意为滤镜或者过滤器,用于在Servlet之外对request或者response进行修改。Filter提出了过滤链的概念。一个FilterChain包括多个Filter。客户端请求request在抵达Servlet之前会经过FilterChian里的所有Filter,服务器响应response在从Servlet抵达客户端浏览器之前也会经过FileterChain里的所有Filter。Filter处理过程如图所示。

Filter接口

一个Filter必须实现javax.servlet.Filter接口。Filter有三个方法。

public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
} void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; default void destroy() {
}
}

这三个方法反映了Filter的生命周期,其中init与dstory只会被调用一次,分别在web程序加载和卸载的时候调用。而doFilter()方法每次有客户端请求时都会被调用一次。Filter的所有工作集中在doFilter方法中,另外可从init方法传入的filterConfig对象得到filter的初始化参数。

下面是Filter的一个简单实现。

public class TestFilter implements Filter {
public void destroy() {
System.out.println("我被销毁了");
} public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("在请求到达Servlet之前我输出了");
chain.doFilter(req, resp);
System.out.println("在响应到达客户端之前我输出了");
} public void init(FilterConfig config) throws ServletException {
System.out.println("我被初始化了");
//得到初始化数据
String value1 = config.getInitParameter("name1");
String value2 = config.getInitParameter("name2");
System.out.println(value1 + " " + value2);
} }

chain.doFilter(req, resp)将request递交给下一个FilterChain的下一个Filter,如果都走完了则交给Servlet处理。

Filter配置

Filter需要在web.xml或@WebFilter注解中配置才能生效。Filter的配置与Servlet的配置非常类似。

在web.xml中需要配置<filter>与<filter-mapping>标签。

<filter>
<filter-name>filtername</filter-name>
<filter-class>filter.TestFilter</filter-class>
<init-param>
<param-name>paraName</param-name>
<param-value>paraValue</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filtername</filter-name>
<url-pattern>*.do</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

<filter>配置Filter名称,实现类,和初始化参数,可同时配置多个初始化参数,<filter-mapping>配置在什么规则下使用Filter,这两者的filter-name必须匹配。

<url-pattern>配置URL的规则,可以配置多个,可以使用通配符()。例如"/jsp/"适用于本contextPath下以"/jsp"开头的Serlvet,"*.do"适用于所有以".do"结尾的Servlet路径。

<dispatcher>配置到达Servlet的方式。有四种取值:REQUEST,FORWORD,INCLUDE,ERROR。可以同时配置多个<dispatcher>,如果没有配置<dispatcher>,默认为REQUEST。它们的区别为:

  • REQUEST:表示仅当直接请求Servlet时才生效。
  • FORWORD:表示仅当某Servlet通过FORWARD到该Servlet时才生效。
  • INCLUDE:JSP中可以通过jsp:include/请求某Servlet,仅在这种情况下有效。
  • ERROR:JSP中可以通过<%@ page errorPage="error.jsp" %>指定错误处理页面,仅在这种情况下有效。

注意:一个Web程序可以配置多个Filter,这多个Filter的执行顺序有先有后,规则是<filter-mapping>配置在前面的Fliter执行要早与配置在后面的Filter,多个Filter之间可能会相互影响。

在@WebFilter注解中配置,这样就简单多了

@WebFilter(
filterName = "MyFilter",
urlPatterns = "*.do",
initParams = {
@WebInitParam(name="paramName", value = "paramValue")
},
dispatcherTypes = REQUEST
)

应用:字符过滤器

在Servlet里获取请求参数时经常遇到乱码问题,在每个Servlet里处理编码问题就非常麻烦,可以利用过滤器统一处理字符编码问题。你肯定会想到亲自实现那个HttpServletRequest接口,但是如果自己实现的话,要重写里面所有的方法,非常麻烦,所以java提供了HttpServletRequestWrapper类,它已经帮你实现了httpServletRequest接口,你只需要重写你想要重新定义的方法即可。

/**
增强了所有的获取参数的方法
request.getParameterValues("name");
request.getParameter("name");
request.getParameterMap();
*/
class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
private boolean flag = true;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
} @Override
public String getParameter(String name) {
if(name==null || name.trim().length()==0){
return null;
}
String[] values = getParameterValues(name);
if(values==null || values.length==0){
return null;
}
return values[0];
} @Override
public String[] getParameterValues(String name) {
if(name==null || name.trim().length()==0){
return null;
}
Map<String, String[]> map = getParameterMap();
if(map==null || map.size()==0){
return null;
}
return map.get(name);
} @Override
public Map<String,String[]> getParameterMap() { /**
* 首先判断请求方式
* 若为post request.setchar...(utf-8)
* 若为get 将map中的值遍历编码就可以了
*/
String method = request.getMethod();
if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}else if("get".equalsIgnoreCase(method)){
Map<String,String[]> map = request.getParameterMap();
if(flag){
for (String key:map.keySet()) {
String[] arr = map.get(key);
//继续遍历数组
for(int i=0;i<arr.length;i++){
//编码
try {
arr[i]=new String(arr[i].getBytes("iso-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
flag=false;
}
return map;
}
return super.getParameterMap();
} }

接着编写EncodeFilter过滤器,对请求的文本进行编码处理。

/**
* 统一编码
*/
@WebFilter(
filterName = "EncodingFilter",
urlPatterns = "/*"
)
public class EncodingFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse) resp;
chain.doFilter(new MyRequest(request), response);
} @Override
public void destroy() { } }

Java Web(四) 过滤器Filter的更多相关文章

  1. 【java web】过滤器filter

    一.过滤器简介 过滤器filter依赖于servlet容器 所谓过滤器顾名思义是用来过滤的,Java的过滤器能够为我们提供系统级别的过滤,也就是说,能过滤所有的web请求, 这一点,是拦截器无法做到的 ...

  2. Java Web之过滤器(Filter)

    转: Java Web之过滤器(Filter) 2018年07月31日 16:58:40 喻志强 阅读数 13705更多 所属专栏: Java Web入门   版权声明:本文为博主原创文章, 转载请注 ...

  3. Java Web使用过滤器防止Xss攻击,解决Xss漏洞

    转: Java Web使用过滤器防止Xss攻击,解决Xss漏洞 2018年11月11日 10:41:27 我欲乘风,直上九天 阅读数:2687   版权声明:本文为博主原创文章,转载请注明出处!有时候 ...

  4. JAVA入门[15]-过滤器filter

    一.过滤器 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的: 在客户端的请求访问后端资源之前,拦截这些请求. 在服务器的响应发送回客户端之前,处理这些响应. 参考:http:/ ...

  5. java web(四):request、response一些用法和文件的上传和下载

    上一篇讲了ServletContent.ServletCOnfig.HTTPSession.request.response几个对象的生命周期.作用范围和一些用法.今天通过一个小项目运用这些知识.简单 ...

  6. Java基础95 过滤器 Filter

    1.filter 过滤器的概述 filter过滤器:是面向切面编程的一种实现策略,在不影响原来的程序流程的前提下,将一些业务逻辑切入流程中,在请求达到目标之前进行处理,一般用于编码过滤.权限过滤... ...

  7. 初学Java Web(8)——过滤器和监听器

    什么是过滤器 过滤器就是 Servlet 的高级特性之一,就是一个具有拦截/过滤功能的一个东西,在生活中过滤器可以是香烟滤嘴,滤纸,净水器,空气净化器等,在 Web 中仅仅是一个实现了 Filter ...

  8. Java Web学习总结(29)——Java Web中的Filter和Interceptor比较

    1. 背景 在设计web应用的时候,用户登录/注册是必不可少的功能,对用户登录信息进行验证的方法也是多种多样,大致可以认为如下模式:前端验证+后台验证.根据笔者的经验,一般会在前端进行一些例如是否输入 ...

  9. java web(四)文件上传与下载

     一.文件上传原理 1.在TCP/IP中,最早出现的文件上传机制是FTP ,它是将文件由客户端发送到服务器的标准机制:但是在jsp使用过程中不能使用FTP方法上传文件,这是由jsp运行机制所决定. 通 ...

随机推荐

  1. 手动添加jar包到maven仓库

    引言: 虽然配置了maven以后可以通过索引的方式自动下载jar包到本地maven仓库,从而使项目中直接使用本地仓库里面的架包, 但是这一招并不是每一次都灵应,也有遇到了失败的时候,当遇到失败的时候, ...

  2. linux JAVA_HOME和 java -version不匹配

    ~/.bashrc 中更新了jdk, JAVA_HOME 起效果了,但是java -version还是老的. 原因是/usr/bin/java   和usr/bin/javac是一个链接,得改. 使用 ...

  3. easyUI tree 自定义图标

    文章转载自: https://blog.csdn.net/zhlantian/article/details/52913115 近期由于项目中需要使用easyui tree树形列表,并在系统中动态配置 ...

  4. 神兽保佑代码无bug O(∩_∩)O

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  5. Linux 各种软件的安装-ElasticSearch

    安装elasticSearch之前先将一个问题: 重启服务器后发现 ssh上不去了,后来采用另外一种方式登录进去发现 sshd服务没启动. 解决过程:先查看sshd的状态 service sshd s ...

  6. Feign二: @FeignClient 接口调用

    在项目的启动文件加入:@EnableFeignClients 注解, import org.springframework.boot.SpringApplication; import org.spr ...

  7. 雷林鹏分享:jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点

    jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点 通常表示一个树节点的方式就是在每一个节点存储一个 parentid. 这个也被称为邻接列表模型. 直接加载这些数据到树形菜单(Tree ...

  8. 单细胞数据高级分析之消除细胞周期因素 | Removal of cell cycle effect

    The normalization method described above aims to reduce the effect of technical factors in scRNA-seq ...

  9. ionic3 打包一个已签名的apk

    1 进入ionic官方文档,点击左边导航菜单,找到INTRO下的Deploying2 终端进入项目目录(根据项目环境定是否需要root权限)3 运行命令ionic cordova build andr ...

  10. Android Error:Could not find lottie.jar

    Android Error:Could not find lottie.jar 今天遇到了一个及其头疼的问题 同事的工程导到我的电脑里却报错,错误是找不到jcenter仓库里的lottie.jar包 ...