当前位置 : 主页 > 编程语言 > java >

JavaWeb开发专题(十四)-过滤器

来源:互联网 收集:自由互联 发布时间:2022-07-04
1.过滤器(Filter)是什么 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 ht

1.过滤器(Filter)是什么

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

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

例如: 地铁安检、身份验证。

2.过滤器快速入门

1.定义一个类,实现javax.servlet.Filter接口,实现方法

package filter;

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;

public class FilterDemo implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化中...");
System.out.println("过滤器初始化中...");
System.out.println("过滤器初始化中...");
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器成功拦截了用户请求的资源...");
System.out.println("过滤器成功拦截了用户请求的资源...");
System.out.println("过滤器成功拦截了用户请求的资源...");
// 对请求的资源进行放行,如果不放行,服务器将不响应任何内容(空白页面)。
chain.doFilter(request, response);
}

public void destroy() {
System.out.println("过滤器被销毁了...");
System.out.println("过滤器被销毁了...");
System.out.println("过滤器被销毁了...");
}
}

2.在web.xml中配置相关的配置

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>hei15_web23_filter</display-name>
<!-- 注册过滤器 -->
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>filter.FilterDemo</filter-class>
</filter>
<!-- 对哪些资源进行拦截 -->
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<!-- /*表示拦截所有路径,后面再细讲 -->
<url-pattern>/*</url-pattern>
</filter-mapping>

3.过滤器的执行顺序

Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:

  • 调用目标资源之前,让一段代码执行。
  • 是否调用目标资源(即是否让用户访问web资源)。
  • 调用目标资源之后,让一段代码执行。

web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。
JavaWeb开发专题(十四)-过滤器_xml_02

4.过滤器的生命周期(了解)

生命周期:一个对象从创建到销毁的过程。
和过滤器的生命周期相关的3个方法:

  • init:服务器在启动的时候创建Filter对象,并调用初始化过滤器的方法,对过滤器进行初始化
  • doFilter:过滤器的核心方法,在这个方法中可以对请求对象和响应对象进行一些预处理(对请求和响应对象进行增强)。
  • destroy:服务器关闭时销毁,只有在正常关闭时,才执行destroy方法。

5.过滤器配置详解

5.1.doFilter方法

JavaWeb开发专题(十四)-过滤器_java-ee_03
这个方法,是完成过滤的核心处理方法,有3个参数
参数1:ServletRequest 请求,使用时,一般需要向下转型HttpServletRequest req = (HttpServletRequest) request;
参数2:ServletResponse 响应,使用时,也需要向下转型HttpServletResponse resp = (HttpServletResponse) response;
参数3:FilterChain 这个对象就是用来决定是否放行的对象,放行时,调用该对象的doFilter(req, resp);
放行的方法:

package filter;

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;

public class FilterDemo implements Filter {
// 初始化
public void init(FilterConfig arg0) throws ServletException {
System.out.println("过滤器被创建了。。。");
}

// 核心方法:拦截
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("您访问的资源被拦截了。。。");
String username = request.getParameter("username");
if ( "zhangsan".equals(username) ) {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("跟我来一下...");
} else {
System.out.println("合法公民,请进。。。");
chain.doFilter(request, response);
}
}

// 销毁
public void destroy() {
System.out.println("过滤器被销毁了。。。");
}
}

5.2.过滤规则url-pattern

该节点用于规定拦截哪些资源,规则和Servlet中的url-pattern是一致的,有3种规则:
1.全路径匹配:
以/开始 ,例如:/index.jsp
2.通配符匹配:
a.以/开始 以/结尾 例如:/aaa/ 项目中aaa目录下的所有资源
b. /* 拦截所有的请求资源 是过滤器的最常用配置
3.后缀名(扩展名)匹配:
​​​*.xxx​​​,例如​​*.do​​​ ​​*.abc​​等等,不能以/开始

5.3.转发器dispatcher(了解)

<filter-mapping>
<filter-name>FilterDemo</filter-name>
<!-- 配置对哪些路径进行过滤,和Servlet中的一样! -->
<url-pattern>/*</url-pattern>
<!-- 默认配置,只拦截来自客户端的请求,在服务器的内部使用转发时,
不会对转发的目标资源进行拦截 -->
<dispatcher>REQUEST</dispatcher>
<!-- 在服务器的内部做转发的时候,也被拦截 -->
<!-- <dispatcher>FORWARD</dispatcher> -->
<!-- 当使用动态引入的时候,引入的资源也会被拦截
静态引入(include指令):<%@ include file="..."%>
先合并,再翻译
动态引入(jsp动作):<jsp:include path=".." />
被引入的jsp先单独翻译,然后把最终输出的结果引入到页面中
-->
<!-- <dispatcher>INCLUDE</dispatcher> -->

<!-- 当跳转到错误页面的时候进行拦截
在web.xml中可以配置项目的全局的错误页面,
一旦服务器内部发生异常,就会跳转到配置的对应的错误页面
-->
<!-- <dispatcher>ERROR</dispatcher> -->
</filter-mapping>

项目的统一错误页面配置:
JavaWeb开发专题(十四)-过滤器_xml_04

6.过滤器链

6.1.过滤器链概念

通常客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。

每个过滤器实现某个特定的功能,一个过滤器检测多个Servlet。(匹配几个,检测几个)。
一组过滤器中的执行顺序与​​​<filter-mapping>​​的配置顺序呢有关。

当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源.
JavaWeb开发专题(十四)-过滤器_xml_05

6.2.过滤器链示例

ResponseFilter.java

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
CustomResponseWrapper customResponseWrapper = new CustomResponseWrapper((HttpServletResponse) servletResponse);
System.out.println("ResponseFilter 执行前");
filterChain.doFilter(servletRequest,customResponseWrapper);//执行下一层过滤
System.out.println("ResponseFilter 执行后");
}
}

SecondFilter.java

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Second doFilter执行前");
filterChain.doFilter(servletRequest,servletResponse);//这是最后一层过滤器,会直接请求resource
System.out.println("Second doFilter执行后");
}

web.xml (两个过滤器使用了相同的匹配模式‘/*’,所以会处于同一过滤链中)

<filter>
<filter-name>ResponseFilter</filter-name>
<filter-class>filter.ResponseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>SecondFilter</filter-name>
<filter-class>filter.SecondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecondFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
  • 执行结果:
    JavaWeb开发专题(十四)-过滤器_服务器_06
    从执行结果并结合以上分析可以很清楚的看出doFilter的执行顺序

7.全站乱码处理

在每个servlet中,都需要进行乱码的处理,这样太麻烦,可以使用过滤器来对乱码进行统一的处理
思路:在放行之前,对request进行编码的设置,那么在请求到达servlet之后,就相当于在每一个servlet中对乱码进行了处理!

定义处理乱码的过滤器

public class EncodingFilter implements Filter {
// 在过滤器的核心方法中,对请求和响应对象进行预处理
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 将ServletRequest、ServletResponse转换成和Http协议相关的对象
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 解决POST的请求方式乱码问题
req.setCharacterEncoding("UTF-8");
// 处理响应的乱码
resp.setContentType("text/html;charset=UTF-8");
// 对request和response对象处理之后,放行
chain.doFilter(req, resp);
}

public void init(FilterConfig filterConfig) throws ServletException {
}

public void destroy() {
}
}

测试页面:

<body>
<form action="regServlet" method="post">
<input name="name" /><br/>
<input type="submit" value="提交" />
</form>
</body>

获取数据的Servlet

package web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("all")
public class RegServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
response.getWriter().write(name);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

页面效果:

JavaWeb开发专题(十四)-过滤器_xml_07

8.强制登录

系统的某些页面需要登录才能访问,如果在每个页面中都写判断,很麻烦,而且不好维护。
可以使用过滤器对需要登录才能访问的页面进行拦截,然后在过滤器中判断用户是否登录,如果没有登录,则强制跳转到登录页面:

public class PrivilegeFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
Object user = request.getSession().getAttribute("loginUser");
if ( user == null ) {
//response.sendRedirect(request.getContextPath() + "/login.jsp");
String path = request.getContextPath();
// top是js中的一个对象,它永远指最顶层窗口的window对象
response.getWriter().write("<script>top.location='"+path+"/login.jsp';</script>");
return ;
}
chain.doFilter(request, response);
}

public void init(FilterConfig arg0) throws ServletException {

}
public void destroy() {

}
}

配置web.xml

<filter>
<filter-name>PrivilegeFilter</filter-name>
<filter-class>filter.PrivilegeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrivilegeFilter</filter-name>
<!-- 配置需要登录才能访问的资源 -->
<servlet-name>QueryGoodsPage</servlet-name> <!-- 对某个Servlet进行拦截 -->
<url-pattern>/aaaa/*</url-pattern> <!-- 对/aaaa下面的资源进行拦截 -->
<url-pattern>/bbbb/*</url-pattern> <!-- 对/bbbb下面的资源进行拦截-->
</filter-mapping>


上一篇:JavaWeb开发专题(十五)-监听器
下一篇:没有了
网友评论