Jersey:如何访问全局应用程序对象?
Jersey: how to access the global application object?
我正在使用 Java、Tomcat 和 Jersey 创建一个 REST Web 应用程序。我正在使用注释(没有 web.xml!)我最终使用了这个应用程序配置:
package com.my_own.server;
import java.util.Properties;
import javax.ws.rs.ApplicationPath;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.my_own.db.PostgreSQLDb;
@ApplicationPath("/api")
public class Application extends javax.ws.rs.core.Application {
private static Logger logger = LogManager.getLogger(Application.class);
public static Application application = null;
public final Properties properties;
public final PostgreSQLDb adminDb;
public Application() throws Exception {
logger.debug("Loading properties from ",
getClass().getClassLoader().getResource("config.properties"));
properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("config.properties"));
adminDb = new PostgreSQLDb(properties, "admin");
application = this; // Setting the global application object here
}
}
这是我的问题。 Web 容器有一个全局应用程序对象。我将它从应用程序构造函数保存到一个静态字段中。稍后我需要从其他 类 访问它(它包含全局配置、全局数据库连接工厂,可能还有其他东西。)
我这样做对吗?我怀疑一定有更好的方法:在处理注释时保存对应用程序的引用。但我不确定如何。我可以确定应用程序的构造函数将被调用一次,并且以后可以从任何 REST 调用访问 Application.application 引用吗?
让我分享一下我的观点:您当然可以使用众所周知的 Singleton 模式来存储 "global" 静态对象,但是,如今它确实是一种反模式。
如果它不是家庭作业或其他东西,那么存储全局 "static" 对象在设计方面总是一个坏主意。如果您想知道为什么有很多来源可以回答这个问题,例如 this discussion
所以我建议考虑改用依赖注入容器,那里有很多非常好的容器:Spring,Guice 等等。
这些容器可以将这些对象存储为 bean,如果您的 "pieces" 功能也由这些容器管理,您将能够 "inject" 应用程序 bean 直接进入控制器。
有效解决了单例模式带来的所有问题。
在jersey中使用依赖注入,在初始化时绑定你的应用程序:
public class MyApplication extends ResourceConfig {
public MyApplication() {
super(MyApplication.class);
register(new MyBinder());
packages(true, "location.of.my.jersey.classes");
}
/* Bind is used to let jersey know what can be injected */
private static class MyBinder extends AbstractBinder {
@Override
protected void configure() {
bind(MyApplication.class).to(MyApplication.class);
}
}
}
然后在你的代码中:
@Path("myapi")
@Produces(MediaType.APPLICATION_JSON)
public class ServerRoutes {
@Inject
MyApplication application;
//... your rest code here
}
现在您可以从您的代码中访问 MyApplication,而无需任何静态或单例,jersey 会处理它。
我正在使用 Java、Tomcat 和 Jersey 创建一个 REST Web 应用程序。我正在使用注释(没有 web.xml!)我最终使用了这个应用程序配置:
package com.my_own.server;
import java.util.Properties;
import javax.ws.rs.ApplicationPath;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.my_own.db.PostgreSQLDb;
@ApplicationPath("/api")
public class Application extends javax.ws.rs.core.Application {
private static Logger logger = LogManager.getLogger(Application.class);
public static Application application = null;
public final Properties properties;
public final PostgreSQLDb adminDb;
public Application() throws Exception {
logger.debug("Loading properties from ",
getClass().getClassLoader().getResource("config.properties"));
properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("config.properties"));
adminDb = new PostgreSQLDb(properties, "admin");
application = this; // Setting the global application object here
}
}
这是我的问题。 Web 容器有一个全局应用程序对象。我将它从应用程序构造函数保存到一个静态字段中。稍后我需要从其他 类 访问它(它包含全局配置、全局数据库连接工厂,可能还有其他东西。)
我这样做对吗?我怀疑一定有更好的方法:在处理注释时保存对应用程序的引用。但我不确定如何。我可以确定应用程序的构造函数将被调用一次,并且以后可以从任何 REST 调用访问 Application.application 引用吗?
让我分享一下我的观点:您当然可以使用众所周知的 Singleton 模式来存储 "global" 静态对象,但是,如今它确实是一种反模式。
如果它不是家庭作业或其他东西,那么存储全局 "static" 对象在设计方面总是一个坏主意。如果您想知道为什么有很多来源可以回答这个问题,例如 this discussion
所以我建议考虑改用依赖注入容器,那里有很多非常好的容器:Spring,Guice 等等。
这些容器可以将这些对象存储为 bean,如果您的 "pieces" 功能也由这些容器管理,您将能够 "inject" 应用程序 bean 直接进入控制器。
有效解决了单例模式带来的所有问题。
在jersey中使用依赖注入,在初始化时绑定你的应用程序:
public class MyApplication extends ResourceConfig {
public MyApplication() {
super(MyApplication.class);
register(new MyBinder());
packages(true, "location.of.my.jersey.classes");
}
/* Bind is used to let jersey know what can be injected */
private static class MyBinder extends AbstractBinder {
@Override
protected void configure() {
bind(MyApplication.class).to(MyApplication.class);
}
}
}
然后在你的代码中:
@Path("myapi")
@Produces(MediaType.APPLICATION_JSON)
public class ServerRoutes {
@Inject
MyApplication application;
//... your rest code here
}
现在您可以从您的代码中访问 MyApplication,而无需任何静态或单例,jersey 会处理它。