具有Resteasy的多个端点

我在一个应用程序中有两个单独的REST服务。 让我们说一个主要的“人”服务和一个辅助“管理”服务。 我想要的是在服务器上的不同路径中公开它们。 我正在使用JAX-RS,RESTEasy和Spring。

例:

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

web.xml目前有以下设置:

  org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap   org.jboss.resteasy.plugins.spring.SpringContextLoaderListener   resteasy.servlet.mapping.prefix /public   Resteasy  org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher    Resteasy /public/*  

PeopleServiceManagementService实现只是Spring bean。 上面的web.xml配置会在/public上公开它们(所以分别使用/public/people/public/management )。

我想要实现的是在/public/public PeopleService ,以便完整路径将成为/public/people并在/internal上公开ManagementService ,以便其完整路径将成为/internal/management

不幸的是,我无法更改@Path注释的值。

我该怎么做?

实际上你可以。 经过几个小时的调试后,我想到了这个:

1)在web.xml声明多个resteasy servlet(在我的例子中为两个)

  resteasy-servlet org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher  resteasy.servlet.mapping.prefix /openrest   resteasy.resources com.mycompany.rest.PublicService    private-resteasy-servlet org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher  resteasy.servlet.mapping.prefix /protectedrest   resteasy.resources com.mycompany.rest.PrivateService    private-resteasy-servlet /protectedrest/*   resteasy-servlet /openrest/*  

请注意我们为每个servlet初始化个人resteasy.servlet.mapping.prefixresteasy.resources 。 请不要忘记包含任何botstrap类作为filter或servlet! 并禁用自动扫描。

2)创建一个filter,清除RESTeasy在上下文中保存的全局信息中的应用程序:

 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 } } 

注册它以获取对您服务的任何请求(此处我将其用于所有简化请求):

  CleanupFilter com.mycompany.ResteasyCleanupFilter   CleanupFilter /*  

这就是它!现在你有两种不同的REST服务,它们位于不同的前缀下: /openrest意味着服务所有公共请求, /protectedrest负责处理应用程序中的所有私有内容。

那么它为什么会起作用(或者为什么它不起作用)呢?

当你第一次调用openrest实例时,它会尝试openrest ,并在完成时将状态保存在全局servletContext如下所示:

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

如果你愿意接听你的第二个/protectedrest保护者,你将获得相同的配置! 这就是为什么你需要在某些地方清理这些信息。 这就是为什么我们使用CleanupFilter上下文的CleanupFilter ,因此全新的rest servlet可以使用我们声明的所有init参数初始化自己。

这是一个黑客攻击,但它可以解决问题。

该解决方案针对RESTEasy 2.3.6进行了测试

EDITED

兼容3.0.9.final!

AFAIK,您的JAX-RS实现不能有多个servlet mappins。 您可以做的是:将RESTEasy映射到'/' (或'/api' ,例如,如果您的应用程序有其他资源要服务,并且您不希望JAX-RS部分干扰),那么请使用以下@Path注释:

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