标准JAX-RS使用Application
作为其配置类。延伸。ResourceConfig
Application
在Servlet容器中,有三种主要的不同配置方式来配置Jersey(JAX-RS):
- 仅使用web.xml
- 同时具有web.xml和一个
Application/ResourceConfig
类
- 仅用
Application/ResourceConfig
注释了一个类@ApplicationPath
。
仅使用web.xml
可以用标准的JAX-RS方式配置应用程序,但以下内容仅适用于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>
柜员机来扫描我们的@Path
和@Provider
类的软件包,以便可以注册它们。
在引擎盖下,Jersey实际上会创建一个 ResourceConfig
实例,因为它是用来配置应用程序的。然后它将注册通过程序包扫描发现的所有类。
同时使用web.xml和 Application/ResourceConfig
如果我们要使用Application
或ResourceConfig
子类以编程方式配置应用程序,则可以对上述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");
}
}
在这里,我们init-param
javax.ws.rs.Application
使用ResourceConfig
子类的完全限定名称配置。而且,我们没有使用init-param
告诉Jersey扫描哪个软件包的方法packages()
,而是使用的便捷方法ResourceConfig
。
我们也可以使用的方法register()
和property()
注册资源和提供者,以及配置泽西属性。使用该property()
方法,可以配置为的任何内容init-param
也可以使用该property()
方法进行配置。例如packages()
,我们可以不用调用
public JerseyApplication() {
property("jersey.config.server.provider.packages",
"com.mypackage.to.scan");
}
仅 Application/ResourceConfig
没有web.xml,Jersey需要一种方法来提供servlet映射。我们通过@ApplicationPath
注释来实现。
@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
。这是Servlet 3.0规范中引入的,因此我们不能在较早的Servlet容器中使用“仅Java”配置。
基本上发生的是,初始化器的实现者可以告诉servlet容器寻找什么类,并且servlet容器会将这些类传递给初始化器onStartup()
方法。在Jersey的初始化程序实现中,Jersey将其配置为查找Application
带有注释的类和类@ApplicationPath
。有关更多说明,请参见此帖子。因此,当servlet容器启动应用程序时,Jersey的初始化程序将通过我们的Application/ResourceConfig
类。
我可以在ResourceConfig的子类中做什么
只要看看javadoc即可。它主要只是课程注册。您不需要做很多其他事情。您将使用的主要方法是register()
,packages()
和property()
方法。该register()
方法使您可以手动注册资源和提供程序的类和实例。packages()
前面讨论的方法列出了希望Jersey扫描的软件包,@Path
并@Provider
分类并为您注册。并且该property()
方法允许您设置一些可配置的属性1。
这ResourceConfig
只是一个便利班。记住,它扩展了Application
,所以我们甚至可以使用标准Application
类
@ApplicationPath("/services")
public class JerseyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(MyResource.class);
return classes;
}
@Override
public Set<Object> getSingletons() {
final Set<Object> singletons = new HashSet<>();
singletons.add(new MyProvider());
return 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配置应用程序。
SE环境
上面的所有示例均假定您正在已安装的服务器环境中运行,例如Tomcat。但是,您也可以在SE环境中运行该应用程序,在该环境中,您可以运行嵌入式服务器并通过某种main
方法启动该应用程序。您有时会在搜索信息时看到这些示例,所以我想展示一下它的外观,这样当您每次遇到此问题时,您都不会感到惊讶,并且知道它与您的设置有何不同。
所以有时候你会看到一个例子
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-param
param-name
。如果您使用的是Java config(ResourceConfig
),则可以调用property(ServerProperties.SOME_CONF, value)