`

servletContextResource (ServletContext.getResourceAsStream)

阅读更多
/*
 * Copyright 2002-2005 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.context.support;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.servlet.ServletContext;

import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;

/**
 * Resource implementation for ServletContext resources,
 * interpreting relative paths within the web application root directory.
 *
 * <p>Always supports stream access and URL access, but only allows
 * <code>java.io.File</code> access when the web application archive
 * is expanded.
 *
 * @author Juergen Hoeller
 * @since 28.12.2003
 * @see javax.servlet.ServletContext#getResourceAsStream
 * @see javax.servlet.ServletContext#getResource
 * @see javax.servlet.ServletContext#getRealPath
 */
public class ServletContextResource extends AbstractResource {

	private final ServletContext servletContext;

	private final String path;


	/**
	 * Create a new ServletContextResource.
	 * <p>The Servlet spec requires that resource paths start with a slash,
	 * even if many containers accept paths without leading slash too.
	 * Consequently, the given path will be prepended with a slash if it
	 * doesn't already start with one.
	 * @param servletContext the ServletContext to load from
	 * @param path the path of the resource
	 */
	public ServletContextResource(ServletContext servletContext, String path) {
		// check ServletContext
		Assert.notNull(servletContext, "Cannot resolve ServletContextResource without ServletContext");
		this.servletContext = servletContext;

		// check path
		Assert.notNull(path, "path is required");
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		this.path = StringUtils.cleanPath(path);
	}

	/**
	 * Return the ServletContext for this resource.
	 */
	public final ServletContext getServletContext() {
		return servletContext;
	}

	/**
	 * Return the path for this resource.
	 */
	public final String getPath() {
		return path;
	}


	/**
	 * This implementation delegates to <code>ServletContext.getResourceAsStream</code>,
	 * but throws a FileNotFoundException if no resource found.
	 * @see javax.servlet.ServletContext#getResourceAsStream(String)
	 */
	public InputStream getInputStream() throws IOException {
		InputStream is = this.servletContext.getResourceAsStream(this.path);
		if (is == null) {
			throw new FileNotFoundException("Could not open " + getDescription());
		}
		return is;
	}

	/**
	 * This implementation delegates to <code>ServletContext.getResource</code>,
	 * but throws a FileNotFoundException if no resource found.
	 * @see javax.servlet.ServletContext#getResource(String)
	 */
	public URL getURL() throws IOException {
		URL url = this.servletContext.getResource(this.path);
		if (url == null) {
			throw new FileNotFoundException(
					getDescription() + " cannot be resolved to URL because it does not exist");
		}
		return url;
	}

	/**
	 * This implementation delegates to <code>ServletContext.getRealPath</code>,
	 * but throws a FileNotFoundException if not found or not resolvable.
	 * @see javax.servlet.ServletContext#getRealPath(String)
	 */
	public File getFile() throws IOException {
		String realPath = WebUtils.getRealPath(this.servletContext, this.path);
		return new File(realPath);
	}

	/**
	 * This implementation creates a ServletContextResource, applying the given path
	 * relative to the path of the underlying file of this resource descriptor.
	 * @see org.springframework.util.StringUtils#applyRelativePath(String, String)
	 */
	public Resource createRelative(String relativePath) throws IOException {
		String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
		return new ServletContextResource(this.servletContext, pathToUse);
	}

	/**
	 * This implementation returns the name of the file that this ServletContext
	 * resource refers to.
	 * @see org.springframework.util.StringUtils#getFilename(String)
	 */
	public String getFilename() {
		return StringUtils.getFilename(this.path);
	}

	/**
	 * This implementation returns a description that includes the ServletContext
	 * resource location.
	 */
	public String getDescription() {
		return "ServletContext resource [" + this.path + "]";
	}


	/**
	 * This implementation compares the underlying ServletContext resource locations.
	 */
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}
		if (obj instanceof ServletContextResource) {
			ServletContextResource otherRes = (ServletContextResource) obj;
			return (this.servletContext.equals(otherRes.servletContext) && this.path.equals(otherRes.path));
		}
		return false;
	}

	/**
	 * This implementation returns the hash code of the underlying
	 * ServletContext resource location.
	 */
	public int hashCode() {
		return this.path.hashCode();
	}

}

 

其中使用到了Log4J作为日志输出工具,Log4J的配置文件log4j.propertes放在DefaultWebApp\WEB-INF目录下。Log4J通过一个自动加载的Servlet进行初始化,初始化代码如下:

ServletContext context = getServletContext(); 
org.apache.log4j.PropertyConfigurator.
configure(context.getRealPath("/")
+ "/WEB-INF/log4j.properties");


其中,context.getRealPath("/")得到当前Web应用的真实根目录,比如,如果你的WebLogic安装在D:\bea下,在Windows下context.getRealPath("/")通常会返回:

D:\bea\wlserver6.1\config\mydomain
\applications\DefaultWebApp



在UNIX下类似:

/bea/wlserver6.1/config/mydomain
/applications/DefaultWebApp



这样,和 "/ WEB-INF /log4j.properties"

拼接后,就得到了log4j.properties文件的真实路径


现在一切正常!测试通过后,将DefaultWebApp下的所有文件打为一个.war包,进行部署时,发现系统报告找不到“D:\bea\wlserver6.1\null\ WEB-INF \log4j.properties”文件!如果你的应用中还需要读取其它已经被打包到war包中的文件,都会报告找不到文件。并且,系统并不会到D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp目录下寻找,而会到D:\bea\wlserver6.1\null下寻找。这是因为context.getRealPath("/")返回了null。

查看ServletContext的API文档,原来,对一个打包的应用来说,是没有RealPath的概念的,调用getRealPath只会简单地返回null。其实,也很好理解,一个文件被打包入了.war文件,就不存在目录结构了(虽然包中仍然存在目录结构,但这不等同于文件系统中的目录结构)。

所以,对war包中的资源是无法得到RealPath的。这样也就无从通过文件IO进行读取了。那么,如何读取war包中的资源呢?答案是使用ServletContext.getResourceAsStream(String)方法

对于org.apache.log4j.PropertyConfigurator,有如下几种配置方法:

static void configure(Properties properties); 
static void configure(String configFilename); 
static void configure(URL configURL);



既然,现在不能得到war包中的Log4J的配置文件,那么可以通过读入InputStream,构造一个Properties,通过configure(Properties properties)方法同样可以完成配置。示例代码如下:

InputStream is = getServletContext(). 
getResourceAsStream("/WEB-INF/log4j.properties"); 
Properties props = new Properties(); 
try
{ 
props.load(is); 
}
catch (IOException e)
{ 
System.err.println("Load log4j 
configuration failed"); 
        } 
        PropertyConfigurator.configure(props);



那么,现在对于war应用可以成功运行,但如果现在不通过war部署,直接通过目录结构部署应用会不会又出现找不到资源的错误呢?请来看看ServletContext.getResourceAsStream的API文档,

Returns a URL to the resource that is 
mapped to a specified path. The path 
must begin with a "/" and is interpreted
as relative to the current context root. 
This method allows the servlet container 
to make a resource available to servlets
from any source. Resources can be located 
on a local or remote file system,
in a database, or in a .war file.



可见,通过getResourceAsStream可以获取包括本地文件系统、远程文件系统、war包等资源。不会出现上面担心的问题。

结论:在开发J2EE Web应用时,如果需要读取本应用中的文件,尽量使用ServletContext.getResourceAsStream进行,而不要使用文件IO

 

System.out.println(this.getServletContext().getResourceAsStream("/WEB-INF/classes/log4j.properties"));

 

1.关于request.getRealPath
问题:
String filename=request.getRealPath(filename)
-------------------
信息:
warning: [deprecation] getRealPath(java.lang.String) in javax.servlet.ServletRequest has been deprecated

解决:
这个getRealPath方法已经不建议使用了

参看request.getRealPath的java doc:
Deprecated. As of Version 2.1 of the Java Servlet API, use ServletContext.getRealPath(java.lang.String) instead. 


而在servlet中使用getServletContext.getRealPath()这个方法受到war 和non-war的影响,以及不同app server实现的影响,运气好的话,你常常会得到null,嘿嘿,比如你在weblogic上部署war文件,又调用这个方法..

推荐ServletContext.getResourceAsStream


2.关于serveletContext.getRealPath返回NULL和不同的app server返回不同的结果

问题:

有几个配置文本配置文件(是一些报表的模板),放在WEB-INF下面的config目录下,程序中是这样得到这个config的实际路径的:
先用 serveletContext.getRealPath得到根路径,tomcat中比如是
c:\tomcat\webapp\test

然后我加上 "/WEB-INF/config/aa.config",这样得到文件的path然后进行读入,应用在tomcat上跑是ok的,后来将war放到weblogic上,出错,原因是:
在weblogic上用getRealPath得到的是像
myserver\stage\_appsdir_test_war\test.war!\WEB-INF\config....
这样的路径,于是一直报FileNotFoundException

解决:

serveletContext.getRealPath
这个方法在不同的服务器上所获得的实现是不一样的,建议是通过classloader来获得你配置的资源文件

context.getRealPath("/")可能返回了null,你可以输入来看看,
对一个打包的应用来说,是没有RealPath的概念的,调用getRealPath只会简单地返回null。其实,也很

好理解,一个文件被打包入了.war文件,就不存在目录结构了(虽然包中仍然存在目录结构,但这不等同于文件系统中的目录结构)。所以,对war包中的资源是无法得到RealPath的。这样也就无从通过文件IO进行读取了。

那么,如何读取war包中的资源呢?答案是使用:
ServletContext.getResourceAsStream("/WEB-INF/config/aa.config")方法。


原则:基本上就是尽量使用j2ee规范中的各层次classloader来获取资源,而不是试图去找文件的绝对路
径
方法:调用this.getClass().getClassLoader().getResource("/").getPath(); 获取到classes目录的全路径

使用:在得到classes目录的全路径后再根据字符串的截取与拼装达到你的要求即可。




   绝对不要使用ServletContext的getRealPath方法获取Web应用的路径!应该使用ServletContext的getResource()方法,直接使用相对于Web应用根目录的相对路径来获取资源。


ServletContext接口中定位资源的方法
getResource
java.net.URL getResource(java.lang.String path)
throws java.net.MalformedURLException
Returns a URL to the resource that is mapped to a specified path. The path must begin with a "/" and is interpreted as relative to the current context root. 
This method allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file. 
The servlet container must implement the URL handlers and URLConnection objects that are necessary to access the resource. 
This method returns null if no resource is mapped to the pathname. 
Some containers may allow writing to the URL returned by this method using the methods of the URL class. 
The resource content is returned directly, so be aware that requesting a .jsp page returns the JSP source code. Use a RequestDispatcher instead to include results of an execution. 
This method has a different purpose than java.lang.Class.getResource, which looks up resources based on a class loader. This method does not use class loaders. 
Parameters:
path - a String specifying the path to the resource 
Returns:
the resource located at the named path, or null if there is no resource at that path 
Throws:
java.net.MalformedURLException - if the pathname is not given in the correct form

--------------------------------------------------------------------------------

getResourceAsStream
java.io.InputStream getResourceAsStream(java.lang.String  path)
Returns the resource located at the named path as an InputStream object. 
The data in the InputStream can be of any type or length. The path must be specified according to the rules given in getResource. This method returns null if no resource exists at the specified path. 
Meta-information such as content length and content type that is available via getResource method is lost when using this method. 
The servlet container must implement the URL handlers and URLConnection objects necessary to access the resource. 
This method is different from java.lang.Class.getResourceAsStream, which uses a class loader. This method allows servlet containers to make a resource available to a servlet from any location, without using a class loader. 
Parameters:
path - a String specifying the path to the resource 
Returns:
the InputStream returned to the servlet, or null if no resource exists at the specified path

getRealPath
java.lang.String getRealPath(java.lang.String path)
Returns a String containing the real path for a given virtual path. For example, the path "/index.html" returns the absolute file path on the server's filesystem would be served by a request for "http://host/contextPath/index.html", where contextPath is the context path of this ServletContext.. 
The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive). 
Parameters:
path - a String specifying a virtual path 
Returns:
a String specifying the real path, or null if the translation cannot be performed

说明
可以看到,ServletContext接口中的getResource()等方法,可以找到任何从应用程序的根目录开始的资源。包括在.war包这样的压缩文件中。参数必须以/开头。
而我们常用的getRealPath(“/”)方法,在.war包发布时,就会失效。会返回null。
因此,我们应该避免使用getRealPath(“/”)这样的方法来获取应用程序的绝对路径。

 

分享到:
评论

相关推荐

    ServletContext

    5. 资源访问:`getResource`和`getResourceAsStream`可以访问Web应用类路径或Web-INF目录下的资源。 三、在Myeclipse中使用`ServletContext` 在Myeclipse中,我们可以方便地在Servlet中获取`ServletContext`实例,...

    servlet中的ServletContext的使用

    `getResource()`返回一个`URL`,而`getResourceAsStream()`则返回一个`InputStream`。 4. **广播事件**:` ServletContext`支持` ServletContextEvent`,可以在一个Servlet中触发事件,然后由其他注册的监听器接收...

    关于java和web工程项目中各种路径的获取总结借鉴.pdf

    这里通过`this.getServletContext()`获取当前Servlet的`ServletContext`对象,然后通过`getRealPath("/")`方法获取Web项目的根目录路径。 2. **从`HttpServletRequest`出发** ```java String cp11111 = request...

    JAVAweb开发14566PPT课件.ppt

    - `getResourceAsStream(String path)`: 获取资源的InputStream,相当于`getResource(path).openStream()`。 - `getRealPath(String path)`: 返回相对于Web应用根目录的文件系统路径。 例如,用于下载文件的`...

    Servlet代码

    5. 路径操作:`getContextPath()`方法返回Web应用的根路径,而`getResource()`和`getResourceAsStream()`可以获取Web应用内资源的URL或输入流。 6. 通知其他Servlet:通过`广播事件`,例如使用`ServletContextEvent...

    API读取Properties文件的六种方法

    throw new ServletException("Could not find resource: " + path); } Properties p = new Properties(); p.load(in); // 示例:获取配置文件中的属性 String dbUrl = p.getProperty("db.url"); System.out....

    javaweb 读取 classes 下的文件

    `ServletContext`提供了`getResourceAsStream()`和`getResource()`方法。例如: ```java ServletContext context = servlet.getServletContext(); InputStream inputStream = context.getResourceAsStream("/WEB-...

    ServletContext读取web资源_动力节点Java学院整理

    根据给定的文件信息,我们来详细探讨ServletContext读取web资源的知识点: ### ServletContext概述 ServletContext是Java Servlet API中的一个接口,它表示一个web应用的所有环境信息和web服务器相关的一些环境信息...

    获取路径的各种方法

    而如果是在类路径中查找资源,`getResource()`和`getResourceAsStream()`更适合。对于客户端的资源,如用户上传的文件,`getParameter()`和ActionForm的属性就显得尤为重要。 总之,掌握这些获取路径的方法,能够...

    35、servlet--servletContext

    3. **资源加载**:可以通过`getResource()`和`getResourceAsStream()`方法获取Web应用根目录下的资源,例如读取配置文件、图片等。 4. **请求转发和重定向**:`getRequestDispatcher()`方法可以获取到`...

    JavaWeb_servlet(10)_ 通过 ServletContex 获得根目录下的文件路径

    此时,我们可能需要寻找其他方式来处理文件,例如使用`getResourceAsStream()`方法来读取资源,或者使用Spring框架提供的Resource对象。 在Servlet中,我们通常在Servlet初始化时获取ServletContext,这可以通过...

    ServletContext接口

    `getResource(String path)`方法根据给定的路径返回一个`java.net.URL`对象,该路径通常以“/”开头,表示相对于当前Web应用根目录的位置。通过`getResourceAsStream(String path)`方法,可以直接读取资源的内容作为...

    JavaWeb_servlet(11)_ 通过 ServletContex 获得类路径下的文件路径

    2. `getResource()`和`getResourceAsStream()`:这两个方法用于获取URL资源和对应的输入流。如果你只想读取文件内容,而不需要文件系统路径,可以使用它们。例如: ```java ServletContext context = ...

    servletcontext详解

    - **`getResourceAsStream(String path)`**:返回一个用于读取指定文件的输入流。 - **`getMimeType(String file)`**:返回给定文件的MIME类型。 ##### 5. 输出日志 - **`log(String msg)`**:向Servlet的日志文件...

    servlet2.4doc

    A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both. Filters perform filtering in the ...

    javaservlet连接mysql数据库.pdf

    在Servlet类中,通过调用`ServletContext`的`getResource()`或`getResourceAsStream()`方法,以及`InitialContext`的`lookup()`方法,可以获取到`DataSource`实例,然后使用`getConnection()`方法建立到数据库的...

    ServletContext中常用方法介绍

    Servlet上下文(ServletContext)是Java Servlet API中的一个核心接口,它代表了Web应用的全局共享数据和环境信息。在开发基于Servlet的Web应用时,ServletContext提供了一个在所有Servlet和JSP页面之间共享信息的...

    JAVA servlet API说明文档

    9. getResourceAsStream(String path):返回指定路径资源的输入流。 10. getRequestDispatcher(String path):返回一个RequestDispatcher对象,用于请求转发和包含。 11. getServerInfo():返回服务器的信息字符串。...

Global site tag (gtag.js) - Google Analytics