GWT与SPRING整合

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>GWTSpringservlet-name>
6. <servlet-class>
7. org.springframework.web.servlet.DispatcherServlet
8. servlet-class>
9. <load-on-startup>1load-on-startup>
10. servlet>
11.
12. <servlet-mapping>
13. <servlet-name>GWTSpringservlet-name>
14. <url-pattern>*.rpcurl-pattern>
15. servlet-mapping>
16. <servlet>
17. <servlet-name>shellservlet-name>
18. <servlet-class>com.google.gwt.dev.shell.GWTShellServletservlet-class>
19. servlet>
20.
21. <servlet-mapping>
22. <servlet-name>shellservlet-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>requestSettervalue>
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>


我们配置了一个“/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 = new ThreadLocal();
12.
13. private static ThreadLocal servletResponse = new ThreadLocal();
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(2, 0, 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(0, 0, "用户名:");
86. table.setWidget(0, 1, userName);
87. table.setText(1, 0, "密 码:");
88. table.setWidget(1, 1, 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的路径换成你自己机子上的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值