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

泽西2中的ResourceConfig类到底是什么?

岳昊空
2023-03-14

我见过很多泽西教程都是以类似这样的东西开头的

@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

而不解释ResourceConfig类的具体内容。那么在哪里可以找到它的文档、用法等呢?谷歌搜索“泽西资源Config”并没有得到任何官方文件。

  • 我可以在ResourceConfig的子类中做什么?
  • 我需要在某个地方注册ResourceConfig的子类以便可以找到它还是由Jersey自动检测?
  • 如果自动检测到子类,如果有ResourceConfig的多个子类,会发生什么情况?
  • resourceConfig的用途与web.xml文件相同吗?如果是这样,如果我的项目中同时包含这两个,会发生什么?其中一个优先于另一个吗?

共有1个答案

慎建本
2023-03-14

标准JAX-RS使用application作为配置类。resourceConfig扩展了application

配置Jersey(JAX-RS)有三种主要方式(在servlet容器中):

  1. 仅使用web.xml
  2. 同时使用web.xml和应用程序/ResourceConfig
  3. 仅使用@applicationpath注释的application/resourceConfig类。
<web-app>
    <servlet>
        <servlet-name>jersey-servlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.mypackage.to.scan</param-value>
        </init-param>
    </servlet>
    ...
    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
    ...
</web-app>

由于Jersey在servlet容器中运行,因此Jersey应用程序作为servlet运行是完全正确的。处理传入请求的Jersey Servlet是ServletContainer。因此这里我们将其声明为 。我们还配置了一个 ,告诉Jersey要扫描哪些包以查找我们的@path@provider类,以便它可以注册它们。

实际上,Jersey将创建一个resourceConfig实例,因为这是它用来配置应用程序的。然后它将注册它通过包扫描发现的所有类。

如果我们希望用applicationresourceConfig子类以编程方式配置应用程序,那么只需对上面的web.xml进行一次更改即可。我们不是设置init-param来扫描包,而是使用init-param来声明Application/ResourceConfig子类。

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.example.JerseyApplication</param-value>
    </init-param>
    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
</servlet>
package com.example;

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

在这里,我们使用ResourceConfig子类的完全限定名配置init-paramjavax.ws.rs.application。而不是使用告诉Jersey要扫描哪个包的init-param,我们只使用ResourceConfig的方便方法packages()

我们还可以使用register()property()方法注册资源和提供程序,并配置Jersey属性。使用property()方法,可以配置为init-param的任何内容,也可以使用property()方法进行配置。例如,与调用packages()不同,我们可以

public JerseyApplication() {
    property("jersey.config.server.provider.packages",
             "com.mypackage.to.scan");
}

如果没有web.xml,Jersey需要一种方法来提供servlet映射。我们使用@applicationpath注释来实现这一点。

// 'services', '/services', or '/services/*'
// is all the same. Jersey will change it to be '/services/*'
@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

这里使用@applicationpath,就像我们在web.xml中配置servlet映射一样

<servlet-mapping>
    <servlet-name>JerseyApplication</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

当只使用Java代码进行配置时,需要有某种方法让Jersey发现我们的配置类。这是通过使用ServletContanerInitializer来完成的。这是Servlet3.0规范中引入的内容,因此我们不能在早期的Servlet容器中使用“Java Only”配置。

基本上发生的情况是,初始化器的实现者可以告诉servlet容器要查找哪些类,servlet容器将把那些类传递给初始化器onstartup()方法。在Jersey的初始化器实现中,Jersey将其配置为查找application类和用@applicationpath注释的类。进一步的解释请看这篇文章。因此,当servlet容器启动应用程序时,Jersey的初始化器将通过application/resourceConfig类传递。

resourceConfig只是一个方便的类。记住,它扩展了application,因此我们甚至可以使用标准的application

@ApplicationPath("/services")
public class JerseyApplication extends Application {

    private final Set<Class<?>> classes;
    private final Set<Object> singletons;

    public JerseyApplication() {
        // configure in constructor as Jersey
        // may call the getXxx methods multiple times

        this.classes = new HashSet<>();
        this.classes.add(MyResource.class);

        this.singletons = new HashSet<>();
        this.singletons.add(new MyProvider());
    }

    @Override
    public Set<Class<?>> getClasses() {
        return this.classes;
    }

    @Override
    public Set<Object> getSingletons() {
        return this.singletons;
    }

    @Override
    public Map<String, Object> getProperties() {
        final Map<String, Object> properties = new HashMap<>();
        properties.put("jersey.config.server.provider.packages",
                       "com.mypackage.to.scan");
        return properties;
    }
}

使用resourceConfig,我们只需

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        register(MyResource.class);
        register(new MyProvider());
        packages("com.mypackages.to.scan");
    }
}

除了更方便之外,还有一些东西可以帮助Jersey配置应用程序。

ResourceConfig config = new ResourceConfig();
config.packages("com.my.package");
config.register(SomeFeature.class);
config.property(SOME_PROP, someValue);

这里最有可能发生的情况是,示例使用的是嵌入式服务器,如Grizzly。启动服务器的其余代码可能类似于

public static void main(String[] args) {
    ResourceConfig config = new ResourceConfig();
    config.packages("com.my.package");
    config.register(SomeFeature.class);
    config.property(SOME_PROP, someValue);

    String baseUri = "http://localhost:8080/api/";
    HttpServer server = GrizzlyHttpServerFactory
            .createHttpServer(URI.create(baseUri), config);
    server.start();
}

因此,在本例中,启动了一个独立服务器,并使用resourceConfig配置Jersey。这里和前面示例的不同之处在于,在这个示例中,我们没有扩展resourceConfig,而只是实例化它。如果我们做

public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        packages("com.my.package");
        register(SomeFeature.class);
        property(SOME_PROP, someValue);
    }
}

HttpServer server = GrizzlyHttpServerFactory
            .createHttpServer(URI.create(baseUri), new JerseyConfig());

假设您正在学习一些教程,其中显示了一个独立应用程序的配置,在该配置中,他们实例化了resourceConfig。但是您是在安装的servlet容器中运行应用程序的,并且一直在使用前面的配置,在前面的配置中扩展resourceConfig。好了,现在你知道区别是什么了,你需要做什么改变了。我见过一些人做一些很奇怪的事情,因为他们不理解这种区别。例如,我看到有人在资源类中实例化resourceConfig。所以这就是为什么我加了这个额外的小片;这样你就不会犯同样的错误了。

1。有许多不同的可配置属性。指向serverproperties的链接只是一些常规属性。还有与特定特征相关的不同属性。文档应在文档中与该特性相关的部分中提及这些属性。有关所有可配置属性的完整列表,您可以查看所有Jersey常量,并查找字符串值以Jersey.config开头的那些。如果您使用的是web.xml,那么您将使用字符串值作为init-paramparam-name。如果您使用的是Java配置(resourceConfig),那么您可以调用property(serverproperties.some_conf,value)

 类似资料:
  • 有人成功部署了Jersey 2吗。带JBoss 7的x。x?我曾尝试在JBoss 7.1.1中部署Jersey 2.5,但遇到以下错误: 我认为这个问题是因为JBoss与RestEasy捆绑在一起,RestEasy是一个JAX-RS 1.0实现,而Jersey是一个JAX-RS 2.0实现。因此,我采取以下步骤禁用RestEasy: 1)在我的web.xml中添加了以下内容: 2)按照这里的讨论,

  • 我有一个问题,让昂首阔步的博士一代工作。 以下是我使用的专家: 我在ResourceConfig类中添加了swagger ressources: 然后我声明了一个 servlet 来配置 Swagger: 通过上面的配置,可以使用swagger servlet:如果我浏览到api文档url,我会得到以下信息: 但是,如果我使用如下所示的真实配置更改 swagger servlet 配置中的 api

  • 主要内容:一、从单块系统说起,二、团队越来越大,业务越来越复杂,三、分布式出现:庞大系统分而治之,四、分布式系统所带来的技术问题,五、一句话总结:什么是分布式系统设计和开发经验?,六、补充说明:中间件系统及大数据系统前言 现在有很多Java技术方向的同学在找工作的时候,肯定都会去招聘网站上找职位投递简历。 但是在很多职位JD上往往会有这样的一个要求:熟悉分布式系统理论、设计和开发,具备复杂分布式系统构建经验。 之前不少同学后台留言问过我:这个分布式系统的设计和开发经验,到底指的是什么?那么这篇文

  • 问题内容: JavaScript中的类型强制到底是什么? 例如,使用代替? 问题答案: 类型强制意味着当一个运算符的操作数是不同类型时,其中一个将被转换为另一个操作数类型的“等效”值。例如,如果您这样做: 布尔操作数将被转换为整数:变为,变为1。然后将这两个值进行比较。 但是,如果您使用非转换比较运算符,则不会发生这种转换。当操作数为不同类型时,此运算符将返回,并且仅在它们属于相同类型时才比较这些

  • 问题内容: 将Jersey从1.15版本升级到1.17后,它开始记录以下消息: 产生此类消息的服务示例: 我的第一印象是将其视为错误消息,完全基于消息的措辞方式(“找不到”)。但是,它以INFO级别记录,并且在实践中似乎没有任何影响,因为所有服务都可以继续工作。 所以我的问题是这些日志消息是否表明我们配置或使用Jersey的方式存在(潜在)问题。由于以前的版本没有发生这种情况,因此我已经检查了发行