0

私はトップダウンアプローチを使用してWebサービスに取り組んでおり、JAX-WSのwsimportを使用してWSDLからサービスタイプとインターフェイスを生成しています。これにより、次のようなポートタイプのインターフェイスが提供されます。これを実装します。

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2.4-b01
 * Generated source version: 2.2
 */
@WebService(name = "ExamplePortType", targetNamespace = "http://example.com")
public interface ExamplePortType {

    /**
     * @param example
     * @return java.lang.String
     * @throws ExampleException
     */
    @WebMethod
    @WebResult(name = "exampleResponse", targetNamespace = "http://example.com")
    @RequestWrapper(localName = "sendExample", targetNamespace = "http://example.com", className = "com.example.SendExample")
    @ResponseWrapper(localName = "sendExampleResponse", targetNamespace = "http://example.com", className = "com.example.SendExampleResponse")
    public String sendExample(
        @WebParam(name = "example", targetNamespace = "http://example.com")
        ExampleRequest example)
        throws ExampleException
    ;
}

このサービスをアプリケーションサーバー(私の場合はTomcat)に追加する通常の方法は、実装クラスをサーブレットとしてweb.xmlに追加し、リスナーとしてWSServletContextListenerを追加することです。非常に大まかに言えば、コンテキストの初期化時に、リスナーは実装BeanをラップするServletAdaptersを構築し、それらをシンWSServletによって呼び出されるWSServletDelegateに追加するようです。実装へのリクエストはWSServletによって処理され、設定したURLパターンに基づいてデリゲートによってBeanに渡されます。

上記をプログラムで行う方法はありますか?上記のインターフェースのインスタンスを受け入れ、サーブレットのインスタンスを返すメソッドが必要です。サーブレットコンテキストに登録されている場合は、適切なリクエストをラップされた実装にルーティングします。何かのようなもの:

Servlet exampleServlet = new ServletAdapter().wrap(new ExamplePortTypeImpl());

1つの要件は、静的構成ファイル(web.xmlやsun-jaxws.xmlなど)に依存できないことです。JAX-WSまたは関連ライブラリ(つまり、Axis2など)はこの種の機能を提供しますか?

何かが明確でない場合はお詫びします。ここは初めてです:)。どんなポインタでも大歓迎です。

現在、JAX-WS 2.1、Tomcat 7、サーブレット3.0を使用しています。

4

2 に答える 2

2

Anthopの答えに基づいて、これは私が思いついたコードであり、私にとってはうまくいきます。

// Main code:

final ServletContextHandler soapContextHandler = createSoapServletContextHandler();

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { soapContextHandler });

server = createServer(port);
server.setHandler(handlers);
server.start();
// Function:
    private ServletContextHandler createSoapServletContextHandler()
    {
        final ServletContextHandler soapContextHandler =
                new ServletContextHandler(ServletContextHandler.SESSIONS);

        WSEndpoint<SoapServiceImpl> endpoint =
                WSEndpoint.create(SoapServiceImpl.class, false, null, null, null, null,
                        BindingImpl.getDefaultBinding(), null, null, null, false);

        ServletAdapter servletAdapter = new ServletAdapterList().createAdapter("soap", "/soap", endpoint);

        SoapServlet soapServlet = new SoapServlet(
                new WSServletDelegate(Collections.singletonList(servletAdapter), new EmptyServletContext()));

        soapContextHandler.addServlet(new ServletHolder(soapServlet), "/soap");
        return soapContextHandler;
    }
// Servlet:
    private static class SoapServlet extends HttpServlet
    {
        private final WSServletDelegate delegate;

        SoapServlet(WSServletDelegate delegate)
        {
            this.delegate = delegate;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            delegate.doGet(req, resp, getServletContext());
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            delegate.doPost(req, resp, getServletContext());
        }
    }

SoapServiceImpl石鹸サービスの実装はどこにありますか。これはEmptyServletContext完全に空の実装でありServletContext、すべてのメソッドに対してnullまたはデフォルトを返します。

/soapこれは、Jettyを使用するパスでsoapリクエストを処理する必要があります。リストに他のコンテキストハンドラーを追加することができ、それらはsoapハンドラーと一緒に機能します。私はJerseyコンテキストハンドラーと一緒にテストしたので、私のサービスはJettyと同じポートでRESTリクエストとSOAPリクエストの両方を処理します。

于 2021-01-14T16:10:39.160 に答える
1

さて、たくさんの実験の後、私はうまくいくものをまとめることができました。ドキュメントのためにここに投稿します。

基本的に、私はJAX-WSがWSServletContextListenerからWSServletを作成する方法をエミュレートまたは再実装することでこれに到達しました。残念ながら、私はこれを行うためのより簡単またはより良いサポートと簡単な方法を見つけることができませんでした。

基本的に、私のファクトリはWSEndpoint.create()メソッドを使用してWSEndpointを作成します。create()は、ラップしようとしているWebService実装のクラスを入力として受け取ります。WSEndpointがデフォルトを使用するか、実装クラスのアノテーションからいくつかの構成をプルしようとするように促すために、他のほとんどの入力はnullです。

次に、新しいServletAdapterList()を使用して、以前に作成したWSEndpointを使用してServletAdapterを作成します。このため、実装クラスごとに1つのサーブレットを作成しているため、アダプターの名前は重要ではなく、URLに関係なくすべてのトラフィックを実装に送信するように構成できます。

次に、以前のServletAdapterのシングルトンリストを使用して、単一の新しいWSServletDelegate()を作成します。ここでの唯一のトリックは、JAX-WSには、少なくともこのステップと次のステップでは、ServletContextのinitパラメーターにいくつかの値を格納するという悪い習慣があるように見えることです。また、パラメータがコンテキストにない場合に使用するデフォルトがありますが、nullチェックは適切に行われません。そのため、WSServletDelegateコンストラクターに渡すServletContextのダミー実装を作成して、initパラメーターを検索しているように感じさせることもできました。

最後に、WSServletと同様にWSServletDelegateにリクエストを転送するHttpServletの実装を作成しました。WSServletは再びデリゲートオブジェクトをServletContextinitparamsに格納するので、既存のWSServletをいじくり回すよりも、その機能を再実装する方が簡単であることがわかりました。このHttpServletの実装は、SOAPWebサービス呼び出しを受け入れて処理する通常のサーブレットと同じように扱うことができます。

于 2012-08-30T01:06:06.150 に答える