为非实体请求实现GWT RequestFactory服务

 TzXh爱是生活 发布于 2023-02-12 19:21

我有以下Java servlet执行我称之为" 添加服务 ":

public class AdditionService extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        // The request will have 2 Integers inside its body that need to be
        // added together and returned in the response.
        Integer addend = extractAddendFromRequest(request);
        Integer augend = extractAugendFromRequest(request);

        Integer sum = addend + augend;

        PrintWriter writer = response.getWriter();
        writer.write(sum);
    }
}

我试图让GWT的RequestFactory做同样的事情(在应用服务器上添加两个数字并将总和作为响应返回)使用ValueProxyAdditionService,并且遇到了一些问题.

这是AdditionRequest(客户端层),它是一个包含两个要添加的整数的值对象:

// Please note the "tier" (client, shared, server) I have placed all of my Java classes in
// as you read through the code.
public class com.myapp.client.AdditionRequest {
    private Integer addend;
    private Integer augend;

    public AdditionRequest() {
        super();

        this.addend = 0;
        this.augend = 0;
    }

    // Getters & setters for addend/augend.
}

接下来我的代理(客户端层):

@ProxyFor(value=AdditionRequest.class)
public interface com.myapp.client.AdditionRequestProxy extends ValueProxy {
    public Integer getAddend();
    public Integer getAugend();
    public void setAddend(Integer a);
    public void setAugend(Integer a);
}

接下来我的服务API(在共享层中):

@Service(value=DefaultAdditionService.class)
public interface com.myapp.shared.AdditionService extends RequestContext {
    Request sum(AdditionRequest request);
}

接下来我的请求工厂(共享层):

public class com.myapp.shared.ServiceProvider implements RequestFactory {
    public AdditionService getAdditionService() {
        return new DefaultAdditionService();
    }

    // ... but since I'm implementing RequestFactory, there's about a dozen
    // other methods GWT is forcing me to implement: find, getEventBus, fire, etc.
    // Do I really need to implement all these?
}

最后魔术发生的地方(服务器层):

public class com.myapp.server.DefaultAdditionService implements AdditionService {
    @Override
    public Request sum(AdditionRequest request) {
        Integer sum = request.getAddend() + request.getAugend();
        return sum;
    }

    // And because AdditionService extends RequestContext there's another bunch of
    // methods GWT is forcing me to implement here: append, create, isChanged, etc.
    // Do I really need to implement all these?
}

这是我的问题:

    我的"等级"策略是否正确?我是否已将所有类型打包在正确的客户端/共享/服务器包中?

    我不认为我的设置是正确的,因为AdditionService(在共享的)引用DefaultAdditionService,它在服务器上,它不应该做.共享类型应该能够在客户端和服务器上同时存在,但不能依赖于...

    应该ServiceProvider是一个实现的类RequestFactory,还是应该是一个扩展它的接口?如果是后者,我在哪里定义ServiceProviderimpl,以及如何将它链接回所有这些其他类?

    怎么样在所有这些方法ServiceProviderDefaultAdditionService?我是否需要实施所有20多种核心GWT方法?或者我是否正确地使用API​​或者不像我使用它那样简单?

    服务定位器在哪里因素?怎么样?

我认为我很接近但需要帮助越过终点线.如果有人可以接受我的代码并调整它以显示使用RF/ValueProxies的正确方法,我认为它会将整个框架与我联系在一起...提前感谢!

1 个回答
  • 如果你想使用RF作为一个简单的RPC机制[*]你可以(而且你是对的:只有ValueProxys),但你需要更多ServiceLocator的东西:s(即GWT 2.1.1).

    有了ServiceLocator你可以简单地把你的服务实现(比如你的servlet)成为一个真正的服务实例,而不是变成一个实体对象(如用户仅ValueProxyS,没有静态getXyz()方法)所要求的RF协议.注意Locators 的存在,用于从服务器端实体外部化所有这些方法:如果你ValueProxy在任何地方使用,则不需要.

    一个ServiceLocator看起来像(取自官方文档):

    public class DefaultAdditionServiceLocator implements ServiceLocator {
      @Override
      public Object getInstance(Class<?> clazz) {
        try {
          return clazz.newInstance();
        } catch (InstantiationException e) {
          throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
          throw new RuntimeException(e);
        }
      }
    }
    

    您需要DefaultAdditionService使用定位器参数对您的注释进行注释,以便RF知道在将您的请求发送到您的服务时应该依赖什么.就像是:

    @Service(value = DefaultAdditionService.class, locator = DefaultAdditionServiceLocator.class)
    public interface com.myapp.shared.AdditionService extends RequestContext {
      // Note here, you need to use the proxy type of your AdditionRequest.
      Request<Integer> sum(AdditionRequestProxy request);
    }
    

    您的服务将是地球上最简单的事情(无需扩展/实施与RF相关的任何事情):

    public class com.myapp.server.DefaultAdditionService {
      // The server-side AdditionRequest type.
      public Integer sum(AdditionRequest request) {
        Integer sum = request.getAddend() + request.getAugend();
        return sum;
      }
    }
    

    如果你拼写错误sum()或者你没有实现在你声明的方法,RequestContext你将收到一个错误.

    为了实例RequestContext你需要进行扩展RequestFactory接口,与公共工厂方法com.myapp.shared.AdditionService.就像是:

    public interface AdditionServiceRequestFactory extends RequestFactory {
      public com.myapp.shared.AdditionService createAdditionServiceRequestContext();
    }
    

    您的所有客户来电都将从此开始.如果没有,请参阅文档.

    现在,RF通过完全分离您想要从客户端(使用EntityProxyValueProxy)和服务器(真实对象,Entity值或简单DTO类)传递的对象来工作.您将在客户端/共享层中的任何位置使用代理类型(即,实现自动生成的接口),并且@ProxyFor仅在服务器端使用相对域对象(引用的对象).RF将负责其余部分.因此,您AdditionRequest将在您的服务器端,而AdditionRequestProxy将在您的客户端(请参阅中的说明RequestContext).另请注意,如果您只使用原始/盒装类型作为RequestContext参数或返回类型,则根本不需要创建ValueProxys,因为它们是默认可传输的.

    你需要的最后一点是连接RequestFactoryServlet你的web.xml.请参阅此处的文档.请注意,如果您想要使用自定义ExceptionHandlers或ServiceLayerDecorators,您可以扩展它,但您不需要.

    谈谈在哪里放一切:

    Locators,ServiceLocators,服务实例,域对象和RequestFactoryServlet扩展,将在您的服务器端;

    RequestContext,RequestFactory扩展和所有代理的类型将是共用端;

    客户端将初始化RequestFactory扩展并使用它来获取服务请求的工厂实例.

    总而言之......用RF创建一个简单的RPC机制,只需:

    创造您的服务ServiceLocator;

    RequestContext为您的请求创建一个(使用服务和定位器值注释);

    创建一个RequestFactory扩展来返回你的RequestContext;

    如果你想在你的RequestContext(如简单的DTOs)中使用多个原始类型,只需为它们创建客户端代理接口,注释@ProxyFor,并记住每种类型的使用位置;

    一切都好.

    很像那样.好吧,我写的太多了,可能忘记了一些东西:)

    供参考,请参阅:

    官方RF文件 ;

    Thomas Broyer的文章[1],[2] ;

    从RF作者的角度来看RF与GWT-RPC.

    [*]:在这种方法中,您将逻辑从面向数据的应用程序转移到面向服务的应用程序.当涉及到操作时,你放弃使用Entitys,IDs,versions,当然还有客户端和服务器之间的所有复杂差异逻辑CRUD.

    2023-02-12 19:23 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有