网上已经有很多这方面的文档,但很奇怪大家都只翻译了一半,而更重要的后半部分却没有看到过翻译。
我也参考了theserverside上面关于这方面的经典文章:http://www.theserverside.com/tt/articles/article.tss?l=GWTandJSF
并加了自己的一些注解,希望对大家有所帮助。
整合流程:
1、正常的编写GWT组件
2、在hosted mode下,可以通过修改public/*.html来向Widget动态传递参数,Widget通过Map m = getWidgetParams(id);来获取参数;
比如:final String buttonLabel = (String) m.get("buttonLabel");
但这种方式只能用于Hosted Mode,在Run Time模式下不能用。这个时候就需要通过JSF EL来做。
3、通过G4JSF编译GWT module.
ant -Dout=D:/workspace/KickStart -Dmodule=demo.gwt.HelloWidget create-component
这样就产生了可供JSF对应的页面,这里用了Facelet. 在WebContent下能找到对应的页面。
编辑对应的xhtml页面,找到<widget:component id="main" />,定义其buttonLabel等属性。然后就可以在Run Time查看。
4、定义一个Managed Bean,
package demo.gwt.app;
import demo.gwt.client.ResultGreeting;
import demo.gwt.client.EventData;
public class GreetingBean {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//事件响应返回一个Result类,且事件的参数是一个EventData类,也就是Event参数
public ResultGreeting takeGreeting(EventData event) {
name = event.getName();
ResultGreeting result = new ResultGreeting();
result.setGreetingText("Hello " + name + " from JSF!");
return result;
}
}
然后就可以通过JSF EL来传递值。
<widget:component id="main" buttonLabel ="#{bundle.buttonLabel}"
greeting="Hello #{greetingBean.name}!" />
同样可以通过资源文件传递,比如上面的buttonLabel。这只需要在xhtml中添加<f:loadBundle basename="demo.gwt.app.bundle.Labels" var="bundle"/>
完成上面部分只是完成了客户端的一小部分,还有如何实现JSF响应GWT请求的重点。
5、GWT通过RPC来实现与服务器端的交互,而不是标准AJAX的XMLHttpRequest。
先定义客户端向服务器端传递参数的Event类。
package demo.gwt.client;
import org.ajax4jsf.gwt.client.GwtFacesEvent;
public class EventData extends GwtFacesEvent {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建服务器向客户端返回值的Result类
package demo.gwt.client;
import org.ajax4jsf.gwt.client.GwtFacesResult;
public class ResultGreeting extends GwtFacesResult {
String greetingText;
public String getGreetingText() {
return this.greetingText;
}
public void setGreetingText(String greetingText) {
this.greetingText = greetingText;
}
}
在Hosted Mode中,修改组件代码。
public class HelloWidgetEntryPoint extends ComponentEntryPoint {
Label status;
TextBox input;
protected Widget createWidget(final String id) {
Map m = getWidgetParams(id);
final String buttonLabel = (String) m.get("buttonLabel");
HorizontalPanel panel = new HorizontalPanel();
input = new TextBox();
status = new Label("Loaded.");
//创建一个后台服务接口,在hosted mode下,调用MockHelloWidget.sendEvent ,在Run Time模式下,调用GreetingBean.sendEvent
final GwtFacesServiceAsync service = createFacesService(id);
//service执行的回调函数
final AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
if (null != result) {
status.setText("Loaded");
String greeting = ((ResultGreeting)result).getGreetingText();
Window.alert(greeting);
} else {
status.setText("Request finished, but the result is empty");
}
}
public void onFailure(Throwable caught) {
status.setText("Error call :" + caught.getMessage());
}
};
//定义Button,并指定事件监听器,监听器调用service实现响应
Button btn = new Button(buttonLabel, new ClickListener() {
public void onClick(Widget sender) {
EventData eventData = new EventData();
eventData.setName(input.getText());
service.sendEvent(eventData, callback);
status.setText("Loading...");
}
});
panel.add(input);
panel.add(btn);
panel.add(status);
return panel;
}
}
在Hosted Mode下进行调试,需要定义一个RPC类,来模拟JSF响应,在调试成功后将方法内的代码粘贴到JSF Managed Bean对应的Action Listener方法中即可。
public class MockHelloWidget implements GwtFacesService {
/* (non-Javadoc)
* @see org.ajax4jsf.gwt.client.GwtFacesService#sendEvent(org.ajax4jsf.gwt.client.GwtFacesEvent)
*/
public GwtFacesResult sendEvent(GwtFacesEvent event){
ResultGreeting result = new ResultGreeting();
result.setGreetingText( "Hello " + ((EventData)event).getName() );
return result;
}
}
修改xhtml文件中的组件tag,添加事件监听器
<widget:component id="main" buttonLabel="#{bundle.buttonLabel}"
greeting="Hello #{greetingBean.name}!" >
<gwt:gwtListener method="#{greetingBean.takeGreeting}"
event ="demo.gwt.client.EventData"/>
</widget:component>