java过滤器的应用_Java过滤器详细文档,简介,实例,应用

Java过滤器(Filter)是Servlet技术的重要组成部分,用于拦截和修改请求与响应。本文介绍了Filter的工作原理,包括其在请求处理链中的执行顺序,以及Filter的生命周期,包括实例化、初始化、过滤和销毁阶段。此外,还详细讲解了如何在web.xml中注册和映射Filter,以及Filter的开发步骤,包括实现Filter接口并配置相应参数。
摘要由CSDN通过智能技术生成

简介

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

Filter技术是servlet 2.3新增加的功能。它能够对Servlet容器的请求和响应对象进行检查和修改。

Filter本身并不生成请求和响应对象,只是提供过滤功能。

Filter能够在Servlet被调用之前检查Request对象,并修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response的内容。

Filter可以过滤的Web组件包括Servlet,JSP和HTML等文件。

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

6f917c4fecc762981a311f0e2b6f054d.png

edb634163e71c5329dfe543cd3362ffb.png

2.Filter的工作原理

当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。

两个过滤器同时过滤一个请求时,就要用到过滤链FilterChain。Filter的FilterChain中,服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序就如下图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。

bdbb8cf21b3336b910296548d3bc3453.png

Filter的执行流程就是:

执行第一个过滤器的chain.doFilter()之前的代码——

>第二个过滤器的chain.doFilter()之前的代码——>……——

>第n个过滤器的chain.doFilter()之前的代码——

>所请求servlet的service()方法中的代码——>

所请求servlet的doGet()或doPost()方法中的代码——

>第n个过滤器的chain.doFilter()之后的代码——>……——

>第二个过滤器的chain.doFilter()之后的代码——

>第一个过滤器的chain.doFilter()之后的代码。

3、Filter生命周期

1> 和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方法只会直接一次。

也可以简单理解:

(1)实例化:Web容器在部署Web应用程序时对所有过滤器进行实例化。Web容器回调它的无参构造方法。

(2)初始化:实例化完成之后,马上进行初始化工作。Web容器回调init()方法。

(3)过滤:请求路径匹配过滤器的URL映射时。Web容器回调doFilter()方法——主要的工作方法。

(4)销毁: Web容器在卸载Web应用程序前,Web容器回调destroy()方法。

4,Filter的部署

分为两个步骤:

1、注册Filter

用于添加描述信息,该元素的内容可为空,可以不配置。

用于为过滤器指定一个名字,该元素的内容不能为空。

元素用于指定过滤器的完整的限定类名。

元素用于为过滤器指定初始化参数,它的子元素指定参数的名字,指定参数的值。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。如果过滤器不需要指定初始化参数,那么元素可以不配置。

2、映射Filter

在web.xml文件中注册了Filter之后,还要在web.xml文件中映射Filter

FilterDemo02

/*

元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径

子元素用于设置filter的注册名称。该值必须是在元素中声明过的过滤器的名字

设置 filter 所拦截的请求路径(过滤器关联的URL样式)

指定过滤器所拦截的Servlet名称。

指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。

用户可以设置多个 子元素用来指定 Filter 对资源的多种调用方式进行拦截。如下:

testFilter

/index.jsp

REQUEST

FORWARD

子元素可以设置的值及其意义:

REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。

INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。

ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

Filter开发步骤

Filter开发分为二个步骤:

编写java类实现Filter接口,并实现其doFilter方法。

在 web.xml 文件中使用和元素对编写的filter类进行注册,并设置它所能拦截的资源。

authorityFilter           

cn.thinknet.filter.AuthorityFilter

allowAuthorityURL

login.jsp,register.jsp,login.action,sendMail.action,register.action,getbackPwdOne.jsp,getbackPwdTwo.jsp,getbackPwdThree.jsp,getbackOne.action,getbackTwo.action,getbackThree.action,forget_pwd.action,getHomePageResult.action,index.jsp,index.html,userAuthen.action

authorityURL

.action,.jsp,.do

redirectPath

/wrtPlatformVt/wrt/login.jsp

disableFilter

N

authorityFilter

/*

标签对应的是参数名和值,可以用于在init()时通过FilterConfig的对象filterConfig.getInitParameter("参数名")获取。

自定义过滤器代码:

package cn.thinknet.filter;

import java.io.IOException;

import java.io.PrintWriter;

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.Cookie;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;

import org.apache.commons.lang3.StringUtils;

import cn.thinknet.utils.others.AKKeysUtil;

/**

* 过滤器

*

*

*

*/

public class AuthorityFilter extends HttpServlet implements Filter

{

private static final long serialVersionUID = 4504557649329493897L;

public String[] allowAuthorityURLs;

public String[] authorityURLs;

public FilterConfig config;

/**

* 过滤不能访问的地址

*/

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain filterChain) throws IOException, ServletException

{

// 未登录需要跳转的地址

String redirectPath = config

.getInitParameter(AKKeysUtil.WEB_CONTEXT_REDIRECT_PATH);

// 过滤是否启用

boolean isEnable = true; // 过滤器可用

String disableStr = config

.getInitParameter(AKKeysUtil.WEB_CONTEXT_DISABLE_FILTER);

if (StringUtils.isNotEmpty(disableStr))

{

isEnable = disableStr.equals("N");

}

HttpServletRequest req = (HttpServletRequest) request;

// 判断过滤器是否启用

if (!isEnable)

{

filterChain.doFilter(request, response);

return;

}

// 需要过滤的后缀

String authorityURL = config

.getInitParameter(AKKeysUtil.WEB_CONTEXT_AUTHORITY_URL);

if (StringUtils.isNotEmpty(authorityURL))

{

authorityURLs = authorityURL.split(",");

}

// 判断当前的请求地址中是否存在需要过滤的后缀

if (authorityURL(req))

{

// 不需要过滤的地址

String allowAuthorityURL = config

.getInitParameter(AKKeysUtil.WEB_CONTEXT_ALLOW_AUTHORITY_URL);

if (StringUtils.isNotEmpty(allowAuthorityURL))

{

allowAuthorityURLs = allowAuthorityURL.split(",");

}

// 过滤不拦截的url

if (allowAuthorityURL(req))

{

filterChain.doFilter(request, response);

return;

} else

{

// 判断当前用户是否登录,没有登录直接跳转到登录页面

if (!relogin(redirectPath, response, req))

{

return;

}

}

// 最后对action与jsp进行权限校验

// if (authorityRequestAddress(req))

// {

// 【暂时不实现纵向越权控制】

filterChain.doFilter(request, response);

// }

// else

// {

// 没有权限时

// noAuthority();

// }

} else

{

// 例如js,image,css等文件不列入权限控制范围内

filterChain.doFilter(request, response);

}

}

@Override

public void init(FilterConfig filterConfig) throws ServletException

{

config = filterConfig;

// WebApplicationContext ctx = WebApplicationContextUtils

// .getWebApplicationContext(this.getServletContext());

// menuService = (MenuService) ctx.getBean("menuService");

}

/**

* 在未登陆的情况下允许访问的URL

*

* @return Boolean

*/

private boolean allowAuthorityURL(HttpServletRequest request)

{

boolean isAllow = false;

// 获得当前访问的地址

String current_url = request.getRequestURI();

if (ArrayUtils.isNotEmpty(allowAuthorityURLs))

{

for (String allowUrl : allowAuthorityURLs)

{

if (StringUtils.containsIgnoreCase(current_url, allowUrl))

{

isAllow = true;

break;

}

}

}

return isAllow;

}

/**

* 需要过滤的后缀

*

* @return Boolean

*/

private boolean authorityURL(HttpServletRequest request)

{

boolean isFilter = false;

if (ArrayUtils.isNotEmpty(authorityURLs))

{

for (String suffix : authorityURLs)

{

if (request.getRequestURI().indexOf(suffix) != -1)

{

isFilter = true;

break;

}

}

}

return isFilter;

}

/**

* 判断员工回话是否失效

*

* @param redirectPath

*            需要跳转的页面

* @param response

*            请求响应

*

* @param request

*            请求

*

* @throws IOException

*

* @return boolean 假:代表重新登录,真:代表session存在

*/

private boolean relogin(String redirectPath, ServletResponse response,

HttpServletRequest request) throws IOException

{

response.setContentType("text/html;charset=UTF-8");

response.setCharacterEncoding("UTF-8");

PrintWriter out = response.getWriter();

// 判断该用户是否存在session中,如果有直接进入当前action

if (null == request.getSession(true).getAttribute(

AKKeysUtil.USER_EMPLOY_SESSION_KEY))

{

// 跳转到登录界面

out.print("

+ redirectPath + "';");

return false;

}

// 如果用户禁用掉cookie,则跳转到登录界面,提示用户启用cookie

Cookie[] cookies = request.getCookies();

if (null == cookies)

{

// 1.可能用户清除过cookie 2.可能是由于用户禁用了cookie 此时都会跳转到登录界面

// 跳转到登录界面

out.print("

+ redirectPath + "';");

return false;

}

return true;

}

}

注意,AKKeysUtil这个是封装好的一个工具类,所有使用到的地方对应的均是标签的参数名,自行对应更改即可。

servlet过滤器并不等同于拦截器,常用的拦截器莫过于框架所自带的,如:Struts2,spring mvc等。如想达到权限认证(是否登陆、未登录返回登陆页面),通过框架的拦截器达到其效果,当然也可以直接使用servlet的filter.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值