Java 使用JSF时,http GET参数有时会丢失
我有一个servlet过滤器,用于处理普通servlet和Java 使用JSF时,http GET参数有时会丢失,java,http,jsf,servlets,Java,Http,Jsf,Servlets,我有一个servlet过滤器,用于处理普通servlet和JSF页面的错误 如果检测到错误,用户将被重定向到错误页面,在那里他可以给出反馈。然后我尝试读取ErrorBean对象中的值。然而,有时错误并不存在——存在错误的可能性为50% 当我使用 FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap() 它有时返回一个带有1个条目的映射,有时返回一个空映射。在任何情况下,id都是在http级别传
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);
}
}
}
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);
}
}
我认为FacesContext在Servlet过滤器中不可用。在点击FacesServlet(创建FacesContext)之前是否运行过滤器
试着阅读:在任何比JSF本身更大的上下文中,错误页面通常都不适合JSF(例如,在webapp框架中)。是的,FaceContext并不是任何时候都可以使用的东西。它是由facesservlet创建的,用于处理JSF请求,当请求完成时,它将被丢弃。它不再具有从一个请求到另一个请求的长期持久性
而且,URL在JSF中的意义与在大多数web应用程序中的意义完全不同。它们更像是用于跟踪对话的句柄,而不是请求或显示的页面的绝对指示。以我的拙见来看,当请求已经重定向时,faces上下文应该第一次看到参数vary:
resp.sendRedirect(“/faces/error.jsp?token=“+token”)代码>
但是,当您发出一些其他请求时,Faces会对其导航系统进行操作并重定向页面,显然,过滤器正在执行chain.doFilter(req,resp)此时,它授权JSF导航模型执行,从而删除您的请求参数
我的建议是,您可以将其添加到另一个会话值中,这样会更容易操作。我相信他的意思是错误页面是一个JSF页面,它使用托管bean来查找过滤器设置的HTTP参数(在这种情况下,上下文将可用)。他有注释“创建带有“int”标记的errorInfo对象”。如果看不到这个物体以及它是如何使用的,很难说。据我们所知,该对象上的.getToken()可能会返回null。该标记只是一个如下生成的随机字符串:this.token=new DecimalFormat(“00000000”).format(Math.abs(random.nextInt()%Integer.MAX_VALUE));请注意,在过滤器中根本不使用facescontext。在ErrorBean中使用它来获取参数。我没有弄清楚它有时失败的确切原因。。您提出的解决方案效果很好,我以这种方式实现了它。在会话中存储令牌属性。这一点非常有效。