专栏首页码猿技术专栏Servlet总结四(过滤器)

Servlet总结四(过滤器)

文章目录

  1. 1. Servlet总结四(过滤器的使用)
    1. 1.1. 简介
    2. 1.2. 过滤器的实现
      1. 1.2.1. 重点
      2. 1.2.2. 简单的例子
      3. 1.2.3. 过滤器的设置
        1. 1.2.3.1. 注意
      4. 1.2.4. 初始参数的设置和获取
        1. 1.2.4.1. 设置初始值
        2. 1.2.4.2. 获取初始参数的值
      5. 1.2.5. 设置触发的时机

Servlet总结四(过滤器的使用)

简介

在容器调用Servlet的service()的方法钱,Servlet其实并不会知道有请求的到来,而在service()方法执行后,容器真正对浏览器进行HTTP响应之前,浏览器也不知道Servlet真正响应是什么。过滤器(Filter)正如其名称所示,它介于Servlet之前,可拦截浏览器对Servlet的请求,也可以改变Servlet对浏览器的响应。 其实说白了,过滤器就是应用程序的一个额外的组件,为了方便使用并且不改变Servlet源代码,比如用户验证,字符替换,压缩这类的需求,你可能只是暂时的需要这类需求,但是过一段时间又不需要了,如果直接在Servlet中改动源码,那么就太麻烦了。因此此时就需要设置一个独立的组件,在使用的时候直接引用,不需要的时候直接删除即可,这就是过滤器的必要。

过滤器的实现

想要实现过滤器,那么需要实现Filter接口,这个接口中有三个必须实现的方法,分别为init(),doFilter(),destroy()init(FilterConfig config) 这是一个初始化方法,其中的参数可以获取定义的初始值,这个在后面会详细说 destroy() 这个是销毁方法 doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain) 这是主要的方法,用来执行过滤的作用。当请求来到了web容器中,容器发现了调用Servlet的service()方法之前可以应用某过滤器的时候就会调用该过滤器的doFilter()方法。就是在doFilter()方法中进行了service()方法的前置处理,而后根据是否调用FilterChain中的doFilter()决定是否执行下一个过滤器,如果没有那么就执行第一个过滤器。 如果执行了FilterChain的doFilter()方法,那么就会执行下一个过滤器,如果没有就调用指定的Servlet的service()方法。

重点

  • Servlet的响应分为前置处理和后置处理。前置处理就是在调用service()方法之前进行的处理,就是Servlet还没有接受到请求的时候,后置处理就是在Servlet执行过service()方法之后,就是Servlet已经处理完请求之后。因此FilterChaindoFilter()方法就将过滤器处理分为了前置处理和后置处理,在调用FilterChaindoFilter()方法之前的都是对Servlet的前置处理,也就是说这时候Servlet并不知道此时有请求过来,而在其之后的都是对Servlet的后置处理。
doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)
{       
        //service()的前置处理
        chain.doFilter(request,response);
        //service()的后置处理
}

  • FilterChain执行后会一堆栈顺序返回,就是说如果有多个Filter,那么就先按照顺序执行chain.doFilter(request,response)之前的代码,即是先前置处理,然后入栈,这样一直到执行到最后一个Filter,之后就从栈顶开始执行chain.doFilter()的方法之后的代码,即是后置处理。总的来说就是先执行前置处理,然后入栈,待全部执行完毕之后再从栈顶开始后置处理的代码。
  • FilterdoFilter的方法中的requestresponse和Servlet的doGet()doPost()方法中的是一样的,即是可以设置属性,可以得到表单提交的值,总之是一样的。

简单的例子

  • 下面实现一个过滤器用来验证提交请求的用户名和密码是否正确
package com;

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.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

public class FilterDemo1 implements Filter {

	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// 根据request获取表单的用户名和密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		// 如果用户名和密码正确
		if ("陈加兵".equals(username) && "123456".equals("password")) {
			System.out.println("用户名或者密码错误,请重新输入");
		}
		//继续执行下一个过滤器,如果有就执行
		chain.doFilter(request, response);
		//当所有过滤器的前置处理都执行完毕才执行这个语句
		System.out.println("Servlet已经执行完毕");
	}

	public void init(FilterConfig config) throws ServletException {

	}

}

过滤器的设置

  • web.xml中设置过滤器,设置的方式如下:
<?xml version="1.0" encoding="UTF-8"?>
<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>web2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
    

    
<!-- 定义FilterDemo1的过滤器 -->
<filter>
        <!--设置过滤器文件的名字-->
  		<filter-name>FilterDemo1</filter-name>
        <!--设置过滤器类所在的路径,具体到包名-->
  		<filter-class>com.FilterDemo1</filter-class>
</filter>

<filter-mapping>
    
  	<filter-name>FilterDemo3</filter-name>
    <!--设置作用的url,即是Demo9这个Servlet应用这个过滤器-->
  	<url-pattern>/Demo9</url-pattern>   
<!-- <servlet-name>Demo9</servlet-name> 这个标签和上面的<url-pattern>是一个效果,直接指明应用的Servlet的名称 -->
    <!--Demo1也应用这个过滤器-->
    <servlet-name>Demo1</servlet-name>   
 </filter-mapping>
<!-- 定义FilterDemo1的过滤器 -->
    
    
    
<!-- 定义FilterDemo2的过滤器 -->
    <filter>
        <filter-name>FilterDemo2</filter-name>
        <filter-class>com.FilterDemo2</filter-class>
    </filte>
    
    <filter-mapping>
        <filter-name>FilterDemo2</filter-name>
<!--     Demo1这个Servlet文件也应用FilterDemo2这个过滤器,那么当请求Demo的时候要按照定义的先后顺序先执行FilterDemo1这个过滤器 -->
        <url-pattern>/Demo1</url-pattern>    
    </filter-mapping>
    
<!-- 定义FilterDemo2的过滤器 -->


    
    
    
</web-app>

注意

  • 可以在同一个<filter-mapping>中定义多个Servlet文件,表示多个Servlet都应用于这个过滤器
  • 一个Servlet文件可以同时应用多个过滤器,但是执行的顺序要按照定义的先后顺序执行

初始参数的设置和获取

设置初始值

这个和ServletConfig一样的都存在初始参数,当然定义的方式也是不尽相同,都是在web.xml中定义的,如下:

<filter>
  		<filter-name>FilterDemo3</filter-name>
  		<filter-class>com.FilterDemo3</filter-class>
  		<!--直接在filter下可以设置初始参数,当然我们可以在过滤器中获取参数-->
  		<init-param>
  			<param-name>username</param-name>
  			<param-value>陈加兵</param-value>
  		</init-param>
    
        <init-param>
  			<param-name>password</param-name>
  			<param-value>123456</param-value>
  		</init-param>
  		
</filter>

获取初始参数的值

直接利用其中的init(FilteConfig config) 获取初始化参数

package com;

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.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

public class FilterDemo1 implements Filter {

	public String username;
	public String password;
	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
	}

	//直接在init方法中利用FilterConfig的方法获取参数的值
	public void init(FilterConfig config) throws ServletException {
		//获取初始值
		username=config.getInitParameter("username");
		password=config.getInitParameter("password");
		
	}

}

设置触发的时机

当我们直接请求Servlet文件的url或者表单提交的时候使用的都是浏览器默认发出的请求,这个是可以触发过滤器的。但是如果是那些重定向(sendirect)或者转发包含(forward,include)就不会默认触发,因此我们需要在web.xml设置触发的时机,定义如下:

<filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/Demo1</url-pattern>
    <dispatcher>REQUEST</dispatcher>      <!--默认的-->
    <dispatcher>FORWARD</dispatcher>       <!--forward-->
    <dispatcher>INCLUDE</dispatcher>        <!--include-->
    <dispatcher>ERROR</dispatcher>        <!--error -->
</filter-mapping>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Springmvc解决中文乱码问题

    爱撒谎的男孩
  • Springmvc响应Ajax请求(@ResponseBody)

    爱撒谎的男孩
  • Struts2之OGNL的使用

    爱撒谎的男孩
  • SpringMVC处理Multipart数据

    一般的提交简单的文本格式的数据,基于文本的表单提交可以满足要求,但是对于传输视频和照片二进制文件,就不行了。

    黑白格
  • Java Web学习总结(五)——Servlet开发(一)

      Servlet是sun公司提供的一门用于开发动态web资源的技术。   Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(...

    Java团长
  • JavaWeb三大组件之Filter学习详解

    JavaWeb三大组件之Filter学习详解 Filter基本上可以说存在所有的JavaWeb项目中,比如最基本的一个请求参数的编码CharacterEnco...

    一灰灰blog
  • 即时通讯软件openfire+spark+smack

    所以我基本上分为三篇文章来介绍此类软件的开发: 第一篇是关于XMPP 协议是啥,IM 是啥以及一个比较有名的开源实现,该开源实现包括三个部分(Spark、Sma...

    xiangzhihong
  • thinkphp5使html5实现动态跳转的例子

    在application/模块名/controller/控制器名/方法名中对数据库进行获取,这里为了方便,举例为application/modulea/cont...

    砸漏
  • bboss会话共享 原

        区别于官方demo,这里介绍的是集群项目的session共享,以下是项目属性:

    尚浩宇
  • 使用SAP Cloud Application Programming模型开发OData的一个实际例子

    刚刚过去的SAP TechEd上,SAP CTO Juergen Mueller向外界传递了一个重要的信息:身处云时代大环境下的SAP从业者,在SAP云平台上该...

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券