使用一个servlet来分配所有的gwt service

GWT中默认一个service对应一个servlet,这样会使web.xml要配置很多servlet, 不是很方便。我这里通过一个Dispatch servlet来分配service, 这样每个service都成了pojo,使得配置更加方便,也容易测试。

1. Server code

Configure web.xml like

<servlet>
<servlet-name>gwt-dispatch</servlet-name>
<servlet-class>
com.xxxxx.gwt.GwtRpcServiceDispatch
</servlet-class>
<init-param>
<param-name>prefix</param-name>
<param-value>/gsvc</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>gwt-dispatch</servlet-name>
<url-pattern>/gsvc/*</url-pattern>
</servlet-mapping>

prefix参数表示service访问url的根路径

Why it works: Let's see the code of GwtRpcServiceDispatch.java
1 /**
2 * @author xwang
3 * Dispatch the gwt services
4 */
5 public class GwtRpcServiceDispatch extends RemoteServiceServlet {
6 private static final long serialVersionUID = -2797202947611240618L;
7
8 private Injector injector;
9
10 private int beginIndexOfClassName;
11
12 @Override
13 public void init(ServletConfig config) throws ServletException {
14 super.init(config);
15 // get guice injector, it init by ServletContextListener
16 injector = InjectorHolder.getInjector();
17 if (injector == null) {
18 throw new UnavailableException("Guice Injector not found (did you forget to register a "
19 + this.getClass().getSimpleName() + "?)");
20 }
21
22 // set prefix of service url
23 String prefix = config.getInitParameter("prefix");
24 if (prefix == null || prefix.length() == 0) {
25 beginIndexOfClassName = 1;
26 } else if (prefix.startsWith("/")) {
27 beginIndexOfClassName = prefix.length() + 1;
28 } else {
29 beginIndexOfClassName = prefix.length() + 2;
30 }
31 }

这里先要设置Guice Injector, 应为我们的service中用到了guice. 其次设置prefix的长度.

接着就可以根据URL来实例化RomteService,如下:

1 /**
2 * get service implement class's instance
3 * @return service implement class's instance
4 */
5 protected Object getCurrentHandler() {
6 String classPath = getThreadLocalRequest().getRequestURI();
7 // /gsvc/com/xxxxx/bus/domain/service/LandmarkService => com.xxxxx.bus.domain.service.LandmarkService
8 String className = classPath.substring(beginIndexOfClassName);
9 if (className.endsWith("/")) {
10 className = className.substring(0, className.length() - 1);
11 }
12 className = className.replaceAll("/", ".");
13
14 Class<?> clazz = null;
15 try {
16 clazz = Class.forName(className);
17 } catch (ClassNotFoundException e) {
18 e.printStackTrace();
19 throw new IllegalStateException(e.getMessage());
20 }
21
22 return injector.getInstance(clazz);
23 }

当然我们需要重新定义RemoteServiceServlet的主处理方法:

1 // this is the main method of RemoteServiceServlet to process request
2 @Override
3 public String processCall(String payload) throws SerializationException {
4 Object serviceHandler = getCurrentHandler(); //get instance of RemoteService
5
6 try {
7 RPCRequest rpcRequest = RPC.decodeRequest(payload, serviceHandler.getClass(), this);
8 return RPC.invokeAndEncodeResponse(serviceHandler, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest
9 .getSerializationPolicy());
10 } catch (IncompatibleRemoteServiceException ex) {
11 getServletContext().log("An IncompatibleRemoteServiceException was thrown while processing this call.", ex);
12 return RPC.encodeResponseForFailure(null, ex);
13 }
14 }

还要重新定义support方法:

1 // RemoteServiceServlet use this judge the instance
2 public boolean supports(Object handler) {
3 return handler instanceof RemoteService;
4 }

现在我们的RemoteService就成为了一个pojo如:

1 public interface LandmarkService extends RemoteService {
2 ...........
3 }
4
5 public class LandmarkServiceImpl implements LandmarkService {
6 ...........
7 }

2. Client code

gwt client这边需要用

1 ServiceHelper.registerServiceEntryPoint(instance);

获取访问URL.

why it works:
1 /**
2 * register service url
3 * @param svcObj service object
4 * com.xxxxx.bus.domain.service.LandmarkService => /gsvc/com/xxxxx/bus/domain/service/LandmarkService
5 */
6 public static void registerServiceEntryPoint(Object svcObj) {
7 ServiceDefTarget endpoint = (ServiceDefTarget) svcObj;
8 String endpointText = GWT.getTypeName(svcObj);
9 endpointText = endpointText.substring(0, endpointText.indexOf("_Proxy"));
10 endpointText = endpointText.replace('.', '/');
11 endpoint.setServiceEntryPoint("/gsvc/" + endpointText);
12 }

GWT.getTypeName can get the class name of service object

你可以使用如下代码的方式构造你的service
1 public interface LandmarkService extends RemoteService {
2 public static class Initer {
3 private static LandmarkServiceAsync instance;
4 public static LandmarkServiceAsync getInstance(){
5 if (instance == null) {
6 instance = (LandmarkServiceAsync) GWT.create(LandmarkService.class);
7 ServiceHelper.registerServiceEntryPoint(instance);
8 }
9
10 return instance;
11 }
12 }
13 ........
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值