13

我无法使用 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);
    }
}

这是我的应用程序类:

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 类:

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;
    }
}

网页.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 类的单例实例的资源:

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();
    }
}

在泽西岛部署/初始化战争时会发出此警告:

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.

当我调用这个网络服务时,我得到的错误:

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。我确定我缺少一些基本的东西。任何指导将不胜感激。

4

2 回答 2

19
bind(JustOne.class).to(JustOne.class).in(Singleton.class);     

是最重要的部分。如果没有“in(Singleton.class)”,将创建多个 JustOne 实例。

于 2014-11-11T00:48:54.407 回答
15

好的,在花了很多时间在这上面之后,我让它工作了。

我使用了 HK2 AbstractBinder 和 JAX-RS Feature (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;
    }

}

准单身人士班级:

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();
    }
}
于 2014-04-28T04:51:47.493 回答