论坛首页 Web前端技术论坛

GWT整合SPRING

浏览 26055 次
锁定老帖子 主题:GWT整合SPRING
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-07  
GWT
1. 我们这里整合spring主要是用到了一个组件gwt-widgets-server  可以在http://jaist.dl.sourceforge.net/sourceforge/gwt-widget/gwt-widgets-server-0.1.2-bin.zip下载。
2. 我们使用gwt的命令(projectCreator applicationCreator )生成gwt的eclipse项目,参见:http://code.google.com/webtoolkit/gettingstarted.html   
3. 导入eclipse中,导入后请看附件1.
4. 分析代码
首先看web.xml


 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <web-app>  
  3.   
  4.     <servlet>  
  5.         <servlet-name>GWTSpring<!---->servlet-name>  
  6.         <servlet-class>  
  7.             org.springframework.web.servlet.DispatcherServlet  
  8.         <!---->servlet-class>  
  9.         <load-on-startup>1<!---->load-on-startup>  
  10.     <!---->servlet>  
  11.   
  12.     <servlet-mapping>  
  13.         <servlet-name>GWTSpring<!---->servlet-name>  
  14.         <url-pattern>*.rpc<!---->url-pattern>  
  15.     <!---->servlet-mapping>  
  16.     <servlet>  
  17.         <servlet-name>shell<!---->servlet-name>  
  18.         <servlet-class>com.google.gwt.dev.shell.GWTShellServlet<!---->servlet-class>  
  19.     <!---->servlet>  
  20.       
  21.     <servlet-mapping>  
  22.         <servlet-name>shell<!---->servlet-name>  
  23.         <url-pattern>/static/*<!---->url-pattern>  
  24.     <!---->servlet-mapping>  
  25.       
  26. <!---->web-app>  

可以看到我们增加了段GWTSpring的servlet配置,熟悉spring-web的朋友一眼就可以看出。gwt-widgets-server 正是使用了spring-web的control来做gwt的remoteServiceServlet的。他是使用了cglib或者javassist 来动态使我们的Sevice class继承RemoteServiceServlet。细心的朋友可以看到代码中的粗体部分,本来直接生成的gwt模版是"/*"的url- pattern。但是我这里为什么要在前面加上"/static"部分呢?请让我在后面为你解释。下面看看GWTSpring-servlet.xml的配置。

 
  1. xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. >  
  4.   
  5. <beans>  
  6.     <bean id="urlMapping" class="org.gwtwidgets.server.spring.GWTHandler" depends-on="userServiceTarget">  
  7.         <property name="mapping">  
  8.             <map>  
  9.                 <entry key="/userService.rpc" value-ref="userService" />  
  10.             <!---->map>  
  11.         <!---->property>  
  12.         <property name="usingInstrumentation" value="false" />  
  13.         <property name="unwrappingGWTExceptions" value="true" />  
  14.         <!---->
  15.             You can specify your own class enhancer here  
  16.             <property name="classEnhancer">  
  17.             <bean class="org.gwtwidgets.server.spring.enhancer.JavassistEnhancer"/>  
  18.             <!---->property>  
  19.         -->  
  20.     <!---->bean>  
  21.   
  22.     <bean id="userServiceTarget" class="com.javaeye.dengyin2000.truck.server.impl.UserServiceImpl">  
  23.     <!---->bean>  
  24.     <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">  
  25.         <property name="target" ref="userServiceTarget" />  
  26.         <property name="autodetectInterfaces" value="true" />  
  27.         <property name="interceptorNames">  
  28.             <list>  
  29.                 <value>requestSetter<!---->value>  
  30.             <!---->list>  
  31.         <!---->property>  
  32.     <!---->bean>  
  33.   
  34.     <bean id="requestSetter"  
  35.         class="org.gwtwidgets.server.spring.RequestInjection">  
  36.         <property name="requestSetterName" value="setRequest" />  
  37.         <property name="responseSetterName" value="setResponse" />  
  38.     <!---->bean>  
  39. <!---->beans>  

<beans><bean depends-on="userServiceTarget" class="org.gwtwidgets.server.spring.GWTHandler" id="urlMapping"> <property value="false" name="usingInstrumentation"><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="userService">
</bean></property> </bean></beans><beans><bean depends-on="userServiceTarget" class="org.gwtwidgets.server.spring.GWTHandler" id="urlMapping"> <property value="false" name="usingInstrumentation"><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="userService"> <property ref="userServiceTarget" name="target"><bean id="requestSetter"> </bean></property> </bean></property> </bean></beans> <beans><bean depends-on="userServiceTarget" class="org.gwtwidgets.server.spring.GWTHandler" id="urlMapping"> <property value="false" name="usingInstrumentation"><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="userService"> <property ref="userServiceTarget" name="target"><bean id="requestSetter">我们配置了一个“/userService.rpc”的servlet mapping。你应该可以想到这个url应该就是gwt的RemoteServiceServlet的url。我不想多解释配置里面的内容,因为我也是抄的,如果仔细看的话应该可以明白,如果不明白的话可以看看gwt-widgets-server的源码。这段配置里面主要就是初始化了一个gwt的RemoteServiceServlet。他可以是任何的object。不需要显示的继承RemoteServiceServlet,一切都让org.gwtwidgets.server.spring.GWTHandler帮你解决吧。他还帮你在RemoteServiceServlet注入了httpServletRequest 和 httpServletResponse。你不需要使用通过RemoteServiceServlet.getThreadLocalRequest()去取。下面看看UserServiceImpl

java 代码
  1. package com.javaeye.dengyin2000.truck.server.impl;  
  2.   
  3. import javax.servlet.ServletRequest;  
  4. import javax.servlet.ServletResponse;  
  5. import javax.servlet.http.HttpServletRequest;  
  6.   
  7. import com.javaeye.dengyin2000.truck.client.server.UserService;  
  8.   
  9. public class UserServiceImpl implements UserService {  
  10.   
  11.     private static ThreadLocal<servletrequest> servletRequest = </servletrequest>new ThreadLocal<servletrequest>();  </servletrequest>
  12.   
  13.     private static ThreadLocal<servletresponse> servletResponse = </servletresponse>new ThreadLocal<servletresponse>();  </servletresponse>
  14.   
  15.     public void setRequest(ServletRequest request) {  
  16.         servletRequest.set(request);  
  17.     }  
  18.   
  19.     public void setResponse(ServletResponse request) {  
  20.         servletResponse.set(request);  
  21.     }  
  22.   
  23.     protected HttpServletRequest getRequest() {  
  24.         return (HttpServletRequest) servletRequest.get();  
  25.     }  
  26.   
  27.     public boolean checkUser(String userName, String password) {  
  28.         if ("denny".equals(userName) && "123456".equals(password)) {  
  29.             getRequest().getSession().setAttribute("user", userName);  
  30.             return Boolean.TRUE;  
  31.         }  
  32.         return Boolean.FALSE;  
  33.     }  
  34.   
  35. }  

这里面有个checkUser方法。在这里我发现了一个问题。gwt-widgets-server中的例子上面setRequest和setResponse方法里面的参数的类型是HttpServletRequest和HttpServletResponse但是这样的话,requst和response不能被注入。清看
gwt-widgets-server中的RequestInjection class

java 代码
 
  1. package org.gwtwidgets.server.spring;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import javax.servlet.ServletRequest;  
  6. import javax.servlet.ServletResponse;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import org.aopalliance.intercept.MethodInterceptor;  
  11. import org.aopalliance.intercept.MethodInvocation;  
  12.   
  13. /** 
  14.  * Method interceptor that injects the current {@link HttpServletRequest} and 
  15.  * the current {@link HttpServletResponse} via reflection to a target. You must specify 
  16.  * the setter names via {@link #setRequestSetterName(String)} and {@link #setResponseSetterName(String)} 
  17.  * otherwise they will fail silently. These setters can and must have only a single argument 
  18.  * namely {@link ServletRequest} and {@link ServletResponse} respectively. 
  19.  *  
  20.  * @author George Georgovassilis 
  21.  *  
  22.  */  
  23. public class RequestInjection implements MethodInterceptor {  
  24.   
  25.     protected String requestSetterName;  
  26.   
  27.     protected String responseSetterName;  
  28.   
  29.     private void setRequestOnTarget(HttpServletRequest request, HttpServletResponse response, Object target)  
  30.         throws Exception {  
  31.     if (requestSetterName != null)  
  32.         try {  
  33.         Method method = target.getClass().getMethod(requestSetterName,  
  34.             new Class[] { ServletRequest.class });  
  35.         method.invoke(target, new Object[] { request });  
  36.         } catch (NoSuchMethodException e) {  
  37.         }  
  38.     if (responseSetterName != null)  
  39.         try {  
  40.         Method method = target.getClass().getMethod(responseSetterName,  
  41.             new Class[] { ServletResponse.class });  
  42.         method.invoke(target, new Object[] { response });  
  43.         } catch (NoSuchMethodException e) {  
  44.         }  
  45.     }  
  46.   
  47.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  48.     Object target = invocation.getThis();  
  49.     setRequestOnTarget(GWTSpringController.getRequest(), GWTSpringController.getResponse(), target);  
  50.     return invocation.proceed();  
  51.     }  
  52.   
  53.     /** 
  54.          * Specify the name of the setter method that can be invoked to set the 
  55.          * current request and response on the target. If the method does not 
  56.          * exist on the target, it is silently discarded. 
  57.          *  
  58.          * @param setterName 
  59.          */  
  60.     public void setRequestSetterName(String setterName) {  
  61.     this.requestSetterName = setterName;  
  62.     }  
  63.   
  64.     /** 
  65.          * Specify the name of the setter method that can be invoked to set the 
  66.          * current response on the target. If the method does not exist on the 
  67.          * target, it is silently discarded. 
  68.          *  
  69.          * @param setterName 
  70.          */  
  71.     public void setResponseSetterName(String setterName) {  
  72.     this.responseSetterName = setterName;  
  73.     }  
  74.   
  75. }  

请看上面的粗体部分他这里取的参数类型是ServletRequest和ServletResponse。所以我把UserServiceImpl中的setRequest和setResponse类型改成了ServletRequest和ServletResponse。在getRequest中cast成HttpServletRequest。ok,看看在gwt的client中怎么调用吧。

java 代码
 
  1. package com.javaeye.dengyin2000.truck.client;  
  2.   
  3. import com.google.gwt.core.client.EntryPoint;  
  4. import com.google.gwt.core.client.GWT;  
  5. import com.google.gwt.user.client.Window;  
  6. import com.google.gwt.user.client.rpc.AsyncCallback;  
  7. import com.google.gwt.user.client.rpc.ServiceDefTarget;  
  8. import com.google.gwt.user.client.ui.Button;  
  9. import com.google.gwt.user.client.ui.ClickListener;  
  10. import com.google.gwt.user.client.ui.DockPanel;  
  11. import com.google.gwt.user.client.ui.FlexTable;  
  12. import com.google.gwt.user.client.ui.HTML;  
  13. import com.google.gwt.user.client.ui.PasswordTextBox;  
  14. import com.google.gwt.user.client.ui.RootPanel;  
  15. import com.google.gwt.user.client.ui.TextBox;  
  16. import com.google.gwt.user.client.ui.Widget;  
  17. import com.javaeye.dengyin2000.truck.client.server.UserService;  
  18. import com.javaeye.dengyin2000.truck.client.server.UserServiceAsync;  
  19.   
  20. /** 
  21.  * Entry point classes define onModuleLoad(). 
  22.  */  
  23. public class TruckApp implements EntryPoint {  
  24.     private TextBox userName;  
  25.   
  26.     private PasswordTextBox password;  
  27.   
  28.     private Button submit;  
  29.   
  30.     private FlexTable loginTable;  
  31.   
  32.     public static final HTML HEAD_TITLE = new HTML(");  
  33.   
  34.     private UserServiceAsync userService;  
  35.   
  36.     /** 
  37.      * This is the entry point method. 
  38.      */  
  39.     public void onModuleLoad() {  
  40.           
  41.         DockPanel panel = new DockPanel();  
  42.         panel.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);  
  43.         panel.setHorizontalAlignment(DockPanel.ALIGN_CENTER);  
  44.         submit = new Button("提交");  
  45.         submit.addClickListener(new ClickListener(){  
  46.   
  47.             public void onClick(Widget sender) {  
  48.                 // TODO check the user for validate  
  49.                 getUserClientService().checkUser(userName.getText(), password.getText(), new AsyncCallback(){  
  50.   
  51.                     public void onFailure(Throwable caught) {  
  52.                         Window.alert("Server error!");  
  53.                     }  
  54.   
  55.                     public void onSuccess(Object result) {  
  56.                         if (((Boolean)result).booleanValue() == true){  
  57.                             Window.alert("Login successfully!");  
  58.                         }else{  
  59.                             Window.alert("Login failed!");  
  60.                         }  
  61.                     }  
  62.                       
  63.                 });  
  64.             }  
  65.               
  66.         });  
  67.   
  68.         userName = new TextBox();  
  69.         password = new PasswordTextBox();  
  70.   
  71.         loginTable = createLoginTable();  
  72.   
  73.         panel.setWidth("100%");  
  74.         panel.setHeight("100%");  
  75.           
  76.         loginTable.setWidget(20, submit);  
  77.         panel.add(loginTable, DockPanel.CENTER);  
  78.         panel.add(HEAD_TITLE, DockPanel.NORTH);  
  79.           
  80.         RootPanel.get().add(panel);  
  81.     }  
  82.   
  83.     private FlexTable createLoginTable() {  
  84.         FlexTable table = new FlexTable();  
  85.         table.setText(00"用户名:");  
  86.         table.setWidget(01, userName);  
  87.         table.setText(10"密  码:");  
  88.         table.setWidget(11, password);  
  89.         table.setStyleName("ks-layouts-Label");  
  90.         return table;  
  91.     }  
  92.       
  93.     private UserServiceAsync getUserClientService(){  
  94.         if (userService == null){  
  95.             userService = (UserServiceAsync) GWT.create(UserService.class);  
  96.             ServiceDefTarget endPoint = (ServiceDefTarget) userService;  
  97.             String moduleRelativeURL = "/userService.rpc";  
  98.             endPoint.setServiceEntryPoint(moduleRelativeURL);  
  99.         }  
  100.         return userService;  
  101.     }  
  102. }  

java 代码
 
  1. package com.javaeye.dengyin2000.truck.client.server;  
  2.   
  3. import com.google.gwt.user.client.rpc.RemoteService;  
  4.   
  5. public interface UserService extends RemoteService {  
  6.     boolean checkUser(String userName, String password);  
  7. }  

java 代码
 
  1. package com.javaeye.dengyin2000.truck.client.server;  
  2.   
  3. import com.google.gwt.user.client.rpc.AsyncCallback;  
  4.   
  5. public interface UserServiceAsync {  
  6.     void checkUser(String userName, String password, AsyncCallback callback);  
  7. }  

ok。到此配置结束。对了好像还忘了解释为什么要在web.xml中加上/static这段。原因是如果shell的url-pattern是/*的话,就会handler了gwt的RemoteServiceServlet的路径,这样的话remote rpc调用就总是Server error了。这时我们访问地址需要变成http://localhost:8888/static/com.javaeye.dengyin2000.truck.TruckApp/TruckApp.html 这样了。我提交了整个eclipse gwt项目所有代码但是把require lib去掉了。 需要的lib是spring-1.2.8.jar log4j-1.2.13.jar javassist-3.0.jar gwt-widgets-server-0.1.2.jar gwt-servlet.jar commons-logging-1.1.jar cglib-nodep-2.1_3.jar。请自行下载然后放到eclipse项目中的tomcat\webapps\ROOT\WEB-INF\lib\下面。你还需要把项目中引用到gwt lib的路径换成你自己机子上的。

:)

参考:http://g.georgovassilis.googlepages.com/usingthegwthandler
</bean></property> </bean></property> </bean></beans>
  • 大小: 13.4 KB
   发表时间:2007-03-08  
xml格式不正确,浪费了很多时间呀。本以为java格式是正确的,想用java格式。可是出来更吓人。
0 请登录后投票
   发表时间:2007-03-08  
调整格式花了一个小时,基本上每种格式都试过了。 还是不行。请看附件里面的文件吧。java代码的格式没有问题。
0 请登录后投票
   发表时间:2007-03-08  
dengyin2000 写道
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="urlMapping" class="org.gwtwidgets.server.spring.GWTHandler" depends-on="userServiceTarget">
<property name="mapping">
<map>
<entry key="/userService.rpc" value-ref="userService" />
</map>
</property>
<property name="usingInstrumentation" value="false" />
<property name="unwrappingGWTExceptions" value="true" />
<!--
You can specify your own class enhancer here
<property name="classEnhancer">
<bean class="org.gwtwidgets.server.spring.enhancer.JavassistEnhancer"/>
</property>
-->
</bean>

<bean id="userServiceTarget" class="com.javaeye.dengyin2000.truck.server.impl.UserServiceImpl">
</bean>
<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="userServiceTarget" />
<property name="autodetectInterfaces" value="true" />
<property name="interceptorNames">
<list>
<value>requestSetter</value>
</list>
</property>
</bean>

<bean id="requestSetter"
class="org.gwtwidgets.server.spring.RequestInjection">
<property name="requestSetterName" value="setRequest" />
<property name="responseSetterName" value="setResponse" />
</bean>
</beans>
0 请登录后投票
   发表时间:2007-03-08  
可惜还是初级会员不能投票,呵呵
早点看到这篇文章就好了,我是参考GwtPetstore那个项目,我水平太低,分析了好久才模仿成功的.
兄台有没有关于Gwt和报表结合使用相关的文章?
0 请登录后投票
   发表时间:2007-03-08  
报表是server端的事情吧。
0 请登录后投票
   发表时间:2007-03-09  
xml格式的编辑器有bug,你第一次粘贴进去以后,以后再改文章的时候,基本上都要重新粘贴一边才行
0 请登录后投票
   发表时间:2007-03-09  
重新粘贴还是有问题。 在写的时候没有问题, 提交后就乱了。 回家后, 我改成bbcode排版吧。 听说bbcode没有问题。
0 请登录后投票
   发表时间:2007-03-09  
bbcode排版我还没学会....但是我重新粘帖以后就没问题了的说,你可以看看我这个帖子:

http://www.iteye.com/topic/58265
0 请登录后投票
   发表时间:2007-03-09  
还是没有搞定, 可以用了feditor后不能用bbcode了
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics