使用JSF时缺少http GET参数SOMETIMES

时间:2009-05-28 15:09:28

标签: java http jsf servlets

我有一个servlet过滤器,可以处理vanilla servlet和JSF页面的错误。

如果检测到错误,用户将被重定向到错误页面,在那里他可以提供反馈。然后我尝试读取ErrorBean对象中的值。但是,有时错误不存在 - 错误出现的可能性为50%。

当我使用

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

它有时会返回一个包含1个条目的地图,有时会返回一个空地图。在每种情况下,id都以http级别传递。

我无法真正重现造成这种情况的原因。这是相关代码(辅助方法+空实现省略)。 ErrorFilter映射到/*,ErrorBean是由JSF管理的会话范围bean。

ErrorFilter

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);
    }
  }
}

ErrorBean

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 个答案:

答案 0 :(得分:2)

从我的卑微观点来看,面孔上下文应该看到参数在请求已被重定向时第一次变化:resp.sendRedirect("/faces/error.jsp?token=" + token);

但是当你做出一些其他请求时,Faces会使用它的导航系统进行操作并重定向页面,显然过滤器正在执行chain.doFilter(req,resp);那个时间,它授权JSF Navigation模型执行,从而删除你的请求参数。

我的建议是你可以将它添加到另一个会话值,然后操作会更容易。

答案 1 :(得分:0)

我不认为FacesContext在Servlet过滤器中可用。在点击FacesServlet(创建FacesContext)之前是否运行过滤器?

尝试阅读:http://www.thoughtsabout.net/blog/archives/000033.html

答案 2 :(得分:0)

在任何大于JSF本身的环境中,错误页面通常不适合JSF(例如,来自webapp framerwork)。是的,FaceContext不是你可以随时随地可用的东西。它由Faces Servlet创建,用于处理JSF请求,并在请求完成时被丢弃。从请求到请求,它没有持久的持久性。

此外,URL在JSF中的重要性与在大多数Web应用程序中的完全不同。它们更像是用于跟踪对话的句柄,而不是对请求或显示的页面的绝对指示。