代码之家  ›  专栏  ›  技术社区  ›  Andreas Petersson

使用JSF时,http GET参数有时会丢失

  •  0
  • Andreas Petersson  · 技术社区  · 16 年前

    JSF

    如果检测到错误,用户将被重定向到错误页面,在那里他可以给出反馈。然后我尝试读取 ErrorBean 对象然而,有时错误并不存在——存在错误的可能性为50%。

    FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()
    

    它有时返回一个带有1个条目的映射,有时返回一个空映射。在任何情况下,id都是在http级别传递的。

    我真的无法重现是什么导致了这一切。以下是相关代码(省略了helper方法+空实现)。ErrorFilter映射在 /* ErrorBean是由JSF管理的会话范围bean。

    public class ErrorFilter implements Filter 
    {
      public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException 
      {
        HttpServletRequest hreq = (HttpServletRequest) req;
        HttpServletResponse hres = (HttpServletResponse) resp;
    
        try 
        {
          chain.doFilter(req, resp);
        } 
        catch (IOException e) 
        {
          handleError(e, hreq, hres);
        } 
        catch (ServletException e) 
        {
          handleError(e, hreq, hres);
        } 
        catch (RuntimeException e) 
        {
          handleError(e, hreq, hres);
        }
      }
    
      private static void handleError(Throwable e, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
      {
        final RequestInfo requestInfo = new RequestInfo(getUri(req), req.getSession().getId(), null, null, UserFactory.getUser(), InetAddress.getByName(req.getRemoteAddr()));
        String token = new DecimalFormat("00000000").format(Math.abs(RANDOM.nextInt() % Integer.MAX_VALUE));
        //log msg
        //send mail in a different thread
    
        if (!req.getRequestURI().startsWith("/faces/error.jsp")) 
        {
          resp.sendRedirect("/faces/error.jsp?token=" + token);
        } 
        else 
        {
          //log that an infite loop occurred
          throw new ServletException(crapMsg, e);
        }
      }
    }
    

    错误豆

    public class ErrorBean implements Serializable 
    {
      private String feedback;
      private String lastToken;
    
      public String getLastErrorCode() 
      {
        return "your token: " + getToken();
      }
    
      private String getToken() 
      {
        final String token = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("token");
        //here the "token" returns null although it is sent via get.
    
        if (token != null) 
        {
            if (!token.equals(lastToken)) 
            {
              // reset data on token change.
              feedback = null;
            }
            lastToken = token;
        }
    
        return lastToken;
      }
    
      public void setFeedback(String feedback) 
      {
        this.feedback = feedback;
      }
    
        public String getFeedback() 
        {
          if (feedback == null) 
          {
            feedback = getDefaultMessage();
          }
    
          return feedback;
        }
    
      public void send()
      {
        sendMail(lastToken,feedback);
      }
    }
    
    3 回复  |  直到 9 年前
        1
  •  2
  •   Amr Gawish    16 年前

    从我的角度来看,faces上下文应该在请求已重定向时第一次看到参数vary: resp.sendRedirect("/faces/error.jsp?token=" + token);

    chain.doFilter(req,resp); 此时,它授权JSF导航模型执行,从而删除您的请求参数。

    我的建议是,您可以将其添加到另一个会话值中,这样会更容易操作。

        3
  •  0
  •   Tim H    16 年前

    在任何比JSF本身更大的上下文中,错误页面通常都不是JSF的好候选对象(例如,来自webapp框架的错误页面)。是的,FaceContext并不是任何时候都可以使用的东西。它是由facesservlet创建的,用于处理JSF请求,当请求完成时,它将被丢弃。它不再具有从一个请求到另一个请求的长期持久性。

    而且,URL在JSF中的意义与在大多数web应用程序中的意义完全不同。它们更像是用来跟踪对话的手柄,而不是请求或显示页面的绝对指示。