Java 高效访问HttpServletRequest以进行调试打印

Java 高效访问HttpServletRequest以进行调试打印,java,production-environment,servlets,debug-print,Java,Production Environment,Servlets,Debug Print,为了调试失败的请求,我想打印来自HttpServletRequest的所有信息 现在,一个请求可能会部分失败(例如,有几个匹配成功,但有一个失败),在这种情况下,我希望捕获失败的内部方法中的异常,打印错误+ServletUtil.ToStringttpServletRequest()并继续提供服务(降级但与完全请求失败相比仍然有用) 我们当前的实现要么捕获异常并打印哑信息(“getRules failed”),要么将异常一直抛出到doGet()(有效地取消了用户的服务),在doGet()中,我可

为了调试失败的请求,我想打印来自HttpServletRequest的所有信息

现在,一个请求可能会部分失败(例如,有几个匹配成功,但有一个失败),在这种情况下,我希望捕获失败的内部方法中的异常,打印错误+ServletUtil.ToStringttpServletRequest()并继续提供服务(降级但与完全请求失败相比仍然有用)

我们当前的实现要么捕获异常并打印哑信息(“getRules failed”),要么将异常一直抛出到doGet()(有效地取消了用户的服务),在doGet()中,我可以访问HttpServletRequest,在那里我可以打印相关的调试信息(头、参数…)

将HttpServletRequest传递给在请求过程中调用的每个可能失败的函数似乎有点难看,如果没有其他优雅的解决方案出现,我会这样做

创建一个before-head ServletUtil.toStringttpServletRequest()并将其存储在ThreadLocal映射中会浪费内存和CPU时间。出于某种原因,将HttpServletRequest对象存储在ThreadLocal中感觉不正确(如果我错了,请更正)

调试信息被写入本地计算机日志,并通过电子邮件直接发送给devs(Great work log4j),因此在多个地方进行日志记录是不现实的(需要收集多封电子邮件以了解发生了什么),而ssh进入服务器是很老的:)(我们这里都是多云的…在我查看错误时,服务器可能不存在)

因此,我的解决方案是访问一个“PrintErrorUtility”(TODO:更好地命名它)。它将接收(字符串errorMsg,Throwable t,HttpServletRequest),它将把错误打印在一起,并将所有相关信息…这将从内部try{}调用将通知错误但不会因此取消请求的catch块

显然,我是在讨论生产中运行的服务器

评论?请告知


谢谢你,马克西姆。

过滤器链#doFilter()之后的
过滤器中执行此任务
call.
ServletRequest
对象已经存在。在要优雅地抑制此异常的业务代码中,将异常存储为请求属性,然后让
过滤器从请求中检查/获取它


更新:根据评论,下面是一个示例:

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);
    }
}
下面是如何在执行的业务代码中使用它:

} catch (Exception e) {
    Context.getCurrentInstance().addException(e);
}

好的,但是为了在request属性中存储异常,我需要访问request对象,这不是让我们回到第1步吗?(除非我遗漏了什么,在这种情况下,请纠正我的错误)编辑:我想问一下您是使用特定的MVC框架还是自己开发的框架?大多数现有的MVC框架都有一个threadlocal上下文,您可以从中获取“底层”内容原始请求/响应对象。没有MVC,它是后端服务器。所有的服务器都在计算每个请求的匹配,而不是纯代码。它提供了对请求/响应的访问。您只需要确保在任何情况下都会最终释放它。调用业务操作的
try
块的
finally
块对此很好。普通的servletcontainer使用线程池,从而重用线程。嗨,系统运行在Tomcat5.5(Debian)上。这是我不喜欢线程本地(这么多)的原因之一。你能提供一个基于线程本地上下文方法的代码示例吗?
} catch (Exception e) {
    Context.getCurrentInstance().addException(e);
}