使用G4JSF整合JSF与GWT(完整版)

时间:2022-11-05 20:01:34

网上已经有很多这方面的文档,但很奇怪大家都只翻译了一半,而更重要的后半部分却没有看到过翻译。

我也参考了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>