首页 Java java教程 Java中如何利用ServletContext读取web资源的图文详解

Java中如何利用ServletContext读取web资源的图文详解

Jul 26, 2017 pm 03:13 PM
java web

这篇文章主要介绍了ServletContext读取web资源,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

ServletContext类中有这么四个方法:

  1. getRealPath(String path)

  2. getResource(String path)

  3. getResourceAsStream(String path)

  4. getResourcePaths(String path)

这四个方法都使用web工程下某个web资源路径的字符串表现形式作为参数,而每个方法返回不同的类型,我们通过这四个方法之一可以获取某个资源,并对其进行读取和修改操作。

假设我们的【myservlet】web工程中有一个数据库的配置文件:database.properties,在这个数据库中已经有了一些参数,而我们在web工程中希望读取这个配置文件中的有关信息:

先来看看ServletContext中的getResourceAsStream()方法,这个方法返回InputStream对象。由于我们的配置文件为properties文件,所以可以用Properties对象来装载这个输入流,代码如下:


 public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
     ServletContext context = this.getServletContext();
     InputStream in = context.getResourceAsStream("/database.properties");
     
     Properties prop = new Properties();
     prop.load(in);
     
     String url = prop.getProperty("url");
     String username = prop.getProperty("username");
     String password = prop.getProperty("password");
     System.out.println(url);
     System.out.println(username);
     System.out.println(password);
   }
登录后复制

最后在浏览器中访问这个Servlet,那么在MyEclipse的控制台上能看到的数据正好是database.properties中我们配置的信息:

接下来看看ServletContext中的getRealPath()方法,这个方法返回String对象。由于我们的配置文件为properties文件,所以可以用Properties对象来装载这个输入流,代码如下:


   ServletContext context = this.getServletContext();
     String filePath = context.getRealPath("/database.properties");
     
     FileInputStream fis = new FileInputStream(filePath);
     Properties prop = new Properties();
     prop.load(fis);
     
     String url = prop.getProperty("url");
     String username = prop.getProperty("username");
     String password = prop.getProperty("password");
     System.out.println(url);
     System.out.println(username);
     System.out.println(password);
登录后复制

最后在浏览器中访问这个Servlet,那么在MyEclipse的控制台上能看到的数据正好是database.properties中我们配置的信息:

使用getRealPath()方法的好处在于这个方法还可以获取文件名,而getResourceAsStream()方法就只能获取文件流了。例如获取文件名:


    ServletContext context = this.getServletContext();
     String filePath = context.getRealPath("/WEB-INF/web.xml");
     System.out.println(filePath);
     
     if(filePath == null) {
       System.out.println("所找文件不存在!");
     }
     String fileName = filePath.substring(filePath.lastIndexOf("\\"));
     System.out.println("文件为:"+fileName);
登录后复制

接着来看看ServletContext中的getResource()方法,这个方法返回URL对象。而URL对象具有打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream的openStream()方法。由于我们的配置文件为properties文件,所以可以用Properties对象来装载这个输入流,代码如下:


    ServletContext context = this.getServletContext();
     URL fileUrl = context.getResource("/database.properties");
     InputStream in = fileUrl.openStream();
     
     Properties prop = new Properties();
     prop.load(in);
     
     String url = prop.getProperty("url");
     String username = prop.getProperty("username");
     String password = prop.getProperty("password");
     System.out.println(url);
     System.out.println(username);
     System.out.println(password);
登录后复制

最后在浏览器中访问这个Servlet,那么在MyEclipse的控制台上能看到的数据正好是database.properties中我们配置的信息:

以上说完了几种通过ServletContext对象来读取web应用下的某个资源文件,只要通过读取的方法,并将资源相对于web工程的路径作为参数传入其中便可。我们上述的例子都是直接在web工程中,或者web工程的某个目录下,而如果我们把某个web资源放置在MyEclipse中的【src】目录中,那么该如何读取呢:

我们说过,这个web应用在发布时,会将【src】目录下的.java文件编译成为.class字节码文件,由服务器自动将这些字节码文件放置在该web应用中的【WEB-INF】下的【classes】目录里,如果没有【classes】目录,服务器会自动帮我们创建,因此,只要是放置在【src】目录中的资源,最后也会被服务器自动放置在【classes】目录中,这样我们可以继续通过ServletContext对象来获取:


    ServletContext context = this.getServletContext();
     InputStream in = context.getResourceAsStream("/WEB-INF/classes/database.properties");
     
     Properties prop = new Properties();
     prop.load(in);
     
     String url = prop.getProperty("url");
     String username = prop.getProperty("username");
     String password = prop.getProperty("password");
     System.out.println(url);
     System.out.println(username);
     System.out.println(password);
登录后复制

关于web工程下某个web资源在不同位置下的问题:

问题一:我们为什么不能用传统方式,如FileInputStream或者File对象来直接获取web工程中的资源呢?其实也是可以的,但是有个路径的问题,Servlet中方法所需要的路径都是相对于web应用的路径,而传统的FileInputStream等等中方法所需的路径参数都是相对于虚拟机的路径。而又因为我这个web应用是从MyEclipse中的Tomcat里启动的,所以这时候的虚拟机目录其实是Tomcat中的【bin】目录。所以如果想用传统方式读取文件必须每次都将文件放置在Tomcat的【bin】目录下, 这是多么麻烦的事,因此我们开发web工程就应该使用web工程中的方法来读取文件!但是,这却又引出了问题二。。。

问题二:当我们web工程中有别的非Servlet的类时,比如JavaBean,当JavaBean需要连接数据库时,这就是非Servlet对象读取web工程中的资源文件了,不能用ServletContext来读取,问题一种也说过不能用传统方式如FileInputStream来读取,那么该如何读取呢?

答案是:类加载器!由于在【src】目录下的Java程序经过编译成字节码class文件,如果要用到这些类,Java虚拟机需要先将这些字节码文件加载到内存中才可以使用,而这个过程就是由类加载器来完成。因此这就有一个知识点,如果我们将某个web资源放置在【src】目录下,因为这是个web工程,服务器会自动将各个字节码文件重新放置在【classes】目录下, 而这个web资源也会重新被服务器放置在【classes】目录下,那么类加载器能加载【classes】目录下所有的字节码文件,同时,同处在这个目录下的web资源也会被类加载器加载进内存,这时我们就可以使用类加载器读取该web资源了。

例:在【myservlet】的dao包中创建一个Student的JavaBean对象,并在src【目录下】创建一个student的配置文件student.properties,而这个配置文件内容如下图所示:

在Student类中,我们需要通过类加载器来获取输入流来读取这个文件:


 public class Student {  
   public void getStudent() throws IOException {
     ClassLoader loader = Student.class.getClassLoader();
     InputStream in = loader.getResourceAsStream("student.properties");
     
     Properties prop = new Properties();
     prop.load(in);
     
     String studentName = prop.getProperty("name");
     String studentAge = prop.getProperty("age");
     System.out.println(studentName+":"+studentAge);
   }
 }
登录后复制

另外创建一个Servlet作为可以供浏览器访问的对象,在该Servlet中创建Student的示例来获取配置文件中的内容,这样就达到了从非Servlet对象读取web资源内容并向Servlet对象传递数据:


 public class ServletDemo extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
 
     Student student = new Student();
     student.getStudent();
   }
 }
登录后复制

从浏览器中访问该Servlet,可以看到通过类加载器读取的配置文件中的内容:

注意,这种方法只能是web资源放置在【src】目录中才可以使用,如果要读取的web资源是放置在web工程的目录下,使用类加载器也还是无法读取,因为类加载器只能读取类目录下的文件,这时候非Servlet类就无法读取资源文件,只能使用ServletContext来读取了。

方立勋老师说:“类加载器只能加载【classes】目录下的所有文件一次,这样在服务器运行web工程的过程中,如果我们修改【classes】目录下的student.properties配置文件,则由于类加载器不再加载,因此使用类加载器的方式不能读取修改后的内容”

但是我修改后,还是可以使用类加载器的方式读取classes】目录下修改后的student.properties配置文件,难道是因为JDK7的原因吗?

不过不管是什么原因,方立勋老师针对他的问题所采取的解决方案还是值得学习的,他采用先用类加载器获取该配置文件的路径,然后再采用传统方式获取这个文件的输入流。所以在Student中的getStudent()方法代码改为:


 public class Student {  
   public void getStudent() throws IOException {
     ClassLoader loader = Student.class.getClassLoader();
     URL fileUrl = loader.getResource("student.properties");
     String filePath = fileUrl.getPath();
 
     FileInputStream fis = new FileInputStream(filePath);
     Properties prop = new Properties();
     prop.load(fis);
     
     String studentName = prop.getProperty("name");
     String studentAge = prop.getProperty("age");
     System.out.println(studentName+":"+studentAge);  
 }
 }
登录后复制

这种方式还有一种好处就是,如果要读取的文件过大,而之前通过类加载器将大文件加载进内存就容易导致内存溢出,所以还是采用这种方式比较好。

最后再说明一点,如果是在非Servlet类中采用类加载器获取【classes】目录中的资源,方法参数的路径只需要是相对于【src】目录即可。

补充:使用类加载器加载【classes】目录中的资源,得到的路径取决是哪个虚拟机(或服务器)调用,例如上面的代码getStudent()方法,如果是在非Servlet的类的方法中被调用,那么就是使用JVM虚拟机,那么得到的资源路径并不是Tomcat的应用【webapps】目录的路径。因此如果是要为Servlet中提供资源,那么非Servlet类中获取资源的方法,请一定要使用Servlet来调用,这样才能保证得到的资源路径是在Tomcat服务器下的自己的web应用所在目录中的正确位置。

例如下面的例子,我的MyEclipse工作空间在【E】盘,而Tomcat服务器所在路径为【F】盘:


 public class ResourceUtils {
   
   public static void main(String[] args) throws IOException {
     getResource();
   }
   
   @Test
   public static void getResource() throws IOException {
     
     ClassLoader loader = ResourceUtils.class.getClassLoader();
     URL url = loader.getResource("student.properties");
     String path = url.getPath();
     System.out.println(path);
   }
 }
登录后复制

而资源为student.properties配置文件,放置的位置为【src】目录下:

这个是在我的一个web应用中定义的一个非Servlet的普通Java类,这个类无论是用JUnit测试还是使用Main函数,亦或是使用别的非Servlet类来调用getResource方法获取在web应用下【src】目录中的student.properties资源,显示的路径为MyEclipse的工作空间,而不是Tomcat服务器:

而如果是使用Servlet来调用的话,才是真正显示在Tomcat中web应用所在的地方:


 public class ServletDemo extends HttpServlet {
 
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
 
     ResourceUtils.getResource();
   }
 }
登录后复制

因此在使用web工程中,如果使用非Servlet类来获取资源,请一定注意这个资源路径问题!!!

以上是Java中如何利用ServletContext读取web资源的图文详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java 中的完美数 Java 中的完美数 Aug 30, 2024 pm 04:28 PM

Java 完美数指南。这里我们讨论定义,如何在 Java 中检查完美数?,示例和代码实现。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。这里我们通过示例讨论简介、如何使用weka java、平台类型和优点。

Java 中的史密斯数 Java 中的史密斯数 Aug 30, 2024 pm 04:28 PM

Java 史密斯数指南。这里我们讨论定义,如何在Java中检查史密斯号?带有代码实现的示例。

Java Spring 面试题 Java Spring 面试题 Aug 30, 2024 pm 04:29 PM

在本文中,我们保留了最常被问到的 Java Spring 面试问题及其详细答案。这样你就可以顺利通过面试。

突破或从Java 8流返回? 突破或从Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

Java 中的时间戳至今 Java 中的时间戳至今 Aug 30, 2024 pm 04:28 PM

Java 中的时间戳到日期指南。这里我们还结合示例讨论了介绍以及如何在java中将时间戳转换为日期。

Java程序查找胶囊的体积 Java程序查找胶囊的体积 Feb 07, 2025 am 11:37 AM

胶囊是一种三维几何图形,由一个圆柱体和两端各一个半球体组成。胶囊的体积可以通过将圆柱体的体积和两端半球体的体积相加来计算。本教程将讨论如何使用不同的方法在Java中计算给定胶囊的体积。 胶囊体积公式 胶囊体积的公式如下: 胶囊体积 = 圆柱体体积 两个半球体体积 其中, r: 半球体的半径。 h: 圆柱体的高度(不包括半球体)。 例子 1 输入 半径 = 5 单位 高度 = 10 单位 输出 体积 = 1570.8 立方单位 解释 使用公式计算体积: 体积 = π × r2 × h (4

创造未来:面向零基础的 Java 编程 创造未来:面向零基础的 Java 编程 Oct 13, 2024 pm 01:32 PM

Java是热门编程语言,适合初学者和经验丰富的开发者学习。本教程从基础概念出发,逐步深入讲解高级主题。安装Java开发工具包后,可通过创建简单的“Hello,World!”程序实践编程。理解代码后,使用命令提示符编译并运行程序,控制台上将输出“Hello,World!”。学习Java开启了编程之旅,随着掌握程度加深,可创建更复杂的应用程序。

See all articles