论坛首页 入门技术论坛

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

浏览 3208 次
该帖已经被评为新手帖
作者 正文
   发表时间:2007-12-19   最后修改:2010-02-21
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 ........
   发表时间:2008-07-15  
楼主能谈谈具体的优势在哪个地方啊
0 请登录后投票
论坛首页 入门技术版

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