maven 打包时缺少文件_(三)Java资源文件和路径相关扫盲
本来打算接着上文直接写登录功能的,顺便介绍下SpringSecurity,但是SpringSecurity和Spring以及SpirngBoot是如何衔接的又是个较为复杂的事情。看了下SpringBoot的启动过程之后,发现里面很多地方用到了类加载器以及Classpath等。其实如果没用过Eclipse写过传统的java项目或者web项目,经常会对ClassPath,根目录,类加载器,jar包格式,war包格式等迷糊,所以一方面自己总结下,一方面也给大家扫下盲。
一、Jar包和War包
通常来说java可以分为普通项目和web项目。普通项目的运行我们需要自己写一个main函数,然后以这个main函数作为入口启动项目。而web项目则需要交给servlet容器去启动,通常是tomcat或者jetty。web项目的启动过程是一个十分复杂的事情,不过目前我们不用关心细节,毕竟是一篇扫盲文章。
1、什么是打包
除了SDK以外,一个项目我们写完之后都需要部署到linux服务器上运行。但是并不是直接部署项目源码到linux上,而是经过编译,打包后的"包"。整个过程我们称之为构建(build),后端常用的构建工具也就那几个,当然最简单也最普遍的就是maven了。编译和打包对应到maven命令则分别是compile和package。
mvn compile可以将.java文件编译成.class文件,也就是将源码转化为字节码,即一次编译到处运行的编译过程。
mvn package则将编译后的.class文件和相关的资源配置如.properties配置文件.xml配置文件按照约定或者我们自己的配置整合到一个jar包或者war包中。至于如何整合,以及最终是jar包还是war包,要根据我们的配置来决定,maven的配置文件就是项目根目录下的pom.xml文件。
所以打包可以有两个概念,术语来说就是指mvn package这一步,如果是我们口头上常说的打包其实就是整个构建过程。
2、如何打包
目前市场上最常用的构建工具要属maven(其他的还有ant,gradle等就不介绍了)。
首先我们使用idea创建一个maven项目:File -> New -> Project,然后一路点next就行
![](/assets/blank.gif)
这样我们就创建了一个最基本的maven项目,如下图所示
![](/assets/blank.gif)
可以看到,我们通过maven创建的项目,已经有了自己默认的目录结构。这里不得不提到这个目录结构的由来,即maven的核心思想:约定先行于配置。只要知道了这个,maven的神秘面纱就基本揭开了。
maven为什么要提供这样一个默认的结构?这个目录结构又有什么用呢?
maven给我们提供的这个默认的结构其实就是对我们的约定,即认为我们的项目目录结构就是这个样子,并没有自己的改动。如果我们遵守了这个约定,则我们在不需要自己额外配置的情况下,可以对项目进行正确的构建。
因为jar和war都是有着严格格式要求的,所以正确的构建就是指打包后的项目目录格式能够满足规定的格式要求。综合起来就是如果我们的项目结构和maven约定的结构相同,则我们可以直接使用mvn package进行打包,无需在pom.xml文件中进行额外配置。当然如果我们想应用自己的目录结构,也可以在pom.xml文件中配置相关内容,让项目正确构建。pom.xml就是maven的相关配置文件。
JAR包:
用刚才创建的项目,我们先在java目录下创建一个类,然后再运行mvn package就可以进行一次打包:
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
虽然我们只运行了一个mvn package命令,但是从构建日志上来看,似乎运行了很多插件。没错,mvn package并不只是运行package插件,而且根据maven的插件生命周期运行package和它之前的所有插件。
package之前最重要的一步就是compile,打包的也是编译后的文件夹。图上有个黄色的target文件夹就是编译后的文件。而这里有个classes目录,就是所谓的ClassPath,这个概念之后我们会经常遇到,java项目所有的相关内容编译后都会直接放在ClassPath下。
target是编译后的目录,但仍需要将编译后的文件夹转化为jar文件。我们打开打包后的jar包。
![](/assets/blank.gif)
可以看到target/classes目录下的内容直接放到了jar包的根目录,并且多了个META-INF文件夹。至于META-INF文件夹有什么作用,暂且可以不用知道,不过我们目前可以确定的就是,ClassPath对应着Jar包的根目录,对应着编译后的target的classes目录。
WAR包:
和jar包不同但经常使用到的就是web项目打包后的war包了。我们重新创建一个项目,并且使用maven提供的约定好的web项目的目录结构:maven-archetype-webapp
![](/assets/blank.gif)
创建完成的项目基础结构如下
![](/assets/blank.gif)
我们可以发现main目录下还缺少一个java目录,我们需要自己添加一个java目录,并且设置成Root目录,resources目录设置成Source目录,然后创建一个java类,至此一个基本的web模型已经创建完成了。
![](/assets/blank.gif)
接下来就是打包测试,我们运行mvn package命令:
![](/assets/blank.gif)
如同普通java项目一样,项目结构中多了个编译后的target文件夹。只不过我们需要注意两个子文件夹,分别是classes和web。classes文件夹下存放的依然是编译后的.class文件,而原来的webapp目录编译后则变成了web目录,并且将WEB-INF目录保留了下来。另外你会发现,classes文件夹在WEB-INF下也有一个。这两个classes文件夹是一模一样的。我们来打开war包看看:
![](/assets/blank.gif)
和web目录一模一样。所以我们可以得出一个结论就是:ClassPath在web项目中就是/WEB-INF/classes目录。
另外无论是java项目还是javaweb项目,都会有个resources文件夹,你试一下就可以知道,这个目录下的内容打包后都会被复制到ClassPath目录下。
![](/assets/blank.gif)
![](/assets/blank.gif)
通常上面的测试我们可以了解到,jar包和war包的固定格式。通常来说我们不需要自己去打破约定,按照自己的方式设置项目目录,因为项目毕竟是很多人在同时完成,还是需要有一定的标准。
二、资源文件的加载
通过上面的介绍我们现在已经很清楚什么是ClassPath路径了对吧。下面我们来了解一下Java项目中资源文件的加载。
Java项目中加载资源文件通常有两种方式:1、Class.getResource(String path)
2、Class.getClassLoader().getResource(String path)
这两种方式有一些区别,首先来看1:
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
可以看出,如果是绝对路径,则绝对路径的起点为ClassPath,如果为相对路径,则路径的起点为该类的所在目录,也就是图中的TestClass所在的目录。
然后来看2,依旧是上面那个项目结构:
![](/assets/blank.gif)
![](/assets/blank.gif)
可以看出如果使用类加载器加载资源,则只能填入相对路径,且路径的起点一定是ClassPath,而且跟这个类在哪没有任何关系。
三、环境变量相关资源
在了解ClassLoader体系之前我们应该先了解一下我们刚学Java时最头疼的问题,环境变量。
大家对JDK和JRE一定不陌生,其中JRE是Java的运行环境,而JDK包含了JRE。
![](/assets/blank.gif)
JDK比JRE多出来的东西主要就是bin目录下的一些exe程序,提供给我们一些强大的开发工具。常用的有javac、java、javap等。
![](/assets/blank.gif)
回想一下,学习Java的时候我们配置过三个环境变量:
JAVA_HOME:JDK的安装目录
![](/assets/blank.gif)
CLASS_PATH:指向系统JAVA_HOME所在路径的lib文件夹或者其下面的jar包
![](/assets/blank.gif)
PATH:添加到PATH路径下的exe文件,可以在cmd中直接使用。所以通常是将JAVA_HOME所在路径的bin文件夹添加到PATH,这样就能在cmd命令行中直接使用java、javac等命令了。我们在学习Mysql时配置Path同样是这个原因。通过这里我们又学到了一个CLASS_PATH,只不过这里指的是系统变量。
最后附上一条个人认为目前看到过写的最全的一个关于类加载器的一篇文章,不过文章中有些地方有点错误,比如引导类加载器加载的并不是JAVA_HOME路径下的类,而是JRE_HOME下的类。
https://blog.csdn.net/javazejian/article/details/73413292blog.csdn.net
maven 打包时缺少文件_(三)Java资源文件和路径相关扫盲相关推荐
- maven 打包时缺少文件_解决Intellij Idea下使用Maven项目打包时部分文件缺失问题
问题 Idea被越来越多的java开发者青睐,特别是丰富的插件极大方便了开发者.Idea虽然没有Eclipse的繁琐配置,但也会出现一些问题.问题如下: 一.在进行Maven项目打包的时候,会发现有的 ...
- maven 打包时缺少文件_maven父子工程---子模块相互依赖打包时所遇到的问题:依赖的程序包找不到...
场景: 因为之前用到的是,基于springboot框架所搭建的maven工程,而且都是相互独立的.现研发经理要求将所有工程进行整合和规范化,所以抽出一个parent父工程,base基础模块(包含一些公 ...
- 解决Eclipse建立Maven项目后无法建立src/main/java资源文件夹的办法
2019独角兽企业重金招聘Python工程师标准>>> 建立好一个Maven项目后,如果Java Resources资源文件下没有src/main/java文件夹,并且在手动创建这个 ...
- cmd 将文件夹下文件剪切到另外一个文件_总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇...
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- Java实现剪切MP3格式的文件_总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇...
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 很多朋友在看我的<java IO总结系列>之前觉得创建文件.文件夹删除文件这些基础操作真的是太简单了.但看了我的文章之后,有小 ...
- java编译过程中产生哪些文件_编译Java源程序文件后将产生相应的可执行字节码文件,这些文件的扩展名为( )。...
编译Java源程序文件后将产生相应的可执行字节码文件,这些文件的扩展名为( ). 答:class 恒温下,对同一反应来说,下列叙述正确的是 答:转化率和平衡常数都可以表示化学反应的进行程度 老瞎子在一 ...
- java中怎么剪切文件_总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 很多朋友在看我的<java IO总结系列>之前觉得创建文件.文件夹删除文件这些基础操作真的是太简单了.但看了我的文章之后,有小 ...
- 文件_ _android从资源文件中读取文件流并显示的方法
======== 1 android从资源文件中读取文件流并显示的方法. 在android中,假如有的文本文件,比如TXT放在raw下,要直接读取出来,放到屏幕中显示,可以这样: private ...
- java工程打包时进行签名_使用Java SDK实现离线签名
严格来说,tx-signer并不属于SDK,它是bytomd中构建交易.对交易签名两大模块的java实现版.因此,若想用tx-signer对交易进行离线签名,需要由你在本地保管好自己的私钥. 如果你的 ...
最新文章
- 基于SSM实现的民宿网站系统
- BC之链式块状结构:区块链之链式块状结构——链式块状结构、内容相关配图
- 百度健康打通医药电商服务
- HDU 1517 A Multiplication Game
- ref获取元素 vue 删除子元素_vue中的 ref 和 $refs
- 数据分析数据拼接案例
- 充实你的素材库!10款免费的 PSD 素材下载
- bootstrap table 的简单Demo
- 【计算机网络】传输媒体与物理层概念辨析
- 程序员---不要对自己说“不可能”
- 14 SD配置-企业结构-分配-分配销售组织-分销渠道-工厂
- SpringCloud04 服务配置中心、消息总线、远程配置动态刷新
- 电子商务ICP经营许可证申请条件
- PL/SQL 12.0配置连接远程Oracle数据库
- 沿着哈勃望远,看清MyBatis整体架构
- 安装SQL Server 2012时报.net framework 3.5错误
- Pascal 转 C++ 教程2
- 装机必备的浏览器推荐,干净好用,选这4款不会出错
- 什么是二维码?为什么需要一个二维码?
- 17位时间戳转换为Unix时间戳及转换工具,代码实现转换 WebKit/Chrome Timestamp Converter
热门文章
- tomcat和idea都占用了8080_IDEA 启动tomcat 端口占用原因以及解决方法( 使用debug模式)...
- python中lines是什么类型_python里的splitlines详解
- SD和TF两种卡片的区别
- php与mysql店事物处理_PHP与MYSQL事务处理
- python 排序统计滤波器_马尔可夫链+贝叶斯滤波器的Python展示
- Altium designer中提示some net were not able to be matched问题解决办法
- windows下挂载ext4_WSL2 支持挂载物理磁盘,Windows 可直接访问 ext4
- mysql中的逻辑类型如何定义_MYSQL存储过程即常用逻辑知识点总结
- ireport修改jrxml中的sql语句_SQL中的create table与insert into语句
- pyenv 让 python 版本完美切换