Filter执行流程

Filter是从Servlet2.3规范开始新增的功能,并在Servlet2.4规范中得到增强,接下来让我们一起来看看Filter的真实面目吧。

一. 概念

    过滤器就是在源数据和目的数据之间起过滤作用的中间组件。对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和资源之间的请求与响应信息,并对这些信息进行过滤。

 

二. 执行流程

    当Web容器接受到一个对资源的请求时,它就会判断是否有过滤器与这个资源相关联(这是一个自动的过程)。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,再过滤器中,你可以对响应的内容进行转换,然后再将响应发送到客户端.。

    如果有多个过滤器,则它会像一个链(根据web.xml中的位置)一样执行。

    我们先看一个图:

   

三. 实例及解析

    我们来看一个登录的例子,它需要用到两个过滤器,一个是转换编码格式,一个是判断是否登录。

    先看一下这个例子的时序图:

    

    接下来我们看一下源码:

   login.jsp

<%@ page language="java" contentType="text/html; charset=GB18030"
	pageEncoding="GB18030"%>
<%
	String command = request.getParameter("command");
	if ("login".equals(command)) {
		if ("dan".equals(request.getParameter("userId"))
				&& "123".equals(request.getParameter("password"))) {

			//登陆成功将用户信息放到session中
			session.setAttribute("user_name",
					request.getParameter("userId"));

			//设置超时,单位:秒
			session.setMaxInactiveInterval(6000);

			//重定向到主控页面
			response.sendRedirect(request.getContextPath() + "/main.jsp");
		}
	}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>登录</title>
<SCRIPT language=JavaScript>
	function init() {
		loginForm.userId.focus();
	}

</SCRIPT>
</head>
<body οnlοad=init()>
	<FORM name="loginForm">
		<input type="hidden" name="command" value="login">	
		用户名:  
		<INPUT name="userId" value="dan" type="text" size="20"	maxlength="20"> 
		密   码: 
		<INPUT name="password"	value="123" type="password" size="21" maxlength="20"> 
		<input type="submit" οnclick="submitForm()" value="提交" name="login" id="login">
	</FORM>
</body>
</html>


   CharsetEncodingFilter.java

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 CharsetEncodingFilter implements Filter {

	private String encoding;
	
	@Override
	public void destroy() {
		
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain) throws IOException, ServletException {
		//设置字符集
		servletRequest.setCharacterEncoding(encoding);
		filterChain.doFilter(servletRequest, servletResponse);
		
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//取得初始化参数
		this.encoding = filterConfig.getInitParameter("encoding");
	}

}

   AuthFilter.java

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

public class AuthFilter implements Filter {

	public void destroy() {	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		String requestURI = req.getRequestURI().substring(
				req.getRequestURI().indexOf("/", 1),
				req.getRequestURI().length());
		if (!"/login.jsp".equals(requestURI)) {
			HttpSession session = req.getSession(false);
			if (session == null || session.getAttribute("user_name") == null) {
				res.sendRedirect(req.getContextPath() + "/login.jsp");
				return;
			}
		}
		// 继续访问其他资源
		chain.doFilter(req, res);
	}

	public void init(FilterConfig filterConfig) 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/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
    
  <filter>
    <filter-name>CharsetEncodingFilter</filter-name>
    <filter-class>filter.CharsetEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>GB18030</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharsetEncodingFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
  </filter-mapping>
  <filter-mapping>
  	<filter-name>CharsetEncodingFilter</filter-name>
  	<url-pattern>/servlet/*</url-pattern>
  </filter-mapping>
  
  <filter>
  	<filter-name>AuthFilter</filter-name>
  	<filter-class>filter.AuthFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>AuthFilter</filter-name>
  	<url-pattern>*.jsp</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  	<filter-name>AuthFilter</filter-name>
  	<url-pattern>/servlet/*</url-pattern>
  </filter-mapping>
    
</web-app>


Filter中主要有三个方法init(),doFilter(),destroy()

  1.init(FilterConfigfilterConfig)     

    Web容器调用该方法该方法来初始化过滤器。容器在调用该方法时,向过滤器传递

FilterConfig对象,利用FilterConfig对象可以得到ServletContext对象,以及部署描述符中配置的过滤器的初始化参数。

    

    从图中可以看出来Listener,Filter,Servlet及Tomcat的一个启动顺序。

    2.doFilter(ServletRequestrequest, ServletResponse response,FilterChain chain)

    这是Filter的主要方法,其中的request和response和servlet里的参数一样,至于chain是用于后面对请求的转发的,该参数的chain.doFilter方法是一种回调过程。

    该方法以chain.doFilter()为界限,先执行前面的代码,然后执行chain.doFilter()方法来将请求传递给下一个Filter(如果没有Filter了就传递给Servlet),等到这条链执行完后,再往回执行后面的代码,它是使用回调来实现的。    

     大家可以通过下面的图来进行理解:

    

    3.destroy()

     这个方法servlet的destroy()方法一样,都是当服务器断开的时候才执行该销毁方法,Filter也是实例化一次,多次调用。


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Spark的执行流程包括以下几个步骤: 1. 创建SparkSession:SparkSession是Spark应用程序的入口点,用于与Spark进行交互。在创建SparkSession时,需要指定应用程序的名称和配置信息。 2. 创建RDD或DataFrame:Spark支持两种数据抽象类型:弹性分布式数据集(RDD)和数据框架(DataFrame)。RDD是Spark中最基本的数据结构,而DataFrame则是基于RDD的高级数据结构。你可以从外部数据源(如文件系统、数据库等)中读取数据,或者通过转换操作从已有的RDD或DataFrame中创建新的数据集。 3. 转换操作:Spark提供了一系列的转换操作,如map、filter、reduce等。转换操作并不立即执行,而是会生成一个新的RDD或DataFrame。这些转换操作可以链式调用,形成一个转换操作的有向无环图(DAG)。 4. 行动操作:当需要获取计算结果时,就需要触发行动操作。行动操作会触发Spark引擎根据转换操作的DAG来执行计算,并将结果返回给驱动程序。 5. 优化执行计划:在执行转换操作之前,Spark会对转换操作的DAG进行优化,以提高执行效率。优化过程包括选择最佳的执行计划、重排转换操作的顺序、合并相邻的转换操作等。 6. 任务划分与调度:Spark将执行计划划分为一系列的任务,并将这些任务分发到集群中的多个执行器上并行执行。任务划分的策略可以根据数据分区进行优化,以实现数据本地性和负载均衡。 7. 执行任务:每个执行器会接收到一些任务,并根据指定的转换操作进行计算。计算过程中,Spark会利用内存和磁盘进行数据交换和缓存,以提高计算效率。 8. 结果返回:当所有任务执行完成后,计算结果会被返回给驱动程序,可以进行进一步的处理或输出。 需要注意的是,Spark的执行流程是延迟计算的,只有在触发行动操作时才会真正执行计算。这种延迟计算的特性使得Spark可以对计算进行优化,并支持容错和增量计算等特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值