【问题标题】:How to add a request logging filter in Jetty 8?如何在 Jetty 8 中添加请求日志过滤器?
【发布时间】:2016-01-19 00:06:15
【问题描述】:

这是我设置 Jetty 服务器的方法:

Server server = new Server(80);
server.setStopAtShutdown(true);

ServletHandler servletHandler = new ServletHandler();
servletHandler.addServletWithMapping(Erreur500Servlet.class, "/generate-error-500");
servletHandler.addServletWithMapping(AresServlet.class, "/ares/*");
servletHandler.addFilterWithMapping(RequestLoggingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

server.setHandler(servletHandler);
server.start(); // at com.company.MyPoc.init(MyPoc.java:44)
server.join();

但是,当它启动时,我得到了以下异常:

2015-10-20 12:53:07,565 (?:?) [WARN] FAILED com.company.filter.RequestLoggingFilter-896472140: java.lang.NullPointerException 
java.lang.NullPointerException: null
    at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:100) ~[jetty-servlet-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) [jetty-util-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:753) [jetty-servlet-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.servlet.ServletHandler.doStart(ServletHandler.java:183) [jetty-servlet-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) [jetty-util-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) [jetty-server-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.server.Server.doStart(Server.java:262) [jetty-server-8.0.1.v20110908.jar:8.0.1.v20110908]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) [jetty-util-8.0.1.v20110908.jar:8.0.1.v20110908]
    at com.company.MyPoc.init(MyPoc.java:44) 

我错过了什么?

码头 8.0.1.v20110908

【问题讨论】:

    标签: java servlets filter jetty jetty-8


    【解决方案1】:

    首先,也是最重要的,Jetty 8 is EOL (End of Life)

    接下来,请使用更新的 Jetty 版本,Jetty 8.0.1 (目前)比当前稳定版本的 Jetty 大约落后 110 个版本。

    现在,解释一下发生了什么。

    您正在直接使用 ServletHandler,这是一个内部类,不打算直接实例化和访问,而是在最简单和幼稚的情况下。即只有 1 个(并且只有 1 个)Servlet、没有过滤器、没有安全性、没有会话处理等的服务器......

    使用ServletContextHandler 并向其中添加您的servlet 和过滤器。这是正确的方法,因为它建立了一个ServletContext,所有相关的 Servlet 和过滤器都使用它来协调。

    示例(这是凭记忆完成的,因为 Jetty 8.0.1 太旧了,这可能需要一些调整才能在您的旧版 Jetty 上正常工作)

    Server server = new Server(8080);
    ServletContextHandler context = new ServletContextHandler();
    context.setContextPath("/");
    context.setResourceBase("/path/to/my/static/resources/");
    context.setHandler(server);
    
    context.addServlet(Erreur500Servlet.class, "/generate-error-500");
    context.addServlet(AresServlet.class, "/ares/*");
    context.addFilter(RequestLoggingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
    context.addServlet(DefaultServlet.class, "/");
    
    server.start();
    server.join();
    

    注意:

    • 如果您要提供静态资源(html、javascript、css、图像等),则使用.setResourceBase(String) 设置基本资源路径(Jetty 9 中添加了一个新的更好的.setBaseResource(Resource)
    • 如果您想提供静态资源或获取错误处理,请不要忘记致电context.addServlet(DefaultServlet.class, "/")

    如果您想要自定义错误处理,请使用像这样的 ServletContextHandler ErrorHandler 功能

    // Default error handler
    ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
    errorHandler.addErrorPage(500,"/error");
    
    // Your webapp
    ServletContextHandler context = new ServletContextHandler();
    context.setErrorHandler(errorHandler);
    context.addServlet(MyCustomErrorServlet.class, "/error");
    // etc ...
    

    另外值得注意的是,Jetty 附带一个 RequestLogHandler,它的最终目标相同(但使用 Jetty 处理程序,而不是通过过滤器)。

    【讨论】:

      【解决方案2】:

      这是我想出的解决方案:

      Server server = new Server(80);
      server.setStopAtShutdown(true);
      
      ServletContextHandler context = new ServletContextHandler();
      context.addServlet(Erreur500Servlet.class, "/generate-error-500");
      context.addServlet(AresServlet.class, "/ares/*");
      context.addFilter(RequestLoggingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
      
      server.setHandler(context);
      server.start();
      server.join();
      

      【讨论】:

      • 不要使用.add*WithMapping() 方法,使用普通的addServlet().addFilter() 方法来保持向前兼容。
      • 不要忘记.addServlet(DefaultServlet.class, "/"),否则您将无法获得静态内容处理、错误处理或调度程序功能。
      猜你喜欢
      • 2013-11-01
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-21
      • 2016-07-10
      • 2021-09-22
      • 2017-07-17
      相关资源
      最近更新 更多