java java如何在没有servlet上下文的情况下访问WEB-INF文件夹中的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26356504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:47:09  来源:igfitidea点击:

java how to access file in WEB-INF folder WITHOUT servlet context

javaspringtomcatweb-inf

提问by siliconchris

I searched the internet since yesterday, but I seem unable to cope with the task at hand. I have a central class (RuntimeConfiguration) that holds around 100 parameters for my application. These parameters are taken from an XML file which I stored in the WEB-INF folder. On my development box I hard-coded the path, but for very obvious reasons, this is not a productive solution.

我从昨天开始在网上搜索,但我似乎无法应付手头的任务。我有一个中心类 (RuntimeConfiguration),它为我的应用程序保存大约 100 个参数。这些参数取自我存储在 WEB-INF 文件夹中的 XML 文件。在我的开发箱上,我对路径进行了硬编码,但出于非常明显的原因,这不是一个有效的解决方案。

For portability reasons (my application might be executed on a tomcat or a jetty and under Windows OR Unix), I want to have a generic access way to this file from within my RuntimeConfiguration class.

出于可移植性的原因(我的应用程序可能在 tomcat 或 jetty 上以及在 Windows 或 Unix 下执行),我希望从我的 RuntimeConfiguration 类中拥有对该文件的通用访问方式。

I know, I can use getRealPath in case I have a servlet, BUT RuntimeConfiguration is NOT started within a servlet context. It is invoked from a job (a crawler) which in turn is started from quartz job control via applicationContext.xml. Now this seems to be the core of my problem.

我知道,如果我有一个 servlet,我可以使用 getRealPath,但是 RuntimeConfiguration 不是在 servlet 上下文中启动的。它是从一个作业(一个爬虫)调用的,而该作业又通过 applicationContext.xml 从quartz 作业控制中启动。现在这似乎是我问题的核心。

Can anyone tell me, how to get the absolute path to my XML in this environment?

谁能告诉我,如何在这种环境中获得我的 XML 的绝对路径?

I tried this ClassLoader approach, but it gives me a null-pointer exception:

我尝试了这种 ClassLoader 方法,但它给了我一个空指针异常:

ClassLoader loader = this.getClass().getClassLoader();
loader.getResource("WEB-INF");
result = loader.getSystemResource(RTCF).toString(); 

I also tried

我也试过

URL url = this.getClass().getClassLoader().getResource("WEB-INF");

which also throws a null pointer exception

这也会引发空指针异常

Can anyone give me a portable solution, one that works on my dev-machine and on a production system where my application is deployed as a WAR-file??? By the way, the method should at best be able to handle Windows AND Mac OS X / Unix based systems.

谁能给我一个便携式解决方案,一个适用于我的开发机器和我的应用程序部署为 WAR 文件的生产系统的解决方案???顺便说一下,该方法最多应该能够处理基于 Windows 和 Mac OS X / Unix 的系统。

Thabks in advance,

提前敲定,

Christian

基督教

回答by Serge Ballesta

You can always use the holderpattern : you create a class, with a static field (with its static getter) that will contain the real path of the WEB-INFdirectory. This class should implement ApplicationContextAware

您始终可以使用持有者模式:您创建一个类,其中包含一个包含WEB-INF目录真实路径的静态字段(及其静态 getter)。这个类应该实现ApplicationContextAware

You create in root spring application context an instance of this holder class, Spring give it a pointer to the ApplicationContext that will be a WebApplicationContextas you are in a web application.

您在根 spring 应用程序上下文中创建了这个持有者类的一个实例,Spring 给它一个指向 ApplicationContext 的指针,WebApplicationContext就像您在 Web 应用程序中一样。

In the init method, you use the WebApplicationContextto get the path and store it in the static field. Thanks to Spring, you are sure that the method is called once and only once before the application really starts.

在 init 方法中,您使用WebApplicationContext来获取路径并将其存储在静态字段中。多亏了 Spring,您可以确保在应用程序真正启动之前调用该方法一次且仅一次。

Now anywhere in the application where you want to get the path, you can use it by calling the static getter.

现在,在应用程序中您想要获取路径的任何地方,您都可以通过调用静态 getter 来使用它。

public class ResourcePathHolder implements ApplicationContextAware, InitializingBean{
    private WebApplicationContext wac;
    private static String resourcePath;
    private static ServletContext sc;
    private String path = "WEB-INF";

    public static String getResourcePath() {
        return resourcePath;
    }

    public static ServletContext getServletContext() {
        return sc;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        wac = (WebApplicationContext) applicationContext;
    }

    public void setPath(String path) {
        this.path = path;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        ResourcePathHolder.sc = wac.getServletContext();
        ResourcePathHolder.resourcePath = sc.getRealPath(path);
    }
}

This implementation also gives you access to the ServletContextto allow you to use ServletContext.getResource()

此实现还使您可以访问ServletContext以允许您使用ServletContext.getResource()

EDIT :

编辑 :

Using the full path may not work on production servers that would not explode the war. From the javadoc for ServletContext.getRealPath(): This method returns null if the servlet container is unable to translate the given virtual path to a real path. But in that case, you can always access to the files as resources with ServletContext.getResource()or ServletContext.getResourceAsStream()

使用完整路径可能不适用于不会引发War的生产服务器。来自 javadoc for ServletContext.getRealPath()如果 servlet 容器无法将给定的虚拟路径转换为实际路径,则此方法返回 null。但在这种情况下,您始终可以使用ServletContext.getResource()ServletContext.getResourceAsStream()

回答by Stefan

Just put it in your classpath and load it with "getResourcesAsStream()", or better make it a ".properties"-file and load it the usual way:

只需将它放在您的类路径中并使用“getResourcesAsStream()”加载它,或者更好地将其设为“.properties”文件并以通常的方式加载它:

ResourceBundle config = ResourceBundle.getBundle("filename");

回答by OO7

In spring web application, you cannot get context path until you declare some class as bean in your web application context. Add below code in your RuntimeConfigurationclass

在 Spring Web 应用程序中,除非在 Web 应用程序上下文中将某个类声明为 bean,否则无法获取上下文路径。在您的RuntimeConfiguration课程中添加以下代码

@Autowired
private ServletContext servletContext;

public {desired returnType} getDirectoryPath(){
    File webInfPath = new File(this.getClass().getClassLoader().getResource("WEB-INF"));
    // OR use getResourceAsStream() method
    InputStream is = RuntimeConfiguration.class.getClassLoader().getResourceAsStream("WEB-INF");
}

OR

或者

If you don't want to do autowiring, then you can implement RuntimeConfiguration with ServletContextAware interface.Just like below, to get servlet context object in this class :-

如果您不想进行自动装配,那么您可以使用 ServletContextAware 接口实现 RuntimeConfiguration。就像下面一样,要在此类中获取 servlet 上下文对象:-

public class RuntimeConfiguration implements ServletContextAware {

    private ServletContext context;
    private ServletConfig config;

    @Override
    public void setServletContext(final ServletContext servletContext) {
        this.context = servletContext;
    }

    public ServletContext getServletContext()[
        return context;
    }
    //do other tasks
}

OR

或者

Have a look at ServletContextResourceServletContextResource - Spring Docs

看看ServletContextResource ServletContextResource - Spring Docs