ric*_*icb 12 singleton dependency-injection jax-rs jersey-2.0 hk2
我无法使用Jersey 2(2.7)和Jersey内置的HK2依赖注入来实现一个非常基本的单例类实现.我在Tomcat上运行它.
我的目标是创建将由各种Web服务方法使用的支持类的单例实例.我没有强烈的偏好在构造函数注入,方法注入和注释类成员之间(如下所示).
这是我要成为的单身人士课程:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的应用程序类:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的Provider/ContextResolver类:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
我打算注入JustOne类的单例实例的资源:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
在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.
Run Code Online (Sandbox Code Playgroud)
我调用这个Web服务时得到的错误:
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)
Run Code Online (Sandbox Code Playgroud)
所以,我明白了:hk2没有获得足够的信息来创建/绑定JustOne实例和/或查找/使用我的JustOneProvider.我确定我遗漏了一些基本的东西.任何指导将不胜感激.
小智 19
bind(JustOne.class).to(JustOne.class).in(Singleton.class);
Run Code Online (Sandbox Code Playgroud)
是最重要的部分.如果没有"in(Singleton.class)",将创建JustOne的多个实例.
ric*_*icb 14
好吧,在花了一大笔时间在这上面后,我开始工作了.
我使用了HK2 AbstractBinder和JAX-RS功能(javax.ws.rs.core.Feature).
事实证明,不需要Provider/ContextResolver.
应用:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
待单身类:
public class JustOne {
private int secretNumber = 0;
public int getSecretNumber() {
return secretNumber;
}
public void bumpSecretNumber() {
secretNumber += 1;
}
}
Run Code Online (Sandbox Code Playgroud)
活页夹:
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class JustOneBinder extends AbstractBinder {
@Override
protected void configure() {
bind(new JustOne()).to(JustOne.class);
}
}
Run Code Online (Sandbox Code Playgroud)
特征:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
获取单例注入的资源:
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();
}
}
Run Code Online (Sandbox Code Playgroud)