目录
一.过滤器作用
二.Filter对象的创建
三.在Filter中设置请求编码
四.FilterConfig对象的使用
五.FilterChain(过滤器链)
六.基于注解式开发Filter
?七.Filter的生命周期 ?
一.过滤器作用
Filter
过滤器是
Servlet2.3
中所提供的一个过滤请求与响应的对象。
Filter
过滤器既可以对客户端向服务器端发送的请求进行过滤,也可以对服务器端向客户端产生的响应进行过滤处理。
二.Filter对象的创建
创建一个
Class
实现
Filter
接口,并实现接口中三个抽象方法。
- init()方法:初始化方法,在创建Filter后立即调用。可用于完成初始化动作。
- doFilter()方法:拦截请求与响应方法,可用于对请求和响应实现预处理。
- destroy()方法:销毁方法,在销毁Filter之前自动调用。可用于完成资源释放等动作。
容器启动时,就会创建Filter对象,Filter对象被实例化后会立即调用init函数,容器关闭时,才会销毁Filter对象。
FirstFilter.java:
package com.first.filter;
import javax.servlet.*;
import java.io.IOException;
public class FirstFilter implements Filter {
/*
当Filter对象被实例化后,会立即调用的一个方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Init......");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//对请求进行处理
System.out.println("请求被过滤");
//对请求做放行处理
filterChain.doFilter(servletRequest,servletResponse);
//对响应进行处理
System.out.println("响应被过滤");
}
/*
当Filter对象在销毁之前会调用一次该方法
*/
@Override
public void destroy() {
}
}
配置web.xml:
配置和servlet的配置差不多,放在<web-app>标签内
路径配置为/test/*,和上节的AnnotationServlet.java路径一样,给此servlet过滤
<filter>
<filter-name>firstFilter</filter-name>
<filter-class>com.first.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/test/*</url-pattern>
</filter-mapping>
输出:
控制台输出:
请求被过滤
响应被过滤
三.在Filter中设置请求编码
需求:在
Filter
中实现对请求的编码的设置。
实际应用原因:因为当有多个servlet接受客户端请求时,而此时客户端的数据都包含了中文,如果一个个servlet去单独设置编码的话效率太低,所以可以直接在过滤器中设置编码!
控制台如果乱码的话那就是请求编码没设置。
以之前添加用户的例子(戳这里)稍加修改做演示:
getRequestDataServlet.java:
package com.first.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/*
获取请求数据
*/
public class getRequestDataServlet extends HttpServlet {
@Override
//客户端是以post方式传递的数据,所以这里要用doPost函数
//Tomcat拿到请求后会对请求做解析,解析出的数据会放到req对象当中
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求编码,这个必须放在获取请求数据之前,否则无效
//将请求编码注释掉,检测Filter的作用
//req.setCharacterEncoding("utf-8");
//获取用户名
String username=req.getParameter("username");
//获取用户密码
String password=req.getParameter("password");
//获取复选框中被选中的数据
String[] hobbies=req.getParameterValues("hobbies");
//转化为列表
List<String> list= Arrays.asList(hobbies);
//获取表单中的所有的key
Enumeration<String> parameterNames=req.getParameterNames();
List<String> paraList=new ArrayList<>();
while(parameterNames.hasMoreElements()){
paraList.add(parameterNames.nextElement());
}
//使用Map结构获取提交数据
Map<String,String[]> parameterMap=req.getParameterMap();
Iterator<Map.Entry<String,String[]>> iterator=parameterMap.entrySet().iterator();
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
pw.println("username:"+username);
//在控制台输出username,看是否乱码
//System.out.println(username);
pw.println("password:"+password);
pw.println("hobbies:"+list);
pw.println("all_key:"+paraList);
while(iterator.hasNext()){
Map.Entry<String,String[]> entry=iterator.next();
String key=entry.getKey();
String[] value=entry.getValue();
//要转化成列表再输出,直接输出value输出的是数组的地址
pw.println(key+" = "+Arrays.asList(value));
}
pw.flush();
pw.close();
}
}
addUser.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--action加个../是为了从test目录里跳出,最前面加个/是因为Context Path用了绝对路径/,
所以在最前面才可以加/,也可以不加/-->
<form action="getRequestData.do" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
爱好:<input type="checkbox" name="hobbies" value="sports">体育
<input type="checkbox" name="hobbies" value="music">音乐
<input type="checkbox" name="hobbies" value="art">艺术<br>
<input type="submit" value="OK">
</form>
</body>
</html>
配置web.xml:
路径配置为/*,即匹配所有路径
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.first.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EncodingFilter.java:
package com.first.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置请求编码
servletRequest.setCharacterEncoding("utf-8");
//对请求做放行处理
filterChain.doFilter(servletRequest,servletResponse);
}
}
输出:
控制台输出的username也没乱码,可见配置成功!
四.FilterConfig对象的使用
FilterConfig对象是用来读取<filter>
中<init-param>
初始化参数的对象。该对象通过参数传递到init方法中,用于读取初始化参数。
filterConfig.getInitParameter("name")
通过
name
获取对应的
value
。
filterConfig.getInitParameterNames()
返回该
Filter中所有<param-name>
中的值。
?
对上一个编码的例子进行改造
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.first.filter.EncodingFilter</filter-class>
<!-- 通过修改<param-value>达到灵活设置请求编码的功能-->
<init-param>
<param-name>code</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EncodingFilter.java:
package com.first.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
//设置默认编码
private String defaultCode = "utf-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String code=filterConfig.getInitParameter("code");
// 如果web.xml中没有配置编码,那么就使用默认编码
if (code!=null && code.length()>0){
this.defaultCode = code;
}
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置请求编码
servletRequest.setCharacterEncoding(this.defaultCode);
//对请求做放行处理
filterChain.doFilter(servletRequest,servletResponse);
}
}
可以再运行addUser.html测试一下。
五.FilterChain(过滤器链)
Filter
技术的特点是在对请求或响应做预处理时,可实现
“
插拔式
”
的程序设计。我们可以根据自己需求添加多个
Filter
,也可以根据需求
去掉某个
Filter
,通过修改
web.xml
文件即可实现。那么如果有多个
过滤器对某个请求及响应进行过滤,那么这组过滤器就称为过滤器
链。
Filter
执行顺序
则按照在
web.xml
文件中配置的上下顺序来决定先后。在上的先执行,在下的后执行。
?
六.基于注解式开发Filter
Filter
支持注解式开发,通过
@WebFilter
注解替代
web.xml
中
Filter的配置。
使用注解式开发
Filter
时,执行顺序会根据
Filter
的
名称
进行排序的结果决定调用的顺序,即按字典序的是顺序排序。
当web.xml文件和注解都配置了Filter时,web.xml文件里面的配置优先级更高。
配置示例:
和servlet注解配置大同小异
?
?七.Filter的生命周期 ?
Filter
的生命周期是由容器管理的。当容器启动时会实例化
Filter
并调用
init
方法完成初始化动作。当客户端浏览器发送请求时,容器会
启动一个新的线程来处理请求,如果请求的
URL
能够被过滤器所匹
配,那么则先调用过滤器中 的
doFilter
方法,再根据是否有
chain.doFilter
的指令,决定是否继续请求目标资源。当容器关闭时
会销毁
Filter
对象,在销毁之前会调用
destroy
方法。
?
|