2013-12-19 13 views
10

私は1つのアプリケーションに2つの独立したRESTサービスを用意しています。メインの "人"サービスと二次の "管理"サービスを考えてみましょう。私が望むのは、サーバー上の別々のパスにそれらを公開することです。 JAX-RS、RESTEasy、Springを使用しています。Resteasyを使用した複数のエンドポイント

例:

@Path("/people") 
public interface PeopleService { 
    // Stuff 
} 

@Path("/management") 
public interface ManagementService { 
    // Stuff 
} 

現在I web.xmlで持って、次のセットアップ:

<listener> 
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
</listener> 

<listener> 
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
</listener> 

<context-param> 
    <param-name>resteasy.servlet.mapping.prefix</param-name> 
    <param-value>/public</param-value> 
</context-param> 

<servlet> 
    <servlet-name>Resteasy</servlet-name> 
    <servlet-class> 
     org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher 
    </servlet-class> 
</servlet> 

<servlet-mapping> 
    <servlet-name>Resteasy</servlet-name> 
    <url-pattern>/public/*</url-pattern> 
</servlet-mapping> 

PeopleServiceManagementService実装はちょうど春の豆です。 上にweb.xmlを設定すると、/public(両方とも/public/people/public/management)の両方に公開されます。私が達成したい何

はフルパスが/public/peopleとなり、そのフルパスが/internal/managementになるよう、/internalManagementServiceを公開なるように、/publicPeopleServiceを公開することです。

残念ながら、@Pathアノテーションの値を変更することはできません。

どうすればよいですか?

+0

なぜパス注釈を変更できないのですか?あなたはコードにアクセスできない?限り、私は彼らがインターフェイスであることがわかります、あなたは実装にアクセスできますか? –

答えて

2

AFAIKでは、JAX-RSの実装に複数のサーブレット・マッパーを使用することはできません。 何をあなたができることは次のとおりです。

@Path("/public/people") 
public interface PeopleService { 
    // Stuff 
} 

@Path("/internal/management") 
public interface ManagementService { 
    // Stuff 
} 
:次 @Path注釈を持って、 '/'にマップのRESTEasy(例えばまたは '/api'アプリケーションが他のリソースを持っている場合は、提供するために、あなたはJAX-RSの部分が干渉したくありません)実際にできるのは
14

です。私たちは、個人resteasy.servlet.mapping.prefixresteasy.resourcesを初期化していることに注意してください私の場合は自分のweb.xml(2)

<servlet> 
    <servlet-name>resteasy-servlet</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    <init-param> 
     <param-name>resteasy.servlet.mapping.prefix</param-name> 
     <param-value>/openrest</param-value> 
    </init-param>  
    <init-param> 
     <param-name>resteasy.resources</param-name> 
     <param-value>com.mycompany.rest.PublicService</param-value> 
    </init-param> 
</servlet> 

    <servlet> 
    <servlet-name>private-resteasy-servlet</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    <init-param> 
     <param-name>resteasy.servlet.mapping.prefix</param-name> 
     <param-value>/protectedrest</param-value> 
    </init-param>  
    <init-param> 
     <param-name>resteasy.resources</param-name> 
     <param-value>com.mycompany.rest.PrivateService</param-value> 
    </init-param> 
</servlet> 
<servlet-mapping> 
    <servlet-name>private-resteasy-servlet</servlet-name> 
    <url-pattern>/protectedrest/*</url-pattern> 
</servlet-mapping>  

<servlet-mapping> 
    <servlet-name>resteasy-servlet</servlet-name> 
    <url-pattern>/openrest/*</url-pattern> 
</servlet-mapping> 

で複数のRESTEasyのサーブレットを宣言します)

1:デバッグの数時間後、私はこの思い付きました私たちのサーブレットごとに。 を忘れないでください。には、フィルタまたはサーブレットとしてのボットストラップクラスが含まれています。オートスキャンも無効にします。 )

public class ResteasyCleanupFilter implements Filter { 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 
      ServletException { 
     request.getServletContext().setAttribute(ResteasyProviderFactory.class.getName(), null); 
     request.getServletContext().setAttribute(Dispatcher.class.getName(), null); 
     chain.doFilter(request, response); 


    } 

    @Override 
    public void destroy() { 
     // TODO Auto-generated method stub 

    } 

} 

は、ここで私はsimplisityに対するすべての要求のためにそれを使用し(あなたのサービスへの要求のためにそれを登録します。

2)それはコンテキストに保存していることのRESTEasyのグローバルな情報からアプリケーションをクリーンアップフィルタを作成します。 :!/openrest Aですべてのプライベートなものについて世話をするすべての公開要求と/protectedrestにサービスを提供するためのもの:

これだけ
<filter> 
    <filter-name>CleanupFilter</filter-name> 
    <filter-class>com.mycompany.ResteasyCleanupFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>CleanupFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

今、あなたは異なるプレフィックスの下に産む二つの異なるRESTサービスを持っていますpp。

なぜそれが機能するのですか(またはそれが別の方法で動作しないのはなぜですか)?

あなたはそれが自分自身をinitalizeしようと行われたときに、このようにグローバルservletContextに状態を保存し、初めてopenrestインスタンスを呼び出します。

servletContext.setAttribute(ResteasyProviderFactory.class.getName(), deployment.getProviderFactory()); 
servletContext.setAttribute(Dispatcher.class.getName(), deployment.getDispatcher()); 

そして、あなたはそれがあなたの第二の通話もできるようになる場合/protectedrestは同じ設定になります!だからこそ、この情報をきれいにする必要があるのです。そのため、コンテキストを空にしたCleanupFilterを使用して、新しいrestサーブレットが、宣言したすべてのinitパラメータで初期化できるようにしました。

これはハックですが、それはトリックです。

このソリューションはRESTEasyの2.3.6

について試験したとしても3.0.9.finalで

作品を編集しました!

+0

Anton、これを理解する時間をとってくれてありがとう!本当に私を助けました! JBossのissueトラッカーで[バグリクエスト](https://issues.jboss.org/browse/RESTEASY-1312)を公開しました。少なくともテストするには – jpaugh

+1

(プラス1)。質問に答えてくれるほとんどの人には私が言うことができます:-) –

+0

本当に良い説明。あなたの投稿に対する私の貢献は: 'request.getServletContext()'メソッドはServlet 3.0をサポートするコンテナでのみ動作します。 – Dherik

関連する問題