├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.md ├── src ├── main │ ├── resources │ │ ├── mybatis │ │ │ ├── mybatis-config.xml │ │ │ └── mapper │ │ │ │ └── TUserMapper.xml │ │ ├── application.properties │ │ ├── jdbc.properties │ │ └── log4j2.xml │ └── java │ │ └── git │ │ └── yampery │ │ └── cryptic │ │ ├── cryptic │ │ ├── ADESInterface.java │ │ ├── CryptPojo.java │ │ ├── ADESUtils.java │ │ └── CryptPojoUtils.java │ │ ├── Application.java │ │ ├── dao │ │ └── UserDao.java │ │ ├── annotation │ │ ├── DecryptField.java │ │ └── EncryptField.java │ │ ├── service │ │ ├── UserService.java │ │ └── impl │ │ │ └── UserServiceImpl.java │ │ ├── pojo │ │ └── TUser.java │ │ ├── common │ │ ├── SysException.java │ │ └── QueryParams.java │ │ ├── config │ │ └── DruidConfig.java │ │ └── interceptor │ │ └── DBInterceptor.java └── test │ └── java │ └── git │ └── yampery │ └── cryptic │ └── ApplicationTests.java ├── .gitignore ├── database └── CRYPTIC_DATA.sql ├── gradlew.bat └── gradlew /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'cryptic-data' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yampery/cryptic-data/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 06 12:27:20 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cryptic-data 2 | 基于Spring-mybatis项目,以AES的方式对指定数据(注解)进行加解密 3 | # 说明 4 | - 更改jdbc连接 jdbc.properties 5 | - 生成128位秘钥 6 | - 运行测试文件 7 | 8 | **该项目使用springboot+mybatis+gradle构建,对于传统spring+maven项目,只需要更改配置即可** 9 | **具体问题访问博客: https://blog.csdn.net/wizard_rp/article/details/79821671** 10 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/cryptic/ADESInterface.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.cryptic; 2 | 3 | /** 4 | * @decription ADESInterface 5 | *

自加解密接口

6 | * @author Yampery 7 | * @date 2017/10/24 13:15 8 | */ 9 | public interface ADESInterface { 10 | public T encryptSelf(); 11 | public T decryptSelf(); 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | ### NetBeans ### 21 | nbproject/private/ 22 | build/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/Application.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication 8 | @MapperScan("git.yampery.cryptic.dao") 9 | public class Application { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(Application.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.dao; 2 | 3 | import git.yampery.cryptic.pojo.TUser; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @decription UserDao 10 | *

用户数据库表访问

11 | * @author Yampery 12 | * @date 2018/4/4 13:54 13 | */ 14 | public interface UserDao { 15 | 16 | int insert(TUser record); 17 | 18 | int insertSelective(TUser record); 19 | 20 | List queryList(Map map); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/annotation/DecryptField.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @decription DecryptField 10 | *

字段解密注解

11 | * @author Yampery 12 | * @date 2017/10/24 13:05 13 | */ 14 | @Target(ElementType.FIELD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface DecryptField { 17 | String value() default ""; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/annotation/EncryptField.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @decription EncryptField 10 | *

字段加密注解

11 | * @author Yampery 12 | * @date 2017/10/24 13:01 13 | */ 14 | @Target(ElementType.FIELD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface EncryptField { 17 | String value() default ""; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/service/UserService.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.service; 2 | 3 | import git.yampery.cryptic.pojo.TUser; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @decription UserService 10 | *

用户服务

11 | * @author Yampery 12 | * @date 2018/4/4 14:48 13 | */ 14 | public interface UserService { 15 | 16 | /** 17 | * 查询 18 | * @param map 19 | */ 20 | List queryList(Map map); 21 | 22 | /** 23 | * 写入数据 24 | * @param user 25 | */ 26 | void insert(TUser user); 27 | } 28 | -------------------------------------------------------------------------------- /database/CRYPTIC_DATA.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : docker_mysql 5 | Source Server Version : 50720 6 | Source Host : localhost:3306 7 | Source Database : CRYPTIC_DATA 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50720 11 | File Encoding : 65001 12 | 13 | Date: 2018-04-04 13:50:51 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for T_USER 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `T_USER`; 22 | CREATE TABLE `T_USER` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id自增主键', 24 | `user_name` varchar(20) DEFAULT NULL COMMENT '用户名', 25 | `phone` varchar(32) DEFAULT NULL, 26 | PRIMARY KEY (`id`) 27 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 28 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ################################ 系统配置 ############################# 2 | # 设置内置端口 3 | # server.port =8090 4 | # 配置协议为http(如果网站使用了证书,删除掉配置即可) 5 | # server.tomcat.protocol-header-https-value =http 6 | 7 | # log4j2 8 | # log4j.config-locations =classpath:log4j2.xml 9 | 10 | # Mybatis 11 | mybatis.config-location =classpath:mybatis/mybatis-config.xml 12 | mybatis.mapper-locations =classpath:mybatis/mapper/*.xml 13 | mybatis.type-aliases-package =git.yampery.cryptic.pojo 14 | 15 | # 开启debug模式可以在控制台查看springboot加载流程 16 | # debug =true 17 | 18 | # 密盐(使用工具ADESUtils生成) 19 | sys.aes.salt =4BB90812C2B9B0882A6FA7C203E4717F 20 | # 加解密开关(1:开启加解密;0:关闭加解密) 21 | sys.aes.switch =1 -------------------------------------------------------------------------------- /src/main/resources/jdbc.properties: -------------------------------------------------------------------------------- 1 | jdbc.driver =com.mysql.cj.jdbc.Driver 2 | jdbc.url =jdbc:mysql://localhost:3306/CRYPTIC_DATA?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai 3 | jdbc.username =root 4 | jdbc.password =1 5 | #定义初始连接数 6 | jdbc.pool.initialSize =10 7 | #定义最大连接数 8 | jdbc.pool.maxActive =100 9 | #定义最大空闲 10 | jdbc.pool.maxIdle =0 11 | #定义最小空闲 12 | jdbc.pool.minIdle =10 13 | #定义最长等待时间 14 | jdbc.pool.maxWait =60000 15 | #连接检测 16 | jdbc.pool.timeBetweenEvictionRunsMillis =60000 17 | jdbc.pool.minEvictableIdleTimeMillis =300000 18 | jdbc.pool.maxPoolPreparedStatementPerConnectionSize =100 -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.service.impl; 2 | 3 | import git.yampery.cryptic.common.SysException; 4 | import git.yampery.cryptic.dao.UserDao; 5 | import git.yampery.cryptic.pojo.TUser; 6 | import git.yampery.cryptic.service.UserService; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /** 14 | * @decription UserServiceImpl 15 | *

16 | * @author Yampery 17 | * @date 2018/4/4 14:50 18 | */ 19 | @Service 20 | public class UserServiceImpl implements UserService { 21 | 22 | @Resource private UserDao userDao; 23 | 24 | @Override 25 | public List queryList(Map map) { 26 | try { 27 | return userDao.queryList(map); 28 | } catch (Exception e) { 29 | throw new SysException("获取用户列表出错", e); 30 | } 31 | } 32 | 33 | @Override 34 | public void insert(TUser user) { 35 | try { 36 | userDao.insert(user); 37 | } catch (Exception e) { 38 | throw new SysException("写入用户列表出错", e); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/pojo/TUser.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.pojo; 2 | 3 | import git.yampery.cryptic.annotation.DecryptField; 4 | import git.yampery.cryptic.annotation.EncryptField; 5 | 6 | /** 7 | * @decription TUser 8 | *

用户pojo

9 | * @author Yampery 10 | * @date 2018/4/4 14:00 11 | */ 12 | public class TUser { 13 | private Integer id; 14 | 15 | private String userName; 16 | 17 | @EncryptField 18 | @DecryptField 19 | private String phone; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getUserName() { 30 | return userName; 31 | } 32 | 33 | public void setUserName(String userName) { 34 | this.userName = userName; 35 | } 36 | 37 | public String getPhone() { 38 | return phone; 39 | } 40 | 41 | public void setPhone(String phone) { 42 | this.phone = phone; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "TUser{" + 48 | "userName='" + userName + '\'' + 49 | ", phone='" + phone + '\'' + 50 | '}'; 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/common/SysException.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.common; 2 | 3 | /** 4 | * @decription SysException 5 | *

系统自定义异常
6 | * 说明:在可能存在运行时异常的地方进行捕获,获取异常信息,向上层抛出此异常
7 | * 在表现层进行捕获,并使用logger.error()打印日志
8 | *

异常码说明:{ 如果有自定义code,在此注明 }
9 | * 500:服务器内部错误,可能是系统自行抛出被捕获,也可能是明确的个人抛出的系统异常
10 | *

11 | *

12 | * @author Yampery 13 | * @date 2018/4/4 17:15 14 | */ 15 | public class SysException extends RuntimeException { 16 | 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String msg; 20 | private int code = 500; 21 | 22 | public SysException(String msg) { 23 | super(msg); 24 | this.msg = msg; 25 | } 26 | 27 | public SysException(String msg, Throwable e) { 28 | super(msg, e); 29 | this.msg = msg; 30 | } 31 | 32 | public SysException(String msg, int code) { 33 | super(msg); 34 | this.msg = msg; 35 | this.code = code; 36 | } 37 | 38 | public SysException(String msg, int code, Throwable e) { 39 | super(msg, e); 40 | this.msg = msg; 41 | this.code = code; 42 | } 43 | 44 | public String getMsg() { 45 | return msg; 46 | } 47 | 48 | public void setMsg(String msg) { 49 | this.msg = msg; 50 | } 51 | 52 | public int getCode() { 53 | return code; 54 | } 55 | 56 | public void setCode(int code) { 57 | this.code = code; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/common/QueryParams.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.common; 2 | 3 | import git.yampery.cryptic.cryptic.ADESUtils; 4 | 5 | import java.util.LinkedHashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @decription QueryParams 10 | *

封装查询参数

11 | * @author Yampery 12 | * @date 2018/4/4 14:23 13 | */ 14 | public class QueryParams extends LinkedHashMap{ 15 | 16 | private static final long serialVersionUID = 1L; 17 | private static final String REGIX_PHONE = "^((0\\d{2,3}\\d{7,8})|(1[35784]\\d{9}))$"; 18 | //当前页码 19 | private int page; 20 | //每页条数 21 | private int limit; 22 | 23 | public QueryParams(Map params){ 24 | // 如果参数是手机号,则加密后查询 25 | if (params.containsKey("phone")) { 26 | String number = params.get("phone").toString(); 27 | if (number.matches(REGIX_PHONE)) { 28 | params.put("phone", ADESUtils.getInstance().encrypt(number)); 29 | } 30 | } 31 | this.putAll(params); 32 | 33 | //分页参数 34 | if (null != params.get("page")) { 35 | this.page = Integer.parseInt(params.get("page").toString()); 36 | this.put("page", page); 37 | } 38 | if (null != params.get("limit")) { 39 | this.limit = Integer.parseInt(params.get("limit").toString()); 40 | this.put("limit", limit); 41 | this.put("offset", (page - 1) * limit); 42 | } 43 | } 44 | 45 | 46 | public int getPage() { 47 | return page; 48 | } 49 | 50 | public void setPage(int page) { 51 | this.page = page; 52 | } 53 | 54 | public int getLimit() { 55 | return limit; 56 | } 57 | 58 | public void setLimit(int limit) { 59 | this.limit = limit; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/TUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | insert into T_USER (user_name, phone 11 | ) 12 | values (#{userName,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR} 13 | ) 14 | 15 | 16 | insert into T_USER 17 | 18 | 19 | id, 20 | 21 | 22 | user_name, 23 | 24 | 25 | phone, 26 | 27 | 28 | 29 | 30 | #{id,jdbcType=INTEGER}, 31 | 32 | 33 | #{userName,jdbcType=VARCHAR}, 34 | 35 | 36 | #{phone,jdbcType=VARCHAR}, 37 | 38 | 39 | 40 | 54 | -------------------------------------------------------------------------------- /src/test/java/git/yampery/cryptic/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic; 2 | 3 | import git.yampery.cryptic.common.QueryParams; 4 | import git.yampery.cryptic.common.SysException; 5 | import git.yampery.cryptic.cryptic.ADESUtils; 6 | import git.yampery.cryptic.pojo.TUser; 7 | import git.yampery.cryptic.service.UserService; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest 22 | public class ApplicationTests { 23 | 24 | @Resource private UserService userService; 25 | private static final Logger logger = LoggerFactory.getLogger(ApplicationTests.class); 26 | 27 | @Test 28 | public void contextLoads() { 29 | } 30 | 31 | /** 32 | * 生成AES加密秘钥 33 | */ 34 | @Test 35 | public void testGeneratorSalt() throws Exception { 36 | String salt = ADESUtils.generateAESKey(); 37 | System.out.println("秘钥: " + salt); 38 | } 39 | 40 | /** 41 | * 测试写入数据 42 | */ 43 | @Test 44 | public void testInsert() { 45 | TUser user = new TUser(); 46 | user.setPhone("18700000000"); 47 | user.setUserName("yampery"); 48 | try { 49 | userService.insert(user); 50 | } catch (SysException e) { 51 | System.err.println("insert user error"); 52 | e.printStackTrace(); 53 | } 54 | } 55 | 56 | /** 57 | * 测试选择数据 58 | */ 59 | @Test 60 | public void testSelect() { 61 | try { 62 | List users = userService.queryList(null); 63 | users.forEach(System.out::println); 64 | } catch (SysException e) { 65 | System.err.println("select user error"); 66 | e.printStackTrace(); 67 | } 68 | } 69 | 70 | /** 71 | * 测试携参查询 72 | */ 73 | @Test 74 | public void testSelectByParams() { 75 | try { 76 | Map map = new HashMap<>(); 77 | map.put("phone", "18700000000"); 78 | // 封装参数 79 | QueryParams params = new QueryParams(map); 80 | List users = userService.queryList(params); 81 | users.forEach(System.out::println); 82 | } catch (SysException e) { 83 | System.err.println("select user error"); 84 | e.printStackTrace(); 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/config/DruidConfig.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.alibaba.druid.support.http.StatViewServlet; 5 | import com.alibaba.druid.support.http.WebStatFilter; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 10 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.context.annotation.Primary; 14 | import org.springframework.context.annotation.PropertySource; 15 | 16 | import javax.sql.DataSource; 17 | import java.sql.SQLException; 18 | 19 | /** 20 | * @decription DruidConfig 21 | *

Druid连接池配置

22 | * @author Yampery 23 | * @date 2018/4/4 12:59 24 | */ 25 | @Configuration 26 | @PropertySource("classpath:jdbc.properties") 27 | public class DruidConfig { 28 | 29 | // private Logger logger = LoggerFactory.getLogger(getClass()); 30 | 31 | /** 32 | * 数据源 33 | * @return 34 | */ 35 | @Bean("dataSource") 36 | @Primary 37 | public DataSource druidDataSource() { 38 | DruidDataSource datasource = new DruidDataSource(); 39 | 40 | datasource.setUrl(this.dbUrl); 41 | datasource.setUsername(username); 42 | datasource.setPassword(password); 43 | datasource.setDriverClassName(driverClassName); 44 | datasource.setInitialSize(initialSize); 45 | datasource.setMinIdle(minIdle); 46 | datasource.setMaxActive(maxActive); 47 | datasource.setMaxWait(maxWait); 48 | datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 49 | datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 50 | datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); 51 | return datasource; 52 | } 53 | 54 | 55 | @Value("${jdbc.url}") 56 | private String dbUrl; 57 | @Value("${jdbc.username}") 58 | private String username; 59 | @Value("${jdbc.password}") 60 | private String password; 61 | @Value("${jdbc.driver}") 62 | private String driverClassName; 63 | @Value("${jdbc.pool.initialSize}") 64 | private int initialSize; 65 | @Value("${jdbc.pool.minIdle}") 66 | private int minIdle; 67 | @Value("${jdbc.pool.maxActive}") 68 | private int maxActive; 69 | @Value("${jdbc.pool.maxWait}") 70 | private int maxWait; 71 | @Value("${jdbc.pool.timeBetweenEvictionRunsMillis}") 72 | private int timeBetweenEvictionRunsMillis; 73 | @Value("${jdbc.pool.minEvictableIdleTimeMillis}") 74 | private int minEvictableIdleTimeMillis; 75 | @Value("${jdbc.pool.maxPoolPreparedStatementPerConnectionSize}") 76 | private int maxPoolPreparedStatementPerConnectionSize; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/cryptic/CryptPojo.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.cryptic; 2 | 3 | import git.yampery.cryptic.annotation.DecryptField; 4 | import git.yampery.cryptic.annotation.EncryptField; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | /** 10 | * @decription CryptPojo 11 | *

该类是加密对象。需要特殊对一个对象处理,可以采用安全克隆加密方法 12 | * 其子类可以通过调用encryptSelf()方法实现自加密,返回子类对象; 13 | * 调用decryptSelf()实现自解密,返回解密后的子类对象; 14 | * 上述加密方法encryptSelf对注解{@link EncryptField}字段有效; 15 | * 上述解密方法decryptSelf对注解{@link DecryptField}字段有效。

16 | * @author Yampery 17 | * @date 2018/4/4 13:36 18 | */ 19 | public class CryptPojo implements Cloneable, ADESInterface { 20 | 21 | /** 22 | * 拷贝一个对象,并对新对象进行加密 23 | * 该方法主要用在日志打印上,可防止原对象被加密而影响程序执行 24 | * @param 25 | * @return 26 | */ 27 | public T cloneAndEncrypt() { 28 | T cloneT = null; 29 | try { 30 | cloneT = (T) this.clone(); 31 | } catch (CloneNotSupportedException e) { 32 | e.printStackTrace(); 33 | return null; 34 | } 35 | if(cloneT !=null) 36 | return cloneT.encryptSelf(); 37 | throw new RuntimeException("拷贝对象异常"); 38 | } 39 | /** 40 | * 重写clone方法 41 | * @return 42 | * @throws CloneNotSupportedException 43 | */ 44 | @Override 45 | protected Object clone() throws CloneNotSupportedException { 46 | try { 47 | return super.clone(); 48 | } catch (CloneNotSupportedException e) { 49 | e.printStackTrace(); 50 | return null; 51 | } 52 | } 53 | 54 | @Override 55 | public T encryptSelf() { 56 | Field[] declaredFields = this.getClass().getDeclaredFields(); 57 | try { 58 | if (declaredFields != null && declaredFields.length > 0) { 59 | for (Field field : declaredFields) { 60 | if (field.isAnnotationPresent(EncryptField.class) && field.getType().toString().endsWith("String")) { 61 | field.setAccessible(true); 62 | String fieldValue = (String) field.get(this); 63 | if (StringUtils.isNotEmpty(fieldValue)) { 64 | field.set(this, ADESUtils.getInstance().encrypt(fieldValue)); 65 | } 66 | field.setAccessible(false); 67 | } 68 | } 69 | } 70 | } catch (IllegalAccessException e) { 71 | throw new RuntimeException(e); 72 | } 73 | return (T) this; 74 | } 75 | 76 | @Override 77 | public T decryptSelf() { 78 | Field[] declaredFields = this.getClass().getDeclaredFields(); 79 | try { 80 | if (declaredFields != null && declaredFields.length > 0) { 81 | for (Field field : declaredFields) { 82 | if (field.isAnnotationPresent(DecryptField.class) && field.getType().toString().endsWith("String")) { 83 | field.setAccessible(true); 84 | String fieldValue = (String)field.get(this); 85 | if(StringUtils.isNotEmpty(fieldValue)) { 86 | field.set(this, ADESUtils.getInstance().decrypt(fieldValue)); 87 | } 88 | } 89 | } 90 | } 91 | } catch (IllegalAccessException e) { 92 | throw new RuntimeException(e); 93 | } 94 | return (T) this; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/interceptor/DBInterceptor.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.interceptor; 2 | 3 | import git.yampery.cryptic.annotation.DecryptField; 4 | import git.yampery.cryptic.cryptic.CryptPojoUtils; 5 | import org.apache.commons.lang.StringUtils; 6 | import org.apache.ibatis.executor.Executor; 7 | import org.apache.ibatis.mapping.BoundSql; 8 | import org.apache.ibatis.mapping.MappedStatement; 9 | import org.apache.ibatis.plugin.*; 10 | import org.apache.ibatis.session.ResultHandler; 11 | import org.apache.ibatis.session.RowBounds; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.stereotype.Component; 16 | 17 | import java.lang.reflect.Field; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Properties; 21 | 22 | /** 23 | * @decription DBInterceptor 24 | *

实现Mybatis拦截器,用于拦截修改,插入和返回需要加密或者解密的对象

25 | * @author Yampery 26 | * @date 2018/4/4 14:17 27 | */ 28 | @Intercepts({ 29 | @Signature(type=Executor.class,method="update",args={MappedStatement.class,Object.class}), 30 | @Signature(type=Executor.class,method="query",args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}) 31 | }) 32 | @Component 33 | public class DBInterceptor implements Interceptor { 34 | private final Logger logger = LoggerFactory.getLogger(DBInterceptor.class); 35 | @Value("${sys.aes.switch}") private String CRYPTIC_SWITCH; 36 | @Override 37 | public Object intercept(Invocation invocation) throws Throwable { 38 | MappedStatement statement = (MappedStatement) invocation.getArgs()[0]; 39 | String methodName = invocation.getMethod().getName(); 40 | Object parameter = invocation.getArgs()[1]; 41 | BoundSql sql = statement.getBoundSql(parameter); 42 | logger.info("sql is: {}", sql.getSql()); 43 | 44 | /** 45 | * @TODO 处理查询 46 | */ 47 | if (StringUtils.equalsIgnoreCase("query", methodName)) { 48 | /** 49 | * 在这里可以处理查询参数,如传递的参数为明文,要按照密文查询 50 | * 本文选择使用同一参数封装处理方案{@link git.yampery.cryptic.common.QueryParams} 51 | */ 52 | } 53 | /** 54 | * 拦截批量插入操作不仅繁琐,而且为了通用逐一通过反射加密不妥 55 | * 如果有批量操作,最好在传递参数之前,向list中添加之前就加密 56 | */ 57 | if (!"0".equals(CRYPTIC_SWITCH)) { 58 | if (StringUtils.equalsIgnoreCase("update", methodName) 59 | || StringUtils.equalsIgnoreCase("insert", methodName)) { 60 | CryptPojoUtils.encryptField(parameter); 61 | } 62 | } 63 | 64 | Object returnValue = invocation.proceed(); 65 | 66 | try { 67 | if (!"0".equals(CRYPTIC_SWITCH)) { 68 | if (returnValue instanceof ArrayList) { 69 | List list = (ArrayList) returnValue; 70 | if (null == list || 1 > list.size()) 71 | return returnValue; 72 | Object obj = list.get(0); 73 | if (null == obj) // 这里虽然list不是空,但是返回字符串等有可能为空 74 | return returnValue; 75 | // 判断第一个对象是否有DecryptField注解 76 | Field[] fields = obj.getClass().getDeclaredFields(); 77 | int len; 78 | if (null != fields && 0 < (len = fields.length)) { 79 | // 标记是否有解密注解 80 | boolean isD = false; 81 | for (int i = 0; i < len; i++) { 82 | /** 83 | * 由于返回的是同一种类型列表,因此这里判断出来之后可以保存field的名称 84 | * 之后处理所有对象直接按照field名称查找Field从而改之即可 85 | * 有可能该类存在多个注解字段,所以需要保存到数组(项目中目前最多是2个) 86 | * @TODO 保存带DecryptField注解的字段名称到数组,按照名称获取字段并解密 87 | * */ 88 | if (fields[i].isAnnotationPresent(DecryptField.class)) { 89 | isD = true; 90 | break; 91 | } 92 | } /// for end ~ 93 | if (isD) // 将含有DecryptField注解的字段解密 94 | list.forEach(l -> CryptPojoUtils.decryptField(l)); 95 | } /// if end ~ 96 | } /// if end ~ 97 | } 98 | 99 | } catch (Exception e) { 100 | logger.info("抛出异常 ==> " + e.getMessage()); 101 | e.printStackTrace(); 102 | return returnValue; 103 | } 104 | return returnValue; 105 | } 106 | 107 | @Override 108 | public Object plugin(Object target) { 109 | return Plugin.wrap(target, this); 110 | } 111 | 112 | @Override 113 | public void setProperties(Properties properties) { 114 | // TODO Auto-generated method stub 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/cryptic/ADESUtils.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.cryptic; 2 | 3 | import org.apache.commons.codec.binary.Hex; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.crypto.Cipher; 9 | import javax.crypto.KeyGenerator; 10 | import javax.crypto.NoSuchPaddingException; 11 | import javax.crypto.SecretKey; 12 | import javax.crypto.spec.SecretKeySpec; 13 | import java.security.InvalidKeyException; 14 | import java.security.NoSuchAlgorithmException; 15 | 16 | /** 17 | * @decription ADESUtils 18 | *

字段加解密,使用MySql AES算法

19 | * @author Yampery 20 | * @date 2018/4/4 13:10 21 | */ 22 | @Component 23 | public class ADESUtils { 24 | private static final String ENCRYPT_TYPE = "AES"; 25 | private static final String ENCODING = "UTF-8"; 26 | 27 | // 密盐 28 | private static String aesSalt; 29 | private static ADESUtils adesUtils; 30 | private static Cipher encryptCipher; // 加密cipher 31 | private static Cipher decryptChipher; // 解密chipher 32 | 33 | // 加解密开关,从配置获取 34 | private static String CRYPTIC_SWITCH; 35 | /** 36 | * 从配置中获取秘钥 37 | * :默认值填写自己生成的秘钥 38 | * @param key 39 | */ 40 | @Value("${sys.aes.salt:0}") 41 | public void setAESSalt(String key){ 42 | ADESUtils.aesSalt = key; 43 | } 44 | 45 | /** 46 | * 获取开关 47 | * 默认为不加密 48 | * @param val 49 | */ 50 | @Value("${sys.aes.switch:0}") 51 | public void setCrypticSwitch(String val) { 52 | ADESUtils.CRYPTIC_SWITCH = val; 53 | } 54 | /** 55 | * encryptCipher、decryptChipher初始化 56 | */ 57 | public static void init(){ 58 | try { 59 | encryptCipher = Cipher.getInstance(ENCRYPT_TYPE); 60 | decryptChipher = Cipher.getInstance(ENCRYPT_TYPE); 61 | encryptCipher.init(Cipher.ENCRYPT_MODE, generateMySQLAESKey(aesSalt)); 62 | decryptChipher.init(Cipher.DECRYPT_MODE, generateMySQLAESKey(aesSalt)); 63 | } catch (InvalidKeyException e) { 64 | throw new RuntimeException(e); 65 | } catch (NoSuchAlgorithmException e) { 66 | throw new RuntimeException(e); 67 | } catch (NoSuchPaddingException e) { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | 72 | private ADESUtils() { } 73 | 74 | /** 75 | * 获取单例 76 | * @return 77 | */ 78 | public static ADESUtils getInstance(){ 79 | if(adesUtils == null){ 80 | // 当需要创建的时候在加锁 81 | synchronized(ADESUtils.class) { 82 | if (adesUtils == null) { 83 | adesUtils = new ADESUtils(); 84 | init(); 85 | } 86 | } 87 | } 88 | return adesUtils; 89 | } 90 | 91 | /** 92 | * 对明文加密 93 | * @param pString 94 | * @return 95 | */ 96 | public String encrypt(String pString) { 97 | 98 | if (StringUtils.isBlank(pString) || StringUtils.equals("0", CRYPTIC_SWITCH)) 99 | return StringUtils.trimToEmpty(pString); 100 | try{ 101 | return new String(Hex.encodeHex(encryptCipher.doFinal(pString.getBytes(ENCODING)))).toUpperCase(); 102 | } catch (Exception e) { 103 | e.printStackTrace(); 104 | return pString; 105 | } 106 | } 107 | 108 | /** 109 | * 对密文解密 110 | * @param eString 111 | * @return 112 | */ 113 | public String decrypt(String eString) { 114 | if (StringUtils.isBlank(eString) || StringUtils.equals("0", CRYPTIC_SWITCH)) 115 | return StringUtils.trimToEmpty(eString); 116 | try { 117 | return new String(decryptChipher.doFinal(Hex.decodeHex(eString.toCharArray()))); 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | return eString; 121 | } 122 | } 123 | /** 124 | * 产生mysql-aes_encrypt 125 | * @param key 加密的密盐 126 | * @return 127 | */ 128 | public static SecretKeySpec generateMySQLAESKey(final String key) { 129 | try { 130 | final byte[] finalKey = new byte[16]; 131 | int i = 0; 132 | for(byte b : Hex.decodeHex(key.toCharArray())) 133 | finalKey[i++ % 16] ^= b; 134 | return new SecretKeySpec(finalKey, "AES"); 135 | } catch(Exception e) { 136 | throw new RuntimeException(e); 137 | } 138 | } 139 | 140 | /** 141 | * 生成秘钥(128位) 142 | * @return 143 | * @throws Exception 144 | */ 145 | public static String generateAESKey() throws Exception{ 146 | //实例化 147 | KeyGenerator kgen = KeyGenerator.getInstance("AES"); 148 | //设置密钥长度 149 | kgen.init(128); 150 | //生成密钥 151 | SecretKey skey = kgen.generateKey(); 152 | // 转为16进制字串 153 | String key = new String(Hex.encodeHex(skey.getEncoded())); 154 | //返回密钥的16进制字串 155 | return key.toUpperCase(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/git/yampery/cryptic/cryptic/CryptPojoUtils.java: -------------------------------------------------------------------------------- 1 | package git.yampery.cryptic.cryptic; 2 | 3 | import git.yampery.cryptic.annotation.DecryptField; 4 | import git.yampery.cryptic.annotation.EncryptField; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | /** 10 | * @decription CryptPojoUtils 11 | *

对象加解密工具 12 | * 通过反射,对参数对象中包含指定注解的字段进行加解密。 13 | * 调用encrypt(T t)方法实现加密,返回加密后的对象; 14 | * 调用decrypt(T t)实现解密,返回解密后的对象; 15 | * encrypt对注解{@link EncryptField}字段有效; 16 | * decrypt对注解{@link DecryptField}字段有效。

17 | * @author Yampery 18 | * @date 2017/10/24 13:36 19 | */ 20 | public class CryptPojoUtils { 21 | 22 | /** 23 | * 对对象t加密 24 | * @param t 25 | * @param 26 | * @return 27 | */ 28 | public static T encrypt(T t) { 29 | Field[] declaredFields = t.getClass().getDeclaredFields(); 30 | try { 31 | if (declaredFields != null && declaredFields.length > 0) { 32 | for (Field field : declaredFields) { 33 | if (field.isAnnotationPresent(EncryptField.class) && field.getType().toString().endsWith("String")) { 34 | field.setAccessible(true); 35 | String fieldValue = (String) field.get(t); 36 | if (StringUtils.isNotEmpty(fieldValue)) { 37 | field.set(t, ADESUtils.getInstance().encrypt(fieldValue)); 38 | } 39 | field.setAccessible(false); 40 | } 41 | } 42 | } 43 | } catch (IllegalAccessException e) { 44 | throw new RuntimeException(e); 45 | } 46 | return t; 47 | } 48 | 49 | /** 50 | * 对象解密 51 | * @param t 52 | * @param 53 | * @return 54 | */ 55 | public static T decrypt(T t) { 56 | Field[] declaredFields = t.getClass().getDeclaredFields(); 57 | try { 58 | if (declaredFields != null && declaredFields.length > 0) { 59 | for (Field field : declaredFields) { 60 | if (field.isAnnotationPresent(DecryptField.class) && field.getType().toString().endsWith("String")) { 61 | field.setAccessible(true); 62 | String fieldValue = (String)field.get(t); 63 | if(StringUtils.isNotEmpty(fieldValue)) { 64 | field.set(t, ADESUtils.getInstance().decrypt(fieldValue)); 65 | } 66 | } 67 | } 68 | } 69 | } catch (IllegalAccessException e) { 70 | throw new RuntimeException(e); 71 | } 72 | return t; 73 | } 74 | 75 | /** 76 | * 对含注解字段解密 77 | * @param t 78 | * @param 79 | */ 80 | public static void decryptField(T t) { 81 | Field[] declaredFields = t.getClass().getDeclaredFields(); 82 | try { 83 | if (declaredFields != null && declaredFields.length > 0) { 84 | for (Field field : declaredFields) { 85 | if (field.isAnnotationPresent(DecryptField.class) && field.getType().toString().endsWith("String")) { 86 | field.setAccessible(true); 87 | String fieldValue = (String)field.get(t); 88 | if(StringUtils.isNotEmpty(fieldValue)) { 89 | field.set(t, ADESUtils.getInstance().decrypt(fieldValue)); 90 | } 91 | } 92 | } 93 | } 94 | } catch (IllegalAccessException e) { 95 | throw new RuntimeException(e); 96 | } 97 | // return t; 98 | } 99 | 100 | /** 101 | * 对含注解字段加密 102 | * @param t 103 | * @param 104 | */ 105 | public static void encryptField(T t) { 106 | Field[] declaredFields = t.getClass().getDeclaredFields(); 107 | try { 108 | if (declaredFields != null && declaredFields.length > 0) { 109 | for (Field field : declaredFields) { 110 | if (field.isAnnotationPresent(EncryptField.class) && field.getType().toString().endsWith("String")) { 111 | field.setAccessible(true); 112 | String fieldValue = (String)field.get(t); 113 | if(StringUtils.isNotEmpty(fieldValue)) { 114 | field.set(t, ADESUtils.getInstance().encrypt(fieldValue)); 115 | } 116 | } 117 | } 118 | } 119 | } catch (IllegalAccessException e) { 120 | throw new RuntimeException(e); 121 | } 122 | } 123 | 124 | /** 125 | * 隐藏号码中间4位 126 | * @param t 127 | * @param 128 | */ 129 | public static void hidePhone(T t) { 130 | Field[] declaredFields = t.getClass().getDeclaredFields(); 131 | try { 132 | if (declaredFields != null && declaredFields.length > 0) { 133 | for (Field field : declaredFields) { 134 | if (field.isAnnotationPresent(DecryptField.class) && field.getType().toString().endsWith("String")) { 135 | field.setAccessible(true); 136 | String fieldValue = (String)field.get(t); 137 | if(StringUtils.isNotEmpty(fieldValue)) { 138 | // 暂时与解密注解共用一个注解,该注解隐藏手机号中间四位 139 | field.set(t, StringUtils.overlay(fieldValue, "****", 3, 7)); 140 | } 141 | } 142 | } 143 | } 144 | } catch (IllegalAccessException e) { 145 | throw new RuntimeException(e); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | --------------------------------------------------------------------------------