javax.faces.application.ViewExpiredException: Không thể khôi phục chế độ xem


175

Tôi đã viết ứng dụng đơn giản với bảo mật được quản lý container. Vấn đề là khi tôi đăng nhập và mở một trang khác mà tôi đăng xuất, sau đó tôi quay lại trang đầu tiên và tôi nhấp vào bất kỳ liên kết nào, v.v. hoặc làm mới trang tôi nhận được ngoại lệ này. Tôi đoán đó là bình thường (hoặc có thể không :)) vì tôi đã đăng xuất và phiên bị hủy. Tôi nên làm gì để chuyển hướng người dùng đến ví dụ index.xhtml hoặc login.xhtml và lưu anh ta khỏi nhìn thấy trang / thông báo lỗi đó?

Nói cách khác, làm thế nào tôi có thể tự động chuyển hướng các trang khác đến trang chỉ mục / đăng nhập sau khi tôi đăng xuất?

Đây là:

javax.faces.application.ViewExpiredException: viewId:/index.xhtml - View /index.xhtml could not be restored.
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:212)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at filter.HttpHttpsFilter.doFilter(HttpHttpsFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
    at java.lang.Thread.run(Thread.java:619)

Câu trả lời:


353

Giới thiệu

Các ViewExpiredExceptionsẽ được ném bất cứ khi nào javax.faces.STATE_SAVING_METHODđược cài đặt để server(mặc định) và enduser gửi một yêu cầu HTTP POST trên một cái nhìn qua <h:form>với <h:commandLink>, <h:commandButton>hoặc <f:ajax>, trong khi tình trạng xem liên quan là không có sẵn trong phiên giao dịch nữa.

Trạng thái xem được xác định là giá trị của trường đầu vào ẩn javax.faces.ViewStatecủa <h:form>. Với phương thức lưu trạng thái được đặt thành server, điều này chỉ chứa ID trạng thái xem tham chiếu trạng thái xem được tuần tự hóa trong phiên. Vì vậy, khi phiên hết hạn vì một số lý do (đã hết thời gian ở phía máy chủ hoặc máy khách hoặc cookie phiên không được duy trì nữa vì một số lý do trong trình duyệt hoặc do gọi HttpSession#invalidate()máy chủ hoặc do lỗi cụ thể của máy chủ với cookie phiên như được biết đến trong WildFly ), sau đó trạng thái xem được tuần tự hóa không còn khả dụng trong phiên và trình kết thúc sẽ có ngoại lệ này. Để hiểu hoạt động của phiên, xem thêm Làm thế nào để các servlet hoạt động? Khởi tạo, phiên, biến chia sẻ và đa luồng .

Ngoài ra còn có giới hạn về số lượt xem mà JSF sẽ lưu trữ trong phiên. Khi giới hạn được nhấn, thì chế độ xem ít được sử dụng gần đây nhất sẽ hết hạn. Xem thêm com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews .

Với phương thức lưu trạng thái được đặt thành client, trường javax.faces.ViewStateđầu vào ẩn chứa thay vào đó là toàn bộ trạng thái xem được tuần tự hóa, vì vậy bộ xử lý sẽ không nhận được ViewExpiredExceptionkhi hết phiên. Tuy nhiên, điều đó vẫn có thể xảy ra trên môi trường cụm ("LRI: MAC không xác minh" là có triệu chứng) và / hoặc khi có thời gian chờ cụ thể thực hiện ở trạng thái phía máy khách được định cấu hình và / hoặc khi máy chủ tạo lại khóa AES trong khi khởi động lại , xem thêm Bắt ViewExpiredException trong môi trường cụm trong khi phương thức lưu trạng thái được đặt thành phiên khách và phiên người dùng là hợp lệ làm thế nào để giải quyết nó.

Bất kể giải pháp nào, hãy đảm bảo bạn không sử dụng enableRestoreView11Compatibility. nó hoàn toàn không khôi phục trạng thái xem ban đầu. Về cơ bản, nó tái tạo lại khung nhìn và tất cả các hạt đậu được xem có liên quan từ đầu và do đó làm mất tất cả dữ liệu gốc (trạng thái). Vì ứng dụng sẽ hoạt động theo cách khó hiểu ("Này, giá trị đầu vào của tôi ở đâu .. ??"), điều này rất tệ cho trải nghiệm người dùng. Tốt hơn nên sử dụng các chế độ xem không trạng thái hoặc <o:enableRestorableView>thay vào đó để bạn có thể quản lý nó trên một chế độ xem cụ thể thay vì trên tất cả các chế độ xem.

Về lý do tại sao JSF cần lưu trạng thái xem, hãy đi đến câu trả lời này: Tại sao JSF lưu trạng thái của các thành phần UI trên máy chủ?

Tránh ViewExpiredException trên điều hướng trang

Để tránh ViewExpiredExceptionkhi ví dụ: điều hướng trở lại sau khi đăng xuất khi lưu trạng thái được đặt thành server, chỉ chuyển hướng yêu cầu POST sau khi đăng xuất là không đủ. Bạn cũng cần hướng dẫn trình duyệt không lưu các trang JSF động, nếu không trình duyệt có thể hiển thị chúng từ bộ đệm thay vì yêu cầu một trang mới từ máy chủ khi bạn gửi yêu cầu GET trên đó (ví dụ bằng nút quay lại).

Trường javax.faces.ViewStateẩn của trang được lưu trong bộ nhớ cache có thể chứa giá trị ID trạng thái xem không còn hợp lệ trong phiên hiện tại. Nếu bạn (ab) sử dụng POST (liên kết lệnh / nút) thay vì GET (liên kết / nút thông thường) để điều hướng từ trang này sang trang khác và nhấp vào nút / liên kết lệnh như vậy trên trang được lưu trong bộ nhớ cache, thì điều này sẽ lần lượt thất bại với a ViewExpiredException.

Để kích hoạt chuyển hướng sau khi logout trong JSF 2.0, hoặc thêm <redirect />vào <navigation-case>trong câu hỏi (nếu có), hoặc thêm ?faces-redirect=truevào outcomegiá trị.

<h:commandButton value="Logout" action="logout?faces-redirect=true" />

hoặc là

public String logout() {
    // ...
    return "index?faces-redirect=true";
}

Để hướng dẫn trình duyệt không lưu trữ các trang JSF động, hãy tạo một trang Filterđược ánh xạ trên tên servlet của FacesServletvà thêm các tiêu đề phản hồi cần thiết để vô hiệu hóa bộ đệm của trình duyệt. Ví dụ

@WebFilter(servletNames={"Faces Servlet"}) // Must match <servlet-name> of your FacesServlet.
public class NoCacheFilter implements 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);
    }

    // ...
}

Tránh ViewExpiredException khi làm mới trang

Để tránh ViewExpiredExceptionkhi làm mới trang hiện tại khi lưu trạng thái được đặt thành server, bạn không chỉ cần đảm bảo rằng bạn đang thực hiện điều hướng từ trang này sang trang khác bằng GET (liên kết / nút thông thường), mà bạn cũng cần đảm bảo rằng bạn đang sử dụng ajax để gửi biểu mẫu. Nếu bạn đang gửi biểu mẫu một cách đồng bộ (không phải ajax), thì tốt nhất bạn nên đặt chế độ xem không trạng thái (xem phần sau) hoặc gửi chuyển hướng sau POST (xem phần trước).

Có một ViewExpiredExceptionlàm mới trên trang là trong cấu hình mặc định một trường hợp rất hiếm. Nó chỉ có thể xảy ra khi giới hạn về số lượt xem mà JSF sẽ lưu trữ trong phiên được nhấn. Vì vậy, điều đó sẽ chỉ xảy ra khi bạn đặt thủ công mức giới hạn quá thấp hoặc bạn liên tục tạo chế độ xem mới trong "nền" (ví dụ: cuộc thăm dò ajax được triển khai kém trong cùng một trang hoặc do 404 thực hiện kém trang lỗi trên hình ảnh bị hỏng của cùng một trang). Xem thêm com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews để biết chi tiết về giới hạn đó. Một nguyên nhân khác là có các thư viện JSF trùng lặp trong đường dẫn lớp chạy xung đột lẫn nhau. Quy trình đúng để cài đặt JSF được nêu trong trang wiki JSF của chúng tôi .

Xử lý ViewExpiredException

Khi bạn muốn xử lý một điều không thể tránh khỏi ViewExpiredExceptionsau một hành động POST trên một trang tùy ý đã được mở trong một số tab / cửa sổ trình duyệt trong khi bạn đăng xuất trong một tab / cửa sổ khác, thì bạn muốn chỉ định một trang error-pagecho web.xmlnó. đến trang "Phiên của bạn đã hết giờ". Ví dụ

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/WEB-INF/errorpages/expired.xhtml</location>
</error-page>

Sử dụng nếu cần một tiêu đề làm mới meta trong trang lỗi trong trường hợp bạn có ý định thực sự chuyển hướng xa hơn đến trang chủ hoặc trang đăng nhập.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Session expired</title>
        <meta http-equiv="refresh" content="0;url=#{request.contextPath}/login.xhtml" />
    </head>
    <body>
        <h1>Session expired</h1>
        <h3>You will be redirected to login page</h3>
        <p><a href="#{request.contextPath}/login.xhtml">Click here if redirect didn't work or when you're impatient</a>.</p>
    </body>
</html>

( 0in contentđại diện cho số giây trước khi chuyển hướng, 0do đó có nghĩa là "chuyển hướng ngay lập tức", bạn có thể sử dụng ví dụ 3để cho trình duyệt chờ 3 giây với chuyển hướng)

Lưu ý rằng việc xử lý các ngoại lệ trong các yêu cầu ajax yêu cầu đặc biệt ExceptionHandler. Xem thêm Thời gian chờ phiên và xử lý ViewExpiredException trên yêu cầu ajax của JSF / PrimeFaces . Bạn có thể tìm thấy một ví dụ trực tiếp tại trang giới thiệu OmniFacesFullAjaxExceptionHandler (điều này cũng bao gồm các yêu cầu không phải là ajax).

Cũng lưu ý rằng "chung" trang báo lỗi của bạn nên được ánh xạ vào <error-code>trong 500thay vì một <exception-type>số ví dụ java.lang.Exceptionhoặc java.lang.Throwable, nếu không tất cả trường hợp ngoại lệ được bọc trong ServletExceptionnhư ViewExpiredExceptionvẫn sẽ kết thúc trong trang lỗi chung. Xem thêm ViewExpiredException được hiển thị trong java.lang.Thẻ lỗi trang trong tệp web.xml .

<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/errorpages/general.xhtml</location>
</error-page>

Quan điểm không quốc tịch

Một cách khác hoàn toàn khác là chạy các khung nhìn JSF ở chế độ không trạng thái. Bằng cách này, không có trạng thái nào của JSF sẽ được lưu và các khung nhìn sẽ không bao giờ hết hạn, mà chỉ được xây dựng lại từ đầu theo mọi yêu cầu. Bạn có thể bật quan điểm không quốc tịch bằng cách thiết lập transientthuộc tính của <f:view>để true:

<f:view transient="true">

</f:view>

Bằng cách này, javax.faces.ViewStatetrường ẩn sẽ nhận được giá trị cố định "stateless"trong Mojarra (chưa kiểm tra MyFaces tại thời điểm này). Lưu ý rằng tính năng này đã được giới thiệu trong Mojarra 2.1.19 và 2.2.0 và không có sẵn trong các phiên bản cũ hơn.

Hậu quả là bạn không thể sử dụng xem phạm vi đậu nữa. Bây giờ họ sẽ hành xử như yêu cầu đậu có phạm vi. Một trong những nhược điểm là bạn phải tự theo dõi trạng thái bằng cách thay đổi các đầu vào ẩn và / hoặc các tham số yêu cầu lỏng lẻo. Chủ yếu là những hình thức với các lĩnh vực đầu vào với rendered, readonlyhoặc disabledthuộc tính được điều khiển bởi sự kiện ajax sẽ bị ảnh hưởng.

Lưu ý rằng <f:view>không nhất thiết phải là duy nhất trong toàn bộ chế độ xem và / hoặc chỉ nằm trong mẫu chính. Nó cũng hoàn toàn hợp pháp để tái phân phối và lồng nó vào một máy khách mẫu. Về cơ bản nó "kéo dài" cha mẹ <f:view>rồi. Ví dụ: trong mẫu chính:

<f:view contentType="text/html">
    <ui:insert name="content" />
</f:view>

và trong ứng dụng khách mẫu:

<ui:define name="content">
    <f:view transient="true">
        <h:form>...</h:form>
    </f:view>
</f:view>

Bạn thậm chí có thể bọc <f:view>trong một <c:if>để làm cho nó có điều kiện. Lưu ý rằng nó sẽ áp dụng trên toàn bộ khung nhìn, không chỉ trên các nội dung lồng nhau, chẳng hạn như <h:form>trong ví dụ trên.

Xem thêm


Không liên quan đến vấn đề cụ thể, sử dụng HTTP POST để điều hướng từ trang này sang trang khác không thân thiện với người dùng / SEO. Trong JSF 2.0, bạn thực sự nên thích <h:link>hoặc <h:button>hơn <h:commandXxx>những người điều hướng trang vanilla đơn giản.

Vì vậy, thay vì ví dụ

<h:form id="menu">
    <h:commandLink value="Foo" action="foo?faces-redirect=true" />
    <h:commandLink value="Bar" action="bar?faces-redirect=true" />
    <h:commandLink value="Baz" action="baz?faces-redirect=true" />
</h:form>

làm tốt hơn

<h:link value="Foo" outcome="foo" />
<h:link value="Bar" outcome="bar" />
<h:link value="Baz" outcome="baz" />

Xem thêm


Làm thế nào tôi có thể làm điều đó với điều hướng ngầm trong java ee 6? Tôi không sử dụng khuôn mặt-config.
l245c4l

1
Ồ, bạn đang sử dụng JSF 2.0? Bạn nên đề cập rằng trong câu hỏi của bạn! Thêm ?faces-redirect=truevào outcome. Tôi đã cập nhật câu trả lời tương ứng.
BalusC

Có, tôi mới bắt đầu với java ee :) và tôi đang sử dụng khuôn mặt-redirect = true trong tất cả các điều hướng của mình. Tôi chỉ sử dụng h: CommandLink khi tôi có hành động được xác nhận với nó. Ví dụ: Liên kết đăng xuất ... Tôi có hành động Đăng xuất chuỗi () trong đó tôi vô hiệu hóa phiên và chuyển hướng để đăng nhập, nhưng nó không hoạt động trên trang nơi tôi đã đăng nhập và tại thời điểm đăng xuất và ném ngoại lệ đó :(
l245c4l

1
Cảm ơn một lần nữa và xin lỗi vì điều đó :) nhưng ít nhất tôi đã nhận được câu trả lời nhanh chóng và chuyên nghiệp ngay lập tức: p
l245c4l

1
@LS: Tuy nhiên, bộ lọc vẫn là bắt buộc cho trường hợp bất cứ khi nào người ta nhấn nút quay lại sau khi POST hết hạn và cố gắng gọi một yêu cầu POST khác trên nó. Điều này nếu không sẽ vô tình dẫn đến ngoại lệ này.
BalusC

56

Bạn đã thử thêm các dòng dưới đây vào của bạn web.xml?

<context-param>
   <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
   <param-value>true</param-value>
</context-param>

Tôi thấy điều này rất hiệu quả khi tôi gặp phải vấn đề này.


1
nó cũng làm việc cho tôi Cảm ơn câu trả lời. mục đích của việc này là gì?
MartK

2
Không nhớ chính xác, nhưng tôi đã tìm thấy giải pháp này trên trang web ICEFaces.
Mike GH

Tôi có thể đến bữa tiệc muộn một chút, nhưng điều này cũng có hiệu quả với tôi. cảm ơn!
stellarossa

4
Có phải điều này chỉ được định nghĩa cho JSF 1.2 hoặc JSF 2 không?
SRy

17
Điều này sẽ ngừng ném ngoại lệ khi chế độ xem hết hạn và chỉ cần tiếp tục yêu cầu, nhưng JSF vẫn không thể khôi phục trạng thái xem cũng như không tìm thấy bất kỳ hạt đậu nào trong phạm vi xem. Giao dịch này sẽ hoạt động giống như JSF không trạng thái và bạn cần tự khôi phục trạng thái xem dựa trên các tham số yêu cầu POST để tránh "wtf?" kinh nghiệm của enduser khi xử lý biểu mẫu gửi phản hồi bất ngờ. Nếu bạn chỉ muốn áp dụng điều này trên các trang JSF cụ thể, thì nên sử dụng OmniFaces <o:enableRestorableView>thay vì tham số ngữ cảnh rộng của ứng dụng.
BalusC

5

Trước tiên, những gì bạn phải làm, trước khi thay đổi web.xml là đảm bảo ManagedBean của bạn implements Serializable:

@ManagedBean
@ViewScoped
public class Login implements Serializable {
}

Đặc biệt nếu bạn sử dụng MyFaces


3

Tránh các hình thức nhiều phần trong Richfaces:

<h:form enctype="multipart/form-data">
    <a4j:poll id="poll" interval="10000"/>
</h:form>

Nếu bạn đang sử dụng Richfaces, tôi đã thấy rằng các yêu cầu ajax bên trong các biểu mẫu nhiều phần sẽ trả về một ID View mới cho mỗi yêu cầu.

Cách gỡ lỗi:

Trên mỗi yêu cầu ajax, một View ID được trả về, điều đó cũng tốt miễn là View ID luôn giống nhau. Nếu bạn nhận được ID xem mới trên mỗi yêu cầu, thì có một vấn đề và phải được khắc phục.


Hãy cẩn thận khi chơi với các cuộc thăm dò, nó có thể ngăn các phiên người dùng của bạn hết hạn ..
Jonathan Simas

0

Bạn coud sử dụng AjaxExceptionHandler hoặc phần mở rộng tùy chỉnh của riêng bạn

Cập nhật khuôn mặt của bạn-config.xml

...
<factory>
  <exception-handler-factory>org.primefaces.extensions.component.ajaxerrorhandler.AjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
...

Thêm mã sau vào trang jsf của bạn

...
<pe:ajaxErrorHandler />
...

0

Tôi đã gặp lỗi này: javax.faces.application.ViewExpiredException. Khi tôi sử dụng các yêu cầu khác nhau, tôi thấy những người có cùng JsessionId, ngay cả sau khi khởi động lại máy chủ. Vì vậy, điều này là do bộ nhớ cache của trình duyệt. Chỉ cần đóng trình duyệt và thử, nó sẽ hoạt động.


0

Khi trang của chúng tôi không hoạt động trong x lượng thời gian, chế độ xem sẽ hết hạn và ném javax.faces.application.ViewExpiredException để ngăn điều này xảy ra, một giải pháp là tạo CustomViewHandler mở rộng phương thức ViewHandler và ghi đè phương thức khôi phục tất cả các phương thức khác đang được ủy quyền cho Cha mẹ

import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

public class CustomViewHandler extends ViewHandler {
    private ViewHandler parent;

    public CustomViewHandler(ViewHandler parent) {
        //System.out.println("CustomViewHandler.CustomViewHandler():Parent View Handler:"+parent.getClass());
        this.parent = parent;
    }

    @Override 
    public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
    /**
     * {@link javax.faces.application.ViewExpiredException}. This happens only  when we try to logout from timed out pages.
     */
        UIViewRoot root = null;
        root = parent.restoreView(facesContext, viewId);
        if(root == null) {
            root = createView(facesContext, viewId);
        }
        return root;
    }

    @Override
    public Locale calculateLocale(FacesContext facesContext) {
        return parent.calculateLocale(facesContext);
    }

    @Override
    public String calculateRenderKitId(FacesContext facesContext) {
        String renderKitId = parent.calculateRenderKitId(facesContext);
        //System.out.println("CustomViewHandler.calculateRenderKitId():RenderKitId: "+renderKitId);
        return renderKitId;
    }

    @Override
    public UIViewRoot createView(FacesContext facesContext, String viewId) {
        return parent.createView(facesContext, viewId);
    }

    @Override
    public String getActionURL(FacesContext facesContext, String actionId) {
        return parent.getActionURL(facesContext, actionId);
    }

    @Override
    public String getResourceURL(FacesContext facesContext, String resId) {
        return parent.getResourceURL(facesContext, resId);
    }

    @Override
    public void renderView(FacesContext facesContext, UIViewRoot viewId) throws IOException, FacesException {
        parent.renderView(facesContext, viewId);
    }

    @Override
    public void writeState(FacesContext facesContext) throws IOException {
        parent.writeState(facesContext);
    }

    public ViewHandler getParent() {
        return parent;
    }

}   

Sau đó, bạn cần thêm nó vào khuôn mặt của bạn-config.xml

<application>
    <view-handler>com.demo.CustomViewHandler</view-handler>
</application>

Cảm ơn câu trả lời ban đầu ở liên kết dưới đây: http://www.gregormsaj.com/?p=164


Cách tiếp cận này không khôi phục xem đậu có phạm vi.
BalusC

-2

Vui lòng thêm dòng này vào web.xml của bạn. Nó hoạt động với tôi

<context-param>
        <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name> 
        <param-value>true</param-value>     
    </context-param>

4
Câu trả lời của bạn sẽ hữu ích hơn nếu bạn bao gồm giải thích và bối cảnh về những gì mã đang làm.
Palpatim

1
Ngay cả khi đây là câu trả lời đúng, StackOverflow không khuyến khích các câu trả lời như thế này mà không có lời giải thích. Nó sẽ hữu ích cho cộng đồng để thêm thông tin về lý do tại sao nó hoạt động.
RacerNerd

-2

Bản thân tôi đã gặp phải vấn đề này và nhận ra rằng đó là do tác dụng phụ của Bộ lọc mà tôi đã tạo ra, đó là lọc tất cả các yêu cầu trên ứng dụng. Ngay sau khi tôi sửa đổi bộ lọc để chỉ chọn một số yêu cầu nhất định, sự cố này đã không xảy ra. Có thể tốt để kiểm tra các bộ lọc như vậy trong ứng dụng của bạn và xem cách chúng hoạt động.


-3

Tôi thêm cấu hình sau vào web.xml và nó đã được giải quyết.

<context-param>
    <param-name>com.sun.faces.numberOfViewsInSession</param-name>
    <param-value>500</param-value>
</context-param>
<context-param>
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>500</param-value>
</context-param>

6
Lời khuyên khủng khiếp. Chỉ làm điều này khi bạn có nhiều bộ nhớ và những người ủng hộ của bạn thực sự có tới 500 tab trình duyệt mở và nhấn nút quay lại của trình duyệt lên tới 500 lần cho các lần gửi lại đồng bộ trước đó.
BalusC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.