Ответ 1
на самом деле вы можете. После нескольких часов отладки я придумал следующее:
1) Объявите несколько сервлетов resteasy в вашем web.xml
(два в моем случае)
<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.servlet.mapping.prefix
и resteasy.resources
для каждого нашего сервлета.
Не забывайте, что НЕ включает любые классы ботстрапа в качестве фильтров или сервлетов! Также отключите автозапуск.
2) Создайте фильтр, который очищает приложение от глобальной информации 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
}
}
Зарегистрируйте его для любого запроса к вашим услугам (здесь я использовал его для всех запросов для упрощения):
<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, которые лежат в разных префиксах: /openrest
, которые предназначены для обслуживания всех публичных запросов и /protectedrest
, которые заботятся обо всех личных вещах в приложении.
Так почему это работает (или почему это не работает иначе)?
Когда вы вызываете экземпляр openrest
в первый раз, он пытается инициализировать себя и, когда это делается, сохраняет состояние в глобальном servletContext
следующим образом:
servletContext.setAttribute(ResteasyProviderFactory.class.getName(), deployment.getProviderFactory());
servletContext.setAttribute(Dispatcher.class.getName(), deployment.getDispatcher());
И если вы позвоните, ваш звонок к вашему второму /protectedrest
получит САМУЮ конфигурацию! Вот почему вам нужно очистить эту информацию где угодно. Вот почему мы использовали наш CleanupFilter
, который опустошил контекст, поэтому новый сервлет отдыха может инициализировать себя всеми объявленными параметрами init.
Это взломать, но он делает трюк.
Это решение было протестировано для RESTEasy 2.3.6
EDITED
Работает с версией 3.0.9.final!