1、寫在前面的前端
fis3-jello 是基於 fis3 針對 jsp/velocity 模板的前端工程解決方案。github 地址爲:https://github.com/fex-team/fis3-jello。java
注意:fis3 對 Node 版本要求 0.8.x,0.10.x, 0.12.x,4.x,6.x,不在此列表中的版本不予支持。git
本文主要介紹如何在 fis3-jello 的基礎上來添加本身的需求。github
2、fis3-server-jelloweb
fis3-jello 具備不少特性,大多特性都是經過內嵌的 JavaEE 服務器實現的,例如模板繼承、模板數據綁定。fis3-jello 在 release 時,會使用 fis3 提供的配置/接口將項目中相應的目錄複製到內嵌服務器的目錄中。咱們在 release 後,能夠經過命令 fis3 server open 打開服務器資源目錄看到。spring
1. fis3 如何開發服務器插件express
fis3 中的服務器是經過獨立的 npm 包來完成的,命名規範爲 fis3-server-xxxx。而 fis3-jello 中的服務器對應的 npm 包爲 fis3-server-jello。apache
fis3-jello 打開內嵌服務器的命令爲 fis3 server start --type jello,而該命令的執行模塊爲 fis3-command-server,該模塊接收到 --type jello 參數後,經過 fis.require() 方法找到對應的服務器模塊,以後調用 fis3-server-jello 模塊中的 start 方法。npm
2. 結構json
fis3-server-jello 的 github 地址爲:https://github.com/fex-team/fis3-server-jello。
文件目錄以下:
│ .gitignore
│ .npmignore
│ fis.keystore
│ index.js
│ LICENSE
│ package.json
│ README.md
│
└─vendor
framework.tar
server.jar
server.js
3. 分析
該插件的大體運行流程爲,先檢查計算機中是否配置 java 環境,代碼以下:
function checkJavaEnable (opt, callback) { var javaVersion = false process.stdout.write('checking java support: ') var java = spawn('java', ['-version']) java.on('exit', function () { if (!javaVersion) { process.stdout.write('java not support!') } callback(javaVersion. opt) }) }
接着解壓 framework.tar 至系統臨時目錄下,最後構建 java 命令來執行 server.jar。
var markerFile = path.join(opt.root, 'WEB-INF', 'web.xml') if (!fis.util.exists(markerFile)) { extract(path.join(__dirname, 'framework.tar'), opt.root, done) } else { setTimeout(done, 200) }
我反編譯了 server.jar,看到主要就是使用 apache commons 將 tomcat embed 包裝成一個命令工具,反編譯獲得的代碼以下。
package com.baidu.fis.server.launch; import java.io.File; import java.io.PrintStream; import org.apache.catalina.Server; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; public class Main { public static int PORT = 8080; public static String BASE_DIR = null; public static String WEBAPP_DIR = "./web"; public static String WEBAPP_PATH = ""; public static Boolean HTTPS = Boolean.valueOf(false); public static void main(String[] args) throws Exception { System.setProperty("java.awt.headless", "true"); Options options = new Options(); options.addOption("h", "help", false, "output usage information"); options.addOption("p", "port", true, "server listen port"); options.addOption("base", true, "tomcat base dir"); options.addOption("root", true, "document root"); options.addOption("webapp", true, "webapp path"); options.addOption("type", false, "useless just ignore it."); options.addOption("https", false, "https"); HelpFormatter help = new HelpFormatter(); BasicParser parser = new BasicParser(); CommandLine cmd = parser.parse(options, args); if (cmd.hasOption("help")) { help.printHelp("assemble", options); return; } if (cmd.hasOption("port")) { PORT = Integer.valueOf(cmd.getOptionValue("port")).intValue(); } if (cmd.hasOption("base")) { BASE_DIR = cmd.getOptionValue("base"); } else if (BASE_DIR == null) { BASE_DIR = System.getProperty("java.io.tmpdir"); } if (cmd.hasOption("root")) { WEBAPP_DIR = cmd.getOptionValue("root"); } if (cmd.hasOption("webapp")) { WEBAPP_PATH = cmd.getOptionValue("webapp"); if ((!WEBAPP_PATH.isEmpty()) && (!WEBAPP_PATH.startsWith("/"))) { WEBAPP_PATH = "/" + WEBAPP_PATH; } } if (cmd.hasOption("https")) { HTTPS = Boolean.valueOf(true); } startServer(); } protected static void startServer() { Tomcat tomcat = new Tomcat(); try { String base = new File(BASE_DIR).getCanonicalPath(); String webapp = new File(WEBAPP_DIR).getCanonicalPath(); tomcat.setBaseDir(base); Connector defaultConnector = tomcat.getConnector(); defaultConnector.setPort(PORT); if (HTTPS.booleanValue()) { System.out.println("Use HTTPS"); System.out.println(System.getProperty("user.dir") + "/../fis.keystore"); defaultConnector.setScheme("https"); defaultConnector.setSecure(true); defaultConnector.setAttribute("keystoreFile", System.getProperty("user.dir") + "/../fis.keystore"); defaultConnector.setAttribute("keystorePass", "123456"); defaultConnector.setAttribute("clientAuth", "false"); defaultConnector.setAttribute("sslProtocol", "TLS"); defaultConnector.setAttribute("SSLEnabled", Boolean.valueOf(true)); } tomcat.addWebapp(WEBAPP_PATH, webapp); tomcat.start(); tomcat.getServer().await(); } catch (Exception e) { e.printStackTrace(); } } }
最後來看一下 framework.tar 文件,在執行 server.jar 以前,程序會解壓 framework.tar 中的文件到指定的系統臨時目錄中。咱們能夠解壓 framework.tar 文件,看到文件的目錄結構以下:
├─META-INF └─WEB-INF │ fis.tld │ tools.xml │ velocity.properties │ web.xml │ ├─lib │ antlr-2.7.2.jar │ aopalliance-1.0.jar │ commons-beanutils-1.7.0.jar │ commons-chain-1.1.jar │ commons-collections-3.2.1.jar │ commons-digester-1.8.jar │ commons-fileupload-1.3.1.jar │ commons-io-2.4.jar │ commons-lang-2.4.jar │ commons-logging-1.1.jar │ commons-validator-1.3.1.jar │ dom4j-1.1.jar │ fastjson-1.1.41.jar │ fis-velocity-tools.jar │ jstl-1.2.jar │ oro-2.0.8.jar │ slf4j-api-1.7.7.jar │ spring-aop-3.2.10.RELEASE.jar │ spring-beans-3.2.10.RELEASE.jar │ spring-context-3.2.10.RELEASE.jar │ spring-core-3.2.10.RELEASE.jar │ spring-expression-3.2.10.RELEASE.jar │ spring-web-3.2.10.RELEASE.jar │ sslext-1.2-0.jar │ standard-1.1.2.jar │ struts-core-1.3.8.jar │ struts-taglib-1.3.8.jar │ struts-tiles-1.3.8.jar │ velocity-1.7.jar │ velocity-tools-2.0.jar │ └─views index.vm
這裏最值得注意的就是 /WEB-INF/lib/fis-velocity-tools.jar,該 jar 包就是用來 fis3-jello 服務器中最主要的程序,其開源的工程git地址爲:https://github.com/fex-team/fis-velocity-tools。咱們能夠經過修改該項目,來定製本身的特性。
3、fis-velocity-tools
1. 開發準備
整個項目使用 maven 工具進行管理,爲了使其在 tomcat 容器中運行以方便開發,我在 pom.xml 中添加了一個插件,以下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <version>1.1</version> <configuration> <path>/wp</path> <port>8080</port> <uriEncoding>UTF-8</uriEncoding> <url>http://localhost:8080/</url> <server>tomcat6</server> </configuration> </plugin>
2. web.xml
這個項目就是在開發一個 web 項目。