2008年6月11日
#
java在桌面软件的失利,很大程度上取决与她运行环境的陪着复杂度,还有随时带的一个庞大的jre环境。有时候我们并不需要jre中全部的类库支持,我们只需要一些对我们项目有用的类库,能否有一种通用的方法来抽取jre中的这些对我们有用的部分呢?google了下找到了几篇文章介绍这个的。主要就是用verbose参数运行jar,然后观察java载入了多少java类,然后手动或者写个程序自动的吧这些类打包和jvm打包为一个全新的jre环境。这种方法是可行的,但是却是不通用,而且这种方法还有一个很大的弊端,当有些类导入到我们项目中,但是在verbose的时候没有用到(比如一些异常类),我们就不会导入,最终可能在发布运行的时候就用到了,这样可不妙。那么是否还有其他方法来瘦身jre环境呢,然后通过随身附带jre发布java程序?答案一定是有的,我已经着手在开发这个应用,我把她起名为BuildJre。
一,可行性分析(我们加上在win系统下):
java.exe是java运行的一个入口程序,当我们键入明了 java className的时候,首先启动都是这个程序,然后这个程序回去查找可用的jre库,一般是先搜索本目录和父亲目录,如果接着搜索环境变量,判断是否为jre的依据是,首先java.exe查找怀疑目录(比如父目录)的bin下有没有java.dll,如果找到,那么他就判定这个是jre目录然后查找lib\i386下的jvm.cfg,最后更具这里面的参数去启动bin\client或者bin\server下的jvm.dll,这个才是真正的java虚拟机,到这里,java.exe把控制权全部交给jvm,然后jvm就初始化,分配内存等,运行程序了,运行程序期间导入的jdk包,都在jre目录下的lib\rt.jar下。
说道这里,我们发现,其实不用环境变量,只要有jre环境就能运行java程序,这使得我们更加坚定java程序也可以桌面化,因为他也是可以不用配置那么麻烦的环境变量直接运行的。再回到瘦身来,刚才说了,jdk中所有的以来包全部位于jre\lib\rt.jar下,我们要廋的就是这个,40多M的rt,我们通过类依赖抽取,对于一个普通的java程序,预计可以廋到小于10M,然后配合java.exe,java.dll,等几个小的程序,预计目标是平均廋身到15M以内。
二,实施思路,用verbose方法不通用,不能在程序内部抽取jre,而且还有可能遗漏依赖项,不足提倡。我们架设有一个标志的依赖说明库,比如ArrayList这个类依赖的所有包都一一对应,那么我们如果在程序里import ArrayList的话,那么我们可以迅速抽取相关的依赖包,然后在整个项目的所有import中去重复,不就ok了?现在的问题在于:
1,不是所有的jdk包都需要import的,比如java.lang下就不用import
2,有些jdk内部类在同一个包下不用写import也一样依赖。
3,计算jdk内部依赖估计要很长实践,因为文件很多,依赖很复杂。
这些问题基本上都有解决方法,我已经开始着手解决。
希望有一天,我们的java项目发布,只要带上10M的小型环境,也不用配置环境变量,双击,ok。。哈哈
这年头,webgame一个一个的冒出来,令我们应接不暇,有人说webgame是一场新的泡沫,也有人说是互联网新的机会,有人说webgame是小公司叫板游戏行业的机会,也有资深游戏人士说小公司做webgmae没戏(盛大高管说,因为没有品牌和玩家资源)。不管怎么样,webgame的兴起已经无法阻挡,包括我们公司,也是众进军者中的一个。
webgame游戏商进军的主要两个领域是 策略类游戏(往往以js,ajax技术和纯通的web技术为基础),和flash休闲社区游戏(以flash as3等技术为基础)。策略类游戏很早就有了,甚至比现在的门户网站还早,只是那个时候没有现在这么兴起,时下具有代表性的主要是一些三国,战争类游戏,像盛大这种大游戏公司也介入不少,连baidu这种重来不碰游戏的公司都开始进入了。而flash游戏相对来说比较少,比如梦境家园(纯休闲娱乐,可以k歌),比如热舞街(劲舞团的web版),天空左岸 和 富豪街 等都不错。还有两个我本人比较期待的还没有公测的flash网游,一个是昆仑online,一个是和热舞街,富豪街同一个公司的 口袋宠物。看他们的游戏截图已经非常类似传统的大型游戏了。当然,更期待的是我们在开发的flash网游,哈,内容和名字现在还不能透露(小小透露下,我们的网游pk模式和现在任何一种网游的pk模式都不同,挺好玩的哦)。
。。。。不想说了。。想起来一本书上的一句话“真正有想法的人,已经埋头在实现自己的想法了,不会把自己的想法写出来,在网上瞎扯淡的,都是没事干的。”
游戏前台主要以flash as3 为主,后台用java,目前已经初步做出一个原型,包括用户行走,多用户移动同步,地图场景与主程序分离,场景加载等等功能,地图编辑器也已经做的差不多了,计划今天能完成,如果完成的话,就可以直接拿给美工去做地图场景了,最终导出一个xml文件和相关的资源(图片等),主程序通过这个xml文件加载场景。
这几天主要的任务包括 客户端UI统一界面设计,需要做到高耦合,让ui界面通过xml文件配置,服务器端数据库的设计,主程序调用外部swf模块的企业级设计,游戏任务脚本语言的初步设计,等等。
以后开始正式要做网络游戏啦,flash前台,java后台。嘿嘿
还没有整理出完整的api,里面有一个简单的例子。
下载
IMVC对ajax有了很好的支持。主要体现在两方面。
一 ajax View类型支持。Imvc的视同是通过一个View类来返回的,在action中通过return new View("/xxx.html")返回一个视图,然后IMVC会通过Value中的数据渲染这个视图。这是一般的流程,有些特殊的流程可以返回其他类型的View,我们先来看看View类的代码:
public final class View implements Cloneable{
/**
* 属性介绍:普通的view,通过模板转换
*/
public static final int TYPE_VIEW=1;
/**
* 属性介绍:转向,不改变url
*/
public static final int TYPE_REDIRECT=2;
/**
* 属性介绍:专心 ,改变url
*/
public static final int TYPE_REDIRECT2=3;
/**
* 属性介绍:直接返回string,path的值
*/
public static final int TYPE_AJAX=4;
public static final int TYPE_EXCEPTION=5;
private String path;
private int type=1;
public View(String path){
this.path=path;
}
public View(String path,int type){
this.path=path;
this.type=type;
}
public View(Map map){
JSONObject jsono=JSONObject.fromObject(map);
path=jsono.toString();
type=TYPE_AJAX;
}
public View(List array){
JSONArray jsona=JSONArray.fromObject(array);
path=jsona.toString();
type=TYPE_AJAX;
}
public View(Object bean){
JSONObject jsono=JSONObject.fromObject(bean);
path=jsono.toString();
type=TYPE_AJAX;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public View clone(String path){
View v=cloneBase();
v.path=path;
return v;
}
public View clone(String path,int type){
View v=cloneBase();
v.path=path;
v.type=type;
return v;
}
public View clone(Map map){
View v=cloneBase();
JSONObject jsono=JSONObject.fromObject(map);
v.path=jsono.toString();
v.type=TYPE_AJAX;
return v;
}
public View clone(List array){
View v=cloneBase();
JSONArray jsona=JSONArray.fromObject(array);
v.path=jsona.toString();
v.type=TYPE_AJAX;
return v;
}
public View clone(Object bean){
View v=cloneBase();
JSONObject jsono=JSONObject.fromObject(bean);
v.path=jsono.toString();
v.type=TYPE_AJAX;
return v;
}
private View cloneBase(){
View v=null;
try {
v = (View) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return v;
}
}
我们主要关注以下几个变量:
/**
* 属性介绍:普通的view,通过模板转换
*/
public static final int TYPE_VIEW=1;
/**
* 属性介绍:转向,不改变url
*/
public static final int TYPE_REDIRECT=2;
/**
* 属性介绍:专心 ,改变url
*/
public static final int TYPE_REDIRECT2=3;
/**
* 属性介绍:直接返回string,path的值
*/
public static final int TYPE_AJAX=4;
public static final int TYPE_EXCEPTION=5;
第一个是普通的View,通过ViewFactory.getView("/tt.html")这个方法返回的是普通的view,也就是可以通过IMVC渲染的视图,而TYPE_REDIRECT则是返回一个跳转view,可以跳转到下一个action,TYPE_REDIRECT2也是一个跳转view,不过是改变URL地址的view。TYPE_AJAX就是ajax试图了,也是今天要讲的主角了,至于最后一个TYPE_EXCEPTION,是把异常返回到客户端浏览器到view,这里暂时不考虑。我们可以通过这样一个构造函数创造出ajax试图,比如new View("这是ajax信息",View.TYPE_AJAX),或者通过ViewFactory.getView("这是ajax信息",View.TYPE_AJAX)也是一样,不过用factory创建的对象是通过对象的clone创建的,能节省一定的性能开销。当返回的是一个ajax View的时候,信息就会直接返回,而不是通过渲染试图,比如上面的就直接返回“这是ajax信息”给客户端,如果这个action是由客户端ajax请求的话,直接返回数据,是不是很方便呢?
接下来的ajx特性也许会让你觉得更方便,比如以下代码:
....action前面的内如.....
User u=new User();
u.setAge(1);
u.setName("汪汪汪");
return ViewFactory.getView(u);
这样的返回会直接在客户端打印出 {"age":1,"name":"汪汪汪"};也就是IMVC把对象映射成立JSON(一种js对象的String形式),这个返回数据在客户端直接可以调用,比如data.name就直接调用出“汪汪汪”,是不是很方便?而且IMVC还支持把List,数组,Map,还有对象相互无限级嵌套返回成JSON数据,这将大大增加AJAX开发的敏捷性和清晰性。
二 ajax Chain支持。我们假设有一个全部ajax的网页,里面有几个div中的数据都是通过ajax的方式向服务器请求的,那么每个div都会请求一次ajax action,这样就导致了请求次数频繁,资源的浪费,IMVC提供了一种ajaxChain的概念,可以通过一个url请求多个action,然后把数据自动合并,比如下面的url
http://xxx.com/ajaxChain.x?id=|one,two?id=1|
这个url请请求了两个action,然后把action数据合并,比如本来one.x返回的数据是{"name":"111"},而two返回的数据是 {"name":"2222"};则现在应该返回的是{"one":{"name":"111"},"two?id=1",{"name":"2222"}},这样,ajaxChain支持无数个action的连接。这样以后可以将多个ajax合并为一个ajax,节省服务器资源。
好了,IMVC的ajax支持就讲到这里。