Filter也称为过滤器,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制,页面的同一编码,过滤敏感词汇、压缩响应信息等一些高级功能!
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
看一下filter中有哪些方法!
<span style="font-size:18px;">public class Demo1Filter implements Filter {
//Filter 链的执行
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
}
//Init 方法在 Filter 生命周期中仅执行一次,web 容器在调用 init 方法时
public void init(FilterConfig filterConfig) throws ServletException {
}
//在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
public void destroy() {
}
}
</span>
我们先来看一下在访问资源的时候,他的执行过程!
在我们的web容器启动时在 web 应用程序启动时,web 服务器将根据 web.xml 文件中的配置信息来创建每个注册的 Filter 实例对象,并将其保存在服务器的内存中。然后当用户用浏览器请求一个页面的时候, 会先向web的容器发送一个请求,然后web容器在根据请求去找相应的资源!在找资源的时候,会先经过Filter,然后在继续向后执行,一个应用程序中可以有多个filter!filter 的执行的顺序跟在web.xml文件中配置的顺序是一样的!
下边我们通过一个实例来看一下filter是如何应用的!
web.xml配置
<!-- 编码过滤器 -->
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 请求url日志记录过滤器 -->
<filter>
<filter-name>logfilter</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>logfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
编码拦截器:
public class EncodingFilter implements Filter {
private String encoding;
private Map<String, String> params = new HashMap<String, String>();
// 项目结束时就已经进行销毁
public void destroy() {
System.out.println("end do the encoding filter!");
params=null;
encoding=null;
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//UtilTimerStack.push("EncodingFilter_doFilter:");
System.out.println("before encoding " + encoding + " filter!");
req.setCharacterEncoding(encoding);
// resp.setCharacterEncoding(encoding);
// resp.setContentType("text/html;charset="+encoding);
chain.doFilter(req, resp);
System.out.println("after encoding " + encoding + " filter!");
System.err.println("----------------------------------------");
//UtilTimerStack.pop("EncodingFilter_doFilter:");
}
// 项目启动时就已经进行读取
public void init(FilterConfig config) throws ServletException {
System.out.println("begin do the encoding filter!");
encoding = config.getInitParameter("encoding");
for (Enumeration e = config.getInitParameterNames(); e
.hasMoreElements();) {
String name = (String) e.nextElement();
String value = config.getInitParameter(name);
params.put(name, value);
}
}
}
日志拦截器:
public class LogFilter implements Filter {
FilterConfig config;
public void destroy() {
this.config = null;
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
// 获取ServletContext 对象,用于记录日志
ServletContext context = this.config.getServletContext();
//long before = System.currentTimeMillis();
System.out.println("before the log filter!");
//context.log("开始过滤");
// 将请求转换成HttpServletRequest 请求
HttpServletRequest hreq = (HttpServletRequest) req;
// 记录日志
System.out.println("Log Filter已经截获到用户的请求的地址:"+hreq.getServletPath() );
//context.log("Filter已经截获到用户的请求的地址: " + hreq.getServletPath());
try {
// Filter 只是链式处理,请求依然转发到目的地址。
chain.doFilter(req, res);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("after the log filter!");
//long after = System.currentTimeMillis();
// 记录日志
//context.log("过滤结束");
// 再次记录日志
//context.log(" 请求被定位到" + ((HttpServletRequest) req).getRequestURI()
// + "所花的时间为: " + (after - before));
}
public void init(FilterConfig config) throws ServletException {
System.out.println("begin do the log filter!");
this.config = config;
}
}
HelloServlet类:
public class HelloWorldServlet extends HttpServlet{
/**
* 查看httpservlet实现的service一看便知,起到了一个controll控制器的作用(转向的)
* 之后便是跳转至我们熟悉的doget,dopost等方法中
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("doservice..."+this.getInitParameter("encoding"));
super.service(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("doget...");
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("dopost...");
}
结果:
before encoding utf-8 filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/hello
doservice...UTF-8
doget...
dopost...
after the log filter!
after encoding utf-8 filter!
----------------------------------------
Filter生命周期
和Servlet一样Filter的创建和销毁也是由WEB服务器负责。不过与Servlet区别的是
1>在应用启动的时候就进行装载Filter类(与Servlet的load-on-startup配置效果相同)。
2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。
3>当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。
4>当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。
注意:init方法与destroy方法只会直接一次。
原文:https://www.cnblogs.com/chhhh/p/10591204.html