【问题标题】:Efficient access to HttpServletRequest for debug prints高效访问 HttpServletRequest 以进行调试打印
【发布时间】:2010-07-12 11:59:48
【问题描述】:

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

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

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

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

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

调试信息会写入本地机器日志并直接通过电子邮件发送给开发人员(很棒的工作 log4j TLSSMTPAppender),因此在多个地方登录是不切实际的(需要收集几封电子邮件才能了解发生了什么)并且 ssh'ing 进入服务器已经很老了 :) (我们这里都是阴天......当我看到错误时服务器可能不存在)

所以,我的解决方案是访问“PrintErrorUtility”(TODO:最好命名它)。这将接收 (String errorMsg, Throwable t, HttpServletRequest) 将所有相关信息一起打印错误...这将从内部 try {} catch 块中调用,该块将通知错误但不会取消请求,因为。

显然,我正在考虑在生产中运行的服务器。

评论?请指教。

谢谢你,马克西姆。

【问题讨论】:

    标签: java production-environment servlets debug-print


    【解决方案1】:

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


    更新:根据 cmets,这是一个示例:

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

    下面是如何在你的控制器 servlet 中使用它:

    Context context = Context.newInstance(request);
    try {
        executeBusinessCode();
    } finally {
        context.release();
    }
    

    您可以在执行的业务代码中使用它:

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

    【讨论】:

    • 好的,但是为了将异常存储在请求属性中,我需要访问请求对象,这不是让我们回到第 1 格吗? (除非我遗漏了什么,在这种情况下请纠正我的错误) 编辑:我会传递一个
    • 您使用的是特定的 MVC 框架还是自己开发的?大多数现有 MVC 框架都有一个线程本地上下文,您可以从中获取“底层”原始请求/响应对象。
    • 没有 MVC,它是一个后端服务器。服务器所做的只是计算每个请求的匹配,没有框架纯粹是我们的代码。
    • 好吧,您可能会考虑自己开发一个线程本地“上下文”,它提供对请求/响应的访问。您只需要确保确定,在任何 的情况下最终都会发布。要调用业务操作的try 块的finally 块对此很有用。普通的 servletcontainer 即使用线程池,从而重用线程。
    • 您好,系统运行在tomcat 5.5 (Debian)上。这就是我不喜欢线程本地(这么多)的原因之一。您能否为这种基于 ThreadLocal 的上下文方法提供一个代码示例?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2011-01-08
    • 2011-09-28
    • 1970-01-01
    相关资源
    最近更新 更多