2011-11-09 3 views
12

어떤 문제가입니다 : 브라우저에서 뒤로 버튼을 클릭하면 어떻게됩니까 -> 그에서있는 명령에서 요청을 제출 ->이 viewscoped-ManagedBean은 이미 파괴 된 페이지를 엽니 다 그리드 레코드 선택 페이지?브라우저 + viewscope 콩

내가 기대 : 연관된 viewscope-managebean 다시 만들어집니다 를, 그리드 기록 선택을 수신하고 다시 브라우저 버튼이 포함되지 않습니다 것처럼 그들과 거래.

내가 경험 한 것 : 연관된 viewscope-managebean은 다시 생성되지 않으며 그리드 레코드 선택을받지 못합니다. URL을 다시 입력하거나 F5 키를 다시 눌러 브라우저가 제대로 작동하게하십시오.

그래서 여기가 성공 시나리오의 모든 콩 viewscoped하는 콩 :

  1. GET의 page1.xhtml -> page1Bean 생성, 쿼리 데이터는 @PostConstruct에
  2. 체크 /에서 여러 레코드를 선택 등 데이터 테이블, 처리 버튼 클릭
  3. page1Bean의 프로세스 메소드는 선택한 레코드를 플래시 객체에 저장하고 page2.xhtml
  4. 페이지 1로 리디렉션하고 page2Bean을 삭제하고 preRenderView로 리디렉션합니다. 리스너 방법은 플래시 객체에서 선택한 레코드를 가져, 그리고 그들과 거래를
  5. 클릭 "메인 페이지로 이동"명령 단추가 page1.xhtml로 리디렉션 및 page2Bean이 page1Bean없이 2에서 다시
  6. 루프 생성, 파괴 - > page1Bean 생성 -

    1. 이 page1.xhtml GET : 5이가 다시 브라우저 버튼을 (다른 식료품 일어나고 # 6부터 시작) 관련된 errornous 시나리오입니다, 지금은 여전히 ​​

  7. 행할 dat 질의 A, 등 @PostConstruct에
  8. 검사/데이터 테이블에서 여러 레코드를 선택
  9. page1Bean의 처리 방법은 플래시 객체에서 선택한 레코드, 그리고
  10. page1Bean가 파괴 page2.xhtml로 리디렉션 저장 프로세스 버튼을 클릭, 생성 page2Bean 및 preRenderView 리스너 방법, 플래시 객체에서 선택한 레코드를 가져, 그리고 그들과 거래를하는 것은
  11. /뒤로 버튼 page2Bean이 page1Bean이
  12. 수표를 작성되지 파괴되지 않는 브라우저를 클릭에서 여러 레코드를 선택 데이터 테이블, 프로세스 버튼 클릭
  13. page1Bean 메서드가 실행됩니다 (즉, page1Bean이 파괴 되었기 때문에 이상합니다). 그러나 레코드 선택을 볼 수없고 page2로 리디렉션 할 수 없습니다.XHTML
  14. page1Bean는 page2Bean이 (가 파괴되지 이후)가 생성되지 않는다 (NO 로깅 출력) 파기 평소대로 preRenderView 리스너를 실행하고, 이번에는 더 플래시 오브젝트의 레코드를 선택하지 않은

브라우저 백 버튼이있는 viewscope-beans에서 정상적인 경험을 할 수 있습니까 (예 : 브라우저 백 버튼이없는 것처럼)?

<dependency> 
    <groupId>org.glassfish</groupId> 
    <artifactId>javax.faces</artifactId> 
    <version>2.1.3</version> 
    <scope>compile</scope> 
</dependency> 

이 당신의 아이디어를 공유하십시오 :

여기 내 의존성입니다!

답변

15

브라우저가 JSF 상태 저장 방법을 server (기본값)으로 설정 한 상태에서 전체 HTTP GET 요청을 서버로 보내는 대신 캐시에서 해당 페이지를 제공 한 것으로 보입니다.

  1. 동적 JSF 페이지를 캐시하지 않도록 브라우저를주기 :

    는이 문제를 해결하는 두 가지 방법이 있습니다. filter의 도움으로이 작업을 수행 할 수 있습니다.

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
        HttpServletRequest req = (HttpServletRequest) request; 
        HttpServletResponse res = (HttpServletResponse) response; 
    
        if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc) 
         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. 
         res.setHeader("Pragma", "no-cache"); // HTTP 1.0. 
         res.setDateHeader("Expires", 0); // Proxies. 
        } 
    
        chain.doFilter(request, response); 
    } 
    

    필터를 FacesServlet 또는 동일한 URL 패턴으로 매핑하십시오.

  2. 전체보기 상태가 서버 측 세션이 아닌 양식의 숨김 필드에 저장되도록 JSF 상태 저장 방법을 클라이언트에 설정하십시오.

    <context-param> 
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
        <param-value>client</param-value> 
    </context-param> 
    

필터 방법이 바람직하다.

+0

예를 들어 주셔서 감사합니다 :) 나는 클라이언트에 상태 저장 방법을 변경하려고했는데, 나는 좀 이상하게 들렸습니다. 나는 많은 빈과 도메인 빈을 직렬화 가능으로 변경해야합니다. 그래서, 필터를 시도하고 위대한 일을! http://turbomanage.wordpress.com/2006/08/08/disable-browser-caching-in-jsf/ 여기에는이 기사의 걱정거리가 있지만 걱정할 필요는 없습니다. 하지만 여기서 제 경험으로는 아주 잘 작동합니다. – bertie

+0

'PhaseListener'에서 이것을하는 것은 어색합니다. 보장에 관해서는, 그는 요점을 가지고 있지만 모든 최신 브라우저 (IE, FF, GC, AS, O 등)는 HTTP 캐싱 규칙을 올바르게 준수합니다. 클라이언트가 모호한 브라우저를 사용할 때만 실패 할 것입니다. – BalusC

+0

하지만 한 가지가 있습니다. 브라우저의 뒤로 버튼을 클릭하면 p : datatable의 체크 박스가 선택되어 있지만 제출되면 실제로 체크되지 않습니다. 이것은 Google 크롬 15에서 발생하지만, Firefox 5.0.1에서는 발생하지 않습니다. 나는 이것과 같은 상황이라고 생각한다 : http://stackoverflow.com/questions/6100741/how-to-prevent-browsers-from-remembering-checkbox-state. 나는 솔루션에 명시된대로 무작위 화 된 폼 이름을 사용하려고한다. ,하지만 모르겠다면 내 양식의 이름을 모르는 경우 여러 양식이있는 페이지에서 다른 양식을 새로 고치는 방법을 모르겠다. – bertie

0

페이지의 브라우저 캐시를 사용하지 않는 단점은 브라우저를 사용하여 이전 페이지로 이동하는 경우 브라우저 오류 페이지가 표시된다는 것입니다.

@Named("browserCacheController") 
@RequestScoped 
public class BrowserCacheController implements Serializable { 
private static final long serialVersionUID = 1L; 
/** 
* Returns a unique increasing id for each request 
* @return 
*/ 
public long getCacheID() { 
    return System.currentTimeMillis(); 
} 
} 
:

먼저 (내 경우 현재 시스템 시간) 고유 ID를 제공하는 간단한 백업 빈을 만들 : 그래서 다른 솔루션 페이지는 자바 스크립트를 사용하여 서버 또는 브라우저 캐시에서 오는 경우 식별하는 것입니다

이제 서버 또는 브라우저에서 페이지가 제공되는지 테스트하고 현재 페이지가 브라우저 캐시에서 제공된 경우 사용자를 리디렉션 할 수 있습니다.

<script type="text/javascript"> 
    // check for latestCacheID 
    if (!isValidCacheID(#{browserCacheController.cacheID})) { 
     //redirect to some page 
     document.location="#{facesContext.externalContext.requestContextPath}/index.jsf"; 
    } 

    // test cacheID if it comes from the server.... 
    function isValidCacheID(currentCacheID) { 
     if (!('localStorage' in window && window['localStorage'] !== null)) 
      return true; // old browsers not supported 
     var latestCacheID=localStorage.getItem("org.imixs.latestCacheID"); 
     if (latestCacheID!=null && currentCacheID<=latestCacheID) { 
      return false; // this was a cached browser page! 
     } 
     // set new id 
     localStorage.setItem("org.imixs.latestCacheID", currentCacheID); 
     return true; 
    } 
</script> 

스크립트는 또한 JSF 코드를 더 깨끗하게 만들 수 facelet에 배치 할 수 있습니다 : 브라우저 캐시해서는 안 JSF 페이지에 배치 다음과 같은 자바 스크립트 코드를 참조하십시오.

+1

POST를 사용해서 탐색하면 안됩니다. – BalusC