diff --git a/pom.xml b/pom.xml index d1c7ffd..7a91dde 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ test-eureka-client-test test-kafka test-eureka-web - test-auth-token + test-netty diff --git a/test-auth-token/pom.xml b/test-auth-token/pom.xml deleted file mode 100644 index 263c623..0000000 --- a/test-auth-token/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - wsd - com.springboot.test - 1.0-SNAPSHOT - - 4.0.0 - - test-auth-token - token - 获取验证的token,包含有权限信息(角色 及 权限资源) - - - - - org.springframework.cloud - spring-cloud-starter-archaius - 1.3.4.RELEASE - - - - org.springframework.cloud - spring-cloud-starter-eureka - 1.3.4.RELEASE - - - - org.springframework.cloud - spring-cloud-starter-feign - 1.3.0.RELEASE - - - - - org.apache.commons - commons-lang3 - 3.7 - - - - - io.jsonwebtoken - jjwt - 0.7.0 - - - - - com.springboot.test - test-eureka-client-test - 1.0-SNAPSHOT - - - - - \ No newline at end of file diff --git a/test-auth-token/src/main/java/com/test/auth/token/AuthApplication.java b/test-auth-token/src/main/java/com/test/auth/token/AuthApplication.java deleted file mode 100644 index b8ddcf9..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/AuthApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.test.auth.token; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/29 17:31 - * Version: V1.0 - * Description: - * ====================== - */ -//TODO 增加客户端的启动注解以及熔断注解 -@MapperScan(basePackages = {"com.test.auth.token.dao"}) -@SpringBootApplication -public class AuthApplication -{ - public static void main(String[] args){ - new SpringApplicationBuilder(AuthApplication.class).web(true).run(args); - } - -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/dao/UserMapper.java b/test-auth-token/src/main/java/com/test/auth/token/dao/UserMapper.java deleted file mode 100644 index 41674a8..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/dao/UserMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.test.auth.token.dao; - -import org.springframework.stereotype.Repository; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/1/29 17:48 - * Version: V1.0 - * Description:用户信息 - * ======***********========= - */ -@Repository -public interface UserMapper -{ -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/service/AuthTokenService.java b/test-auth-token/src/main/java/com/test/auth/token/service/AuthTokenService.java deleted file mode 100644 index fe9122d..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/service/AuthTokenService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.test.auth.token.service; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/1/29 17:35 - * Version: V1.0 - * Description:根据用户的账号 获取当前用户的角色以及权限 产生对应的Token - * ======***********========= - */ -public interface AuthTokenService -{ - /** - * 根据账号或者手机号码 获取token - * @param account :账号或者 手机号码 - */ - void getToekn(String account); -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/service/impl/AuthTokenServiceImpl.java b/test-auth-token/src/main/java/com/test/auth/token/service/impl/AuthTokenServiceImpl.java deleted file mode 100644 index 814e927..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/service/impl/AuthTokenServiceImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.test.auth.token.service.impl; - -import com.test.auth.token.service.AuthTokenService; -import com.test.auth.token.service.rpc.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/29 17:38 - * Version: V1.0 - * Description: 产生用户token - * ====================== - */ -@Service -public class AuthTokenServiceImpl implements AuthTokenService -{ - @Autowired - private UserService userService ; - - @Override - public void getToekn(String account) - { - - } -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/service/impl/TokenUtilsServiceImpl.java b/test-auth-token/src/main/java/com/test/auth/token/service/impl/TokenUtilsServiceImpl.java deleted file mode 100644 index 6f5b254..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/service/impl/TokenUtilsServiceImpl.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.test.auth.token.service.impl; - -import com.test.auth.token.service.rpc.TokenUtilsService; -import com.test.auth.token.util.RSAEncryptUtil; -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.stereotype.Service; - -import java.security.interfaces.RSAPrivateKey; -import java.util.Base64; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/3/2 9:20 - * Version: V1.0 - * Description: - * ====================== - */ -@Service -public class TokenUtilsServiceImpl implements TokenUtilsService { - - private static final String PRIVATE_KEY_FILE = "D:/RAS/private.txt"; - - - @Override - public String decodePassword(String password) { - - if(null == password){ - return null ; - } - byte[] privateKey = RSAEncryptUtil.decoderByPrivateKey(password.getBytes(), RSAEncryptUtil.getPrivateKeyByString(RSAEncryptUtil.getKeyByFile(PRIVATE_KEY_FILE))); - - if(ArrayUtils.isEmpty(privateKey)){ - return null; - } - - byte[] decode = Base64.getDecoder().decode(privateKey); - - return new String(decode); - } -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/service/rpc/TokenUtilsService.java b/test-auth-token/src/main/java/com/test/auth/token/service/rpc/TokenUtilsService.java deleted file mode 100644 index 7af8b83..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/service/rpc/TokenUtilsService.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.test.auth.token.service.rpc; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/3/2 9:07 - * Version: V1.0 - * Description: 用于token 远程调用的工具service - * ======***********========= - */ -public interface TokenUtilsService { - - static final String BASE_URL = "rpc/rsa"; - - /** - * 用户进行登录时 对密码进行解密操作 - * @param password:用户密码 - * @return :解密以后的密码 - */ - @RequestMapping(value = BASE_URL+"/util",method = RequestMethod.POST) - String decodePassword(String password); -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/service/rpc/UserService.java b/test-auth-token/src/main/java/com/test/auth/token/service/rpc/UserService.java deleted file mode 100644 index 5dd2b87..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/service/rpc/UserService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.test.auth.token.service.rpc; - -import com.test.eureka.client.test.service.MemberClientService; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/1/29 17:54 - * Version: V1.0 - * Description: - * ======***********========= - */ -@FeignClient(name = "test-eureka-client") -public interface UserService extends MemberClientService -{ -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/util/JWTutil.java b/test-auth-token/src/main/java/com/test/auth/token/util/JWTutil.java deleted file mode 100644 index b2832f8..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/util/JWTutil.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.test.auth.token.util; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/29 17:10 - * Version: V1.0 - * Description:产生token - * ====================== - */ -public class JWTutil -{ - - - - - -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/util/RSAEncryptUtil.java b/test-auth-token/src/main/java/com/test/auth/token/util/RSAEncryptUtil.java deleted file mode 100644 index 460d5bc..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/util/RSAEncryptUtil.java +++ /dev/null @@ -1,420 +0,0 @@ -package com.test.auth.token.util; - -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import java.io.*; -import java.security.*; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; -import java.util.Objects; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/27 14:34 - * Version: V1.0 - * Description: 通过RSA 获取 Public_key 及 Private_key - * ====================== - */ -public class RSAEncryptUtil -{ - private static final Logger LOGGER = LoggerFactory.getLogger(RSAEncryptUtil.class); - - //使用的加密算法 - private static final String KEY_ALGORITHM = "RSA"; - - //长度 (单位 位;)RSA得到的密文长度不能超过 密匙长度的11位; - private static final Integer KEY_SIZE = 1024; - - //将公匙 和 私匙 保存到指定的 文件中 - private static final String PRIVATE_KEY_FILE = "D:/RAS/private.txt"; - private static final String PUBLIC_KEY_FILE = "D:/RAS/public.txt"; - - - public static void main(String[] args) - { - String text = "123456789"; - //获取密匙对 -// getKeyPair(); - //通过公匙对内容加密 - byte[] bytes = encodeByPublicKey(text.getBytes(), getPublicKeyByStr(getKeyByFile(PUBLIC_KEY_FILE))); - String string = Base64.getEncoder().encodeToString(bytes); - System.out.println(string); - } - - - /** - * 获取 密匙对 - */ - private static void getKeyPair() - { - try - { - KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM); - kpg.initialize(KEY_SIZE, new SecureRandom()); - - KeyPair keyPair = kpg.generateKeyPair(); - - RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); - RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); - - String strPublicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded()); - String strPrivateKey = Base64.getEncoder().encodeToString(privateKey.getEncoded()); - - LOGGER.info("kpg.generateKeyPair() 生成的公匙:" + strPublicKey); - LOGGER.info("kpg.generateKeyPair() 生成的私匙:" + strPrivateKey); - - FileWriter privateKeyFW = new FileWriter(PRIVATE_KEY_FILE); - FileWriter publicKeyFW = new FileWriter(PUBLIC_KEY_FILE); - - BufferedWriter privateKeyBw = new BufferedWriter(privateKeyFW); - BufferedWriter publicKeyBw = new BufferedWriter(publicKeyFW); - - publicKeyBw.write(strPublicKey); - privateKeyBw.write(strPrivateKey); - - privateKeyBw.flush(); - publicKeyBw.flush(); - - privateKeyBw.close(); - publicKeyBw.close(); - - privateKeyFW.close(); - publicKeyFW.close(); - - LOGGER.info("写入完成"); - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - LOGGER.info("加密算法有误,无法找到对应的加密算法"); - } catch (IOException e) - { - e.printStackTrace(); - LOGGER.info("创建文件出现异常"); - } - } - - - /** - * 从文件中 读取 密匙 - * - * @param filePath :文件路径 - */ - public static String getKeyByFile(String filePath) - { - try - { - if (StringUtils.isEmpty(filePath)) - { - LOGGER.info("文件路径为空"); - return null; - } - BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); - StringBuilder sb = new StringBuilder(); - String readLine = ""; - if ((readLine = bufferedReader.readLine()) != null) - { - sb.append(readLine); - } - - bufferedReader.close(); - - return sb.toString(); - - } catch (FileNotFoundException e) - { - e.printStackTrace(); - LOGGER.info("未找到对应的文件"); - } catch (IOException e) - { - e.printStackTrace(); - LOGGER.info("读取文件出现异常"); - } - return null; - } - - - /** - * 从 字符串中 还原 公匙 - * - * @param string : 字符串 - * @return : RSApublicKey 公匙 - */ - public static RSAPublicKey getPublicKeyByStr(String string) - { - if (StringUtils.isEmpty(string)) - { - LOGGER.info("缺少字符串来源"); - return null; - } - try - { - byte[] decode = Base64.getDecoder().decode(string); - //使用 公匙规范 还原 公匙 - X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode); - KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); - return (RSAPublicKey) factory.generatePublic(x509EncodedKeySpec); - - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - LOGGER.info("指定的算法有误"); - } catch (InvalidKeySpecException e) - { - e.printStackTrace(); - LOGGER.info("无效的公匙规范"); - } - return null; - } - - - /** - * 从给定的字符串中加载 私匙 - * - * @param string :指定的字符串 - * @return : RSAPrivatekey - */ - public static RSAPrivateKey getPrivateKeyByString(String string) - { - if (StringUtils.isEmpty(string)) - { - LOGGER.info("原字符串为空"); - return null; - } - try - { - byte[] decode = Base64.getDecoder().decode(string); - //私匙还原规范 - PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(decode); - - KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); - - return (RSAPrivateKey) factory.generatePrivate(pkcs8); - - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - LOGGER.info("找不到指定的算法"); - } catch (InvalidKeySpecException e) - { - e.printStackTrace(); - LOGGER.info("无效的规范"); - } - return null; - } - - /** - * 公匙 加密 - * - * @param content :加密内容 - * @param publicKey : 公匙 - */ - public static byte[] publicKeyEncrypt(byte[] content, RSAPublicKey publicKey) - { - if (Objects.isNull(publicKey) || ArrayUtils.isEmpty(content)) - { - LOGGER.info("通过publicKey加密时 参数有误"); - return null; - } - try - { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - return cipher.doFinal(content); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) - { - e.printStackTrace(); - LOGGER.info("找不到指定的算法出现异常或者。。。。。。"); - - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的key异常"); - - } catch (BadPaddingException | IllegalBlockSizeException e) - { - e.printStackTrace(); - LOGGER.info("使用公匙加密"); - } - return null; - } - - - /** - * 通过 私匙进行 加密 - * - * @param content : 需要加密的过程 - * @param privateKey :私匙 - */ - public static byte[] encodeByPrivateKey(byte[] content, RSAPrivateKey privateKey) - { - if (ArrayUtils.isEmpty(content) || Objects.isNull(privateKey)) - { - LOGGER.info("通过privateKey 加密时,参数有误"); - return null; - } - - try - { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - - cipher.init(Cipher.ENCRYPT_MODE, privateKey); - - return cipher.doFinal(content); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) - { - e.printStackTrace(); - LOGGER.info("无效的算法异常"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的privateKey异常"); - } catch (BadPaddingException | IllegalBlockSizeException e) - { - e.printStackTrace(); - LOGGER.info("privateKey加密时出现异常"); - } - - return null; - } - - - /** - * 通过私匙进行 解密 - * @param content : 解密的内容 - * @param privateKey :私匙 - */ - public static byte[] decoderByPrivateKey(byte[] content, RSAPrivateKey privateKey) - { - if (ArrayUtils.isEmpty(content) || Objects.isNull(privateKey)) - { - LOGGER.info("私匙机密时参数有误"); - return null ; - } - - try - { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - - cipher.init(Cipher.DECRYPT_MODE, privateKey); - return cipher.doFinal(content); - } catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) - { - e.printStackTrace(); - LOGGER.info("私匙解密的过程中出现异常"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的私匙"); - } - return null; - } - - - /** - * 公匙解密过程 - * - * @param content : 解密内容 - * @param publicKey : 公匙 - */ - public static byte[] decoderByPublicKey(byte[] content, RSAPublicKey publicKey) - { - if (ArrayUtils.isEmpty(content) || Objects.isNull(publicKey)) - { - LOGGER.info("publicKey解密过程中 参数有误"); - return null; - } - try - { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - - cipher.init(Cipher.DECRYPT_MODE, publicKey); - - return cipher.doFinal(content); - - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) - { - e.printStackTrace(); - LOGGER.info("解密时,没有找到指定的算法"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的公匙"); - } catch (BadPaddingException | IllegalBlockSizeException e) - { - e.printStackTrace(); - LOGGER.info("通过公匙解密时出现异常"); - } - return null; - } - - /** - * 公匙 加密 - * - * @param content : 加密的内容 - * @param publicKey : 公匙 - */ - public static byte[] encodeByPublicKey(byte[] content, RSAPublicKey publicKey) - { - if (ArrayUtils.isEmpty(content) || Objects.isNull(publicKey)) - { - LOGGER.info("公匙加密的过程中 参数有误"); - return null; - } - - try - { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - - return cipher.doFinal(content); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) - { - e.printStackTrace(); - LOGGER.info("无效的算法"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.debug("无效的私匙"); - } catch (BadPaddingException | IllegalBlockSizeException e) - { - e.printStackTrace(); - LOGGER.debug("PrivateKey加密时 出现异常"); - } - return null; - } - - /** - * 将字节内容 通过 Base64 加密成 字符串 - * - * @param content : 内容 - * @return : 加密以后的字符串内容 - */ - public static String encodeByBase64(byte[] content) - { - return Base64.getEncoder().encodeToString(content); - } - - /** - * 通过Base64 将 字符串 转换成 字节数组 - * - * @param content : 字符串内容 - * @return : 字节数组 - */ - public static byte[] decodeByBase64(String content) - { - return Base64.getDecoder().decode(content); - } -} diff --git a/test-auth-token/src/main/java/com/test/auth/token/util/RSASign.java b/test-auth-token/src/main/java/com/test/auth/token/util/RSASign.java deleted file mode 100644 index 46d41d6..0000000 --- a/test-auth-token/src/main/java/com/test/auth/token/util/RSASign.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.test.auth.token.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.*; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/28 11:45 - * Version: V1.0 - * Description: 签名 以及 验签类 - * ====================== - */ -public class RSASign -{ - private static final Logger LOGGER = LoggerFactory.getLogger(RSASign.class); - - - private static final String PRIVATE_KEY_FILE_PATH = "D:/RAS/private.txt"; - - //签名的算法 可在sign中查找 - private static final String SIGN_ALGORITHM = "SHA1withRSA"; - - private static final String KEY_ALGORITHM = "RSA"; - - /** - * 通过私匙 签发 签名 - * - * @param data :加密数据 - * @param privateKey : 私匙 - */ - public static String sign(byte[] data, String privateKey) - { - try - { - //先使用Base64解密 - byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey); - //使用规范获取私匙 - PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(privateKeyBytes); - - //使用工厂 进行初始化 - KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); - //更具规范 从工厂中获取到私匙 - RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) factory.generatePrivate(pkcs8); - - //获取签名对象 - Signature signature = Signature.getInstance(SIGN_ALGORITHM); - //有私匙 初始化签名 - signature.initSign(rsaPrivateKey); - signature.update(data); - - return Base64.getEncoder().encodeToString(signature.sign()); - - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - LOGGER.info("签名时,找不到指定的算法"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的私匙"); - } catch (SignatureException e) - { - e.printStackTrace(); - LOGGER.info("签名时出现异常"); - } catch (InvalidKeySpecException e) - { - e.printStackTrace(); - LOGGER.info("无效的规范"); - } - return null; - } - - - /** - * 验签 - * - * @param content : 原始签名内容 - * @param publicKey :公匙 - * @param sign :使用Base64加密后的签名串 - */ - public static boolean checkSign(String content, String publicKey, String sign) - { - try - { - //处理字符串公匙 - byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey); - - X509EncodedKeySpec x509 = new X509EncodedKeySpec(publicKeyBytes); - KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); - RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(x509); - Signature signature = Signature.getInstance(SIGN_ALGORITHM); - signature.initVerify(rsaPublicKey); - signature.update(content.getBytes()); - - return signature.verify(RSAEncryptUtil.decodeByBase64(sign)); - - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - LOGGER.info("无效的算法签名"); - } catch (InvalidKeySpecException e) - { - e.printStackTrace(); - LOGGER.info("无效的公匙规范"); - } catch (InvalidKeyException e) - { - e.printStackTrace(); - LOGGER.info("无效的公匙"); - } catch (SignatureException e) - { - e.printStackTrace(); - LOGGER.info("更新数据时,出现异常"); - } - return false; - } - - -} diff --git a/test-auth-token/src/main/resources/application.yml b/test-auth-token/src/main/resources/application.yml deleted file mode 100644 index 1808f1c..0000000 --- a/test-auth-token/src/main/resources/application.yml +++ /dev/null @@ -1,27 +0,0 @@ -server: - port: 9555 -spring: - application: - name: test-auth-token -eureka: - instance: - lease-renewal-interval-in-seconds: 10 - lease-expiration-duration-in-seconds: 30 - client: - register-with-eureka: true - fetch-registry: true - registry-fetch-interval-seconds: 30 - service-url: - defaultZone: http://testService:123aaa@127.0.0.1:9888/eureka/,http://testService:123aaa@127.0.0.1:9999/eureka/ -endpoints: - enabled: true -feign: - hystrix: - enable: true - compression: - request: - enable: true - mime-types: application/json,text/html,application/xml - min-request-size: 2048 - response: - enable: true \ No newline at end of file diff --git a/test-auth-token/src/test/java/TestRSA.java b/test-auth-token/src/test/java/TestRSA.java deleted file mode 100644 index 4310270..0000000 --- a/test-auth-token/src/test/java/TestRSA.java +++ /dev/null @@ -1,93 +0,0 @@ -import com.test.auth.token.util.RSAEncryptUtil; -import com.test.auth.token.util.RSASign; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; - -/** - * ====================== - * Created By User: RXK - * Date: 2018/1/29 10:01 - * Version: V1.0 - * Description: 公私匙 分别加密 然后再检验以及验签 - * ====================== - */ -public class TestRSA -{ - private static final Logger LOGGER = LoggerFactory.getLogger(TestRSA.class); - - - private static final String PRIVATE_KEY_FILE = "D:/RAS/private.txt"; - private static final String PUBLIC_KEY_FILE = "D:/RAS/public.txt"; - - public static void main(String[] args) - { - //需要加密的 内容 - String encryptText = "测试私匙加密公匙解密的文字"; - - LOGGER.info("私匙加密 ------- 公匙解密"); - - //从文件中加载私匙 - String privateKeyByFile = RSAEncryptUtil.getKeyByFile(PRIVATE_KEY_FILE); - - //将字符串还原成私匙 - RSAPrivateKey rsaPrivateKey = RSAEncryptUtil.getPrivateKeyByString(privateKeyByFile); - - //加密以后的内容 - byte[] encodeData = RSAEncryptUtil.encodeByPrivateKey(encryptText.getBytes(), rsaPrivateKey); - - //Base64加密 - String secretData = RSAEncryptUtil.encodeByBase64(encodeData); - - //从文件中加载公匙 - String publicKeyByFile = RSAEncryptUtil.getKeyByFile(PUBLIC_KEY_FILE); - - //将文件中的公匙通过 Base64 以及 公匙规范 工厂 得到公匙 - RSAPublicKey rsaPublicKey = RSAEncryptUtil.getPublicKeyByStr(publicKeyByFile); - - // 通过公匙解密 - byte[] decodeDataByte = RSAEncryptUtil.decoderByPublicKey(RSAEncryptUtil.decodeByBase64(secretData), rsaPublicKey); - - assert decodeDataByte != null; - String decodeData = new String(decodeDataByte); - - System.out.println("原文是:"+encryptText); - System.out.println("加密以后是:"+secretData); - System.out.println("解密以后是:"+decodeData); - - System.out.println("----------------------------------------------------------------------------------------"); - - //对需要加密的内容使用私匙进行 签名; 一起发送给 另一方 - String sign = RSASign.sign(encryptText.getBytes(), RSAEncryptUtil.getKeyByFile(PRIVATE_KEY_FILE)); - - System.out.println("签名串:"+sign); - - System.out.println("************************验签**********************************"); - - //接收方 使用公匙 先解密数据,然后再使用公匙 以及 签名 对解密的数据进行 验签 确保没有被更改过 - boolean checkSign = RSASign.checkSign(decodeData, RSAEncryptUtil.getKeyByFile(PUBLIC_KEY_FILE), sign); - System.out.println("检验结果:"+checkSign); - - - LOGGER.info("公匙加密 ------------------------------ 私匙解密 "); - - String testText = "测试使用公匙加密后然后使用私匙解密的过程"; - - //获取到公匙 并对内容进行加密 - byte[] encodeByPublicKey = RSAEncryptUtil.encodeByPublicKey(testText.getBytes(), RSAEncryptUtil.getPublicKeyByStr(RSAEncryptUtil.getKeyByFile(PUBLIC_KEY_FILE))); - String strEncodeByPublicKey = RSAEncryptUtil.encodeByBase64(encodeByPublicKey); - - //获取到私匙 并对内容进行 解密 - byte[] decoderByPrivateKey = RSAEncryptUtil.decoderByPrivateKey(RSAEncryptUtil.decodeByBase64(strEncodeByPublicKey), RSAEncryptUtil.getPrivateKeyByString(RSAEncryptUtil.getKeyByFile(PRIVATE_KEY_FILE))); - - assert decoderByPrivateKey != null; - String text = new String(decoderByPrivateKey); - - System.out.println("公匙加密以后的内容:"+strEncodeByPublicKey); - System.out.println("私匙解密以后的内容:"+text); - } - - -} diff --git a/test-eureka-client-test/src/main/java/com/test/eureka/client/test/service/ResourceClientService.java b/test-eureka-client-test/src/main/java/com/test/eureka/client/test/service/ResourceClientService.java index d45897f..fe92d47 100644 --- a/test-eureka-client-test/src/main/java/com/test/eureka/client/test/service/ResourceClientService.java +++ b/test-eureka-client-test/src/main/java/com/test/eureka/client/test/service/ResourceClientService.java @@ -13,7 +13,6 @@ * Description: 资源 * ====================== */ -@RestController public interface ResourceClientService { diff --git a/test-eureka-client/pom.xml b/test-eureka-client/pom.xml index 661e9a8..3f2ada6 100644 --- a/test-eureka-client/pom.xml +++ b/test-eureka-client/pom.xml @@ -38,7 +38,12 @@ org.springframework.boot - spring-boot-actuator + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-aop @@ -57,8 +62,13 @@ org.springframework.boot spring-boot-starter-jdbc - + + commons-collections + commons-collections + 3.2.2 + + local @@ -66,9 +76,6 @@ local - - true - dev @@ -76,9 +83,11 @@ dev dev + + true + - @@ -90,9 +99,9 @@ src/main/resources true + - **/*.xml - **/application-${profileActive}.yml + **/*.* @@ -131,6 +140,4 @@ - - \ No newline at end of file diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/EurekaClientApplication.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/EurekaClientApplication.java index a022e49..0e081ca 100644 --- a/test-eureka-client/src/main/java/com/test/eureka/web/client/EurekaClientApplication.java +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/EurekaClientApplication.java @@ -25,20 +25,18 @@ * Description: * ====================== */ -@MapperScan(annotationClass = Repository.class,basePackages = {"com.test.eureka.web.client.dao"}) -@ComponentScan(basePackages = {"com.test.eureka.web.client"}) @SpringBootApplication +@MapperScan(annotationClass = Repository.class, basePackages = {"com.test.eureka.web.client.dao"}) +@ComponentScan(basePackages = {"com.test.eureka.web.client"}) @EnableTransactionManagement -@EnableFeignClients -@EnableDiscoveryClient +//@EnableFeignClients +//@EnableDiscoveryClient @ServletComponentScan -@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) +@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class}) @Import(DruidConfig.class) -public class EurekaClientApplication -{ - public static void main(String[]args){ - new SpringApplicationBuilder(EurekaClientApplication.class).web(true) - .run(args); - } +public class EurekaClientApplication { + public static void main(String[] args) { + new SpringApplicationBuilder(EurekaClientApplication.class).web(true).run(args); + } } diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ChangeDataSourceAop.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ChangeDataSourceAop.java new file mode 100644 index 0000000..e46e6f6 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ChangeDataSourceAop.java @@ -0,0 +1,85 @@ +package com.test.eureka.web.client.config; + +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.util.Stack; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/9 17:27 + * Version: V1.0 + * Description: 切换数据源的 AOP 在 进入Service 层之前 切换数据源 + * 按照包结构 或者 注解 拦截 + * 拦截以后 将本地线程变量 中的内容删除 + *

+ * 注解 解释: + * 切面 @Aspect + * ====================== + */ +@Aspect +@Order(-1) //确保 该切面执行的顺序比 事务要早 +@Component +public class ChangeDataSourceAop { + + + private Stack booleanStack = new Stack<>(); + + private static final Logger LOGGER = LoggerFactory.getLogger(ChangeDataSourceAop.class); + + @Pointcut("execution(* com.test.eureka.web.client.rpc.service.*.*(..)) && @annotation(com.test.eureka.web.client.config.ReadDataSource)") + public void pointCut() { + } + + + @Before("pointCut()") + public void beforeSetRedDataSourceType() { + LOGGER.info("进入设置读数据库的AOP"); + Boolean flag = false; + + if (StringUtils.isEmpty(DataSourceLookUpKeyThreadLocal.getDataSourceLookUpKey())) { + LOGGER.info("设置当前的线程为 read"); + DataSourceLookUpKeyThreadLocal.setReadDataSourceLookUpKey(); + + flag = true; + } + + booleanStack.push(flag); + } + + + @Before("pointCut()") + public void beforeSetWriteDataSourceType() { + LOGGER.info("设置当前线程中的数据库类型为读"); + Boolean flag = false; + + if (StringUtils.isEmpty(DataSourceLookUpKeyThreadLocal.getDataSourceLookUpKey())) { + LOGGER.info("设置当前的线程为 write"); + DataSourceLookUpKeyThreadLocal.setWriteDataSourceLookUpKey(); + + flag = true; + } + + booleanStack.push(flag); + } + + + @After("pointCut()") + public void after(){ + if(booleanStack.pop()){ + LOGGER.info("去除当前线程中的 数据库读写的类型"); + DataSourceLookUpKeyThreadLocal.remove(); + } + } + + + +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomTranstionManagement.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomTranstionManagement.java new file mode 100644 index 0000000..d681ffc --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomTranstionManagement.java @@ -0,0 +1,36 @@ +package com.test.eureka.web.client.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/10 10:47 + * Version: V1.0 + * Description: 自定义 事务管理 + * ====================== + */ +@Configuration +@EnableTransactionManagement +public class CoustomTranstionManagement extends DataSourceTransactionManagerAutoConfiguration { + + + @Resource(name = "dataSource") + private DataSource writerDataSource; + + private static final Logger LOGGER = LoggerFactory.getLogger(CoustomTranstionManagement.class); + + public DataSourceTransactionManager transactionManager(){ + LOGGER.info("使用读数据库时 进事务管理器"); + return new DataSourceTransactionManager(writerDataSource); + } + +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceLookUpKeyThreadLocal.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceLookUpKeyThreadLocal.java new file mode 100644 index 0000000..ed5f648 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceLookUpKeyThreadLocal.java @@ -0,0 +1,39 @@ +package com.test.eureka.web.client.config; + +import com.test.eureka.web.client.enums.DatasourceEnum; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/7 22:45 + * Version: V1.0 + * Description: 使用当前线程 保存 使用的数据源的key + * 一是可以解决并发操作 保证线程安全 + * 二是 读库有多个数据源时 不会随意的跟换 + * ====================== + */ +public class DataSourceLookUpKeyThreadLocal { + + private static final ThreadLocal local = new ThreadLocal<>(); + + public static void setReadDataSourceLookUpKey(){ + local.set(DatasourceEnum.READ.name()); + } + + public static void setWriteDataSourceLookUpKey(){ + local.set(DatasourceEnum.WRITE.name()); + } + + + public static String getDataSourceLookUpKey(){ + return local.get(); + } + + /** + * 使用完后 必须删除 否则 很可能会操作内存溢出 + */ + public static void remove(){ + local.remove(); + } + +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomerDataSource.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceProperties.java similarity index 94% rename from test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomerDataSource.java rename to test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceProperties.java index 94d101e..f0b4086 100644 --- a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/CoustomerDataSource.java +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DataSourceProperties.java @@ -10,10 +10,9 @@ * Description: * ====================== */ -@ConfigurationProperties(prefix = CoustomerDataSource.DATA_SOURCE ) -public class CoustomerDataSource { - - public static final String DATA_SOURCE = "spring.datasource"; +@ConfigurationProperties(prefix = DataSourceProperties.DATA_SOURCE ) +public class DataSourceProperties { + public static final String DATA_SOURCE = "spring.datasource.master"; private String username ; @@ -39,7 +38,7 @@ public class CoustomerDataSource { private String validationQuery ; - private boolean testWhileIdle ; + private Boolean testWhileIdle ; private Boolean testOnBorrow ; @@ -53,9 +52,6 @@ public class CoustomerDataSource { private String type; - public CoustomerDataSource() { - } - public String getUsername() { return username; } diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DruidConfig.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DruidConfig.java index 3bc4469..9cda488 100644 --- a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DruidConfig.java +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/DruidConfig.java @@ -6,11 +6,10 @@ import com.alibaba.druid.support.http.WebStatFilter; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallFilter; -import org.mybatis.spring.SqlSessionFactoryBean; +import org.apache.commons.lang.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; @@ -18,6 +17,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import javax.sql.DataSource; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -31,13 +31,20 @@ * ====================== */ @Configuration -@EnableConfigurationProperties({CoustomerDataSource.class}) +@EnableConfigurationProperties({DataSourceProperties.class,SlaveDataSourceProperties.class}) public class DruidConfig { private static final Logger LOGGER = LoggerFactory.getLogger(DruidConfig.class); + private final DataSourceProperties writeProperties; + + private final SlaveDataSourceProperties readProperties; + @Autowired - private CoustomerDataSource properties; + public DruidConfig(DataSourceProperties dataSourceProperties,SlaveDataSourceProperties readProperties) { + this.writeProperties = dataSourceProperties; + this.readProperties = readProperties; + } @Bean public ServletRegistrationBean druidStatViewServlet() { @@ -61,32 +68,35 @@ public FilterRegistrationBean registrationBean() { return bean; } - @Bean + /** + * 作为主库 也是 唯一一个 写库 + */ + @Bean(name = "dataSource") public DruidDataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); - dataSource.setUrl(properties.getUrl()); - dataSource.setUsername(properties.getUsername()); - dataSource.setPassword(properties.getPassword()); - dataSource.setDriverClassName(properties.getDriverClassName()); - - dataSource.setTestWhileIdle(properties.getTestWhileIdle()); - dataSource.setTestOnReturn(properties.getTestOnReturn()); - dataSource.setTestOnBorrow(properties.getTestOnBorrow()); - dataSource.setMaxActive(properties.getMaxActive()); - dataSource.setMaxWait(properties.getMaxWait()); - dataSource.setMinIdle(properties.getMinIdle()); - dataSource.setInitialSize(properties.getInitialSize()); - dataSource.setValidationQuery(properties.getValidationQuery()); - - dataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements()); - dataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis()); - dataSource.setPoolPreparedStatements(properties.getPoolPreparedStatements()); - dataSource.setTimeBetweenConnectErrorMillis(properties.getTimeBetweenEvictionRunsMillis()); - dataSource.setConnectionProperties(properties.getConnectionProperties()); + dataSource.setUrl(writeProperties.getUrl()); + dataSource.setUsername(writeProperties.getUsername()); + dataSource.setPassword(writeProperties.getPassword()); + dataSource.setDriverClassName(writeProperties.getDriverClassName()); + + dataSource.setTestWhileIdle(writeProperties.getTestWhileIdle()); + dataSource.setTestOnReturn(writeProperties.getTestOnReturn()); + dataSource.setTestOnBorrow(writeProperties.getTestOnBorrow()); + dataSource.setMaxActive(writeProperties.getMaxActive()); + dataSource.setMaxWait(writeProperties.getMaxWait()); + dataSource.setMinIdle(writeProperties.getMinIdle()); + dataSource.setInitialSize(writeProperties.getInitialSize()); + dataSource.setValidationQuery(writeProperties.getValidationQuery()); + + dataSource.setMaxOpenPreparedStatements(writeProperties.getMaxOpenPreparedStatements()); + dataSource.setTimeBetweenEvictionRunsMillis(writeProperties.getTimeBetweenEvictionRunsMillis()); + dataSource.setPoolPreparedStatements(writeProperties.getPoolPreparedStatements()); + dataSource.setTimeBetweenConnectErrorMillis(writeProperties.getTimeBetweenEvictionRunsMillis()); + dataSource.setConnectionProperties(writeProperties.getConnectionProperties()); try { - dataSource.setFilters(properties.getFilters()); + dataSource.setFilters(writeProperties.getFilters()); List filterList=new ArrayList(); filterList.add(wallFilter()); @@ -99,6 +109,50 @@ public DruidDataSource dataSource() { return dataSource; } + @Bean(name="readDataSource") + public List readDataSource(){ + List list = new ArrayList<>(); + //不使用的时候 在配置文件中 直接删除掉 也不会报错 + if(readProperties != null && ArrayUtils.isNotEmpty(readProperties.getUrl())) { + + DruidDataSource readDataSource = new DruidDataSource(); + readDataSource.setDriverClassName(readProperties.getDriverClassName()); + try { + readDataSource.setFilters(readProperties.getFilters()); + List filters = new ArrayList<>(); + filters.add(wallFilter()); + dataSource().setProxyFilters(filters); + + } catch (SQLException e) { + LOGGER.info("读库设置过滤出现异常:{}", e.getMessage()); + } + readDataSource.setMaxWait(readProperties.getMaxWait()); + readDataSource.setMinIdle(readProperties.getMinIdle()); + readDataSource.setMaxActive(readProperties.getMaxActive()); + readDataSource.setInitialSize(readProperties.getInitialSize()); + readDataSource.setTestOnBorrow(readProperties.getTestOnBorrow()); + readDataSource.setTestOnReturn(readProperties.getTestOnReturn()); + readDataSource.setTestWhileIdle(readProperties.getTestWhileIdle()); + readDataSource.setInitialSize(readProperties.getInitialSize()); + readDataSource.setValidationQuery(readProperties.getValidationQuery()); + readDataSource.setConnectionProperties(readProperties.getConnectionProperties()); + readDataSource.setPoolPreparedStatements(readProperties.getPoolPreparedStatements()); + readDataSource.setMaxOpenPreparedStatements(readProperties.getMaxOpenPreparedStatements()); + readDataSource.setMinEvictableIdleTimeMillis(readProperties.getMinEvictableIdleTimeMillis()); + readDataSource.setTimeBetweenEvictionRunsMillis(readProperties.getTimeBetweenEvictionRunsMillis()); + list.add(readDataSource); + for(int i =0 ; i< readProperties.getUrl().length; i++){ + DruidDataSource dataSource = readDataSource.cloneDruidDataSource(); + dataSource.setUrl(readProperties.getUrl()[i]); + dataSource.setUsername(readProperties.getUsername()[i]); + dataSource.setPassword(readProperties.getPassword()[i]); + list.add(dataSource); + } + } + return list; + } + + @Bean public WallConfig wallConfig(){ WallConfig config =new WallConfig(); diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyAbstractroutintDataSource.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyAbstractroutintDataSource.java new file mode 100644 index 0000000..a06bcb4 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyAbstractroutintDataSource.java @@ -0,0 +1,48 @@ +package com.test.eureka.web.client.config; + +import com.test.eureka.web.client.enums.DatasourceEnum; +import org.apache.commons.lang.StringUtils; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/6 23:49 + * Version: V1.0 + * Description: 继承 Spring 的AbstractRoutingDataSource + * 实现 determineCurrentLookupKey 主要是获取当前线程中使用的 是 什么数据源 + * 自己实现该方法 决定实现的方式 + *

+ * ====================== + */ +public class MyAbstractroutintDataSource extends AbstractRoutingDataSource { + + private int readDataSourceSize; + + private AtomicInteger count = new AtomicInteger(); + + public MyAbstractroutintDataSource(int readDataSourceSize) { + this.readDataSourceSize = readDataSourceSize; + } + + + @Override + protected Object determineCurrentLookupKey() { + + //从当前的线程中 获取 LookUpKey + String lookUpKey = DataSourceLookUpKeyThreadLocal.getDataSourceLookUpKey(); + + //当前环境中 读库的数量 不为0 并且 LookUpKey 不为空 + //如果当前线程中 保存的是从库或者读库 数据源会有多个 那个轮询的方式 选择对应的数据源 + if (readDataSourceSize > 0 && StringUtils.isNotBlank(lookUpKey) && lookUpKey.equalsIgnoreCase(DatasourceEnum.READ.name())) { + int num = count.getAndAdd(1); + int i = num % readDataSourceSize; + return new Integer(i); + } + + // 返回 主库huozhe或者 写的数据源 + return DatasourceEnum.WRITE.name(); + } +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyBatisConfigration.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyBatisConfigration.java new file mode 100644 index 0000000..3a1ace5 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/MyBatisConfigration.java @@ -0,0 +1,116 @@ +package com.test.eureka.web.client.config; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.ibatis.mapping.DatabaseIdProvider; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; +import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; +import org.mybatis.spring.boot.autoconfigure.MybatisProperties; +import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ResourceLoader; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/6 22:31 + * Version: V1.0 + * Description: + * ====================== + */ +@Configuration +public class MyBatisConfigration extends MybatisAutoConfiguration { + + + @Autowired + private MybatisProperties properties; + + @Autowired + private ResourceLoader resourceLoader; + + + @Resource(name = "dataSource") + private DataSource writeDataSource; + + @Resource(name = "readDataSource") + private List readDataSource; + + public MyBatisConfigration(MybatisProperties properties, ObjectProvider interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider> configurationCustomizersProvider) { + super(properties, interceptorsProvider, resourceLoader, databaseIdProvider, configurationCustomizersProvider); + } + + + /** + * 自定义 SqlSessionFactory 中使用的数据源 + * + * @return :sqlSessionFactory 对象 + */ + @Bean + @ConditionalOnMissingBean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); + factory.setDataSource(this.routingDataSource()); + factory.setVfs(SpringBootVFS.class); + if (StringUtils.hasText(this.properties.getConfigLocation())) { + factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); + } + org.apache.ibatis.session.Configuration configuration = this.properties.getConfiguration(); + if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) { + configuration = new org.apache.ibatis.session.Configuration(); + } + + factory.setConfiguration(configuration); + if (this.properties.getConfigurationProperties() != null) { + factory.setConfigurationProperties(this.properties.getConfigurationProperties()); + } + if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { + factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); + } + if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { + factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); + } + if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { + factory.setMapperLocations(this.properties.resolveMapperLocations()); + } + + return factory.getObject(); + } + + + @Bean + public AbstractRoutingDataSource routingDataSource() { + int size = 0; + + if (CollectionUtils.isNotEmpty(readDataSource)) { + size = readDataSource.size(); + } + + MyAbstractroutintDataSource dataSourceProxy = new MyAbstractroutintDataSource(size); + + Map targetDataSource = new HashMap<>(); + + for (int i = 0; i < readDataSource.size(); i++) { + targetDataSource.put(i, readDataSource.get(i)); + } + + // 默认的 写库 + dataSourceProxy.setDefaultTargetDataSource(writeDataSource); + dataSourceProxy.setTargetDataSources(targetDataSource); + return dataSourceProxy; + } +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ReadDataSource.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ReadDataSource.java new file mode 100644 index 0000000..842e0e7 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/ReadDataSource.java @@ -0,0 +1,22 @@ +package com.test.eureka.web.client.config; + +import java.lang.annotation.*; + +/** + * 自定义注解 时 使用的元注解 + * @Retention(RetentionPolicy.RUNTIME) --- 定义 注解的 生命周期 分为三个阶段 + * 1 编译阶段 SOURCE 也称为 源码阶段 + * 2 类加载阶段 CLASS + * 3 运行阶段 RUNTIME + *@Target({ElementType.TYPE,ElementType.METHOD}) --- 定义该注解 使用于那些目标上 + * Type : 用于Class Interface Enum 上 + * Method :用于方法上 + * Filed :用于字段上 + * Package :包上 + * Varlable LocalVarlable 以及 构造方法上 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE,ElementType.METHOD}) +public @interface ReadDataSource { +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/config/SlaveDataSourceProperties.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/SlaveDataSourceProperties.java new file mode 100644 index 0000000..5dff427 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/config/SlaveDataSourceProperties.java @@ -0,0 +1,209 @@ +package com.test.eureka.web.client.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/6/6 17:04 + * Version: V1.0 + * Description: + * ====================== + */ +@ConfigurationProperties(prefix = SlaveDataSourceProperties.DataSource) +public class SlaveDataSourceProperties { + public static final String DataSource ="spring.datasource.slave" ; + + private String[] url ; + + private String[] username; + + private String[] password ; + + private String driverClassName ; + + private String filters ; + + private Integer maxActive ; + + private Integer initialSize ; + + private Integer maxWait ; + + private Integer minIdle ; + + private Long timeBetweenEvictionRunsMillis ; + + private Long minEvictableIdleTimeMillis ; + + private String validationQuery ; + + private Boolean testWhileIdle ; + + private Boolean testOnBorrow ; + + private Boolean testOnReturn ; + + private Boolean poolPreparedStatements; + + private Integer maxOpenPreparedStatements ; + + private String connectionProperties ; + + private String type; + + + public String[] getUrl() { + return url; + } + + public void setUrl(String[] url) { + this.url = url; + } + + public String[] getUsername() { + return username; + } + + public void setUsername(String[] username) { + this.username = username; + } + + public String[] getPassword() { + return password; + } + + public void setPassword(String[] password) { + this.password = password; + } + + public String getDriverClassName() { + return driverClassName; + } + + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + + public String getFilters() { + return filters; + } + + public void setFilters(String filters) { + this.filters = filters; + } + + public Integer getMaxActive() { + return maxActive; + } + + public void setMaxActive(Integer maxActive) { + this.maxActive = maxActive; + } + + public Integer getInitialSize() { + return initialSize; + } + + public void setInitialSize(Integer initialSize) { + this.initialSize = initialSize; + } + + public Integer getMaxWait() { + return maxWait; + } + + public void setMaxWait(Integer maxWait) { + this.maxWait = maxWait; + } + + public Integer getMinIdle() { + return minIdle; + } + + public void setMinIdle(Integer minIdle) { + this.minIdle = minIdle; + } + + public Long getTimeBetweenEvictionRunsMillis() { + return timeBetweenEvictionRunsMillis; + } + + public void setTimeBetweenEvictionRunsMillis(Long timeBetweenEvictionRunsMillis) { + this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; + } + + public Long getMinEvictableIdleTimeMillis() { + return minEvictableIdleTimeMillis; + } + + public void setMinEvictableIdleTimeMillis(Long minEvictableIdleTimeMillis) { + this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; + } + + public String getValidationQuery() { + return validationQuery; + } + + public void setValidationQuery(String validationQuery) { + this.validationQuery = validationQuery; + } + + public Boolean getTestWhileIdle() { + return testWhileIdle; + } + + public void setTestWhileIdle(Boolean testWhileIdle) { + this.testWhileIdle = testWhileIdle; + } + + public Boolean getTestOnBorrow() { + return testOnBorrow; + } + + public void setTestOnBorrow(Boolean testOnBorrow) { + this.testOnBorrow = testOnBorrow; + } + + public Boolean getTestOnReturn() { + return testOnReturn; + } + + public void setTestOnReturn(Boolean testOnReturn) { + this.testOnReturn = testOnReturn; + } + + public Boolean getPoolPreparedStatements() { + return poolPreparedStatements; + } + + public void setPoolPreparedStatements(Boolean poolPreparedStatements) { + this.poolPreparedStatements = poolPreparedStatements; + } + + public Integer getMaxOpenPreparedStatements() { + return maxOpenPreparedStatements; + } + + public void setMaxOpenPreparedStatements(Integer maxOpenPreparedStatements) { + this.maxOpenPreparedStatements = maxOpenPreparedStatements; + } + + public String getConnectionProperties() { + return connectionProperties; + } + + public void setConnectionProperties(String connectionProperties) { + this.connectionProperties = connectionProperties; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/test-eureka-client/src/main/java/com/test/eureka/web/client/enums/DatasourceEnum.java b/test-eureka-client/src/main/java/com/test/eureka/web/client/enums/DatasourceEnum.java new file mode 100644 index 0000000..bd40d84 --- /dev/null +++ b/test-eureka-client/src/main/java/com/test/eureka/web/client/enums/DatasourceEnum.java @@ -0,0 +1,18 @@ +package com.test.eureka.web.client.enums; + +/** + * ************************ + * Created By User: RXK + * Date: 2018/5/13 11:43 + * Version: V1.0 + * Description: 主从库枚举 + * 作为多数据源的lookup key + * ************************** + */ +public enum DatasourceEnum { + READ, + WRITE; + + /*先省略*/ + +} diff --git a/test-eureka-client/src/main/resources/application-dev.yml b/test-eureka-client/src/main/resources/application-dev.yml index 9e7aaf6..d403940 100644 --- a/test-eureka-client/src/main/resources/application-dev.yml +++ b/test-eureka-client/src/main/resources/application-dev.yml @@ -1,33 +1,57 @@ server: port: 9777 spring: - application: - name: test-eureka-client datasource: - username: test - password: test - driver-class-name: com.mysql.cj.jdbc.Driver - filters: stat,wall,slf4j - maxActive: 20 - initialSize: 1 - maxWait: 60000 - minIdle: 1 - timeBetweenEvictionRunsMillis: 60000 - minEvictableIdleTimeMillis: 300000 - validationQuery: select 'x' - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - poolPreparedStatements: true - maxOpenPreparedStatements: 20 - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - type: com.alibaba.druid.pool.DruidDataSource - url: jdbc:mysql://192.168.60.76:3306/rxk?serverTimezone=UTC&characterEncoding=UTF-8 - profiles: - active: @profileActive@ -mybatis: - mapper-locations: classpath*:com/test/eureka/web/client/**/dao/**/*Mapper.xml # 不能有空格 - config-location: classpath:mybatis-config.xml + master: + url: jdbc:mysql://127.0.0.1:3306/rxk?serverTimezone=UTC&characterEncoding=UTF-8 + username: helloworld + password: 1234567890 + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat,wall,slf4j + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + type: com.alibaba.druid.pool.DruidDataSource + slave: + - + url: jdbc:mysql://10.0.20.170:3306/dev_healthmall_sail?useUnicode=true&characterEncoding=utf-8 + username: dev_healthmall_sail + password: PNB4SIwR2MSHfXcGOB98fu370 + - + url: jdbc:mysql://127.0.0.1:3306/rxk?serverTimezone=UTC&characterEncoding=UTF-8 + username: helloworld + password: 1234567890 + - + url: jdbc:mysql://10.0.20.170:3306/healthmall_iot?useUnicode=true&characterEncoding=utf-8 + username: healthmall_iot + password: TkFMKeO5xbXgbgKBWv7YOf9H8 + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat,wall,slf4j + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + type: com.alibaba.druid.pool.DruidDataSource + eureka: instance: lease-renewal-interval-in-seconds: 10 diff --git a/test-eureka-client/src/main/resources/application.yml b/test-eureka-client/src/main/resources/application.yml index 0e70528..02a3169 100644 --- a/test-eureka-client/src/main/resources/application.yml +++ b/test-eureka-client/src/main/resources/application.yml @@ -4,30 +4,12 @@ spring: application: name: test-eureka-client profiles: - active: "@profileActive@" - datasource: - url: jdbc:mysql://127.0.0.1:3306/rxk?serverTimezone=UTC&characterEncoding=UTF-8 - username: helloworld - password: 1234567890 - driver-class-name: com.mysql.cj.jdbc.Driver - filters: stat,wall,slf4j - maxActive: 20 - initialSize: 1 - maxWait: 60000 - minIdle: 1 - timeBetweenEvictionRunsMillis: 60000 - minEvictableIdleTimeMillis: 300000 - validationQuery: select 'x' - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - poolPreparedStatements: true - maxOpenPreparedStatements: 20 - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - type: com.alibaba.druid.pool.DruidDataSource + active: dev + mybatis: mapper-locations: classpath*:com/test/eureka/web/client/**/dao/**/*Mapper.xml # 不能有空格 config-location: classpath:mybatis-config.xml + eureka: instance: lease-renewal-interval-in-seconds: 10 @@ -44,3 +26,11 @@ endpoints: enabled: true health: enabled: true +feign: + compression: + request: + enabled: true + mime-types: application/json + min-request-size: 2048 + response: + enabled: true \ No newline at end of file diff --git a/test-eureka-client/src/test/java/test.java b/test-eureka-client/src/test/java/test.java index 1559bfe..9d4ae06 100644 --- a/test-eureka-client/src/test/java/test.java +++ b/test-eureka-client/src/test/java/test.java @@ -10,7 +10,7 @@ * Description: * ====================== */ -@PropertySource(value ="classpath:application.yml" ) +@PropertySource(value = "classpath:application.yml") public class test { @Value(value = "${spring.datasource.url}") diff --git a/test-eureka-web/pom.xml b/test-eureka-web/pom.xml index 697bbe6..773b806 100644 --- a/test-eureka-web/pom.xml +++ b/test-eureka-web/pom.xml @@ -67,10 +67,12 @@ com.springboot.test - test-eureka-client-test + test-eureka-client 1.0-SNAPSHOT + + io.springfox springfox-swagger2 @@ -88,6 +90,13 @@ spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-redis + 1.4.7.RELEASE + + org.apache.shiro @@ -100,14 +109,6 @@ shiro-ehcache 1.4.0 - - - - com.springboot.test - test-auth-token - 1.0-SNAPSHOT - - com.alibaba fastjson @@ -125,6 +126,23 @@ org.springframework.boot spring-boot-starter-data-mongodb + + + @@ -133,9 +151,6 @@ local - - true - dev @@ -143,6 +158,9 @@ dev dev + + true + diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/WebApplication.java b/test-eureka-web/src/main/java/com/test/eureka/web/WebApplication.java index d9e257e..84f0afe 100644 --- a/test-eureka-web/src/main/java/com/test/eureka/web/WebApplication.java +++ b/test-eureka-web/src/main/java/com/test/eureka/web/WebApplication.java @@ -11,8 +11,10 @@ import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.transaction.PlatformTransactionManager; /** * ====================== @@ -23,14 +25,14 @@ * Description: * ====================== */ -@EnableFeignClients // 开启feign -@EnableDiscoveryClient // 开启客户端发现 +//@EnableFeignClients // 开启feign +//@EnableDiscoveryClient // 开启客户端发现 @SpringBootApplication @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) @ServletComponentScan @ComponentScan(basePackages = {"com.test.eureka.web"}) @EnableHystrix //开启熔断 包含有 @EnableCircuitBreaker -@EnableHystrixDashboard // 开启熔断器的仪表盘 +//@EnableHystrixDashboard // 开启熔断器的仪表盘 @EnableAsync public class WebApplication { @@ -38,4 +40,5 @@ public static void main(String[] args) { new SpringApplicationBuilder(WebApplication.class).web(true).run(args); } + } diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/config/GloableRuntimeException.java b/test-eureka-web/src/main/java/com/test/eureka/web/config/GloableRuntimeException.java new file mode 100644 index 0000000..cc07e3d --- /dev/null +++ b/test-eureka-web/src/main/java/com/test/eureka/web/config/GloableRuntimeException.java @@ -0,0 +1,31 @@ +package com.test.eureka.web.config; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/20 10:54 + * Version: V1.0 + * Description: 使用注解 定义全解的异常处理类 + * ====================== + */ +@RestControllerAdvice //其中包括 @InitBinder @ExceptionHandler +public class GloableRuntimeException { + + /** + * @InitBinder 注解会作用在 所有的@RequestMapping注解的方法上,进行初始化 比如多Model进行初始化 + * + * @ExceptionHandler 用于捕获指定的异常类 用于自定义的异常 统一处理 + */ + + + @ExceptionHandler(value = MyRuntimeException.class) + public ResponseEntity dileException(){ + //捕捉到指定的异常类时 就执行该处的代码逻辑 + return null ; + } + +} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/config/MyRuntimeException.java b/test-eureka-web/src/main/java/com/test/eureka/web/config/MyRuntimeException.java new file mode 100644 index 0000000..04de39b --- /dev/null +++ b/test-eureka-web/src/main/java/com/test/eureka/web/config/MyRuntimeException.java @@ -0,0 +1,61 @@ +package com.test.eureka.web.config; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/20 10:50 + * Version: V1.0 + * Description: 将运行时异常 换成自定义的异常 + * ====================== + */ +public class MyRuntimeException extends RuntimeException{ + + private Integer code ; + + private String msg ; + + public MyRuntimeException(Integer code, String msg) { + this.code = code; + this.msg = msg; + } + + public MyRuntimeException(String message, Integer code, String msg) { + super(message); + this.code = code; + this.msg = msg; + } + + public MyRuntimeException(String message, Throwable cause, Integer code, String msg) { + super(message, cause); + this.code = code; + this.msg = msg; + } + + public MyRuntimeException(Throwable cause, Integer code, String msg) { + super(cause); + this.code = code; + this.msg = msg; + } + + public MyRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Integer code, String msg) { + super(message, cause, enableSuppression, writableStackTrace); + this.code = code; + this.msg = msg; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/config/PageIntecepter.java b/test-eureka-web/src/main/java/com/test/eureka/web/config/PageIntecepter.java new file mode 100644 index 0000000..ee8b3d2 --- /dev/null +++ b/test-eureka-web/src/main/java/com/test/eureka/web/config/PageIntecepter.java @@ -0,0 +1,13 @@ +package com.test.eureka.web.config; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/26 9:37 + * Version: V1.0 + * Description:MyBatis中是用拦截器实现物理分页 + * 将全部的数据查询出来 再分页 + * ====================== + */ +public class PageIntecepter { +} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/config/RequestBodyHelper.java b/test-eureka-web/src/main/java/com/test/eureka/web/config/RequestBodyHelper.java index b7e053f..23cf4c0 100644 --- a/test-eureka-web/src/main/java/com/test/eureka/web/config/RequestBodyHelper.java +++ b/test-eureka-web/src/main/java/com/test/eureka/web/config/RequestBodyHelper.java @@ -26,29 +26,17 @@ public class RequestBodyHelper //从request请求流中获取内容 相当于做备份 是的流可以多次读取 public static String getBody(HttpServletRequest request) { - BufferedReader br = null; InputStream inputStream = null; - StringBuilder sb = null; try { inputStream = request.getInputStream(); - br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); - - sb = new StringBuilder(); - String readLine = null; - while ((readLine = br.readLine()) != null) - { - sb.append(readLine); - } + String string = IOUtils.toString(inputStream); + return string ; } catch (IOException e) { e.printStackTrace(); LOGGER.info("读取参数时,出现异常:{}", e.getMessage()); - } finally - { - IOUtils.closeQuietly(br); - IOUtils.closeQuietly(inputStream); + return null ; } - return sb.toString() ; } } diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/controller/LogInController.java b/test-eureka-web/src/main/java/com/test/eureka/web/controller/LogInController.java index a107f87..8d5fae0 100644 --- a/test-eureka-web/src/main/java/com/test/eureka/web/controller/LogInController.java +++ b/test-eureka-web/src/main/java/com/test/eureka/web/controller/LogInController.java @@ -1,8 +1,6 @@ package com.test.eureka.web.controller; -import com.test.eureka.client.test.dto.Member; import com.test.eureka.web.dto.LogInInDTO; -import com.test.eureka.web.service.rpc.TokenFeignService; import com.test.eureka.web.utils.EncryptUtil; import io.swagger.annotations.Api; import org.apache.shiro.SecurityUtils; @@ -11,7 +9,6 @@ import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -31,20 +28,17 @@ public class LogInController { private static final Logger LOGGER = LoggerFactory.getLogger(LogInController.class); - @Autowired - private TokenFeignService tokenFeignService ; - @RequestMapping("/login") public ResponseEntity logIn(@RequestBody LogInInDTO inDTO) { LOGGER.info("*************************用户登录***************************"); //密码 需要使用 私匙进行解密 在经过 加密 传进去 - String password = tokenFeignService.decodePassword(inDTO.getPassword()); + /* String password = tokenFeignService.decodePassword(inDTO.getPassword()); inDTO.setPassword(password); - +*/ String encryptPassword = EncryptUtil.encryptPassword(inDTO); - UsernamePasswordToken token = new UsernamePasswordToken(inDTO.getUsername(), encryptPassword); + UsernamePasswordToken token = new UsernamePasswordToken(inDTO.getUserName(), encryptPassword); try { diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/dto/LogInInDTO.java b/test-eureka-web/src/main/java/com/test/eureka/web/dto/LogInInDTO.java index d5e0b4d..63fb7a3 100644 --- a/test-eureka-web/src/main/java/com/test/eureka/web/dto/LogInInDTO.java +++ b/test-eureka-web/src/main/java/com/test/eureka/web/dto/LogInInDTO.java @@ -12,16 +12,16 @@ */ public class LogInInDTO implements Serializable { - private String username ; + private String userName ; private String password ; - public String getUsername() { - return username; + public String getUserName() { + return userName; } - public void setUsername(String username) { - this.username = username; + public void setUserName(String userName) { + this.userName = userName; } public String getPassword() diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/service/hystrix/TokenFeignServiceHystrix.java b/test-eureka-web/src/main/java/com/test/eureka/web/service/hystrix/TokenFeignServiceHystrix.java deleted file mode 100644 index 65d84a7..0000000 --- a/test-eureka-web/src/main/java/com/test/eureka/web/service/hystrix/TokenFeignServiceHystrix.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.test.eureka.web.service.hystrix; - -import com.test.eureka.web.service.rpc.TokenFeignService; -import org.springframework.stereotype.Component; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/3/2 9:11 - * Version: V1.0 - * Description:token 熔断器 - * ======***********========= - */ -@Component -public class TokenFeignServiceHystrix implements TokenFeignService{ - @Override - public String decodePassword(String password) { - return null; - } -} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/service/rpc/TokenFeignService.java b/test-eureka-web/src/main/java/com/test/eureka/web/service/rpc/TokenFeignService.java deleted file mode 100644 index 1c5a489..0000000 --- a/test-eureka-web/src/main/java/com/test/eureka/web/service/rpc/TokenFeignService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.test.eureka.web.service.rpc; - -import com.test.auth.token.service.rpc.TokenUtilsService; -import com.test.eureka.web.config.CustomFeignConfig; -import com.test.eureka.web.service.hystrix.TokenFeignServiceHystrix; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * ======***********========= - * Created By User: RXK - * Date: 2018/3/2 9:04 - * Version: V1.0 - * Description:用于密码进行 加 解 迷的 操作 - * ======***********========= - */ -@FeignClient(value = "test-token-client",configuration = CustomFeignConfig.class,fallback = TokenFeignServiceHystrix.class) -public interface TokenFeignService extends TokenUtilsService{ -} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/utils/EncryptUtil.java b/test-eureka-web/src/main/java/com/test/eureka/web/utils/EncryptUtil.java index f449a6e..e02de42 100644 --- a/test-eureka-web/src/main/java/com/test/eureka/web/utils/EncryptUtil.java +++ b/test-eureka-web/src/main/java/com/test/eureka/web/utils/EncryptUtil.java @@ -1,6 +1,5 @@ package com.test.eureka.web.utils; -import com.test.eureka.client.test.dto.Member; import com.test.eureka.web.dto.LogInInDTO; import org.apache.shiro.crypto.SecureRandomNumberGenerator; import org.apache.shiro.crypto.hash.SimpleHash; @@ -28,10 +27,10 @@ public static String encryptPassword(LogInInDTO member){ SecureRandomNumberGenerator numberGenerator = new SecureRandomNumberGenerator(); StringBuffer sb = new StringBuffer(); - String salt = sb.append(member.getUsername()).append(numberGenerator.nextBytes().toHex()).toString(); + String salt = sb.append(member.getUserName()).append(numberGenerator.nextBytes().toHex()).toString(); //经过加密以后的密码 确保用户名的唯一性 就可以保证 即使相同的密码 加密以后的密码也是不一样的 - return new SimpleHash(ALGORRITHM, member.getPassword(), member.getUsername()+PRIVATE_SALT, HASHCOUNT).toHex(); + return new SimpleHash(ALGORRITHM, member.getPassword(), member.getUserName()+PRIVATE_SALT, HASHCOUNT).toHex(); } diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyPairsUtils.java b/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyPairsUtils.java new file mode 100644 index 0000000..32989e1 --- /dev/null +++ b/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyPairsUtils.java @@ -0,0 +1,108 @@ +package com.test.eureka.web.utils; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Base64; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/20 13:55 + * Version: V1.0 + * Description: 非对称加密 + * 使用JDK自带的Base64 以及 对应的类 产生私匙 以及 公匙 + * ====================== + */ +public class KeyPairsUtils { + + + private static final Logger LOGGER = LoggerFactory.getLogger(KeyPairsUtils.class); + + + public static final String ALGORITHM = "RSA"; //使用RSA算法 + + private static final Integer SIZE = 1024; //初始化的长度 + + + public static final String RSA_FILE_PRIVATE = "D:/RAS/private.txt"; + public static final String RSA_FILE_PUBLIC = "D:/RAS/public.txt"; + + /** + * 产生私匙 和 公匙 对 + */ + private static void getSecrity() { + + try { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM); + + kpg.initialize(SIZE, new SecureRandom()); + + //得到 私匙 和公匙 + RSAPrivateKey privateKey = (RSAPrivateKey) kpg.generateKeyPair().getPrivate(); + RSAPublicKey publicKey = (RSAPublicKey) kpg.generateKeyPair().getPublic(); + + //使用Base64 将 公匙 和私匙 进行处理 + String strPrivateKey = Base64Utils.encodeToString(privateKey.getEncoded()); + String strPublicKey = Base64Utils.encodeToString(publicKey.getEncoded()); + + writeToFile(strPrivateKey, RSA_FILE_PRIVATE); + writeToFile(strPublicKey,RSA_FILE_PUBLIC ); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + LOGGER.info("**************未找到指定的算法的异常*******"); + } + + + } + + /** + * 将私匙和公匙写入到指定的文件中 + * + * @param strPrivateKey :私匙或者公匙 + * @param rsaFilePrivate :文件的名称 + */ + private static void writeToFile(String strPrivateKey, String rsaFilePrivate) { + + if(StringUtils.isBlank(strPrivateKey) || StringUtils.isBlank(rsaFilePrivate)){ + Assert.notNull(strPrivateKey,"参数不能为空" ); + Assert.notNull(rsaFilePrivate,"参数不能为空" ); + } + + BufferedWriter bw = null; + FileWriter writer = null; + try { + writer = new FileWriter(rsaFilePrivate); + bw = new BufferedWriter(writer); + bw.write(strPrivateKey); + + bw.flush(); + LOGGER.info("****************写入成功********************"); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.info("***************写入文件失败******************"); + } finally { + IOUtils.closeQuietly(bw); + IOUtils.closeQuietly(writer); + } + } + + + public static void main(String[] args) { + getSecrity(); + } + +} diff --git a/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyUtils.java b/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyUtils.java new file mode 100644 index 0000000..55d7178 --- /dev/null +++ b/test-eureka-web/src/main/java/com/test/eureka/web/utils/KeyUtils.java @@ -0,0 +1,212 @@ +package com.test.eureka.web.utils; + +import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.*; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/20 15:16 + * Version: V1.0 + * Description: 获取公匙 和 私匙的一些列操作 + * 先从文件中获取到私匙 + * 在使用base64 还原成 原本的私匙或者公匙 + * ====================== + */ +public class KeyUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(KeyUtils.class); + + /** + * 从指定的文件中获取读取数据 + * + * @param rsaFilePrivate :文件的路径 + */ + private static String getKeyFromFile(String rsaFilePrivate) { + + if (StringUtils.isBlank(rsaFilePrivate)) { + Assert.notNull(rsaFilePrivate, "文件路径不能为空"); + } + + FileReader reader = null; + BufferedReader br = null; + try { + reader = new FileReader(rsaFilePrivate); + br = new BufferedReader(reader); + return br.readLine(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + LOGGER.info("************读取文件失败**********************"); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.info("************从文件中获取数据失败********************"); + } finally { + IOUtils.closeQuietly(br); + IOUtils.closeQuietly(reader); + } + return null; + } + + /** + * 通过从文件冲获取到的字符串 通过64工具进行 encoder + * + * @param keyFromFile :从文件中获取到的 key 字符串 + * @param num 509 或者 8 + */ + private static Key encoderByBase64(String keyFromFile, int num) { + Assert.notNull(keyFromFile, "key DON'T NULL"); + + try { + KeyFactory keyFactory = KeyFactory.getInstance(KeyPairsUtils.ALGORITHM); + if (num == 8) { + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(keyFromFile)); + return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); + } else if (num == 509) { + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Utils.decodeFromString(keyFromFile)); + return (RSAPublicKey) keyFactory.generatePublic(keySpec); + } else { + Assert.isTrue(true, "参数有误"); + } + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + LOGGER.info("***************无法找到对应的算法*************"); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + LOGGER.info("获取公匙或者私匙的时候 规则有误"); + } + return null; + } + + + /** + * 使用私匙加密 + * + * @param privateKey 私匙 + * 如果有大段的文字 需要进行 分段加密 + * @param text + */ + private static String privateEncrypt(RSAPrivateKey privateKey, String text) { + + try { + Cipher cipher = Cipher.getInstance(KeyPairsUtils.ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, privateKey, new SecureRandom()); + //优化 加密时 分段加密 当明文长度超过 密文的长度时 + return Base64Utils.encodeToString(spiltencript(cipher,Cipher.ENCRYPT_MODE ,text.getBytes() ,privateKey.getModulus().bitLength() )); + + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + e.printStackTrace(); + LOGGER.info("*********创建加密对象时 出现异常 NoSuchAlgorithmException | NoSuchPaddingException**********"); + } catch (InvalidKeyException e) { + e.printStackTrace(); + LOGGER.info("***********加密时出现异常 InvalidKeyException****************"); + } + return null; + } + + /** + * private static Object getPublicKey(String publicKeyFromFile) { + * } + *

+ * /** + * 使用公匙解密 + * + * @param publicKey :公匙解密 + * @param data + */ + private static String publicKeyUnEncrypt(RSAPublicKey publicKey, String data) { + try { + Cipher cipher = Cipher.getInstance(KeyPairsUtils.ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + //解密时 分段解密 + byte[] bytes = spiltencript(cipher, Cipher.DECRYPT_MODE, data.getBytes(), publicKey.getModulus().bitLength()); + return new String(Base64Utils.decode(bytes)); + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { + e.printStackTrace(); + LOGGER.info("****************使用公匙进行解密时出现异常****************"); + } + return null; + } + + /** + * javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes + * 针对以上 长度大于128位的问题 要采取分段加密的方法 + * + * @param cipher :加密对象 + * @param decryptMode :Cipher.DECRYPT_MODE 或者 Cipher.ENCRYPT_MODE + * @param bytes :加密或者解密的数据 + * @param keyModelsSize :获取到的公匙或者私匙的模数 + * @return :返回分段后组成的数组 + */ + private static byte[] spiltencript(Cipher cipher, int decryptMode, byte[] bytes, int keyModelsSize) { + int maxBlock = 0; //一个阈值 + //根据 decryptMode 判断是 加密还是解密 + if (decryptMode == Cipher.DECRYPT_MODE) { + maxBlock = keyModelsSize / 8; //解密的时候 要求密文长度不超过128字节 + } else { + maxBlock = keyModelsSize / 8 - 11; // 加密的时候 要求不超过117字节 + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try { + int offset = 0; + byte[] buff; + int num = 0; //作为标记 + int length = bytes.length; + while (length > offset) { + if (length - offset > maxBlock) { + buff = cipher.doFinal(bytes, offset, maxBlock); + } else { + buff = cipher.doFinal(bytes, offset, length - offset); + } + outputStream.write(buff, 0, buff.length); + num++; + offset = num * maxBlock; + } + byte[] array = outputStream.toByteArray(); + IOUtils.closeQuietly(outputStream); + return array; + + } catch (IllegalBlockSizeException | BadPaddingException e) { + e.printStackTrace(); + } + return null; + } + + + public static void main(String[] args) { + /* String text = "铭文"; + String keyFromFile = getKeyFromFile(KeyPairsUtils.RSA_FILE_PRIVATE); + LOGGER.debug("私匙:"+keyFromFile); + RSAPrivateKey privateKey = (RSAPrivateKey) encoderByBase64(keyFromFile,8); + //使用私匙进行加密 + System.out.println("加密以后的内容:"+privateEncrypt(privateKey,text));*/ + //相同的铭文 加密以后 不相同 + + //加密以后的内容 + String data = "QbyS/cPCQxu2njNN2oVP8JBluVdrkrlC/rXvP+mhtn/YQfp2JpDzldepdEDpyFG/A/ht5qKg4KzZHuR4aH9sYssCOuAgRg1vfIWLT5zuDz0kfD13k11xiRP5C5BGvANWCVntBXcBzw4eZ0fS/eSk1ExGfpMKMN56tf56/nAO8NM="; + //获取公匙 + String publicKeyFromFile = getKeyFromFile(KeyPairsUtils.RSA_FILE_PUBLIC); + RSAPublicKey publicKey = (RSAPublicKey) encoderByBase64(publicKeyFromFile, 509); + System.out.println("解密以后的内容:" + publicKeyUnEncrypt(publicKey, data)); + + } + + +} diff --git a/test-eureka-web/src/main/resources/static/login.html b/test-eureka-web/src/main/resources/static/login.html new file mode 100644 index 0000000..90fef75 --- /dev/null +++ b/test-eureka-web/src/main/resources/static/login.html @@ -0,0 +1,40 @@ + + + + + 登录页面 + + + + + +

+
+ 用户名: + 密码: +
+ +
+ + \ No newline at end of file diff --git a/test-eureka-web/src/test/java/Alograthm.java b/test-eureka-web/src/test/java/Alograthm.java new file mode 100644 index 0000000..8c76525 --- /dev/null +++ b/test-eureka-web/src/test/java/Alograthm.java @@ -0,0 +1,54 @@ +import java.util.Arrays; +import java.util.Collection; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/2 12:26 + * Version: V1.0 + * Description:排序 算法 + * ====================== + */ +public class Alograthm { + + /** + * 插入排序 + * + * + * 先指定选取任意一个元素作为起始排好的序列 -- 称为哨兵 可以使用第一个元素 作为 哨兵 进行比较 + * 其余的元素再分别 与 排好的 元素 进行比较 插入 指定的位置 + */ + public static int[] insertionSort(int[] arr){ + + //获取数组中的每一个元素 + for(int i=0 ; i0 && element org.springframework.boot spring-boot-starter-web + + + + + + + org.apache.tomcat + tomcat-servlet-api + 9.0.4 org.springframework.cloud @@ -117,6 +131,31 @@ + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.test.spring.cloud.eureka.server.EurkServerApplication + true + + + + + org.apache.maven.plugins diff --git a/test-eurk-server-cluster-master/src/main/java/com/test/spring/cloud/eureka/server/EurkServerApplication.java b/test-eurk-server-cluster-master/src/main/java/com/test/spring/cloud/eureka/server/EurkServerApplication.java index 6ae3701..11354c1 100644 --- a/test-eurk-server-cluster-master/src/main/java/com/test/spring/cloud/eureka/server/EurkServerApplication.java +++ b/test-eurk-server-cluster-master/src/main/java/com/test/spring/cloud/eureka/server/EurkServerApplication.java @@ -2,6 +2,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** @@ -15,12 +16,16 @@ */ @EnableEurekaServer @SpringBootApplication -public class EurkServerApplication +public class EurkServerApplication extends SpringBootServletInitializer { + /*@Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(EurkServerApplication.class); + }*/ + public static void main(String[] args) { new SpringApplicationBuilder(EurkServerApplication.class).web(true).run(args); } - } diff --git a/test-netty/pom.xml b/test-netty/pom.xml new file mode 100644 index 0000000..66613dc --- /dev/null +++ b/test-netty/pom.xml @@ -0,0 +1,38 @@ + + + + wsd + com.springboot.test + 1.0-SNAPSHOT + + 4.0.0 + + test-netty + netty + + + + org.springframework.boot + spring-boot-starter-web + + + + + + io.netty + netty-all + 4.1.21.Final + + + + + org.apache.commons + commons-lang3 + 3.7 + + + + + \ No newline at end of file diff --git a/test-netty/src/main/java/com/test/netty/NettyApplication.java b/test-netty/src/main/java/com/test/netty/NettyApplication.java new file mode 100644 index 0000000..a24c35d --- /dev/null +++ b/test-netty/src/main/java/com/test/netty/NettyApplication.java @@ -0,0 +1,22 @@ +package com.test.netty; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +/** + * ====================== + * Created By User: RXK + * Date: 2018/3/28 13:53 + * Version: V1.0 + * Description: 启动配置类 + * ====================== + */ +@SpringBootApplication +public class NettyApplication { + + public static void main(String[] args){ + new SpringApplicationBuilder().sources(NettyApplication.class).web(true).run(args); + } + + +} diff --git a/test-netty/src/main/resources/application.yml b/test-netty/src/main/resources/application.yml new file mode 100644 index 0000000..30815e9 --- /dev/null +++ b/test-netty/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 9333 \ No newline at end of file