2012-06-07 4 views
2

아파치에서 MyFaces 오케스트라는 CSS 파일에 대한 요청에 대한 모든 요청에 ​​추가하는, 나는 conversationContext 매개 변수를 제거 싶어 적절한 브라우저 캐싱을 제공한다. Bozho으로정적 리소스에 대한 오케스트라 converstation 컨텍스트 매개 변수를 제거하는 방법?

내가 오케스트라가 찾고있는 속성을 설정하는 필터를 구현했습니다 제안했다.

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 파일 요청)에는 요청에 이미 conversation context이 포함되어 있습니다. 내가 항상 속성 설정에 필터를 수정하면

이상한 것은,이다, 모든 요청은 conversation context 속성이 없습니다. 그러나 이는 conversation context도 jsf 사이트 요청에 포함되어 있지 않음을 의미합니다.

jsf 사이트의 생성 된 HTML에있는 CSS 파일에 대한 링크에도 conversation context 속성이 포함되어 있는지 여부는 필터 구현에 따라 다릅니다. 두 번째 요청에 이미 conversation context 매개 변수가 포함 된 이유는 무엇입니까? 오케스트라뿐 아니라 속성이 설정되지 않은 요청에 대한 모든 요청에 ​​conversation context 매개 변수를 추가 왜 이해가 안

.

어떻게 제대로 작동하려면 필터를 구현할 수있다?

답변

3

다음 요청 (예 : CSS 파일의 경우)이 페이지의 요청 후에 필터를 누르는 것은 이전 요청의 페이지에서이 리소스의 URL이 렌더링 된 방식이기 때문에 이미 conversationContext 매개 변수가 포함되어 있습니다.

그래서 conversationContext에 대한 제어는 렌더링 시간에주의해야한다. 다음 솔루션은 JSF 2 (JSF 2 (Mojarra 2.1.11, myfaces-orchestra-core20 1.5, RichFaces 4.1.0. 최종)를 사용하고 있습니다. 특별한 서블릿 필터는 아무것도하지 않고 있지만, 우리 자신의 래퍼 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); 
    } 
    ... 
} 

응답 래퍼 URL이 being a richfaces resource 인코딩하는 테스트와의 시간을 현재의 thread에 오케스트라의 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); 
    } 

} 

(I는 전달 된 URL을 앞에 추가하는 일이 컨텍스트 경로와 서블릿 경로로 자원이기 위해 URL을 테스트 할 때 String.startsWith() 대신 String.contains()를 사용 했어.)

그러나이 순간에도 도움이되지 않습니다. 그 이유는 오케스트라는 RequestParameterFacesContextFactory에서 일어나는 자신의 응답 포장을 사용한다는 것입니다,이 포장은 우리의 필터를 맞았다 후 발생합니다. 이런 식으로 오케스트라의 래퍼는 우리의 래퍼가 외부에있는 것으로 판명되어 URL이 이미 가로 채어 졌을 때 래퍼가 url을 늦게 수신하고 conversationContext을 추가하게됩니다.

이 문제를 방지하려면 RequestParameterFacesContextFactory 인터셉터의 효과를 RequestParameterServletFilter (실제로는 does the same work)으로 바꾸어서 오케스트라의 외부에 응답 래퍼를 만들 수있는 방법이 있습니다. 불행히도 다른 필터를 사용하는 것은 우리가하지 못할 수도있는 아주 정교하지는 않지만 지금까지는 다른 방법을 보지 못했습니다.

그래서, web.xml 오케스트라의 한 후 필터 장소 :

<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> 
관련 문제