servlet高级-Filter过滤器

2023-10-21 11:26:50 浏览数 (2)

可以对调用servlet容器的过程进行拦截,用于在servlet进行响应前后进行实现一些特殊功能。

实例

servlet程序

代码语言:javascript复制
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;
import java.io.PrintWriter;

@WebServlet("/servlet")
public class servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.println("this is servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.println("this is servlet");
    }
}

filter程序

代码语言:javascript复制
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;

public class filter implements Filter{
//    初始化时被调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter out = servletResponse.getWriter();
        out.println("this is filter");
    }
//    销毁时调用
    @Override
    public void destroy() {

    }
}

index.jsp

代码语言:javascript复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>filter</title>
  </head>
  <body>
  <jsp:forward page="servlet" />
  </body>
</html>

最后在web.xml文件中配置filter拦截的servlet容器,还可以使用通配符拦截用户请求的所有资源。

代码语言:javascript复制
<filter>        
    <filter-name>filter</filter-name>        
    <filter-class>filter</filter-class>    
</filter>    
<filter-mapping>        
    <filter-name>filter</filter-name>        
    <url-pattern>/servlet</url-pattern>
</filter-mapping>

运行之后在首页显示的是this is servlet,这种情况下好像并没有拦截请求。直接访问servlet时显示的时this is filter完成了拦截。因为使用forward()方式访问,而web.xml中并没有配置filter拦截的servlet资源被调用的方式。

拦截不同方式的请求

那么如何让filter拦截forward()方式的资源请求呢?

在filter-mapping元素中有一个特殊的子元素dispatcher,指定被拦截servlet资源的请求方式。修改web.xml的配置

代码语言:javascript复制
<filter>        
    <filter-name>filter</filter-name>        
    <filter-class>filter</filter-class>    
</filter>    
<filter-mapping>        
    <filter-name>filter</filter-name>        
    <url-pattern>/servlet</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

再次访问index.jsp,可以看到显示的是this is filter,成功拦截了forward()方式的资源请求。

dispatcher元素的值有四个

  1. REQUEST :Request.Dispathcer.include()和Request.Dispathcer.forward()方法调用将不会使用过滤器
  2. INCLUDE:Request.Dispathcer.include()方法调用
  3. FORWARD:Request.Dispathcer.forward()方法调用
  4. ERROR:声明异常处理机制调用

Filter链

当多个Filter链对同一个url进行请求过滤时,这些Filter就组成了一个过滤器链。

在上面的实例增加一个filter2程序

代码语言:javascript复制
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;

public class filter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter out = servletResponse.getWriter();
        out.println("before<br>");
        filterChain.doFilter(servletRequest, servletResponse);
        out.println("after<br>");
    }

    @Override
    public void destroy() {

    }
}

修改filter程序

代码语言:javascript复制
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;

public class filter implements Filter{
//    初始化时被调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter out = servletResponse.getWriter();
        out.println("this is filter<br>");
        filterChain.doFilter(servletRequest, servletResponse);
    }
//    销毁时调用
    @Override
    public void destroy() {

    }
}

配置web.xml

代码语言:javascript复制
<filter>            
    <filter-name>filter</filter-name>            
    <filter-class>filter</filter-class>     
</filter>
<filter>        
    <filter-name>filter2</filter-name>        
    <filter-class>filter2</filter-class>
</filter>
<filter-mapping>        
    <filter-name>filter</filter-name>        
    <url-pattern>/servlet</url-pattern>        
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>     
    <filter-name>filter2</filter-name>        
    <url-pattern>/servlet</url-pattern>        
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

在web.xml中,filte的filter-mapping声明在filter2前面,因此在filter链当中filter首先被调用。用户的请求首先被filter拦截,再被filter2拦截。

程序的执行结果如下

首先调用了filter,然后调用filter2输出before,filter2再放行请求,调用了filter2上层的servlet容器,最后filter2输出了after。

FilterConfig接口

用于获取Filter程序在web.xml中的配置信息

声明

描述

String getFilterName()

返回web.xml中设置的filter-name

String getInitParameter(String name)

返回web.xml中设置的某个初始化参数

Enumeration getInitParameterNames()

返回web.xml中设置的所有初始化参数名称的集合

ServletContext getServletContext ()

返回FilterConfig对象中封装的ServletContext对象

0 人点赞