创建样板项目以向启用JPA的数据库公开RESTful API。它使用以下版本:
- 春季3.2.6
- Hibernate 4.3.0
- 泽西岛2.5.1
我终于能够让他们一起玩,但仍然有一些问题。这是最令人费解的事情之一(参见REST服务类的摘录)
@Service
@Path("resources")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Transactional
public class ResourceServices extends AbstractServices<Resource> {
...
}
如果使用@Service注释类,则忽略@Transactional注释并且不启动方法的事务。但是,当更改为@Component时,一切正常。想不通,为什么。
可以看到整个项目here
答案 0 :(得分:9)
我也对此感到困惑,但终于弄明白了。
jersey-spring模块只会从您的上下文中导入@Component
个bean。确切地说是beanClass.isAnnotationPresent(Component.class)
中的SpringComponentProvider
支票。
否则它似乎只创建了半生不熟的请求范围的bean实例(我在服务构造函数中用Thread.dumpStack
跟踪它)。他们似乎有依赖注入,但不是AOP。
泽西岛问题跟踪器中已有许多JIRA项目:JERSEY-2495,JERSEY-2059,JERSEY-2301
更新:我已经合并了这些请求,这应该在Jersey 2.11中修复。
答案 1 :(得分:2)
正如在另一个答案中提到的,SpringComponentProvider获取Jersey创建的bean并在Spring上下文中注册它,但在这种情况下你不会得到Spring AOP。
我设法让它以相反的方式使用AOP:bean是由Spring创建的(因此实际上它是AOP的代理)然后在Jersey中注册。
但我必须修复Jersey的ModelHelper类中的错误:https://github.com/jersey/jersey/pull/90
如果没有这个修复,Jersey无法在Spring代理中找到@Path注释。
这是基本结构:
public class MyApplication extends ResourceConfig {
@Inject
public MyApplication(ServletContext servletContext) {
super(JSONController.class, XSSSecurityFilter.class, JacksonFeature.class);
WebApplicationContext springFactory = WebApplicationContextUtils.getWebApplicationContext(servletContext);
// TODO: scan entire Spring factory for beans annotated with @Path and register them, so we don't need to do this manually.
// Letting Jersey register the beans does not work because in this case Spring will not intercept the calls.
register(springFactory.getBean(UserServiceFacade.class));
}
}
答案 2 :(得分:0)
原因是你的Spring有一个不同的注释容器,而且jersey有一个不同的注释容器,为了在spring容器中访问你的bean你可以参考下面的代码;
我不同意你使用的版本,我没有尝试使用最新版本的球衣:
通过web.xml加载spring,如下所示为普通弹簧配置:
<servlet>
<servlet-name>project-spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:project-spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>project-spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
现在通过应用程序加载你的球衣资源,如下所示:
@ApplicationPath("/rest")
public class ResourceLoader extends Application
{
/* (non-Javadoc)
* @see javax.ws.rs.core.Application#getClasses()
*/
@Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
loadResourceClasses(classes);
return classes;
}
private void loadResourceClasses(Set<Class<?>> classes)
{
classes.add(StudentResource.class);
}
}
然后在你的资源中:
@Path("student")
class StudentResource
{
private StudentService studentService;
StudentResource(@Context ServletContext servletContext)
{
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
this.studentService= applicationContext.getBean(StudentService .class);
}
}
你可以使用Spring的WebApplicationContextUtils传递servlet上下文来获取你的ApplicationContext,其中所有bean已经被初始化,并获取你的bean