Jersey Rest 服务的 ResourceConfig 和 ServletContextListener 之间的区别
Difference between ResourceConfig and ServletContextListener for Jersey Rest Service
我想初始化 Jersey Rest 服务并引入一个全局应用程序范围的变量,该变量应在应用程序启动时计算,并且应在每个 rest 资源和每个方法中可用(此处由整数 globalAppValue= 17,但以后会是一个复杂的对象)。
为了初始化服务并在启动时计算一次值,我找到了两种做法:通用的 ServletContextListener 和 Jersey ResourceConfig 方法。但是我一直不明白它们之间有什么区别?两种方法都会在启动时触发(都会打印 System.out 消息)。
这是我的 ServletContextListener 的实现,它运行良好:
public class LoadConfigurationListener implements ServletContextListener
{
private int globalAppValue = 17;
@Override
public void contextDestroyed (ServletContextEvent event)
{
}
@Override
public void contextInitialized (ServletContextEvent event)
{
System.out.println ("ServletContext init.");
ServletContext context = event.getServletContext ();
context.setAttribute ("globalAppValue", globalAppValue);
}
}
这是 Jersey Rest ResourceConfig 方法的实现,其中 ServletContext 不可用。此应用程序对象以后也无法通过资源方法注入获得:
@ApplicationPath("Resources")
public class MyApplication extends ResourceConfig
{
@Context
ServletContext context;
private int globalAppValue = 17;
public MyApplication () throws NamingException
{
System.out.println ("Application init.");
// returns NullPointerException since ServletContext is not injected
context.setAttribute ("globalAppValue", 17);
}
public int getAppValue ()
{
return globalAppValue;
}
}
这是我希望在资源方法中访问全局值的方式:
@Path("/")
public class TestResource
{
@Context
ServletContext context;
@Context
MyApplication application;
@Path("/test")
@GET
public String sayHello () throws SQLException
{
String result = "Hello World: ";
// returns NullPointerException since application is not injected
result += "globalAppValue=" + application.getAppValue ();
// works!
result += "contextValue=" + context.getAttribute ("globalAppValue");
return result;
}
}
因此,虽然经典的 ServletContextListener 工作正常,但我在使用 ResourceConfig/Application 时遇到了几个问题,但我更喜欢这种方式,因为它似乎更自然地集成到 Jersey 中。所以我的问题是哪种方式是最好的做法。谢谢!
您可以通过调用 property( key, value )
.
在 ResourceConfig
中设置 属性
public MyApplication() {
property("MyProp", "MyValue");
}
在您的资源 class 中,您只能注入超级抽象 class javax.ws.rs.core.Application
,ResourceConfig
从中扩展。
然后你可以做的是调用标准 Application
API 方法之一来获取设置属性。该方法当然被命名为 getProperties()
,其中 returns 是一个属性映射。
@Path("/")
public class TestResource
{
@Context
Application application;
@GET
public String get() {
String value = (String)application.getProperties().get("MyProp");
}
}
同样通过在 ResourceConfig
上使用 property
方法,将 属性 放入全局 javax.ws.rs.core.Configuration
对象中,该对象也是可注入的。因此,您可以注入 Configuration
而不是 Application
@Path("/")
public class TestResource
{
@Context
Configuration config;
@GET
public String get() {
String value = (String)config.getProperty("MyProp");
}
}
另请参阅:
- Using a custom hk2 InjectionResolver to inject application configuration 一些其他有趣的方法来注入值而不是必须从
Application
或 Configuration
中检索它
对不起,如果调用 GET /test/,这会产生 "value=null" 作为输出。
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
@Path("/test")
public class TestResource
{
@Context
Application application;
@GET
public String sayHello ()
{
String result = "value=" + application.getProperties ().get ("value");
return result;
}
}
ApplicationPath 在这里设置为 "resources" ?
package rest;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath("resources")
public class MyApplication extends ResourceConfig
{
public MyApplication ()
{
property ("value", 17);
System.out.println (getProperties ());
}
}
编辑: 对于关注我们讨论的人,solution/problem 如下。加上我的servlet部署部分web.xml,首先我写错了
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
删除 * 并将 url 模式更改为 <url-pattern>/</url-pattern>
(不带 *)并分别更改
@ApplicationPath("/")
public class MyApplication extends ResourceConfig
终于解决了。因此,ApplicationPath 必须与 web.xml 中的 Servlet-Url 中的相同,以便正确完成方法 class 中的注入。
我想初始化 Jersey Rest 服务并引入一个全局应用程序范围的变量,该变量应在应用程序启动时计算,并且应在每个 rest 资源和每个方法中可用(此处由整数 globalAppValue= 17,但以后会是一个复杂的对象)。
为了初始化服务并在启动时计算一次值,我找到了两种做法:通用的 ServletContextListener 和 Jersey ResourceConfig 方法。但是我一直不明白它们之间有什么区别?两种方法都会在启动时触发(都会打印 System.out 消息)。
这是我的 ServletContextListener 的实现,它运行良好:
public class LoadConfigurationListener implements ServletContextListener
{
private int globalAppValue = 17;
@Override
public void contextDestroyed (ServletContextEvent event)
{
}
@Override
public void contextInitialized (ServletContextEvent event)
{
System.out.println ("ServletContext init.");
ServletContext context = event.getServletContext ();
context.setAttribute ("globalAppValue", globalAppValue);
}
}
这是 Jersey Rest ResourceConfig 方法的实现,其中 ServletContext 不可用。此应用程序对象以后也无法通过资源方法注入获得:
@ApplicationPath("Resources")
public class MyApplication extends ResourceConfig
{
@Context
ServletContext context;
private int globalAppValue = 17;
public MyApplication () throws NamingException
{
System.out.println ("Application init.");
// returns NullPointerException since ServletContext is not injected
context.setAttribute ("globalAppValue", 17);
}
public int getAppValue ()
{
return globalAppValue;
}
}
这是我希望在资源方法中访问全局值的方式:
@Path("/")
public class TestResource
{
@Context
ServletContext context;
@Context
MyApplication application;
@Path("/test")
@GET
public String sayHello () throws SQLException
{
String result = "Hello World: ";
// returns NullPointerException since application is not injected
result += "globalAppValue=" + application.getAppValue ();
// works!
result += "contextValue=" + context.getAttribute ("globalAppValue");
return result;
}
}
因此,虽然经典的 ServletContextListener 工作正常,但我在使用 ResourceConfig/Application 时遇到了几个问题,但我更喜欢这种方式,因为它似乎更自然地集成到 Jersey 中。所以我的问题是哪种方式是最好的做法。谢谢!
您可以通过调用 property( key, value )
.
ResourceConfig
中设置 属性
public MyApplication() {
property("MyProp", "MyValue");
}
在您的资源 class 中,您只能注入超级抽象 class javax.ws.rs.core.Application
,ResourceConfig
从中扩展。
然后你可以做的是调用标准 Application
API 方法之一来获取设置属性。该方法当然被命名为 getProperties()
,其中 returns 是一个属性映射。
@Path("/")
public class TestResource
{
@Context
Application application;
@GET
public String get() {
String value = (String)application.getProperties().get("MyProp");
}
}
同样通过在 ResourceConfig
上使用 property
方法,将 属性 放入全局 javax.ws.rs.core.Configuration
对象中,该对象也是可注入的。因此,您可以注入 Configuration
Application
@Path("/")
public class TestResource
{
@Context
Configuration config;
@GET
public String get() {
String value = (String)config.getProperty("MyProp");
}
}
另请参阅:
- Using a custom hk2 InjectionResolver to inject application configuration 一些其他有趣的方法来注入值而不是必须从
Application
或Configuration
中检索它
对不起,如果调用 GET /test/,这会产生 "value=null" 作为输出。
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
@Path("/test")
public class TestResource
{
@Context
Application application;
@GET
public String sayHello ()
{
String result = "value=" + application.getProperties ().get ("value");
return result;
}
}
ApplicationPath 在这里设置为 "resources" ?
package rest;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath("resources")
public class MyApplication extends ResourceConfig
{
public MyApplication ()
{
property ("value", 17);
System.out.println (getProperties ());
}
}
编辑: 对于关注我们讨论的人,solution/problem 如下。加上我的servlet部署部分web.xml,首先我写错了
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
删除 * 并将 url 模式更改为 <url-pattern>/</url-pattern>
(不带 *)并分别更改
@ApplicationPath("/")
public class MyApplication extends ResourceConfig
终于解决了。因此,ApplicationPath 必须与 web.xml 中的 Servlet-Url 中的相同,以便正确完成方法 class 中的注入。