在GWT中,Java的很多机制都是不支持的,比如:
不支持类的动态加载
不支持Java的反射机制
不支持标准Java序列化
不支持WEB模式下的Java对象清理
不支持strictfp关键字,要避免在客户端代码中进行精确精度的计算
......
如果我们想让GWT支持反射机制,可以使用GWT Reflection框架扩展实现。以下简单介绍其实现步骤:
1、到http://gwtreflection.sourceforge.net/网站下载GWT Reflection框架文件,将ant.jar、antlr-2.7.7.jar、commons-cli-1.0.jar、gwtr-core.jar、gwtr-emule.jar、stringtemplate.jar这些jar文件拷贝到工程的lib目录下。
2、修改gwtr-emule.jar的JavaToJSArrayUtil.java源文件,将包含long和Long的代码段去掉,重新编译后覆盖gwtr-emule.jar里面对应的class文件和java文件。
如果不这样做的话,在启动工程时会抛出以下异常信息:
[ERROR] Errors in 'jar:file:/E:/gwtext/web/WEB-INF/lib/gwtr-emule.jar!/pl/rmalinowski/gwtreflect/client/utils/JavaToJSArrayUtil.java'
[ERROR] Line 90: Parameter 'value': type 'long' is not safe to access in JSNI code
那是因为:
在GWT1.5中,现在Java long类型可以正确的工作,允许你给一个64位的整数一个完全适当的范围。然而,由于JavaScript缺少真正的64位整型,long 被视为一对32位整型,使用JavaScript的标准数学符号不能很好的工作。
如果你给JSNI传入一个long型值,GWT1.5编译器会产生错误,此时在你不完全需要long范围的地方,推荐方式是把类型改为double 。事实上,如果你使用long返回System.currentTimeMillis(),我们推荐你使用新建的Duration类来作为替换方式。对于JSNI 方法来说,它使用派生对象(opaque objects 不能进行任何数学计算)来处理long 值,你可以使用UnsafeNativeLong annotation 来欺瞒编译器。但是我们强烈建议您避免这种方式,因为很容易忘掉JSNI方法中该值是一个非数值型的。
修改pl.rmalinowski.gwtreflect.tool.AntAttributeStrategy类的源码为:
public class AntAttributeStrategy implements ClassFindingStrategy {
public boolean isClassReflectable(Class clazz) {
Class[] classes = clazz.getInterfaces();
if(classes!=null && classes.length>0){
for(int i=0;i<classes.length;i++){
if(classes[i].getSimpleName().equals("Reflectable")){
return true;
}
}
}
return false;
}
}
,这样,只有实现了Reflectable接口的类才会生成其反射代理类。
3、如果要让一个类支持通过反射机制进行实例化,该类必须实现GWT Reflection框架中的Reflectable接口,其范例如下:
public class TicketRecievePanel extends BasePanel implements Reflectable{
public TicketRecievePanel(){
setTitle("票证领取:TicketRecievePanel");
setClosable(true);
}
@Override
public void onLoad() {
MessageBox.setMinWidth(150);
MessageBox.alert(this.getTitle());
}
}
通过反射实例化一个类的方法是:调用GWT Reflection框架中的Class类的forName方法。其范例如下:
String panelName = "com.cjm.client.ticket.TicketRecievePanel";
BasePanel panel = (BasePanel)pl.rmalinowski.gwtreflect.client.reflect.Class.forName(panelName).newInstance();
4、生成类的反射代理类和反射代理类的注册器类
一个类在能够支持通过反射进行实例化之前,必须要用GWT Reflection框架提供的ant命令 GWTReflect 来生成该类的反射代理类和反射代理类的注册器类,然后调用注册器类的registerAll方法注册反射代理类之后,才能使反射机制生效。
注册反射代理类的范例代码:
ClassRegistrator.registerAll();
先注册反射代理类,再调用Class类的forName方法。
在调用ant命令 GWTReflect 生成类的反射代理类之前,必须先将类打包成一个jar文件
ant任务定义文件源码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
主要功能:
1、清除之前生成的文件
2、将类打包成jar文件
3、生成反射代理类
4、将反射代理类复制到java源码目录
-->
<project default="main" basedir=".">
<property name="path.webinf" value="${basedir}/web/WEB-INF"/>
<path id="lib.path">
<fileset dir="${path.webinf}/lib" includes="*.jar"/>
</path>
<!-- 将类打包成jar文件 -->
<target name="buildJar">
<jar destfile="ticket.jar">
<fileset dir="${basedir}/build/classes/">
<exclude name="com/cjm/client/gwtr/**"/> <!-- 排除反射代理类 -->
<exclude name="com/cjm/public/**"/>
<exclude name="com/cjm/server"/>
</fileset>
</jar>
</target>
<target name="clean">
<delete file="${basedir}/ticket.jar"/>
<!-- 删除java源码目录中的反射代理类 -->
<delete dir="${basedir}/src/com/cjm/client/gwtr"/>
<delete dir="${basedir}/gwtr_src"/>
<mkdir dir="${basedir}/gwtr_src"/>
</target>
<!-- 用于生成反射代理类的task -->
<taskdef name="gwtreflect" classname="pl.rmalinowski.gwtreflect.ant.GWTReflect" classpathref="lib.path" />
<!--
outdir:生成类的输出目录
source:需要生成反射代理类的目标类的jar文件及其依赖jar文件
packagein:目标类的包路径
packageout:反射代理类的包路径
templatepath:模板所在路径
-->
<target name="main" depends="clean,buildJar">
<gwtreflect
outdir="${basedir}/gwtr_src"
source="${basedir}/ticket.jar;${path.webinf}/lib/gwtext.jar;${path.webinf}/lib/gwt-user.jar;${path.webinf}/lib/gwtr-core.jar;${path.webinf}/lib/gwtr-emule.jar"
packagein="com.cjm.client"
packageout="com.cjm.client.gwtr"
templatepath="${basedir}/st">
</gwtreflect>
<!-- 将反射代理类复制到java源码目录 -->
<copy todir="${basedir}/src">
<fileset dir="${basedir}/gwtr_src"/>
</copy>
<delete dir="${basedir}/gwtr_src"/>
</target>
</project>
对于范例中的TicketRecievePanel类,将生成以下两个Java类:
TicketRecievePanel__GWTR 反射代理类
ClassRegistrator 反射代理类的注册类。一个包下有一个注册类
5、需要在模块配置文件增加以下信息:
<inherits name="pl.rmalinowski.gwtreflect.GWTReflect"/>
分享到:
相关推荐
标题中的“gwt反射”指的是Google Web Toolkit (GWT) 中的反射机制。GWT 是一个用于构建富互联网应用程序(RIA)的开放源代码Java框架,它允许开发者使用Java编程语言来编写前端应用,然后通过编译器将Java代码转换...
【标题】:“GWT反射”是指在Google Web Toolkit (GWT)环境中利用Java的反射机制来操作类和对象的一种技术。GWT是一个开源框架,它允许开发者使用Java语言编写客户端Web应用,然后编译成高效的JavaScript代码运行在...
- **反射与垃圾回收**:GWT不支持Java的反射机制,以提高性能和减少复杂性。JavaScript引擎的单线程性质使得GWT中的`synchronized`关键字无效,同时没有垃圾回收机制,开发者需手动管理内存。 3. **运行时库支持**...
5. **反射**:GWT不支持Java的反射机制,但提供GWT.getTypeName(Object)来获取对象的类名。 6. **无用对象清理**:JavaScript不支持垃圾回收,GWT无法在Web模式下清理JAVA对象。 7. **严格浮点运算**:GWT不支持...
然而,某些特性在JavaScript中无法完全实现,如long类型被映射为double,多线程同步关键字`synchronized`仅作标记,反射机制受限,以及严格浮点运算不受支持。 2. **运行时库**:GWT模拟了Java运行时环境的一部分,...
5. **反射与动态类型**:GWT不支持Java的反射机制,以提高效率和优化编译结果。`GWT.getTypeName(Object)`提供了一种获取对象类名的方法。 6. **无用对象清理**:JavaScript没有垃圾回收机制,因此GWT在Web模式下...
- **反射**:GWT不支持Java的反射机制,但可以通过GWT.getTypeName(Object)获取对象的类名。 - **无用对象清理**:GWT不支持JavaScript的垃圾回收,因此开发者需要手动管理客户端对象。 - **浮点数处理**:GWT不...
- **序列化**:由于动态类装载和反射在编译后的 JavaScript 中不可用,GWT 不支持标准的 Java 序列化,而是提供了一个 RPC 机制,支持在调用远程方法时的自动对象序列化。 #### 二、构建用户界面 这部分涵盖了如何...
这使得开发者能够在开发过程中使用熟悉的Java语法和结构。 - **统一的编程模型**: GWT允许开发者使用Java编写客户端和服务器端代码,从而实现了语言层面的统一,便于代码复用和维护。 - **跨平台和兼容性**: 生成的...
1. **Java Bean to JavaScriptObject 转换**:Gwt-Bean 提供了将 Java Bean 对象自动转换为 JavaScriptObject 的能力,使得 Java 对象可以直接在浏览器环境中使用。这大大简化了数据在服务器端和客户端之间传递的...
【GWT-Dagger2-Demo】是一个演示项目,它展示了如何在Google Web Toolkit(GWT)应用程序中集成和使用Dagger 2依赖注入框架。这个项目对于理解GWT与Dagger 2之间的协同工作方式非常有帮助,尤其对Java开发者来说,...
此外,通过阅读源码,初学者也可以学习到关于GWTP框架、Maven插件开发以及Java反射机制的相关知识。 总的来说,GWTP-Typed-Slot-Upgrader是GWT和GWTP项目升级过程中的一个实用工具,它可以自动化处理TypedSlot的...