java中加解密合集
1.背景
项目过程中遇到很多需要加密和解密的数据,用于记录学习
2.对称加密和非对称加密
3.对称加密
对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES
4.非对称加密
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法
5.区别
1、加密和解密过程不同
对称加密的加密过程和解密过程使用的同一个密钥,加密过程相当于用原文+密钥可以传输出密文,同时解密过程用密文-密钥可以推导出原文。
但非对称加密采用了两个密钥,一般使用公钥进行加密,使用私钥进行解密。
2、加密解密速度不同
对称加密解密的速度比较快,适合数据比较长时的使用。
非对称加密和解密花费的时间长、速度相对较慢,只适合对少量数据的使用。
3、传输的安全性不同
对称加密的过程中无法确保密钥被安全传递,密文在传输过程中是可能被第三方截获的,如果密码本也被第三方截获,则传输的密码信息将被第三方破获,安全性相对较低。
非对称加密算法中私钥是基于不同的算法生成不同的随机数,私钥通过一定的加密算法推导出公钥,但私钥到公钥的推导过程是单向的,也就是说公钥无法反推导出私钥。所以安全性较高。
6、例子
6.1 DES加解密
DES 全称 Data Encryption Standard(数据加密标准),作为算法的DES称为数据加密算法(Data Encryption Algorithm, DEA),已与作为标准的DES区分开来
package com.cloud.user;import java.security.Key;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;public class DESUtil {public static Key setKey(String strKey) {Key key = null;try {KeyGenerator generator = KeyGenerator.getInstance("DES");generator.init(new SecureRandom(strKey.getBytes())); // 根据参数生成keykey = generator.generateKey();} catch (Exception e) {e.printStackTrace();}return key;}/*** @param source 编码内容* @param key 密钥* @param charSet 编码格式* @return*/public static String encrypt(String source, String key, String charSet) {String encrypt = null;try {byte[] ret = encrypt(source.getBytes(charSet), key);encrypt = new String(Base64.getEncoder().encode(ret));} catch (Exception e) {e.printStackTrace();encrypt = null;}return encrypt;}/*** @param encryptedData 解码内容* @param key 密钥* @param charSet 编码格式* @return*/public static String decrypt(String encryptedData, String key, String charSet) {String descryptedData = null;try {byte[] ret = descrypt(Base64.getDecoder().decode(encryptedData.getBytes()), key);descryptedData = new String(ret, charSet);} catch (Exception e) {e.printStackTrace();descryptedData = null;}return descryptedData;}private static byte[] encrypt(byte[] primaryData, String key) {Key desKey = setKey(key);try {Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成加密操作cipher.init(Cipher.ENCRYPT_MODE, desKey); // 用密钥初始化Cipher对象(加密)return cipher.doFinal(primaryData);} catch (Exception e) {e.printStackTrace();return null;}}private static byte[] descrypt(byte[] encryptedData, String key) {Key desKey = setKey(key);try {Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成解密操作cipher.init(Cipher.DECRYPT_MODE, desKey); // 用密钥初始化Cipher对象(解密)return cipher.doFinal(encryptedData);} catch (Exception e) {e.printStackTrace();return null;}}public static void main(String[] args) {String code = "hello";String key = "thisisakey";String unicode = "utf-8";String encrypt = encrypt(code, key, unicode);String decrypt = decrypt(encrypt, key, unicode);System.out.println("原内容:" + code);System.out.println("加密:" + encrypt);System.out.println("解密:" + decrypt);}
}
6.2 3DES加解密
三重数据加密算法(英语:Triple Data Encryption Algorithm,缩写为TDEA,Triple DEA),或称3DES(Triple DES),是一种对称密钥加密块密码,相当于是对每个数据块应用三次DES算法。由于计算机运算能力的增强,原版DES由于密钥长度过低容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
添加依赖
<dependency><groupId>io.lions</groupId><artifactId>LionsUtils</artifactId><version>0.0.1-SNAPSHOT</version><exclusions><exclusion><groupId>cn.ccvnc</groupId><artifactId>commons-logging</artifactId></exclusion><exclusion><groupId>cn.ccvnc</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions> </dependency>
工具类
package com.cloud.common.util;import io.lions.security.encryption.bidirectional.DESede;/*** 常量工具类*/
public class ConstantUtils {/*** 加密*/public static final DESede DES = new DESede();/*** 加密盐*/public static final String SALT = "@321Dr0wSsaP111";}
测试
package com.cloud.user;import com.cloud.common.util.ConstantUtils;public class Demo3DES {public static void main(String[] args) throws Exception {System.out.println("------加密-------");String mingwen = "admin1";encrypt(mingwen);System.out.println("------解密-------");String miwen = "W6%2FfyeyMdWEI32ZCPTHLAw%3D%3D";decrypt(miwen);}public static void encrypt(String str) {String desEncrypt = ConstantUtils.DES.get3DESEncrypt(str, ConstantUtils.SALT);System.out.println(desEncrypt);}public static void decrypt(String str) {String desDecrypt = ConstantUtils.DES.get3DESDecrypt(str, ConstantUtils.SALT);System.out.println(desDecrypt);}}
6.3 md5单向加密
MD5是一种单向加密算法,只能加密不能解密
MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密
package com.cloud.user;import org.springframework.util.DigestUtils;import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class MD5Util {/*** java自带jar工具 java.security.MessageDigest 实现** @param text 要加密的字符串* @param rad 进制:比如 16、32* @param isUpp 是否转换为大写* @return*/public static String strToMD5(String text, int rad, boolean isUpp) {MessageDigest messageDigest = null;try {//通过MessageDigest类来的静态方法getInstance获取MessageDigest对象messageDigest = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {e.printStackTrace();}// 4、获取明文字符串对应的字节数组byte[] input = text.getBytes();// 5、执行加密messageDigest.update(input);//这里也可以直接使用byte[] output = messageDigest.digest(input)方法来进行加密,就省略了上面的update方法了byte[] output = messageDigest.digest();// 6、创建BigInteger对象// signum为1表示正数、-1表示负数、0表示0。不写默认表示正数int signum = 1;BigInteger bigInteger = new BigInteger(signum, output);// 7、按照16进制(或32进制)将bigInteger转为字符串return isUpp ? bigInteger.toString(rad).toUpperCase() : bigInteger.toString(rad);}/*** spring自带的工具 org.springframework.util.DigestUtils 实现* @param text* @return 16进制*/public static String _strToMD5(String text) {return DigestUtils.md5DigestAsHex(text.getBytes());}public static void main(String[] args) {String str = "hello";System.out.println(strToMD5(str, 16, true));System.out.println(_strToMD5(str));System.out.println(strToMD5(str, 16, false).equals(_strToMD5(str)));}
}
6.4 Base64加解密
Java 8 内置编码器和解码器。
static class Base64.Decoder:解码器,使用 Base64 编码来解码字节数据。
static class Base64.Encoder:编码器,使用 Base64 编码来编码字节数据。
package com.cloud.user;import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;public class Base64Util {public static void main(String[] args) throws Exception {String text = "hello";try {/*** static Base64.Encoder getEncoder()* 返回一个 Base64.Encoder ,编码使用基本型 base64 编码方案。*/String base64encodedString = Base64.getEncoder().encodeToString(text.getBytes("utf-8"));System.out.println("Base64 编码字符串 (基本) :" + base64encodedString);/*** static Base64.Decoder getDecoder()* 返回一个 Base64.Decoder ,解码使用基本型 base64 编码方案。*/byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8"));/*** static Base64.Encoder getUrlEncoder()* 返回一个 Base64.Encoder ,编码使用 URL 和文件名安全型 base64 编码方案。*/base64encodedString = Base64.getUrlEncoder().encodeToString(text.getBytes("utf-8"));System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);/*** static Base64.Decoder getUrlDecoder()* 返回一个 Base64.Decoder ,解码使用 URL 和文件名安全型 base64 编码方案。*/byte[] base64decodedBytes2 = Base64.getUrlDecoder().decode(base64encodedString);System.out.println("原始字符串: " + new String(base64decodedBytes2, "utf-8"));StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i < 10; ++i) {stringBuilder.append(UUID.randomUUID().toString());}byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);System.out.println("Base64 编码字符串 (MIME) :" + mimeEncodedString);} catch (UnsupportedEncodingException e) {System.out.println("Error :" + e.getMessage());}}
}
6.5 AES加解密
AES 与 DES 一样,一共有四种加密模式:电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)
package com.cloud.user;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;public class AESUtil {//指定为AES算法,不区分大小写private static final String KEY_ALGORITHM = "AES";private static final String CHARSET_NAME = "utf-8";/** 加密 1.构造密钥生成器 2.根据ecnodeRules规则初始化密钥生成器 3.产生密钥 4.创建和初始化密码器 5.内容加密 6.返回字符串*/public static String AESEncode(String encodeRules, String content) {try {// 1.构造密钥生成器,指定为AES算法,不区分大小写KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);// 2.根据ecnodeRules规则初始化密钥生成器// 生成一个128位的随机源,根据传入的字节数组//keygen.init(128, new SecureRandom(encodeRules.getBytes()));SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");secureRandom.setSeed(encodeRules.getBytes());keygen.init(128, secureRandom);// 3.产生原始对称密钥SecretKey original_key = keygen.generateKey();// 4.获得原始对称密钥的字节数组byte[] raw = original_key.getEncoded();// 5.根据字节数组生成AES密钥SecretKey key = new SecretKeySpec(raw, KEY_ALGORITHM);// 6.根据指定算法AES自成密码器Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);// 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEYcipher.init(Cipher.ENCRYPT_MODE, key);// 8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码byte[] byte_encode = content.getBytes(CHARSET_NAME);// 9.根据密码器的初始化方式--加密:将数据加密byte[] byte_AES = cipher.doFinal(byte_encode);// 10.将加密后的数据转换为字符串// 这里用Base64Encoder中会找不到包// 解决办法:// 在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。String AES_encode = new String(Base64.getEncoder().encodeToString(byte_AES));// 11.将字符串返回return AES_encode;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}// 如果有错就返加nulllreturn null;}/** 解密 解密过程: 1.同加密1-4步 2.将加密后的字符串反纺成byte[]数组 3.将加密内容解密*/public static String AESDncode(String encodeRules, String content) {try {// 1.构造密钥生成器,指定为AES算法,不区分大小写KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);// 2.根据ecnodeRules规则初始化密钥生成器// 生成一个128位的随机源,根据传入的字节数组//keygen.init(128, new SecureRandom(encodeRules.getBytes()));SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");secureRandom.setSeed(encodeRules.getBytes());keygen.init(128, secureRandom);// 3.产生原始对称密钥SecretKey original_key = keygen.generateKey();// 4.获得原始对称密钥的字节数组byte[] raw = original_key.getEncoded();// 5.根据字节数组生成AES密钥SecretKey key = new SecretKeySpec(raw, KEY_ALGORITHM);// 6.根据指定算法AES自成密码器Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);// 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEYcipher.init(Cipher.DECRYPT_MODE, key);// 8.将加密并编码后的内容解码成字节数组byte[] byte_content = Base64.getDecoder().decode(content);/** 解密*/byte[] byte_decode = cipher.doFinal(byte_content);String AES_decode = new String(byte_decode, CHARSET_NAME);return AES_decode;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}// 如果有错就返加nulllreturn null;}public static void main(String[] args) {String encodeRules = "rule";String text = "hello";String encodeText = AESEncode(encodeRules, text);System.out.println("加密后的密文是:" + encodeText);System.out.println("解密后的内容是:" + AESDncode(encodeRules, encodeText));}
}
6.6 非对称加密——RSA
RSA密钥对生成:http://web.chacuo.net/netrsakeypair
在线加密解密:在线加密解密 - chahuo.com
RSA算法是一种非对称加密算法,RSA 加密主要有这么几步:生成密钥对、公开公钥、公钥加内容加密、私钥+加密公钥解密。
package com.cloud.user;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;public class RSAUtil {private static final String CHARSET_NAME = "utf-8";private static final String TYPE = "RSA";/*** RSA公钥加密** @param str 加密字符串* @param publicKey 公钥* @return 密文* @throws Exception 加密过程中的异常信息*/public static String encrypt(String str, String publicKey) throws Exception {//base64编码的公钥byte[] decoded = Base64.decodeBase64(publicKey);RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(TYPE).generatePublic(new X509EncodedKeySpec(decoded));//RSA加密Cipher cipher = Cipher.getInstance(TYPE);cipher.init(Cipher.ENCRYPT_MODE, pubKey);String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(CHARSET_NAME)));return outStr;}/*** RSA私钥解密** @param str 加密字符串* @param privateKey 私钥* @return 铭文* @throws Exception 解密过程中的异常信息*/public static String decrypt(String str, String privateKey) throws Exception {//64位解码加密后的字符串byte[] inputByte = Base64.decodeBase64(str.getBytes(CHARSET_NAME));//base64编码的私钥byte[] decoded = Base64.decodeBase64(privateKey);RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(TYPE).generatePrivate(new PKCS8EncodedKeySpec(decoded));//RSA解密Cipher cipher = Cipher.getInstance(TYPE);cipher.init(Cipher.DECRYPT_MODE, priKey);String outStr = new String(cipher.doFinal(inputByte));return outStr;}public static void main(String[] args) throws Exception {String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKalqxfHXrZ0JZdLd2+BLhNS6bZxVyCOXvzFd0xCyX4oX/IbglKp9BGxQYaNl7stlHkQmMYBTAkIj0mAQzOVkqisYDevxKA5Yeitnim8R+N+a1SYaoQCfHLbCmMg4ZP0xaC30rA3DSMbEWQTD7p/g6v3sZevQUDVUcge9oaif9AQIDAQAB";String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMpqWrF8detnQll0t3b4EuE1LptnFXII5e/MV3TELJfihf8huCUqn0EbFBho2Xuy2UeRCYxgFMCQiPSYBDM5WSqKxgN6/EoDlh6K2eKbxH435rVJhqhAJ8ctsKYyDhk/TFoLfSsDcNIxsRZBMPun+Dq/exl69BQNVRyB72hqJ/0BAgMBAAECgYEAwOZKOArcddKaMJZCoWYY1/bOy9qZXWuNddHPJsAtnzGJcXK5AvJzgqBDrl99o5z15HYcG2MVY85aNn8IwahNh8CpFF8At7O2hVz1sTER2MPeiV5324BGOCPUkT4lY2iT2Dq6hXraZDI9sovit4FnfFlWH9nMOV5ckBvm5ypcCoECQQD/YLgSqXEERuu5qjU+PBCBKqbtOq5+EBNwLb9isxTPjRPoQ98sEzWsbyeLrc73Cjql5vU1io9rsG3IiYdEvFn9AkEAyuiaK95pbILOqK096d3Gt9oz0fqc5K4c9V44anaFzkEOysZlO3o1iZxqjfHdBlJiE4j0fq52+s+L9riqFbNMVQJATL3V0tXUPoLJZ3u8kD0ggJA+pV9S/FL8ZGN69b/26v/sEYoD0IzdPjoQ2iqa3SXXxe8HlNVUj/nuo6qgWYl4SQJBAJsXsYfoh7JeRXHegV15m8O5sDRGl5efkhjmfL67e0kMpy7M+GG+5p8ZhMScYzHK1JZT73XJCr5o13Ws7qyJkMUCQQD2EaVPOG+5M0VbzGGG820NRk9omSwO3GdSf4HZ6JWmeGk0FJN4NfAHnD8nA5L/HP+muqCdYQtYD068oZrNSabP";String text = "hello";String encodeText = encrypt(text, publicKey);System.out.println("加密后:" + encodeText);System.out.println("解密后:" + decrypt(encodeText, privateKey));}
}
java中加解密合集相关推荐
- 京东java笔试_2017阿里,百度,京东java面试+笔试大合集,2018的你会吗?
2017阿里,百度,京东java面试+笔试大合集 1.阿里 面试(一二面合集) 1.介绍一下你自己. 2.介绍一下你认为做的最好的一个项目. 3.请用五分钟的时间把你做的项目的流程图画一下. 4.项目 ...
- java老师和学生(java老师学生类合集)
Java学生老师类是一种用于模拟学生和老师之间的关系的类,通过它可以模拟学生和老师之间的信息交互.学生交作业等行为. 1.java老师和学生什么意思说法一,两种身份.java老师和学生是指在学习jav ...
- 调频合成器加预设合集 – Native Instruments FM8 v1.4.1 win-mac
Native Instruments FM8 v1.4.1 win-mac | 500M FM合成在过去几十年中在音乐文化的发展中发挥了巨大作用.FM8作为插件介绍了数字域的FM综合.强大的音频引擎可 ...
- Java中级面试题合集
Java中级面试题合集:1.弹出式选择菜单(Choice)和列表(List)有什么区别 Choice是以一种紧凑的形式展示的,需要下拉才能看到所有的选项.Choice中一次只能选中一个选项.List同 ...
- 【11款最全最新】Java游戏开发项目合集_Java项目实战_Java练手项目
黄金矿工.俄罗斯方块.飞机大战.超级玛丽.坦克大战.飞翔的小鸟.扫雷.王者荣耀.推箱子.贪吃蛇.大鱼吃小鱼这些经典小游戏相信很多人都玩过.那大家有没有想过亲自制作出这些小游戏呢? 下面就给大家分享这1 ...
- 【11款最全最新】Java游戏开发项目合集(上)_Java项目实战_Java练手项目
黄金矿工.俄罗斯方块.飞机大战.超级玛丽.坦克大战.飞翔的小鸟等等经典小游戏相信很多人都玩过.大家有没有想过亲自制作出这些小游戏呢? 今天给大家分享11款经典小游戏的Java开发教程,快来戳下方视频学 ...
- 网络安全中机器学习大合集 Awesome
网络安全中机器学习大合集 from:https://github.com/jivoi/awesome-ml-for-cybersecurity/blob/master/README_ch.md#-da ...
- Cakewalk Z3TA+ 2 v2.2.3.51 win-mac 波塑形合成器加预设合集
Cakewalk Z3TA+ 2 v2.2.3.51 win-mac | 100M Z3TA + 2设计为适合您的任何电子产品.从流行音乐到说唱音乐,从充满活力的音乐到大气,您都可以触手可及的声音. ...
- Java中加载配置文件方式的总结
当需要在Java中加载配置文件的时候,有几个选项提供选择: · File · Class.getResourceAsStream · Class.getCla ...
最新文章
- shortcut icon 修改浏览器标签网站图标
- html5游戏制作入门系列教程(七)
- HDOJ 1002 A + B Problem II 解题报告
- 如何在Linux中找到您的IP地址
- 提高搜索引擎结果页面排名的各种技术
- iOS网络请求 get - post 区别
- (一)使用RED5搭建流媒体服务器
- erlang的又一力作——英雄联盟聊天服务器
- 计算机基本应用Excel考题,excel考题_大学计算机基础期末考试试题word ppt excel的操作题_淘题吧...
- 论文阅读 decaNLP -- The Natural Language Decathlon: Multitask Leaning as Question Answering
- 支教日记软件测试,教学实习每周工作计划精选 .doc
- ajax的Provisional headers are shown
- Diss GitHub被收购?说不定是件大喜事呢!
- Markdown合并表格单元格
- 如何拆分PDF成多个文件?这样拆分非常简单
- 金融 python 招聘,滴滴、度小满金融python工程师社招面经
- 人脸颜值预测(facial beauty prediction)综述
- portal 源代码
- python导入自己的类型_如何将使用导入模块的我自己的类导入jupyter noteb
- 办理公司经营贷款需要什么条件呢?-民兴商学院
热门文章
- picoCTF - RE - Hurry up! Wait!
- 如何解决KEIL 5 编译KEIL4的带有RTX系统的工程解决方法
- 多线程|pi1.c 使用2个线程根据莱布尼兹级数计算PI
- sql 除法计算一直 为0原因及解决方案
- PMI-ACP练习题(12)
- gks的定义计算机图形学,计算机图形学(概念)
- Hadoop集群启动后利用Web界面管理HDFS
- python内置模块re_13.python内置模块之re模块
- 谈一谈SaaS产品的架构设计
- 【JS】使用onclick方法把对象本身传输给方法