Jelajahi Sumber

Merge branch 'master' into release-2.8.0

JustryDeng 3 tahun lalu
induk
melakukan
9dc1a748f0
30 mengubah file dengan 592 tambahan dan 166 penghapusan
  1. 58 26
      README.md
  2. 1 1
      class-winter-core/pom.xml
  3. 2 2
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Forward.java
  4. 59 36
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Reverses.java
  5. 24 19
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/DecryptExecutor.java
  6. 106 30
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/EncryptExecutor.java
  7. 10 4
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Cache.java
  8. 21 0
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Constant.java
  9. 104 0
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/EncryptClassArgs.java
  10. 73 16
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JavassistUtil.java
  11. 14 0
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/StrUtil.java
  12. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AllTest.java
  13. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AlreadyProtectedLibs_Test.java
  14. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Debug_Test.java
  15. 88 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/EncryptArgParam_Test.java
  16. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ExcludePrefix_Test.java
  17. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/FinalName_Test.java
  18. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludeLibs_Test.java
  19. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludePrefix_Test.java
  20. 3 3
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/JvmArgCheck_Test.java
  21. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/OriginJarOrWar_Test.java
  22. 3 3
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Password_Test.java
  23. 2 2
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/SupportFile_Test.java
  24. 3 3
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Tips_Test.java
  25. 5 5
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/War_Test.java
  26. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Xml_Test.java
  27. TEMPAT SAMPAH
      class-winter-core/src/test/resources/class-winter-core-2.8.0.jar
  28. TEMPAT SAMPAH
      class-winter-core/src/test/resources/class-winter-core-enhance-2.8.0.jar
  29. 1 1
      class-winter-maven-plugin/pom.xml
  30. 1 1
      pom.xml

+ 58 - 26
README.md

@@ -52,7 +52,7 @@
   <plugin>
   <plugin>
       <groupId>com.idea-aedi</groupId>
       <groupId>com.idea-aedi</groupId>
       <artifactId>class-winter-maven-plugin</artifactId>
       <artifactId>class-winter-maven-plugin</artifactId>
-      <version>2.7.9</version>
+      <version>2.8.0</version>
       <!-- 相关配置 -->
       <!-- 相关配置 -->
       <configuration>
       <configuration>
           <!-- <finalName></finalName>-->
           <!-- <finalName></finalName>-->
@@ -83,15 +83,15 @@
   ```
   ```
   注:不必担心信息泄漏问题,使用此方式生成混淆的jar包时,会擦除pom.xml中关于class-winter-plugin的信息。
   注:不必担心信息泄漏问题,使用此方式生成混淆的jar包时,会擦除pom.xml中关于class-winter-plugin的信息。
   
   
-- #### <font face="幼圆" ><font face="幼圆"  color = "#86CA5E">**方式二**</font>:通过 [**class-winter-core.jar**](https://gitee.com/JustryDeng/class-winter/raw/master/class-winter-core/src/test/resources/class-winter-core-2.7.9.jar) 主动加密</font>
+- #### <font face="幼圆" ><font face="幼圆"  color = "#86CA5E">**方式二**</font>:通过 [**class-winter-core.jar**](https://gitee.com/JustryDeng/class-winter/raw/master/class-winter-core/src/test/resources/class-winter-core-2.8.0.jar) 主动加密</font>
 
 
   ```bash
   ```bash
-  java -jar class-winter-core-2.7.9.jar originJarOrWar=${要加密的项目.jar或.war包} includePrefix=${加密范围} [k3=v3 k4=v4 ...]
+  java -jar class-winter-core-2.8.0.jar originJarOrWar=${要加密的项目.jar或.war包} includePrefix=${加密范围} [k3=v3 k4=v4 ...]
   # 对于复杂的参数值,可以使用引号引起来
   # 对于复杂的参数值,可以使用引号引起来
   # linux
   # linux
-  java -jar class-winter-core-2.7.9.jar k1='v1' k2='v2'
+  java -jar class-winter-core-2.8.0.jar k1='v1' k2='v2'
   # windows
   # windows
-  java -jar class-winter-core-2.7.9.jar k1="v1" k2="v2"
+  java -jar class-winter-core-2.8.0.jar k1="v1" k2="v2"
   ```
   ```
 
 
 ## <font  face="幼圆" color = "#3399EA" >加密参数</font>
 ## <font  face="幼圆" color = "#3399EA" >加密参数</font>
@@ -120,6 +120,24 @@
     <td>includePrefix=com
     <td>includePrefix=com
     <br/>
     <br/>
 includePrefix=com,org</td>
 includePrefix=com,org</td>
+  </tr>
+ <tr align="center">
+    <td>cca(依托于includePrefix)</td>
+    <td>否</td>
+    <td>作为includePrefix的附加设置,设置是否清空类上的注释(写法同url后面设置参数)</td>
+    <td>includePrefix=com?cca=true</td>
+  </tr>
+ <tr align="center">
+    <td>cma(依托于includePrefix)</td>
+    <td>否</td>
+    <td>作为includePrefix的附加设置,设置是否清空方法上的注释(写法同url后面设置参数)</td>
+    <td>includePrefix=com?cca=true&cma=true</td>
+  </tr>
+ <tr align="center">
+    <td>cfa(依托于includePrefix)</td>
+    <td>否</td>
+    <td>作为includePrefix的附加设置,设置是否清空字段上的注释(写法同url后面设置参数)</td>
+    <td>includePrefix=com?cca=true&cma=true&cfa=true</td>
   </tr>
   </tr>
     <tr align="center">
     <tr align="center">
     <td>excludePrefix</td>
     <td>excludePrefix</td>
@@ -270,6 +288,7 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
 
 
 
 
 
 
+
 ## <font  face="幼圆" color = "#3399EA" >解密(启动)</font>
 ## <font  face="幼圆" color = "#3399EA" >解密(启动)</font>
 
 
 通过-javaagent指定代理进行解密启动。
 通过-javaagent指定代理进行解密启动。
@@ -277,8 +296,8 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
   ```bash
   ```bash
   # 假设your-project-encrypted.jar是由class-winter加密后的包,那么你可以这么启动
   # 假设your-project-encrypted.jar是由class-winter加密后的包,那么你可以这么启动
   java -javaagent:/your-project-encrypted.jar -jar /your-project-encrypted.jar
   java -javaagent:/your-project-encrypted.jar -jar /your-project-encrypted.jar
-  # 也可以用class-winter-core-2.7.9.jar
-  # java -javaagent:/class-winter-core-2.7.9.jar -jar /your-project-encrypted.jar
+  # 也可以用class-winter-core-2.8.0.jar
+  # java -javaagent:/class-winter-core-2.8.0.jar -jar /your-project-encrypted.jar
   # 或者指定参数
   # 或者指定参数
   # java -javaagent:/your-project-encrypted.jar=debug=true,password=pwd12345 -jar /your-project-encrypted.jar
   # java -javaagent:/your-project-encrypted.jar=debug=true,password=pwd12345 -jar /your-project-encrypted.jar
   # 参数可以引起来(linux)
   # 参数可以引起来(linux)
@@ -294,39 +313,43 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
     编辑tomcat/bin/catalina.sh文件,在最上面加上
     编辑tomcat/bin/catalina.sh文件,在最上面加上
 
 
     ```bash
     ```bash
-    # 如果你有参数, 那么 -javaagent:/class-winter-core-2.7.9.jar=k1=v1,k2=v2
-    CATALINA_OPTS="$CATALINA_OPTS -javaagent:/class-winter-core-2.7.9.jar=debug=true";
+    # 如果你有参数, 那么 -javaagent:/class-winter-core-2.8.0.jar=k1=v1,k2=v2
+    # tomcat启动往往需要通过decryptProjectPathPrefix指定要解密的路径
+    CATALINA_OPTS="$CATALINA_OPTS -javaagent:/class-winter-core-2.8.0.jar=debug=true,decryptProjectPathPrefix=/usr/local/xxx/";
     export CATALINA_OPTS;
     export CATALINA_OPTS;
     ```
     ```
-
+  
   - linux方式二
   - linux方式二
-
+  
     在tomcat/bin目录下创建setenv.sh文件,并写上
     在tomcat/bin目录下创建setenv.sh文件,并写上
-
+  
     ```bash
     ```bash
-    # 如果你有参数, 那么 -javaagent:/class-winter-core-2.7.9.jar=k1=v1,k2=v2
-    JAVA_OPTS="$JAVA_OPTS -javaagent:/class-winter-core-2.7.9.jar=debug=true";
+    # 如果你有参数, 那么 -javaagent:/class-winter-core-2.8.0.jar=k1=v1,k2=v2
+    # tomcat启动往往需要通过decryptProjectPathPrefix指定要解密的路径
+    JAVA_OPTS="$JAVA_OPTS -javaagent:/class-winter-core-2.8.0.jar=debug=true,decryptProjectPathPrefix=/usr/local/xxx/";
     export JAVA_OPTS;
     export JAVA_OPTS;
     ```
     ```
 
 
   - windows方式一
   - windows方式一
 
 
     编辑tomcat/bin/catalina.bat文件,在@echo off后加上catalina参数
     编辑tomcat/bin/catalina.bat文件,在@echo off后加上catalina参数
-
+  
     ```bash
     ```bash
-    rem 如果你有参数, 那么 -javaagent:D:/class-winter-core-2.7.9.jar=k1=v1,k2=v2
-    set CATALINA_OPTS="-javaagent:D:/class-winter-core-2.7.9.jar"
+    rem 如果你有参数, 那么 -javaagent:D:/class-winter-core-2.8.0.jar=k1=v1,k2=v2
+    rem tomcat启动往往需要通过decryptProjectPathPrefix指定要解密的路径
+    set CATALINA_OPTS="-javaagent:D:/class-winter-core-2.8.0.jar=decryptProjectPathPrefix=/D:/tmp/"
     ```
     ```
-
+  
   - windows方式二
   - windows方式二
-
+  
     在tomcat/bin目录下创建setenv.bat文件,并写上
     在tomcat/bin目录下创建setenv.bat文件,并写上
-
+  
     ```bash
     ```bash
-    rem 如果你有参数, 那么 -javaagent:D:/class-winter-core-2.7.9.jar=k1=v1,k2=v2
-    set JAVA_OPTS="-javaagent:D:/class-winter-core-2.7.9.jar"
+    rem 如果你有参数, 那么 -javaagent:D:/class-winter-core-2.8.0.jar=k1=v1,k2=v2
+    rem tomcat启动往往需要通过decryptProjectPathPrefix指定要解密的路径
+    set JAVA_OPTS="-javaagent:D:/class-winter-core-2.8.0.jar=decryptProjectPathPrefix=/D:/tmp/"
     ```
     ```
-
+  
 - #### <font  face="幼圆" color = "#86CA5E" >IDE解密(启动)</font>
 - #### <font  face="幼圆" color = "#86CA5E" >IDE解密(启动)</font>
 
 
   > 设置`-javaagent`参数指定class-winter-core或者任一加密包。有必要的话,再搭配`skipProjectPathPrefix`或者`decryptProjectPathPrefix`参数启动即可
   > 设置`-javaagent`参数指定class-winter-core或者任一加密包。有必要的话,再搭配`skipProjectPathPrefix`或者`decryptProjectPathPrefix`参数启动即可
@@ -365,7 +388,7 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
     <tr align="center">
     <tr align="center">
     <td>skipProjectPathPrefix</td>
     <td>skipProjectPathPrefix</td>
     <td>否</td>
     <td>否</td>
-    <td>是否跳过指定前缀的项目路径(当class-winter解密逻辑试图解析那些进入premain但是非class-winter加密项目时,会因为获取印章失败Obtain project seal fail而停止,此时如果确认这个项目没有加密文件的话,可以使用此参数跳过)<br/>注:不知道此值怎么填的,可以把debug代开, 观察日志 Exist projectPath -> xxx 或输出所有的projectPath <br/>注:此参数由2.6.4版本开始支持</td>
+    <td>是否跳过指定前缀的项目路径(当class-winter解密逻辑试图解析那些进入premain但是非class-winter加密项目时,会因为获取印章失败Obtain project seal fail而停止,此时如果确认这个项目没有加密文件的话,可以使用此参数跳过)<br/>注:值中的路径分隔符请统一使用/ <br/>注:不知道此值怎么填的,可以把debug代开, 观察日志 Exist projectPath -> xxx 或输出所有的projectPath <br/>注:此参数由2.6.4版本开始支持</td>
     <td>
     <td>
         skipProjectPathPrefix=/D:/apache-tomcat-9.0.71/bin/
         skipProjectPathPrefix=/D:/apache-tomcat-9.0.71/bin/
         <br/>
         <br/>
@@ -375,7 +398,7 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
     <tr align="center">
     <tr align="center">
     <td>decryptProjectPathPrefix</td>
     <td>decryptProjectPathPrefix</td>
     <td>否</td>
     <td>否</td>
-    <td>是否仅解密指定前缀的项目路径(优先级低于skipProjectPathPrefix)<br/>注:不知道此值怎么填的,可以把debug代开, 观察日志 Exist projectPath -> xxx 或输出所有的projectPath <br/>注:此参数由2.6.6版本开始支持</td>
+    <td>是否仅解密指定前缀的项目路径(优先级低于skipProjectPathPrefix)<br/>注:值中的路径分隔符请统一使用/ <br/>注:不知道此值怎么填的,可以把debug代开, 观察日志 Exist projectPath -> xxx 或输出所有的projectPath <br/>注:此参数由2.6.6版本开始支持</td>
     <td>
     <td>
         decryptProjectPathPrefix=/D:/apache-tomcat-9.0.71/bin/
         decryptProjectPathPrefix=/D:/apache-tomcat-9.0.71/bin/
         <br/>
         <br/>
@@ -435,7 +458,7 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
       <parent>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <artifactId>spring-boot-starter-parent</artifactId>
-          <version>2.7.9</version>
+          <version>2.8.0</version>
           <relativePath/> <!-- lookup parent from repository -->
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       </parent>
       <groupId>com.example</groupId>
       <groupId>com.example</groupId>
@@ -541,6 +564,15 @@ linux示例:tips='请不要直接使用混淆后的jar/war'</td>
 
 
 
 
 
 
+## 功能扩展案例
+
+> 感谢以下小伙伴们的优秀扩展案例
+
+| 序号   | 扩展功能   | 作者                                                         | 仓库地址                                                    |
+| ------ | ---------- | ------------------------------------------------------------ | ----------------------------------------------------------- |
+| 1      | 机器码支持 | qq号:`85546017`<br /><br />当前(2023-06-11)状态:<br />&emsp;qq名:`╮(╯_╰)╭`<br />&emsp;是否在class-winter QQ群:是 | [点击跳转](https://gitee.com/tts2/class-winter/tree/master) |
+| ...... | ......     | ......                                                       | ......                                                      |
+
 ## QQ群
 ## QQ群
 
 
 > 群号:727930548
 > 群号:727930548

+ 1 - 1
class-winter-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
     <parent>
         <groupId>com.idea-aedi</groupId>
         <groupId>com.idea-aedi</groupId>
         <artifactId>class-winter</artifactId>
         <artifactId>class-winter</artifactId>
-        <version>2.7.9</version>
+        <version>2.8.0</version>
     </parent>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
 
 

+ 2 - 2
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Forward.java

@@ -24,8 +24,8 @@ public class Forward {
     public static void main(String[] args) {
     public static void main(String[] args) {
         /// main test
         /// main test
         ///args =new String[]{
         ///args =new String[]{
-        ///        "originJarOrWar=C:/Users/Administrator/Desktop/test.war",
-        ///        "includePrefix=com.ideaaedi.test"
+        ///        "originJarOrWar=D:/working/class-winter/class-winter-core/target/test-classes/boot-jar-encrypted.jar",
+        ///        "includePrefix=com?cca=true&cma=true&koa=false&cfa=true,com.ideaaedi,com.ideaaedi.demo"
         ///};
         ///};
         // 解析参数
         // 解析参数
         String originJarOrWar = parseValueByPrefixFromTail("originJarOrWar=", args);
         String originJarOrWar = parseValueByPrefixFromTail("originJarOrWar=", args);

+ 59 - 36
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Reverses.java

@@ -120,8 +120,8 @@ public class Reverses {
                     try {
                     try {
                         projectPath = JarUtil.getRootPath(projectPath);
                         projectPath = JarUtil.getRootPath(projectPath);
                     } catch (ClassWinterException e) {
                     } catch (ClassWinterException e) {
-                        // 如果没有指定解密该projectPath,那么返回
-                        if (!ifPointToDecrypt(decryptProjectPathPrefixSet, projectPath)) {
+                        // 如果不需要试着解密该projectPath,那么返回
+                        if (notPointToDecrypt(projectPath, decryptProjectPathPrefixSet)) {
                             return classfileBuffer;
                             return classfileBuffer;
                         }
                         }
                     } catch (Exception e) {
                     } catch (Exception e) {
@@ -141,37 +141,16 @@ public class Reverses {
                             return classfileBuffer;
                             return classfileBuffer;
                         }
                         }
                     }
                     }
-                    if (decryptProjectPathPrefixSet.size() > 0) {
-                        if (!ifPointToDecrypt(decryptProjectPathPrefixSet, projectPath)) {
+                    boolean settingDecryptProjectPath = decryptProjectPathPrefixSet.size() > 0;
+                    if (settingDecryptProjectPath) {
+                        if (notPointToDecrypt(projectPath, decryptProjectPathPrefixSet)) {
                             return classfileBuffer;
                             return classfileBuffer;
                         }
                         }
                     }
                     }
                     className = className.replace("/", ".").replace("\\", ".");
                     className = className.replace("/", ".").replace("\\", ".");
-                    // 本项目的印章
-                    if (Cache.sealCache == null) {
-                        try {
-                            byte[] sealByte = IOUtil.readFileFromWorkbenchRoot(new File(projectPath), Constant.SEAL_FILE);
-                            if (sealByte == null) {
-                                Logger.error(Reverses.class, "Obtain project seal fail. "
-                                        + "Maybe you need to try it with decrypt params 'decryptProjectPathPrefix' or 'skipProjectPathPrefix'. "
-                                        + "@see https://gitee.com/JustryDeng/class-winter#%E8%A7%A3%E5%AF%86%E5%8F%82%E6%95%B0 ");
-                                // 结束程序
-                                exit(projectPath);
-                            }
-                            String sealContent = new String(sealByte, StandardCharsets.UTF_8);
-                            Logger.debug(Reverses.class, "seal of the project is -> " + sealContent);
-                            Cache.sealCache = sealContent;
-                        } catch (Exception e) {
-                            Logger.error(Reverses.class, "Obtain project seal fail.");
-                            Logger.error(Reverses.class, ExceptionUtil.getStackTraceMessage(e));
-                            exit(projectPath);
-                            for (int i = 0; i < Constant.TEN; i++) {
-                                Logger.error(Reverses.class, "!!!!!!!!!!! class-winter Invalidation. !!!!!!!!!!!");
-                            }
-                            return null;
-                        }
-                    }
-                    
+                    // 抽取印章
+                    extractSeal(projectPath, settingDecryptProjectPath);
+    
                     /// ============================================ 1.校验启动时是否输入了加密时指定的jvm参数   2.处理non-class文件
                     /// ============================================ 1.校验启动时是否输入了加密时指定的jvm参数   2.处理non-class文件
                     final String inputPwd = javaagentCmdArgs.getPassword();
                     final String inputPwd = javaagentCmdArgs.getPassword();
                     if (firstExec.compareAndSet(false, true)) {
                     if (firstExec.compareAndSet(false, true)) {
@@ -251,7 +230,7 @@ public class Reverses {
                     
                     
                     /// ============================================ 处理class文件
                     /// ============================================ 处理class文件
                     // 判断是否应该解密
                     // 判断是否应该解密
-                    if (DecryptExecutor.checklistContain(projectPath, className) && DecryptExecutor.verifySeal(classfileBuffer)) {
+                    if (DecryptExecutor.checklistContain(projectPath, className) && DecryptExecutor.verifySeal(projectPath, classfileBuffer)) {
                         //noinspection DuplicatedCode
                         //noinspection DuplicatedCode
                         try {
                         try {
                             Logger.debug(Reverses.class, "Decrypt class[" + className + "] start.");
                             Logger.debug(Reverses.class, "Decrypt class[" + className + "] start.");
@@ -304,17 +283,61 @@ public class Reverses {
     }
     }
     
     
     /**
     /**
-     * 是否指定了要试着解密projectPath指向的代码
+     * 抽取项目印章
+     *
+     * @param settingDecryptProjectPath 是否指定了项目解密路径前缀
+     */
+    private static void extractSeal(String projectPath, boolean settingDecryptProjectPath) {
+        if (Cache.sealCache.containsKey(projectPath)) {
+            return;
+        }
+        try {
+            byte[] sealByte = IOUtil.readFileFromWorkbenchRoot(new File(projectPath), Constant.SEAL_FILE);
+            String sealContent = null;
+            if (sealByte == null) {
+                // 在没有指定解密路径的情况下,没有获取到印章的话,那么获取第一个印章作为本projectPath的印章
+                if (!settingDecryptProjectPath && Cache.firstSealCache != null) {
+                    sealContent = Cache.firstSealCache;
+                    Logger.debug(Reverses.class, "Use first-seal as curr project seal.");
+                }
+            } else {
+                sealContent = new String(sealByte, StandardCharsets.UTF_8);
+                Logger.debug(Reverses.class, "direct-seal of the project is -> " + sealContent);
+            }
+            if (sealContent == null) {
+                Logger.error(Reverses.class, "Obtain project seal fail.");
+                // 结束程序
+                exit(projectPath);
+            }
+            Cache.sealCache.put(projectPath, sealContent);
+            if (Cache.firstSealCache == null) {
+                Cache.firstSealCache = sealContent;
+                Cache.firstSealProjectPath = projectPath;
+                Logger.debug(Reverses.class, "first-seal found. projectPath -> " + Cache.firstSealProjectPath);
+                Logger.debug(Reverses.class, "first-seal found. sealContent -> " + Cache.firstSealCache);
+            }
+        } catch (Exception e) {
+            Logger.error(Reverses.class, "Obtain project seal fail.");
+            Logger.error(Reverses.class, ExceptionUtil.getStackTraceMessage(e));
+            exit(projectPath);
+            for (int i = 0; i < Constant.TEN; i++) {
+                Logger.error(Reverses.class, "!!!!!!!!!!! class-winter Invalidation. !!!!!!!!!!!");
+            }
+        }
+    }
+    
+    /**
+     * 是否不需要试着解密projectPath指向的代码
      */
      */
-    private static boolean ifPointToDecrypt(Set<String> decryptProjectPathPrefixSet, String projectPath) {
-        boolean needTryDecrypt = false;
+    private static boolean notPointToDecrypt(String projectPath, Set<String> decryptProjectPathPrefixSet) {
+        boolean notNeedTryDecrypt = true;
         for (String decryptProjectPathPrefix : decryptProjectPathPrefixSet) {
         for (String decryptProjectPathPrefix : decryptProjectPathPrefixSet) {
             if (projectPath != null && projectPath.startsWith(decryptProjectPathPrefix)) {
             if (projectPath != null && projectPath.startsWith(decryptProjectPathPrefix)) {
-                needTryDecrypt = true;
+                notNeedTryDecrypt = false;
                 break;
                 break;
             }
             }
         }
         }
-        return needTryDecrypt;
+        return notNeedTryDecrypt;
     }
     }
     
     
     /**
     /**
@@ -326,7 +349,7 @@ public class Reverses {
                 Logger.error(Reverses.class, "Curr projectPath is -> " + projectPath);
                 Logger.error(Reverses.class, "Curr projectPath is -> " + projectPath);
             }
             }
             TimeUnit.SECONDS.sleep(10);
             TimeUnit.SECONDS.sleep(10);
-        } catch (InterruptedException interruptedException) {
+        } catch (InterruptedException ignore) {
         }
         }
         System.exit(-1);
         System.exit(-1);
     }
     }

+ 24 - 19
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/DecryptExecutor.java

@@ -20,6 +20,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 import java.util.zip.ZipFile;
 import java.util.zip.ZipFile;
 
 
@@ -31,14 +32,15 @@ import java.util.zip.ZipFile;
  */
  */
 public class DecryptExecutor {
 public class DecryptExecutor {
     
     
-    /** 要解密的文件清单,记录已加密的class的全类名的清单文件 */
-    private static Set<String> checklist;
+    /** key- projectPath; value-要解密的文件清单,记录已加密的class的全类名的清单文件 */
+    private static final Map<String, Set<String>> checklist = new ConcurrentHashMap<>(8);
     
     
     /**
     /**
-     * 以key-value的形式记录lib中的被混淆的类(key-被混淆的类的无后缀全类名, value-存放采集到的类所在lib的信息的文件夹)
-     *
+     * 以key-value的形式记录lib中的被混淆的类(key-被混淆的类的无后缀全类名, value-存放采集到的类所在lib的信息的文件夹)
+     * <pre>
      * key   - 形如: com.abc.xyz.Qwer
      * key   - 形如: com.abc.xyz.Qwer
      * value - 形如: META-INF/winter/abc-1.0.0_jar/
      * value - 形如: META-INF/winter/abc-1.0.0_jar/
+     * </pre>
      */
      */
     private static Map<String, String> checklistOfAllLibsMap;
     private static Map<String, String> checklistOfAllLibsMap;
 
 
@@ -99,19 +101,20 @@ public class DecryptExecutor {
      * @return classLongName是否在(记录已加密类的)清单列表中
      * @return classLongName是否在(记录已加密类的)清单列表中
      */
      */
     public static boolean checklistContain(String projectPath, String classLongName) {
     public static boolean checklistContain(String projectPath, String classLongName) {
-        if (checklist == null) {
+        // 如果当前projectPath的印章,用的是Cache.firstSealCache的话,那么此方法中获取checklist,也获取Cache.firstSealCache对应的checklist
+        projectPath = Cache.firstSealCache.equals(Cache.sealCache.get(projectPath)) ? Cache.firstSealProjectPath : projectPath;
+        if (!checklist.containsKey(projectPath)) {
             byte[] checklistByte = IOUtil.readFileFromWorkbenchRoot(new File(projectPath),
             byte[] checklistByte = IOUtil.readFileFromWorkbenchRoot(new File(projectPath),
                     Constant.ALREADY_ENCRYPTED_CLASS_CHECKLIST_CLASSES_SAVE_FILE);
                     Constant.ALREADY_ENCRYPTED_CLASS_CHECKLIST_CLASSES_SAVE_FILE);
             if (checklistByte == null) {
             if (checklistByte == null) {
-                checklist = new HashSet<>();
                 Logger.debug(DecryptExecutor.class, "checklistByte is null. ");
                 Logger.debug(DecryptExecutor.class, "checklistByte is null. ");
             } else {
             } else {
                 String checklistContent = new String(checklistByte, StandardCharsets.UTF_8);
                 String checklistContent = new String(checklistByte, StandardCharsets.UTF_8);
                 Logger.debug(DecryptExecutor.class, "checklistContent " + checklistContent);
                 Logger.debug(DecryptExecutor.class, "checklistContent " + checklistContent);
-                checklist = new HashSet<>(Arrays.asList(checklistContent.split(Constant.COMMA)));
+                checklist.put(projectPath, new HashSet<>(Arrays.asList(checklistContent.split(Constant.COMMA))));
             }
             }
         }
         }
-        return checklist.contains(classLongName);
+        return checklist.get(projectPath).contains(classLongName);
     }
     }
     
     
     /**
     /**
@@ -175,12 +178,16 @@ public class DecryptExecutor {
     /**
     /**
      * 判断类classBytes是否被盖章
      * 判断类classBytes是否被盖章
      *
      *
-     * @param classBytes
-     *            类的字节码
+     * @param projectPath 项目路径
+     * @param classBytes 类的字节码
      * @return classBytes中是否存在加密印章
      * @return classBytes中是否存在加密印章
      */
      */
-    public static boolean verifySeal(byte[] classBytes) {
-        return new String(classBytes, StandardCharsets.UTF_8).contains(Cache.sealCache);
+    public static boolean verifySeal(String projectPath, byte[] classBytes) {
+        String seal = Cache.sealCache.get(projectPath);
+        if (StrUtil.isBlank(seal)) {
+            throw new ClassWinterException("seal should not be blank. curr projectPath -> " + projectPath + ". curr sealCache is -> " + Cache.sealCache);
+        }
+        return new String(classBytes, StandardCharsets.UTF_8).contains(seal);
     }
     }
     
     
     /**
     /**
@@ -263,10 +270,8 @@ public class DecryptExecutor {
     /**
     /**
      * 恢复非class文件的混淆
      * 恢复非class文件的混淆
      *
      *
-     * @param zipFilePath
-     *            项目jar/war包路径
-     * @param password
-     *            项目加密密码(可能为null)
+     * @param zipFilePath 项目jar/war包路径
+     * @param password 项目加密密码(可能为null)
      * @return  被替换了的ZipEntry的相对路径及重写前后的内容信息<br/>
      * @return  被替换了的ZipEntry的相对路径及重写前后的内容信息<br/>
      *          k - ZipEntry的相对路径,如:BOOT-INF/classes/application.yml<br/>
      *          k - ZipEntry的相对路径,如:BOOT-INF/classes/application.yml<br/>
      *          v - 左:重写前的内容,右:重写后的内容
      *          v - 左:重写前的内容,右:重写后的内容
@@ -291,7 +296,7 @@ public class DecryptExecutor {
         for (String zipEntryName : needToDecryptNonClassFileSet) {
         for (String zipEntryName : needToDecryptNonClassFileSet) {
             // 只处理有印章的
             // 只处理有印章的
             byte[] cleanedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile, zipEntryName);
             byte[] cleanedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile, zipEntryName);
-            if (DecryptExecutor.verifySeal(cleanedBytes)) {
+            if (DecryptExecutor.verifySeal(zipFilePath, cleanedBytes)) {
                 byte[] encryptedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile,
                 byte[] encryptedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile,
                         Constant.DEFAULT_ENCRYPTED_NON_CLASSES_SAVE_DIR + zipEntryName);
                         Constant.DEFAULT_ENCRYPTED_NON_CLASSES_SAVE_DIR + zipEntryName);
                 byte[] bytes = EncryptUtil.decrypt(encryptedBytes, userIfInputPwdWhileDecrypt ? password :
                 byte[] bytes = EncryptUtil.decrypt(encryptedBytes, userIfInputPwdWhileDecrypt ? password :
@@ -329,7 +334,7 @@ public class DecryptExecutor {
             }
             }
             // 存时,是加密存进去的; 这里读取时,解密一下
             // 存时,是加密存进去的; 这里读取时,解密一下
             passwordByte = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
             passwordByte = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
-                    Cache.sealCache.toCharArray()).getBytes(StandardCharsets.UTF_8);
+                    Cache.sealCache.get(projectPath).toCharArray()).getBytes(StandardCharsets.UTF_8);
             String password = new String(passwordByte, StandardCharsets.UTF_8);
             String password = new String(passwordByte, StandardCharsets.UTF_8);
             char[] passwordCharArr = password.toCharArray();
             char[] passwordCharArr = password.toCharArray();
             // 放入缓存
             // 放入缓存
@@ -348,7 +353,7 @@ public class DecryptExecutor {
             Objects.requireNonNull(passwordByte);
             Objects.requireNonNull(passwordByte);
             // 存时,是加密存进去的; 这里读取时,解密一下
             // 存时,是加密存进去的; 这里读取时,解密一下
             char[] passwordCharArr = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
             char[] passwordCharArr = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
-                    Cache.sealCache.toCharArray()).toCharArray();
+                    Cache.sealCache.get(projectPath).toCharArray()).toCharArray();
             Cache.libPasswordCache.put(classWinterInfoDir, passwordCharArr);
             Cache.libPasswordCache.put(classWinterInfoDir, passwordCharArr);
             return passwordCharArr;
             return passwordCharArr;
         }
         }

+ 106 - 30
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/EncryptExecutor.java

@@ -16,6 +16,7 @@ import winter.com.ideaaedi.classwinter.author.JustryDeng;
 import winter.com.ideaaedi.classwinter.exception.ClassWinterException;
 import winter.com.ideaaedi.classwinter.exception.ClassWinterException;
 import winter.com.ideaaedi.classwinter.util.Cache;
 import winter.com.ideaaedi.classwinter.util.Cache;
 import winter.com.ideaaedi.classwinter.util.Constant;
 import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.EncryptClassArgs;
 import winter.com.ideaaedi.classwinter.util.EncryptUtil;
 import winter.com.ideaaedi.classwinter.util.EncryptUtil;
 import winter.com.ideaaedi.classwinter.util.ExceptionUtil;
 import winter.com.ideaaedi.classwinter.util.ExceptionUtil;
 import winter.com.ideaaedi.classwinter.util.FileOrderSupport;
 import winter.com.ideaaedi.classwinter.util.FileOrderSupport;
@@ -40,11 +41,15 @@ import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.Base64;
 import java.util.Base64;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -81,6 +86,7 @@ public class EncryptExecutor {
         CLASS_WINTER_FILES.add(PathUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(PathUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(SimpleFileOrderSupport.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(SimpleFileOrderSupport.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(StrUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(StrUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
+        CLASS_WINTER_FILES.add(EncryptClassArgs.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(Reverses.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(Reverses.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(Reverses.class.getName().replace(".", "/").replace("Reverses", "Reverses$1") + Constant.CLASS_SUFFIX);
         CLASS_WINTER_FILES.add(Reverses.class.getName().replace(".", "/").replace("Reverses", "Reverses$1") + Constant.CLASS_SUFFIX);
     }
     }
@@ -125,8 +131,10 @@ public class EncryptExecutor {
     
     
     /**
     /**
      * 要加密的类的全类名前缀(也可以精确匹配)
      * 要加密的类的全类名前缀(也可以精确匹配)
+     * <br />
+     * 注:可携带参数, 写法同url后面待参数 url?key1=value1&key2=value2
      */
      */
-    private final Set<String> includePrefixSet;
+    private final LinkedHashSet<String> includePrefixSet;
     
     
     /**
     /**
      * 要加密的lib包(若不指定,则加密筛选范围默认仅从项目代码本身进行筛选加密)。
      * 要加密的lib包(若不指定,则加密筛选范围默认仅从项目代码本身进行筛选加密)。
@@ -164,7 +172,7 @@ public class EncryptExecutor {
      *  在一些外置lib的项目中,可能需要用到此参数;如果是内置lib,忽略此参数即可
      *  在一些外置lib的项目中,可能需要用到此参数;如果是内置lib,忽略此参数即可
      * </pre>
      * </pre>
      */
      */
-    private String alreadyProtectedRootDir;
+    private final String alreadyProtectedRootDir;
     
     
     /**
     /**
      * 已经被class-winter加密过了的lib的信息
      * 已经被class-winter加密过了的lib的信息
@@ -215,7 +223,7 @@ public class EncryptExecutor {
     private EncryptExecutor(String originJarOrWar, boolean originIsJar, String finalName, String targetRootDir,
     private EncryptExecutor(String originJarOrWar, boolean originIsJar, String finalName, String targetRootDir,
                             String targetLibDir, String targetClassesDir, String password,
                             String targetLibDir, String targetClassesDir, String password,
                             Set<String> includeXmlPrefixSet, Set<String> excludeXmlPrefixSet, Set<String> toCleanXmlChildElementNameSet,
                             Set<String> includeXmlPrefixSet, Set<String> excludeXmlPrefixSet, Set<String> toCleanXmlChildElementNameSet,
-                            Set<String> includePrefixSet, Set<String> excludePrefixSet, Set<String> includeLibSet,
+                            LinkedHashSet<String> includePrefixSet, Set<String> excludePrefixSet, Set<String> includeLibSet,
                             String alreadyProtectedRootDir, Set<Pair<String, String>> alreadyProtectedLibSet,
                             String alreadyProtectedRootDir, Set<Pair<String, String>> alreadyProtectedLibSet,
                             String supportFile, Set<String> jvmArgCheckSet) {
                             String supportFile, Set<String> jvmArgCheckSet) {
         this.originJarOrWar = originJarOrWar;
         this.originJarOrWar = originJarOrWar;
@@ -264,12 +272,12 @@ public class EncryptExecutor {
         
         
         // step3. 找到需要加密混淆的class文件
         // step3. 找到需要加密混淆的class文件
         List<File> allFiles = IOUtil.listSubFile(targetRootDirFile, 1);
         List<File> allFiles = IOUtil.listSubFile(targetRootDirFile, 1);
-        List<File> allNeedEncryptedClassFileList = filterClasses(allFiles);
+        List<EncryptClassArgs> allNeedEncryptedClassInfoList = filterClasses(allFiles);
         showProcess("step03", lastStep, "filter-classes");
         showProcess("step03", lastStep, "filter-classes");
         
         
         // step4.1. 根据原.class文件,生成加密后的.class文件,并存至Constant.ENCRYPTED_CLASSES_SAVE_DIR
         // step4.1. 根据原.class文件,生成加密后的.class文件,并存至Constant.ENCRYPTED_CLASSES_SAVE_DIR
-        List<String> allAlreadyEncryptedClassFileList = encryptClasses(allNeedEncryptedClassFileList, new File(targetRootDir,
-                Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR));
+        List<String> allAlreadyEncryptedClassFileList = encryptClasses(allNeedEncryptedClassInfoList,
+                new File(targetRootDir, Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR));
         // step4.2. 生成记录已加密class的全类名的清单文件
         // step4.2. 生成记录已加密class的全类名的清单文件
         generateChecklistFile(allAlreadyEncryptedClassFileList);
         generateChecklistFile(allAlreadyEncryptedClassFileList);
         showProcess("step04", lastStep, "encrypt-classes");
         showProcess("step04", lastStep, "encrypt-classes");
@@ -283,7 +291,7 @@ public class EncryptExecutor {
         showProcess("step06", lastStep, "setting-jvm-arg-check-items");
         showProcess("step06", lastStep, "setting-jvm-arg-check-items");
 
 
         // step7. 混淆原.class文件(即:清空方法体)
         // step7. 混淆原.class文件(即:清空方法体)
-        clearClassMethod(allNeedEncryptedClassFileList);
+        clearClassMethod(allNeedEncryptedClassInfoList);
         showProcess("step07", lastStep, "clear-class-method");
         showProcess("step07", lastStep, "clear-class-method");
     
     
         // step8. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
         // step8. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
@@ -368,6 +376,9 @@ public class EncryptExecutor {
         // 清空原xml文件的关键节点
         // 清空原xml文件的关键节点
         for (String zipEntryName : encryptNonClassFileSet) {
         for (String zipEntryName : encryptNonClassFileSet) {
             byte[] bytes = IOUtil.readFileFromWorkbenchRoot(targetRootDirFile, zipEntryName);
             byte[] bytes = IOUtil.readFileFromWorkbenchRoot(targetRootDirFile, zipEntryName);
+            if (bytes == null) {
+                continue;
+            }
             String cleanedXml = clearXml(new String(bytes, StandardCharsets.UTF_8), "\n\t\t\t" + Constant.TIPS + "\n\t\t\t" + Constant.SEAL, toCleanXmlChildElementNameSet);
             String cleanedXml = clearXml(new String(bytes, StandardCharsets.UTF_8), "\n\t\t\t" + Constant.TIPS + "\n\t\t\t" + Constant.SEAL, toCleanXmlChildElementNameSet);
             IOUtil.writeContentToFile(cleanedXml, new File(targetRootDir, zipEntryName));
             IOUtil.writeContentToFile(cleanedXml, new File(targetRootDir, zipEntryName));
         }
         }
@@ -398,9 +409,7 @@ public class EncryptExecutor {
      *
      *
      * <?xml version="1.0" encoding="UTF-8"?>
      * <?xml version="1.0" encoding="UTF-8"?>
      * <project ...>
      * <project ...>
-     *
      *     ......
      *     ......
-     *
      *     <build>
      *     <build>
      *         <plugins>
      *         <plugins>
      *         	// 要把这部分清除 start
      *         	// 要把这部分清除 start
@@ -757,10 +766,9 @@ public class EncryptExecutor {
     /**
     /**
      * 清空class文件的方法体,并保留参数信息
      * 清空class文件的方法体,并保留参数信息
      *
      *
-     * @param classFiles
-     *            需要清空方法体的class文件
+     * @param allNeedEncryptedClassInfoList 需要加密的class相关参数集合
      */
      */
-    private void clearClassMethod(List<File> classFiles) {
+    private void clearClassMethod(List<EncryptClassArgs> allNeedEncryptedClassInfoList) {
         // step0. 初始化javassist
         // step0. 初始化javassist
         ClassPool pool = ClassPool.getDefault();
         ClassPool pool = ClassPool.getDefault();
         // step1. 把所有可能涉及到的jar、.class添加进加载路径
         // step1. 把所有可能涉及到的jar、.class添加进加载路径
@@ -774,10 +782,11 @@ public class EncryptExecutor {
             throw new ClassWinterException(e);
             throw new ClassWinterException(e);
         }
         }
         // step2. 修改class方法体,并保存文件
         // step2. 修改class方法体,并保存文件
-        classFiles.forEach(classFile -> {
+        allNeedEncryptedClassInfoList.forEach(encryptClassArgs -> {
+            File classFile = encryptClassArgs.getEncryptClassFile();
             String className = JavassistUtil.resolveClassName(classFile.getAbsolutePath(), true);
             String className = JavassistUtil.resolveClassName(classFile.getAbsolutePath(), true);
             try {
             try {
-                byte[] bts = JavassistUtil.clearMethodBody(pool, className, true);
+                byte[] bts = JavassistUtil.clearMethodBody(pool, className, encryptClassArgs);
                 IOUtil.toFile(bts, classFile, true);
                 IOUtil.toFile(bts, classFile, true);
             } catch (NotFoundException e) {
             } catch (NotFoundException e) {
                 // ignore
                 // ignore
@@ -865,13 +874,12 @@ public class EncryptExecutor {
     /**
     /**
      * 加密class文件,并将加密后的class文件放在savaDir里
      * 加密class文件,并将加密后的class文件放在savaDir里
      *
      *
-     * @param classFiles
-     *            需要加密的class文件
-     * @param savaDir
-     *            加密后的class文件的存储目录
+     * @param encryptClassInfoList 需要加密的class相关参数集合
+     * @param savaDir 加密后的class文件的存储目录
      * @return  已经加密了的类的全类名(如: com.aaa.bbb.Abc)
      * @return  已经加密了的类的全类名(如: com.aaa.bbb.Abc)
      */
      */
-    private List<String> encryptClasses(List<File> classFiles, File savaDir) {
+    private List<String> encryptClasses(List<EncryptClassArgs> encryptClassInfoList, File savaDir) {
+        List<File> classFiles = encryptClassInfoList.stream().map(EncryptClassArgs::getEncryptClassFile).collect(Collectors.toList());
         // 保证目录存在
         // 保证目录存在
         JarUtil.guarantyDirExist(savaDir);
         JarUtil.guarantyDirExist(savaDir);
         classFiles.stream().map(File::getName).forEach(name -> {
         classFiles.stream().map(File::getName).forEach(name -> {
@@ -924,35 +932,81 @@ public class EncryptExecutor {
     /**
     /**
      * 找出所有需要加密的class文件
      * 找出所有需要加密的class文件
      *
      *
-     * @param allFileList
-     *            所有文件
-     * @return  需要加密的class文件
+     * @param allFileList 所有文件
+     * @return  需要加密的class信息
      */
      */
-    private List<File> filterClasses(List<File> allFileList) {
+    private List<EncryptClassArgs> filterClasses(List<File> allFileList) {
         return allFileList.stream()
         return allFileList.stream()
                 .filter(file -> file.getName().endsWith(Constant.CLASS_SUFFIX))
                 .filter(file -> file.getName().endsWith(Constant.CLASS_SUFFIX))
-                .filter(file -> {
+                .map(file -> {
                     // 全类名
                     // 全类名
                     String classLongName = JavassistUtil.resolveClassName(file.getAbsolutePath(), true);
                     String classLongName = JavassistUtil.resolveClassName(file.getAbsolutePath(), true);
                     if (excludePrefixSet != null) {
                     if (excludePrefixSet != null) {
                         for (String excludePrefix : excludePrefixSet) {
                         for (String excludePrefix : excludePrefixSet) {
                             if (classLongName.startsWith(excludePrefix)) {
                             if (classLongName.startsWith(excludePrefix)) {
                                 // 排除
                                 // 排除
-                                return false;
+                                return null;
                             }
                             }
                         }
                         }
         
         
                     }
                     }
                     if (includePrefixSet != null) {
                     if (includePrefixSet != null) {
                         for (String includePrefix : includePrefixSet) {
                         for (String includePrefix : includePrefixSet) {
-                            if (classLongName.startsWith(includePrefix)) {
+                            Pair<String, Map<String, String>> pair = extraPrefixAndParam(includePrefix);
+                            String pureIncludePrefix = pair.getLeft();
+                            Map<String, String> params = pair.getRight();
+                            
+                            if (classLongName.startsWith(pureIncludePrefix)) {
                                 // 包含
                                 // 包含
-                                return true;
+                                return EncryptClassArgs.create(file,
+                                        StrUtil.isTrueDefault(params.get(Constant.CLEAN_CLASS_ANNOTATION_PARAM_NAME), false),
+                                        StrUtil.isTrueDefault(params.get(Constant.CLEAN_METHOD_ANNOTATION_PARAM_NAME), false),
+                                        StrUtil.isTrueDefault(params.get(Constant.CLEAN_FIELD_ANNOTATION_PARAM_NAME), false)
+                                );
                             }
                             }
                         }
                         }
                     }
                     }
-                    return false;
-                }).collect(Collectors.toList());
+                    return null;
+                })
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 从includePrefix中抽取纯净的前缀及相关参数
+     * <br />
+     * 注:参考从url中获取参数
+     *
+     * @param includePrefix 要加密的类前缀
+     *                      <p>
+     *                      可携带参数,如:com.ideaaedi.demo.service?key1=value1&key2=value2
+     *
+     * @return <ul>
+     *     <li>左-要加密的类前缀</li>
+     *     <li>右-相关加密参数信息</li>
+     * </ul>
+     */
+    private Pair<String, Map<String, String>> extraPrefixAndParam(String includePrefix) {
+        Map<String, String> param = new HashMap<>(8);
+        int index = includePrefix.indexOf("?");
+        if (index < 0) {
+           return Pair.of(includePrefix, param);
+        }
+        String pureIncludePrefix = includePrefix.substring(0, index);
+        String paramStr = includePrefix.substring(index + 1);
+        for (String keyValue : paramStr.split("&")) {
+            int equalIndex = keyValue.indexOf("=");
+            if (equalIndex < 0) {
+                continue;
+            }
+            String key = keyValue.substring(0, equalIndex).trim();
+            String value = keyValue.substring(equalIndex + 1).trim();
+            if (StrUtil.isBlank(key) || StrUtil.isBlank(value)) {
+                continue;
+            }
+            param.put(key, value);
+        }
+        return Pair.of(pureIncludePrefix, param);
     }
     }
     
     
     /**
     /**
@@ -1222,6 +1276,8 @@ public class EncryptExecutor {
                     Constant.WEB_INF, Constant.CLASSES);
                     Constant.WEB_INF, Constant.CLASSES);
 
 
             Set<String> includePrefixSet = StrUtil.strToSet(includePrefix);
             Set<String> includePrefixSet = StrUtil.strToSet(includePrefix);
+            LinkedHashSet<String> includePrefixSortSet = sortByPurePrefixLenthDesc(includePrefixSet);
+    
             Set<String> excludePrefixSet = StrUtil.strToSet(excludePrefix);
             Set<String> excludePrefixSet = StrUtil.strToSet(excludePrefix);
             Set<String> includeLibSet = StrUtil.strToSet(includeLibs);
             Set<String> includeLibSet = StrUtil.strToSet(includeLibs);
             Set<Pair<String, String>> alreadyProtectedLibSet = parseAlreadyProtectedLibs();
             Set<Pair<String, String>> alreadyProtectedLibSet = parseAlreadyProtectedLibs();
@@ -1250,10 +1306,30 @@ public class EncryptExecutor {
             Set<String> toCleanXmlChildElementNameSet = StrUtil.strToSet(toCleanXmlChildElementName);
             Set<String> toCleanXmlChildElementNameSet = StrUtil.strToSet(toCleanXmlChildElementName);
             
             
             return new EncryptExecutor(this.originJarOrWar, originIsJar, this.finalName, targetRootDir, targetLibDir, targetClassesDir,
             return new EncryptExecutor(this.originJarOrWar, originIsJar, this.finalName, targetRootDir, targetLibDir, targetClassesDir,
-                    password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSet,
+                    password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSortSet,
                     excludePrefixSet, includeLibSet, alreadyProtectedRootDir, alreadyProtectedLibSet, this.supportFile, jvmArgCheckSet);
                     excludePrefixSet, includeLibSet, alreadyProtectedRootDir, alreadyProtectedLibSet, this.supportFile, jvmArgCheckSet);
         }
         }
     
     
+        /**
+         * 按照(不带参数的)前缀的长度倒序
+         *
+         * @param includePrefixSet 前缀集合
+         *
+         * @return  倒序的前缀集合
+         */
+        private static LinkedHashSet<String> sortByPurePrefixLenthDesc(Set<String> includePrefixSet) {
+            List<String> includePrefixSortList = new ArrayList<>(includePrefixSet);
+            includePrefixSortList.sort(Comparator.comparingInt(x -> {
+                int idx = x.indexOf("?");
+                if (idx < 0) {
+                    return x.length();
+                }
+                return x.substring(0, idx).length();
+            }));
+            Collections.reverse(includePrefixSortList);
+            return new LinkedHashSet<>(includePrefixSortList);
+        }
+    
         /**
         /**
          * 解析alreadyProtectedLibs信息为Set<Pair<String, String>>
          * 解析alreadyProtectedLibs信息为Set<Pair<String, String>>
          */
          */

+ 10 - 4
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Cache.java

@@ -3,8 +3,8 @@ package winter.com.ideaaedi.classwinter.util;
 import winter.com.ideaaedi.classwinter.author.JustryDeng;
 import winter.com.ideaaedi.classwinter.author.JustryDeng;
 import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
 import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
 
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 
 /**
 /**
  * 简单缓存
  * 简单缓存
@@ -24,10 +24,16 @@ public final class Cache {
      *     <li>value-密码</li>
      *     <li>value-密码</li>
      * </ul>
      * </ul>
      */
      */
-    public static Map<String, char[]> passwordCacheForEncrypt = new HashMap<>(8);
+    public static volatile Map<String, char[]> passwordCacheForEncrypt = new ConcurrentHashMap<>(8);
     
     
-    /** 本项目加密时的印章 */
-    public static volatile String sealCache = null;
+    /** 本项目加密时的印章 (key-projectPath; value-印章) */
+    public static volatile Map<String, String>  sealCache =  new ConcurrentHashMap<>(8);
+    
+    /** 本项目获取到的第一个印章 */
+    public static volatile String  firstSealCache;
+    
+    /** 本项目获取到的第一个印章的项目路径 */
+    public static volatile String  firstSealProjectPath;
     
     
     /**
     /**
      * 以key-value的形式记录lib的印章。(key-存放采集到的类所在lib的信息的文件夹, value-印章字符串)
      * 以key-value的形式记录lib的印章。(key-存放采集到的类所在lib的信息的文件夹, value-印章字符串)

+ 21 - 0
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Constant.java

@@ -234,4 +234,25 @@ public interface Constant {
      * NotFoundException标识
      * NotFoundException标识
      */
      */
     String NOT_FOUND_EXCEPTION_FLAG = "javassist.NotFoundException:";
     String NOT_FOUND_EXCEPTION_FLAG = "javassist.NotFoundException:";
+    
+    /**
+     * 参数名:是否清除类上的注解. 值为boolean类型
+     * <p>
+     * {@link EncryptClassArgs#isCleanAnnotationOverClazz()}
+     */
+    String CLEAN_CLASS_ANNOTATION_PARAM_NAME = "cca";
+    
+    /**
+     * 参数名:是否清除方法的注解. 值应为boolean类型
+     * <p>
+     * {@link EncryptClassArgs#isCleanAnnotationOverMethod()}
+     */
+    String CLEAN_METHOD_ANNOTATION_PARAM_NAME = "cma";
+    
+    /**
+     * 参数名:是否清除字段的注解. 值应为boolean类型
+     * <p>
+     * {@link EncryptClassArgs#isCleanAnnotationOverField()}
+     */
+    String CLEAN_FIELD_ANNOTATION_PARAM_NAME = "cfa";
 }
 }

+ 104 - 0
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/EncryptClassArgs.java

@@ -0,0 +1,104 @@
+package winter.com.ideaaedi.classwinter.util;
+
+import java.io.File;
+import java.util.Objects;
+
+/**
+ * 加密类相关参数
+ *
+ * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
+ * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
+ * @since 2.8.0
+ */
+public class EncryptClassArgs {
+    
+    /**
+     * 待加密的class文件
+     */
+    private File encryptClassFile;
+    
+    /**
+     * 是否清除类上的注解
+     */
+    private boolean cleanAnnotationOverClazz = false;
+    
+    /**
+     * 是否清除方法的注解
+     */
+    private boolean cleanAnnotationOverMethod = false;
+    
+    /**
+     * 是否清除字段的注解
+     */
+    private boolean cleanAnnotationOverField = false;
+    
+    /**
+     * 是否保留原方法的参数名
+     */
+    private boolean keepOriginArgsName = true;
+    
+    /**
+     * fast create
+     */
+    public static EncryptClassArgs create(File encryptClassFile, boolean cleanAnnotationOverClazz,
+                                          boolean cleanAnnotationOverMethod, boolean cleanAnnotationOverField) {
+        Objects.requireNonNull(encryptClassFile, "encryptClassFile cannot be null.");
+        EncryptClassArgs encryptClassArgs = new EncryptClassArgs();
+        encryptClassArgs.setEncryptClassFile(encryptClassFile);
+        encryptClassArgs.setCleanAnnotationOverClazz(cleanAnnotationOverClazz);
+        encryptClassArgs.setCleanAnnotationOverMethod(cleanAnnotationOverMethod);
+        encryptClassArgs.setCleanAnnotationOverField(cleanAnnotationOverField);
+        return encryptClassArgs;
+    }
+    
+    public File getEncryptClassFile() {
+        return encryptClassFile;
+    }
+    
+    public void setEncryptClassFile(File encryptClassFile) {
+        this.encryptClassFile = encryptClassFile;
+    }
+    
+    public boolean isCleanAnnotationOverClazz() {
+        return cleanAnnotationOverClazz;
+    }
+    
+    public void setCleanAnnotationOverClazz(boolean cleanAnnotationOverClazz) {
+        this.cleanAnnotationOverClazz = cleanAnnotationOverClazz;
+    }
+    
+    public boolean isCleanAnnotationOverMethod() {
+        return cleanAnnotationOverMethod;
+    }
+    
+    public void setCleanAnnotationOverMethod(boolean cleanAnnotationOverMethod) {
+        this.cleanAnnotationOverMethod = cleanAnnotationOverMethod;
+    }
+    
+    public boolean isCleanAnnotationOverField() {
+        return cleanAnnotationOverField;
+    }
+    
+    public void setCleanAnnotationOverField(boolean cleanAnnotationOverField) {
+        this.cleanAnnotationOverField = cleanAnnotationOverField;
+    }
+    
+    public boolean isKeepOriginArgsName() {
+        return keepOriginArgsName;
+    }
+    
+    public void setKeepOriginArgsName(boolean keepOriginArgsName) {
+        this.keepOriginArgsName = keepOriginArgsName;
+    }
+    
+    @Override
+    public String toString() {
+        return "EncryptClassArgs{" +
+                "encryptClassFile=" + encryptClassFile +
+                ", cleanAnnotationOverClazz=" + cleanAnnotationOverClazz +
+                ", cleanAnnotationOverMethod=" + cleanAnnotationOverMethod +
+                ", cleanAnnotationOverField=" + cleanAnnotationOverField +
+                ", keepOriginArgsName=" + keepOriginArgsName +
+                '}';
+    }
+}

+ 73 - 16
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JavassistUtil.java

@@ -3,8 +3,11 @@ package winter.com.ideaaedi.classwinter.util;
 import javassist.CannotCompileException;
 import javassist.CannotCompileException;
 import javassist.ClassPool;
 import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.CtClass;
+import javassist.CtField;
 import javassist.CtMethod;
 import javassist.CtMethod;
 import javassist.NotFoundException;
 import javassist.NotFoundException;
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.AttributeInfo;
 import javassist.bytecode.BadBytecode;
 import javassist.bytecode.BadBytecode;
 import javassist.bytecode.Bytecode;
 import javassist.bytecode.Bytecode;
 import javassist.bytecode.CodeAttribute;
 import javassist.bytecode.CodeAttribute;
@@ -32,12 +35,9 @@ public final class JavassistUtil {
     /**
     /**
      * 清空类中的方法体,并简单处理一下main,使提示密码无效
      * 清空类中的方法体,并简单处理一下main,使提示密码无效
      *
      *
-     * @param classPool
-     *            javassist的classPool
-     * @param className
-     *            要修改的class类的全类名
-     * @param keepOriginArgsName
-     *            是否保留原方法的参数名
+     * @param classPool javassist的classPool
+     * @param className 要修改的class类的全类名
+     * @param encryptClassArgs 加密相关参数
      *
      *
      * @return  处理后的类的字节
      * @return  处理后的类的字节
      * @throws NotFoundException 当清空的类中涉及到了某些其他的类,但是根本就没有引入(这些其他的类)相应的依赖时,就会抛出此异常(即:这个类本身就报错来着)
      * @throws NotFoundException 当清空的类中涉及到了某些其他的类,但是根本就没有引入(这些其他的类)相应的依赖时,就会抛出此异常(即:这个类本身就报错来着)
@@ -46,7 +46,8 @@ public final class JavassistUtil {
      *                           注:在某些其它情况下,也会抛出此异常。
      *                           注:在某些其它情况下,也会抛出此异常。
      * @throws  CannotCompileException 统一封装异常
      * @throws  CannotCompileException 统一封装异常
      */
      */
-    public static byte[] clearMethodBody(ClassPool classPool, String className, boolean keepOriginArgsName) throws CannotCompileException, NotFoundException {
+    public static byte[] clearMethodBody(ClassPool classPool, String className, EncryptClassArgs encryptClassArgs)
+            throws CannotCompileException, NotFoundException {
         CtClass ctClass;
         CtClass ctClass;
         try {
         try {
             ctClass = classPool.getCtClass(className);
             ctClass = classPool.getCtClass(className);
@@ -54,6 +55,19 @@ public final class JavassistUtil {
                 Logger.debug(JavassistUtil.class, "defrost class " + className);
                 Logger.debug(JavassistUtil.class, "defrost class " + className);
                 ctClass.defrost();
                 ctClass.defrost();
             }
             }
+            // 清空注解
+            boolean cleanOverCLass = encryptClassArgs.isCleanAnnotationOverClazz();
+            boolean cleanOverMethod = encryptClassArgs.isCleanAnnotationOverMethod();
+            boolean cleanOverField = encryptClassArgs.isCleanAnnotationOverField();
+            if (cleanOverCLass || cleanOverMethod || cleanOverField) {
+                try {
+                    clearAnnotation(ctClass, cleanOverCLass, cleanOverMethod, cleanOverField);
+                } catch (Exception ignore) {
+                    Logger.warn(JavassistUtil.class, "clean className [" + className + "] annotation fail. ignore.");
+                    // ignore
+                }
+            }
+            boolean keepOriginArgsName = encryptClassArgs.isKeepOriginArgsName();
             CtMethod[] methods = ctClass.getDeclaredMethods();
             CtMethod[] methods = ctClass.getDeclaredMethods();
             for (CtMethod ctMethod : methods) {
             for (CtMethod ctMethod : methods) {
                 // 当前类中的方法 && 非构造方法
                 // 当前类中的方法 && 非构造方法
@@ -67,18 +81,12 @@ public final class JavassistUtil {
                     } else {
                     } else {
                         ctMethod.setBody(null);
                         ctMethod.setBody(null);
                     }
                     }
-                    /// 顺带处理一下main方法:提示jar包已经被保护,请使用javaagent启动项目
-                    /// if (isMain(ctMethod)) {
-                    ///     ctMethod.insertBefore(
-                    ///             "System.out.println(\"\\n " + TIPS +" \\n\");"
-                    ///                     + "\nSystem.exit(-1);"
-                    ///     );
-                    /// }
                     try {
                     try {
                         ctMethod.insertBefore(
                         ctMethod.insertBefore(
-                                "System.out.println(\"\\n " + Constant.TIPS +" \\n\");"
+                                "System.out.println(\"\\n " + Constant.TIPS + " \\n\");"
                                 // 也输出印章信息吧
                                 // 也输出印章信息吧
-                                + "\nSystem.out.println(\" " + Constant.SEAL +" \");"
+                                + "\nSystem.out.println(\" Located in '" + className + "' \");"
+                                + "\nSystem.out.println(\" " + Constant.SEAL + " \");"
                                 + "\nSystem.exit(-1);"
                                 + "\nSystem.exit(-1);"
                         );
                         );
                     } catch (CannotCompileException e) {
                     } catch (CannotCompileException e) {
@@ -97,6 +105,55 @@ public final class JavassistUtil {
         }
         }
     }
     }
     
     
+    /**
+     * 清空注解
+     *
+     * @param ctClass 目标类
+     * @param cleanOverCLass 是否清空类上的注解
+     * @param cleanOverMethod 是否清空方法上的注解
+     * @param cleanOverField 是否清空字段上的注解
+     */
+    private static void clearAnnotation(CtClass ctClass, boolean cleanOverCLass, boolean cleanOverMethod, boolean cleanOverField) {
+        // 清空类上的注解
+        if (cleanOverCLass) {
+            removeAnnotationsAttribute(ctClass.getClassFile().getAttributes());
+        }
+        // 清空方法上的注解
+        if (cleanOverMethod) {
+            CtMethod[] methods = ctClass.getDeclaredMethods();
+            for (CtMethod ctMethod : methods) {
+                removeAnnotationsAttribute(ctMethod.getMethodInfo().getAttributes());
+            }
+        }
+        // 清空字段上的注解
+        if (cleanOverField) {
+            CtField[] fields = ctClass.getDeclaredFields();
+            for (CtField declaredField : fields) {
+                removeAnnotationsAttribute(declaredField.getFieldInfo().getAttributes());
+            }
+        }
+    }
+    
+    /**
+     * 移除注解属性
+     *
+     * @param attributeInfoList 属性信息集合
+     * @return 操作是否成功
+     */
+    @SuppressWarnings("UnusedReturnValue")
+    private static boolean removeAnnotationsAttribute(List<AttributeInfo> attributeInfoList) {
+        if (attributeInfoList == null || attributeInfoList.size() == 0) {
+            return true;
+        }
+        return attributeInfoList.removeIf(x -> {
+            try {
+                return x instanceof AnnotationsAttribute;
+            } catch (Exception e) {
+                return false;
+            }
+        });
+    }
+    
     /**
     /**
      * 加载paths指定的.jar文件(或加载对应子孙目录下的所有jar包)
      * 加载paths指定的.jar文件(或加载对应子孙目录下的所有jar包)
      *
      *

+ 14 - 0
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/StrUtil.java

@@ -28,6 +28,20 @@ public final class StrUtil {
         return str == null || str.length() == 0;
         return str == null || str.length() == 0;
     }
     }
     
     
+    /**
+     * 判断字符串是否为true
+     *
+     * @param str 字符串
+     * @param defaultValue 字符串为空时的默认值
+     * @return  是否为true
+     */
+    public static boolean isTrueDefault(String str, boolean defaultValue) {
+        if (isBlank(str)) {
+            return defaultValue;
+        }
+        return str.equalsIgnoreCase("true");
+    }
+    
     /**
     /**
      * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
      * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
      *
      *

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AllTest.java

@@ -68,7 +68,7 @@ public class AllTest {
         // 加密
         // 加密
         String projectRootDir = PathUtil.getProjectRootDir(AllTest.class);
         String projectRootDir = PathUtil.getProjectRootDir(AllTest.class);
         String originJarOrWar = projectRootDir + "my-project-with-encrypted-lib-have-pwd.jar";
         String originJarOrWar = projectRootDir + "my-project-with-encrypted-lib-have-pwd.jar";
-        String includePrefix = "com.szlaozicl,com.aspire.ssm,org.springframework.aop.target.dynamic,com.fasterxml.jackson";
+        String includePrefix = "com.szlaozicl?cca=true&cfa=true,com.aspire.ssm,org.springframework.aop.target.dynamic,com.fasterxml.jackson";
         String excludePrefix = "com.aspire.ssm.config,com.aspire.ssm.util.Person";
         String excludePrefix = "com.aspire.ssm.config,com.aspire.ssm.util.Person";
         String finalName = "jd";
         String finalName = "jd";
         String password = "pwd12345";
         String password = "pwd12345";
@@ -77,7 +77,7 @@ public class AllTest {
         String alreadyProtectedLibs = "encrypted-lib-have-pwd-1.0.0.jar:qwer123~";
         String alreadyProtectedLibs = "encrypted-lib-have-pwd-1.0.0.jar:qwer123~";
         String jvmArgCheck = "-XX:+DisableAttachMechanism";
         String jvmArgCheck = "-XX:+DisableAttachMechanism";
         String debug = "true";
         String debug = "true";
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " excludePrefix=" + excludePrefix
                 + " excludePrefix=" + excludePrefix

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AlreadyProtectedLibs_Test.java

@@ -67,7 +67,7 @@ public class AlreadyProtectedLibs_Test {
         String originJarOrWar = projectRootDir + Constant.LINUX_FILE_SEPARATOR + "my-project-with-encrypted-lib-no-pwd.jar";
         String originJarOrWar = projectRootDir + Constant.LINUX_FILE_SEPARATOR + "my-project-with-encrypted-lib-no-pwd.jar";
         String includePrefix = "non-exist";
         String includePrefix = "non-exist";
         String alreadyProtectedLibs = "encrypted-lib-no-pwd-1.0.0.jar";
         String alreadyProtectedLibs = "encrypted-lib-no-pwd-1.0.0.jar";
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
@@ -110,7 +110,7 @@ public class AlreadyProtectedLibs_Test {
         String includePrefix = "non-exist";
         String includePrefix = "non-exist";
         String alreadyProtectedLibs = "encrypted-lib-have-pwd-1.0.0.jar:qwer123~";
         String alreadyProtectedLibs = "encrypted-lib-have-pwd-1.0.0.jar:qwer123~";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Debug_Test.java

@@ -36,7 +36,7 @@ public class Debug_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com";
         String includePrefix = "com";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 ;
                 ;
@@ -64,7 +64,7 @@ public class Debug_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com";
         String includePrefix = "com";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " debug=" + true
                 + " debug=" + true

+ 88 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/EncryptArgParam_Test.java

@@ -0,0 +1,88 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 测试加密参数
+ * <p>
+ *     注:在includePrefix后面允许设置加密参数(方式同在url后加参数一样,只是不需要urlEncoding)
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class EncryptArgParam_Test {
+    
+    public static void main(String[] args) {
+//        // 测试1: 无参数(默认参数)测试
+//        Map<String, String> argMap = new HashMap<>();
+//        have(argMap);
+    
+//        // 测试2: 有参数测试
+//        Map<String, String> argMap = new HashMap<>();
+//        argMap.put(Constant.CLEAN_CLASS_ANNOTATION_PARAM_NAME, "true");  // 默认为false
+//        argMap.put(Constant.CLEAN_METHOD_ANNOTATION_PARAM_NAME, "true");  // 默认为false
+//        argMap.put(Constant.CLEAN_FIELD_ANNOTATION_PARAM_NAME, "true"); // 默认为false
+//        have(argMap);
+    
+//        // 测试3: 有参数测试
+//        Map<String, String> argMap = new HashMap<>();
+//        argMap.put(Constant.CLEAN_CLASS_ANNOTATION_PARAM_NAME, "false");  // 默认为false
+//        argMap.put(Constant.CLEAN_METHOD_ANNOTATION_PARAM_NAME, "true");  // 默认为false
+//        argMap.put(Constant.CLEAN_FIELD_ANNOTATION_PARAM_NAME, "false"); // 默认为false
+//        have(argMap);
+    
+        // 测试4: 有参数测试
+        Map<String, String> argMap = new HashMap<>();
+        argMap.put(Constant.CLEAN_CLASS_ANNOTATION_PARAM_NAME, "true");  // 默认为false
+        argMap.put(Constant.CLEAN_METHOD_ANNOTATION_PARAM_NAME, "false");  // 默认为false
+        argMap.put(Constant.CLEAN_FIELD_ANNOTATION_PARAM_NAME, "true"); // 默认为false
+        have(argMap);
+    }
+    
+    /**
+     * jar测试 - 失败测试
+     */
+    public static void have(Map<String, String> argMap) {
+        // 杀下进程(以保证端口没有被占用)
+        BashUtil.killProcessByPorts("8080");
+        
+        String projectRootDir = PathUtil.getProjectRootDir(AlreadyProtectedLibs_Test.class);
+        String originJarOrWar = projectRootDir + "boot-jar.jar";
+        String includePrefix = "com";
+        
+        // 在includePrefix后面组装参数(和在url后面增加参数一样)
+        if (argMap != null && argMap.size() > 0) {
+            StringBuilder sb = new StringBuilder(includePrefix);
+            sb.append("?");
+            argMap.forEach((key, value) -> {
+                sb.append(key).append("=").append(value).append("&");
+            });
+            sb.replace(sb.length() - 1, sb.length(), "");
+            includePrefix= sb.toString();
+        }
+        
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
+                + " originJarOrWar=" + originJarOrWar
+                + " includePrefix=" + includePrefix
+                + " debug=true"
+                ;
+        // 加密
+        BashUtil.runBashAndPrint(startBat);
+    
+    
+        String encryptedJar = originJarOrWar.replace(".jar", "-encrypted.jar");
+    
+        // 解密
+        String javaagentArgs = "";
+        // String javaagentArgs = "=debug=true";
+        // String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runBashAndPrint(String.format("java -javaagent:%s%s=debug=true -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+    }
+    
+}

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ExcludePrefix_Test.java

@@ -38,7 +38,7 @@ public class ExcludePrefix_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com.aspire.ssm.util.AesEncryptDecryptUtil,com.aspire.ssm.util.DbSecurityBeanUtil";
         String includePrefix = "com.aspire.ssm.util.AesEncryptDecryptUtil,com.aspire.ssm.util.DbSecurityBeanUtil";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " debug=" + true
                 + " debug=" + true
@@ -72,7 +72,7 @@ public class ExcludePrefix_Test {
         String includePrefix = "com.aspire.ssm.util.AesEncryptDecryptUtil,com.aspire.ssm.util.DbSecurityBeanUtil";
         String includePrefix = "com.aspire.ssm.util.AesEncryptDecryptUtil,com.aspire.ssm.util.DbSecurityBeanUtil";
         String excludePrefix = "com.aspire.ssm.util.DbSecurityBeanUtil";
         String excludePrefix = "com.aspire.ssm.util.DbSecurityBeanUtil";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " excludePrefix=" + excludePrefix
                 + " excludePrefix=" + excludePrefix

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/FinalName_Test.java

@@ -23,7 +23,7 @@ public class FinalName_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String finalName = "YiYaKaKa";
         String finalName = "YiYaKaKa";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " finalName=" + finalName
                 + " finalName=" + finalName

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludeLibs_Test.java

@@ -42,7 +42,7 @@ public class IncludeLibs_Test {
         String includePrefix = "org.springframework.aop.target.dynamic,com.google.common.xml";
         String includePrefix = "org.springframework.aop.target.dynamic,com.google.common.xml";
         String includeLibs = "spring-aop-5.1.8.RELEASE.jar,guava-28.2-jre.jar";
         String includeLibs = "spring-aop-5.1.8.RELEASE.jar,guava-28.2-jre.jar";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " includeLibs=" + includeLibs
                 + " includeLibs=" + includeLibs

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludePrefix_Test.java

@@ -39,7 +39,7 @@ public class IncludePrefix_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com.aspire.ssm.util";
         String includePrefix = "com.aspire.ssm.util";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " debug=" + true
                 + " debug=" + true

+ 3 - 3
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/JvmArgCheck_Test.java

@@ -33,7 +33,7 @@ public class JvmArgCheck_Test {
     
     
         String jvmArg = "-XX:+DisableAttachMechanism,-Xms1024M";
         String jvmArg = "-XX:+DisableAttachMechanism,-Xms1024M";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " jvmArgCheck=" + jvmArg
                 + " jvmArgCheck=" + jvmArg
@@ -65,7 +65,7 @@ public class JvmArgCheck_Test {
     
     
         String jvmArg = "-XX:+DisableAttachMechanism,-Xms1024M";
         String jvmArg = "-XX:+DisableAttachMechanism,-Xms1024M";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " jvmArgCheck=" + jvmArg
                 + " jvmArgCheck=" + jvmArg
@@ -97,7 +97,7 @@ public class JvmArgCheck_Test {
     
     
         String jvmArg = "-XX:+DisableAttachMechanism";
         String jvmArg = "-XX:+DisableAttachMechanism";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " jvmArgCheck=" + jvmArg
                 + " jvmArgCheck=" + jvmArg

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/OriginJarOrWar_Test.java

@@ -32,7 +32,7 @@ public class OriginJarOrWar_Test {
         String originJarOrWar = projectRootDir + "non-exist.jar";
         String originJarOrWar = projectRootDir + "non-exist.jar";
         String includePrefix = "com.aspire.ssm.util";
         String includePrefix = "com.aspire.ssm.util";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " debug=" + true
                 + " debug=" + true
@@ -58,7 +58,7 @@ public class OriginJarOrWar_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com.aspire.ssm.util";
         String includePrefix = "com.aspire.ssm.util";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " debug=" + true
                 + " debug=" + true

+ 3 - 3
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Password_Test.java

@@ -34,7 +34,7 @@ public class Password_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String password = "pwd123";
         String password = "pwd123";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " password=" + password
                 + " password=" + password
@@ -65,7 +65,7 @@ public class Password_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String password = "pwd123";
         String password = "pwd123";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " password=" + password
                 + " password=" + password
@@ -97,7 +97,7 @@ public class Password_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String password = "pwd123";
         String password = "pwd123";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " password=" + password
                 + " password=" + password

+ 2 - 2
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/SupportFile_Test.java

@@ -42,7 +42,7 @@ public class SupportFile_Test {
         String originJarOrWar = projectRootDir + "normal-jar.jar";
         String originJarOrWar = projectRootDir + "normal-jar.jar";
         String includePrefix = "com";
         String includePrefix = "com";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 ;
                 ;
@@ -62,7 +62,7 @@ public class SupportFile_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String supportFile = projectRootDir + "help";
         String supportFile = projectRootDir + "help";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " supportFile=" + supportFile
                 + " supportFile=" + supportFile

+ 3 - 3
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Tips_Test.java

@@ -32,7 +32,7 @@ public class Tips_Test {
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String originJarOrWar = projectRootDir + "boot-jar.jar";
         String includePrefix = "com";
         String includePrefix = "com";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 ;
                 ;
@@ -55,8 +55,8 @@ public class Tips_Test {
         String tips = "[潘嘎之交] 潘: 你别怪潘叔说话比较直白, 网络上的东西都是虚拟的, 你把握不住, 孩子! 因为这里的水很深...";
         String tips = "[潘嘎之交] 潘: 你别怪潘叔说话比较直白, 网络上的东西都是虚拟的, 你把握不住, 孩子! 因为这里的水很深...";
     
     
         // 如果tips值由一些特殊字符(如空格等)的话,可以用windows双引号(linux单引号)引起来。
         // 如果tips值由一些特殊字符(如空格等)的话,可以用windows双引号(linux单引号)引起来。
-        // java -jar class-winter-core-2.7.9.jar originJarOrWar=/boot-jar.jar includePrefix=com tips="[潘嘎之交] 潘: 你别怪潘叔说话比较直白, 网络上的东西都是虚拟的, 你把握不住, 孩子! 因为这里的水很深..."
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        // java -jar class-winter-core-2.8.0.jar originJarOrWar=/boot-jar.jar includePrefix=com tips="[潘嘎之交] 潘: 你别怪潘叔说话比较直白, 网络上的东西都是虚拟的, 你把握不住, 孩子! 因为这里的水很深..."
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " tips=" + (BashUtil.IS_WINDOWS ? "\"".concat(tips).concat("\"") : "'".concat(tips).concat("'"));
                 + " tips=" + (BashUtil.IS_WINDOWS ? "\"".concat(tips).concat("\"") : "'".concat(tips).concat("'"));

+ 5 - 5
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/War_Test.java

@@ -34,7 +34,7 @@ public class War_Test {
         String originJarOrWar = projectRootDir + "war-project.war";
         String originJarOrWar = projectRootDir + "war-project.war";
         String includePrefix = "com";
         String includePrefix = "com";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 ;
                 ;
@@ -62,7 +62,7 @@ public class War_Test {
         String includePrefix = "com";
         String includePrefix = "com";
         String password = "123456";
         String password = "123456";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " password=" + password
                 + " password=" + password
@@ -93,7 +93,7 @@ public class War_Test {
         String alreadyProtectedLibs = "encrypted-lib-no-pwd.jar";
         String alreadyProtectedLibs = "encrypted-lib-no-pwd.jar";
         String password = "oop857857";
         String password = "oop857857";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
@@ -124,7 +124,7 @@ public class War_Test {
         String alreadyProtectedLibs = "encrypted-lib-have-pwd.jar:qwer123~";
         String alreadyProtectedLibs = "encrypted-lib-have-pwd.jar:qwer123~";
         String password = "yiyakaka";
         String password = "yiyakaka";
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
                 + " alreadyProtectedLibs=" + alreadyProtectedLibs
@@ -160,7 +160,7 @@ public class War_Test {
         String alreadyProtectedLibs = "encrypted-lib-have-pwd.jar:qwer123~";
         String alreadyProtectedLibs = "encrypted-lib-have-pwd.jar:qwer123~";
         String debug = "true";
         String debug = "true";
     
     
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " excludePrefix=" + excludePrefix
                 + " excludePrefix=" + excludePrefix

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Xml_Test.java

@@ -31,7 +31,7 @@ public class Xml_Test {
         String toCleanXmlChildElementName = "select";
         String toCleanXmlChildElementName = "select";
         
         
         
         
-        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.7.9.jar"
+        String startBat = "java -jar " + projectRootDir + "class-winter-core-2.8.0.jar"
                 + " originJarOrWar=" + originJarOrWar
                 + " originJarOrWar=" + originJarOrWar
                 + " includePrefix=" + includePrefix
                 + " includePrefix=" + includePrefix
                 + " includeXmlPrefix=" + includeXmlPrefix
                 + " includeXmlPrefix=" + includeXmlPrefix

TEMPAT SAMPAH
class-winter-core/src/test/resources/class-winter-core-2.8.0.jar


TEMPAT SAMPAH
class-winter-core/src/test/resources/class-winter-core-enhance-2.8.0.jar


+ 1 - 1
class-winter-maven-plugin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
     <parent>
         <groupId>com.idea-aedi</groupId>
         <groupId>com.idea-aedi</groupId>
         <artifactId>class-winter</artifactId>
         <artifactId>class-winter</artifactId>
-        <version>2.7.9</version>
+        <version>2.8.0</version>
     </parent>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
 
 

+ 1 - 1
pom.xml

@@ -9,7 +9,7 @@
     </modules>
     </modules>
     <groupId>com.idea-aedi</groupId>
     <groupId>com.idea-aedi</groupId>
     <artifactId>class-winter</artifactId>
     <artifactId>class-winter</artifactId>
-    <version>2.7.9</version>
+    <version>2.8.0</version>
 
 
     <!-- 配置项目的基础信息 -->
     <!-- 配置项目的基础信息 -->
     <name>class-winter</name>
     <name>class-winter</name>