我在 Spring Boot 1.5.2 上将一个包含 Web 服务的大型 Web 应用程序缩减为仅一个 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 [/*]
。但是,当我使用 Web 浏览器访问/时,出现 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 onReadOnlyAtomFeed.getFeed
is not inherited byActivityLog.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/44031946/