【问题标题】:CXF/Jetty equivalent of the following Jersey/Jetty codeCXF/Jetty 等效于以下 Jersey/Jetty 代码
【发布时间】:2015-01-18 14:19:08
【问题描述】:

我有一些带有 Jersey (2.7) 和 Jetty (9.2.5.v2014112) 的测试代码,我正在尝试移植到 CXF (3.0.x) 和 Jetty(相同版本)。有一部分我想不通,相当于下面的rc.register(resource) 行:

    ServletContextHandler sch = new ServletContextHandler();
    sch.setContextPath("/xxx");

    resource = new TheResource();
    ResourceConfig rc = new ResourceConfig();
    rc.register(resource);

    ServletContainer sc = new ServletContainer(rc);        
    ServletHolder holder = new ServletHolder(sc);
    sch.addServlet(holder, "/*");

    Server server = new Server(port);
    server.setHandler(sch);
    server.start();
    server.join();

对于 CXF/Jetty 案例,我知道我需要执行以下操作:

CXFNonSpringJaxrsServlet context = new CXFNonSpringJaxrsServlet();
// EQUIVALENT OF:
//     ResourceConfig rc = new ResourceConfig();
//     rc.register(myresource)
//     SOMETHING.setResourceConfig(rc)
ServletHolder holder = new ServletHolder(context);
ServletContextHandler handler = new ServletContextHandler("/restroot");
handler.addServlet(holder, "/*");

// Using ContextHandlerCollection cos my jetty needs to serve more
// than just this REST service
ContextHandlerCollection collection = new ContextHandlerCollection();
collection.addHandler(handler);

Server server = new Server(8080);
server.setHandler(collection);
server.start();
server.join();

有人知道如何/如果这可能吗?

只是为了澄清我在这里尝试做的事情:我正在尝试在嵌入式 Jetty 实例上发布 JAX-RS 服务,并且我需要 完全控制 JAX 的生命周期-RS 豆。

马丁

【问题讨论】:

    标签: java jersey jetty cxf jax-rs


    【解决方案1】:

    从 CXF 版本 3.0.4 开始,CXFNonSpringJaxrsServlet 上有额外的构造函数,使这变得更容易:

    public SNAPSHOTApp(int port) throws Exception {
        resource = new TheResource();
        Set<Object> resourceSingletons = new HashSet<>();
        resourceSingletons.add(resource);
    
        CXFNonSpringJaxrsServlet context = new CXFNonSpringJaxrsServlet(resourceSingletons);
    
        ServletHolder servlet = new ServletHolder(context);
        ServletContextHandler handler = new ServletContextHandler();
        handler.addServlet(servlet, "/*");
        handler.setContextPath("/snapshot");
    
        Server server = new Server(port);
        server.setHandler(handler);
        server.start();
        server.join();
    }
    

    非常感谢 @Sergey Beryozkin 根据我在 CXF 用户邮件列表中的问题添加此内容。

    【讨论】:

      【解决方案2】:

      查看 CXFNonSpringJaxrsServlet 的源代码,它是通过 web.xml 中的 init 参数配置的。但是,您当然可以随意覆盖该功能

      【讨论】:

      • 通过 web.xml 进行的配置将永远无法指定 特定的 bean 实例 作为将传入请求分派到...的对象...真的工作。只是补充一下,我确实浏览了 CXF 源代码,但还没有找到一种方法来完成这项工作。这就是我在这里问的原因。
      • servlet 类中的 getResourceProviders 方法创建资源类到提供者的映射。您应该扩展 servlet 类以覆盖此方法以返回带有您自己的提供程序的映射。
      • 根据您对“覆盖 getResourceProviders()”的提示找到了一个似乎可行的解决方案...
      【解决方案3】:

      我已经设法让一些工作:

      • 扩展CXFNonSpringJaxrsServlet
      • 覆盖getResourceProviders()
      • 提供我自己的ResourceProvider 实现

      这一切看起来有点复杂,我觉得CXF中应该有一个标准的API,但无论如何,这是我的解决方案:

      public class TheApp {
          private static final Logger LOG = LoggerFactory.getLogger(TheApp.class);
      
          TheResource resource;
      
          public static class BeanResourceProvider implements ResourceProvider {
              private final Object theBean;
      
              public BeanResourceProvider(Object theBean) {
                  this.theBean = theBean;
              }
      
              @Override
              public Object getInstance(Message m) {
                  return theBean;
              }
      
              @Override
              public void releaseInstance(Message m, Object o) {            
              }
      
              @Override
              public Class<?> getResourceClass() {
                  return theBean.getClass();
              }
      
              @Override
              public boolean isSingleton() {
                  return true;
              }
      
          };
      
          public TheApp(int port) throws Exception {
              resource = new TheResource();
      
              CXFNonSpringJaxrsServlet context = new CXFNonSpringJaxrsServlet() {
                  public void configureSingleton(Object o) {
                      LOG.info("configureSingleton() called");
                  }
      
                  public Map<Class<?>, ResourceProvider>
                          getResourceProviders(ServletConfig servletConfig,
                                  Map<Class<?>, Map<String, List<String>>> resourceClasses) throws ServletException {
                      LOG.info("getResourceProviders called");
      
                      Map<Class<?>, ResourceProvider> map = new HashMap<Class<?>, ResourceProvider>();
                      for (Map.Entry<Class<?>, Map<String, List<String>>> entry : resourceClasses.entrySet()) {
                          Class<?> c = entry.getKey();
                          LOG.info("getting provider for {}", c.getName());
                          map.put(c, new BeanResourceProvider(resource));
                      }
                      return map;
                  }
              };
      
              ServletHolder holder = new ServletHolder(context);
              holder.setInitParameter("jaxrs.serviceClasses", "com.test.cxfjetty.TheResource");
      
              ServletContextHandler handler = new ServletContextHandler();
              handler.addServlet(holder, "/*");
              handler.setContextPath("/theroot");
      
              Server server = new Server(port);
              server.setHandler(handler);
              server.start();
              server.join();
          }
      
          public static void main(String[] args) throws Exception {
              TheApp app = new TheApp(8122);        
          }
      }
      

      这是一个有趣的练习……

      【讨论】:

        猜你喜欢
        • 2012-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多