与泽西岛的宁静服务接口

时间:2013-11-22 15:18:01

标签: web-services jetty jackson jersey-2.0 jetty-8

我可以使用接口和实现类创建一个restful服务吗?和所有JAX-RS相关的导入进入界面?我正在使用jersey2.4和jetty8.1。

这是我的界面:

MyService.java

package foo.bar; 

@Path("/abc")
public interface MyService {

     @GET
     @JSONP
     @Path("/method/{id}")
     public MyResponse getStuff(@PathParam("id") Integer id);

}

MyServiceImpl.java

package foo.bar.impl;

public class MyServiceImpl implements MyService {

     public MyServiceImpl() {}

     @Override
     public MyResponse getStuff(Integer id) {
         // do stuff
         return MyResponse;
     }
}

这是我的web.xml:

<servlet>
    <servlet-name>Scivantage REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>foo.bar</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

我注册了这个服务提供程序包(foo.bar),但它抱怨说这个 - javax.servlet.ServletException:MultiException有1个例外。它们是:| 1。 java.lang.NoSuchMethodException:在foo.bar.MyService类中找不到合适的构造函数。|

当我尝试使用实现类包(foo.bar.impl)时,它抱怨说这个 - 我得到HTTP ERROR 404;什么都不做;控制台上没有例外

当我尝试两者时 - 它抱怨与上面相同:

javax.servlet.ServletException:MultiException有1个例外。它们是:| 1。 java.lang.NoSuchMethodException:在foo.bar.MyService类中找不到合适的构造函数。|

你能帮帮忙吗?我做错了什么?

5 个答案:

答案 0 :(得分:3)

虽然这是一年前发布的问题,但这是我在几次试验后遇到的解决方案(我正在使用jetty 9和jersey 2.13):而不是注释界面(使用@Path("/abc")),尝试注释实现类。我认为这很有道理,因为接口是“抽象的”,不应该绑定到物理路径。这样,界面可以在不同的路径中重复使用。

答案 1 :(得分:1)

如果要使用带有JAX-RS注释的接口,则无法再使用web.xml扫描包

<param-name>jersey.config.server.provider.packages</param-name>
<param-value>XXX</param-value>

您需要手动将接口与资源实现绑定

bind(YourResource.class).to(YourResourceImpl.class);

原因:

  

出于性能原因,我们决定在扫描期间忽略接口。我们还修复了Jersey不会尝试实例化接口的问题。

https://java.net/jira/browse/JERSEY-1004

答案 2 :(得分:0)

我也在努力解决“找不到合适的构造函数”的问题。我想将所有注释(包括@Path)放在我的界面上。我能够通过自己管理资源的生命周期来实现它,而不是让Jersey实例化它们。

例如,如果您有YourImplementation实现YourRestInterface,那么您可以执行类似的操作来向Jersey注册实现的实例:

public class RestConfig extends ResourceConfig {

    @Inject
    public RestConfig(ServiceLocator locator) {
        super();

        DynamicConfiguration c = Injections.getConfiguration(locator);
        Object implInstance = new YourImplementation();
        ServiceBindingBuilder<Object> bb = Injections.newFactoryBinder(new BeanFactory(locator, implInstance));
         // tell Jersey to use the factory below to get an instance of YourRestInterface.class
        bb.to(YourRestInterface.class);
        Injections.addBinding(bb, c);

            c.commit();
    }

    private static class BeanFactory implements Factory<Object> {

        private ServiceLocator locator;
        private Object bean;

        BeanFactory(ServiceLocator locator, Object bean)
        {
            this.locator = locator;
            this.bean = bean;
        }

        @Override
        public Object provide() {
               // have Jersey inject things annotated with @Context
            locator.inject(bean);
            return bean;
        }

        @Override
        public void dispose(Object instance) {
        }

    }
}

答案 3 :(得分:0)

在班级make geth中,有一个像这样的构造函数

ResourceConfig

构造函数创建一个使用给定资源/提供者类集初始化的新资源配置 因此,您可以扩展ResourceConfig(Class<?>... classes) 以注册实现类。

ResourceConfig

然后,配置public class RestConfig extends ResourceConfig { public RestConfig() { // register the implementation class super(MyServiceImpl.class); } }

web.xml

但最简单的方法是在<servlet> <servlet-name>Scivantage REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <!-- the path of RestConfig --> <param-value>foo.bar.RestConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 注册实现类。

web.xml

答案 4 :(得分:-1)

是的,您可以使用界面进行注释。在我们的应用程序中,我们以这种方式实现。以下引用取自Jersy specifications

  

JAX-RS注释可用于方法和方法参数   超类或实现的接口。这样的注释是   由相应的子类或实现类方法继承   前提是该方法及其参数没有任何JAX-RS   自己的注释。超类上的注释优先   在实现的接口上的那些。如果是子类或   实现方法有任何JAX-RS注释然后所有   超类或接口方法上的注释被忽略

我认为在您的情况下错误因为您可能错过了映射请检查。 <servlet-mapping> <servlet-name>api</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping>