使用内置的Jersey依赖项注入在Jersey 2中创建简单的单例类很麻烦 [英] Trouble creating a simple singleton class in Jersey 2 using built-in Jersey dependency injection
问题描述
在使用Jersey 2(2.7)和仅Jersey内置的HK2依赖项注入时,很难实现单例类的非常基本的实现.我正在Tomcat上运行它.
I am having trouble getting a very basic implementation of a singleton class off the ground with Jersey 2 (2.7) and only Jersey's built-in HK2 dependency injection. I am running this on Tomcat.
我的目标是创建支持类的单例实例,该类将被各种Web服务方法使用.我在构造函数注入,方法注入和注释类成员之间没有强烈的偏好(就像我在下面所做的那样).
My goal is to create a singleton instance of a support class that will be used by various web service methods. I don't have a strong preference between constructor injection, method injection, and annotating a class member (as I do below).
这是我的单身班:
package singletest;
import javax.inject.Singleton;
@Singleton
public class JustOne {
private int secretNumber = 0;
public void hitMe(int input) {
secretNumber += input;
}
@Override
public String toString() {
return String.format("{ \"secretNumber\": %s }", secretNumber);
}
}
这是我的应用程序类:
package singletest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
@ApplicationPath("/*")
public class MainApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
return classes;
}
@Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
singletons.add(new JustOneProvider());
return singletons;
}
}
这是我的Provider/ContextResolver类:
Here is my Provider/ContextResolver class:
package singletest;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class JustOneProvider implements ContextResolver<JustOne> {
private static JustOne justOne = new JustOne();
@Override
public JustOne getContext(Class<?> type) {
return justOne;
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>singletest.MainApplication</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>singletest.MainApplication</param-value>
</init-param>
<!-- pass to next filter if Jersey/App returns 404 -->
<init-param>
<param-name>jersey.config.servlet.filter.forwardOn404</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>singletest.MainApplication</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
我打算在其中注入JustOne类的单例实例的资源:
The resource where I intend to inject the singleton instance of my JustOne class:
package singletest;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/test")
public class TestResource {
@Inject
private JustOne justOne;
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@Path("/func1/{input}")
public Response func1(@PathParam("input") int input) {
justOne.hitMe(input);
String responseData = justOne.toString();
return Response.ok(responseData).build();
}
}
在泽西岛部署/初始化战争时会发出此警告:
This warning is raised when the war is deployed/initialized in Jersey:
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.7 ${buildNumber}...
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.internal.inject.Providers checkProviderRuntime
WARNING: A provider java.lang.Class registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider java.lang.Class will be ignored.
调用此Web服务时出现错误:
And the error I get when I call this web service:
type Exception report
message A MultiException has 3 exceptions. They are:
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=JustOne,parent=TestResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,58952407)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of singletest.TestResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on singletest.TestResource
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:333)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
因此,我明白了:hk2没有获得足够的信息来创建/绑定JustOne实例和/或查找/使用我的JustOneProvider.我确定我缺少一些基本的知识.任何指导将不胜感激.
So, I get it: hk2 isn't getting enough information to create/bind a JustOne instance and/or find/use my JustOneProvider. I'm sure I'm missing something basic. Any guidance would be appreciated.
推荐答案
好的,在花了非常健康的时间后,我开始使用它了.
Okay, after spending a very healthy chunk of time on this, I got it working.
我使用了HK2 AbstractBinder和JAX-RS功能(javax.ws.rs.core.Feature).
I used an HK2 AbstractBinder and JAX-RS Feature (javax.ws.rs.core.Feature).
事实证明,不需要Provider/ContextResolver.
It turned out that no Provider/ContextResolver was required.
应用程序:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
@ApplicationPath("/*")
public class MainApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
classes.add(JustOneFeature.class);
return classes;
}
}
单身班:
public class JustOne {
private int secretNumber = 0;
public int getSecretNumber() {
return secretNumber;
}
public void bumpSecretNumber() {
secretNumber += 1;
}
}
活页夹:
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class JustOneBinder extends AbstractBinder {
@Override
protected void configure() {
bind(new JustOne()).to(JustOne.class);
}
}
功能:
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
public class JustOneFeature implements Feature {
@Override
public boolean configure(final FeatureContext context) {
context.register(new JustOneBinder());
return true;
}
}
注入单例的资源:
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/test")
public class TestResource {
@Inject
private JustOne justOne;
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@Path("/func1/{input}")
public Response func1(@PathParam("input") int input) {
justOne.bumpSecretNumber();
String responseData = String.format("{ \"result\": %s }", input + justOne.getSecretNumber());
return Response.ok(responseData).build();
}
}
这篇关于使用内置的Jersey依赖项注入在Jersey 2中创建简单的单例类很麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!