worklight 怎么改启动浏览器启动很慢

使用IBM Mobilefirst(Worklight)构建Hybrid应用:3.Adapter - 增删改查
使用IBM Mobilefirst(Worklight)构建Hybrid应用:3.Adapter
十月 28, 2015
接,之前我们已经明确如何建立一个Hybrid应用,并且正常启动,进行真机调试。
另外,我们也大致了解了在构建时如何进行文件重载合并,并且也初步调用了下系统硬件机能
但是至于如何去和服务器后台服务接口进行交互,我们还一无所知…
接下来就让我们了解下IBM MobileFirst(Worklight)下如何进行服务调用,并且尝试编写一些代码进行调用练习
Adapter(适配器)
适配器是在 IBM(R) MobileFirst 上部署和维护的应用程序的服务器端代码。 适配器连接到企业应用程序(或称为后端系统),在适配器与移动应用程序之间传递数据,并对此数据执行任何必要的服务器端逻辑。
这里将集中讨论HTTP、JAVA、SQL三种适配器的构建和使用。
1.6.1. Http Adapter
http适配器以访问douban音乐Api为例,首先在工程上单击右键-New-MobileFirst Adapter,创建一个MobileFirst Adapter。
选择类型选择Http Adapter,名称填写为DoubanMusic,然后点击Finish。
完成之后,adapter中会出现一个名为DoubanMuaic的HttpAdapter:
首先我们修改DoubanMusic.xml来定义URL地址以及接口:
&?xml version="1.0" encoding="UTF-8"?&
&!-- adapter名称申明 --&
&wl:adapter name="DoubanMusic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wl="/mfp/integration"
xmlns:http="/mfp/integration/http"&
&displayName&DoubanMusic&/displayName&
&description&DoubanMusic&/description&
&connectivity&
&connectionPolicy xsi:type="http:HTTPConnectionPolicyType"&
&!-- 访问协议、地址、端口申明 --&
&protocol&https&/protocol&
&domain&&/domain&
&port&443&/port&
&connectionTimeoutInMilliseconds&30000&/connectionTimeoutInMilliseconds&
&socketTimeoutInMilliseconds&30000&/socketTimeoutInMilliseconds& &maxConcurrentConnectionsPerNode&50&/maxConcurrentConnectionsPerNode&
&/connectionPolicy&
&/connectivity&
&!-- 接口申明 --&
&procedure name="getMusics"/&
&procedure name="getMusicInfo"/&
&/wl:adapter&
你也可以使用MobileFirst提供的图形化工具AdapterEditor修改相关参数:
我们分别定义了两个接口(getMusics获取音乐列表、getMusicInfo获取音乐详情),下面让我们在DoubanMusic-impl.js中实现它:
* 豆瓣音乐 - 获取音乐列表
function getMusics(musicName,count) {
var input = {
method : 'get',
returnedContentType : 'json',
headers: {
'Content-Type': 'application/charset=utf-8'
path : 'v2/music/search?q='+encodeURI(musicName)+'&start='+count
return WL.Server.invokeHttp(input);
豆瓣音乐 - 获取音乐详情数据
function getMusicInfo(musicId) {
var input = {
method : 'get',
returnedContentType : 'json',
headers: {
'Content-Type': 'application/charset=utf-8'
path : 'v2/music/'+musicId
return WL.Server.invokeHttp(input);
在实现中,以下属性参照下表配置:
get、post、put、delete
returnedContentType
xml、json、html、pain
contentType
parameters
{name1: value1, … }
请求路径(相对)
接下来,让我们编写调用代码,并尝试在移动APP中调用它,并通过console.log打印结果:
$scope.getMusicList =
function(musicname,fromIndex)
var invocationData = {
adapter : 'DoubanMusic',
procedure : 'getMusics',
parameters
: [musicname,fromIndex]
* 豆瓣音乐 - 获取音乐列表
WL.Client.invokeProcedure(invocationData, {
onSuccess : function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log(result.responseHeaders);
for(var t=0;t&result.responseJSON.musics.t++){
console.log("豆瓣接口返回音乐:"+result.responseJSON.musics[t].title+"id:"+result.responseJSON.musics[t].id);
console.log("--------------");
onFailure : function(result){
console.log(result);
豆瓣音乐 - 获取音乐详情数据接口调用
$scope.getMusicDetails = function(id){
var invocationData = {
adapter : 'DoubanMusic',
procedure : 'getMusicInfo',
parameters
WL.Client.invokeProcedure(invocationData, {
onSuccess : function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log(result.responseHeaders);
console.log("音乐:"+result.responseJSON.title);
console.log("音乐介绍:"+result.responseJSON.summary);
console.log("--------------");
onFailure : function(result){
console.log(result);
调用音乐列表返回结果:
调用音乐详情
1.6.2. SQL Adapter
创建SQL Adapter 主要是用来进行数据库的CRUD操作以及(无Out参数的)Procedure的调用。在工程上单击右键-New-MobileFirst Adapter,在弹出的Adapter类型中选择SQL Adapter,并填写Adapter名称:
完成之后,adapter中会出现一个名为SQLAdapter的SQL Adapter,让我们先打开SQLAdapter.xml
配置数据源以及相关接口
&?xml version="1.0" encoding="UTF-8"?&
&wl:adapter name="SQLAdapter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wl="/mfp/integration"
xmlns:sql="/mfp/integration/sql"&
&!-- 数据源参数 --&
&displayName&SQLAdapter&/displayName&
&description&SQLAdapter&/description&
&connectivity&
&connectionPolicy xsi:type="sql:SQLConnectionPolicy"&
&dataSourceDefinition&
&driverClass&oracle.jdbc.driver.OracleDriver&/driverClass&
&url&jdbc:oracle:thin:@114.215.82.74:1521:orcl&/url&
&user&用户名&/user&
&password&密码&/password&
&/dataSourceDefinition&
&/connectionPolicy&
&/connectivity&
&!--接口申明 --&
&procedure name="queryCarName"/&
&/wl:adapter&
继续打开SQLAdapter-impl.js实现queryCarName接口
* 模糊查询SQL语句(查询车辆)
var sqlString = WL.Server.createSQLStatement("select * from T_SM_PLATE t where 1=1 and t.C_PLATEID like ? and C_USEFLG = ?");
function queryCarName(param,flag) {
return WL.Server.invokeSQLStatement({
preparedStatement : sqlString,
parameters : [new String("%"+param+"%"),flag]
接下来,让我们编写调用代码,并尝试在移动APP中调用它,并通过console.log打印结果:
DATABASE调用
$scope.queryCarName = function(name){
var invocationData = {
adapter : 'SQLAdapter',
procedure : 'queryCarName',
parameters
: [name,'1']
WL.Client.invokeProcedure(invocationData, {
onSuccess : function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log(result.responseHeaders);
console.log("车牌遍历:");
var resultSetObj = result.responseJSON.resultS
for(var t=0;t&resultSetObj.t++){
console.log(resultSetObj[t].C_PLATEID + " - " +resultSetObj[t].C_PLATENO);
console.log("--------------");
onFailure : function(result){
console.log(result);
注意:目前并不赞成通过SQL Adapter的方式来调用Procedure和Function(因为不支持out参数的procedure),请参见后面JAVA ADAPTER章节。
1.6.3. 在Adapter中使用JAVA
MobileFirst允许我们在Adapter中调用java类方法并返回。接下来我们将1.5.1中HttpAdapter的例子给予扩充,来演示如何调用java方法。
首先,让我们添加一个JAVA类,展开Java Resources,并起名JavaService,包名为:com.td.helloworld.
文件内容:
静态方法addTwoIntegers、方法subtractTwoIntegers、和引用第三方库文件的方法getList。
package com.tf.helloworld.
import java.util.ArrayL
import java.util.HashM
import java.util.L
import java.util.M
import com.google.gson.G
import com.google.gson.GsonB
public class JavaService {
Gson gson = new GsonBuilder().serializeNulls().create();
* 静态方法 两数相加
* @param first
* @param second
public static int addTwoIntegers(int first,int second){
return first +
* 需要实例化 两数相减
* @param first
* @param second
public int subtractTwoIntegers(int first , int second){
return first -
* 调用google gson库,返回json字符串
public String getList(){
List&Map&String,Object&& list = new ArrayList&Map&String,Object&&();
Map&String,Object& zhangsan = new HashMap&String,Object&();
zhangsan.put("name", "zhangsan");
zhangsan.put("age", 18);
Map&String,Object& lisi = new HashMap&String,Object&();
lisi.put("name", "lisi");
lisi.put("age", 20);
list.add(zhangsan);
list.add(lisi);
String jsonString = gson.toJson(list);
return jsonS
其中,我们调用了google gson的类库,所以也需要把相关的jar包放入到工程lib文件夹下:
接下来,让我们扩充原有的HttpAdapter例子中的相关方法,首先是接口DoubanMusic.xml:
其次是实现文件DoubanMusic-impl.js
注意:除了静态方法外,方法一律需要对类进行实例化才能调用。
最后,让我们编写调用方法:
返回结果:
两数相加:
两数相减:
调用google gson库返回json格式的字符串:
1.6.4. JAVA Adapter
JAVA适配器基于规范,每一个JAVA适配器都是一个JAX-RS服务能够很容易的部署到MobileFirst Server供客户端调用。同时,JAVA Adapter也有访问MobileFirst Server API的能力。
我们将会在Java Adapter中测试接口调用,参数传递,以及第三方库和数据库的访问等内容。
让我们首先创建一个Java Adapter:
填入相关的Adapter名称、类型、包名等等:
相关结构如下:
在编写接口之前,我们需要在server中创建JNDI数据源,切换到MobileFirst Development Server中,修改server.xml,新增一个名为mobilefirst_oracle的JNDI数据源:
您也可以通过IBM的Server Configuration图形化工具来配置server.xml:
另外,也需要把相关的数据库驱动放入lib中:
至此,server中JNDI数据源创建完毕。接下来回到我们的接口文件中,如下代码所示编写代码初始化数据库以及相关接口:
JavaAdapterApplication.java
public class JavaAdapterApplication extends MFPJAXRSApplication{
static Logger logger = Logger.getLogger(JavaAdapterApplication.class.getName());
protected void init() throws Exception {
//初始化JNDI数据源
JavaAdapterResource.init();
("Adapter initialized!");
protected void destroy() throws Exception {
("Adapter destroyed!");
protected String getPackageToScan() {
//The package of this class will be scanned (recursively) to find JAX-RS resources.
//注册package
return getClass().getPackage().getName();
JavaAdapterResource.java
static DataSource ds =
static Context ctx =
static Logger logger = Logger.getLogger(JavaAdapterResource.class.getName());
Gson gson = new GsonBuilder().serializeNulls().create();
WLServerAPI api = WLServerAPIProvider.getWLServerAPI();
* 初始化jndi数据源
* @throws NamingException
public static void init() throws NamingException {
ctx = new InitialContext();
ds = (DataSource)ctx.lookup("jdbc/mobilefirst_oracle");
* Content-type:application/json
* 调用地址: "&server address&/HelloWorld/adapters/JavaAdapter/users"
@Produces("application/json")
public String hello(){
return "{\"flag\": 1}";
/* GETPath传参
* 调用地址:"&server address&/HelloWorld/adapters/JavaAdapter/users/{username}"
@Path("/{username}")
public String helloUser(@PathParam("username") String name){
("PathParam name:"+name);
return "Hello " +
/* POST QueryParameter传参
* 调用地址: "&server address&/HelloWorld/adapters/JavaAdapter/users/helloUserQuery?username=&yearold=" */
@Path("/helloUserQuery")
public String helloUserQuery(@QueryParam("username") String name,@QueryParam("yearold") String year){
return "Hello " + name+",year old "+
* DB数据库调用,查询车牌
@Path("/getplate")
@Produces("application/json")
public String getplate(@QueryParam("ct") String ct) throws Exception{
Connection con =
ResultSet rs =
PreparedStatement ps =
List&Car& list = new ArrayList&Car&();
String jsonString = "";
StringBuffer sb = new StringBuffer();
con = ds.getConnection();
ps = con.prepareStatement("select C_PLATEID,C_PLATENO,N_MILEAGE from t_sm_plate f where rownum &= ?");
ps.setString(1, ct);
rs = ps.executeQuery();
while (rs.next()) {
String plateId = rs.getString("C_PLATEID");
String plateNo = rs.getString("C_PLATENO");
int mileAge = rs.getInt("N_MILEAGE");
Car car = new Car();
car.setPlateid(plateId);
car.setPlateno(plateNo);
car.setMileage(mileAge);
list.add(car);
jsonString = gson.toJson(list);
} catch (SQLException e) {
} finally {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
return jsonS
* DB存储过程(带out参数)调用
@Path("/callableStatement")
@Produces("application/json")
public String callableStatement() throws Exception{
Connection con =
ResultSet rs =
PreparedStatement ps =
CallableStatement proc =
String testPrint = "";
con = ds.getConnection();
proc = con.prepareCall("{ call p_sm_getwarnmessage(?) }");
proc.registerOutParameter(1, Types.VARCHAR);
proc.execute();
testPrint = proc.getString(1);
} catch (SQLException e) {
if(rs!=null)
rs.close();
if(ps!=null)
ps.close();
if(con!=null)
con.close();
return testP
* JSON实体注入:插入车辆(单实体对象)
@Path("/insertCar")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String jsonInjection(Car car) throws Exception{
if(car != null){
car.setMileage(99999);
return gson.toJson(car);
* JSON实体注入:插入车辆列表
@Path("/insertCarList")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String jsonInjection(List&Car& list) throws Exception{
return gson.toJson(list);
客户端调用代码(GET请求):
* Content-type:application/json
* 调用地址: "&server address&/HelloWorld/adapters/JavaAdapter/users"
$scope.javaadapterNoPath = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users", WLResourceRequest.GET);
resourceRequest.send().then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(Getpath传参):
/* GETPath传参
* 调用地址:"&server address&/HelloWorld/adapters/JavaAdapter/users/{username}"
$scope.javaadapterPathParam = function(){
var paramsOfName = "xiang";
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/"+paramsOfName, WLResourceRequest.GET);
resourceRequest.send().then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(Post QueryParameter 传参)
/* POST QueryParameter传参
* 调用地址: "&server address&/HelloWorld/adapters/JavaAdapter/users/helloUserQuery?username=&yearold=" */
$scope.javaadapterQueryParameter = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/helloUserQuery", WLResourceRequest.POST);
resourceRequest.setQueryParameter("username", "xiang");
resourceRequest.setQueryParameter("yearold", "28");
resourceRequest.send().then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(DB数据库调用)
* DB数据库调用,查询车牌
$scope.javaadapterSQLinvoke = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/getplate", WLResourceRequest.POST);
resourceRequest.setQueryParameter("ct", 30);
resourceRequest.send().then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
//console.log("result.responseText:"+result.responseJSON);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(DB存储过程调用 带out参数)
* DB存储过程(带out参数)调用
$scope.javaadapterSQLcallableStatement = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/callableStatement", WLResourceRequest.POST);
resourceRequest.send().then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
//console.log("result.responseText:"+result.responseJSON);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(Json单对象注入)
* JSON调用:插入单辆车
$scope.insertCar = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/insertCar", WLResourceRequest.POST);
var json = {
plateid:"PK100001",
plateno:"湘G 10001",
mileage:100
resourceRequest.setHeader("Content-Type", "application/json");
resourceRequest.send(json).then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
//console.log("result.responseText:"+result.responseJSON);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
客户端调用代码(Json对象集合注入)
* JSON调用:插入车列表
$scope.insertCarList = function(){
var resourceRequest = new WLResourceRequest("/adapters/JavaAdapter/users/insertCarList", WLResourceRequest.POST);
var json = [{
plateid:"PK100001",
plateno:"湘G 10001",
mileage:100
plateid:"PK100002",
plateno:"湘G 10002",
mileage:200
resourceRequest.setHeader("Content-Type", "application/json");
resourceRequest.send(json).then(
function(result){
console.log("--------------");
console.log("返回状态:"+result.status);
console.log("result.responseText:"+result.responseText);
//console.log("result.responseText:"+result.responseJSON);
console.log("--------------");
},function(result){
console.log(result);
调用结果:
1.6.5. 在Adapter中调用Webservice
MobileFirst对于处理webservice是作为一个Back-end services服务来处理的,同时拥有一个Http 类型的Adapter来连接此Back-end services服务。
假设已存在一个webservice地址: 并存在一个方法qqCheckOnline并接受一个参数qqCode用来查询用户QQ是否存在。
首先让我们创建一个Back-end services,找到工程的services目录-右键选择Discover Back-end Services:
在弹出的窗口中选择WSDL类型,然后填入该wsdl地址,选中相关接口然后Finish:
工程目录结构如下:
①Adapter目录中会生成一个名为SoapAdapter的HttpAdapter,同时在SoapAdapter的XML中含有webservice调用的接口,并且Adapter的实现js也已经生成好了。
②Services目录中也生成好了一个Back-end Services,在上面按右键-Properties能看到调用参数示例。
接下来,让我们编写调用方法:
* wenservice调用
$scope.webserviceCall = function(){
/*参见生成的调用实例*/
var requestJson = {
"qqCheckOnline": {
"qqCode": ""
var headers = {
var invocationData = {
adapter : 'SoapAdapter1',
procedure : 'qqOnlineWebService_qqCheckOnline',
parameters
: [requestJson,headers]
WL.Client.invokeProcedure(invocationData, {
onSuccess : function(result){
console.log("--------------");
console.log(result);
console.log("是否存在:"+result.responseJSON.Envelope.Body.qqCheckOnlineResponse.qqCheckOnlineResult);
console.log("--------------");
onFailure : function(result){
console.log(result);
调用结果:
其他相关章节:
原文链接:,来自博客,转载请注明来源!
添加新评论worklight好用吗?前景如何?
IBM的worklight studio大家用过吗,感觉如何?稳定吗,做出来的东西可维护性好吗?请用它做过一个完整项目的开发人员谈谈它的使用感受吧.小型团队用这个做企业app开发合适吗?
本人在用eclipse+phonegap+jqm做一个安卓上的hybird软件,未来这个app可能会放到ios等其他平台上或者做成一个纯html5应用.我感觉eclipse从开发到测试,用到的工具太零散,想用worklight换掉eclipse,今后用worklight做开发,不知可行性好吗?
按投票排序
我在 答案的基础上再补充几点:1. IBM的产品一直是大而全,复杂繁琐。大而全的缺点是用起来没有那么顺手和犀利,同时在某个特定领域,产品的功能比较浅。比如,Worklight自带了数据分析功能,它提供了一些预定义的简单报表。但在实际应用中,这个功能太过简单而无法支持客户定制化的需求。2. 个人认为Worklight最多只能适合在企业内部用用,缺点太突出。第一是性能,页面都是纯的html+js,而且基本用的是SPA的形式,做个简单的demo没问题,稍微复杂点的应用,性能绝对不靠谱,参考12306。第二,很难实现和Native应用一样的动画效果,而这点恰恰是很多客户想要的。第三,既然是基于web的,那肯定有兼容性的问题,客户要求支持的设备越多,兼容性问题就越突出,除了主流的苹果,三星,还有国内的各种杂牌厂商的,安卓版本还要支持2.*的,哭去吧。3. 售后支持。Worklight是IBM的一个新产品,至少在中国内地,根本没有一个资深的Worklight Consultant可以帮助客户解决实际问题。Worklight的实施也没有一个好的最佳实践。IBM内部可以说没有有效的Worklight产品的培训,大家都是边做项目边学习。最后,传闻上海CDL Worklight研发组的成员都跳光了。
提起IBM Worklight ,可以氣得我幾晚都睡不著目前負責的兩個項目,一個是建立和布署移動平台,也就是IBM Worklight 版本是6.2。另一項目是基於Worklight 開發的手機應用。IBM Worklight 并不適合一般的企業用於移動方案,原因是整體成本是非常非常的貴! 最要的是不值!!!!!在沒有展開全文之際,假如貴司錢多人少想要快,買IBM Worklight 的話,聽我一言,千萬別上當。以下是我對Worklight 的認知,和痛苦IBM Worklight ,現在產品改為 IBM Mobile First,有以下幾個組成部份組件一 Worklight StudioWorklight Studio 是一個在Eclipse 上的擴展,可以簡單的認為PhoneGap 的加強版,帶有一個Worklight Development Server ,而這個套件的Patch Level 是要和你最終Deploy 的伺服器要對等,不然整個系統會死給你看。組件二 Worklight Application Center就是一個對內的,可以看作是 B2B 或者是Apple 的Enterprise App Center 。我沒有怎麼用,不了解組件三 Device RuntimeRuntime ,看圖好像寫了很多功能,其實超過九成就是PhoneGap 的東西,然後有一些自帶的API 寫到Worklight Server組件四 Worklight Server *** 重點 ***為什麼說是重點?Worklight 的賣點是可以Direct Update ,免除了很多業務上的更新導致要重新上架的時效,就是「Time To Market」。問題是這Server 有一千種低級,可笑的Bug !!!!這Worklight Server ,其實并不是Server 。是一個運行在IBM WebSphere Application Server 上的應用。沒錯,它只是應用,在架構層面來說,Worklight Server 充其量是 Worklight Application Instance。而它的功能其實是 DSL runtime ,可以較靈活的配合 Device Runtime 完成Business Logic 而不須要重新上架。作為只是一個運行在 IBM WAS 的應用,所以這個Worklight Server(Instance) 其實是有Threading issue,所以在Worklight Project 上真的信了IBM 使用了JMS, Java Adapter. 那恭喜你了,可以天天睡在公司了。假如貴司很有錢,伺服器不只一台,是集群的,還是恭喜你了,用天價買回來了垃圾!!!!Worklight Server 是依賴 WAS 作為集群的自動同步。假如貴司是一家充滿熱血,應用常有更新的話。那Worklight Server 會死給你看,因為它有系統同步問題,你會在deploy 完成後,整個系統沒有反應,然後在log 里找到一句完整的英文說同步失敗,請restart application,是application ,你不會知道是要restart server? restart WAS? 還是restart worklight。而且假如你用了Java Adapter,那你就有更深層次的Bug 體驗。就是你可以想的都Restart 完了,都系統還是死給你看?怎麼?你只有把會調用Java Adapter 的 HTTP adapter remove 掉。它才開始有反應。最後還要記住上Adapter
的順序,不然,那些含有heart beat 的adapter 也會弄死worklight server。別問我為什麼,IBM Global S2 的技術支持也不作回答,他們說,你們還是升去最新版本吧~~~~然後到了最無聊,沒想到會有問題的地方了,大家都習以為常,而IBM Sales 說支持的Push Notification 是有重大的問題!!!!Worklight 的Push Notification 是基於 User Group Tag 來設計的。也就是說,系統要發給獨立一個用戶,該用戶自己就要有一個獨立的Tag。也就是你系統要 User Group Tag Pool 里是含有 1:1 的Tag 。因為Worklight 只能做到Active Active 的集群,假如你要群發大量推送,系統會直接佔用高於50%的CPU,就算你有十台集群,也只會那個被你要求服務的instance 給你做!! 可且你并不會知道到底有沒有,有沒有發送成功!!!!更可恨的是!!! 你更新HTTP Adapter 也要restart worklight instance,不要然Push Notification 會死掉!!!!!假如你的系統是要Worklight HTTP Adapter 保存一些 Application Level Session,對不起, Worklight 是沒有這東西的!!! 你要用,他們技術顧問會叫你把session / system token 寫到Database !!!,成千上萬的mobile request 要到DB 里拿一拿token 再去子系統完成Business logic!!! 。然後呢,逼著寫Java Adapter ,而這Java Adapter 編譯時要非常注意,要求是伺服器環境的Patch Level , JRE version 和 Worklight studio 一樣,不然,你會在deploy 完整個,是整項目,直接因為這個原因把整個worklight server 弄死!!!!!!前景就是,希望使用過Worklight 的同業都出來說一說這IBM Worklight 給你帶來多少痛苦。以上我只寫了十份一 !!!! 技術支持就是耗你一個月,問一千樣面試似的技術問題,然後說你版本過底,請用最新的Patch !! 如果剛所說,升級Patch 是開發端也要升級,然後要重新編譯,然後要按排伺服器更新,再重新deploy,再按排測試部門作全面功能檢測,才上線!!!! 然後才有機會知道這Patch 有沒有解決它產品的問題!!!!
本人资深worklight使用者,对worklight各种功能用了不能再用。我觉得worklight目前来讲还是着眼于传统企业用户。个人开发仅供学习和参考。它的优势是IBM建立了一套完整地安全、推送、更新、整合等解决方案。这个跟自己用开源从0做起的代价是不一样的。它是有很多不足,目前比较挑战的是过分依赖Eclipse平台,从google对Android的战略来讲已经转向了Android studio上,这个挑战会很大;还有就是对于云平台,特别是IBM自己的云平台的支持还有待提高。目前IMF(IBM Mobile First)还没有提供云平台的版本。最后我要说,任何事物出现都有2面性,IBM IMF也不例外,不过这个产品还处在成长阶段,但毕竟一开始就站在了巨人的肩膀上了,所以你一看到的就是完整地解决方案,所以从全局而言,绝对是可用的。至于上面同仁所说的,关于分析报告等得诟病。我要说的是术业有专攻,如果你的应用已经发展的了一定高度,并开始使用高级分析功能,那么默认IMF提供的这些功能肯定是很弱,因为他的重点不是这方面而已,这不是他自己的错,就好比你买了一本书,虽然随书附赠了光盘,但是你读了一段时间,感觉应该有必要跟作者作交流,但是这件事,是书无法做到的,他只能提供一些基本的邮箱QQ之类,交流的话肯定要通过其他工具实现。
目标客户是企业App应用的话,Worklight平台还是个不错的选择。对于企业级的应用,App前端(UI)的开发工作量一般能占到30%左右。而剩余70%左右的工作量都是和企业后台业务等相关的。例如需要考虑用户参与度(灵活的信息推送,位置追踪,是否需要离线工作,App的分发方式....),安全(用户授权,恶意软件防范,数据保护,推送安全升级,...),运营(管理App的版本和升级,影响用户体验的问题追踪,...)等等方面。总之,针对企业级的移动应用开发,IBM的Worklight提供了从前端到后端,从开发到部署,从信息推送到数据收集和分析的一系列的,全套的,完整的解决方案。以上仅是个人意见,仅供参考。
我所在的银行今年开始也使用Worklight(现在叫MobileFirst ),前台用angularjs,做出来的页面还是不错的,我负责其中一个模块iOS源码SDK的编写,提供给MobileFirst那边调用(PS:MobileFirst不是万能的,很多地方必须写OC)。中间出现过好多奇形怪状的bug,不过基本都能解决。因为银行今年开始统一配备iPad air 2,所以只做iOS版本,其他情况不同清楚。总的来说IBM的东西里面会掺杂超级多其他技术混合才能使用,感觉没Facebook的react native好用吧。2016年开始在银行系统中我发现很多银行工作的朋友都聊到了公司开始使用手机端跨平台开发技术,这应该就是一个趋势吧。
worklight对用户强行推送增量包才能打开的情况,有没人能找到方法不需要安装都可以打开app。
Worklight(现在叫MobileFirst Platform Foundation,简称MFPF)一致很关注,但最近才开始仔细琢磨。下面就最新版本7.1谈谈看法:1、MFPF的本质是一个企业移动应用的运行和管理平台,其价值在Server能力,而不是前端开发能力。2、MobileFirst Platform
Studio是基于Eclipse的混合应用前端开发工具和Adapter开发工具。但7.1提供了命令行mfp,可以完成MFPF开发、测试和发布的所有功能。采用命令行,开发人员任然可以选择喜欢的IDE,比如xcode、Android Studio,或者subline等。3、在五年前强调worklight的价值是支持多手机平台(比如iOS, Android, Windows Phone, BlackBerry)的开发混合应用,但在如今主要的手机平台只有iOS和Andrioid,因此支持混合应用的开发能力所带来的价值大不如以前。我是移动开发新手,不熟悉iOS和Android的Native开发和基于HTML5/CSS/JavaScript Web开发。但我会比较倾向采用Native方式调用MFPF提供的SDK进行Native应用开发,这样出现问题比较容易定位。如果采用混合应用开发,如果MFPF所依赖的Cordova有缺陷,定位和解决问题的周期会比较长。
12306用的就是WorkLight,可见一斑
作为一个曾经的GDC码农,关于worklight我只想说一点。bug多而且低级到你无法想象!
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 ie浏览器无法启动 的文章

 

随机推荐