正常前后端是独立开发的,一般而言前端使用reactjs/vuejs,独立部署在nginx服务器上。web-platform目前支持前者,当然也支持直接打包前端到web-platform插件里,这样就没有前端部署的烦恼。值得一提的是,因为有sfcli工具的支持,前端同学也可以很容易启动后端的web服务,方便在本地测试。 web-platform现阶段默认集成reactjs支持。
本文目标:
开发一个简单的的带有web界面的插件
基础知识
大家可以先看这篇文章了解一个插件的流程
开发过程
首先,使用sfcli 创建插件:
sfcli create --name ar_runtime_web_console --include_ui
--include_ui 指示需要创建前端页面。你需要在系统中安装create-react-app命令。系统创建完成后,根目录下会多一个web_console目录,该目录是一个标准的reactjs项目。
后端部分
先提供一个Action,方便前端调用测试:
/**
* Action logical
*/
class HelloWorldAction extends CustomAction {
override def run(params: Map[String, String]): String = {
JSONTool.toJsonStr(Map("msg" -> "hello world"))
}
}
/**
* Action Info
*/
object HelloWorldAction {
def action = "hello_world"
def plugin = PluginItem(HelloWorldAction.action,
classOf[HelloWorldAction].getName, PluginType.action, None)
}
现在可以访问 http://127.0.0.1:9007/run?action=hello_world 得到结果了。在安装插件时,我们需要告诉应用容器如何加载这个静态资源。这个可以通过实现CustomApp接口实现:
class ArRuntimeWebConsoleApp extends CustomApp {
override def run(params: Map[Any, Any]): Any = {
if (ServiceFramwork.injector == null) return ""
val httpServer = ServiceFramwork.injector.getInstance(classOf[HttpServer])
val server = ReflectHelper.field(httpServer, "server").asInstanceOf[Server]
val server_handler = server.getHandler.asInstanceOf[HandlerList]
if (!ReflectHelper.field(server_handler, "_mutableWhenRunning").asInstanceOf[Boolean]) {
ReflectHelper.field(server_handler, "_mutableWhenRunning", true)
}
val resource_handler = new ResourceHandler
resource_handler.setDirectoriesListed(false)
val webDir = this.getClass().getClassLoader().getResource(PluginDB.plugin_name).toExternalForm()
resource_handler.setResourceBase(webDir);
val origin = server_handler.getHandlers.filterNot { item =>
item.isInstanceOf[ResourceHandler] && item.asInstanceOf[ResourceHandler].getBaseResource.getName.split("/").last == PluginDB.plugin_name
}
server_handler.setHandlers(Array(resource_handler) ++ origin);
}
override def phase: StartupPhase = BeforeHTTPPhase
}
object ArRuntimeWebConsoleApp {
def action = PluginDB.plugin_name
def plugin = PluginItem(ArRuntimeWebConsoleApp.action,
classOf[ArRuntimeWebConsoleApp].getName, PluginType.app, Option(AfterHTTPPhase))
}
该代码主要是往已有的http容器里动态添加了一个静态资源处理器。代码有点hacker,理论上其他项目拷贝过去就行。
到目前为止,后端已经开发完成。
前端部分
新建一个Hello.js:
import React from 'react'
import {Action,Method,Backend} from '@allwefantasy/web-platform-ui'
export default class Hello extends React.Component{
constructor(props) {
super(props)
this.state = {}
}
componentDidMount(){
const backend = new Backend()
backend.request(Action.HELLO,Method.GET,{},(s)=>{
this.setState({hello:s.msg})
},(s)=>{})
}
render(){
return <div>{this.state.hello}</div>
}
}
其中@allwefantasy/web-platform-ui
库是我开发的一个辅助库,利用里面的backend可以直接访问后端。
将Hello放到 App.js里。前端开发完成。
发布成插件(并运行)
打包:
sfcli release
启动一个应用容器:
sfcli create --name test-project --empty true
cd test-project
sfcli runtime
安装插件:
sfcli plugin
--add ar_runtime_web_console-bin_2.11-1.0.0.jar
--token xxxxxx
访问地址:
http://127.0.0.1:9007/ar_runtime_web_console/index.html
其中ar_runtime_web_console为插件名称。
页面如下:
插件代码看这里: