3

特に春のリモーティングのチュートリアルに従いましたがHttpInvokerServiceExporter、クライアントとサーバー(ファクトリービーン)の両方のセットアップに問題はありません。

質問は、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は、removeメソッドの呼び出しを受け取るエンドポイントを提供することです。

サーバー側では、を構成し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名)によってマップされた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>

春にクライアント側でBeanをインスタンス化すると、プロキシがインスタンス化され、すべてのメソッド呼び出しがシリアル化され、HTTP経由でエンドポイントに送信されます(この場合http://foo.bar.org/springSample/myService。サーバー側では、このリクエストは逆シリアル化されて解釈されます。つまり、メソッドを呼び出します。公開されている実際のサービス(この場合はDefaultMyService)。サービスは、クライアントによって実行されたHTTPリクエストの結果としてシリアル化されるものを返します。クライアントはそれを受信して​​逆シリアル化し、元のメソッド呼び出し元に返します。 。

ご覧のとおり(そしてSpringのドキュメントから入手):

サーバー側は

リモート呼び出しオブジェクトを逆シリアル化し、リモート呼び出し結果オブジェクトをシリアル化します。RMIと同じようにJavaシリアル化を使用しますが、CauchoのHTTPベースのHessianおよびBurlapプロトコルと同じように簡単にセットアップできます。

クライアント側は

リモート呼び出しオブジェクトをシリアル化し、リモート呼び出し結果オブジェクトを逆シリアル化します。RMIと同じようにJavaシリアル化を使用しますが、CauchoのHTTPベースのHessianおよびBurlapプロトコルと同じように簡単にセットアップできます。

この場合にSpringRemotingで使用されるシリアル化はJavaシリアル化です。つまり、HTTPリクエストはシリアル化されたオブジェクトを含むエンティティ本体を保持します(この場合、JVMバージョンとクラスバージョンは互換性がある必要があることに注意してください)。

URL解説は全体として行われ、そのインターフェースのメソッドごとに1つずつ持って分離することはできませんでした。したがって、Spring MVCの使用が簡単になり、コントローラーを作成して(@Controller)インターフェース上にあるメソッドごとにメソッドを実装し、@RequestMapping次の例のようにサービスでメソッドを呼び出します。

コントローラサンプル


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とパッケージの下にあるクラスを自動的にマップします。つまり、コンテキストxmlでBeanを構成しなくても、サンプルで行われたように、Service実装( )をコントローラーDefaultMyServiceにマップできます。@Service@Autowired

ただし、これによりサービスがRESTインターフェースを介して公開されます。つまり、PHPコンシューマーなどの他のコンシューマーによって実行される可能性のあるHTTPプレーンリクエストを処理します(純粋なJavaシリアル化を使用するためSpring Remotingでは実行できませんでした)。

クライアントがJavaの場合は、間違いなくRemotingを使用してサービス全体を公開できますが、そうでない場合は、SpringMVCを使用したREST実装が適切なソリューションです。

Springのドキュメントはここにあります

于 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の方が適しています。別のアプリケーションでサービスを別のSpringBeanに公開している場合は、SpringRemotingで十分な場合があります。

Spring構成ファイルの「公開されたWebサービス」というコメントは、目的が明確でないようです。

リモートクライアントにサービスを公開するときは、リモートクライアントに何が可能かを知らせるための契約を常に提供する必要があります。RESTは、URLを使用してそのコントラクトを公開します。SOAPは、WSDLを使用してそのコントラクトを公開します。また、Spring Remotingは、Javaインターフェースでコントラクトするクライアントを直接提供するため、クライアントはそのインターフェースを独自のBeanに挿入し、ローカルで定義されたBeanのように使用できます。

あなたの質問で、メソッドをURLにマッピングするとおっしゃいましたが、Spring Remotingはインターフェースを公開するため、それを行うことはできません。あなたがやりたいことは私にはとてもRESTに聞こえます。そして、@ stevebrownに同意します。マップされたコントローラーを使用してサービスを公開することは、良いアプローチです。

于 2012-06-22T15:53:06.537 に答える