3

我已经按照教程进行了春季远程处理,特别是在HttpInvokerServiceExporter设置客户端和服务器(factorybean)时没有问题。

问题是,我注意到使用 Spring MVC,每个接口都映射到一个特定的 URL

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="hello.htm">test_service</prop>
            </props>
        </property>
    </bean>

    <!-- *********************exposed web services*************************--> 
    <bean name="test_service" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="serviceInterface" value="foo.webservices.HelloServiceInterface" />
        <property name="service">
            <ref bean="helloService"></ref>
        </property>

问题是,如果我的服务接口中有多个方法,是否可以将这些接口方法中的每一个映射到 URL 本身?

4

3 回答 3

4

背后的想法HTTPInvokerServiceExporter是提供一个端点来接收删除方法调用。

服务器端,很容易配置 a RemoteExporter,声明要公开的接口并将其关联到将处理调用的真实 bean。

客户端上,必须配置RemoteAcessor基本上需要在服务器端访问的接口。

通过 HTTP 的实现可以使用服务器端的HttpInvokerServiceExporter来完成,如下例所示:

服务接口:


package foo.bar.services;

public interface MyService {

    public int sum(int num1, int num2);

}

对于此服务,您将有一个实现(比方说foo.bar.services.DefaultMyService)。

spring 上下文的说明和配置如下所示:


<bean name="myService" class="foo.bar.DefaultMyService" />
<bean name="/myService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
  <property name="service" ref="myService"/>
  <property name="serviceInterface" value="foo.bar.MyService"/>
</bean>

使用此配置,我只是打算在最简单的情况下,在由(bean name)映射的 URL 上的接口MyService下公开我的实现的实例,除了将 URL 映射到具有 URL 值的 bean 之外什么都不做(本例)。foo.bar.MyService/myServiceBeanNameUrlHandlerMapping/myService

在客户端(消费者),您将配置一个 bean,仅声明您希望远程端公开的接口。对于我们的服务将是这样的:

<bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
  <property name="serviceUrl" value="http://foo.bar.org/springSample/myService"/>
  <property name="serviceInterface" value="foo.bar.MyService"/>
</bean>

在 spring 在客户端实例化 bean 的那一刻,代理被实例化,然后每个方法调用都将被序列化并通过 HTTP 发送到端点(在这种情况下http://foo.bar.org/springSample/myService)。在服务器端,这个请求被反序列化和解释,即调用方法暴露的真实服务(在我们的例子中为 DefaultMyService)。该服务将返回一些将被序列化并作为结果给客户端执行的 HTTP 请求的内容。客户端将接收它并反序列化它并将其返回给原始方法调用器.

如您所见(并从 Spring 文档中获得):

服务器端将

反序列化远程调用对象并序列化远程调用结果对象。像 RMI 一样使用 Java 序列化,但提供与 Caucho 基于 HTTP 的 Hessian 和 Burlap 协议相同的易于设置。

客户端将

序列化远程调用对象和反序列化远程调用结果对象。像 RMI 一样使用 Java 序列化,但提供与 Caucho 基于 HTTP 的 Hessian 和 Burlap 协议相同的易于设置。

在这种情况下,与 Spring Remoting 一起使用的序列化是 Java 序列化,这意味着 HTTP 请求包含一个包含序列化对象的实体主体(请记住,在这种情况下,JVM 版本和类版本需要兼容)。

展示是作为一个整体完成的,您无法将它分开URL,为该接口的每个方法都提供一个。因此,使用 Spring MVC 并创建一个控制器(@Controller)会更容易为您在接口上将其注释为@RequestMapping(使用所需 URL)的每个方法实现一个方法,并按如下示例调用服务上的方法:

控制器示例


package foo.bar;

import foo.bar.service.MyService;

@Controller
public class MyService {
    @Autowired
    private MyService myService;

    @RequestMapping("/sum/{num1}/{num2}")
    public int sum(@PathVariable("num1") int num1, @PathVariable("num2") int num2) {
        return myService.sum(num1, num2);
    }

}

使用上下文配置

<context:component-scan base-package="foo.bar"/>

它会自动映射在foo.bar 和包下找到的类,这意味着实现ServiceDefaultMyService@Service@Autowired

但这将通过 REST 接口公开您的服务,这意味着它将处理可以由其他消费者(如 PHP 消费者)完成的 HTTP 普通请求(这不能用 Spring Remoting 完成,因为它使用纯 Java 序列化)。

如果您的客户端是 Java,您可以明确地使用 Remoting 并将您的服务作为一个整体公开,如果不是,使用 Spring MVC 的 REST 实现是一个很好的解决方案。

弹簧文档可以在这里找到

于 2012-06-23T18:16:49.057 回答
1

我真的建议使用 @Controller 注释定义你的控制器。在Spring 文档中,首先将组件扫描添加到 Spring 配置中。

<context:component-scan base-package="your.package.path"/>

然后,在一个类中,比如 your.package.path.WhateverController,注释该类:

@Controller
WhateverController

并使用 @RequestMapping 注释您的方法:

@RequestMapping(value = "/helloWorld")
public ModelAndView helloWorld() {
...
}

@RequestMapping(value = "/project/{projectId}")
public ModelAndView helloWorld(@PathVariable String projectId) {
...
}

就是这样,每个控制器有多个映射。

于 2012-06-21T06:52:24.033 回答
1

我认为您需要先告诉我们您要做什么。如果您将服务暴露给通用 Web 客户端,REST 或 SOAP 将是更好的选择;如果您将服务暴露给另一个应用程序中的另一个 Spring bean,那么 Spring Remoting 可能就足够了。

您的 spring 配置文件中的“exposed web services”注释似乎不清楚您的目的。

当你向远程客户端公开一个服务时,你总是需要提供一个契约让远程客户端知道什么是可能的。REST 使用 URL 公开该合约;SOAP 使用 WSDL 公开该契约;而 Spring Remoting 只是直接为客户端提供了 java 接口中的契约,因此客户端可以将该接口注入到自己的 bean 中,并像本地定义的 bean 一样使用它。

在您提到将方法映射到 URL 的问题中,Spring Remoting 不能这样做,因为它暴露了接口;你想做的事情对我来说听起来很 REST。我同意@stevebrown,使用映射控制器公开您的服务是一种好方法。

于 2012-06-22T15:53:06.537 回答