为了调试失败的请求,我想打印来自 HttpServletRequest 的所有信息。
现在,请求可能会部分失败(例如,几个匹配成功,但一个失败),在这种情况下,我想捕获失败的内部方法中的异常,打印错误+ ServletUtil .toStringHttpServletRequest() 并继续提供服务(降级但相对于完全请求失败仍然有用)。
我们当前的实现要么捕获异常并打印愚蠢的信息(“getRules failed”),要么将异常一直抛出到 doGet() (有效地取消用户的服务),就像在 doGet() 中一样,我可以访问 HttpServletRequest我可以在其中打印相关的调试信息(标题、参数...)。
将 HttpServletRequest 传递给请求期间调用的每个可能失败的函数似乎有点难看,如果没有其他优雅的解决方案出现,我会这样做。
制作一个 before head ServletUtil.toStringHttpServletRequest() 并将其存储在 ThreadLocal 映射中会浪费内存和 CPU 时间。由于某种原因,将 HttpServletRequest 对象存储在 ThreadLocal 中感觉不对(如果我错了,请纠正)。
调试信息既写入本地计算机日志,又直接通过电子邮件发送给开发人员(伟大的工作 log4j TLSSMTPAppender ),因此在多个位置进行日志记录是不切实际的(需要组合几封电子邮件才能了解发生了什么)并且 ssh'ing 进入服务器已经很老了:)(我们这里都是多云的...当我查看错误时服务器可能不存在)
所以,我的解决方案是访问“PrintErrorUtility”(TODO:更好地命名它)。这将接收 (String errorMsg, Throwable t, HttpServletRequest) ,它将打印错误以及所有相关信息...这将从内部 try {} catch block 调用,它将通知错误但不会取消请求,因为其中。
显然,我正在考虑在生产中运行的服务器。
评论?请指教。
谢谢你,马克西姆。
最佳答案
在Filter
调用FilterChain#doFilter()
之后执行此任务。 ServletRequest
对象已经存在。在要优雅地抑制此异常的业务代码中,将异常存储为请求属性,然后让 Filter
从请求中检查/抓取它。
更新:根据评论,这里有一个示例:
public class Context {
private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
private HttpServletRequest request;
private List<Exception> exceptions = new ArrayList<Exception>();
private Context(HttpServletRequest request) {
this.request = request;
this.request.setAttribute("exceptions", exceptions);
}
public static Context getCurrentInstance() {
return instance.get();
}
public static Context newInstance(HttpServletRequest request) {
Context context = new Context(request);
instance.set(context);
return context;
}
public void release() {
instance.remove();
}
public void addException(Exception exception) {
exceptions.add(exception);
}
}
以下是如何在 Controller servlet 中使用它:
Context context = Context.newInstance(request);
try {
executeBusinessCode();
} finally {
context.release();
}
以下是如何在执行的业务代码中使用它:
} catch (Exception e) {
Context.getCurrentInstance().addException(e);
}
关于java - 高效访问 HttpServletRequest 以进行调试打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3228276/