Jersey 2 中的 ResourceConfig 类到底是什么? [英] What exactly is the ResourceConfig class in Jersey 2?
问题描述
我看过很多以类似开头的 Jersey 教程
I have seen a lot of Jersey tutorials that starts with something like
@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("com.abc.jersey.services");
}
}
没有解释 ResourceConfig
类到底是什么.那么我在哪里可以找到它的文档、用法等呢?谷歌搜索jersey resourceconfig"不会产生任何官方文档.
without explaining what exactly the ResourceConfig
class is. So where can I find its documentation, usage, etc.? Googling for "jersey resourceconfig" does not yield any official doc.
我对这个类及其用法的一些问题是:
Some of my questions about this class and its usage are:
- 我可以在
ResourceConfig
的子类中做些什么? - 我是否需要在某处注册
ResourceConfig
的子类以便可以找到它,或者它会被 Jersey 自动检测到? - 如果自动检测到子类,如果我有多个
ResourceConfig
子类会怎样? ResourceConfig
的用途和web.xml
文件的用途一样吗?如果是这样,如果我在我的项目中同时拥有这两者会发生什么?其中一个是否优先于另一个?
- What things can I do inside the subclass of
ResourceConfig
? - Do I need to register the subclass of
ResourceConfig
somewhere so that it can be found or is it automatically detected by Jersey? - If the subclass is automatically detected what happens if I have multiple subclasses of
ResourceConfig
? - Is the purpose of
ResourceConfig
the same as theweb.xml
file? If so what happens if I have both in my project? Does one of them take precedence over the other?
推荐答案
标准 JAX-RS 使用 Application
作为它的配置类.ResourceConfig
扩展 Application
.
Standard JAX-RS uses an Application
as its configuration class. ResourceConfig
extends Application
.
有三种主要方式(在 servlet 容器中)来配置 Jersey (JAX-RS):
There are three main ways (in a servlet container) to configure Jersey (JAX-RS):
- 只有 web.xml
- 同时使用 web.xml 和一个
Application/ResourceConfig
类 - 只有一个
Application/ResourceConfig
类用@ApplicationPath
注释.
- With only web.xml
- With both web.xml and an
Application/ResourceConfig
class - With only an
Application/ResourceConfig
class annotated with@ApplicationPath
.
只有 web.xml
可以以标准的 JAX-RS 方式配置应用程序,但以下是特定于 Jersey 的
With only web.xml
It is possible to configure the application in a standard JAX-RS way, but the following is specific to Jersey
<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
.所以在这里我们将它声明为 <servlet-class>
.我们还配置了一个 <init-param>
告诉 Jersey 为我们的 @Path
和 @Provider
类扫描哪些包,所以它可以注册.
Since Jersey runs in a servlet container, it is only right that the Jersey application runs as a servlet. The Jersey Servlet that handles incoming requests is the ServletContainer
. So here we declare it as the <servlet-class>
. We also configure an <init-param>
telling Jersey which package(s) to scan for our @Path
and @Provider
classes so it can register them.
在底层,Jersey 实际上会创建一个 ResourceConfig
实例,因为它是用来配置应用程序的.然后它将注册它通过包扫描发现的所有类.
Under the hood, Jersey will actually create a ResourceConfig
instance, as that's what it uses to configure the application. Then it will register all the classes that it discovers through the package scan.
如果我们想使用 Application
或 ResourceConfig
子类以编程方式配置我们的应用程序,我们可以对上述 web.xml 进行一次更改.我们没有设置 init-param 来扫描包,而是使用 init-param 来声明我们的 Application/ResourceConfig
子类.
If we want to programmatically configure our application with an Application
or ResourceConfig
subclass, we can do so with one change to the above web.xml. Instead of setting an init-param to scan for packages, we use an init-param to declare our Application/ResourceConfig
subclass.
<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-param
javax.ws.rs.Application
.而不是使用告诉 Jersey 扫描哪个包的 init-param
,我们只使用 ResourceConfig的便捷方法
packages()
代码>.
Here, we configure the init-param
javax.ws.rs.Application
with the fully qualified name of our ResourceConfig
subclass. And instead of using the init-param
that tells Jersey which package(s) to scan, we just use the convenience method packages()
of the ResourceConfig
.
我们还可以使用方法 register()
和 property()
来注册资源和提供者,以及配置 Jersey 属性.使用 property()
方法,可以配置为 init-param
的任何内容也可以使用 property()
方法进行配置.例如,我们可以调用 packages()
,而不是调用
We could also use the methods register()
and property()
to register resources and providers, and to configure Jersey properties. With the property()
method, anything that can be configured as an init-param
, can also be configured using the property()
method. For instance instead of calling packages()
, we could do
public JerseyApplication() {
property("jersey.config.server.provider.packages",
"com.mypackage.to.scan");
}
只有 Application/ResourceConfig
如果没有 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映射
Here with the @ApplicationPath
, it's just like if we configured the servlet mapping in the web.xml
<servlet-mapping>
<servlet-name>JerseyApplication</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
当仅使用 Java 代码进行配置时,Jersey 需要通过某种方式发现我们的配置类.这是通过使用 ServletContanerInitializer
.这是 Servlet 3.0 规范中引入的东西,所以我们不能使用仅 Java".早期 servlet 容器中的配置.
When using only Java code for configuration, there needs to be some way for Jersey to discover our configuration class. This is done with the use of a ServletContanerInitializer
. This is something that was introduced in the Servlet 3.0 Specification, so we cannot use "Java only" configuration in earlier servlet containers.
基本上,初始化程序的实现者可以告诉 servlet 容器要查找哪些类,然后 servlet 容器会将这些类传递给初始化程序的 onStartup()
方法.在 Jersey 的初始化器实现中,Jersey 将其配置为查找 Application
类和使用 @ApplicationPath
注释的类.请参阅这篇文章了解更多说明.所以当 servlet 容器启动应用程序时,Jersey 的初始化程序将通过我们的 Application/ResourceConfig
类.
Basically what happens is that the implementor of the initializer can tell the servlet container what classes to look for, and the servlet container will pass those classes to the initializer onStartup()
method. In Jersey's implementation of the initializer, Jersey configures it to look for Application
classes and classes annotated with @ApplicationPath
. See this post for further explanation. So when the servlet container starts the application, Jersey's initializer will get passed our Application/ResourceConfig
class.
看看 javadoc.它主要只是注册课程.你不需要做太多其他事情.您将使用的主要方法是 register()
、packages()
和 property()
方法.register()
方法允许您手动注册资源和提供者的类和实例.前面讨论过的 packages()
方法列出了您希望 Jersey 扫描 @Path
和 @Provider
类并注册的包他们给你.property()
方法允许你设置一些 可配置属性 1.
Just look at the javadoc. Its mostly just registration of classes. Not much else you need to do with it. The main methods you will be using are the register()
, packages()
, and property()
methods. The register()
method lets you manually register classes and instances of resources and providers manually. The packages()
method, discussed earlier, lists the package(s) you want Jersey to scan for @Path
and @Provider
classes and register them for you. And the property()
method allows you to set some configurable properties 1.
ResourceConfig
只是一个便利类.请记住,它扩展了 Application
,因此我们甚至可以使用标准的 Application
类
The ResourceConfig
is just a convenience class. Remember, it extends Application
, so we could even use the standard Application
class
@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
,我们就可以做到
With a ResourceConfig
, we would just do
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
register(MyResource.class);
register(new MyProvider());
packages("com.mypackages.to.scan");
}
}
除了更方便之外,还有一些事情可以帮助 Jersey 配置应用程序.
Aside from being more convenient, there are also a few thing under the hood that help Jersey configure the application.
以上所有示例都假设您在已安装的服务器环境中运行,例如雄猫.但您也可以在 SE 环境中运行应用程序,在其中运行嵌入式服务器并从 main
方法启动应用程序.您有时会在四处搜索信息时看到这些示例,所以我想展示一下它们的外观,这样如果您遇到这种情况,您不会感到惊讶,并且知道它与您的设置有何不同.
All the examples above assume you are running in an installed server environment, e.g. Tomcat. But you can also run the app in an SE environment, where you run an embedded server and start the app from a main
method. You will sometimes see these examples when searching around for info, so I want to show what that looks like, so that if you ever do come across this, you are not surprised and know how it differs from your setup.
所以有时你会看到这样的例子
So sometimes you will see an example like
ResourceConfig config = new ResourceConfig();
config.packages("com.my.package");
config.register(SomeFeature.class);
config.property(SOME_PROP, someValue);
这里最有可能发生的情况是该示例使用了嵌入式服务器,例如 Grizzly.启动服务器的其余代码可能类似于
What is most likely happening here is that the example is using an embedded server, like Grizzly. The rest of the code to start the server might be something like
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
,而只是将其实例化.如果我们这样做也不会有什么不同
So in this example, there is a standalone server being started and the ResourceConfig
is used to configure Jersey. The different here and from previous examples is that in this example, we are not extending the ResourceConfig
, but instead just instantiating it. It wouldn't be any different if we were to do
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
.所以这就是我添加这个额外的小片段的原因;所以你不会犯同样的错误.
Say you were going through some tutorial and it showed a configuration for a standalone app where they instantiate the ResourceConfig
. But you are running your app in an installed servlet container and have been using the earlier configuration where you are extending the ResourceConfig
. Well now you know what the difference is and what changes you need to make. I've seen people do some really weird stuff because they didn't understand this difference. For example I saw someone instantiating a ResourceConfig
inside a resource class. So this is why I added this extra little piece; so you don't make the same mistake.
<子>1.有许多不同的可配置属性.ServerProperties
只是一些通用属性.还有与特定功能相关的不同属性.文档应在与该功能相关的文档部分中提及这些属性.有关所有可配置属性的完整列表,您可以查看所有 Jersey 常量 并查找字符串值以 jersey.config
开头的那些.如果您使用的是 web.xml,那么您将使用字符串值作为 init-param
param-name
.如果您使用的是 Java 配置 (ResourceConfig
),那么您将调用 property(ServerProperties.SOME_CONF, value)
1. There are a number of different configurable properties. The link to the ServerProperties
are just some general properties. There are also different properties related to specific features. The documentation should mention these properties in the section of the docs related to that feature. For a complete list of all configurable properties, you can look at all the Jersey constants and look for the ones where the string value starts with jersey.config
. If you are using a web.xml, then you would use the string value as the init-param
param-name
. If you are using Java config (ResourceConfig
), then you would call property(ServerProperties.SOME_CONF, value)
这篇关于Jersey 2 中的 ResourceConfig 类到底是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!