Velocity 不用愁!Velocity 系统的前端工程化之路

Velocity是一个基于Java的Web页面模版引擎。十多年前,Velocity将Java代码从Web页面中分离出来,使得开发者能够并行网页开发和Java开发。随着十年前后端分离的浪潮涌动,回首再面对这些基于Velocity的旧系统,无论是后端还是前端人员维护,都会存在诸多问题:

(1)后端人员维护:不熟悉前端开发模式,需要花费大量精力学习UI和Js框架;

(2)前端人员维护:Velocity渲染依赖Java环境,需要花费大量精力学习Maven工程、环境配置,且前端MVC框架版本老,开发效率低。

这种情况广泛存在于零售内部的一些旧系统中,且业务需求的不断迭代,会导致系统维护成本越来越高。针对需要频繁迭代的页面模块,常见的应对措施是采用前后端分离方案,对页面进行整体重构,但如此以后,整体重构的代价是巨大的,主要体现在如下几点:

(1)需要覆盖所有的业务场景和需求;

(2)缺乏覆盖全场景的测试物料;

(3)页面重构本身不带来业务价值。

我们团队承担了B端业务,由于业务启动时间早,也不可避免需要维护这些Velocity系统。

针对老系统维护难的痛点,我们在实践中探索了一种对老系统侵入程度低、技术架构缓步升级的技术路线,分为4个步骤,分别是(1)搭建Velocity+MVC+MVVC混合架构;(2)建立Velocity单文件组件化能力;(3)创建Velocity本地沙盒环境;(4)Velocity页面前后端分离。下面分别进行详细说明:

一、 搭建Velocity + MVC + MVVC混合架构

Velocity系统多数还在使用JQuery等Js框架,开发效率低,亟待改善。对比MVC框架和MVVC框架,MVVC框架封装了视图层逻辑,开发效率显著提升。

因此第一个步骤是在Velocity页面中引入MVVC框架,实现两套技术架构的共存。我们引入了Vue以及配套的UI组件库,考虑Vue的主要因素有以下几点:

(1)Vue支持Js资源链接的方式引入和使用,即在Velocity页面中加入一行script标签即可实现开箱即用;

(2)Velocity的页面编写语法与Vue的模板语法非常接近。

混合架构内部,模板渲染需要分两步进行: Velocity模板首先在服务端渲染为Vue模板,Vue模板在客户端渲染为最终页面。

混合架构存在的问题是,由于一些Session内关键参数是服务器直出,Vue并不能直接获取到这些参数,因此传参的方案是在页面中提前埋了一些占位符,Vue执行时通过访问DOM来获取。

后续需求迭代时,可以逐步将业务逻辑从老旧MVC技术栈迁移到新的MVVC技术栈中,实现开发、维护效率的提升。

二、 建立Velocity单文件组件化能力

当项目规模较大时,不同模块之间可能存在一些相似的功能或逻辑,摆在面前的问题是如何实现模块级的功能复用。

因此第二个步骤是在Velocity系统中引入组件化能力,实现跨页面代码复用。Velocity系统由于渲染依赖Java环境,难以适用基于NodeJs的前端工程化能力,无法直接使用Vue的单文件组件化能力。幸运的是,可以利用Velocity的包含(#include)和解析(#parse)能力,配合Vue的API接口,实现一种创新型的Velocity+Vue单文件组件化技术。

如果你熟悉Vue,你肯定对Vue单文件组件很熟悉了,即一个文件名以.vue后缀结尾的文件,它描述了一个Vue组件,内部结构的三板斧:template、script、style,简单来说分别描述了组件的模板呈现、逻辑交互、css样式。

Velocity单文件组件的组织方式参照了这个层级结构,使用一个文件名以.vm后缀结尾的文件,描述了一个Velocity组件,由于缺乏工程化的能力,区别点在于:(1)为了兼容低版本浏览器,需要使用script标签来承载模板;不考虑浏览器兼容性的情况下,也可以直接使用template标签。(2)需要手动调用Vue.component执行组件的注册。

实现单文件组件化之后,Velocity页面可以通过粒度更小的组件来层层组装,实现系统的业务耦合程度进一步降低。

三、 创建Velocity本地沙盒环境 + 前端工程化

前面两个步骤对系统整体架构进行了大幅优化,但是仍有一个痛点没解决:Velocity渲染依赖Java环境,习惯了本地开发的前端同学会很无语:改一个小问题需要本地盲开发->在线部署容器->看效果->继续盲修改,一来二去几个小时就过去了。

因此第三个步骤是实现Velocity本地编译和开发环境,并且引入工程化技术实现热更新。

解决Velocity本地编译的核心思路是模拟Server的环境变量,并且支持Velocity语法编译。我们搭建了一套基于Velocity的前端沙盒工程,前者通过在工程中mock服务端变量的方式来实现,在本地JSON数据源承载这些环境变量;后者是基于Velocity语法AST重构,开发了一套解析引擎Velocity-loader,支持在webpack中实时解析文件并注入环境参数。

沙盒能力引入后,开发流程转变为本地实时开发Velocity,热更新达到毫秒级,开发体验只有一个字:爽。

四、 Velocity页面前后端分离

事实上,对比前三个步骤,我们距离Velocity页面彻底前后端分离已经很接近了。

第四个步骤是真正实现Velocity页面的前端独立构建和部署,并永久摆脱依赖Server端渲染。但由于Vue-loader实际上会在工程编译时把模板语法解析成render函数,已经破坏了模板语法的结构,因此不能支持在客户端动态的解析Velocity,需要固化渲染环境变量。Velocity的动态数据渲染部分需要改写为Vue的语法来实现,托靠客户端Ajax来刷新动态数据和页面。

至此,我们完整实现了对Velocity后端应用向前端工程化逐步演进之路,路漫漫其修远兮,吾将上下而求索,也欢迎各位看官共同探讨。

作者:京东零售 陈震

内容来源:京东云开发者社区

本文转载于网络 如有侵权请联系删除

相关文章

  • Install Joomla

    前言是一款用php实现的开源CMS软件TheFlexiblePlatformEmpoweringWebsiteCreators Joomla!isanaward-winningcontentmanagementsystem(CMS),whichenablesyoutobuildwebsitesandpowerfulonlineapplications因为插件丰富,架构灵活,可以简单而快速实现大部分的网站功能,在国外很受欢迎,连续好几年都获得开源CMS的冠军这里演示一下如何构建参考Tip:当前的版本为Joomla3.8.6操作依赖软件SoftwareRecommendedMinimumMoreinformationPHP5.6+or7+5.3.10+www.php.net(MagicQuotesGPC,MBStringOverload=off/ZlibCompressionSupport,XMLSupport,INIParserSupport,JSONSupport,McryptSupport,MBLanguage=Default)数据库SupportedDatabasesRecomme

  • 帅瞎了!手机也能写Python代码!手把手教你在手机或平板上配置Python环境!

    本文旨在讲解如何在Android平板或手机上搭建Python开发环境,帮助Python初学者有效利用碎片化时间进行学习,从而达到良好的学习效果。对于大部分初学Python的人来说,由于工作、生活等因素常常无法进行连贯、系统的学习。初学者为了利用上下班通勤等碎片化时间进行学习,通常会在平板上观看学习视频并做记录。虽然这种方法很好,但效果还是不如边学边练来得好。因此,你需要的是这个:不多说,让我们开始吧!一、Termux安装与配置1.系统要求Android7.0以上的平板或手机。这里建议使用兼顾了便携性和屏幕尺寸的8寸平板。2G以上可用空间。由于需要安装各种软件包,对存储空间的消耗还是比较大的。 2.Termux安装在安装Termux前,需要了解一下什么是Termux。Termux是一款支持Linux环境的Android终端模拟器APP。你无需对手机进行root或额外设置即可使用。这款APP会在手机中自动安装一个最小化基本系统,并支持使用APT包管理工具安装软件。目前Termux官网(https://termux.com/)建议使用F-Droid进行安装,不再支持通过GooglePlay

  • 【Z讲堂】Zabbix4.0之趋势预测

    【Z讲堂】Zabbix趋势预测作者:DmitryLambertZabbix培训师监控不一定是指过去和现在。利用Zabbix的趋势预测功能,即可分析已收集的数据,并预测未来值。这样,就有可能在问题发生之前得到通知。简介今天的话题是:Zabbix内部的趋势预测我安装的版本是Zabbix4.0.2,且已启动并运行了虚拟机。我们在完成这个任务时无需使用SSH或LinuxCLI,因此也不需要任何有关Linux的知识。我们将要配置的所有内容都会在Zabbix前端完成。关于Zabbix趋势预测那么,什么是趋势预测?一般而言,当我们谈论监控时,我们指的是监控软件内部的实时数据。我们从主机和数据源中提取数据,并动态评估该数据。如果该数据达到了我们指定的触发阈值,我们就会收到通知。因此基本上,我们会在问题发生后,或至少在问题发生的前一刻作出反应。但有了趋势预测,我们便能作出前瞻性反应。我们不会在事情发生后才收到通知,而是在触发指定阈值之前,被告知还有一周的时间,或被告知一周后的预测值是什么。你可以决定是否要在问题发生之前立即采取行动,或者再等几天。下面,让我们首先思考一下我们究竟可以预测什么。Zabbix

  • Java 7 种阻塞队列详解

    队列和阻塞队列队列队列(Queue)是一种经常使用的集合。Queue实际上是实现了一个先进先出(FIFO:FirstInFirstOut)的有序表。和List、Set一样都继承自Collection。它和List的区别在于,List可以在任意位置添加和删除元素,而Queue只有两个操作:把元素添加到队列末尾;从队列头部取出元素。超市的收银台就是一个队列:我们常用的LinkedList就可以当队列使用,实现了Dequeue接口,还有ConcurrentLinkedQueue,他们都属于非阻塞队列。阻塞队列阻塞队列,顾名思义,首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素当阻塞队列是空时,从队列中获取元素的操作将会被阻塞。当阻塞队列是满时,从队列中添加元素的操作将会被阻塞。试图从空的阻塞队列中获取元素的线程将会阻塞,直到其他的线程往空的队列插入新的元素,同样,试图往已满的阻塞队列添加新元素的线程同样也会阻塞,直到其他的线程从列中移除一个或多个元素或者完全清空队列后继续新增。类似我们去海底捞排队,海底捞爆满情况下,阻塞队

  • Django基础篇-中间件

    Django中间件(Middleware)模板上下文处理器(contextprocessor)①Django中间件(Middleware)是一个轻量级、底层的“插件”系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。激活中间件需要把它添加到Django配置文件中的MIDDLEWARE_CLASSES元组中。自定义中间件每个中间件组件是一个独立的Python类,可以定义下面方法中的一个或多个 _init_:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件。process_request(request):执行视图之前被调用,在每个请求上调用,返回None或HttpResponse对象。process_view(request,view_func,view_args,view_kwargs):调用视图之前被调用,在每个请求上调用,返回None或HttpResponse对象。process_template_response(request,response):在视图刚好执行完毕之后被调用,在每个请求上调用,返回实现了render方法的

  • 认识 Kotlin 语言

    Kotlin的背景Kotlin是一门基于JVM且与JAVA可100%互通的编程语言,用JetBrains的话来说Kotlin是更『现代化、更强大』的编程语言。Kotlin由JetBrains在2010年开发,2011年开源至GitHub,2016年发布1.0版。源码地址:https://github.com/JetBrains/kotlin。GoogleAndroid团队与JetBrains的关系不一般。AndroidStudio由Google研发、维护,但它基于JetBrains开发的IntelliJIDEA社区版。Google和JetBrains将为Kotlin成立一个非盈利基金会。Kotlin语言的开发,还是JB为主导。AndreyBreslav是Kotlin语言的首席设计师。JetBrains对Kotlin的愿景是:用同一种语言,桥接多平台的不同应用的端对端开发。包括全栈Web应用、Android和iOS客户端、嵌入式/物联网等等。(Kotlin与Java100%互通,并具备诸多Java尚不支持的新特性。)AndroidStudio3.0预览版已支持Kotlin。下载AS3.0

  • MySQL分页查询

     当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。下面简单说一下我知道的一些方法。 准备工作 为了对下面列举的一些优化进行测试,下面针对已有的一张表进行说明。 表名:order_history 描述:某个业务的订单历史表 主要字段:unsignedintid,tinyint(4)inttype 字段情况:该表一共37个字段,不包含text等大型数据,最大为varchar(500),id字段为索引,且为递增。 数据量:5709294 MySQL版本:5.7.16线下找一张百万级的测试表可不容易,如果需要自己测试的话,可以写shell脚本什么的插入数据进行测试。以下的sql所有语句执行的环境没有发生改变,下面是基本测试结果: selectcount(*)fromorders_history;复制 返回结果:5709294 三次查询时间分别为: 8903ms 8323ms 8401ms 一般分页查询 一般的分页查询使用简单的limit子句就可

  • MAC 下用 MWeb写博客园日志

    摘要 由于工作原因,很久没有写日志了,原来在windows平台用livewriter写,现转到了mac下,尝试多种工具后,决定用MWeb写博客,并尝试一段时间。 配置过程 主要参考了此博客的内容: https://www.cnblogs.com/russellyoung/p/Mac-xia-ru-he-shi-yongMWeb-fa-bu-dao-bo-ke-yuan-ji.html 配置起来简单,推荐大家使用 printf("fortest!\n"); 复制 结束语 愿新的2019年,不定期更新一些日志。 (完) 作者:khldragon 出处:http://www.cnblogs.com/khldragon/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 俗话说,投资效率是最成功的投资。如果您感觉我的文章质量不错,读后收获很大,感觉能为您提高10%的工作效率,不妨小额【赞助】我一下,让我有动力继续写出更多好文章。

  • [Web] 深入理解现代浏览器

    转载: https://blog.csdn.net/qihoo_tech/article/details/91921777   奇技指南 身为前端,你真正深入理解了浏览器吗? 本文来自公众号奇舞周刊,作者李松峰,资深技术图书译者,翻译出版过40余部技术及交互设计专著,现任360奇舞团Web前端开发资深专家,360前端技术委员会委员、W3CAC代表。 各位,如果你的职业是开挖掘机,你说要不要深入理解挖掘机?通常来说,深入理解你操纵的机器才能最终达到人机一体的境界。 当然,你可以说:不用,因为如果挖掘机不好使,我可以换一台。嗯,也有道理。不过,假如你同时又是一名前端开发者,那你要不要深入理解浏览器呢?注意,身为前端,你不太可能有机会因为浏览器不好使就强迫用户换一个你认为好使的。这时候,你好像别无选择了。 不过也不用害怕,今天我们的现代浏览器深度游会非常轻松、快乐。这首先必须感谢一位名叫MarikoKosaka(小坂真子,https://kosamari.com/)的同行。她在Scripto工作,2018年9月在Google开发者网站上发表了“Insidelookatmo

  • Git linux 版本安装

    1、安装依赖 yuminstall-ycurl-develexpat-develgettext-developenssl-develzlib-devel yuminstall-ygccperl-ExtUtils-MakeMaker复制 2、进入官网下载压缩包(我是centos) https://mirrors.edge.kernel.org/pub/software/scm/git/复制 3、解压 tar-zxvfgit-2.33.0.tar.gz复制 4、编译安装 #执行以下两个命令将Git进行编译安装到/usr/local/git目录下 cdgit-2.33.0/ makeallprefix=/usr/local/git makeinstallprefix=/usr/local/git复制 5、配置环境变量 vim/etc/profile#添加以下内容exportPATH=/usr/local/git/bin:$PATH#保存退出后刷新source/etc/profile复制 最后git--version就能看到成功了额

  • HDU 4655 Cut Pieces

    CutPieces TimeLimit:4000/2000MS(Java/Others)    MemoryLimit:131072/65536K(Java/Others)TotalSubmission(s):762    AcceptedSubmission(s):317 ProblemDescription Supposewehaveasequenceofnblocks.Thenwepainttheblocks.Eachblockshouldbepaintedasinglecolorandblockicanhavecolor1tocolorai.Sothereareatotalofprod(ai)differentwaystocolortheblocks. Consideronewaytocolortheblocks.Wecallaconsecutivesequenceofblockswiththesamecolora"piece".Forexample,sequence"YellowYell

  • python requests报Max retries exceeded with url异常

    项目中有个模块是定时获取设备状态的,通过设备的http请求访问获取返回的状态码,然后根据状态码检测设备是否在线。但是最近发现连接后出现了偶尔连接不上的情况,报错如下: 2018-06-1415:51:42,076-configuration_model-ERROR-HTTPSConnectionPool(host='10.1.1.1',port=443):Maxretriesexceededwithurl:/api/1.0/device/status(CausedbyConnectTimeoutError(<requests.packages.urllib3.connection.VerifiedHTTPSConnectionobjectat0x7f1393d6fbd0>,'Connectionto10.1.1.1timedout.(connecttimeout=2)')) 2018-06-1415:51:48,475-configuration_model-ERROR-HTTPSConnectionPool(host='10.1.1.1',port=443):Maxre

  • centos 最小化安装pycharm

    首先找到安装地址 https://www.jetbrains.com/pycharm/download/#section=linux 选择linux。 打开浏览器的network监视,我用的chrome 点击download。这是会往下载页面跳转,留意着网络连接的请求列表,找到下载文件的请求。点击复制 找到地址后执行 wgethttps://download.jetbrains.8686c.com/python/pycharm-professional-2017.2.3.tar.gz 新建文件夹,我是在local下建立了pycharm目录,并将文件剪切至其中。 mkdirpycharmmvbin/pycharm-professional-2017.2.3.tar.gzpycharm 进入文件夹中 cdpycharm 并解压文件 tarzxvfpycharm-professional-2017.2.3.tar.gz   解压完毕之后进入安装目录 cdpycharm-2017.2.3/ 进入bin中 cdbin并赋予权限chmod+xpycharm.sh 然后执行,启动命令 s

  • Peppa 41-52

    41 Chloespuppetshow. I'mPeppaPig.ThisismyIittIebrother,George.ThisisMummyPig.AndthisisDaddyPig.Peppapig.ChIoe'sPuppetShoW!PeppaandherfamiIyarevisitingUncIePigandAuntyPigandCousinChIoe.IexpectUncIePigWiIIfaIIasIeepafterIunch,IikeheaIWaysdoes.DaddyPig!YoushouIdn'tsaysuchthingsaboutyouroWnbrother!EspeciaIIyinfrontofthechiIdren.Butit'strue!UncIePigaIWayseatstoomuchIunchandfaIIsasIeep,snoringIoudIy!Likethis.Err...Peppa,George,forgetWhatIjustsaidaboutUncIePig.Okay,Daddy!PeppaandherfamiIyhavearrivedatU

  • Pencil code 安装

    首先下载: gitclonehttps://github.com/pencil-code/pencil-code 然后记得添加环境变量 exportPENCIL_HOME=$HOME/pencil-code[orwhereveryouhavethecode] _sourceme_quiet=1;.$PENCIL_HOME/sourceme.sh;unset_sourceme_quiet复制 然后使用 pc_setupsrc--help复制 测试 ok

  • UIwebView 禁止弹出菜单

    在UIwebView发现绑定longTap事件的操作中,在iso会有菜单弹出(复制黏贴,词典等),影响我们设定的交互操作,估要屏蔽之~ window.onload=function(){ document.documentElement.style.webkitTouchCallout="none";//禁止弹出菜单 document.documentElement.style.webkitUserSelect="none";//禁止选中 };复制  

  • eclipse版本信息及操作系统

      一、查看版本信息:   进入到eclipse安装目录下,有一个.eclipseproduct文件,用记事本打开,就可以知道版本了,后面version=的值就是版本      二、是否为32位操作系统:   找到eclipse安装目录的eclipse.ini文件打开,在launcher.library项下,如果是win32.x86则是32位的,如果是win32.x86_64则是64位的

  • Math

    Math.random():获取[0.0,1.0)之间的double值 intnum1=(int)(Math.random()*10);//Math.random的随机数范围[0.0,1.0)之间*10=[0,10)=取0~9之间的随机数 Scannerin=newScanner(System.in); intanswer=in.nextInt(); //输入整数   拼命敲

  • 前端三栏布局

     圣杯布局: <!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width,initial-scale=1.0"> <metahttp-equiv="X-UA-Compatible"content="ie=edge"> <title>圣杯布局</title> <style> *{ margin:0; padding:0; } .wrapper{ padding:0100px; overflow:hidden; } .middle, .left, .right{ float:left; position:relative; } .middle{ width:100%; height:200px; background:red; } .left{ width:100px; height:100px; backg

  • 图片加载错误,显示默认图片

    之前图片加载错误,就一只显示alt内容,昨天回家的路上看了文章,发现了onerror事件 于是今天就用了 <imgsrc=""onerror="this.src='assets/front/images/11.jpg'"alt=""> 复制   发现果然显示了默认图片,在另一个网页用的时候,不小心写错了后面的图片的地址,firebug显示的错误数蹭蹭的想上涨,发现onerror在不停的执行,而且页面不停闪烁 再找解决办法的时候发现了一篇文章,提出了两种解决办法,不过我用了评论中的办法 <imgsrc=""onerror="this.onerror=null;this.src='assets/front/images/11.jpg'"alt="">复制   将onerror置空,使有一次有效; 兼容性:没有IE6测不了,不过兼容ie7;

  • 从0开始使用python flask编写博客网站(2)

    好了上一篇文章中搭建好了完整的框架,以及可以访问一个“helloworld”页面了。现在继续完善我们的博客程序。 1.如法炮制,继续完善error和admin的路由。 首先写把404和500的网页写好放到templates/errors中。然后在error的文件夹中新建handlers.py文件,在这里写错误的路由 fromflaskimportrender_template fromapp.errorsimportbp @bp.app_errorhandler(404) defnot_found_error(error): returnrender_template("errors/404.html"),404 @bp.app_errorhandler(500) definternal_error(error): returnrender_template("errors/500.html"),500 复制 随后和主页面一样,在error的__init__.py文件导入蓝图和路由 fromflaskimportBlueprint bp=Blueprint("errors",_

相关推荐

推荐阅读