RESTEasy不会使用自定义Spring ContextLoader映射我的Spring bean

dav*_*000 6 java spring spring-mvc resteasy

  • RESTEasy 2.0.1GA
  • Java 1.6
  • Spring 3.0.3

我已尽力而为,无法做出正在发生的事情.我有一个Spring MVC应用程序,但是我想在Spring MVC应用程序之外提供一些RESTEasy端点,但是在同一容器中,最终能够连接相同的bean.

作为第一步,我只是试图在容器内部站起来RESTEasy,为Spring配置的bean提供请求.我已经从说明书中试过了样板,并尝试了手动设置,但无济于事.

@Resource
@Path("/")
public class NeighborComparison {

    private String foo;

    @GET @Path(value="customer") @Produces("text/plain")
    public String getNeighborComparison() {
        return "foo";
    }
}
Run Code Online (Sandbox Code Playgroud)

web.xml

<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/api</param-value>
</context-param>

<listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>

<!-- NOT configuring SpringContextLoaderListener because I declare my own, so if I do, everything
     blows up, plus  all it actually does is sanity check configuration -->
<listener>
    <listener-class>com.example.MyCustomContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>
Run Code Online (Sandbox Code Playgroud)

applicationContext.xml

<bean id="resteasy.providerFactory" class="org.jboss.resteasy.spi.ResteasyProviderFactory"
      factory-method="getInstance">
</bean>

<bean id="resteasy.dispatcher" class="org.jboss.resteasy.core.SynchronousDispatcher">
    <constructor-arg ref="resteasy.providerFactory"/>
</bean>

<bean id="resteasy.spring.bean.processor" class="org.jboss.resteasy.plugins.spring.SpringBeanProcessor">
    <description>
        Add Resources and @Providers to the appropriate places
        in Resteasy's infrastructure
    </description>
    <constructor-arg ref="resteasy.dispatcher"/>
</bean>

<bean id="neighborComparison" class="opower.api.customer.neighbor_comparison.NeighborComparison">
</bean>
Run Code Online (Sandbox Code Playgroud)

根据文档,我所要做的就是"通过分配org.jboss.resteasy.plugins.spring.SpringBeanProcessor的实例来手动注册RESTeasy BeanFactoryPostProcessor".我相信这个弹簧配置就是这样.

Jetty启动,应用程序上下文旋转没有问题.应用程序正常,但是当我

> curl -H"Accept: text/plain" localhost:8080/ei/api/customer
Run Code Online (Sandbox Code Playgroud)

("ei"是应用程序上下文).日志显示(仅此而且):

2011-03-29 16:44:24,153 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] PathInfo: /customer
2011-03-29 16:44:24,156 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] Failed executing GET /customer
org.jboss.resteasy.spi.NotFoundException: Could not find resource for relative : /customer of full path: http://localhost:8080/ei/api/customer
Run Code Online (Sandbox Code Playgroud)

即使我可以说服RESTEasy向我展示映射,但它似乎并没有发现我的bean.

如果我通过resteasy.resources上下文参数显式映射它,它可以工作,但显然无法访问自动连接的Spring bean.

还有什么我可以尝试的吗?我有整个RESTEasy代码库的调试日志,我没有收到任何消息.我也确认Spring实际上是在创建我的bean,所以只是RESTEasy没有找到它.

Oph*_*itz 8

您的资源类需要使用注释进行@Path注释,以便RESTeasy在引导期间接收它:

@Path("/customer")
@Resource
public class NeighborComparison {

    @GET @Path("/{customerId}") @Produces("text/plain")
    public String getNeighborComparison(@PathParam("customerId") long customerId) {
        return "foo";
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意@Path("/{customerId}}注释,如果没有这些注释,您的@PathParam参数将无法正确映射,从而导致非常详细的异常(以及客户端附带的500响应).假设RESTeasy当然接受了这项服务.

此外,如果您不使用RESTeasy SpringContextLoader,则必须确保您的SpringBeanProcessor实例已注册ApplicationContext.RESTeasy通过注册ApplicationListenerin 来代表它SpringContextLoader:

  ApplicationListener listener = new ApplicationListener() {
     public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
           ContextRefreshedEvent cre = (ContextRefreshedEvent) event;
           ConfigurableListableBeanFactory autowireCapableBeanFactory = (ConfigurableListableBeanFactory) cre
                 .getApplicationContext().getAutowireCapableBeanFactory();
           new SpringBeanProcessor(dispatcher, registry, providerFactory)
                 .postProcessBeanFactory(autowireCapableBeanFactory);
        }
     }
  };
  configurableWebApplicationContext.addApplicationListener(listener);
Run Code Online (Sandbox Code Playgroud)

如果使用自定义上下文加载器而不是 RESTEasy提供的加载器,则此代码必须出现在上下文加载器中的某处,以便所有内容都连接起来.有点费解,是的.它SpringBeanProcessor遍历所有Spring bean并向RESTeasy注册那些@Path在其层次结构中具有注释的类型(类型及其相应的接口).