>  기사  >  Java  >  Java의 필터 필터에 대한 자세한 설명

Java의 필터 필터에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-03-10 19:16:343122검색

Java의 필터에 대해 자세히 설명하는 글

필터 소개

필터는 필터라고도 하며, 서블릿 기술 가장 실용적인 기술인 웹 개발자는 필터 기술을 사용하여 Jsp, 서블릿, 정적 이미지 파일 또는 정적 HTML 파일 등과 같은 웹 서버에서 관리하는 모든 웹 리소스를 가로채서 몇 가지 특수 기능을 달성합니다. 예를 들어, URL 수준의 권한 접근 제어, 민감한 어휘 필터링, 응답 정보 압축 등 일부 고급 기능을 구현할 수 있습니다.

주로 사용자 요청을 전처리하는 데 사용되며 HttpServletResponse를 후처리할 수도 있습니다. 필터 사용의 전체 프로세스: 필터는 사용자 요청을 전처리한 다음 처리를 위해 요청을 서블릿에 전달하고 응답을 생성하며 마지막으로 필터는 서버 응답을 후처리합니다.

필터 기능

HttpServletRequest가 서블릿에 도달하기 전에 클라이언트의 HttpServletRequest를 가로챕니다. 필요에 따라 HttpServletRequest를 확인하고, HttpServletRequest 헤더 및 데이터를 수정할 수도 있습니다.
클라이언트에 도달하기 전에 HttpServletResponse를 가로채세요. 필요에 따라 HttpServletResponse를 확인하고, HttpServletResponse 헤더 및 데이터를 수정할 수도 있습니다.

Filter를 사용하여 차단 기능을 구현하는 방법

Filter 인터페이스에는 doFilter 메소드가 있습니다. 개발자가 Filter를 작성하고 차단할 웹 리소스를 구성하면 웹 서버가 작동합니다. 매번 웹 리소스를 호출합니다. 리소스의 서비스 메서드 전에 필터의 doFilter 메서드가 먼저 호출됩니다. 따라서 이 메서드에 코드를 작성하면 다음과 같은 목적을 달성할 수 있습니다.

调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问web资源)。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

필터 개발

Java 클래스 구현 필터 인터페이스 작성 및 doFilter 메소드 구현.
web.xml 파일에 작성된 필터 클래스를 등록하고 차단할 수 있는 리소스를 설정합니다.

Web.xml 구성 노드 소개:

<filter>指定一个过滤器。
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
<filter-class>元素用于指定过滤器的完整的限定类名。
<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
<servlet-name>指定过滤器所拦截的Servlet名称。
<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。
<dispatcher>子元素可以设置的值及其意义
REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

필터 체인

웹 애플리케이션에서는 여러 개의 필터를 개발하고 작성할 수 있으며 이러한 필터는 하나의 필터 체인으로 결합됩니다. .

웹 서버는 web.xml 파일에 있는 Filter의 등록 순서에 따라 어떤 Filter를 먼저 호출할지 결정합니다. 첫 번째 Filter의 doFilter 메소드가 호출되면 웹 서버는 다음을 나타내는 FilterChain 객체를 생성합니다. 필터 체인을 전달하고 메소드를 제공하십시오. doFilter 메서드에서 개발자가 FilterChain 개체의 doFilter 메서드를 호출하면 웹 서버는 FilterChain 개체에 다른 필터가 있는지 확인하고, 없으면 두 번째 필터를 호출합니다. 호출됩니다.

필터 수명 주기

public void init(FilterConfig filterConfig) throws ServletException;//初始化
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。

public void destroy();//销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

FilterConfig 인터페이스

필터를 구성할 때 사용자는 웹 컨테이너가 필터 개체를 인스턴스화할 때 필터에 대한 일부 초기화 매개변수를 구성할 수 있습니다. init 메소드에서는 필터 초기화 매개변수를 캡슐화하는 filterConfig 객체가 전달됩니다. 따라서 개발자가 필터를 작성할 때 filterConfig 객체의 메소드를 통해 다음 내용을 얻을 수 있습니다:

String getFilterName();//得到filter的名称。 
String getInitParameter(String name);//返回在部署描述中指定名称的初始化参数的值。如果不存在返回null. 
Enumeration getInitParameterNames();//返回过滤器的所有初始化参数的名字的枚举集合。 
public ServletContext getServletContext();//返回Servlet上下文对象的引用。

필터 사용 사례

필터를 사용하여 사용자 로그인 보안 제어 확인

이전 단락 사용자가 시스템에서 로그아웃한 후에도 URL에 따라 주소 표시줄로 이동하면 시스템 응답 페이지에 들어갈 수 있습니다. 확인해보니 사용자 로그인을 확인하기 위해 요청이 필터링되지 않은 것으로 나타났습니다. 문제를 해결하려면 필터를 추가하세요!

먼저 web.xml에서
<filter>
    <filter-name>SessionFilter</filter-name>
    <filter-class>com.action.login.SessionFilter</filter-class>
    <init-param>
        <param-name>logonStrings</param-name><!-- 对登录页面不进行过滤 -->
        <param-value>/project/index.jsp;login.do</param-value>
    </init-param>
    <init-param>
        <param-name>includeStrings</param-name><!-- 只对指定过滤参数后缀进行过滤 -->
        <param-value>.do;.jsp</param-value>
    </init-param>
    <init-param>
        <param-name>redirectPath</param-name><!-- 未通过跳转到登录界面 -->
        <param-value>/index.jsp</param-value>
    </init-param>
    <init-param>
        <param-name>disabletestfilter</param-name><!-- Y:过滤无效 -->
        <param-value>N</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>SessionFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
를 구성합니다.

한자 깨짐 방지를 위한 필터

프로젝트에서 spring 프레임워크를 사용하는 경우. 프런트엔드 JSP 페이지와 Java 코드에서 인코딩에 서로 다른 문자 집합을 사용하는 경우 양식으로 제출된 데이터나 업로드/다운로드된 중국어 이름 파일이 깨질 수 있으므로 이 필터를 사용할 수 있습니다.

package com.action.login;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 *    判断用户是否登录,未登录则退出系统
 */
public class SessionFilter implements Filter {

    public FilterConfig config;

    public void destroy() {
        this.config = null;
    }

    public static boolean isContains(String container, String[] regx) {
        boolean result = false;

        for (int i = 0; i < regx.length; i++) {
            if (container.indexOf(regx[i]) != -1) {
                return true;
            }
        }
        return result;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hrequest = (HttpServletRequest)request;
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);

        String logonStrings = config.getInitParameter("logonStrings");        // 登录登陆页面
        String includeStrings = config.getInitParameter("includeStrings");    // 过滤资源后缀参数
        String redirectPath = hrequest.getContextPath() + config.getInitParameter("redirectPath");// 没有登陆转向页面
        String disabletestfilter = config.getInitParameter("disabletestfilter");// 过滤器是否有效

        if (disabletestfilter.toUpperCase().equals("Y")) {    // 过滤无效
            chain.doFilter(request, response);
            return;
        }
        String[] logonList = logonStrings.split(";");
        String[] includeList = includeStrings.split(";");

        if (!this.isContains(hrequest.getRequestURI(), includeList)) {// 只对指定过滤参数后缀进行过滤
            chain.doFilter(request, response);
            return;
        }

        if (this.isContains(hrequest.getRequestURI(), logonList)) {// 对登录页面不进行过滤
            chain.doFilter(request, response);
            return;
        }

        String user = ( String ) hrequest.getSession().getAttribute("useronly");//判断用户是否登录
        if (user == null) {
            wrapper.sendRedirect(redirectPath);
            return;
        }else {
            chain.doFilter(request, response);
            return;
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        config = filterConfig;
    }
}

필터 소개

필터는 서블릿 기술 중 가장 실용적인 기술로 웹 서버에서 관리하는 모든 웹 리소스(예: Jsp)를 관리하는 데 사용됩니다. , 서블릿, 정적 그림 파일 또는 정적 HTML 파일을 가로채서 일부 특수 기능을 수행합니다. 예를 들어, URL 수준의 권한 접근 제어, 민감한 어휘 필터링, 응답 정보 압축 등 일부 고급 기능을 구현할 수 있습니다.

주로 사용자 요청을 전처리하는 데 사용되며 HttpServletResponse를 후처리할 수도 있습니다. 필터 사용의 전체 프로세스: 필터는 사용자 요청을 전처리한 다음 처리를 위해 요청을 서블릿에 전달하고 응답을 생성하며 마지막으로 필터는 서버 응답을 후처리합니다.

필터 기능

HttpServletRequest가 서블릿에 도달하기 전에 클라이언트의 HttpServletRequest를 가로챕니다. 필요에 따라 HttpServletRequest를 확인하고 HttpServletRequest 헤더 및 데이터를 수정합니다.

클라이언트에 도달하기 전에 HttpServletResponse를 가로채세요. 필요에 따라 HttpServletResponse를 확인하고, HttpServletResponse 헤더 및 데이터를 수정할 수도 있습니다.


Filter를 사용하여 차단 기능을 구현하는 방법

Filter 인터페이스에는 doFilter 메소드가 있습니다. 개발자가 Filter를 작성하고 차단할 웹 리소스를 구성하면 웹 서버가 작동합니다. 매번 웹 리소스를 호출합니다. 리소스의 서비스 메서드 전에 필터의 doFilter 메서드가 먼저 호출됩니다. 따라서 이 메서드에 코드를 작성하면 다음과 같은 목적을 달성할 수 있습니다.
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问web资源)。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

Filter开发两步走

编写java类实现Filter接口,并实现其doFilter方法。
在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源。

web.xml配置各节点介绍:

<filter>指定一个过滤器。
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
<filter-class>元素用于指定过滤器的完整的限定类名。
<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
<servlet-name>指定过滤器所拦截的Servlet名称。
<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。
<dispatcher>子元素可以设置的值及其意义
REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

Filter链

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

Filter的生命周期

public void init(FilterConfig filterConfig) throws ServletException;//初始化
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。

public void destroy();//销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

FilterConfig接口

用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得以下内容:

String getFilterName();//得到filter的名称。 
String getInitParameter(String name);//返回在部署描述中指定名称的初始化参数的值。如果不存在返回null. 
Enumeration getInitParameterNames();//返回过滤器的所有初始化参数的名字的枚举集合。 
public ServletContext getServletContext();//返回Servlet上下文对象的引用。

Filter使用案例

使用Filter验证用户登录安全控制

前段时间参与维护一个项目,用户退出系统后,再去地址栏访问历史,根据url,仍然能够进入系统响应页面。我去检查一下发现对请求未进行过滤验证用户登录。添加一个filter搞定问题!

先在web.xml配置
<filter>
    <filter-name>SessionFilter</filter-name>
    <filter-class>com.action.login.SessionFilter</filter-class>
    <init-param>
        <param-name>logonStrings</param-name><!-- 对登录页面不进行过滤 -->
        <param-value>/project/index.jsp;login.do</param-value>
    </init-param>
    <init-param>
        <param-name>includeStrings</param-name><!-- 只对指定过滤参数后缀进行过滤 -->
        <param-value>.do;.jsp</param-value>
    </init-param>
    <init-param>
        <param-name>redirectPath</param-name><!-- 未通过跳转到登录界面 -->
        <param-value>/index.jsp</param-value>
    </init-param>
    <init-param>
        <param-name>disabletestfilter</param-name><!-- Y:过滤无效 -->
        <param-value>N</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>SessionFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
接着编写FilterServlet
package com.action.login;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 *    判断用户是否登录,未登录则退出系统
 */
public class SessionFilter implements Filter {

    public FilterConfig config;

    public void destroy() {
        this.config = null;
    }

    public static boolean isContains(String container, String[] regx) {
        boolean result = false;

        for (int i = 0; i < regx.length; i++) {
            if (container.indexOf(regx[i]) != -1) {
                return true;
            }
        }
        return result;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hrequest = (HttpServletRequest)request;
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);

        String logonStrings = config.getInitParameter("logonStrings");        // 登录登陆页面
        String includeStrings = config.getInitParameter("includeStrings");    // 过滤资源后缀参数
        String redirectPath = hrequest.getContextPath() + config.getInitParameter("redirectPath");// 没有登陆转向页面
        String disabletestfilter = config.getInitParameter("disabletestfilter");// 过滤器是否有效

        if (disabletestfilter.toUpperCase().equals("Y")) {    // 过滤无效
            chain.doFilter(request, response);
            return;
        }
        String[] logonList = logonStrings.split(";");
        String[] includeList = includeStrings.split(";");

        if (!this.isContains(hrequest.getRequestURI(), includeList)) {// 只对指定过滤参数后缀进行过滤
            chain.doFilter(request, response);
            return;
        }

        if (this.isContains(hrequest.getRequestURI(), logonList)) {// 对登录页面不进行过滤
            chain.doFilter(request, response);
            return;
        }

        String user = ( String ) hrequest.getSession().getAttribute("useronly");//判断用户是否登录
        if (user == null) {
            wrapper.sendRedirect(redirectPath);
            return;
        }else {
            chain.doFilter(request, response);
            return;
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        config = filterConfig;
    }
}

这样既可完成对用户所有请求,均要经过这个Filter进行验证用户登录。

防止中文乱码过滤器

项目使用spring框架时。当前台JSP页面和Java代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题,那就可以使用这个过滤器。

1d24e586ca31f4bd05eca427459d98c7
    f573a9ccb524cb86b6b9919be70810beencodingb4d5e6fde2c78ede331e20c60d37da11
    e5b954f5d6752e2b67f5dbec1cf5c85eorg.springframework.web.filter.CharacterEncodingFilter3c5315e9114c0f42d7a83b06562caa88
    380fae52cc7d04565d26dd4bbf4b5460
        c13d9669d2c8f87a36a39c8f95f41552encoding02b9ad8b27bc78bd91c18db845cdde4a991869418c27da83b7bdcfcc9422cfd7
        f226acac8cb0e4a9d59fcba58b57a899UTF-822c8aeb51b7638a9da01bd5a66154ac1
    8f161518881ffd7712eaaadc573a3556
    380fae52cc7d04565d26dd4bbf4b5460
        c13d9669d2c8f87a36a39c8f95f41552forceEncoding02b9ad8b27bc78bd91c18db845cdde4a5df15f7cc7f945ba4de3548a29284159
        f226acac8cb0e4a9d59fcba58b57a899false22c8aeb51b7638a9da01bd5a66154ac1
    8f161518881ffd7712eaaadc573a3556
94e66dfbd9fa8f117002935bdd35d0b3
dd0dfb26ea66647667f179a739921d33
    f573a9ccb524cb86b6b9919be70810beencodingb4d5e6fde2c78ede331e20c60d37da11
    66e1775cbd9d5002635ae3285442ba88/*3ec4a5583206d351b61ed79c1a0f9c66
e354d6d34e50ca0d695db95544b3672a

위 내용은 Java의 필터 필터에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.