当前位置: 首页 > 知识库问答 >
问题:

动态注册资源的Jersey web应用程序

阴永逸
2023-03-14

我有一个web应用程序,它将从jar文件动态加载其资源。

我必须如何重新编写加载和注册资源并启动服务器的主类,以便它在web应用程序内部工作?

我目前定义了一个javax.ws.rs.core.application,它在标记为@PostConstruct方法中加载资源。虽然这是有效的,但它会随着每个请求初始化。

我尝试将javax.inject.singleton添加到应用程序中,但这导致了错误:

java.lang.IllegalStateException: Unable to perform operation: post construct on com.test.server.IntegrationServer
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:392)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:83)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:71)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:122)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2020)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:766)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:705)
at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:385)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:342)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:392)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:177)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:369)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)

我的做法是完全错误的吗?或者如何创建这样一个系统,作为可部署的war运行?

*编辑*

通过使用ServletContextListener,我可以解决多个init调用,但我的资源没有加载。

@Path("test")

应用程序现在加载这个文件位置,并通过ServiceLoader加载所有MarkerInterface类并将它们注册。

我有

@WebListener
public class IntegrationServer extends ResourceConfig implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
    LOGGER.info(() -> "CONTEXT INIT");
    try {
        register(JacksonFeature.class);
        // wrapper for the ServiceLoader implementation
        this.serviceLoader = new IntegrationServiceLoader();
       this.serviceLoader.loadIntegrations(MarkerInterface.class, gce -> {
            LOGGER.info(() -> "Adding " + gce.getClass() + " to Server");
            register(gce.getClass());
        });
    }
    catch (IOException e) {
        LOGGER.log(Level.SEVERE, e, () -> "Failed to init integration server");
    }
}

}

当在tomcat上将其部署为server.war时,我在日志中看到了注册输出,但当我调用HTTP://localhost:8080/server/test/get时,我得到了HTTP状态404-未找到。

我的web.xml看起来像

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

**编辑2***

关于这个讨论,请参阅CássioMazzochiMolin的答案。

Builder{names=[com.test.server.TestResource], path='backend', methodBuilders=[], childResourceBuilders=[Builder{names=[[unnamed]], path='info', methodBuilders=[org.glassfish.jersey.server.model.ResourceMethod$Builder@819f71f], childResourceBuilders=[], childResources=[], resourceMethods=[], subResourceLocator=null, handlerClasses=[], handlerInstances=[], parentResource=Builder{names=[com.cetrea.qa.server.TestResource], path='backend'}, extended=false}], childResources=[Resource{"achievements", 3 child resources, 0 resource methods, 0 sub-resource locator, 1 method handler classes, 0 method handler instances},

共有1个答案

岳志义
2023-03-14

Jersey提供了一个API用于以编程方式构建资源。

根据文档,resource类是编程资源建模API的主要入口点,该API提供了以编程方式扩展现有JAX-RS注释资源类或构建Jersey运行时可能使用的新资源模型的能力。

请查看文档提供的示例

@Path("hello")
public class HelloResource {

     @GET
     @Produces("text/plain")
     public String sayHello() {
         return "Hello!";
     }
}
// Register the annotated resource.
ResourceConfig resourceConfig = new ResourceConfig(HelloResource.class);

// Add new "hello2" resource using the annotated resource class
// and overriding the resource path.
Resource.Builder resourceBuilder =
        Resource.builder(HelloResource.class, new LinkedList<ResourceModelIssue>())
        .path("hello2");

// Add a new (virtual) sub-resource method to the "hello2" resource.
resourceBuilder.addChildResource("world").addMethod("GET")
        .produces("text/plain")
        .handledBy(new Inflector<Request, String>() {
                @Override
                public String apply(Request request) {
                    return "Hello World!";
                }
        });

// Register the new programmatic resource in the application's configuration.
resourceConfig.registerResources(resourceBuilder.build());

下表说明了上面示例中配置的应用程序所支持的请求和提供的响应:

 Request              |  Response        |  Method invoked
----------------------+------------------+--------------------------
 GET /hello           | "Hello!"         | HelloResource.sayHello()
 GET /hello2          | "Hello!"         | HelloResource.sayHello()
 GET /hello2/world    | "Hello World!"   | Inflector.apply()

要了解更多细节,请查看泽西文件。

 类似资料:
  • void register_resource(string name, array resource_funcs) Use this to dynamically register a resource plugin with Smarty. Pass in the name of the resource and the array of PHP functions implementing i

  • 本文向大家介绍Oracle Listener 动态注册 与 静态注册,包括了Oracle Listener 动态注册 与 静态注册的使用技巧和注意事项,需要的朋友参考一下 一.什么是注册 注册就是将数据库作为一个服务注册到监听程序。客户端不需要知道数据库名和实例名,只需要知道该数据库对外提供的服务名就可以申请连接到数据库。这个服务名可能与实例名一样,也有可能不一样。   在数据库服务器启动过程中,

  • 本文向大家介绍Oracle静态注册与动态注册详解,包括了Oracle静态注册与动态注册详解的使用技巧和注意事项,需要的朋友参考一下 一、概述:   Oracle的注册就是将数据库作为一个服务注册到监听程序。客户端不需要知道数据库名和实例名,只需要知道该数据库对外提供的服务名就可以申请连接到这个数据库。这个服务名可能与实例名一样,也有可能不一样。   在数据库服务器启动过程中,数据库服务器会向监听程

  • 问题内容: 我想让服务提供以下代码中的资源: 然后,当使用该操作时,我想动态传递一个HTTP标头,这意味着它可能随每次调用而改变。这是一个示例,在控制器中,请参见代码中的注释: 您知道直接或通过技巧做到这一点的方法吗? 最后的想法 接受的答案不能完全回答问题,因为标头不是完全动态的,因为工厂实际上返回了工厂(!),而我的代码中不是这种情况。 由于$ resource是工厂,因此无法使其动态化。 最

  • 作者:陈希章 发表于2017年3月22日 在此前的文章中,我给大家介绍了分别用Graph 浏览器以及第三方工具(POSTMAN)快速体验Microsoft Graph的功能,其中有一个重要的环节就是,开发人员需要访问Microsoft Graph的话,其实是事先需要注册一个应用程序的。Graph 浏览器是特例,因为这个应用程序是微软官方注册好的。而大家在POSTMAN这篇文章中已经看到我注册的自定