如何在 Jetty 8 中添加请求日志过滤器?
How to add a request logging filter in Jetty 8?
以下是我设置 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
首先,也是最重要的,Jetty 8 is EOL (End of Life)。
接下来,请使用更新版本的 Jetty,Jetty 8.0.1(目前)比当前稳定版本的 Jetty 落后大约 110 个版本。
现在,解释一下是怎么回事。
您正在直接使用 ServletHandler,这是一个内部 class 并不意味着直接实例化和访问,而是在最简单和天真的情况下。即一个只有 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 处理程序,而不是通过过滤器)。
这是我想出的解决方案:
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();
以下是我设置 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
首先,也是最重要的,Jetty 8 is EOL (End of Life)。
接下来,请使用更新版本的 Jetty,Jetty 8.0.1(目前)比当前稳定版本的 Jetty 落后大约 110 个版本。
现在,解释一下是怎么回事。
您正在直接使用 ServletHandler,这是一个内部 class 并不意味着直接实例化和访问,而是在最简单和天真的情况下。即一个只有 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 处理程序,而不是通过过滤器)。
这是我想出的解决方案:
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();