CI笔记1

maven相关

包下载

maven项目永远是去本地仓库找JAR包,本地没有的,也是从远程仓库(一级一级找,最后到中央仓库)下载到本地仓库,然后再从本地仓库里面拷出到项目里面。

maven有自己的一个默认中央仓库,在setting.xml里面是看不到的,它的ID是central。

maven的下载机制,是在repository里面,一个仓库的去找你要的东西。而镜像的作用是屏蔽指定的repository并用镜像替代,并不影响其本身的下载机制。

所以镜像的mirrorOf不要选*,这样你就相当于屏蔽了所有的仓库,这是不合适的,mirrorOf最好就填写central,这样就兜底了中央仓库。

类加载

java本身是不会报类冲突的,是因为java类加载的机制,是从类目录下一个个的找(不仅包括引用的jar包,还包括本身的class程序文件),找到了就停下来。

会报冲突的是maven或者编译器的功能。Maven其实很智能,如果是两个一样artifact和groupid的话,不同版本的,在下载的时候都会下载下来,但是编译的时候,只会保留高版本。(maven应该会提示?不然直接就覆盖了,不兼容怎么办)

打出可执行的jar包

正常打jar包的话,被引入的三方jar包是不会一起被打入jar包的,只会有pom跟着你。所以的话,如果你这个jar包被别人用,那个人没用maven的话,是跑不起来的。

要想jar包一打就能用,也就是把三方jar也加到jar包里面(一般我们下载的第三方开源jar不会采用这种方式,因为这样会导致jar包冗余),有两种方式:

  • 通过export打jar包的时候要选择runablejar,里面可以配置你是要把第三方jar配置在本jar包的面,还是外面。这样的话,它会在MANIFEST.MF里面,把你的第三方jar的地址放进去。一个接着一个jar就能衔接上了。
  • 先设置project sturcture里面的artifact,把三方jar加入依赖,然后再通过build里面的artifact build打包。(这里有一点需要注意,manifest的位置不能放默认位置,需要放到resource下,不然IDEA12有bug,识别不了manifest文件)
依赖树

maven里面查看依赖树,用mvn dependency:tree,如果要看详细的,再加参数-Dverbose,如果是要包括或者删除哪些,再用-Dincludes=xx:xx:xx -Dexcludes=xx:xx:xx。

mvn dependency:tree -Dverbose -Dincludes=xx:xx:xx -Dexcludes=xx:xx:xx

生命周期

maven一共有三个生命周期,分别是clean,validate–>compile–>test–>package–>verify–>install,site。

在同一个生命周期内,当你执行一个构建阶段时,所有在该构建阶段之前的构建阶段(根据标准构建顺序)都会被执行。

仓库路径

maven有个巨坑,在配置本地仓库路径的时候,默认是/root/.m2/repository,我也没有去改。

但是在下载和使用jar包时,它使用了C盘下的/root/.m2/repository(猜测是因为maven安装在C盘),但是在install上传jar包时,却使用的是D盘下的/root/.m2/repository(猜测是因为项目源码是在D盘)。。。。

最后在setting的配置文件中手动把仓库路径改成C:/root/.m2/repository解决问题。

删除lastupdate后缀文件

在root下用cmd执行如下命令可以删除所有的update文件

for /r %i in (*.lastUpdated) do del %i

依赖结构
  1. 通过一层一层的parent继承,继承母pom。
  2. 在母pom中通过dependencymanagement的import接口,引入其他三个模块的pom。

JAVA相关

密码

长期密码(master/longterm key)是不能在网络上传输的,只有短期密码(session/shortterm key)才允许在网络上传输。原来如此才有session这个词。

证书

证书的本质,就是两个东西,一个是持证人的公钥明文(既能加密,又能解密),还有一个就是证书发放机构CA用自己的私钥加密过的前面所说明文的摘要。

所以所有的持证人都会有一个CA的证书和一个自己的证书,这个CA的证书里面自然是CA的公钥,可以用来解密其他人的证书,判断其是本人,然后用其证书里面的公钥进行加密约定的对称密钥,发回去。

我们可以看出,证书的本质就是当做一个公钥用的。里面的摘要是CA验证说这个这个证书我授权了,这个机构有资格拿这个证书。但是CA的证书也是需要认证的,这么一层一层网上传,最上面的证书总会没有人给他认证的,它就可以自己给自己认证,用自己的私钥加密自己的公钥。

这种证书的持证人,就只会有一个证书,没有CA的证书。这样的话,通信是安全的,因为你收到他的证书后,用证书里的公钥(代替了CA证书里的公钥)去解密摘要,判断是持证人本人。只是这种证书没有CA背书去审核这个持证人的资质等公司经营状况的信息。

keystore

keystore是java特有的存储证书的文件,里面可以一条一条的存储两种类型的文件,

  • 一种是证书,也就是公钥(可信任的证书实体(trusted certificate entries))。
  • 一种是公钥和私钥对(密钥实体(Key entity))。可以使用keytool的命令来查看keytool -list -v -keystore xxxx

keystore本身有一个storepassword,用于访问。

修改使用keytool -storepasswd -keystore xxxx

keystore里面的私钥公钥对如果想要被访问,需要有私钥的密码,这个是keypassword。(keytool本身是不能看到私钥的,只能去改变私钥的keypassword)

修改使用./keytool -keypasswd -alias com.huawei.cmp.serverkey -keystore xxxx.

这里面有一个坑,要是你的keypasswd和storepasswd一样的话,修改keypasswd的时候,只会提示你输入storepasswd,而不要求你输入keypasswd。

线程

Callable接口,就是在runnable接口的基础上,把run()方法编程了call()方法。在方法里面,利用泛型的约束,要求了必须返回一个值罢了。

FutureTask就相当于Thread,只是传入类必须实现callable而不是Thread对应的runnable,而且在Thread的基础上,通过泛型,约束了返回值必须和callable的返回值相一致。拥有的方法也比thread要多。

FutureTask<String> ft = new FutureTask<String>(callable1);

ReentrantLock,以及各种Atomic类都是java5之后引入的,其本身是通过类的方式实现,而不是JVM的关键字。

所以在使用上,多了很多定制的功能,比如可以设置没拿到锁时的等待时间,但是呢,优化不如sychronized好 。

所以,资源竞争不激烈的时候,用sychronized性能最强。

资源竞争激烈时,如果配置的好,ReentrantLock,以及各种Atomic类可能会提升性能,但是!!!如果用的不好,不仅不能提高性能,还可能带来灾难。

postcontruct注解

如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。(就是某些初始化需要依赖注入进来的类,这样你就没办法在构造器里完成,所以你需要依靠postconstruct注解)

Constructor >> @Autowired >> @PostConstruct

举个例子:

public Class AAA {
    @Autowired
    private BBB b;

    public AAA() {
        System.out.println("此时b还未被注入: b = " + b);
    }

    @PostConstruct
    private void init() {
        System.out.println("@PostConstruct将在依赖注入完成后被自动调用: b = " + b);
    }
}
Could not initialize class

java.lang.NoClassDefFoundError: Could not initialize class

JVM在加载类的时候,会初始化静态变量和执行静态代码块,如果加载失败,以后再用到这个类,就会报上面那个无法初始化类的错误。(区别于无法找到类的错误。)

比如下面这种类,就无法初始化成功。

class ClassWithInitErrors{
	static int data = 1 / 0;
}

第一次和第二次的报错也不一样

第一次new会报:java.lang.ExceptionInInitializerError

第二次new会报:java.lang.NoClassDefFoundError: Could not initialize class ClassWithInitErrors

Docker

Docker的本质是轻量虚拟化(就比原来的程序多了一点硬盘)、资源隔离。

如果在一个容器里装多个软件,除了省一点硬盘外没有什么意义,还有坏处:

  • docker外只能监控主线程,所以一个容器装多个软件,还是只能监控一个线程。其他线程挂了都不知道。
  • 无法实现部件的弹性扩展,要扩展又是一整个一套全部得复制。
  • 除主线程外的其他线程都没有办法暴露出来给其他容器使用。

docker的正确玩法,是每个容器装一个软件,然后通过k8s或者docker compose去进行容器编排。

强制类型转换的坑

JAVA强制类型转换的时候,在编译期间,只会校验是否有继承的关系而已!!!不会去校验继承关系的顺序,也不会去校验实现关系!!!

也就是说,父类强转成子类,以及某个类强转成任何接口,都不会在编译时报错。只会在运行时报错。

比较典型的例子,object对象,可以在编译期强转成任何对象(因为它本身是所有对象的父类)、以及任何接口。却不会报错。。。。这是个巨坑呀。所以代码编译过了,不一定就是对的。

下列错误代码在编译器里面不会报错。

Object  object=new  Object();

ControllerUploadCtx  wrong1=(ControllerUploadCtx)object;

Map  wrong2=(Map)object;

还有一种很坑的应用场景。

像eat( Map m )这种接受接口的方法,在编译时,任何对象都可以通过eat((Map)xxx )的强转方式,接受到任何的对象。。。即使这个对象没有实现Map接口,在编译时都会被报错。

看到强转一定要分外留心:

  • 强转为接口类型:

    我们一般都没看到过强转成接口的。是因为你接口肯定是类的上层,像

    HashMap hashMap = new HashMap() ; 
    
    Map a = hashMap; 
    

    根本就不需要写成Map a = (Map)hashMap; 因为没有必要。所以我们基本就看不到强制转换成接口的。

    如果你发现了有这种强转为接口的使用,就要分外小心了。因为对的时候它没必要,错的时候它还不会编译报错。

  • 强转为类类型:

    有继承关系之间的类的强转,能转换的没问题,不能转换的情况下,在编译时也不会报错。

常用的GIT命令

git remote -v

git remote add team ssh://git@isource-nj.huawei.com:2222/CloudOps/package.git

git pull <远程主机名> <远程分支名>:<本地分支名>

git push <远程主机名> <本地分支名>:<远程分支名>

git cherry-pick <cmmmit-id>

Git在reset时,会删除一些文件,但是有的时候目录或者工程不会被删除,这可能是因为这些工程本身没有被加入到git的同步列表中。但是这种目录结构会导致你的目录结构跟实际情况不一样。这样的话使用gittortoise工具cleanup一下就好。然后在idea里面rebuild一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值