前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Servlet总结四(过滤器)

Servlet总结四(过滤器)

作者头像
爱撒谎的男孩
发布2019-12-31 14:31:43
3380
发布2019-12-31 14:31:43
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

  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的后置处理。
代码语言:javascript
复制
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()方法中的是一样的,即是可以设置属性,可以得到表单提交的值,总之是一样的。

简单的例子

  • 下面实现一个过滤器用来验证提交请求的用户名和密码是否正确
代码语言:javascript
复制
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中设置过滤器,设置的方式如下:
代码语言:javascript
复制

<?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中定义的,如下:

代码语言:javascript
复制
<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) 获取初始化参数

代码语言:javascript
复制
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设置触发的时机,定义如下:

代码语言:javascript
复制
<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>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Servlet总结四(过滤器的使用)
    • 简介
      • 过滤器的实现
        • 重点
        • 简单的例子
        • 过滤器的设置
        • 初始参数的设置和获取
        • 设置触发的时机
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档