如何删除静态资源的Orchestra converstation上下文参数? [英] How to remove Orchestra converstation context parameter for static resources?
问题描述
为了提供适当的浏览器缓存,我想摆脱conversationContext
参数,Apache MyFaces Orchestra将它添加到每个对CSS文件的请求中的请求.
按照 Bozho 的建议,我已经实现了一个过滤器,该过滤器设置了Orchestra正在寻找的属性.
public class ResourceFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse theResponse, FilterChain theChain) throws IOException, ServletException {
if(shouldNotAppendConversation(request)) {
request.setAttribute(RequestParameterServletFilter.REQUEST_PARAM_FILTER_CALLED, Boolean.TRUE);
}
theChain.doFilter(request, theResponse);
}
private boolean shouldNotAppendConversation(ServletRequest theRequest) {
HttpServletRequest aRequest = (HttpServletRequest) theRequest;
String aPath = aRequest.getRequestURI();
if(aPath.endsWith(".css.jsf")) {
return true;
}
return false;
}
@Override
public void init(FilterConfig theFilterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
那不起作用,该参数仍附加到每个请求中.调试时,我发现该过滤器首先被发送到jsf站点的请求.当然,我想在该请求中包含conversation context
,因此过滤器将请求直接转发到链中的下一个过滤器.命中过滤器的下一个请求(通常是对CSS文件的请求)已经包含在请求中.
public class RfOrchestraParamControlFilter implements Filter {
...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
response = new RfOrchestraParamControlResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, response);
}
...
}
.
奇怪的是,如果我将过滤器修改为始终设置属性 ,则所有请求都将不具有conversation context
属性.但这意味着conversation context
也不包含在jsf网站的请求中(但应该).
我注意到,在jsf站点的生成的html中,指向css文件的链接也包含conversation context
属性,取决于过滤器的实现.我想因为这个原因,第二个请求已经包含了conversation context
参数?
我不明白为什么Orchestra会将conversation context
参数附加到每个请求,而不仅仅是未设置属性的请求.
如何实现过滤器才能正常工作?
下一个请求(例如,对于CSS文件)在您对页面的请求中已经包含了conversationContext
参数后,仅在过滤器中出现,这是因为该资源的url已由上一个请求中的页面呈现.
因此,对conversationContext
的控制应在渲染时进行.以下解决方案适用于JSF 2(我正在使用Mojarra 2.1.11,myfaces-orchestra-core20 1.5,RichFaces 4.1.0.Final).特殊的servlet过滤器除了将HttpServletResponse
用我们自己的包装器包装之外,什么也不做:
public class RfOrchestraParamControlFilter implements Filter {
...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
response = new RfOrchestraParamControlResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, response);
}
...
}
响应包装器测试要被编码为成为Richfaces资源的网址并转换乐团的在编码时,ConversationRequestParameterProvider
的分离模式在当前线程中处于打开状态:
package ...
import javax.faces.application.ResourceHandler;
import org.richfaces.resource.ResourceHandlerImpl;
import org.apache.myfaces.orchestra.conversation.ConversationRequestParameterProvider;
public class RfOrchestraParamControlResponseWrapper extends HttpServletResponseWrapper {
public RfOrchestraParamControlResponseWrapper(HttpServletResponse httpServletResponse) {
super(httpServletResponse);
}
@Override
public String encodeURL(String url) {
if (url.contains(ResourceHandler.RESOURCE_IDENTIFIER) || url.contains(ResourceHandlerImpl.RICHFACES_RESOURCE_IDENTIFIER)) {
boolean current = ConversationRequestParameterProvider.isInSeparationMode();
/* Disable conversationContext parameter in current thread for the time of rendering link to a resource */
ConversationRequestParameterProvider.setInSeparationMode(true);
String result = super.encodeURL(url);
/* Restore */
ConversationRequestParameterProvider.setInSeparationMode(current);
return result;
}
else return super.encodeURL(url);
}
}
(当测试URL作为资源时,我不得不使用String.contains()
而不是String.startsWith()
,因为上下文路径和servlet路径恰好在传递的URL之前.)
但是,此刻也无济于事.原因是管弦乐队使用了它自己的响应包装,该包装在其RequestParameterFacesContextFactory
中发生,并且这种包装发生在我们的过滤器被点击后 .这样,Orchestra的包装器就位于我们的包装器的外部,这导致我们的包装器收到url
时为时已晚,这是因为该URL已被拦截并附加了conversationContext
.
为避免这种情况,我们可以通过将RequestParameterFacesContextFactory
拦截器的效果替换为RequestParameterServletFilter
实际上是Bozho suggested, I've implemented a filter that sets the attribute Orchestra is looking for.
public class ResourceFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse theResponse, FilterChain theChain) throws IOException, ServletException {
if(shouldNotAppendConversation(request)) {
request.setAttribute(RequestParameterServletFilter.REQUEST_PARAM_FILTER_CALLED, Boolean.TRUE);
}
theChain.doFilter(request, theResponse);
}
private boolean shouldNotAppendConversation(ServletRequest theRequest) {
HttpServletRequest aRequest = (HttpServletRequest) theRequest;
String aPath = aRequest.getRequestURI();
if(aPath.endsWith(".css.jsf")) {
return true;
}
return false;
}
@Override
public void init(FilterConfig theFilterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
That doesn't work the parameter is still appended to every request. While debugging, I've found out that the filter gets first hit by a request to the jsf site. For sure I want to include the conversation context
in that request, so the filter forwards the request directly to the next filter in the chain. The next request that hits the filter (usually the request for a css file) has already the conversation context
included in the request.
The strange thing is, if I modify the filter to always set the attribute, all request will not have the conversation context
attribute. But that means, the conversation context
is also not included in the request for the jsf site (but should).
I've noticed that the links to css files in the generated html of the jsf site also contains the conversation context
attribute or not depending on the filter implementation. I guess for this reason the second request has already included the conversation context
parameter?
I don't understand why Orchestra is appending the conversation context
parameter to every request and not just for the requests where the attribute is not set.
How can I implement the filter to work correctly?
The next request (e.g. for a CSS file) hitting your filter after the request to your page has already the conversationContext
parameter included just because this is how the url for this resource has been rendered by the page in the previous request.
So the control over conversationContext
should be taken at render time. The following solution is working for me with JSF 2 (I am using Mojarra 2.1.11, myfaces-orchestra-core20 1.5, RichFaces 4.1.0.Final). A special servlet filter is doing nothing but wraps HttpServletResponse
with our own wrapper:
public class RfOrchestraParamControlFilter implements Filter {
...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
response = new RfOrchestraParamControlResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, response);
}
...
}
The response wrapper tests the url to be encoded for being a richfaces resource and turns Orchestra's ConversationRequestParameterProvider
's separation mode on in the current thread for the time of encoding:
package ...
import javax.faces.application.ResourceHandler;
import org.richfaces.resource.ResourceHandlerImpl;
import org.apache.myfaces.orchestra.conversation.ConversationRequestParameterProvider;
public class RfOrchestraParamControlResponseWrapper extends HttpServletResponseWrapper {
public RfOrchestraParamControlResponseWrapper(HttpServletResponse httpServletResponse) {
super(httpServletResponse);
}
@Override
public String encodeURL(String url) {
if (url.contains(ResourceHandler.RESOURCE_IDENTIFIER) || url.contains(ResourceHandlerImpl.RICHFACES_RESOURCE_IDENTIFIER)) {
boolean current = ConversationRequestParameterProvider.isInSeparationMode();
/* Disable conversationContext parameter in current thread for the time of rendering link to a resource */
ConversationRequestParameterProvider.setInSeparationMode(true);
String result = super.encodeURL(url);
/* Restore */
ConversationRequestParameterProvider.setInSeparationMode(current);
return result;
}
else return super.encodeURL(url);
}
}
(I've had to use String.contains()
instead of String.startsWith()
when testing the url for being a resource as context path and servlet path happen to prepend the passed url.)
However that does not help either by this moment. The reason is that Orchestra uses its own response wrapping that takes place in its RequestParameterFacesContextFactory
, and this wrapping happens after our filter is hit. In this way Orchestra's wrapper turns out to be external to our one which results in our wrapper receiving url
too late, when the url has already been intercepted and conversationContext
appended.
To avoid this we have a way to make our response wrapper external to Orchestra's one by replacing effect from RequestParameterFacesContextFactory
interceptor with RequestParameterServletFilter
which actually does the same work. Unfortunately using another filter is not quite exquisite where we might not, but I don't see another way so far.
So, in web.xml
place your filter after Orchestra's one:
<filter>
<filter-name>requestParameterFilter</filter-name>
<filter-class>org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterServletFilter</filter-class>
</filter>
<filter>
<filter-name>myOrchestraFilter</filter-name>
<filter-class>mypkg.RfOrchestraParamControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestParameterFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>myOrchestraFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
这篇关于如何删除静态资源的Orchestra converstation上下文参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!