Jersey:ContainerRequestFilter没有获得Context ServletRequest [英] Jersey: ContainerRequestFilter does not get Context ServletRequest
问题描述
要查看此问题的完整代码,请参阅此github
To see the full code for this issue, please see this github
https://github.com/mobiusinversion/web-application
我还创建了这个Jersey Jira
I also created this Jersey Jira
https://java.net/jira/browse/JERSEY-2851
我正在使用Jersey 2.15处理 ContainerRequestFilter
。这是一个嵌入式Jetty应用程序,它被遮蔽成一个罐子。
I am working on a ContainerRequestFilter
using Jersey 2.15. This is an embedded Jetty app which is shaded into a single jar.
在Jetty启动器(主类)中:
In the Jetty starter (main class):
public static void main(String[] args) throws Exception {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
Server jettyServer = new Server(10005);
jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, ServletConstants.COMPONENT_SCAN_ROOT);
try {
System.out.println("Starting Jetty");
jettyServer.start();
System.out.println("Jetty Started");
jettyServer.join();
} catch (Exception e) {
System.out.println("Could not start server");
e.printStackTrace();
} finally {
jettyServer.destroy();
}
}
我有一个通过提供商包含的过滤器
I have a filter which is included via a provider
@Provider
public class ExampleProvider implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
ExampleFilter exampleFilter = new ExampleFilter();
featureContext.register(exampleFilter);
}
}
然后在过滤器中:
public class ExampleFilter implements ContainerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(ExampleFilter.class);
@Context
private HttpServletRequest servletRequest;
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
logger.info("IP ADDRESS " + servletRequest.getRemoteAddr());
// ...
}
}
但是这会产生 NullPointerException
:
Caused by: java.lang.NullPointerException: null
at com.example.filters.ExampleFilter.filter(ExampleFilter.java:29)
at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:131)
at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:67)
我做错了什么以及如何解决这个问题?
What am I doing wrong and how do I fix this?
更新:包括为Jetty和Jersey指定的pom
UPDATE: Including pom entried for Jetty and Jersey
<properties>
<jersey.version>2.15</jersey.version>
<jetty.version>9.2.6.v20141205</jetty.version>
</properties>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<!-- Jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${jetty.version}</version>
</dependency>
推荐答案
错误在于你手动创建在 ExampleRequestFilterProvider
中的 ExampleRequestLoggingFilter
的实例。依赖注入仅适用于由容器本身创建和管理的实例,例如 ExampleRequestFilterProvider
。这解释了为什么 @Context
注入在手动创建的实例中似乎不起作用。
The mistake was that you manually created an instance of ExampleRequestLoggingFilter
inside the ExampleRequestFilterProvider
. Dependency injection only works on instances created and managed by the container itself, such as the ExampleRequestFilterProvider
. This explains why @Context
injection didn't seem to work in your manually created instance.
解决方案是将注入点移动到 ExampleRequestFilterProvider
,然后将其传递给 ExampleRequestLoggingFilter
的构造函数。
A solution would be to move the injection point to the ExampleRequestFilterProvider
and then pass it through to the constructor of ExampleRequestLoggingFilter
.
@Provider
public class ExampleRequestFilterProvider implements DynamicFeature {
@Context
private HttpServletRequest request;
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
ExampleRequestLoggingFilter exampleRequestLoggingFilter = new ExampleRequestLoggingFilter(request);
featureContext.register(exampleRequestLoggingFilter);
}
}
我在这里测试过(感谢Git项目!)它对我有用。
I tested it here (kudos to the Git project!) and it worked for me.
请注意,你在这里没有传递实际的 HttpServletRequest
实例,但是一个容器管理代理,它在每次方法调用时进一步委托给实际实例,所以这里没有什么可担心的完整性和线程安全。
Note that you're here not passing the actual HttpServletRequest
instance, but a container managed proxy which delegates further to the actual instance on every method call, so there's nothing to worry as to integrity and threadsafety here.
这篇关于Jersey:ContainerRequestFilter没有获得Context ServletRequest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!