我有一个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);
}
}
答案 0 :(得分:2)
从我的卑微观点来看,面孔上下文应该看到参数在请求已被重定向时第一次变化:resp.sendRedirect("/faces/error.jsp?token=" + token);
但是当你做出一些其他请求时,Faces会使用它的导航系统进行操作并重定向页面,显然过滤器正在执行chain.doFilter(req,resp);
那个时间,它授权JSF Navigation模型执行,从而删除你的请求参数。
我的建议是你可以将它添加到另一个会话值,然后操作会更容易。
答案 1 :(得分:0)
我不认为FacesContext在Servlet过滤器中可用。在点击FacesServlet(创建FacesContext)之前是否运行过滤器?
答案 2 :(得分:0)
在任何大于JSF本身的环境中,错误页面通常不适合JSF(例如,来自webapp framerwork)。是的,FaceContext不是你可以随时随地可用的东西。它由Faces Servlet创建,用于处理JSF请求,并在请求完成时被丢弃。从请求到请求,它没有持久的持久性。
此外,URL在JSF中的重要性与在大多数Web应用程序中的完全不同。它们更像是用于跟踪对话的句柄,而不是对请求或显示的页面的绝对指示。