APP下载

Java EE中Filter技术的研究与应用

2018-11-01姚添译杨廷发兰全祥

电脑知识与技术 2018年18期
关键词:开发技术过滤器

姚添译 杨廷发 兰全祥

摘要:过滤器能够对请求信息和响应信息进行处理,在Java Web开发中具有重要的作用和地位。通过对过滤器的概念、方法、配置及执行过程进行分析,阐述了过滤器的特性,并对过滤器在Java EE中的应用进行了研究。从项目开发入手,探讨了过滤器在编码过滤、缓存控制、登录验证、流量统计、敏感字过滤、读取cookie等方面的应用。过滤器的出现极大地减少了开发人员的工作量,有利于网站的开发与维护。

关键词:Java EE;过滤器;开发技术;网站开发

中图分类号:TP311.1 文献标识码:A 文章编号:1009-3044(2018)18-0047-04

Research and Application of Filter Technology on Java EE

YAO Tian-yi, YANG Ting-fa, LAN Quan-xiang

(Panzhihua University, Panzhihua 617000, China)

Abstract: Filters can process request or response information, and play an important role in Java Web development. Through analyzing the concept, method, configuration and execution process of the filter, it describe the characteristics of the filter. A study is made of the application of filter. At the core of project development, it discusses applications of filters in processing coding, controlling caching, validating permissions, counting site access, shielding sensitive words, reading cookie and so on. The filter can greatly reduce the workload of development and maintenance.

Key words: Java EE; filter; development technology; website development

1 背景

Servlet是运行在服务器上的小程序,它作为来自浏览器(或客户端)的请求与服务器(或应用程序)的中间层,为Web开发者提供了一种简便可靠的机制来扩展web服务器的功能[1]。在实际的网站开发中需要处理大量的请求与响应信息,并且大多数时候需要在访问Servlet之前对请求进行处理,判断是否有访问权限。在过滤器出现之前,若想实现上述功能,则需要为Servlet编写一个父类。但如果存在多个处理需求,则需要为Servlet实现多个父类,这给开发人员造成了很多不便。

为解决这一问题sun公司在Servlet 2.3规范中新增了Filter技术,Filter是一个继承了javax.servlet.Filter 接口的Java类,能动态地拦截请求和响应并对request、response进行处理,同时可以决定是否允许访问目标资源。因此,Filter可运用在编码过滤、缓存控制、登录验证、流量统计、敏感字过滤、读取cookie等方面,它的出现极大地简化了网站的开发与部署。

2 Filter简介

2.1 概述

过滤器是Java EE核心编程中的一个重要部分,它实质上就是一个位于服务器上的Web应用组件,用于动态地拦截请求和响应以及决定目标资源是否能被访问。过滤器的出现更便于查看、提取或以某种方式操作客户端和服务器之间交换的数据[2],其处理方式如图1所示。

当一个过滤器不能满足实际业务需要时,则需部署多个过滤器对业务请求进行处理,此时多个过滤器就组成了过滤链,过滤器链如图2所示。

客户端发出的请求会依次通过过滤链上的所有过滤器,直到传递给最后一个为止,再将请求交给目标资源进行处理。目标资源在处理完请求后,响应信息再从最后一个过滤器传递给第一个过滤器,最后传送到客户端[3]。只有当请求的目标资源路径被包含在过滤路径(编写过滤器时需配置过滤路径)中时,过滤器才会对请求进行处理。

2.2 Filter API

过滤器是一个实现了javax.servlet.Filter接口的java类,在Filter接口中定义了三个方法,分别为init()方法、doFilter()方法和destroy()方法。

1)初始化方法init()

init()方法在servlet容器创建servlet Filter实例后就会调用该方法,并且在过滤器的整个生命周期中只执行1次。

该方法无返回值,形参列表包含1个javax.servlet.FilterConfig类型的参数,该参数通过getInitParameter()和getServletContext()方法来读取web.xml文件中Servlet过滤器的初始化参数。

2)对请求进行处理doFilter()

每当请求或响应通过过滤器时,容器都会调用Filter中的doFilter方法,該方法在过滤器的生命周期中可执行多次。当Filter拦截到请求后,会先执行chain.doFilter()之前的代码,然后执行下一个Filter或者访问目标资源,最后再执行chain.doFilter()后的代码。

该方法无返回值,形参列表包含1个javax.servlet. ServletRequest类型的参数(请求),1个javax.servlet. ServletServletResponse类型的参数(响应),1个javax.servlet.FilterChain类型的参数(过滤链)。在此方法中可以将请求传递给下一个过滤器(或目标资源),也可以在此终止请求。

3)销毁方法destroy()

destroy()方法由Web容器调用,调用之后将释放所有被过滤器占用的资源。该方法在过滤器的生命周期中只执行1次。

3 过滤器的创建与配置

3.1 过滤器的创建

过滤器的创建有两种方法:一是直接创建一个实现了javax.servlet.Filter接口的类;二是使用java集成开发环境(IDE)直接创建过滤器。在创建过滤器时应遵循命名规范,类名首字母大写。

3.2 Filter的配置

Filter的配置和Servlet的配置类似,配置内容包含初始化参数(initParams,可选)、过滤路径(urlPatterns,必选)、过滤类型(dispatcherTypes,可选)。在Servlet3.0以前的版本中,只能在web.xml文件中配置过滤器,而在Servlet3.0以及之后的版本中,可以在web.xml文件中配置,也可以通过注解的方式来配置。

1)在web.xml文件中配置

在项目的WEB-INF文件夹中的web.xml文件编写以下配置信息:

filtername

filterclass

namevlaue

filtername

url

2)使用注解配置Filter

@WebFilter(

filterName = "filtername",

urlPatterns = {" urlPatterns "},

servletNames = {"servletname",…})

filterName屬性用于指定过滤器名字。urlPatterns属性用于指定过滤路径,若该属性值为"/*"表示过滤所有文件,属性值为"*.suffix"表示过滤指定类型文件,属性值为"/folder/*"表示过滤指定文件夹下所有文件,属性值为"/filename.suffix"表示过滤掉指定文件。

3.3 Filter的执行顺序

Filter的doFilter方法在Servlet的service方法被调用之前执行。在doFilter方法中,首先执行chain.doFilter()方法之前的代码,再执行chain.doFilter()把请求信息传递给下一个过滤器或直接传递给目标资源,服务器响应之后再执行chain.doFilter()方法之后的代码。

若使用了多个Filter组成了过滤链,Web容器将按配置文件中的配置顺序进行装载。若存在注解方式配置的过滤器,则再按照过滤器类名首字母顺序进行装载。特别注意的是,当对指定的servletname进行过滤时,Servlet采用注解方式配置无效,需在web.xml文件中进行配置。

4 Filter的应用

4.1 统一全站编码

在Java EE项目开发中,经常会出现乱码问题,Filter能够在调用servlet的service方法之前对request进行处理,在离开Servlet后(返回客户端之前)处理response,因此可以使用Filter对全站编码进行统一。将此编码过滤器的过滤路径设置为"/*",具体开发步骤如下。

1)使用注解配置Filter

@WebFilter(urlPatterns = {"/*"})

2)编写核心代码

由于提交方式大多为get和post方法,因此在doFilter方法中主要对以上两种提交方式的编码进行处理,核心代码如下。

if("post".equals(request.getMethod())){

request.setCharacterEncoding("utf-8");

response.setCharacterEncoding("utf-8");

}else if("get".equals(request.getMethod()){

String param =

request.getParameter("param");

param = new String(param.

getBytes("ISO-8859-1"),"UTF-8");

}

chain.doFilter(request, response);

post提交方式直接使用request的setCharacterEncoding()方法设置字符编码,get提交方式则需要先通过getBytes()方法将字符串按ISO-8859-1进行解码,然后再将获得的字节码按UTF-8编码构造字符串[4]。若JSP页面的charset、pageEncoding都设置为UTF-8,则get提交方式不会乱码。因此在项目开发之前建议将所有文件的编码统一为UTF-8,这样能提高了开发效率,降低了程序乱码出现的概率[5]。

4.2 控制页面缓存

Web缓存主要用于存放曾经访问的页面内容(包括图片以及cookie文件等),缓存可以减少响应的等待时间和网络带宽消耗。但是在实际项目开发过程中,为了确保动态页面的及时更新、验证码的有效性等,一般会禁止动态页面缓存。

禁止缓存可以通过response设置响应头信息来实现。Filter技术能够对Web服务器的响应信息进行处理,并能通过配置实现对指定的某类型文件进行响应信息处理。因此若想对某一类文件进行缓存控制,使用Filter技术便能快速实现,具体开发步骤如下:

1)使用注解配置Filter

@WebFilter(urlPatterns = {" *.jsp"})

2)编写核心代码

缓存控制可以通过设置头信息的Cache-control和Pragma属性来实现,也可以通过设置时间头信息的Expires属性来实现,核心代码如下:

response.setDateHeader("Expires", -1);

response.setHeader("Cache-control",

"no-cache");

response.setHeader("Pragma","no-cache");

由于不是所有的浏览器都支持指定的响应头,因此在开发过程中通常会同时使用上述方法。setDateHeader方法中第一个参数Expires是HTTP消息报头中的实体报头,用于设置响应过期的日期和时间。如果是非法的日期格式(如0,-1等)则可看作该页面已经过期。Cache-control是用于控制是否缓存,当把缓存指令设置为no-cache时表示不缓存请求和响应。Pragma设置为no-cache时也表示不缓存,该方法可应用于HTTP 1.0和HTTP 1.1中。

4.3 验证用户身份

现如今很多的Web应用都需要进行身份验证,这些Web应用中大多资源都需要用户登录后才能访问,如果不进行权限控制,在访问过程中很可能出现资源外泄、程序异常等问题。

过滤器可以决定目标资源是否能被访问,因此可以将需要将登录后才能访问的资源全部加入过滤器的过滤路径中并在该过滤器的doFilter()方法中对发起请求的用户身份进行验证。采用过滤器对所有用户请求进行拦截,然后根据用户是否登录来控制用户请求的转发,做好过滤器的配置与功能设置,后续开发过程中不需要在页面检测用户是否登录[6]。

用户在进行身份认证后都会在session中留下相应的权限标识,当用户访问需要授权的页面时,过滤器会在session中查找该用户是否已经获得授权,如果查找成功则表示该用户已获取授权并允许访问,反之则禁止访问。

在Filter中读取session中特定的权限标记flag,若获取到的值不为null,则允许访问下一過滤器或目标资源,否则重定向到主页面,具体开发步骤如下:

1)使用注解配置Filter

@WebFilter(urlPatterns={"/folder/*"})

2)编写核心代码

if(session.getAttribute("flag")!=null){

chain.doFilter(request, response);

}else{

response.sendRedirect("index.jsp");

}

过滤器不仅能对用户身份进行验证,还能实现用户粗粒度权限管理,解决具有管理员、普通会员和普通游客等多角色用户的权限管理问题[7]。

4.4 网站流量统计

Filter可以对用户提交的数据或服务器返回的数据进行更改。任何到达服务器的请求都可以让其先经过Filter的处理。根据Filter的这一特点可以编写一个专门用于统计网站访问量的过滤器,开发步骤如下。

1)使用注解配置Filter

@WebFilter(urlPatterns = {"/index.jsp"})

2)编写核心代码

首先在过滤器中定义全局变量count来保存网站的访问量,然后在doFilter方法中编写如下代码:

this.count++;

request.getServletContext.

setAttribute("count", count);

考虑到当多用户访问时,会产生数据共享冲突,引起统计的数据不准确。因此在开发中可以用关键字synchronized修饰doFilter方法来解决。

4.5 敏感字符过滤

为了防止输出非法内容或者敏感内容,一般情况下网站都需要对显示内容进行控制,常规的办法是在保存到数据库之前对非法内容进行替换,但这种方法具有局限性,工作量大并且耦合性也较高。然而过滤器可以在用户发送数据到服务器时就对敏感字进行处理,保证在写入数据库时不存在非法内容,具体开发步骤如下。

1)使用注解配置Filter

@WebFilter(servletNames=

{"servletName","……"})

2)编写核心代码

在doFilter方法中获取用户发送的数据,并查找数据中是否包含有敏感字符,如果有就把所有的敏感字替换成“***”,关键代码如下:

String message = request.

getParameter("mes");

if(message!=null &&

message.indexOf("敏感字") >= 0){

message=message.replace("敏感字","**");}

request.setAttribute("con", message);

}

4.6 获取cookies信息

为了增加用户体验效果,一般在登录界面都会设置“是否保存用户信息”的选项,当勾选该选项后,用户在一定时间内再次访问该页面就无需再次输入用户信息。这些信息都是由服务器写入到客户端的cookie中进行保存的。

过滤器能够在请求信息到达服务器之前读取请求信息,因此可以利用Filter实现cookie的扫描,实现信息的获取。当用户访问登录界面时,Filter对发送请求的客户端进行cookies扫描,如果查找到指定的cookie,則将其中的信息读取出来并保存到session作用域中,具体开发步骤如下。

1) 通过注解配置Filter

@WebFilter(urlPatterns = {"/login.jsp"})

2)编写核心代码

实现获取到客户端所有的cookie信息,并利用循环进行遍历,核心代码如下:

Cookies[] cookies = request.getCookies();

for (Cookie cookie : cookies) {

if("username".equals(cookie.getName())){

request.setAttribute("username",

cookie.getValue());

}

if("password".equals(cookie.getName())){

request.setAttribute("password",

cookie.getValue());

}

}

特别需要注意的是,如果要在cookie保存中文字符,则需要用URLEncoder.encode("中文","UTF-8")对保存信息进行编码后保存,并在读取cookie之后使用URLDecoder.decode(cookie.getValue(),"UTF-8")进行解码。

5 总结

Filter是为将繁琐问题简化而出现的技术。通过改变请求或响应中的内容。能快速地进行实际需求开发,熟练地掌握这一技术既可以提高项目的可维护性也可以减轻开发人员的负担。

参考文献:

[1] 池亚平, 方勇. Servlet技术与应用方法[J]. 北京: 邮电大学学报, 2003(S1): 137-139, 143.

[2] 李建. Java Web开发中过滤器组件应用及实例解析[J]. 电脑开发与应用, 2009, 22(11): 58-60.

[3] 高翔, 李志浩. Java Web开发与实践[M]. 北京: 人民邮电出版社, 2014.

[4] 王健. Java编程汉字乱码原因分析及解决方法研究[J]. 山西煤炭管理干部学院学报, 2015, 28(3): 185-186, 189.

[5] 周兵. Java Web开发中的中文乱码问题分析及解决方案[J]. 电脑知识与技术, 2014, 10(29): 6884-6888.

[6] 熊传玉, 徐尤华. 过滤器在Java Web开发中的应用研究[J]. 信息技术, 2015(6): 37-41.

[7] 李玉臣. 基于Filter技术的用户粗粒度权限管理的实现[J]. 电脑编程技巧与维护, 2018(3): 69-71.

猜你喜欢

开发技术过滤器
支持过滤器的REST模型研究与实现
声音过滤器
计算机应用软件开发技术的几点探讨
防散脱纬编无痕弹力面料开发技术国际领先
中国煤层气开发技术的现状与未来
基于LOGO!的空气过滤器自洁控制系统
复杂产品设计知识应用开发技术研究
HVM膜过滤器管板改造总结