具有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/*
PeopleService
和ManagementService
实现只是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.prefix
和resteasy.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 }