Maven
Maven是一个项目管理工具。
项目构建
其实就是指项目从开发到最终完成结束整个的流程。一共可以分为几个流程:
1.编译
2.测试(使用单元测试用例来测试编写的代码有没有潜在的bug,此时需要将编写好的代码放置在测试环境对应的目录下)
3.打包(服务器肯定不在本地机器上面,远程服务器上面,压缩成一个压缩包 war、jar)
4.部署上线
本地的代码需要提交到一个服务器上面去托管。 git 版本管理工具
更新失败——–回退到之前版本
分析一下整个的项目构建过程
如果不借助于ide,那么所有的事情都是自己去做的话,还是比较繁琐的。
借助于ide,虽然可以帮助我们减少部分的工作量,但是还是有一些工作必须要求我们自己去处理,
需要我们自己一个一个的去执行对应的测试用例代码(如果执行一个指令,然后就会帮我们把所有的测试代码全部执行一遍该有多好)
虽然idea也提供了给我们打包的简便处理方式,但是处理起来还是比较繁琐的,如果能够执行一个指令,就把war、jar包给打出来了,那该多好。
maven就可以帮助我们实现上述的一些假设。
借助于Maven,今后的项目构建过程个需要做的就是编写好对应的代码,然后执行对应点的指令,其他的所有事情全部都交给Maven来处理。
安装Maven
直接解压缩即可。
配置MAVEN_HOME环境变量
演示项目构建
编译
在桌面上新建了一个maven目录,在maven目录中新建了一个hello目录表示一个应用,编写java文件
说的原因是缺少一个pom.xml文件,maven在执行之前会到一个叫做pom.xml文件中读取一些数据
新建一个pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion> <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如 com.companyname.project-group,maven 会将该项目打成的 jar 包放本地路径: /com/companyname/project-group -->
<groupId>com.project</groupId> <!-- 项目的唯一 ID,一个 groupId 下面可能多个项目,就是靠 artifactId 来 区分的 -->
<artifactId>hello</artifactId> <!-- 版本号 -->
<version>1.0</version>
</project>
接下来设置完pom.xml文件之后再次编译,此时什么事情也没有发生。
约定大于配置。
约定某一个规则,大家约定俗成去遵守它,并没有一个显示的配置文件来配置该规则。
约定:
源代码文件必须放置在src/main/java目录下
配置文件必须放置在src/main/resources目录下
测试代码文件必须放置在src/test/java目录下
测试代码需要一些配置文件那么放置在src/test/resources目录下
测试
mvn test
单元测试用例的概念。
熟悉、掌握junit单元测试用例
针对编写的项目,经常会编写一些测试用例来测试编写的代码功能上是否ok。
比如针对商城的用户模块,你可以去编写一个用户测试用例 User模块
类名应当尽量遵守XXXTest,比如UserTest,然后再该类中,我们去编写具体的测试用例代码,比如这个时候想验证登录功能是否ok,那么这个时候应当去编写一个方法,方法名称尽量写成testXXX,比如testLogin,同时该方法的权限应当为public,返回值应当为void,同时testXXX()方法应当为无参。最后一点要求:在该方法中,必须还要有一个注解@Test。
public class UserTest{
public void testLogin(){
//测试逻辑
}
}
在Maven中,如果想要测试某个代码的逻辑,其实非常简单,只需要引入junit、然后编写好对应的测试用例,接下来还行测试的指令,最终就会告知你整个测试的结果。
打包
mvn package
不借助于maven,如果需要打包,那么其实挺繁琐的,需要使用jar指令,或者借助于idea,但是idea其实也不是特别的方便
借助于maven,同样只需要执行一个指令,那么就可以将maven打包jar包或者额外制定成war包。
清除
mvn clean
清除编译产物。
依赖管理
依赖的管理。不管之前的SE项目还是后面的EE项目,如果我们需要在应用中引入某个类库,我们需要怎么做?
1.导包:把jar包放置在应用中,然后点击add as library。idea不会知道引入该依赖的。在idea中注册该依赖,那么接下来在编译时,idea就可以执行一个javac -classpath xxxx.jar的指令将这个jar包加载到内存中。
你会发现如果有多个应用,那么每个应用都需要这么做一遍,先复制jar包到应用中,然后add as library相当于告诉idea, jar的路径
这么做的目的其实只是一个,就是为了拿到该jar包的路径,也就是接下来编译的时候能够顺利地将jar包导入到内存中。
就像我们之前编写servlet时一样,我们的jar包还是放在tomcat的lib目录下,但是我们编写servlet时,我们将该jar包的路径引入进来即可完成编译。
之前项目面临的痛点:
1.需要频繁的去复制包,去导包,导入当前应用中(其实这步根本没有必要,我们只是为了要拿到该依赖的绝对路径,进而可以通过-classpath 加载到内存中),使得整个项目变得很大
2.另外一个痛点,比如文件上传组件,如果你第一次使用,直接引入了fileupload组件,那么接下来你发现根本运行不起来。因为fileupload运行需要额外io包的支持,也就是说需要额外依赖其他jar包。
万一此时导入的io包和之前的fileupload包再不兼容,那么你又要去排查。
maven也可以极大的简化该步骤。
设置镜像
因为局域网的网速不是特别的快,所以需要设置国内阿里巴巴镜像。
复制镜像的配置,粘贴到settings.xml文件中。
设置本地仓库(可选)
本地仓库默认情况下在c盘某个隐藏文件里面。
经常重装系统。
如果你有经常更换系统的习惯,那么建议你修改一下配置文件里面的本地仓库路径。
D:\repository
还有另外一点:
本地仓库有一个特点,就是如果本地仓库已经有了对应的jar包,那么当你在加载某个类时,就不会再去下载该jar包了。
设置编译版本
设置 jdk 版本:去 maven 安装目录/conf/settings.xml 文件中新增下面代码
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
或者在pom.xml 文件中新增 properties
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
scope
依赖范围。
compile:针对的是主程序代码(src/main/java)、测试程序代码、运行时代码的classpath均有效。
比如设置一个fileupload的scope为compile,
那么主程序代码在编译时,可以拿到该依赖(maven会提供该依赖给主程序代码编译时使用)
测试代码在编译以及运行时,也是可以拿到该依赖
主程序代码在运行时,也是可以拿到该依赖
依赖传递
项目一依赖项目二(第一依赖)
项目二依赖commons-fileupload(第二依赖)
根据依赖的传递性
项目一也可以拿到commons-fileupload依赖。
所以需要记住一点,如果第二依赖是test、provided,传递会断层,需要大家做的事情,如果你需要用这个依赖,那么自己再引入。
依赖冲突
项目
—————依赖A—————–依赖C v1.1
—————依赖B—————-依赖C v1.2
—————依赖C
需要清楚maven解决依赖冲突的几种策略:
spring-context———spring-beans
spring-jdbc————–spring-beans
第一声明者优先
谁先声明用谁的
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
路径近者优先
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.4</version>
</dependency>
依赖排除
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>
提取常量
对于一个系列的jar包,我们建议全部都采用同一个版本,可以通过设置一个常量,固定版本,后面全部沿用该版本。
<properties>
<spring.version1>5.3.4</spring.version1>
</properties>
<dependencies>
<dependency>
<groupId>com.ee</groupId>
<artifactId>mavenProject</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version1}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version1}</version>
</dependency>
本质原因:
有且只有一个原因。
就是在运行的时候没有找到对应的jar包。
运行的时候,tomcat会到哪个目录下去寻找jar包?
会到每个应用的WEB-INF/lib目录下寻找对应的jar包,除此之外,其他目录不会去寻找。
为什么要去加载这个jar包?
编译、运行,都需要该jar包再内存中才可以。
配置文件目录
resources目录。
SE项目、EE项目
SE项目配置文件的存放位置和EE项目文件的存放位置肯定是不同的
SE项目的配置文件其实我可以放置在应用的根目录里面
但是EE项目的配置文件必须要放置在WEB-INF或者它的子目录中。
SE项目配置文件和EE项目配置文件存放需要两套策略。
如果要获取配置文件,肯定需要去写两套代码。
SE:
应用根目录中 application.properties
new File(application.properties);
new FileInputStream(file);
Properties properties = new Properties(inputStream);
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args) throws IOException {
//SE获取配置文件方式
File file = new File("application.properties");
FileInputStream fileInputStream = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInputStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(username);
System.out.println(password);
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//EE项目获取配置文件的方式
String realPath = getServletContext().getRealPath("WEB-INF/application.properties");
FileInputStream fileInputStream = new FileInputStream(new File(realPath));
Properties properties = new Properties();
properties.load(fileInputStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(username);
System.out.println(password);
}
}
为了获取配置文件,需要在不同的项目中编写不同的代码,思考一个问题
有没有一种方式,既可以处理SE也可以处理EE项目中的配置文件呢?
代码容错性不是特别的好
想象一下,SE和EE有哪些共同点。
class文件,都是在硬盘上面的吧,运行的时候能够执行,说明一个问题
被类加载器加载到了内存中。
磁盘 ——–内存 磁盘IO FileInputStream File API
既然类加载器能够将class文件加载到内存,那么它肯定知道class文件的绝对路径——-file——inputStream
假设此时,我把配置文件和class文件放在一起,那么利用类加载器能不能拿到配置文件的绝对路径呢?
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
@WebServlet("/index2")
public class IndexServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如何在当前类中拿到类加载器呢?
ClassLoader classLoader = IndexServlet2.class.getClassLoader();
String path = classLoader.getResource("application.properties").getPath();
FileInputStream fileInputStream = new FileInputStream(new File(path));
}
}
package com.cskaoyan.path;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesTest2 {
public static void main(String[] args) throws IOException {
String path = PropertiesTest2.class.getClassLoader().getResource("application.properties").getPath();
FileInputStream fileInputStream = new FileInputStream(new File(path));
//除此之外还有另外一种简便的方式
InputStream inputStream = PropertiesTest2.class.getClassLoader().getResourceAsStream("application.properties");
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181127.html