如何使用 Spring Boot 1.5.2 注入 Jersey 端点接口的实现? [英] How to use Spring Boot 1.5.2 to inject implementations of Jersey endpoint interfaces?

查看:31
本文介绍了如何使用 Spring Boot 1.5.2 注入 Jersey 端点接口的实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Spring Boot 1.5.2 上,我正在缩减一个包含 Web 服务的大型 Web 应用程序,使其仅成为 Jersey Web 服务.因为 Web 服务已经有一套完整的由 Apache Wink 实现的 JAX-RS 注释,所以我决定使用 Spring + Jersey 而不是 Spring Rest.我发现了这个 spring-boot-jersey-sample 应用程序用作参考.我正在开发的应用程序与示例之间的最大区别在于我的端点定义分为接口和实现.

I am scaling back a large web application that included a web service to become only a Jersey web service, on Spring Boot 1.5.2. Because the web service already had a complete set of JAX-RS annotations implemented by Apache Wink, I decided to go with Spring + Jersey instead of Spring Rest. I found this spring-boot-jersey-sample application to use as a reference. The biggest difference between the application I'm working on and the sample is that my endpoint definitions are divided between interfaces and implementations.

我在 pom.xml 中添加了以下内容:

I added the following to my pom.xml:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jersey</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

我的新泽西配置如下所示:

My new Jersey Config looks like this:

package com.example.configuration;

import org.glassfish.jersey.server.ResourceConfig;
import com.example.EndpointImpl;
import org.springframework.stereotype.Component;

@Component
public class JerseyConfiguration extends ResourceConfig {
  public JerseyConfiguration() {
    registerEndpoints();
  }

  private void registerEndpoints() {
    register(EndpointImpl.class);     
  }
}

然后我有以下Application.java:

Then I have the following Application.java:

package com.example;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer{
  public static void main(String[] args) {
    new Application().configure(new SpringApplicationBuilder(Application.class)).run(args);
  }
}

端点被定义为接口和实现,如下所示(减去导入):

The endpoints are defined as an interface and an implementation, like this (minus imports):

public interface Endpoint {
  @GET
  @Produces({MediaType.APPLICATION_JSON})
  public Response getHello(@Context ServletContext sc, @Context HttpServletRequest req, @Context HttpHeaders httpHeaders) ;
}

@Path("")
@Component
public class EndpointImpl implements Endpoint {
  @Override
  public Response getHello(@Context ServletContext sc, @Context HttpServletRequest req,
      @Context HttpHeaders httpHeaders)  {
      return Response.ok("hello").build();
  }
}

当我启动我的应用程序时,我看到消息说 Tomcat 已启动,其中包括一个消息说 Mapping servlet: 'com.example.configuration.JerseyConfiguration' to [/*].但是,当我使用网络浏览器访问/时,我收到 404 Not Found 错误.看起来 GET 定义并没有被采纳.

When I start up my application, I see messages saying Tomcat has started up, including a messges saying Mapping servlet: 'com.example.configuration.JerseyConfiguration' to [/*]. However, when I go to / with a web browser, I get a 404 Not Found error. It doesn't look like the GET definition is getting picked up.

推荐答案

这个问题在JAX-RS 规范 in § 3.6 Annotation Inheritance.

This problem is explained in the JAX-RS spec in § 3.6 Annotation Inheritance.

JAX-RS 注解可用于超类或已实现接口的方法和方法参数.此类注解由相应的子类或实现类方法继承前提是该方法及其参数没有自己的任何 JAX-RS 注解.

JAX-RS annotations may be used on the methods and method parameters of a super-class or an implemented interface. Such annotations are inherited by a corresponding sub-class or implementation class method provided that the method and its parameters do not have any JAX-RS annotations of their own.

如果子类或实现方法有任何 JAX-RS 注释,则忽略超类或接口方法上的所有注释.例如:

public interface ReadOnlyAtomFeed {
  @GET @Produces("application/atom+xml")
  Feed getFeed();
}

@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {
  public Feed getFeed() {...}
}

在上面,ActivityLog.getFeed从接口继承了@GET@Produces注解.

In the above, ActivityLog.getFeed inherits the @GET and @Produces annotations from the interface.

反之:

@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {
  @Produces("application/atom+xml")
  public Feed getFeed() {...}
}

在上面,ReadOnlyAtomFeed.getFeed 上的 @GET 注释不被 ActivityLog.getFeed 继承,它需要它自己的请求方法指示符 (@GET),因为它重新定义了 @Produces 注释.

In the above, the @GET annotation on ReadOnlyAtomFeed.getFeed is not inherited by ActivityLog.getFeed and it would require its own request method designator (@GET) since it redefines the @Produces annotation.

为了与其他 Java EE 规范保持一致,建议始终重复注解,而不是依赖注解继承.

For consistency with other Java EE specifications, it is recommended to always repeat annotations instead of relying on annotation inheritance.

我已经强调了重要的端口.应该很清楚为什么它不适合你.在您的EndpointImpl 中,您重复了@Context 注释,因此导致忽略超类或接口方法上的所有注释".这包括 @GET.所以最终,这会导致该端点没有被注册,因为端点需要一个 @METHOD.

I've highlighted the important ports. It should be pretty clear why it isn't working for you. In your EndpointImpl, you have repeated the @Context annotations, therefore causing "all of the annotations on the superclass or interface method are ignored". This include the @GET. So ultimately, this causes that endpoint not to be registered, as endpoints require a @METHOD.

至于块引用中的最后一段,您可以选择是否遵循它.我只是为了完整性把它扔在那里.

As far as the last paragraph in the blockquote, you can choose to follow it or not. I just threw it in there just for completeness.

这篇关于如何使用 Spring Boot 1.5.2 注入 Jersey 端点接口的实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆