简体   繁体   English

泽西岛:如何访问全局应用程序对象?

[英]Jersey: how to access the global application object?

I'm creating a REST web application with Java, Tomcat and Jersey. 我正在使用Java,Tomcat和Jersey创建REST Web应用程序。 I'm using annotations (no web.xml!) I ended up using this application configuration: 我使用的是注释(没有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
    }

}

Here is my problem. 这是我的问题。 There is a single global application objects for the web container. Web容器只有一个全局应用程序对象。 I'm saving it into a static field, from the application constructor. 我将其从应用程序构造函数保存到一个静态字段中。 I need to access it from other classes later (it holds the global configuration, a global database connection factory, and probably other things.) 稍后我需要从其他类访问它(它拥有全局配置,全局数据库连接工厂以及可能的其他东西。)

Am I doing this right? 我这样做对吗? I suspect that there must be a better way: save a reference to the application when annotations are processed. 我怀疑必须有更好的方法:在处理批注时保存对应用程序的引用。 But I'm not sure how. 但是我不确定如何。 Can I be sure that the Application's constructor will be called exactly once, and the Application.application reference can be accessed later, from any REST call? 我可以确定Application的构造函数将只被调用一次,并且以后可以通过任何REST调用访问Application.application引用吗?

Let me share my opinion: you can use of course a well-known Singleton pattern to store a "global" static object, however, it's really an antipattern these days. 让我分享我的观点:当然,您可以使用众所周知的Singleton模式来存储“全局”静态对象,但是,如今,它确实是一种反模式。

If it's not a homework or something then storing global "static" objects is always a bad idea design-wise. 如果不是家庭作业或其他东西,那么在设计上存储全局“静态”对象总是一个坏主意。 If you want to know why there are many sources that answer this question, like this discussion for example 如果您想知道为什么有很多来源回答此问题,例如以下讨论

So I suggest considering using a Dependency Injection container instead, There are many really good containers out there: Spring, Guice to name a few. 因此,我建议考虑改用Dependency Injection容器,那里有很多非常好的容器:Spring,Guice等。

These containers can store these objects as beans and if your "pieces" of functionality are also managed by these containers, you'll be able to "inject" application beans right into the controller. 这些容器可以将这些对象存储为bean,如果您的“功能”也由这些容器管理,则可以将应用bean直接注入控制器中。

It effectively solves all the issues introduced by singleton pattern. 它有效地解决了单例模式引入的所有问题。

Use dependency injection in jersey, bind your application when initializing: 在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);
        }
    }
}

Then in your code: 然后在您的代码中:

@Path("myapi")
@Produces(MediaType.APPLICATION_JSON)
public class ServerRoutes {
    @Inject
    MyApplication application;

//... your rest code here
}

Now you can access MyApplication from within your code without needing any statics or singletons, jersey handles it. 现在,您可以从代码内访问MyApplication,而无需任何静态变量或单例,jersey可以处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM