如何使用Spring Boot 1.5.2注入Jersey终结点接口的实现? [英] How to use Spring Boot 1.5.2 to inject implementations of Jersey endpoint interfaces?
问题描述
在Spring Boot 1.5.2上,我正在缩减包含Web服务的大型Web应用程序,使其仅成为Jersey Web Service.因为该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>
我的新Jersey Config看起来像这样:
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 [/*]
的消息.但是,当我使用Web浏览器访问/时,出现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规范.
JAX-RS批注可以用于超类或已实现接口的方法和方法参数.此类注释由相应的子类或实现类方法继承,前提是该方法及其参数自己没有任何JAX-RS注释.
如果子类或实现方法具有任何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
继承,并且由于它重新定义了@Produces
批注,因此将需要其自己的请求方法标识符(@GET
). /strong>
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屋!