java安全——加密

【0】README
1)本文文字描述转自 core java volume 2,旨在学习 java安全——加密 的基础知识;
2)java 安全性的第二个重要方面是加密。
3)认证对于代码签名已足够了-没必要将代码隐藏起来。但是,当applet或者应用程序传输机密信息时,比如信用卡号码和其他个人数据等,就有必要进行加密了。(干货——加密的应用背景)

【1】对称密码(加密和解密都使用相同的密钥)
(干货——对称密码定义:加密和解密都使用相同的密钥)
1)Cipher类: 该类是所有加密算法的超类。
(cipher——
    - n. 密码;暗号;零
    - vi. 使用密码;计算;做算术
    - vt. 计算;做算术;将…译成密码

1.1)获取密码对象:通过调用下面的getInstance方法可以获得一个密码对象:
Cipher cipher = Cipher.getInstance(algorithName);

1.2)获取密码对象:或者调用下面这个方法:

Cipher cipher = Cipher.getInstance(algorithName, providerName);

2)SunJCE:JDK中是由名为"SunJCE"的提供商提供密码,如果没有指定其他提供商,则会默认该提供商。

3)算法名称:是一个字符串,比如"AES" 或者 "DES/CBC/PKCS5Padding"。
3.1)DES(data encoding standard): 即数据加密标准,是一个密钥长度为56位的古老的分组密码。
3.2)AES(advanced encoding standard): 更好的选择是采用它的后续版本,即高级加密标准——AES;(干货——高级加密标准——AES
4)获得一个密码对象后, 
step1)就可以通过设置模式和密钥来对它初始化。
int mode = . . .;
Key key = . . .;
cipher.init(mode, key);
Attention)
A1)模式有以下几种:
Cipher.ENCRYPT_MODE
Cipher.DECRYPT_MODE
Cipher.WRAP_MODE
Cipher.UNWRAP_MODE
A2)wrap 和 unwrap模式用一个密钥对另一个密钥进行加密;
step2)反复调用update方法来对数据块进行加密。

step3) 完成上述操作后,还必须调用一次doFinal方法。

step3.1)如果有最后一个输入数据块(其字节数小于blockSize),那么就要调用:

outBytes = cipher.doFinal(inBytes, 0, inLength);

step3.2)如果所有的输入数据都已经加密,则用下面的方法调用来代替:

outBytes = cipher.doFinal();
Attention)对doFinal的调用是必要的,以便对最后的块进行"填充"。

【2】密钥生成(吧密钥看做一个数学函数)
1)生成密钥的steps
step1)  为加密算法获取KeyGenerator。

step2) 用随机源来初始化密钥发生器。如果密码块的长度是可变的,还需要指定期望的密码块长度。

step3) 调用generateKey方法。

2)看个荔枝:下面是如何生成AES密钥的方法

keyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom();
keygen.init(random);
Key key = keygen.generateKey();
2.1)或者,可以从一组固定的原始数据(也许是由口令或者随机击键产生的)来生成一个密钥,这时可以使用如下的SecretKeyFactory:(干货——引入SecretKeyFactory
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
byte[] keyData = . . .; // 16 bytes for AES
SecretKeySpec keySpec = new SecretKeySpec(keyData, "AES");
Key key = keyFactory.generateSecret(keySpec);

3)problem+solution:

3.1)problem: 如果要生成密钥,必须使用"真正的随机"数。例如,在Random类中的常规的随机数发生器,是根据当前的日期和时间来产生随机数的,因此它不够随机。例如,假设计算机时钟可以精确到1/10秒,那么,每天最多存在864,000个种子。如果攻击者知道发布密钥的日期(通常可以由截止日期推算出来),那么就可以很容易地生成那一天所有可能的种子。

3.2)solution: SecureRandom类产生的随机数,远比由Random类产生的那些数字安全得多。一旦你在字节数组中收集到随机位后,就可以将它传递给setSeed方法。(干货-SecureRandom类产生的随机数,远比由Random类产生的那些数字安全得多。) 

SecureRandom secrand = new SecureRandom();
byte[] b = new byte[20];
// fill with truly random bits
secrand.setSeed(b);
Attention) 如果没有为随机数发生器提供种子,那么它将通过启动线程,使它们睡眠,然后测量它们被唤醒的准确时间,来计算自己的20个字节的种子。

4)代码列表:
package com.corejava.chapter9.cryption;import java.io.*;
import java.security.*;
import javax.crypto.*;public class AESTest
{public static void main(String[] args) throws IOException, GeneralSecurityException, ClassNotFoundException{if (args[0].equals("-genkey")) // 产生密钥{// 获取密钥生成器KeyGenerator keygen = KeyGenerator.getInstance("AES");// 创建随机源SecureRandom random = new SecureRandom();// 用随机源来初始化密钥发生器keygen.init(random);// 生成密钥SecretKey key = keygen.generateKey();try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]))){out.writeObject(key); // 写出密钥到文件}}else // 加密或者解密{int mode;// 加密(解密)模式if (args[0].equals("-encrypt")) mode = Cipher.ENCRYPT_MODE;else mode = Cipher.DECRYPT_MODE;// 带资源的try 语句, args[3]==secret.keytry (ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));InputStream in = new FileInputStream(args[1]);OutputStream out = new FileOutputStream(args[2])){Key key = (Key) keyIn.readObject();Cipher cipher = Cipher.getInstance("AES");cipher.init(mode, key); // 设置模式和密钥对其初始化Util.crypt(in, out, cipher);}}}
}
package com.corejava.chapter9.cryption;import java.io.*;
import java.security.*;
import javax.crypto.*;public class Util
{public static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException,GeneralSecurityException{int blockSize = cipher.getBlockSize();int outputSize = cipher.getOutputSize(blockSize);byte[] inBytes = new byte[blockSize];byte[] outBytes = new byte[outputSize];int inLength = 0;boolean more = true;while (more){// inBytes 就是一个缓冲区inLength = in.read(inBytes);if (inLength == blockSize){// 只要输入数据块具有全长度(长度能够被8整除): 就要调用update方法; int outLength = cipher.update(inBytes, 0, blockSize, outBytes);out.write(outBytes, 0, outLength);}else more = false;}// 而如果输入数据块不具有全长度(长度不能被8整除,此时需要填充): 就要调用 doFinal 方法;if (inLength > 0) outBytes = cipher.doFinal(inBytes, 0, inLength);elseoutBytes = cipher.doFinal();out.write(outBytes);}
}
5)看个荔枝:

5.1)请按照如下 steps 使用上述程序:

step1)首先生成一个密钥,运行如下命令行:

java AESTest -genkey secret.key

step2)密钥就被保存在secret.key文件中了。现在可以用如下命令进行加密:

java AESTest -encrypt plaintextFile encryptedFile secret.key

step3)用如下命令进行解密:

java AESTest -decrypt encryptedFile decryptedFile secret.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>javac com/corejava/chapter9/cryption/AES
Test.java
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AEST
est -genkey com/corejava/chapter9/cryption/secret.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AEST
est -encrypt com/corejava/chapter9/cryption/input.txt com/corejava/chapter9/cryption/output.txt com/
corejava/chapter9/cryption/secret.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AEST
est -encrypt com/corejava/chapter9/cryption/input.txt com/corejava/chapter9/cryption/encrypted.txt c
om/corejava/chapter9/cryption/secret.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AEST
est -decrypt com/corejava/chapter9/cryption/encrypted.txt com/corejava/chapter9/cryption/decrypted.t
xt com/corejava/chapter9/cryption/secret.key
for full source code, please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter9/AES
Conclusion)
C1)该程序非常直观。使用-genkey选项将产生一个新的密钥,并且将其序列化到给定的文件中。
C2)该操作需要花费较长的时间,因为密钥随机生成器的初始化非常耗费时间。
C3) -encrypt 和 -decrypt选项都调用相同的crypt方法,而crypt方法则调用密码的update 和 doFinal方法。
Attention) 请注意update方法和doFinal方法是怎样被调用的?(干货——update方法和doFinal方法的被调用条件的区别
A1)只要输入数据块具有全长度(长度能够被8整除): 就要调用update方法;
A2)而如果输入数据块不具有全长度(长度不能被8整除,此时需要填充): 或者没有更多额外的数据(以便生成一个填充字节),那么就要调用doFinal方法;

【3】密码流
1) JCE(Java Cryptography Extension,java加密扩展)库: 提供了一组使用非常方便的数据类,用于对流进行自动加密或解密。
2)看荔枝:
2.1)下面是对文件数据进行加密的方法:
Cipher cipher = . . .;
cipher.init(Cipher.ENCRYPT_MODE, key);
CipherOutputStream out = new CipherOutputStream(new FileOutputStream(outputFileName), cipher);
byte[] bytes = new byte[BLOCKSIZE];
int inLength = getData(bytes); // get data from data source
while (inLength != -1)
{
out.write(bytes, 0, inLength);
inLength = getData(bytes); // get more data from data source
}
out.flush();
2.2)可以使用CipherInputStream,对文件的数据进行读取和解密:
Cipher cipher = . . .;
cipher.init(Cipher.DECRYPT_MODE, key);
CipherInputStream in = new CipherInputStream(new FileInputStream(inputFileName), cipher);
byte[] bytes = new byte[BLOCKSIZE];
int inLength = in.read(bytes);
while (inLength != -1)
{
putData(bytes, inLength); // put data to destination
inLength = in.read(bytes);
}
Attention) 密码流类能够透明地进行update 和 doFinal方法的调用,所以非常方便。

【4】公共密钥密码(SSH免密码登录的加密解密形式)
1)problem+solution:
1.1)problem: AES密码是一种对称密码,加密和解密都使用相同的密钥。对称密码的致命缺点在于密码的分发。如果Alice给Bob发送一个加密方法,那么Bob需要使用与Alice相同的密钥。如果Alice修改了密钥,那么她必须在给Bob发送信息的同时,还要通过安全信道发送新的密钥,但是也许她并不拥有到达Bob的安全信道,这就是为什么她必须首先对她发送给Bob的信息进行加密的原因。
1.2)solution: 公共密钥密码技术解决了这个问题。
2)公共密钥技术的idea: 在公共密钥密码中,Bob拥有一个密钥对,包括一个公共密钥和一个相匹配的私有密钥。Bob可以在任何地方公布公共密钥,但是他必须严格保守他的私有密钥。Alice只需要使用bob 的 公共密钥对她发送给Bob的信息进行加密即可。(干货——当Alice需要向Bob 发送加密文件时,那Alice就需要使用 Bob 的公共密钥对她发送给Bob的信息进行加密
3)solution+problem:
3.1)problem实际上,加密过程并没有那么简单。所有已知的公共密钥算法的操作速度都比对称密钥算法(比如DES或AES等)慢得多,使用公共密钥算法对大量的信息进行加密是不切实际的。
3.2)solution但是,如果像下面这样,将公共密钥密码与快速的对称密码结合起来,这个问题就可以得到解决:(干货——这里涉及到两次加密——对明文加密 + 对对称密钥加密)

s1 Alice生成一个随机对称加密密钥,她用该密钥对明文进行加密。(第一次加密:对明文加密)

s2 Alice用Bob的公共密钥给对称密钥进行加密。第二次加密:对对称密钥加密)

s3Alice将加密后的对称密钥和加密后的明文同时发送给Bob。

s4 Bob用他的私有密钥给对称密钥解密。

s5) Bob用解密后的对称密钥给信息解密。

4)最普通的公共密钥算法: 是Rivest, Shamir, 和 Adleman发明的RSA算法。

5)如何使用RSA算法?

step1)如果要使用RSA算法,需要一对公共/私有密钥。你可以按如下方法使用KeyPairGenerator来获得:

KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
pairgen.initialize(KEYSIZE, random);
KeyPair keyPair = pairgen.generateKeyPair();
Key publicKey = keyPair.getPublic();
Key privateKey = keyPair.getPrivate();
step2)程序有三个选项。-genkey选项用于产生一个密钥对,-encrypt选项用于生成AES密钥,并且用公共密钥对其进行包装。
Key key = . . .; // an AES key
Key publicKey = . . .; // a public RSA key
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, publicKey);
byte[] wrappedKey = cipher.wrap(key);

step2.1)然后它便生成一个包含下列内容的文件(files):

f1)包装过的密钥的长度;

f2)包装过的密钥字节;

f3)用AES密钥加密的明文;

Attention)-decrypt选项:  用于对这样的文件进行解密。

6)代码列表

package com.corejava.chapter9.cryption;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;public class RSATest
{private static final int KEYSIZE = 512;public static void main(String[] args) throws GeneralSecurityException, IOException, ClassNotFoundException {if(args[0].equals("-genkey")) // 生成密钥对(公钥+私钥){// 密钥对生成器KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");SecureRandom sr = new SecureRandom();pairgen.initialize(KEYSIZE, sr); // 密钥对生成器初始化KeyPair pair = pairgen.generateKeyPair(); // 生成密钥对(公钥+私钥)try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]))){out.writeObject(pair.getPublic()); // 写入公钥到文件}try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[2]))){out.writeObject(pair.getPrivate()); // 写入私钥到文件}}else if(args[0].equals("-encrypt")) // 加密模块{// 生成密钥KeyGenerator keygen = KeyGenerator.getInstance("AES");SecureRandom sr = new SecureRandom();keygen.init(sr);SecretKey key = keygen.generateKey();// wrap with RSA public key// args[3]==public.key,args[2]==encryptedFile,args[1]=inputFiletry(ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));DataOutputStream dataOut = new DataOutputStream(new FileOutputStream(args[2]));InputStream in = new FileInputStream(args[1])){Key publicKey = (Key)keyIn.readObject();// 读入公钥Cipher cipher = Cipher.getInstance("RSA");// RSA密码对象cipher.init(Cipher.WRAP_MODE, publicKey); // 通过设置打包模式和公钥 来对RSA密码对象进行初始化byte[] wrappedKey = cipher.wrap(key);// 通过带有公钥的RSA算法对象给密钥加密dataOut.writeInt(wrappedKey.length); // 将加密后的密钥写入到输出流  dataOutdataOut.write(wrappedKey);cipher = Cipher.getInstance("AES"); // AES 密码对象cipher.init(Cipher.ENCRYPT_MODE, key); // 通过设置加密模式和密钥 来对 AES 密码对象进行初始化Util.crypt(in, dataOut, cipher); // 利用AES密码对象对inFile 进行加密并写入到输出流 dataOut} }else // 解密模块{//args[1]==encryptedFile,args[3]=private.key,args[2]=decryptedFile;try(DataInputStream dataIn = new DataInputStream(new FileInputStream(args[1]));ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));OutputStream out = new FileOutputStream(args[2])){ int length = dataIn.readInt();byte[] wrappedKey = new byte[length];dataIn.read(wrappedKey, 0, length); // 读入加密后的文件(经过公钥加密后的密钥 和 经过密钥加密后的文件内容)// unwrap with RSA private keyKey privateKey = (Key)keyIn.readObject(); // 读入private.key 到 wrappedKeyCipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.UNWRAP_MODE, privateKey); // 通过设置解包模式和私钥 来对RSA密码对象进行初始化// 通过带有私钥的RSA算法对象给密钥解密Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);cipher = Cipher.getInstance("AES"); // AES 密码对象cipher.init(Cipher.DECRYPT_MODE, key);	 // 通过设置解密模式和密钥 来对 AES 密码对象进行初始化				Util.crypt(dataIn, out, cipher); // 通过使用解密后的密钥 对 加密后的文件内容 进行解密并写入到输出流 out} }}
}<strong>
</strong>


7)运行该程序的steps:

step1)首先生成RSA密钥:

java RSATest -genkey public.key private.key

step2)然后对一个文件进行加密:

java RSATest -encrypt plaintextFile encryptedFile public.key

step3)最后,对文件进行解密,并且检验解密后的文件是否与明文相匹配。

java RSATest -decrypt encryptedFile decryptedFile private.key
最后的执行结果:
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSAT
est -genkey com/corejava/chapter9/cryption/public.key com/corejava/chapter9/cryption/private.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSAT
est -encrypt com/corejava/chapter9/cryption/rsa_input.txt com/corejava/chapter9/cryption/rsa_encrypt
ed.txt com/corejava/chapter9/cryption/public.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSAT
est -decrypt com/corejava/chapter9/cryption/rsa_encrypted.txt com/corejava/chapter9/cryption/rsa_dec
rypted.txt com/corejava/chapter9/cryption/private.key
full source code, please visit  https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter9/RSA 
Conclusion)
你现在已经看到了Java安全模型是如何允许我们去控制代码的执行的,这是Java平台的一个独一无二且越来越重要的方面。你已经看到了Java类库提供的认证和加密服务。

Attention)但是我们没有涉及许多高级和专有的话题,比如有:

A1)提供了对Kerberos协议进行支持的"通用安全服务"的GSS-API(原则上同样支持其他安全信息交换协议)。

A2)对SASL的支持,SASL即简单认证和安全层,可以为LDAP和IMAP协议所使用。

A3)对SSL的支持,SSL即安全套接层。在HTTP上使用SSL对应用程序的编程人员是透明的,只需要直接使用以https开头的URL即可。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 异常 最佳实践_处理Java异常的10种最佳实践

java 异常 最佳实践在本文中&#xff0c;我们将看到处理Java异常的最佳实践。 用Java处理异常不是一件容易的事&#xff0c;因为新手很难理解&#xff0c;甚至专业的开发人员也可能浪费时间讨论应该抛出或处理哪些Java异常。 因此&#xff0c;最大的开发公司对如何使用它们有一…

Java NIO总结

一、NIO NIO是new IO&#xff0c;也是非阻塞IO。有Channel、Selector、Buffer、Pipe、FileLock等类。 Buffer在java.nio包 Channel、Selector、Pipe、FileLock等在java.nio.channels包 二、Channel通道 设置非阻塞configureBlocking(false); 注册选择器register(selector,…

java 不可变map_如何用Java创建不可变的Map

java 不可变map你好朋友&#xff0c; 在本教程中&#xff0c;我们将看到如何在Java中创建不可变的Map。 –不可变的类或对象是什么意思&#xff1f; –什么是不可变地图&#xff1f; –如何在Java中创建不可变的Map&#xff1f; 不变的类或对象是什么意思&#xff1f; 不可…

ToolProvider.getSystemJavaCompiler() return null 的解决方法

【1】利用java 编译器API 编译 普通的java文件 1.1&#xff09;代码如下&#xff1a; package com.corejava.chapter10_2;import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream;import javax.tools.JavaCompiler; import jav…

脚本错误和安全警报怎么解决_适用于应用程序错误的AWS警报

脚本错误和安全警报怎么解决监视对于任何实际应用都是关键的。 您必须知道正在发生的事情&#xff0c;并在发生问题时实时得到警报。 AWS为此提供了CloudWatch&#xff0c;并自动为您提供了许多指标。 但是&#xff0c;您必须定义一些自己的东西。 然后&#xff0c;您需要定义适…

java平台脚本+java编译器API

【0】README 0.1&#xff09;本文文字描述转自 core java volume 2&#xff0c; 旨在学习 java平台脚本java编译器API 的 基础知识&#xff1b; ------------------------------------------------------------------------------ 【1】java平台的脚本 1&#xff09;脚本语…

Java 多线程总结

一、多线程实现方式 &#xff08;1&#xff09;继承Thread类&#xff0c;覆盖run方法 &#xff08;2&#xff09;实现Runnable接口&#xff0c;覆盖run方法&#xff0c;将对象传人Thread对象中实现Runnable接口比继承Thread类所具有的优势&#xff1a; 1&#xff09;适合多个相…

古巴比伦乘法_古巴:为生产做准备

古巴比伦乘法“它可以在我的本地机器上运行&#xff01;” 如今&#xff0c;它听起来像模因&#xff0c;但是“开发环境与生产环境”的问题仍然存在。 作为开发人员&#xff0c;您应始终牢记&#xff0c;您的应用程序有一天将在生产环境中开始运行。 在本文中&#xff0c;我们将…

java编译器API——使用编译工具

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://suntips.iteye.com/blog/69002 0.2&#xff09;for basic java compiler API, please visit http://blog.csdn.net/pacosonswjtu/article/details/50718494 1&#xff09;当你需要更好的处理这些结果时,你可以使…

Java 线程同步总结

一、synchronized&#xff08;1&#xff09;synchronized方法 &#xff08;2&#xff09;synchronized块 二、Lock 注意&#xff1a;及时释放Lock锁&#xff0c;否则会出现死锁&#xff0c;通常在finally代码释放锁 &#xff08;1&#xff09;ReentrantLock 实现…

aws es方案_AWS Elasticsearch后模式

aws es方案碰巧我们在SaaS版本的LogSentinel上遇到了生产问题–我们的Elasticsearch停止了对新数据编制索引。 由于Elasticsearch只是辅助存储&#xff0c;因此没有数据丢失&#xff0c;但这给我们的客户带来了一些问题&#xff08;他们无法在其仪表板上看到实时数据&#xff0…

java注解总结

【0】README 0.1&#xff09;本文主要对 java 注解做总结&#xff1b; 【1】处理注解的级别 level1&#xff09; 在运行期级别处理注解&#xff1a; http://blog.csdn.net/pacosonswjtu/article/details/50719361level2&#xff09;在源码级别处理注解&#xff1a; http://b…

Java 类加载总结

一、类加载过程 装载链接验证准备解析初始化二、类初始化情况 1&#xff09;创建类的实例&#xff0c;也就是new一个对象 2&#xff09;访问某个类或接口的静态变量&#xff0c;或者对该静态变量赋值 3&#xff09;调用类的静态方法 4&#xff09;反射&#xff08;Class.…

maven依赖管理_依赖管理和Maven

maven依赖管理Maven伟大而成熟。 几乎所有事物都总有解决方案。 您可能在组织项目上遇到的主要情况是依赖管理。 而不是每个项目都具有自己的依赖关系&#xff0c;您需要一种集中的方式来继承那些依赖关系。 在这种情况下&#xff0c;您可以在父舞会上声明托管依赖项。 在我的…

JavaBean 持久化

【0】README 0.1&#xff09;本文文字描述转自 core java volume 2&#xff0c;旨在学习 JavaBean 持久化 的基础知识&#xff1b; 0.2&#xff09;本文所有源代码荔枝均为原创&#xff1b; 0.3&#xff09; for complete souce code, please visit https://github.com/pa…

apache kafka_Apache Kafka消费者再平衡

apache kafka消费者重新平衡决定哪个消费者负责某个主题的所有可用分区的哪个子集。 例如&#xff0c;您可能有一个包含20个分区和10个使用者的主题。 在重新平衡结束时&#xff0c;您可能希望每个使用者都从2个分区中读取数据。 如果关闭了这些使用者中的10个&#xff0c;则可…

Java 注解总结

一、注解定义 注解早在J2SE1.5就被引入到Java中&#xff0c;主要提供一种机制&#xff0c;这种机制允许程序员在编写代码的同时可以直接编写元数据。 二、元注解 Target 说明了被修饰的注解的应用范围&#xff0c;也就是被修饰的注解可以用来注解哪些程序元…

编译原理三大经典书籍(龙书 虎书 鲸书)

以下内容转自&#xff1a; http://blog.csdn.net/skymingst/article/details/7436892 1、龙书&#xff08;Dragon book&#xff09; 英文名&#xff1a;Compilers: Principles,Techniques,and Tools 作者&#xff1a;Alfred V.Aho,Ravi Sethi,Jeffrey D.Ullman 中文名&…

两个时间之间是多少小时_那是两个小时我不会回来

两个时间之间是多少小时正如我之前关于linting主题所说的 &#xff0c;花时间修改代码的好处很有限&#xff0c;因为自动工具告诉您这样做。 更糟糕的是&#xff0c;这些工具并非万无一失。 例如&#xff0c;我们一直在针对完美无害的try-with-resources构造周围的SpotBugs警告…

java的类载入器

【0】README 0.1&#xff09;本文文字转自&#xff1a; 深入剖析tomcat&#xff0c; 旨在 理解 jvm 的类载入器&#xff1b; 【1】 jvm的类载入器相关 1&#xff09;jvm 使用了3种类载入器来载入所需要的类&#xff1a;分别是引导类载入器&#xff08;bootstrap class load…