设为首页 | 收藏本站欢迎来到卓越网络免费免备案CDN加速,DDoS和CC攻击防御,高防CDN管理平台!

已阅读

快速为前端提供本地JAVA服务和模板渲染环境

作者:cdnfine      来源:cdnfine      发布时间:2019-09-03

开源引流、流量变现是今年的业务重点之一。而搜索引擎仍然是当前互联网流量入口的霸主,是我们快速获取大量免费新用户、以及实现流量变现的重要途径,同时也是一种成本低廉的建立网站口碑和品牌知名度的方式。因此,相关的前端网页遵循搜索引擎优化标准是非常重要的。

    鉴于当前国内主流搜索引擎对前端渲染网页的收录效果不是很好,所以我们的页面必须采用服务端渲染的方式。服务端渲染通常有两种:一种是比较传统的,由后端服务器渲染,譬如我们以前很多基于webx框架的应用基本都是这样的,另一种是现在很多新网站采用的node中间层渲染,譬如淘宝。而我们的前端工程师们考虑了前后端分离以及维护成本等诸多因素之后,暂时没有增设node中间层,而是提出了Hypernova。

    在这样的开发模式下,作为后端开发,我们的工程只需要支持后端模板渲染,并且能及时从集团CDN上将前端发布的模板更新到我们的集群机器上。看起来很完美,我们后端工程狮终于不用苦哈哈地自己写vm了。但是,联调过程并不是那么方便……因为前端只能在本地mock数据,自测时有些异常情况无法覆盖到。另外,前端本地调试是node渲染,据前端开发反馈可能存在和java渲染不同的情况。更麻烦的是,前端需要把vm推到CDN上,后端更新版本号配置之后,才能验证新vm,而且如果渲染vm的过程中出现报错,需要后端开发上服务器查看日志,前端修改代码,再发布CDN,循环以上。这样来来回回,我完全沦为了陪同调试的助理,脑壳疼……

    那么有没有办法解放自己,让前端自助调试的同时,后端能够继续去写写其他代码呢?

方案怎么能没有呢!

    最直接的就是前端自己改版本号配置,用后端的日常机器调试。缺点是前端仍然要不停地发CDN,而且渲染报错了,还是得登服务器查看后端的日志文件。另外后端的配置权限开放给前端也会存在手抖改错配置而后端不知情的风险……

    方案二,反正方案一也不可避免要登录服务器查看日志,不如前端直接把修改好的vm推到测试机上,测好了再发布CDN。缺点是,前端需要登录后端服务器,而且要熟悉后端静态资源位置和日志文件的位置。我想这对于前端来说应该是不那么友好的,尤其是不熟悉后端工程和服务器的话。

    方案三,那我帮前端在本地起一个后端服务呢?本地修改vm立即生效,还能马上看到渲染报错日志,像是个不错的主意。

实践方案

把后端工程打包成jar

    这一步很简单,得益于sping-boot或pandora-boot框架自带了web server,后端工程完全可以打包成jar包,然后执行java命令在本地启动。

第一步是在pom文件中添加打包配置,指定java版本和入口类mainClass:

快速为前端提供本地JAVA服务和模板渲染环境

第二步是在pom文件中指定要打包的资源文件和要排除的资源文件:

快速为前端提供本地JAVA服务和模板渲染环境

添加完之后,直接在工程所在目录下,执行命令即可完成打包:

mvn clean package -Dmaven.test.skip=true

如果你只是想在本地起一个JAVA服务,你已经完成了大部分工作。只要你能通过java命令成功运行这个jar包,到此就结束了。

如果你的工程里涉及到资源文件读写,可能还有一些工作要做。。。

支持读取jar包中的资源文件

我的工程里面,有一个简体中文到繁体中文的映射文件,映射类启动时需要读取这个文件,前面打包时也已经将这个文件打进jar包里了,燃鹅,启动时却失败了:

快速为前端提供本地JAVA服务和模板渲染环境

经过查看源代码,确认读取该文件时使用的是org.springframework.util.ResourceUtils类,该类只支持读取file协议的文件,而打包成jar之后,协议变成了jar:file,该类就抛了异常:

快速为前端提供本地JAVA服务和模板渲染环境

因此,需要对读取jar包中的资源做简单的兼容处理。

我重新定义了一个资源文件的读取方法,在获取文件流时,先判断一下是否是jar文件,如果是,则先在本地“拷贝”一份出来(file.mkdir),然后把这个本地文件流复制到jar文件流里:

快速为前端提供本地JAVA服务和模板渲染环境

支持读取及更新jar包以外的模板文件

    我们采用的后端模板引擎是velocity。velocity支持指定文件默认路径,因此只需要把模板路径设置到jar包以外即可。我的方案是在启动命令处添加配置项,指定默认模板路径。

    velocity默认的缓存机制是开启的,而且一般不自动更新。也就是说,默认情况下,你在本地修改vm模板,JAVA服务是不买账的,资源加载器一旦把vm加载进去就不会变更,即使你在本地把这个vm删除了,服务端也能照常返回vm。所以,本地工程需要把velocity的缓存去掉,并且让资源加载器定时更新vm文件。

这个很简单,只要添加velocity的配置就可以了:

file.resource.loader.cache=false

file.resource.loader.modificationCheckInterval=2

然后懵逼的事情来了。。。。。。

我在IDEA里直接启动JAVA应用,完全OK,修改vm也可以马上更新。看起来我已经大功告成了哇!

燃鹅,打包成jar包后启动,修改vm,emmm……这家伙完全不鸟我……

也就是说,同样的配置在jar包里并不生效。

第一反应是,可能引用的jar包有冲突,模板引擎是不是有冲突。于是排了一轮jar包,确保整个工程里只有一个版本的模板引擎了。重新打了个包,还是毫无反应鸭……

真是叫人头秃啊…………

不得已去看了一下velocity的启动源码,试图找到资源加载相关的线索。

从spring 的VelocityConfigurer开始,这个类在启动时实现了引擎初始化:

快速为前端提供本地JAVA服务和模板渲染环境

然后在真正的引擎初始化之前,spring先干了几件重要的事,一是把配置读进来,这没问题,说明我的配置肯定传进来了。二是初始化资源加载器,emmm,配置没生效,可能就是这里了。

快速为前端提供本地JAVA服务和模板渲染环境

继续看资源加载器是怎么初始化的,发现这里面主要有两种类型的资源加载器:默认是FileResourceLoader,还有一种是SpringResourceLoader。

快速为前端提供本地JAVA服务和模板渲染环境

在用文件资源加载器加载失败的情况下,异常处理是用SpringResourceLoader来加载。

这就是问题所在了。原因同上一节,我们普通的启动读取到的vm文件是file协议的,而改成jar包启动之后变成了jar:file,于是spring默默地把FileResourceLoader换成了SpringResourceLoader……

真是气skr人啊……

于是我也默默地把配置换成:

spring.resource.loader.cache=false

spring.resource.loader.modificationCheckInterval=2

皆大欢喜。

免安装JAVA环境运行

我最讨厌的事情就是配置环境了,emmm

推已及人,如果让前端开发去配一套JAVA环境,想必他们也很烦躁吧。

所以,送佛送到西,把环境问题也吃掉吧。

很简单,随jar包自带一个jre就可以了。

把你本机的jre文件夹直接拷出来,和jar包放在同一文件夹里,然后用jre里的java去启动jar包就可以了。

为了方便使用,我把启动、停止、重启操作都写成了脚本

Keywords: 免费CDN加速 免备案CDN加速 高防CDN加速