spring - 如何使用 Spring Boot 1.5.2 注入(inject) Jersey 端点接口(interface)的实现?

标签 spring spring-boot jersey jax-rs

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

我将以下内容添加到我的 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>

我的新 Jersey 配置如下所示:

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:

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

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

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 定义没有被采纳。

最佳答案

此问题在JAX-RS spec中进行了解释。参见第 3.6 节注释继承。

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.

If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the superclass or interface method are ignored. E.g.:

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

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

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

Conversely:

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

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.

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

我已经突出显示了重要的端口。为什么它不适合你应该很清楚。在 EndpointImpl 中,您重复了 @Context 注释,因此导致“父类(super class)或接口(interface)方法上的所有注释都被忽略”。。这包括@GET。因此,最终,这会导致该端点无法注册,因为端点需要 @METHOD

至于 block 引用中的最后一段,您可以选择跟随或不跟随它。我只是为了完整性才把它放在那里。

关于spring - 如何使用 Spring Boot 1.5.2 注入(inject) Jersey 端点接口(interface)的实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43266904/

相关文章:

spring-boot - cucumber +TestNG+Spring Boot

jersey - JAX-RS:如何在启动时运行方法(没有 servlet)

java spring框架知识巩固

java - 使用@Cacheable注解时加载ApplicationContext失败

java - 使用 LocalDate 类型参数发送请求

java - 类文件版本 57.0,该版本的 Java 运行时仅识别 52.0 以下的类文件版本

集成测试期间未由 gradle 替换的 spring boot 值

java - 尝试 PUT 方法时出现错误 405 (Jersey/Java) : Method Not Allowed

java - 实现REST客户端的类加载问题

spring - 在我的 Spring 批处理中添加 maven 依赖项会出现特定错误