java路径踩坑,详踩!

关于java文件的运行原理都是首先转化成二进制的.class文件,然后交给java虚拟机去运行。但是我们在开发工具中,都是在src下面做开发的,我们怎么知道当前java运行的路径在哪里呢?

       所以我们需要去了解java在开发和实际运行中的区别:

      

      

在普通java工程下:

       我们首先进行分析(我们可以直接到盘符下,将我们的项目ctrl+c,然后利用xmind工具:思维导图工具,进入之后ctrl+v,它就会帮我们列出目录结构和文档类型):

 

这里就可以看出,其实虽然我们开发是在src目录下开发的,但是其实是运行是在bin目录下运行的,因我们都知道java文件运行是依靠.class文件的,我们就可以去对比bin目录和src目录的区别:

       我们发现,src和bin目录下的文件除了.java文件和.class的文件,其它的目录结构和文件一模一样,所以我们得出,bin目录才是我们运行java项目的实际目录,并且结构和开发目录src完全相同(注意,所有在src目录下的文件都会拷贝过去,图片,文本等等:包括后缀为.css、.xml、.properties的各类文件)!

 

所以我们才能在普通java项目中直接使用相对路径,按照src下的目录结构都是能直接访问的。但是这里我们需要注意:在普通java项目中我们最好使用相对路径,因为类似这种绝对路径:

FileInputStream fis =new FileInputStream(“/内容详情.txt”);// 但是我们不建议名称使用中文

是肯定会出错的,在普通java文件下,直接‘/’绝对路径就到了盘符下了例如:E:/

 

那么怎么使用相对路径?我们怎么知道当前的相对路径在什么地方?那我们首先就要了解普通java项目运行的根目录在哪里:

File测试法:

首先我们在我们的xml项目下的src中新建一个test包,在test包下新建一个TestPath的java文件。

以上可以看出,不管我们的.java文件运行在哪个包下,项目的运行路径(即:当前路径),总会被置回到项目路径下。

 

所以在这里使用相对路径更好:

例如我要访问上面的:内容详情.txt

1)     InputStreamin = new FileInputStream("./src/jdbc.properties");

2)     InputStreamin = new FileInputStream("./bin/jdbc.properties");

 

这两种方式都可以获取,理解了以上的讲解我们就明白了。(” ./”代表当前路径

在web项目工程下:

Web的目录结构和普通java工程在开发工具中,几乎一样,但是在运行的时候,目录结构完全不同;我们知道普通java项目是将.java文件编译成为二进制的.class文件之后,按照和src目录下同样的目录层次生成在bin目录下,其它位于src下的文件原封不动的拷贝到bin目录下;(如果有位于src外的类似lib之类的jar包目录,在生成自己的可执行jar包的时候,需要拷贝到和bin同级的目录下,这一点需要注意!)

 

我们来分析web项目的运行:

 

我们可以看出在web目录中,所有的src中的文件(除了.java)文件都被原封不动的拷贝到了webRoot下的WEB-INF中的classes中,而之前我们说的lib也同样位于和classes同级的目录下,而.java文件也同样被编译成二进制的可执行文件放到了classes下的和src中同样层次的目录下了,但是普通java文件不同这里没有了bin目录,注意:这里的根目录是classes,不是webRoot;因为我们的java文件可以“触摸”到的最大的范围就是在classes下,可以看出classes外的文件都和.class文件没有直接关系了。

 

 

File测试法:

同样我们新建一个TestPath的web项目,在下面新建一个servlet包,在其中新建一个TestPathServlet的servlet:

在eclipse中测试:

在myeclipse中测试:

可以看出这里的当前路径就和我们的项目没有半毛钱关系了!为什么呢?

因为我们的IDE的开发环境下的运行原理是,开发web项目每次运行之后,都会把路径切换到工具运行的目录下!!!这个路径对于我们开发者来说也没有任何意义,因为当我们的项目具体跑在tomcat上时,依照的目录和这个目录完全不同:

使用绝对路径:

       使用盘符绝对定位;

使用相对路径:

       将你要读的文件放在上面file测试出来的位置;

以上两种方式理论上是可以的,但是只是开发的时候管用,但是当将项目转到Tomcat上之后必然出错!!!

 

这里就可以看出Servlet中提供的ServletContext的getRealPath()方法的重要性了!(获得以当前项目为根目录的绝对路径)

 

Servlet中通过servletConfig对象去获得servletContext对象,然后ServletContext中提供了两种方法:

1) 获得绝对路径:getRealPath(“参数”);  // 其中的参数是具体的文件名,也可以用”.”,” .”都代表当前路径,这种用法很重要!

 

 

2)获得上下文路径的方法:getContextPath();获取当前的相对路径,即项目名

 

      

【java设计者,为了简便开发者的操作,提供的跳过ServletConfig直接获取Context的方法,但是其实底层代码实现还是通过调用ServletConfig获得的】

我们测试运行此方法:

 

 

【注意我们当前的项目名称叫做TestPath】:

开发环境中的视图:

实际运行的时候在tomcat中的路径的视图:

这里我将TestPath项目运行到【Tomcat下的webapps中】:

【通过getRealPath(“参数”):获得当前项目的绝对路径,然后得到其中的hello.txt】:

FileInputStreamfis = new

FileInputStream(this.getServletContext().getRealPath(".")+

"/WEB-INF/classes/hello.txt");

 

补充:

    当然读者认为我这种先找路径再new流对象的方式过于繁琐,其实也有一体的,这里就不再累述:getResourceAsStream(),可以达到获得路径,并且new 流对象两步一体;

请自行查阅!

如何在web和普通java项目下都适用呢?

举一个最简单的例子,在操作jdbc中,我们new一个JDBCUtil工具,但是因为用户名、密码、URL和导入驱动包的全路径,这四者是在我们工具中可能回重复修改的四个属性,为了我们的代码更友好,我们应该将这个四个字段抽离出来,例如的放到一个properties的文件中,利用集合的Property进行从.properties文件中进行读取。

但是我们的数据库连接不是只在web或者普通java项目中使用吧?怎么能在目录结构大不相同的两个工程中同样适用呢?

这里就需要使用到 Class.getResourceAsStream:

此方法怎么使用呢?其实就是相对路径的高级运用,首先我们随意获得项目下一个类的class对象,通过这个类的class对象我们可以获得当前的绝对路径,然后在当前路径上做变换,直接获得我们需要的文件的流!(因为此方法高级剖析涉及类加载器,如有兴趣,请读者自行查阅):

同样是File测试法:

首先在eclipse中的普通java项目下:

通过 ”.” 获得当前路径

数据库驱动加载成功,且当时sysout的路径为:

 

通过 “/” 获得当前路径下的运行根目录:

注意我们的目录结构:

【以下web目录中同样,不再赘述】

 

 

在myeclipse中的web项目下:

通过 ”.” 获得当前路径:

 

数据库驱动加载成功,且当时sysout的路径为:

 

通过 “/” 获得当前路径下的运行根目录:

 

以上也验证了我们在普通java项目下运行的根目录为bin目录;

在web项目下的运行根目录为classes目录;

 

 

 

总结:

在用File法进行测试的时候:

相对路径:” .” 代表当前目录,当前目录的本质就是java命令的运行目录!

Java项目:” .” 代表当前目录,及项目的根目录!

 

Web项目下 ‘.’当前目录指向%tomcat%的bin目录,因为tomcat的命令是在bin目录下启动的,运行目录就在Tomcat的bin下。在web项目下就不能使用相对路径!

 

在普通java项目中我们可以随意的使用相对路径,因为bin目录和src的相同性;避免使用绝对路径,绝对路径一跳就到了盘符根目录下了。

但是在web项目下,我们就要尽量使用绝对路径;数量使用ServletContext提供的getContextPath和getRealPath方法;

 

但是最大适用性上class对象. getResource()和class. getResourceAsStream是最好的选择!

学习参考:

https://blog.csdn.net/my__sun_/article/details/74450241

感谢!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值