-
流程引擎动态任务实现(收发文流程案例)
2020-06-22 17:27:03收发文流程实现,以及流程引擎中动态增加节点|临时子流程的使用。流程引擎动态任务实现。
1. 原始需求
收发文流程原始需求如下:2. 需求说明
2.1. 收文登记
普通环节处理(普通用户任务)
2.2. 收文拟办
选择1:领导阅示(1)、领导阅(2)、主办(3)、协办(4)可以选四者之一、四者的自由组合、四者全部;且这四者可以自由组合。
选择2:移交归档,如果选择移交归档的前提是承办环节必须被办理过,否则不能选择移交归档。
注意:选择1与选择2是互斥,不能同时选;收文拟办办理完毕后可以补发或撤回领导阅示、领导阅、主办、协办环节上的办理人,当都全部撤回完时,收文拟办会拥有初始时所有操作,不再有补发或撤回操作。
2.3. 领导阅示
办理完毕后,等待领导阅、主办、协办、承办办理,都办理完毕后流到收文拟办环节。
2.4. 领导阅
办理完毕后,等待领导阅示、主办、协办、承办办理,都办理完毕后流到收文拟办环节。
2.5. 主办
选择1:承办(3.1)、协办(3.2)以选二者之一、二者全部;
选择2:直接办理完毕,等待领导阅、领导阅示、协办办理,都办理完毕后流到收文拟办环节。
注意:
1、主办办理完毕后可以补发或撤回承办(3.1)、协办(3.2)环节上的办理人,当都全部撤回完时,主办会拥有初始时所有操作,不再有补发或撤回操作。
2.6. 移交主办
就是办理权移交给其他人
2.7. 承办
选择1:协办;
选择2:直接办理完毕,等待领导阅、领导阅示、主办、协办办理,都办理完毕后流到收文拟办环节。
注意:承办办理完毕后可以补发或撤回协办环节上的办理人,当都全部撤回完时,承办会拥有初始时所有操作,不再有补发或撤回操作。
2.8. 协办
办理完毕,等待领导阅、领导阅示、主办、承办、协办办理,都办理完毕后流到收文拟办环节。
2.9. 移交归档
流程结束。
3. 收发文需求特色
上述的收发文流程,需要工作流引擎具有如下几个能力。
1、任务节点定义人、办理能力。
2、流程部分区间支持排列组合产生任务的能力。(领导阅、主办、协办、承办)可以随便组合使用。
3、流程部分区间的任务可能没有连线的概念。任务的办理没有先后顺序,且可以无限的添加和删减。(这个与BPM2.0的部分概念有些冲突)。比如BPM有严格的先后顺序,任务节点必须有出线,否则实例会卡顿不前。流程部分区间的任务可能没有出线和入线。
4、任务的标记能力。流程部分区间的任务需要进行标记,否则引擎也不知道该区间的任务什么时候创建。
5、流程要有预测的功能,因为每一个节点可能要指定下一个处理的任务节点。
6、任务具有选择执行功能。比如流程节点预测要执行的任务节点是a/b两个节点,那么实际执行的时候,可能进行二选一或者全选执行的功能。
4. 收发文需求落地
4.1. 流程绘制4.2. 流程区间子流程配置
1、点击容器面板,选择展开子流程。
2、选择流程并删除开始节点,如下所示。
3、对需要执行的节点进行标记,如下所示。自定义属性需要增加标记。
adHocInit true
只有该标记的节点才可以任意选择创建。
4、对需要选择执行的任务的节点配置按钮,如下所示。
“可选按钮”可以在任务办理的时候,进行任务的选择。效果如下:
5. 收发文需求执行效果
5.1 流程启动
在申请事务选项卡中找到发起流程菜单,点击“发起流程”菜单,进入当前流程列表页,我们找到“收发文”并点击该流程,如下所示:在流程启动页面,我们填写请假表单:开始时间、结束时间、请假天数、请假事由;填写完成之后,点击启动按钮,如下所示:
5.2 审批流程
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,找到“收文登记”数据,并点击后面的“办理”按钮,如下所示:进入办理页面,我们点击“办理”按钮,如下所示:
5.3 收文登记-办理
在办理页面,可以看到下一个节点是“收文拟办”可以再次选择下一个节点的审批人员,设置优先级,设置任务标题,填写意见,信息核对无误后点击确定按钮,如下所示:5.4 收文拟办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,找到“收文拟办”数据,并点击后面的“办理”按钮,如下所示:在办理页面,点击可选办理,如下所示:
在办理页面,我们可以看到下一个节点信息多选框:领导阅示、领导阅、协办、主办,根据排列组合方式可知一共有24种情况,我们可以根据实际需求,选择哪些节点成为我们的下一个节点,在此处我们从24种情况中选择稍微复杂的主办,填写意见,并点击确定按钮,如下所示:
5.5 主办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,找到“主办”数据,并点击后面的“办理”按钮,如下所示:在办理页面,点击“可选办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点信息多选框,根据需求说明我们可知,主办的下一个节点可选协办和承办,根据排列组合方式一共有3种情况,此处我们验证两个节点都勾选的情况,并填写审批意见,点击确定按钮,如下所示:
5.6 协办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,可以看到有两条数据,一条“协办”数据,另一条“承办”数据;我们可以根据喜好选择先办哪条数据,此处我们选择协办数据,点击该数据后面的办理按钮,如下所示:在办理页面,点击“办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点显示:动态流程无需预测,填写审批意见,并点击确定按钮,如下所示:
5.7 承办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,现在只可以看到有一条“承办”数据,我们选择承办数据,点击该数据后面的办理按钮,如下所示:在办理页面,点击“办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点显示:协办,填写审批意见,并点击确定按钮,如下所示:
5.8 协办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,现在只可以看到有一条“协办”数据,我们选择协办数据,点击该数据后面的办理按钮,如下所示:在办理页面,点击“办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点显示:协办,填写审批意见,并点击确定按钮,如下所示:
5.9 收文拟办-办理
在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,此时只有一条数据“收文拟办”,点击该数据后面的办理按钮,如下所示:在办理页面,点击“办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点信息多选框:领导阅示、领导阅、协办、主办,根据排列组合方式可知一共有24种情况,我们可以根据实际需求,选择哪些节点成为我们的下一个节点,在此处我们从24种情况中选择稍微复杂的主办,填写意见,并点击确定按钮,如下所示:
(后续的操作,可以参考上文操作步骤)
5.10 移交归档
如果流程审核完成之后,需要移交归档,则在办理页面,我们选择移交归档,填写意见,并点击确定按钮,如下所示:在我的任务选项卡中找到我的任务菜单,点击“我的任务”菜单,进入我的任务列表页,在任务列表页,此时只有一条数据“移交归档”,点击该数据后面的办理按钮,如下所示:
在办理页面,点击“办理”,如下所示:
如果在此处您想看流程运转的流程图,可以点击流程图按钮,流程运转情况如下所示:
在办理页面,我们可以看到下一个节点信息为:结束,填写意见,并点击确定按钮,如下所示:
流程结束。
-
开源项目贡献代码流程
2020-11-07 18:05:16现将开源项目贡献代码流程成文,方便后续更多的同学参与到开源社区。 一.整体流程如下图 二.详细步骤 1.fork 作用:在GitHub(或gitlab,gitee)上,将别人项目引出一个新的分支到你的GitHub账号(fork字面意思...原来在github上断断续续给许多项目提交过pr(pull requests),比较有成就感的是参与的datax-web项目,目前已近1.8k star。现将开源项目贡献代码流程成文,方便后续更多的同学参与到开源社区。
一.整体流程如下图
二.详细步骤
1.fork
- 作用:在GitHub(或gitlab,gitee)上,将别人项目引出一个新的分支到你的GitHub账号(fork字面意思“叉子”)
- 操作:github项目右上角点击fork,如下图(因为我已经fork过,所以没有fork到waterWang的选项);
- 效果:自己的github上有了别人项目,可以看到项目从哪里fork过来的;
2.clone
- 作用:将fork到自己github账户的项目,从github克隆到自己机器,以便开发修改代码;
- 操作:git命令行或可视化git工具都可以(我习惯git命令行)。克隆如下图有三种方式,a地址克隆(又分https,SSH,GitHub CLI),b GitHub Desktop,c下载zip包
>git clone url-xxx # 输入命令后安静的等待进度达到100%
- 效果:本地文件夹中出现datax-web项目
3.checkout
- 作用:clone的下来默认的是master分支,但是开发尽量避免在master上—要开发,先切糕(checkout)
- 操作:命令行
>git checkout -b newBranchName # 默认以当前本地分支为基准,创建并切换到新分支。 #也可以以远程分支为基准,创建并切换到新分支 ,如下命令 git chekcout -b origin/master newBranchName #origin/master 是远程地址别名为origin上的master分支;
- 效果:创建出了一个新分支,并切换当前分支到新分支
4.add/commit
- 作用:上步骤切出新分支后,可以书写自己代码,本地测试通过,可以进行代码的提交
- 操作:git命令行
>git add . # git add 还有很多用法,本文不再赘述 >git commit -m 'sth msg' # git commit 还有很多用法,已经msg的规范,本文不赘述
- 效果:代码已经全部存在本地仓库(git status后提示nothing to commit, working tree clean)
5.push
- 作用:从本地仓库将分支推到远程自己GitHub上。
- 操作:git命令行
>git push origin branchName
- 效果:GitHub上对应项目上多看一个分支;
6.pull request
- 作用:将上步骤的远程分支请求合并到原作者的项目上(真正意义上为开源项目提交代码)
- 操作:GitHub页面。在原作者的项目页面点击pull request–》new pull request,(也可以直接点击compare and pull request)
注意选择从哪里合并到哪里(注意箭头方向),GitHub会检测代码是否可以合并,如果可以就会出现Able to merge,反之需要先解决代码冲突。
- 效果:“pull request”合并请求已经发生,安静的等待原作者处理该请求。
-
从源码分析SpringMVC核心处理流程
2020-12-01 16:00:39之前我们都是从一些官方文档或者是博客中了解了springMVC的整个处理流程,并且在前面博客我们也自己动手模拟了一个简单的springMVC容器,那么今天我们就对照流程图从源码分析一下S pringMVC的核心处理流程。...引言
之前我们都是从一些官方文档或者是博客中了解了springMVC的整个处理流程,并且在前面博客我们也自己动手模拟了一个简单的springMVC容器,那么今天我们就对照流程图从源码分析一下S pringMVC的核心处理流程。
一、SpringMVC处理流程图
这张图已经非常清楚的画除了整个SpringMVC的处理流程,里面还写出了每个处理环节当中的类,当然如果没有 分析过源码,那么上面的图看起来会非常的乱。尤其是里面的一些核心类,所以如果想很愉快的欣赏上面的 流程图,就需要我们看过几遍源码。
二、DispatcherServlet 核心处理流程
DispatcherServlet 其实就是一个普通的servlet,所以当一个请求来到servlet的时候,肯定首先会进入service()方法,所以我们的入口方法肯定是service()方法:
进入DispatcherServlet方法:
public class DispatcherServlet extends FrameworkServlet
我们在DispatcherServlet方法中我们没有发现service方法,所以肯定在父类的FrameworkServlet类中
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } }
从上面代码中我们会发现它继续调用了父类的service方法,所以我们继续进入到HttpServlet类中,在这个类中会见到我们非常熟悉的代码,也就是处理我们常见的几种处理方法:GET HEAD DELETE POST PUT等。
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } 。。。。。。。。。。。 }
这里我们分析Get请求,当我们进入到源码以后会发现,get方法比其他的方法复杂一点,这是因为在get 和 head 方法里面处理一个缓存,也就是这个 lastModified,这在我们前后端分离之前会用到,也就是提高get请求的性能,类似时间戳的作用。这个东西在现在的前后端分离的架构中不是很重要了。
下面我们就开始进入找到get请求的主要实现里面:
这样我们进入到一个processRequest方法,在doservice() 方法之前都是完成一些属性赋值。doservice()就是我们的核心方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); //赋值一些属性 RequestAttributes 非常熟悉哈 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); initContextHolders(request, localeContext, requestAttributes); try { //核心方法 doService(request, response); } catch (ServletException | IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } logResult(request, response, failureCause, asyncManager); publishRequestHandledEvent(request, response, startTime, failureCause); } }
进入doService()核心方法:
@Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); 。。。。。。。。。。 //省略的代码主要是往request对象中赋值属性 try { //核心代码 doDispatch(request, response); } }
三、doDispatch()核心方法
核心执行流程图:
开始分析doDispatch()核心方法,这里面完成核心流程,先来总体分析一下里面的几个核心方法,我都已经添加了注释,其实就是我们自己手写框架的时候实现的几个步骤。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //检查文件上传 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. //获得处理器HandlerMapping,这里返回的不在单个的HandlerMapping,而是HandlerExecutionChain 处理器+拦截器链 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //获得对应的 适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //执行拦截器前 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. //执行具体的处理器逻辑 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); //执行拦截器中方法 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } // 处理返回结果和视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
1) 首先我们进入到 mappedHandler = getHandler(processedRequest); 这个方法,也就是完成根据URI获得处理器映射器的流程:
//这个代码是不是非常的熟悉,和我们手写框架中的代码几乎一样 @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { //获得对应的处理器+拦截器链 HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
2、mapping.getHandler(request);具体实现逻辑在模板类AbstractHandlerMapping 实现
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //获得框架内置的处理器和拦截器链 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } //获得完整的链 核心方法 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); config = (config != null ? config.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
3、getHandlerExecutionChain(handler, request);
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { //获得HandlerExecutionChain对象,HandlerExecutionChain构造器方法合并interceptors到interceptorList HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); // 将adaptedInterceptors添加到chain中,并存入到initInterceptorList中 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }
上面几个核心方法我们获得了处理器,下面我们需要根据 处理器获得对应的适配器。
4、getHandlerAdapter(mappedHandler.getHandler());获得适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
上面的方法我们就会非常的熟悉,获得适配器的代码和我们自己手写的框架中的代码是一样的。
5、mappedHandler.applyPreHandle(processedRequest, response);执行拦截器前方法,在执行具体的处理逻辑之前执行
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { //获得拦截器 HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; //执行拦截器前方法, if (!interceptor.preHandle(request, response, this.handler)) { //执行拦截器后方法,规范上有规定,拦截器后的方法必须执行一次 triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true; }
6、mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 执行具体业务逻辑
7、处理以后逻辑
//渲染视图 applyDefaultViewName(processedRequest, mv); //执行拦截中的方法 mappedHandler.applyPostHandle(processedRequest, response, mv); //处理返回值逻辑 rocessDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
四、小结
本文从源码分析了springmvc的执行流程,通过这次分析,对于整个执行流程有了更深入的了解, 重要的是培养我们阅读源码的习惯。
-
For循环执行顺序流程
2018-05-07 15:06:15有以下for循环执行代码较为基础,所以画图给大家讲解一下for循环执行步骤1.执行for循环体里的第一个参数,也就是定义一个int整形...执行完循环体里的代码后,就会去执行for循环的第三个参数也就是++i当以上流程执行...有以下for循环执行代码
较为基础,所以画图给大家讲解一下for循环执行步骤
1.执行for循环体里的第一个参数,也就是定义一个int整形变量,其变量名为i,并初始化为0
2.执行完第一个参数里的代码后,会执行第二个参数,判断i是否小于99
3.当第二个表达式为True时会去执行循环体里的代码,也就是当i不等于99的时候
4.执行完循环体里的代码后,就会去执行for循环的第三个参数也就是++i
当以上流程执行完成之后,进入非第一次执行循环时就不会执行for循环第一个参数了
而是直接去执行第二个参数里的判断表达式
然后在去执行循环体里的代码
然后在执行for循环的第三个参数
直到参数二:i>99的时候循环才会结束
-
SpringMVC的简介和工作流程
2019-04-08 17:15:16一、简介 Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块...二、工作流程 1、用户发送请求至前端控制器DispatcherServlet。... -
软件测试工作流程概括与总结
2018-08-08 23:37:45最近在为面试新工作做准备,所以想想整理一下软件测试的基本工作流程,大致梳理一遍,这样也便于自己在面试过程中可以沉着的面对面试管的测试工作如何进行的问题。 首先,作为测试人员需要学习并了解业务,分析需求... -
APP启动流程解析
2019-04-22 10:07:15启动流程简介 首先要知道的是,手机屏幕其实就是一个Activity,我们专业点将其称为Launcher,相信做过车载设备开发的朋友肯定不会陌生,Launcher是手机厂商提供的,不同的手机厂商比拼的就是Launcher的设计。当然... -
activiti流程例子:详解员工请假流程的实现
2018-08-15 11:12:311. 部署了多个流程变量,如何准确开启特定的流程 2. 在一个流程的执行过程中,怎么确定执行到哪一步,即执行到哪个任务了 3. 在有多种情况的条件下,怎么判断要去的方向 先不急着解决,来看看我的工程 工程模拟情况 ... -
敏捷实践流程学习
2019-12-07 12:50:55个体和互动 高于 流程与工具 工作的软件 高于 详尽的文档 客户合作 高于 合同谈判 响应变化 高于 遵循计划 一、:召开IPM会议(BA主导,迭代计划会议) 会议内容:(需要提前准备好原型,写好AC)PM讲解原型,... -
详解微信小程序支付流程
2018-07-02 18:22:57花了几天把小程序的支付模块接口写了一下,可能有着公众号开发的一点经验,没有入太多的坑,在此我想记录一下整个流程。首先先把小程序微信支付的图搬过来:相信会来查百度的同学们基本都是对文档的说明不是很理解。... -
ASCII流程图
2017-12-30 14:07:14看过RFC文档的同学一定对它上面的纯字符流程图记忆犹新,今天推荐一个专门画这种ASCII流程图的网站: asciiflow -
SpringMVC工作流程
2019-08-06 10:10:35SpringMVC工作流程解析 -
单线流程
2018-01-28 13:01:11绝对的单线流程 用户进入某个流程后,只有“前进”和“后退”,没有其他多余的干扰流程。 1.最简单的单线流程 2.稍微复杂的单线流程 单线流程注意点 1.清晰的布局 1)只采用上下结构或左右结构,... -
如何设计订单流程(包含多个订单流程和流程节点包含子流程)
2018-01-05 09:53:35如何设计订单流程 1 背景: 包含多个订单流程和流程节点包含子流程: 不同的产品的订单会走不同的流程,不同的订单状态,在订单详情页显示不同的按钮。 2 需求分析 3 设计方法 3.1 状态机 如何根据当前状态... -
流程图
2018-09-12 17:59:11流程图 流程图是表示算法思路的一种方法,流程图以特定的图形符号加上说明,表示算法的图。 一、流程图的组成 流程图一般由圆角矩形、矩形、菱形、平行四边形、箭头组成。 二、流程图图形的作用 流程图一般... -
Android基础编译流程
2019-10-30 18:43:59Android工程的构建打包是一个非常复杂的流程,涉及工程源代码、资源文件、AIDL文件,以及工程所依赖的库文件的编译转换。编译流程非常灵活,因此了解它的一些底层工作原理会很有帮助。 从谷歌官网上找到一张典型的... -
vue 流程图组件_Vue.js 的流程图和流程图设计器组件
2020-07-28 05:13:44vue 流程图组件 流程图 (Flowchart) Flowchart & Flowchart designer component for Vue.js. Vue.js的流程图和流程图设计器组件。 View Demo 查看演示 View Github 查看Github 用法 (Usage) yarn add flow... -
数据流程图 状态图 流程图
2018-04-23 14:43:38数据流程图 状态图 流程图 数据流程图 数据流程图(DFD)提供了通过系统的数据流的图形表示。它逻辑上显示了我们的系统进程和外部接口或数据存储交换了哪些信息,但是它没有明确显示信息交换的时间或顺序。 ... -
Java流程控制语句
2019-09-28 23:05:26流程是指程序运行时,各语句的执行顺序。流程控制语句就是用来控制程序中各语句执行的顺序。 分类 顺序结构 Java流程控制语句-顺序结构 分支结构(选择结构) Java流程控制语句-分支结构(选择结构) 循环结构 Java... -
通过流程定义id,开启流程定义,得到流程实例
2018-06-26 19:43:44在部署了一个Zip包后,流程部署表act_re_deployment与流程定义表act_re_procdef均会插入一条新的记录。 这个在之前已经讨论过了。今天要开启流程定义,将流程定义启动。 要准备的操作是:查询程定义实例,也就是对... -
Activiti流程定义缓存源码分析5-流程缓存
2020-02-06 21:05:24首先我们有一种常见的应用场景,比如我们定义流程文档的时候,通常任务节点的使用会非常的频繁,如果我们将流程文档部署之后,流程实例运行了一段时间突然发现任务节点的名称、分类或者处理人需要修改,这个时候我们... -
SIP呼叫流程典型流程图解
2017-11-24 10:05:13注销流程:… 33. 基本呼叫建立过程:… 44. 会话更改流程:… 55. 正常呼叫释放过程:… 66. 被叫忙呼叫释放:… 77.被叫无应答流程一:… 88.被叫无应答流程二:… 99.遇忙呼叫前转:… 1010.无应答呼叫前... -
用java画工作流流程图,java生成流程图
2016-06-30 09:15:32用java画工作流流程图,java生成流程图 -
第13篇: Flowable-BPMN操作流程之流程进展查看之流程图
2019-11-04 18:17:17流程启动后,为了方便我们查看流程的进展,Flowable提供了流程图可以直观的查看流程的进展,本节我们主要研究流程图呈现的相关内容,可以直接显示流程的进展。 原理 流程的一些进展是活动Activity和连线组成的,我们... -
Flowable深入浅出-13 Flowable-BPMN操作流程之流程进展查看之流程图
2019-01-17 21:24:4913 Flowable-BPMN操作流程之流程进展查看之流程图背景原理实现方案验证代码下载打赏版权 背景 流程启动后,为了方便我们查看流程的进展,Flowable提供了流程图可以直观的查看流程的进展,本节我们主要研究流程图呈现... -
渲染流程
2017-08-25 21:53:04应用阶段流程:由cpu进行控制,主要流程如下 1.准备哪些对象被渲染,哪些被剔除,然后将要渲染的对象从硬盘加载到内存,然后从内存加载到显存,方便gpu高速处理。 2.设置每个对象的渲染状态,也就是设置对象所需的材质,... -
activiti 查询流程定义启动流程
2017-03-25 20:00:51要启动流程就必须要知道有哪些流程,可能会涉及到权限的问题,所以启动流程前先查询流程定义的信息(流程定义的信息放在act_re_procdef的表中)所以用RepositoryService中的方法查询,可以根据act_re_procdef表的... -
一个软件完整的开发流程介绍
2018-03-29 19:11:28刚开始写博文的时候就应该将这个文章更新一下,虽然不是什么大牛,但是对于软件的开发流程还是比较了解的,毕竟大大小小做过了好几个项目了,今天就大概的说一下,用我做过的一个项目来说吧,写的不好的,请多多见谅... -
流程梳理
2014-04-15 11:06:43流程梳理很多CIO和我联系希望我讲讲流程管理、流程和IT结合的事。因为CIO们在推进IT项目时候,不理解业务流程、企业业务流程不清晰、业务流程和IT功能怎么结合使用,这些问题给IT项目的推进带来了很大的阻碍,所以... -
流程图怎么画
2017-12-20 21:14:49最近在看博客的时候发现很多流程图都不是流程图,想画成流程图但是总有些时候会变了样子,所以我就想说说流程图到底因该怎么画。 组成 流程图一般由由圆角矩形、矩形、菱形、平行四边形、箭头组成。 作用 流程图...