struts2执行流程
很多同学在进行编程学习时缺乏系统学习的资料。本页面基于struts2执行流程内容,从基础理论到综合实战,通过实用的知识类文章,标准的编程教程,丰富的视频课程,为您在struts2执行流程相关知识领域提供全面立体的资料补充。同时还包含 safari浏览器、samba、SAMP 的知识内容,欢迎查阅!
struts2执行流程相关知识
-
sparksql执行流程分析在前面的文章《spark基础(上篇)》和《spark基础(下篇)》里面已经介绍了spark的一些基础知识,知道了spark sql是spark中一个主要的框架之一。本文我们通过源码,来介绍下spark sql的执行流程。 Spark sql是spark内部最核心,也是社区最活跃的组件。Spark SQL支持在Spark中执行SQL,或者HiveQL的关系查询表达式。列式存储的类RDD(DataSet/DataFrame)数据类型以及对sql语句的支持使它更容易上手,同时,它对数据的抽取、清洗的特性,使它广泛的用于etl,甚至是机器学习领域。因此,saprk sql较其他spark组件,获得了更多的使用者。 下文,我们首先通过查看一个简单的sql的执行计划,对sql的执行流程有一个简单的认识,后面将通过对sql优化器catalyst的每个部分的介绍,来让大家更深入的了解sql后台的执行流程。由于此模板中代码较多,我们在此仅就执行流程中涉及到的主要代码进行介绍,方便大家更快地浏览spark s
-
Spark Task 的执行流程③ - 执行 task本文为 Spark 2.0 源码分析笔记,其他版本可能稍有不同创建、分发 Task一文中我们提到 TaskRunner(继承于 Runnable) 对象最终会被提交到 Executor 的线程池中去执行,本文就将对该执行过程进行剖析。该执行过程封装在 TaskRunner#run() 中,搞懂该函数就搞懂了 task 是如何执行的,按照本博客惯例,这里必定要来一张该函数的核心实现:需要注意的是,上图的流程都是在 Executor 的线程池中的某条线程中执行的。上图中最复杂和关键的是 task.run(...) 以及任务结果的处理,也即怎么把各个 partition 计算结果汇报到 driver 端。task 结果处理这一块内容将另写一篇文章进行说明,下文主要对 task.run(...) 进行分析。Task 类共有两种实现:ResultTask:对于 DAG 图中最后一个 Stage(也就是 ResultStage),会生成与该 DAG 图中哦最后一个 RDD (DAG 图中最后边)partition 个数
-
简单模仿Struts2实现AOPStruts2非常巧妙地利用递归算法来实现AOP(Aspect Oriented Programming,面向切面编程),我们来简单模仿一下其执行流程。 Action接口: public interface Action { String execute(); } MyAction实现Action: public class MyAction implements Action { @Override public String e
-
Spark Job 详细执行流程(二)Spark Job执行流程大体如下:用户提交Job后会生成SparkContext对象,SparkContext向Cluster Manager(在Standalone模式下是Spark Master)申请Executor资源,并将Job分解成一系列可并行处理的task,然后将task分发到不同的Executor上运行,Executor在task执行完后将结果返回到SparkContext。上文中(戳这)详细介绍了Spark申请Executor资源的过程。下面介绍Job从拆分成一系列task到task分发到Executor上运行的过程。整个过程如下图所示。Job执行流程DAGScheduler接收用户提交的job用户提交Job后,SparkContext通过runJob()调用DAGScheduler的runJob()。在runJob()中,调用submitJob来提交Job,然后等待Job的运行结果。def runJob[T, U]( &
struts2执行流程相关课程
struts2执行流程相关教程
- 3. 流式操作的执行流程 流式操作通常分为以下 3 个步骤:创建Stream对象:通过一个数据源(例如集合、数组),获取一个流;中间操作:一个中间的链式操作,对数据源的数据进行处理(例如过滤、排序等),直到执行终止操作才执行;终止操作:一旦执行终止操作,就执行中间的链式操作,并产生结果。下图展示了Stream的执行流程:接下来我们就按照这 3 个步骤的顺序来展开学习Stream API。
- 4.3 NioEventLoop 执行流程 上面讲解了 NioEventLoop 的初始化流程,那么它到底在什么时候开始执行的呢?源码入口:serverBootstrap.bind(80);第一步: 抽象类 AbstractBootstrappublic abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable { public ChannelFuture bind(int inetPort) { return this.bind(new InetSocketAddress(inetPort)); } public ChannelFuture bind(SocketAddress localAddress) { this.validate(); if (localAddress == null) { throw new NullPointerException("localAddress"); } else { //继续跟进 return this.doBind(localAddress); } } private ChannelFuture doBind(final SocketAddress localAddress) { //继续跟进 final ChannelFuture regFuture = this.initAndRegister(); } final ChannelFuture initAndRegister() { //继续跟进 this.init(channel); } //抽象方法 abstract void init(Channel var1) throws Exception;}第二步: 实现类 ServerBootstrappublic class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> { void init(Channel channel) throws Exception { //1.把 ChannelHandler 添加到 ChannelPipeline 里,组成一条双向业务链表 p.addLast(new ChannelHandler[]{new ChannelInitializer<Channel>() { public void initChannel(Channel ch) throws Exception { //1.1.管道 final ChannelPipeline pipeline = ch.pipeline(); //1.2.添加到管道 ChannelHandler handler = ServerBootstrap.this.config.handler(); if (handler != null) { pipeline.addLast(new ChannelHandler[]{handler}); } //1.3.执行线程池的 “execute()”,核心入口 ch.eventLoop().execute(new Runnable() { public void run() { pipeline.addLast( new ChannelHandler[]{ new ServerBootstrap.ServerBootstrapAcceptor( currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs) } ); } }); } }}); }}这里是在 init () 方法里面进行一序列的初始化工作,并且执行上面初始化好的 NioEventLoop 的 execute () 方法。第三步: 执行 SingleThreadEventExecutor 的 execute () 方法public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor { public void execute(Runnable task) { //是否是当前线程 boolean inEventLoop = this.inEventLoop(); if (inEventLoop) { //如果是当前线程,则添加任务到队列 this.addTask(task); } else { //如果不是当前线程,则先启动线程 this.startThread(); //把任务添加到任务队列 this.addTask(task); //如果线程已经关闭并且该任务已经被移除了 if (this.isShutdown() && this.removeTask(task)) { //执行拒绝策略 reject(); } } } private void startThread() { this.doStartThread(); } private void doStartThread() { this.executor.execute(new Runnable() { public void run() { //执行 run() 方法 SingleThreadEventExecutor.this.run(); } }); } //抽象方法 protected abstract void run();}第四步: 子类 NioEventLoop 实现抽象方法 run (),这里是 run () 方法是一个死循环,并且执行三个核心事件,分别是 “监听端口”、“处理端口事件”、“处理队列事件”。public final class NioEventLoop extends SingleThreadEventLoop { protected void run() { while(true) { //省略 } }}run () 方法里面核心执行了 this.processSelectedKeys() 和 this.runAllTasks()。
- 2. 下载中间件执行流程 我们现在来梳理下载中间件这个模块的执行流程。注意在 scrapy/downloadmiddlewares 目录下的代码并没有下载中间件的执行相关代码,该目录下是一系列定义好的内置下载中间件,大部分默认是启用的。这里的代码并不是我们想要的,那么和下载中间件执行流程相关的代码究竟在哪呢?首先回过来头看下前面描述 Scrapy 的架构图,可知下载中间件位于引擎和下载器之间。上一节中我们介绍了下载器类 (Downloader) ,其中有一个属性 self.middleware,如下图所示。下载器类中的连接下载中间件的属性该属性值是下载中间件管理器类 (DownloaderMiddlewareManager) 的一个实例,某种意义上来说它是连接下载模块和下载中间件模块之间的桥梁。我们继续研究下这个中间件管理器类,很明显它应该继承自上面介绍的中间件管理器类,事实也是如此:# 源码位置:scrapy/core/downloader/middleware.py# ...class DownloaderMiddlewareManager(MiddlewareManager): component_name = 'downloader middleware' @classmethod def _get_mwlist_from_settings(cls, settings): return build_component_list( settings.getwithbase('DOWNLOADER_MIDDLEWARES')) def _add_middleware(self, mw): if hasattr(mw, 'process_request'): self.methods['process_request'].append(mw.process_request) if hasattr(mw, 'process_response'): self.methods['process_response'].appendleft(mw.process_response) if hasattr(mw, 'process_exception'): self.methods['process_exception'].appendleft(mw.process_exception) # ...上面的两个方法非常容易理解,也透露了一些信息。对于下载中间件对象,中间件管理器主要提取的是中间件对象中的三个方法:process_request()、process_response() 以及 process_exception() 。注意这里方法进入队列的顺序,这也关系到框架对这些方法的调用顺序。在管理器类中还有一个非常重要的 download() 方法,该方法决定了上面三个方法返回不同值时的处理方案,同时也会将下载中间件中的三个方法按照相应的顺序添加到对应的回调链中:# 源码位置:scrapy/core/downloader/middleware.py# ...class DownloaderMiddlewareManager(MiddlewareManager): # ... def download(self, download_func, request, spider): @defer.inlineCallbacks def process_request(request): # 依次遍历下载中间件的process_request()方法,处理请求 for method in self.methods['process_request']: response = yield deferred_from_coro(method(request=request, spider=spider)) if response is not None and not isinstance(response, (Response, Request)): # 返回非Request或Response类型,抛出异常 # ... if response: return response # 最后将请求传给下载器执行下载 return (yield download_func(request=request, spider=spider)) @defer.inlineCallbacks def process_response(response): # 处理下载的响应 if response is None: raise TypeError("Received None in process_response") elif isinstance(response, Request): return response for method in self.methods['process_response']: response = yield deferred_from_coro(method(request=request, response=response, spider=spider)) if not isinstance(response, (Response, Request)): # 返回非Request或Response类型,抛出异常 # ... if isinstance(response, Request): # 如果返回Request,则直接返回,后续的中间件的process_response()不处理 return response # 最后返回响应结果 return response @defer.inlineCallbacks def process_exception(failure): exception = failure.value for method in self.methods['process_exception']: response = yield deferred_from_coro(method(request=request, exception=exception, spider=spider)) if response is not None and not isinstance(response, (Response, Request)): # 返回非Request或Response类型,抛出异常 # ... if response: return response return failure # 调用请求,同时将process_request()依次加入回调链中并返回一个Deferred对象 deferred = mustbe_deferred(process_request, request) # 异常回调 deferred.addErrback(process_exception) # 响应回调 deferred.addCallback(process_response) return deferred这个 download() 方法非常重要,也有些难以理解。注意一点:该方法主要是形成一个完整的下载链路,包括请求链 (process request chain)、下载请求 (在 download() 方法的 download_func 参数)、响应处理链 (process response chain),另外还加上一个请求异常的回调链。来看看我们对这个过程的一个总结图:下载中间件管理对象的download()方法注意,中间件管理器会和引擎模块以及下载模块之间有交互,那么它们之间发生交互的代码是哪一句呢?这里就不卖关子和追踪了,我们直接给出答案:下载中间件管理对象和下载器的交互就在于 download() 方法中传进来的 download_func 参数。我们在下载器中找到如下代码:# ...class Downloader: # ... def fetch(self, request, spider): def _deactivate(response): self.active.remove(request) return response self.active.add(request) # 调用下载中间件管理对象的download()方法 dfd = self.middleware.download(self._enqueue_request, request, spider) return dfd.addBoth(_deactivate)这里调用的下载中间件管理对象 download() 中的 download_func 参数为 self._enqueue_request,而我们在上一节中正好介绍过该方法正好是下载器中下载网页的起始方法。另一方面,引擎模块和该下载中间件管理器类的交互也正是通过下载器的这个 fetch() 方法。我们直接找出相关的代码语句: # 源码位置:scrapy/core/engine.py # ... class ExecutionEngine: # ... def _download(self, request, spider): # ... # 这里的self.downloader就是下载器对象,调用fetch()方法下载网页 dwld = self.downloader.fetch(request, spider) dwld.addCallbacks(_on_success) dwld.addBoth(_on_complete) return dwld总的来说,我们可以得到如下的一个调用过程:scrapy中下载部分的简要调用过程到目前为止,我们对下载中间件的执行流程进行了一个简要的概述,但没深究其中的代码细节。如果有兴趣的话可以仔细跟踪下代码的执行过程,这些并不复杂,主要是对 Twisted 模块的应用。
- 2.5 执行器 现在到了执行SQL语句的阶段,也就是执行器。执行器负责调用存储引擎,拿到查询结果。select id from a where id=1;假设这个例子中的字段id没有索引,执行器的流程大致如下:调用 InnoDB 引擎接口获取表 a 的第一行,如果 id 值等于 1,则将 id 值存进结果集,如果 id 值不等于 1,则跳过,取下一行;调用 InnoDB 引擎接口获取下一行,重复第一步的逻辑,一直到表 a 的最后一行;将符合查询条件的结果集返回给客户端。
- 4. 生命周期执行流程 ChannelHandler 的一些特殊回调方法,这些回调方法的执行是有顺序的,而这个执行顺序可以称为 ChannelHandler 的生命周期。
- 1.1 流程控制简介 Shell 脚本默认从上到下顺序执行,在程序运行中,会遇到很多种情况,对应不同情况执行对应的操作,例如对于一批数据需要进行执行重复工作,这些都需要我们使用特定的流程控制语句来实现,我们想要程序完成预定的操作,就需要熟练掌握流程控制语句,不同的流程控制语句有不同的适应场景。
struts2执行流程相关搜索
-
s line
safari浏览器
samba
SAMP
samplerate
sandbox
sanitize
saper
sas
sass
save
smarty模板
smil
smtp
snapshot
snd
snmptrap
soap
soapclient
soap协议