【问题标题】:jersey 2.x dependency injectionjersey 2.x 依赖注入
【发布时间】:2015-05-08 06:08:29
【问题描述】:

您好,我在将以下代码从 jersey 1.x 移动到 jersey 2.x 时遇到问题

@Provider
public class LocaleProvider
      extends AbstractHttpContextInjectable<Locale>
      implements InjectableProvider<Context, Type> {

    @Override
    public Injectable<E> getInjectable(ComponentContext ic, Context a, Type c) {
        if (c.equals(Locale.class)) {
            return this;
        }

        return null;
    }

    @Override
    public ComponentScope getScope() {
        return ComponentScope.PerRequest;
    }

    @Override
    public Locale getValue(HttpContext c) {
        final Locales locales = c.getRequest().getAcceptableLanguages();
        if (locales.isEmpty()) {
          return Locale.US;
        }
        return locales.get(0);
    }
}

我也知道 HK2 在 Jersey 2.0 中可用,但我似乎找不到有助于 Jersey 2.0 集成的文档。

【问题讨论】:

    标签: java jersey-2.0 hk2


    【解决方案1】:

    如果您要使用@Context 注释,您真正需要做的就是实现一个Factory&lt;T&gt;,该Factory&lt;T&gt; 由您要注入的类型参数化。您甚至可以将其他标准可注入对象注入Factory,例如HttpServletRequestContainerRequestContextHttpHeaders 等。例如,为了匹配上面示例中发生的事情

    import java.util.List;
    import java.util.Locale;
    import javax.inject.Inject;
    import javax.ws.rs.core.HttpHeaders;
    import org.glassfish.hk2.api.Factory;
    
    public class LocaleFactory implements Factory<Locale> {
    
        private final HttpHeaders headers;
    
        @Inject
        public LocaleFactory(HttpHeaders headers) {
            this.headers = headers;
        }
    
        @Override
        public Locale provide() {
            List<Locale> acceptableLanguges = headers.getAcceptableLanguages();
    
            if (acceptableLanguges.isEmpty()) {
                return Locale.US;
            }
    
            if ("*".equals(acceptableLanguges.get(0).toString())) {
                return Locale.US;
            }
    
            return acceptableLanguges.get(0);
        }
    
        @Override
        public void dispose(Locale t) { /* Do nothing */ }
    }
    

    然后你需要绑定工厂。例如在您的ResourceConfig。您可以在那里设置范围,如示例中的getScope()。目前支持SingletonRequestScopedPerLookup(如果未指定,则为默认)

    @ApplicationPath("/api")
    public class AppConfig extends ResourceConfig {
    
        public AppConfig() {
            packages("packages.to.scan");
    
            register(new AbstractBinder(){
                @Override
                public void configure() {
                    bindFactory(LocaleFactory.class).to(Locale.class)
                                             .in(RequestScoped.class);
                }
            });
        }
    }
    

    如果您使用的是 web.xml,那么您可以创建一个Feature 并在那里注册AbstractBinder,作为seen here

    之后,你就可以注入它了

    @GET
    public Response getLocale(@Context Locale locale) {
    

    如果您想使用自定义注解,则需要为自定义注解实现InjectionResolver。你可以看到一个完整的例子here,并在Jersey documentation - Defining Custom Injection Annotation阅读更多内容

    【讨论】:

    • 在上面的代码中无法自动装配 headers bean
    • 是什么让你这么说?我在发布之前测试了上面的代码。我使用 Jersey 2.17(最新)进行测试。你做了什么与上面的代码不同的事情吗?
    • 其实我用的是dropwizard 0.8.1版本
    • 应该没问题。你env.jersey().register(new AbstractBinder(){...});了吗?
    • 是的,我已经完成了 env.jersey().getResourceConfig().register(new AbstractBinder(){ @Override public void configure() { bindFactory(LocaleFactory.class).to(Locale.class) .in(RequestScoped.class); } });
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多