From b6400c34b5d878abd60ba7717cfc7d8d123ba7db Mon Sep 17 00:00:00 2001
From: xuhy <3313886187@qq.com>
Date: 星期三, 25 十二月 2024 11:31:45 +0800
Subject: [PATCH] 司机端

---
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java                                   |   29 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java |  109 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java                             |  665 ++
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java                                   |   73 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java                                |  206 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java                                 |   57 
 DriverOKTravel/guns-core/src/main/resources/default-config.properties                                               |   36 
 DriverOKTravel/guns-core/src/main/resources/META-INF/spring.factories                                               |    6 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java                      |   19 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java                                 |   50 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java                                    |   39 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java           |  214 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java      |   80 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java                          |  122 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java     |   32 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java                  |   20 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl                           |   41 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java                                 |   32 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java        |  126 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java       |   30 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java                             |   50 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java |   64 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java             |   20 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java                                      |  170 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java               |   35 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl                             |    3 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java                |   87 
 DriverOKTravel/guns-rest/pom.xml                                                                                    |   56 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java               |   16 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java                                  | 1370 ++++++
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java        |   37 
 DriverOKTravel/guns-rest/src/main/resources/application.yml                                                         |   40 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java                                   |  239 +
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java        |   70 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java                    |  297 +
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java    |  115 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java                   |   51 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java         |   41 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java                                     |   38 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java                                |   20 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java           |   70 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl                             |   98 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl                                |   38 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java      |   97 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java                               |   22 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java        |   31 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java          |   35 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java                               |   38 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java              |   18 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java                   |   26 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java               |  194 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java                          |   49 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java     |   81 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java                                        |   11 
 DriverOKTravel/guns-generator/pom.xml                                                                               |   35 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java                                  |  114 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java                     |   59 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl                          |   96 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java                                   |   23 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java              |   30 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java              |   74 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java                           |  801 +++
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java                              |   16 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java                                |  206 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java                                |   67 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java                  |  127 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java                       |   22 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java         |   35 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java                                    |   89 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java                                  |   59 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java                          |   62 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java                                   |  250 +
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java           |   91 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java                                 |   41 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java               |   24 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java                  |   82 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java                                 |  508 ++
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java                |   18 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java                                  |   79 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java                                    |   35 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java                             |   50 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java             |   77 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java                                   |  582 ++
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java               |   55 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java                                           |  108 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java                                  |  254 +
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java              |   45 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java                        |   25 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java               |   55 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl                            |   41 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java                    |   81 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java                             |   58 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java                                    | 1060 ++++
 DriverOKTravel/guns-core/pom.xml                                                                                    |  110 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java                          |   26 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java                            |   86 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java                                     |   65 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java               |  217 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java                 |   71 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java                      |   28 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java                  |   66 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java          |   44 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java              |   45 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java                         |   36 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java              |   38 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java                        |   25 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java                         |   65 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java                |   37 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java                        |   46 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java                       |  149 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java            |   22 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java                            |   15 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java                             |   12 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java                                 |  195 
 DriverOKTravel/guns-rest/db/guns_rest.sql                                                                           |   38 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java                                    |   40 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java                                   |   42 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java |   24 
 DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl                                  |  102 
 DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java                                    |  294 +
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java                  |  140 
 DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java                    |  203 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java                |   37 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml        |   11 
 DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java                                |   30 
 125 files changed, 13,506 insertions(+), 0 deletions(-)

diff --git a/DriverOKTravel/guns-core/pom.xml b/DriverOKTravel/guns-core/pom.xml
new file mode 100644
index 0000000..5051270
--- /dev/null
+++ b/DriverOKTravel/guns-core/pom.xml
@@ -0,0 +1,110 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.stylefeng</groupId>
+        <artifactId>guns-parent</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>guns-core</artifactId>
+    <packaging>jar</packaging>
+
+    <name>guns-core</name>
+    <url>http://maven.apache.org</url>
+
+    <dependencies>
+
+        <!--通用依赖-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatisplus-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!--web-->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!--aop-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!--二维码-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!--缓存-->
+        <dependency>
+            <groupId>org.ehcache</groupId>
+            <artifactId>ehcache</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-cache</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.ehcache</groupId>
+            <artifactId>ehcache-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+    </build>
+</project>
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java
new file mode 100644
index 0000000..c96eb96
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java
@@ -0,0 +1,11 @@
+package com.stylefeng.guns.core;
+
+/**
+ * 此类用来获取core模块的包路径
+ *
+ * @author fengshuonan
+ * @Date 2017/12/5 下午12:44
+ */
+public class CoreFlag {
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java
new file mode 100644
index 0000000..cbc06c3
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java
@@ -0,0 +1,45 @@
+package com.stylefeng.guns.core.aop;
+
+import com.stylefeng.guns.core.base.tips.ErrorTip;
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.core.exception.GunsExceptionEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
+ *
+ * @author fengshuonan
+ * @date 2016年11月12日 下午3:19:56
+ */
+public class BaseControllerExceptionHandler {
+
+    private Logger log = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 拦截业务异常
+     */
+    @ExceptionHandler(GunsException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ResponseBody
+    public ErrorTip notFount(GunsException e) {
+        log.error("业务异常:", e);
+        return new ErrorTip(e.getCode(), e.getMessage());
+    }
+
+    /**
+     * 拦截未知的运行时异常
+     */
+    @ExceptionHandler(RuntimeException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ResponseBody
+    public ErrorTip notFount(RuntimeException e) {
+        log.error("运行时异常:", e);
+        return new ErrorTip(GunsExceptionEnum.SERVER_ERROR.getCode(), GunsExceptionEnum.SERVER_ERROR.getMessage());
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java
new file mode 100644
index 0000000..9b17a14
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java
@@ -0,0 +1,127 @@
+package com.stylefeng.guns.core.base.controller;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.stylefeng.guns.core.base.tips.SuccessTip;
+import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
+import com.stylefeng.guns.core.page.PageInfoBT;
+import com.stylefeng.guns.core.support.HttpKit;
+import com.stylefeng.guns.core.util.FileUtil;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.UnsupportedEncodingException;
+
+public class BaseController {
+
+    protected static String SUCCESS = "SUCCESS";
+    protected static String ERROR = "ERROR";
+
+    protected static String REDIRECT = "redirect:";
+    protected static String FORWARD = "forward:";
+
+    protected static SuccessTip SUCCESS_TIP = new SuccessTip();
+
+    protected HttpServletRequest getHttpServletRequest() {
+        return HttpKit.getRequest();
+    }
+
+    protected HttpServletResponse getHttpServletResponse() {
+        return HttpKit.getResponse();
+    }
+
+    protected HttpSession getSession() {
+        return HttpKit.getRequest().getSession();
+    }
+
+    protected HttpSession getSession(Boolean flag) {
+        return HttpKit.getRequest().getSession(flag);
+    }
+
+    protected String getPara(String name) {
+        return HttpKit.getRequest().getParameter(name);
+    }
+
+    protected void setAttr(String name, Object value) {
+        HttpKit.getRequest().setAttribute(name, value);
+    }
+
+    protected Integer getSystemInvokCount() {
+        return (Integer) this.getHttpServletRequest().getServletContext().getAttribute("systemCount");
+    }
+
+    /**
+     * 把service层的分页信息,封装为bootstrap table通用的分页封装
+     */
+    protected <T> PageInfoBT<T> packForBT(Page<T> page) {
+        return new PageInfoBT<T>(page);
+    }
+
+    /**
+     * 包装一个list,让list增加额外属性
+     */
+    protected Object warpObject(BaseControllerWarpper warpper) {
+        return warpper.warp();
+    }
+
+    /**
+     * 删除cookie
+     */
+    protected void deleteCookieByName(String cookieName) {
+        Cookie[] cookies = this.getHttpServletRequest().getCookies();
+        for (Cookie cookie : cookies) {
+            if (cookie.getName().equals(cookieName)) {
+                Cookie temp = new Cookie(cookie.getName(), "");
+                temp.setMaxAge(0);
+                this.getHttpServletResponse().addCookie(temp);
+            }
+        }
+    }
+
+    /**
+     * 删除所有cookie
+     */
+    protected void deleteAllCookie() {
+        Cookie[] cookies = this.getHttpServletRequest().getCookies();
+        for (Cookie cookie : cookies) {
+            Cookie temp = new Cookie(cookie.getName(), "");
+            temp.setMaxAge(0);
+            this.getHttpServletResponse().addCookie(temp);
+        }
+    }
+
+    /**
+     * 返回前台文件流
+     *
+     * @author fengshuonan
+     * @date 2017年2月28日 下午2:53:19
+     */
+    protected ResponseEntity<byte[]> renderFile(String fileName, String filePath) {
+        byte[] bytes = FileUtil.toByteArray(filePath);
+        return renderFile(fileName, bytes);
+    }
+
+    /**
+     * 返回前台文件流
+     *
+     * @author fengshuonan
+     * @date 2017年2月28日 下午2:53:19
+     */
+    protected ResponseEntity<byte[]> renderFile(String fileName, byte[] fileBytes) {
+        String dfileName = null;
+        try {
+            dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+        headers.setContentDispositionFormData("attachment", dfileName);
+        return new ResponseEntity<byte[]>(fileBytes, headers, HttpStatus.CREATED);
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java
new file mode 100644
index 0000000..1285ada
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java
@@ -0,0 +1,37 @@
+package com.stylefeng.guns.core.base.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 全局的控制器
+ *
+ * @author fengshuonan
+ * @date 2016年11月13日 下午11:04:45
+ */
+@Controller
+@RequestMapping("/global")
+public class GlobalController {
+
+    /**
+     * 跳转到404页面
+     *
+     * @author fengshuonan
+     */
+    @RequestMapping(path = "/error")
+    public String errorPage() {
+        return "/404.html";
+    }
+
+    /**
+     * 跳转到session超时页面
+     *
+     * @author fengshuonan
+     */
+    @RequestMapping(path = "/sessionError")
+    public String errorPageInfo(Model model) {
+        model.addAttribute("tips", "session超时");
+        return "/login.html";
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java
new file mode 100644
index 0000000..42a6edc
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java
@@ -0,0 +1,26 @@
+package com.stylefeng.guns.core.base.controller;
+
+import org.springframework.web.servlet.View;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * 错误页面的默认跳转(例如请求404的时候,默认走这个视图解析器)
+ *
+ * @author fengshuonan
+ * @date 2017-05-21 11:34
+ */
+public class GunsErrorView implements View {
+
+    @Override
+    public String getContentType() {
+        return "text/html";
+    }
+
+    @Override
+    public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
+        httpServletRequest.getRequestDispatcher("/global/error").forward(httpServletRequest, httpServletResponse);
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java
new file mode 100644
index 0000000..8744571
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java
@@ -0,0 +1,16 @@
+package com.stylefeng.guns.core.base.tips;
+
+/**
+ * 返回给前台的错误提示
+ *
+ * @author fengshuonan
+ * @date 2016年11月12日 下午5:05:22
+ */
+public class ErrorTip extends Tip {
+
+    public ErrorTip(int code, String message) {
+        super();
+        this.code = code;
+        this.message = message;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java
new file mode 100644
index 0000000..69e5766
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java
@@ -0,0 +1,15 @@
+package com.stylefeng.guns.core.base.tips;
+
+/**
+ * 返回给前台的成功提示
+ *
+ * @author fengshuonan
+ * @date 2016年11月12日 下午5:05:22
+ */
+public class SuccessTip extends Tip {
+	
+	public SuccessTip(){
+		super.code = 200;
+		super.message = "操作成功";
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java
new file mode 100644
index 0000000..f380904
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java
@@ -0,0 +1,29 @@
+package com.stylefeng.guns.core.base.tips;
+
+/**
+ * 返回给前台的提示(最终转化为json形式)
+ *
+ * @author fengshuonan
+ * @Date 2017年1月11日 下午11:58:00
+ */
+public abstract class Tip {
+
+    protected int code;
+    protected String message;
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java
new file mode 100644
index 0000000..e25afb4
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java
@@ -0,0 +1,38 @@
+package com.stylefeng.guns.core.base.warpper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 控制器查询结果的包装类基类
+ *
+ * @author fengshuonan
+ * @date 2017年2月13日 下午10:49:36
+ */
+public abstract class BaseControllerWarpper {
+
+    public Object obj = null;
+
+    public BaseControllerWarpper(Object obj) {
+        this.obj = obj;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Object warp() {
+        if (this.obj instanceof List) {
+            List<Map<String, Object>> list = (List<Map<String, Object>>) this.obj;
+            for (Map<String, Object> map : list) {
+                warpTheMap(map);
+            }
+            return list;
+        } else if (this.obj instanceof Map) {
+            Map<String, Object> map = (Map<String, Object>) this.obj;
+            warpTheMap(map);
+            return map;
+        } else {
+            return this.obj;
+        }
+    }
+
+    protected abstract void warpTheMap(Map<String, Object> map);
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java
new file mode 100644
index 0000000..ee58e93
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.cache;
+
+
+/**
+ * 缓存工厂基类
+ */
+public abstract class BaseCacheFactory implements ICache {
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String cacheName, Object key, ILoader iLoader) {
+		Object data = get(cacheName, key);
+		if (data == null) {
+			data = iLoader.load();
+			put(cacheName, key, data);
+		}
+		return (T) data;
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass) {
+		Object data = get(cacheName, key);
+		if (data == null) {
+			try {
+				ILoader dataLoader = iLoaderClass.newInstance();
+				data = dataLoader.load();
+				put(cacheName, key, data);
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			}
+		}
+		return (T) data;
+	}
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java
new file mode 100644
index 0000000..e860c53
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.stylefeng.guns.core.cache;
+
+import java.util.List;
+
+/**
+ * 缓存工具类
+ */
+public class CacheKit {
+	
+	private static ICache defaultCacheFactory = new EhcacheFactory();
+
+	public static void put(String cacheName, Object key, Object value) {
+		defaultCacheFactory.put(cacheName, key, value);
+	}
+	
+	public static <T> T get(String cacheName, Object key) {
+		return defaultCacheFactory.get(cacheName, key);
+	}
+	
+	@SuppressWarnings("rawtypes")
+	public static List getKeys(String cacheName) {
+		return defaultCacheFactory.getKeys(cacheName);
+	}
+	
+	public static void remove(String cacheName, Object key) {
+		defaultCacheFactory.remove(cacheName, key);
+	}
+	
+	public static void removeAll(String cacheName) {
+		defaultCacheFactory.removeAll(cacheName);
+	}
+	
+	public static <T> T get(String cacheName, Object key, ILoader iLoader) {
+		return defaultCacheFactory.get(cacheName, key, iLoader);
+	}
+	
+	public static <T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass) {
+		return defaultCacheFactory.get(cacheName, key, iLoaderClass);
+	}
+	
+}
+
+
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java
new file mode 100644
index 0000000..16cb2fc
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2011-2016, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.cache;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Ehcache缓存工厂
+ */
+public class EhcacheFactory extends BaseCacheFactory {
+	
+	private static CacheManager cacheManager;
+	private static volatile Object locker = new Object();
+	private static final Logger log = LoggerFactory.getLogger(EhcacheFactory.class);
+	
+	private static CacheManager getCacheManager() {
+		if (cacheManager == null) {
+			synchronized (EhcacheFactory.class) {
+				if (cacheManager == null) {
+					cacheManager = CacheManager.create();
+				}
+			}
+		}
+		return cacheManager;
+	}
+	
+	static Cache getOrAddCache(String cacheName) {
+		CacheManager cacheManager = getCacheManager();
+		Cache cache = cacheManager.getCache(cacheName);
+		if (cache == null) {
+			synchronized(locker) {
+				cache = cacheManager.getCache(cacheName);
+				if (cache == null) {
+					log.warn("无法找到缓存 [" + cacheName + "]的配置, 使用默认配置.");
+					cacheManager.addCacheIfAbsent(cacheName);
+					cache = cacheManager.getCache(cacheName);
+					log.debug("缓存 [" + cacheName + "] 启动.");
+				}
+			}
+		}
+		return cache;
+	}
+	
+	public void put(String cacheName, Object key, Object value) {
+		getOrAddCache(cacheName).put(new Element(key, value));
+	}
+	
+	@SuppressWarnings("unchecked")
+	public <T> T get(String cacheName, Object key) {
+		Element element = getOrAddCache(cacheName).get(key);
+		return element != null ? (T)element.getObjectValue() : null;
+	}
+	
+	@SuppressWarnings("rawtypes")
+	public List getKeys(String cacheName) {
+		return getOrAddCache(cacheName).getKeys();
+	}
+	
+	public void remove(String cacheName, Object key) {
+		getOrAddCache(cacheName).remove(key);
+	}
+	
+	public void removeAll(String cacheName) {
+		getOrAddCache(cacheName).removeAll();
+	}
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java
new file mode 100644
index 0000000..15d2f4c
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.cache;
+
+import java.util.List;
+
+/**
+ * 通用缓存接口
+ */
+public interface ICache {
+	
+	void put(String cacheName, Object key, Object value);
+	
+	<T> T get(String cacheName, Object key);
+	
+	@SuppressWarnings("rawtypes")
+	List getKeys(String cacheName);
+	
+	void remove(String cacheName, Object key);
+	
+	void removeAll(String cacheName);
+	
+	<T> T get(String cacheName, Object key, ILoader iLoader);
+	
+	<T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass);
+	
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java
new file mode 100644
index 0000000..ec94c33
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.cache;
+
+/**
+ *  数据重载
+ */
+public interface ILoader {
+	Object load();
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java
new file mode 100644
index 0000000..1819147
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java
@@ -0,0 +1,81 @@
+package com.stylefeng.guns.core.config;
+
+import com.alibaba.fastjson.serializer.SerializeConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.serializer.ToStringSerializer;
+import com.alibaba.fastjson.serializer.ValueFilter;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * fastjson配置类
+ *
+ * @author fengshuonan
+ * @date 2017-05-23 22:56
+ */
+@Configuration("defaultFastjsonConfig")
+@ConditionalOnClass(com.alibaba.fastjson.JSON.class)
+@ConditionalOnMissingBean(FastJsonHttpMessageConverter.class)
+@ConditionalOnWebApplication
+public class DefaultFastjsonConfig {
+
+    @Bean
+    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
+        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
+        converter.setFastJsonConfig(fastjsonConfig());
+        converter.setSupportedMediaTypes(getSupportedMediaType());
+        return converter;
+    }
+
+    /**
+     * fastjson的配置
+     */
+    public FastJsonConfig fastjsonConfig() {
+        FastJsonConfig fastJsonConfig = new FastJsonConfig();
+        fastJsonConfig.setSerializerFeatures(
+                SerializerFeature.PrettyFormat,
+                SerializerFeature.WriteMapNullValue,
+                SerializerFeature.WriteEnumUsingToString
+        );
+        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
+        ValueFilter valueFilter = new ValueFilter() {
+            public Object process(Object o, String s, Object o1) {
+                if (null == o1) {
+                    o1 = "";
+                }
+                return o1;
+            }
+        };
+        fastJsonConfig.setCharset(Charset.forName("utf-8"));
+        fastJsonConfig.setSerializeFilters(valueFilter);
+
+        //解决Long转json精度丢失的问题
+        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
+        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
+        serializeConfig.put(Long.class, ToStringSerializer.instance);
+        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
+        fastJsonConfig.setSerializeConfig(serializeConfig);
+        return fastJsonConfig;
+    }
+
+    /**
+     * 支持的mediaType类型
+     */
+    public List<MediaType> getSupportedMediaType() {
+        ArrayList<MediaType> mediaTypes = new ArrayList<>();
+        mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
+        return mediaTypes;
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java
new file mode 100644
index 0000000..f05c344
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java
@@ -0,0 +1,22 @@
+package com.stylefeng.guns.core.config;
+
+import com.stylefeng.guns.core.mutidatasource.aop.MultiSourceExAop;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 多数据源配置
+ *
+ * @author stylefeng
+ * @Date 2017/5/20 21:58
+ */
+@Configuration
+@ConditionalOnProperty(prefix = "guns", name = "muti-datasource-open", havingValue = "true")
+public class DefaultMultiConfig {
+
+    @Bean
+    public MultiSourceExAop multiSourceExAop() {
+        return new MultiSourceExAop();
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java
new file mode 100644
index 0000000..cd69e4a
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java
@@ -0,0 +1,25 @@
+package com.stylefeng.guns.core.config;
+
+import com.stylefeng.guns.core.config.properties.DruidProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ * 默认的配置
+ *
+ * @author fengshuonan
+ * @date 2018-01-07 12:33
+ */
+@Configuration
+@PropertySource("classpath:/default-config.properties")
+public class DefaultProperties {
+
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource")
+    public DruidProperties druidProperties() {
+        return new DruidProperties();
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java
new file mode 100644
index 0000000..f6abb63
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java
@@ -0,0 +1,65 @@
+package com.stylefeng.guns.core.config;
+
+import com.stylefeng.guns.core.base.controller.GunsErrorView;
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.core.exception.GunsExceptionEnum;
+import com.stylefeng.guns.core.util.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.support.GenericConversionService;
+import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+
+import javax.annotation.PostConstruct;
+import java.util.Date;
+import java.util.regex.Pattern;
+
+@Configuration
+public class DefaultWebConfig extends WebMvcConfigurationSupport {
+
+    @Autowired
+    private RequestMappingHandlerAdapter handlerAdapter;
+
+    @Bean("error")
+    public GunsErrorView error() {
+        return new GunsErrorView();
+    }
+
+    @PostConstruct
+    public void addConversionConfig() {
+        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) handlerAdapter.getWebBindingInitializer();
+        GenericConversionService genericConversionService = (GenericConversionService) initializer.getConversionService();
+        genericConversionService.addConverter(new StringToDateConverter());
+    }
+
+    public class StringToDateConverter implements Converter<String, Date> {
+
+        @Override
+        public Date convert(String dateString) {
+
+            String patternDate = "\\d{4}-\\d{1,2}-\\d{1,2}";
+            String patternTimeMinutes = "\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}";
+            String patternTimeSeconds = "\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}";
+
+            boolean dateFlag = Pattern.matches(patternDate, dateString);
+            boolean timeMinutesFlag = Pattern.matches(patternTimeMinutes, dateString);
+            boolean timeSecondsFlag = Pattern.matches(patternTimeSeconds, dateString);
+
+            if (dateFlag) {
+                return DateUtil.parseDate(dateString);
+            } else if (timeMinutesFlag) {
+                return DateUtil.parseTimeMinutes(dateString);
+            } else if (timeSecondsFlag) {
+                return DateUtil.parseTime(dateString);
+            } else {
+                throw new GunsException(GunsExceptionEnum.INVLIDE_DATE_STRING);
+            }
+
+        }
+    }
+}
+
+
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java
new file mode 100644
index 0000000..17ffd3a
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java
@@ -0,0 +1,217 @@
+package com.stylefeng.guns.core.config.properties;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+import java.sql.SQLException;
+
+/**
+ * <p>数据库数据源配置</p>
+ * <p>说明:这个类中包含了许多默认配置,若这些配置符合您的情况,您可以不用管,若不符合,建议不要修改本类,建议直接在"application.yml"中配置即可</p>
+ * @author stylefeng
+ * @date 2017-05-21 11:18
+ */
+public class DruidProperties {
+
+    private String url = "jdbc:mysql://127.0.0.1:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull";
+
+    private String username = "root";
+
+    private String password = "root";
+
+    private String driverClassName = "com.mysql.cj.jdbc.Driver";
+
+    private Integer initialSize = 2;
+
+    private Integer minIdle = 1;
+
+    private Integer maxActive = 20;
+
+    private Integer maxWait = 60000;
+
+    private Integer timeBetweenEvictionRunsMillis = 60000;
+
+    private Integer minEvictableIdleTimeMillis = 300000;
+
+    private String validationQuery = "SELECT 'x'";
+
+    private Boolean testWhileIdle = true;
+
+    private Boolean testOnBorrow = false;
+
+    private Boolean testOnReturn = false;
+
+    private Boolean poolPreparedStatements = true;
+
+    private Integer maxPoolPreparedStatementPerConnectionSize = 20;
+
+    private String filters = "stat";
+
+    public void config(DruidDataSource dataSource) {
+
+        dataSource.setUrl(url);
+        dataSource.setUsername(username);
+        dataSource.setPassword(password);
+
+        dataSource.setDriverClassName(driverClassName);
+        dataSource.setInitialSize(initialSize);     //定义初始连接数
+        dataSource.setMinIdle(minIdle);             //最小空闲
+        dataSource.setMaxActive(maxActive);         //定义最大连接数
+        dataSource.setMaxWait(maxWait);             //最长等待时间
+
+        // 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+
+        // 配置一个连接在池中最小生存的时间,单位是毫秒
+        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+        dataSource.setValidationQuery(validationQuery);
+        dataSource.setTestWhileIdle(testWhileIdle);
+        dataSource.setTestOnBorrow(testOnBorrow);
+        dataSource.setTestOnReturn(testOnReturn);
+
+        // 打开PSCache,并且指定每个连接上PSCache的大小
+        dataSource.setPoolPreparedStatements(poolPreparedStatements);
+        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
+
+        try {
+            dataSource.setFilters(filters);
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getDriverClassName() {
+        return driverClassName;
+    }
+
+    public void setDriverClassName(String driverClassName) {
+        this.driverClassName = driverClassName;
+    }
+
+    public Integer getInitialSize() {
+        return initialSize;
+    }
+
+    public void setInitialSize(Integer initialSize) {
+        this.initialSize = initialSize;
+    }
+
+    public Integer getMinIdle() {
+        return minIdle;
+    }
+
+    public void setMinIdle(Integer minIdle) {
+        this.minIdle = minIdle;
+    }
+
+    public Integer getMaxActive() {
+        return maxActive;
+    }
+
+    public void setMaxActive(Integer maxActive) {
+        this.maxActive = maxActive;
+    }
+
+    public Integer getMaxWait() {
+        return maxWait;
+    }
+
+    public void setMaxWait(Integer maxWait) {
+        this.maxWait = maxWait;
+    }
+
+    public Integer getTimeBetweenEvictionRunsMillis() {
+        return timeBetweenEvictionRunsMillis;
+    }
+
+    public void setTimeBetweenEvictionRunsMillis(Integer timeBetweenEvictionRunsMillis) {
+        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+    }
+
+    public Integer getMinEvictableIdleTimeMillis() {
+        return minEvictableIdleTimeMillis;
+    }
+
+    public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+    }
+
+    public String getValidationQuery() {
+        return validationQuery;
+    }
+
+    public void setValidationQuery(String validationQuery) {
+        this.validationQuery = validationQuery;
+    }
+
+    public Boolean getTestWhileIdle() {
+        return testWhileIdle;
+    }
+
+    public void setTestWhileIdle(Boolean testWhileIdle) {
+        this.testWhileIdle = testWhileIdle;
+    }
+
+    public Boolean getTestOnBorrow() {
+        return testOnBorrow;
+    }
+
+    public void setTestOnBorrow(Boolean testOnBorrow) {
+        this.testOnBorrow = testOnBorrow;
+    }
+
+    public Boolean getTestOnReturn() {
+        return testOnReturn;
+    }
+
+    public void setTestOnReturn(Boolean testOnReturn) {
+        this.testOnReturn = testOnReturn;
+    }
+
+    public Boolean getPoolPreparedStatements() {
+        return poolPreparedStatements;
+    }
+
+    public void setPoolPreparedStatements(Boolean poolPreparedStatements) {
+        this.poolPreparedStatements = poolPreparedStatements;
+    }
+
+    public Integer getMaxPoolPreparedStatementPerConnectionSize() {
+        return maxPoolPreparedStatementPerConnectionSize;
+    }
+
+    public void setMaxPoolPreparedStatementPerConnectionSize(Integer maxPoolPreparedStatementPerConnectionSize) {
+        this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
+    }
+
+    public String getFilters() {
+        return filters;
+    }
+
+    public void setFilters(String filters) {
+        this.filters = filters;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java
new file mode 100644
index 0000000..60fc761
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java
@@ -0,0 +1,80 @@
+package com.stylefeng.guns.core.config.properties;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+/**
+ * 默认多数据源配置
+ *
+ * @author fengshuonan
+ * @date 2017-08-16 10:02
+ */
+public class MutiDataSourceProperties {
+
+    private String url = "jdbc:mysql://127.0.0.1:3306/biz?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull";
+
+    private String username = "root";
+
+    private String password = "root";
+
+    private String driverClassName = "com.mysql.cj.jdbc.Driver";
+
+    private String validationQuery = "SELECT 'x'";
+
+    private String[] dataSourceNames = {"dataSourceGuns", "dataSourceBiz"};
+
+    public void config(DruidDataSource dataSource) {
+        dataSource.setUrl(url);
+        dataSource.setUsername(username);
+        dataSource.setPassword(password);
+        dataSource.setDriverClassName(driverClassName);
+        dataSource.setValidationQuery(validationQuery);
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getDriverClassName() {
+        return driverClassName;
+    }
+
+    public void setDriverClassName(String driverClassName) {
+        this.driverClassName = driverClassName;
+    }
+
+    public String getValidationQuery() {
+        return validationQuery;
+    }
+
+    public void setValidationQuery(String validationQuery) {
+        this.validationQuery = validationQuery;
+    }
+
+    public String[] getDataSourceNames() {
+        return dataSourceNames;
+    }
+
+    public void setDataSourceNames(String[] dataSourceNames) {
+        this.dataSourceNames = dataSourceNames;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java
new file mode 100644
index 0000000..f973103
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java
@@ -0,0 +1,50 @@
+package com.stylefeng.guns.core.constant;
+
+/**
+ * 是否是菜单的枚举
+ *
+ * @author fengshuonan
+ * @date 2017年6月1日22:50:11
+ */
+public enum IsMenu {
+
+    YES(1, "是"),
+    NO(0, "不是"); //不是菜单的是按钮
+
+    int code;
+    String message;
+
+    IsMenu(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public static String valueOf(Integer status) {
+        if (status == null) {
+            return "";
+        } else {
+            for (IsMenu s : IsMenu.values()) {
+                if (s.getCode() == status) {
+                    return s.getMessage();
+                }
+            }
+            return "";
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java
new file mode 100644
index 0000000..c43e362
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java
@@ -0,0 +1,50 @@
+package com.stylefeng.guns.core.datascope;
+
+import java.util.List;
+
+/**
+ * 数据范围
+ *
+ * @author fengshuonan
+ * @date 2017-07-23 22:19
+ */
+public class DataScope {
+
+    /**
+     * 限制范围的字段名称
+     */
+    private String scopeName = "deptid";
+
+    /**
+     * 具体的数据范围
+     */
+    private List<Integer> deptIds;
+
+    public DataScope() {
+    }
+
+    public DataScope(List<Integer> deptIds) {
+        this.deptIds = deptIds;
+    }
+
+    public DataScope(String scopeName, List<Integer> deptIds) {
+        this.scopeName = scopeName;
+        this.deptIds = deptIds;
+    }
+
+    public List<Integer> getDeptIds() {
+        return deptIds;
+    }
+
+    public void setDeptIds(List<Integer> deptIds) {
+        this.deptIds = deptIds;
+    }
+
+    public String getScopeName() {
+        return scopeName;
+    }
+
+    public void setScopeName(String scopeName) {
+        this.scopeName = scopeName;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java
new file mode 100644
index 0000000..5b1ed5b
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java
@@ -0,0 +1,82 @@
+package com.stylefeng.guns.core.datascope;
+
+
+import com.baomidou.mybatisplus.toolkit.PluginUtils;
+import com.stylefeng.guns.core.support.CollectionKit;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * 数据范围的拦截器
+ *
+ * @author fengshuonan
+ * @date 2017-07-23 21:26
+ */
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
+public class DataScopeInterceptor implements Interceptor {
+
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+        StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
+        MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
+        MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
+
+        if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
+            return invocation.proceed();
+        }
+
+        BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
+        String originalSql = boundSql.getSql();
+        Object parameterObject = boundSql.getParameterObject();
+
+        //查找参数中包含DataScope类型的参数
+        DataScope dataScope = findDataScopeObject(parameterObject);
+
+        if (dataScope == null) {
+            return invocation.proceed();
+        } else {
+            String scopeName = dataScope.getScopeName();
+            List<Integer> deptIds = dataScope.getDeptIds();
+            String join = CollectionKit.join(deptIds, ",");
+            originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
+            metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
+            return invocation.proceed();
+        }
+    }
+
+    /**
+     * 查找参数是否包括DataScope对象
+     */
+    public DataScope findDataScopeObject(Object parameterObj) {
+        if (parameterObj instanceof DataScope) {
+            return (DataScope) parameterObj;
+        } else if (parameterObj instanceof Map) {
+            for (Object val : ((Map<?, ?>) parameterObj).values()) {
+                if (val instanceof DataScope) {
+                    return (DataScope) val;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        return Plugin.wrap(target, this);
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java
new file mode 100644
index 0000000..12f2cf9
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java
@@ -0,0 +1,108 @@
+package com.stylefeng.guns.core.db;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.stylefeng.guns.core.util.SpringContextHolder;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <p>
+ * 便捷数据库操作类
+ * <p>
+ * <p>
+ * 本类的使用情景:
+ * <p>
+ * 1.单纯想创建现有的Mapper
+ * <p>例如:
+ * Db.getMapper(UserLoginMapper.class).selectById("14779707158513204");<br>
+ * <p>
+ *
+ * @author fengshuonan
+ * @date 2017年2月22日 下午8:07:17
+ */
+@SuppressWarnings("all")
+public class Db<T> {
+
+    /**
+     * 每个Db类,包装一个Mapper接口,这个clazz就是接口的类类型,例如UserMapper.class
+     */
+    private Class<T> clazz;
+
+    /**
+     * Mapper的父类接口
+     */
+    private BaseMapper<?> baseMapper;
+
+    /**
+     * 私有构造方法,不允许自己创建
+     */
+    private Db(Class clazz) {
+        this.clazz = clazz;
+        this.baseMapper = (BaseMapper<?>) SpringContextHolder.getBean(clazz);
+    }
+
+    /**
+     * <p>
+     * 创建包含指定mapper的Db工具类,使用本类的第一种用法
+     *
+     * @param clazz mapper的类类型
+     * @date 2017年2月22日 下午10:09:31
+     */
+    public static <T> Db<T> create(Class<T> clazz) {
+        return new Db<T>(clazz);
+    }
+
+    /**
+     * <p>
+     * 获取一个mapper的快捷方法
+     *
+     * @param clazz mapper类的类对象
+     * @date 2017年2月22日 下午10:31:35
+     */
+    public BaseMapper<?> getMapper() {
+        return this.baseMapper;
+    }
+
+    /**
+     * <p>
+     * 获取一个mapper的快捷方法
+     *
+     * @param clazz mapper类的类对象
+     * @date 2017年2月22日 下午10:31:35
+     */
+    public static <T> T getMapper(Class<T> clazz) {
+        return SpringContextHolder.getBean(clazz);
+    }
+
+    /**
+     * 通过一个条件获取数据库中的一条记录(会返回null)
+     *
+     * @date 2017年2月22日 下午10:45:51
+     */
+    public <E> E selectOneByCon(String condition, Object value) {
+        List<?> results = selectOneByConList(condition, value);
+        if (results != null && results.size() > 0) {
+            return (E) results.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 通过一个条件获取一堆记录(会返回null)
+     *
+     * @date 2017年2月22日 下午10:45:51
+     */
+    public <E> List<E> selectOneByConList(String condition, Object value) {
+        HashMap<String, Object> conditionMap = new HashMap<String, Object>();
+        conditionMap.put(condition, value);
+
+        List<E> results = (List<E>) this.baseMapper.selectByMap(conditionMap);
+        if (results == null || results.size() == 0) {
+            return null;
+        } else {
+            return results;
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java
new file mode 100644
index 0000000..2cdfcb0
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java
@@ -0,0 +1,36 @@
+package com.stylefeng.guns.core.exception;
+
+/**
+ * 封装guns的异常
+ *
+ * @author fengshuonan
+ * @Date 2017/12/28 下午10:32
+ */
+public class GunsException extends RuntimeException {
+
+    private Integer code;
+
+    private String message;
+
+    public GunsException(ServiceExceptionEnum serviceExceptionEnum) {
+        this.code = serviceExceptionEnum.getCode();
+        this.message = serviceExceptionEnum.getMessage();
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java
new file mode 100644
index 0000000..8a0765f
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java
@@ -0,0 +1,59 @@
+package com.stylefeng.guns.core.exception;
+
+/**
+ * Guns异常枚举
+ *
+ * @author fengshuonan
+ * @Date 2017/12/28 下午10:33
+ */
+public enum GunsExceptionEnum implements ServiceExceptionEnum {
+
+    /**
+     * 其他
+     */
+    INVLIDE_DATE_STRING(400, "输入日期格式不对"),
+
+    /**
+     * 其他
+     */
+    WRITE_ERROR(500, "渲染界面错误"),
+
+    /**
+     * 文件上传
+     */
+    FILE_READING_ERROR(400, "FILE_READING_ERROR!"),
+    FILE_NOT_FOUND(400, "FILE_NOT_FOUND!"),
+
+    /**
+     * 错误的请求
+     */
+    REQUEST_NULL(400, "请求有错误"),
+    SERVER_ERROR(500, "服务器异常");
+
+    GunsExceptionEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    private Integer code;
+
+    private String message;
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java
new file mode 100644
index 0000000..80531be
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java
@@ -0,0 +1,20 @@
+package com.stylefeng.guns.core.exception;
+
+/**
+ * 抽象接口
+ *
+ * @author fengshuonan
+ * @date 2017-12-28-下午10:27
+ */
+public interface ServiceExceptionEnum {
+
+    /**
+     * 获取异常编码
+     */
+    Integer getCode();
+
+    /**
+     * 获取异常信息
+     */
+    String getMessage();
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java
new file mode 100644
index 0000000..bee13e8
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java
@@ -0,0 +1,35 @@
+package com.stylefeng.guns.core.mutidatasource;
+
+/**
+ * datasource的上下文
+ *
+ * @author fengshuonan
+ * @date 2017年3月5日 上午9:10:58
+ */
+public class DataSourceContextHolder {
+
+    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
+
+    /**
+     * 设置数据源类型
+     *
+     * @param dataSourceType 数据库类型
+     */
+    public static void setDataSourceType(String dataSourceType) {
+        contextHolder.set(dataSourceType);
+    }
+
+    /**
+     * 获取数据源类型
+     */
+    public static String getDataSourceType() {
+        return contextHolder.get();
+    }
+
+    /**
+     * 清除数据源类型
+     */
+    public static void clearDataSourceType() {
+        contextHolder.remove();
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java
new file mode 100644
index 0000000..e2cf4be
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java
@@ -0,0 +1,18 @@
+package com.stylefeng.guns.core.mutidatasource;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * 动态数据源
+ *
+ * @author fengshuonan
+ * @date 2017年3月5日 上午9:11:49
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource {
+
+	@Override
+	protected Object determineCurrentLookupKey() {
+		return DataSourceContextHolder.getDataSourceType();
+	}
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java
new file mode 100644
index 0000000..c7da1c6
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java
@@ -0,0 +1,18 @@
+package com.stylefeng.guns.core.mutidatasource.annotion;
+
+import java.lang.annotation.*;
+
+/**
+ * 
+ * 多数据源标识
+ *
+ * @author fengshuonan
+ * @date 2017年3月5日 上午9:44:24
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface DataSource {
+
+	String name() default "";
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java
new file mode 100644
index 0000000..890f9c9
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java
@@ -0,0 +1,77 @@
+package com.stylefeng.guns.core.mutidatasource.aop;
+
+import com.stylefeng.guns.core.mutidatasource.DataSourceContextHolder;
+import com.stylefeng.guns.core.mutidatasource.annotion.DataSource;
+import com.stylefeng.guns.core.config.properties.MutiDataSourceProperties;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.Ordered;
+
+import java.lang.reflect.Method;
+
+/**
+ * 多数据源切换的aop
+ *
+ * @author fengshuonan
+ * @date 2017年3月5日 上午10:22:16
+ */
+@Aspect
+public class MultiSourceExAop implements Ordered {
+
+    private Logger log = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    MutiDataSourceProperties mutiDataSourceProperties;
+
+    @Pointcut(value = "@annotation(com.stylefeng.guns.core.mutidatasource.annotion.DataSource)")
+    private void cut() {
+
+    }
+
+    @Around("cut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable {
+
+        Signature signature = point.getSignature();
+        MethodSignature methodSignature = null;
+        if (!(signature instanceof MethodSignature)) {
+            throw new IllegalArgumentException("该注解只能用于方法");
+        }
+        methodSignature = (MethodSignature) signature;
+
+        Object target = point.getTarget();
+        Method currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
+
+        DataSource datasource = currentMethod.getAnnotation(DataSource.class);
+        if (datasource != null) {
+            DataSourceContextHolder.setDataSourceType(datasource.name());
+            log.debug("设置数据源为:" + datasource.name());
+        } else {
+            DataSourceContextHolder.setDataSourceType(mutiDataSourceProperties.getDataSourceNames()[0]);
+            log.debug("设置数据源为:dataSourceCurrent");
+        }
+
+        try {
+            return point.proceed();
+        } finally {
+            log.debug("清空数据源信息!");
+            DataSourceContextHolder.clearDataSourceType();
+        }
+    }
+
+
+    /**
+     * aop的顺序要早于spring的事务
+     */
+    @Override
+    public int getOrder() {
+        return 1;
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java
new file mode 100644
index 0000000..61bf3fc
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java
@@ -0,0 +1,239 @@
+package com.stylefeng.guns.core.node;
+
+import com.stylefeng.guns.core.constant.IsMenu;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+
+/**
+ * @author fengshuonan
+ * @Description 菜单的节点
+ * @date 2016年12月6日 上午11:34:17
+ */
+public class MenuNode implements Comparable {
+
+    /**
+     * 节点id
+     */
+    private Long id;
+
+    /**
+     * 父节点
+     */
+    private Long parentId;
+
+    /**
+     * 节点名称
+     */
+    private String name;
+
+    /**
+     * 按钮级别
+     */
+    private Integer levels;
+
+    /**
+     * 按钮级别
+     */
+    private Integer ismenu;
+
+    /**
+     * 按钮的排序
+     */
+    private Integer num;
+
+    /**
+     * 节点的url
+     */
+    private String url;
+
+    /**
+     * 节点图标
+     */
+    private String icon;
+
+    /**
+     * 子节点的集合
+     */
+    private List<MenuNode> children;
+
+    /**
+     * 查询子节点时候的临时集合
+     */
+    private List<MenuNode> linkedList = new ArrayList<MenuNode>();
+
+    public MenuNode() {
+        super();
+    }
+
+    public MenuNode(Long id, Long parentId) {
+        super();
+        this.id = id;
+        this.parentId = parentId;
+    }
+
+    public Integer getLevels() {
+        return levels;
+    }
+
+    public void setLevels(Integer levels) {
+        this.levels = levels;
+    }
+
+    public String getIcon() {
+        return icon;
+    }
+
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+
+    public static MenuNode createRoot() {
+        return new MenuNode(0L, -1L);
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public List<MenuNode> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<MenuNode> children) {
+        this.children = children;
+    }
+
+    public Integer getNum() {
+        return num;
+    }
+
+    public void setNum(Integer num) {
+        this.num = num;
+    }
+
+    public Integer getIsmenu() {
+        return ismenu;
+    }
+
+    public void setIsmenu(Integer ismenu) {
+        this.ismenu = ismenu;
+    }
+
+    @Override
+    public String toString() {
+        return "MenuNode{" +
+                "id=" + id +
+                ", parentId=" + parentId +
+                ", name='" + name + '\'' +
+                ", levels=" + levels +
+                ", num=" + num +
+                ", url='" + url + '\'' +
+                ", icon='" + icon + '\'' +
+                ", children=" + children +
+                ", linkedList=" + linkedList +
+                '}';
+    }
+
+    /**
+     * 重写排序比较接口,首先根据等级排序,然后更具排序字段排序
+     *
+     * @param o
+     * @return
+     */
+    @Override
+    public int compareTo(Object o) {
+        MenuNode menuNode = (MenuNode) o;
+        Integer num = menuNode.getNum();
+        Integer levels = menuNode.getLevels();
+        if (num == null) {
+            num = 0;
+        }
+        if (levels == null) {
+            levels = 0;
+        }
+        if (this.levels.compareTo(levels) == 0) {
+            return this.num.compareTo(num);
+        } else {
+            return this.levels.compareTo(levels);
+        }
+
+    }
+
+    /**
+     * 构建页面菜单列表
+     */
+    public static List<MenuNode> buildTitle(List<MenuNode> nodes) {
+        if (nodes.size() <= 0) {
+            return nodes;
+        }
+        //剔除非菜单
+        nodes.removeIf(node -> node.getIsmenu() != IsMenu.YES.getCode());
+        //对菜单排序,返回列表按菜单等级,序号的排序方式排列
+        Collections.sort(nodes);
+        return mergeList(nodes, nodes.get(nodes.size() - 1).getLevels(), null);
+    }
+
+    /**
+     * 递归合并数组为子数组,最后返回第一层
+     *
+     * @param menuList
+     * @param listMap
+     * @return
+     */
+    private static List<MenuNode> mergeList(List<MenuNode> menuList, int rank, Map<Long, List<MenuNode>> listMap) {
+        //保存当次调用总共合并了多少元素
+        int n;
+        //保存当次调用总共合并出来的list
+        Map<Long, List<MenuNode>> currentMap = new HashMap<>();
+        //由于按等级从小到大排序,需要从后往前排序
+        //判断该节点是否属于当前循环的等级,不等于则跳出循环
+        for (n = menuList.size() - 1; n >=0&&menuList.get(n).getLevels() == rank; n--) {
+            //判断之前的调用是否有返回以该节点的id为key的map,有则设置为children列表。
+            if (listMap != null && listMap.get(menuList.get(n).getId()) != null) {
+                menuList.get(n).setChildren(listMap.get(menuList.get(n).getId()));
+            }
+            if (menuList.get(n).getParentId()!=null&&menuList.get(n).getParentId()!=0) {
+                //判断当前节点所属的pid是否已经创建了以该pid为key的键值对,没有则创建新的链表
+                currentMap.computeIfAbsent(menuList.get(n).getParentId(), k -> new LinkedList<>());
+                //将该节点插入到对应的list的头部
+                currentMap.get(menuList.get(n).getParentId()).add(0, menuList.get(n));
+            }
+        }
+        if (n <0) {
+            return menuList;
+        } else {
+            return mergeList(menuList.subList(0, n+1), menuList.get(n).getLevels(), currentMap);
+        }
+    }
+
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java
new file mode 100644
index 0000000..a330514
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java
@@ -0,0 +1,79 @@
+package com.stylefeng.guns.core.node;
+
+/**
+ * 
+ * jquery ztree 插件的节点
+ * 
+ * @author fengshuonan
+ * @date 2017年2月17日 下午8:25:14
+ */
+public class ZTreeNode {
+
+	private Long id;	//节点id
+	
+	private Long pId;//父节点id
+	
+	private String name;//节点名称
+	
+	private Boolean open;//是否打开节点
+	
+	private Boolean checked;//是否被选中
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getpId() {
+		return pId;
+	}
+
+	public void setpId(Long pId) {
+		this.pId = pId;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Boolean getOpen() {
+		return open;
+	}
+
+	public void setOpen(Boolean open) {
+		this.open = open;
+	}
+
+	public Boolean getIsOpen() {
+		return open;
+	}
+
+	public void setIsOpen(Boolean open) {
+		this.open = open;
+	}
+
+	public Boolean getChecked() {
+		return checked;
+	}
+
+	public void setChecked(Boolean checked) {
+		this.checked = checked;
+	}
+	
+	public static ZTreeNode createParent(){
+		ZTreeNode zTreeNode = new ZTreeNode();
+		zTreeNode.setChecked(true);
+		zTreeNode.setId(0L);
+		zTreeNode.setName("顶级");
+		zTreeNode.setOpen(true);
+		zTreeNode.setpId(0L);
+		return zTreeNode;
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java
new file mode 100644
index 0000000..7af90f9
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java
@@ -0,0 +1,65 @@
+package com.stylefeng.guns.core.page;
+
+/**
+ * 分页参数类(for BootStrap Table)
+ *
+ * @author fengshuonan
+ * @date 2017年1月21日 下午2:21:35
+ */
+public class PageBT {
+
+    private int limit;          // 每页显示个数
+
+    private int offset;         // 查询的偏移量(查询的页数 = offset/limit + 1)
+
+    private String order;       // 排序方式
+
+
+    public PageBT() {
+        super();
+    }
+
+    public PageBT(int limit, int offset) {
+        super();
+        this.limit = limit;
+        this.offset = offset;
+    }
+
+    public int getLimit() {
+        return limit;
+    }
+
+    public void setLimit(int limit) {
+        this.limit = limit;
+    }
+
+    public int getOffset() {
+        return offset;
+    }
+
+    public void setOffset(int offset) {
+        this.offset = offset;
+    }
+
+    public String getOrder() {
+        return order;
+    }
+
+    public void setOrder(String order) {
+        this.order = order;
+    }
+
+    public int getPageSize() {
+        return this.limit;
+    }
+
+    public int getPageNumber() {
+        return this.offset / this.limit + 1;
+    }
+
+    @Override
+    public String toString() {
+        return "PageBT [limit=" + limit + ", offset=" + offset + ", order=" + order + "]";
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java
new file mode 100644
index 0000000..6230e13
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java
@@ -0,0 +1,41 @@
+package com.stylefeng.guns.core.page;
+
+import com.baomidou.mybatisplus.plugins.Page;
+
+import java.util.List;
+
+/**
+ * 分页结果的封装(for Bootstrap Table)
+ *
+ * @author fengshuonan
+ * @Date 2017年1月22日 下午11:06:41
+ */
+public class PageInfoBT<T> {
+
+    // 结果集
+    private List<T> rows;
+
+    // 总数
+    private long total;
+
+    public PageInfoBT(Page<T> page) {
+        this.rows = page.getRecords();
+        this.total = page.getTotal();
+    }
+
+    public List<T> getRows() {
+        return rows;
+    }
+
+    public void setRows(List<T> rows) {
+        this.rows = rows;
+    }
+
+    public long getTotal() {
+        return total;
+    }
+
+    public void setTotal(long total) {
+        this.total = total;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java
new file mode 100644
index 0000000..f17a25b
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java
@@ -0,0 +1,294 @@
+package com.stylefeng.guns.core.qr;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 内嵌图片的二维码生成器
+ *
+ * @author lichunxi
+ */
+public class ImgQrTool {
+
+    private static Logger log = LoggerFactory.getLogger(ImgQrTool.class);
+
+    // 镶嵌的图片宽度的一般
+    private static final int IMAGE_WIDTH = 80;
+    private static final int IMAGE_HEIGHT = 80;
+    private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
+    private static final int FRAME_WIDTH = 2;
+
+    // 二维码写码器
+    private static MultiFormatWriter mutiWriter = new MultiFormatWriter();
+
+    /**
+     * 生成带图片的二维码
+     *
+     * @param content       二维码的内容
+     * @param width         宽度
+     * @param height        高度
+     * @param srcImagePath  被镶嵌的图片的地址
+     * @param destImagePath 生成二维码图片的地址
+     * @author fengshuonan
+     * @since 2.3.0
+     */
+    public static void encode(String content, int width, int height, String srcImagePath, String destImagePath) {
+        try {
+            ImageIO.write(genBarcode(content, width, height, srcImagePath), "jpg", new File(destImagePath));
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (WriterException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 生成带图片的二维码
+     *
+     * @param content       二维码的内容
+     * @param width         宽度
+     * @param height        高度
+     * @param srcImagePath  被镶嵌的图片的地址
+     * @author fengshuonan
+     * @since 2.3.0
+     */
+    public static void encode(String content, int width, int height, String srcImagePath, OutputStream outputStream) {
+        try {
+            ImageIO.write(genBarcode(content, width, height, srcImagePath), "jpg", outputStream);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (WriterException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 创建不带参数的二维码
+     *
+     * @author fengshuonan
+     * @since 2.3.0
+     */
+    public static void createSimpleQr(String content, int width, int height, String destImagePath) {
+
+        FileOutputStream output = null;
+
+        try {
+            String format = "jpg";// 图像类型
+            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
+            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
+            File dest = new File(destImagePath);
+            output = new FileOutputStream(dest);
+            MatrixToImageWriter.writeToStream(bitMatrix, format, output);// 输出图像
+        } catch (Exception e) {
+            log.error("生成二维码出错!ImgQrTool:createSimpleQr()", e);
+        } finally {
+            try {
+                output.close();
+            } catch (IOException e) {
+                log.error("生成二维码出错!ImgQrTool:createSimpleQr()", e);
+            }
+        }
+    }
+
+    private static BufferedImage genBarcode(String content, int width, int height, String srcImagePath)
+            throws WriterException, IOException {
+        // 读取源图像
+        BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH, IMAGE_HEIGHT, true);
+        int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];
+        for (int i = 0; i < scaleImage.getWidth(); i++) {
+            for (int j = 0; j < scaleImage.getHeight(); j++) {
+                srcPixels[i][j] = scaleImage.getRGB(i, j);
+            }
+        }
+
+        Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
+        hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
+        hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+        hint.put(EncodeHintType.MARGIN, 1);// 二维码整体白框
+
+        // 生成二维码
+        BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hint);
+
+        // 二维矩阵转为一维像素数组
+        int halfW = matrix.getWidth() / 2;
+        int halfH = matrix.getHeight() / 2;
+        int[] pixels = new int[width * height];
+
+        for (int y = 0; y < matrix.getHeight(); y++) {
+            for (int x = 0; x < matrix.getWidth(); x++) {
+                // 读取图片
+                if (x > halfW - IMAGE_HALF_WIDTH && x < halfW + IMAGE_HALF_WIDTH && y > halfH - IMAGE_HALF_WIDTH
+                        && y < halfH + IMAGE_HALF_WIDTH) {
+                    pixels[y * width + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];
+                }
+                // 在图片四周形成边框
+                else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH
+                        && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
+                        || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
+                        && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
+                        && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
+                        || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
+                        && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
+                        && y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH)
+                        || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
+                        && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH
+                        && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
+                    pixels[y * width + x] = 0xfffffff;
+                } else {
+                    // 此处可以修改二维码的颜色,可以分别制定二维码和背景的颜色;
+                    pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xfffffff;
+                }
+            }
+        }
+
+        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        image.getRaster().setDataElements(0, 0, width, height, pixels);
+
+        return image;
+    }
+
+    /**
+     * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
+     *
+     * @param srcImageFile 源文件地址
+     * @param height       目标高度
+     * @param width        目标宽度
+     * @param hasFiller    比例不对时是否需要补白:true为补白; false为不补白;
+     * @throws IOException
+     */
+    private static BufferedImage scale(String srcImageFile, int height, int width, boolean hasFiller)
+            throws IOException {
+        double ratio = 0.0; // 缩放比例
+        File file = new File(srcImageFile);
+        BufferedImage srcImage = ImageIO.read(file);
+        Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
+        // 计算比例
+        if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
+            if (srcImage.getHeight() > srcImage.getWidth()) {
+                ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();
+            } else {
+                ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();
+            }
+            AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
+            destImage = op.filter(srcImage, null);
+        }
+        if (hasFiller) {// 补白
+            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+            Graphics2D graphic = image.createGraphics();
+            graphic.setColor(Color.white);
+            graphic.fillRect(0, 0, width, height);
+            if (width == destImage.getWidth(null))
+                graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2, destImage.getWidth(null),
+                        destImage.getHeight(null), Color.white, null);
+            else
+                graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null),
+                        destImage.getHeight(null), Color.white, null);
+            graphic.dispose();
+            destImage = image;
+        }
+        return (BufferedImage) destImage;
+    }
+
+    /**
+     * 生成上方带文字的二维码
+     */
+    public static void createQrWithFontsAbove(QrImage para) {
+        try {
+            // 首先生成二维码图片
+            BufferedImage qrImage = genBarcode(para.getQrContent(), para.getQrWidth(), para.getQrHeight(), para.getQrIconFilePath());
+
+            int qrImageWidth = qrImage.getWidth();
+            int qrImageHeight = qrImage.getHeight();
+
+            String[] splitStrLines = null;
+            splitStrLines = splitStrLines(para.getWordContent(), qrImageWidth / para.getWordSize());
+            int fontsImageHeight = splitStrLines.length * para.getWordSize() + 10; //防止文字遮挡
+
+            //创建顶部文字的图片
+            BufferedImage imageWithFonts = new BufferedImage(qrImageWidth, fontsImageHeight, BufferedImage.TYPE_4BYTE_ABGR);
+            Graphics fontsImageGraphics = imageWithFonts.getGraphics();
+            fontsImageGraphics.fillRect(0, 0, qrImageWidth, fontsImageHeight);
+            fontsImageGraphics.setColor(Color.black);
+            fontsImageGraphics.setFont(new Font("宋体", Font.PLAIN, para.getWordSize()));
+
+            //文字长度大于一行的长度,进行分行
+            if (para.getWordContent().length() > qrImageWidth / para.getWordSize()) {//每行限制的文字个数
+                for (int i = 0; i < splitStrLines.length; i++) {
+                    fontsImageGraphics.drawString(splitStrLines[i], 0, para.getWordSize() * (i + 1));
+                }
+            } else {
+                fontsImageGraphics.drawString(
+                        para.getWordContent(),
+                        ((qrImageWidth / para.getWordSize() - para.getWordContent().length()) / 2) * para.getWordSize() + 20, //总长度减去字长度除以2为向右偏移长度
+                        para.getWordSize());
+            }
+
+            // 从图片中读取RGB
+            int[] ImageArrayFonts = new int[qrImageWidth * fontsImageHeight];
+            ImageArrayFonts = imageWithFonts.getRGB(0, 0, qrImageWidth, fontsImageHeight, ImageArrayFonts, 0, qrImageWidth);
+
+            int[] ImageArrayQr = new int[qrImageWidth * qrImageHeight];
+            ImageArrayQr = qrImage.getRGB(0, 0, qrImageWidth, qrImageHeight, ImageArrayQr, 0, qrImageWidth);
+
+            // 生成新图片
+            BufferedImage ImageNew = new BufferedImage(qrImageWidth, qrImageHeight + fontsImageHeight, BufferedImage.TYPE_INT_RGB);
+            ImageNew.setRGB(0, 0, qrImageWidth, fontsImageHeight, ImageArrayFonts, 0, qrImageWidth);// 设置上半部分的RGB
+            ImageNew.setRGB(0, fontsImageHeight, qrImageWidth, qrImageHeight, ImageArrayQr, 0, qrImageWidth);// 设置下半部分的RGB
+
+            File outFile = new File(para.getFileOutputPath());
+            ImageIO.write(ImageNew, "jpg", outFile);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 一行字符串拆分成多行
+     */
+    private static String[] splitStrLines(String str, int len) {
+        int blocks = str.length() / len + 1;
+        String[] strs = new String[blocks];
+        for (int i = 0; i < blocks; i++) {
+            if ((i + 1) * len > str.length()) {
+                strs[i] = str.substring(i * len);
+            } else {
+                strs[i] = str.substring(i * len, (i + 1) * len);
+            }
+        }
+        return strs;
+    }
+
+    public static void main(String[] args) throws IOException {
+        for (int i = 1; i <= 1; i++) {
+            QrImage para = new QrImage.Builder()
+                    .setFileOutputPath("D:\\二维码\\test\\" + i + ".jpg")
+                    .setQrContent("http://www.baidu.com?a=" + "123")
+                    .setQrHeight(300)
+                    .setQrWidth(300)
+                    .setQrIconFilePath("D:\\二维码\\中间图标\\1.png")
+                    .setTopWrodHeight(100)
+                    .setWordContent("test" + 1)
+                    .setWordSize(18).build();
+            ImgQrTool.createQrWithFontsAbove(para);
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java
new file mode 100644
index 0000000..5c264c2
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.stylefeng.guns.core.qr;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Encapsulates custom configuration used in methods of {@link MatrixToImageWriter}.
+ */
+public final class MatrixToImageConfig {
+
+  public static final int BLACK = 0xFF000000;
+  public static final int WHITE = 0xFFFFFFFF;
+  
+  private final int onColor;
+  private final int offColor;
+
+  /**
+   * Creates a default config with on color {@link #BLACK} and off color {@link #WHITE}, generating normal
+   * black-on-white barcodes.
+   */
+  public MatrixToImageConfig() {
+    this(BLACK, WHITE);
+  }
+
+  /**
+   * @param onColor pixel on color, specified as an ARGB value as an int
+   * @param offColor pixel off color, specified as an ARGB value as an int
+   */
+  public MatrixToImageConfig(int onColor, int offColor) {
+    this.onColor = onColor;
+    this.offColor = offColor;
+  }
+
+  public int getPixelOnColor() {
+    return onColor;
+  }
+
+  public int getPixelOffColor() {
+    return offColor;
+  }
+
+  int getBufferedImageColorModel() {
+    // Use faster BINARY if colors match default
+    return onColor == BLACK && offColor == WHITE ? BufferedImage.TYPE_BYTE_BINARY : BufferedImage.TYPE_INT_RGB;
+  }
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java
new file mode 100644
index 0000000..1bbf4b0
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.qr;
+
+import com.google.zxing.common.BitMatrix;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Path;
+
+/**
+ * Writes a {@link BitMatrix} to {@link BufferedImage},
+ * file or stream. Provided here instead of core since it depends on
+ * Java SE libraries.
+ *
+ * @author Sean Owen
+ */
+public final class MatrixToImageWriter {
+
+  private static final MatrixToImageConfig DEFAULT_CONFIG = new MatrixToImageConfig();
+
+  private MatrixToImageWriter() {}
+
+  /**
+   * Renders a {@link BitMatrix} as an image, where "false" bits are rendered
+   * as white, and "true" bits are rendered as black.
+   */
+  public static BufferedImage toBufferedImage(BitMatrix matrix) {
+    return toBufferedImage(matrix, DEFAULT_CONFIG);
+  }
+
+  /**
+   * As {@link #toBufferedImage(BitMatrix)}, but allows customization of the output.
+   */
+  public static BufferedImage toBufferedImage(BitMatrix matrix, MatrixToImageConfig config) {
+    int width = matrix.getWidth();
+    int height = matrix.getHeight();
+    BufferedImage image = new BufferedImage(width, height, config.getBufferedImageColorModel());
+    int onColor = config.getPixelOnColor();
+    int offColor = config.getPixelOffColor();
+    for (int x = 0; x < width; x++) {
+      for (int y = 0; y < height; y++) {
+        image.setRGB(x, y, matrix.get(x, y) ? onColor : offColor);
+      }
+    }
+    return image;
+  }
+
+  /**
+   * @deprecated use {@link #writeToPath(BitMatrix, String, Path)}
+   */
+  @Deprecated
+  public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
+    writeToPath(matrix, format, file.toPath());
+  }
+
+  /**
+   * Writes a {@link BitMatrix} to a file.
+   *
+   * @see #toBufferedImage(BitMatrix)
+   */
+  public static void writeToPath(BitMatrix matrix, String format, Path file) throws IOException {
+    writeToPath(matrix, format, file, DEFAULT_CONFIG);
+  }
+
+  /**
+   * @deprecated use {@link #writeToPath(BitMatrix, String, Path, MatrixToImageConfig)}
+   */
+  @Deprecated
+  public static void writeToFile(BitMatrix matrix, String format, File file, MatrixToImageConfig config) 
+      throws IOException {
+    writeToPath(matrix, format, file.toPath(), config);
+  }
+
+  /**
+   * As {@link #writeToFile(BitMatrix, String, File)}, but allows customization of the output.
+   */
+  public static void writeToPath(BitMatrix matrix, String format, Path file, MatrixToImageConfig config)
+      throws IOException {
+    BufferedImage image = toBufferedImage(matrix, config);
+    if (!ImageIO.write(image, format, file.toFile())) {
+      throw new IOException("Could not write an image of format " + format + " to " + file);
+    }
+  }
+
+  /**
+   * Writes a {@link BitMatrix} to a stream.
+   *
+   * @see #toBufferedImage(BitMatrix)
+   */
+  public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {
+    writeToStream(matrix, format, stream, DEFAULT_CONFIG);
+  }
+
+  /**
+   * As {@link #writeToStream(BitMatrix, String, OutputStream)}, but allows customization of the output.
+   */
+  public static void writeToStream(BitMatrix matrix, String format, OutputStream stream, MatrixToImageConfig config) 
+      throws IOException {  
+    BufferedImage image = toBufferedImage(matrix, config);
+    if (!ImageIO.write(image, format, stream)) {
+      throw new IOException("Could not write an image of format " + format);
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java
new file mode 100644
index 0000000..ce4e48a
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java
@@ -0,0 +1,170 @@
+package com.stylefeng.guns.core.qr;
+
+/**
+ * 二维码图片对象
+ *
+ * @author fengshuonan
+ * @date 2016年12月8日 上午11:37:09
+ */
+public class QrImage {
+
+    /**
+     * 二维码的内容
+     */
+    private String qrContent;
+
+    /**
+     * 二维码的宽度
+     */
+    private int qrWidth;
+
+    /**
+     * 二维码的高度
+     */
+    private int qrHeight;
+
+    /**
+     * 二维码中间图标的文件路径
+     */
+    private String qrIconFilePath;
+
+    /**
+     * 二维码中间小图标的边长
+     */
+    private int qrIconWidth;
+
+    /**
+     * 顶部文字的高度
+     */
+    private int topWrodHeight;
+
+    /**
+     * 文字的大小
+     */
+    private int wordSize;
+
+    /**
+     * 文字的内容
+     */
+    private String wordContent;
+
+    /**
+     * 文件的输出路径
+     */
+    private String fileOutputPath;
+
+    public static class Builder {
+        private String qrContent;
+        private int qrWidth;
+        private int qrHeight;
+        private String qrIconFilePath;
+        private int topWrodHeight;
+        private int wordSize;
+        private String wordContent;
+        private String fileOutputPath;
+        private int qrIconWidth;
+
+        public Builder() {
+        }
+
+        public Builder setQrContent(String qrContent) {
+            this.qrContent = qrContent;
+            return this;
+        }
+
+        public Builder setQrWidth(int qrWidth) {
+            this.qrWidth = qrWidth;
+            return this;
+        }
+
+        public Builder setQrHeight(int qrHeight) {
+            this.qrHeight = qrHeight;
+            return this;
+        }
+
+        public Builder setQrIconFilePath(String qrIconFilePath) {
+            this.qrIconFilePath = qrIconFilePath;
+            return this;
+        }
+
+        public Builder setTopWrodHeight(int topWrodHeight) {
+            this.topWrodHeight = topWrodHeight;
+            return this;
+        }
+
+        public Builder setWordSize(int wordSize) {
+            this.wordSize = wordSize;
+            return this;
+        }
+
+        public Builder setWordContent(String wordContent) {
+            this.wordContent = wordContent;
+            return this;
+        }
+
+        public Builder setFileOutputPath(String fileOutputPath) {
+            this.fileOutputPath = fileOutputPath;
+            return this;
+        }
+
+        public Builder setQrIconWidth(int qrIconWidth) {
+            this.qrIconWidth = qrIconWidth;
+            return this;
+        }
+
+        public QrImage build() {
+            return new QrImage(this.qrContent, this.qrWidth, this.qrHeight, this.qrIconFilePath, this.qrIconWidth,
+                    this.topWrodHeight, this.wordSize, this.wordContent, this.fileOutputPath);
+        }
+    }
+
+    public QrImage(String qrContent, int qrWidth, int qrHeight, String qrIconFilePath, int qrIconWidth,
+                   int topWrodHeight, int wordSize, String wordContent, String fileOutputPath) {
+        super();
+        this.qrContent = qrContent;
+        this.qrWidth = qrWidth;
+        this.qrHeight = qrHeight;
+        this.qrIconFilePath = qrIconFilePath;
+        this.qrIconWidth = qrIconWidth;
+        this.topWrodHeight = topWrodHeight;
+        this.wordSize = wordSize;
+        this.wordContent = wordContent;
+        this.fileOutputPath = fileOutputPath;
+    }
+
+    public String getQrContent() {
+        return qrContent;
+    }
+
+    public int getQrWidth() {
+        return qrWidth;
+    }
+
+    public int getQrHeight() {
+        return qrHeight;
+    }
+
+    public String getQrIconFilePath() {
+        return qrIconFilePath;
+    }
+
+    public int getTopWrodHeight() {
+        return topWrodHeight;
+    }
+
+    public int getWordSize() {
+        return wordSize;
+    }
+
+    public String getWordContent() {
+        return wordContent;
+    }
+
+    public String getFileOutputPath() {
+        return fileOutputPath;
+    }
+
+    public int getQrIconWidth() {
+        return qrIconWidth;
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java
new file mode 100644
index 0000000..322d23d
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java
@@ -0,0 +1,38 @@
+package com.stylefeng.guns.core.support;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 基本变量类型的枚举
+ *
+ * @author xiaoleilu
+ */
+public enum BasicType {
+    BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING;
+
+    /**
+     * 原始类型为Key,包装类型为Value,例如: int.class -> Integer.class.
+     */
+    public static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<Class<?>, Class<?>>(8);
+
+    /**
+     * 包装类型为Key,原始类型为Value,例如: Integer.class -> int.class.
+     */
+    public static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<Class<?>, Class<?>>(8);
+
+    static {
+        wrapperPrimitiveMap.put(Boolean.class, boolean.class);
+        wrapperPrimitiveMap.put(Byte.class, byte.class);
+        wrapperPrimitiveMap.put(Character.class, char.class);
+        wrapperPrimitiveMap.put(Double.class, double.class);
+        wrapperPrimitiveMap.put(Float.class, float.class);
+        wrapperPrimitiveMap.put(Integer.class, int.class);
+        wrapperPrimitiveMap.put(Long.class, long.class);
+        wrapperPrimitiveMap.put(Short.class, short.class);
+
+        for (Map.Entry<Class<?>, Class<?>> entry : wrapperPrimitiveMap.entrySet()) {
+            primitiveWrapperMap.put(entry.getValue(), entry.getKey());
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java
new file mode 100644
index 0000000..b0ec608
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java
@@ -0,0 +1,508 @@
+package com.stylefeng.guns.core.support;
+
+import com.stylefeng.guns.core.support.exception.ToolBoxException;
+import com.stylefeng.guns.core.util.Convert;
+
+import java.beans.*;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Bean工具类
+ *
+ * @author Looly
+ */
+public class BeanKit {
+
+    /**
+     * 判断是否为Bean对象
+     *
+     * @param clazz 待测试类
+     * @return 是否为Bean对象
+     */
+    public static boolean isBean(Class<?> clazz) {
+        if (ClassKit.isNormalClass(clazz)) {
+            Method[] methods = clazz.getMethods();
+            for (Method method : methods) {
+                if (method.getParameterTypes().length == 1 && method.getName().startsWith("set")) {
+                    //检测包含标准的setXXX方法即视为标准的JavaBean
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static PropertyEditor findEditor(Class<?> type) {
+        return PropertyEditorManager.findEditor(type);
+    }
+
+    /**
+     * 获得Bean字段描述数组
+     *
+     * @param clazz Bean类
+     * @return 字段描述数组
+     * @throws IntrospectionException
+     */
+    public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws IntrospectionException {
+        return Introspector.getBeanInfo(clazz).getPropertyDescriptors();
+    }
+
+    /**
+     * 获得字段名和字段描述Map
+     *
+     * @param clazz Bean类
+     * @return 字段名和字段描述Map
+     * @throws IntrospectionException
+     */
+    public static Map<String, PropertyDescriptor> getFieldNamePropertyDescriptorMap(Class<?> clazz) throws IntrospectionException {
+        final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
+        Map<String, PropertyDescriptor> map = new HashMap<>();
+        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+            map.put(propertyDescriptor.getName(), propertyDescriptor);
+        }
+        return map;
+    }
+
+    /**
+     * 获得Bean类属性描述
+     *
+     * @param clazz     Bean类
+     * @param fieldName 字段名
+     * @return PropertyDescriptor
+     * @throws IntrospectionException
+     */
+    public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, final String fieldName) throws IntrospectionException {
+        PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
+        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+            if (ObjectKit.equals(fieldName, propertyDescriptor.getName())) {
+                return propertyDescriptor;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Map转换为Bean对象
+     *
+     * @param map       Map
+     * @param beanClass Bean Class
+     * @return Bean
+     */
+    public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass) {
+        return fillBeanWithMap(map, ClassKit.newInstance(beanClass));
+    }
+
+    /**
+     * Map转换为Bean对象<br>
+     * 忽略大小写
+     *
+     * @param map       Map
+     * @param beanClass Bean Class
+     * @return Bean
+     */
+    public static <T> T mapToBeanIgnoreCase(Map<?, ?> map, Class<T> beanClass) {
+        return fillBeanWithMapIgnoreCase(map, ClassKit.newInstance(beanClass));
+    }
+
+    /**
+     * 使用Map填充Bean对象
+     *
+     * @param map  Map
+     * @param bean Bean
+     * @return Bean
+     */
+    public static <T> T fillBeanWithMap(final Map<?, ?> map, T bean) {
+        return fillBean(bean, new ValueProvider() {
+            @Override
+            public Object value(String name) {
+                return map.get(name);
+            }
+        });
+    }
+
+    /**
+     * 使用Map填充Bean对象,可配置将下划线转换为驼峰
+     *
+     * @param map           Map
+     * @param bean          Bean
+     * @param isToCamelCase 是否将下划线模式转换为驼峰模式
+     * @return Bean
+     */
+    public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, boolean isToCamelCase) {
+        if (isToCamelCase) {
+            final Map<Object, Object> map2 = new HashMap<Object, Object>();
+            for (Entry<?, ?> entry : map.entrySet()) {
+                final Object key = entry.getKey();
+                if (null != key && key instanceof String) {
+                    final String keyStr = (String) key;
+                    map2.put(StrKit.toCamelCase(keyStr), entry.getValue());
+                } else {
+                    map2.put(key, entry.getValue());
+                }
+            }
+            return fillBeanWithMap(map2, bean);
+        }
+
+        return fillBeanWithMap(map, bean);
+    }
+
+    /**
+     * 使用Map填充Bean对象,忽略大小写
+     *
+     * @param map  Map
+     * @param bean Bean
+     * @return Bean
+     */
+    public static <T> T fillBeanWithMapIgnoreCase(Map<?, ?> map, T bean) {
+        final Map<Object, Object> map2 = new HashMap<Object, Object>();
+        for (Entry<?, ?> entry : map.entrySet()) {
+            final Object key = entry.getKey();
+            if (key instanceof String) {
+                final String keyStr = (String) key;
+                map2.put(keyStr.toLowerCase(), entry.getValue());
+            } else {
+                map2.put(key, entry.getValue());
+            }
+        }
+
+        return fillBean(bean, new ValueProvider() {
+            @Override
+            public Object value(String name) {
+                return map2.get(name.toLowerCase());
+            }
+        });
+    }
+
+    /**
+     * ServletRequest 参数转Bean
+     *
+     * @param request   ServletRequest
+     * @param beanClass Bean Class
+     * @return Bean
+     */
+    public static <T> T requestParamToBean(javax.servlet.ServletRequest request, Class<T> beanClass) {
+        return fillBeanWithRequestParam(request, ClassKit.newInstance(beanClass));
+    }
+
+    /**
+     * ServletRequest 参数转Bean
+     *
+     * @param request ServletRequest
+     * @param bean    Bean
+     * @return Bean
+     */
+    public static <T> T fillBeanWithRequestParam(final javax.servlet.ServletRequest request, T bean) {
+        final String beanName = StrKit.lowerFirst(bean.getClass().getSimpleName());
+        return fillBean(bean, new ValueProvider() {
+            @Override
+            public Object value(String name) {
+                String value = request.getParameter(name);
+                if (StrKit.isEmpty(value)) {
+                    // 使用类名前缀尝试查找值
+                    value = request.getParameter(beanName + StrKit.DOT + name);
+                    if (StrKit.isEmpty(value)) {
+                        // 此处取得的值为空时跳过,包括null和""
+                        value = null;
+                    }
+                }
+                return value;
+            }
+        });
+    }
+
+    /**
+     * ServletRequest 参数转Bean
+     *
+     * @param <T>
+     * @param beanClass     Bean Class
+     * @param valueProvider 值提供者
+     * @return Bean
+     */
+    public static <T> T toBean(Class<T> beanClass, ValueProvider valueProvider) {
+        return fillBean(ClassKit.newInstance(beanClass), valueProvider);
+    }
+
+    /**
+     * 填充Bean
+     *
+     * @param <T>
+     * @param bean          Bean
+     * @param valueProvider 值提供者
+     * @return Bean
+     */
+    public static <T> T fillBean(T bean, ValueProvider valueProvider) {
+        if (null == valueProvider) {
+            return bean;
+        }
+
+        Class<?> beanClass = bean.getClass();
+        try {
+            PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(beanClass);
+            String propertyName;
+            Object value;
+            for (PropertyDescriptor property : propertyDescriptors) {
+                propertyName = property.getName();
+                value = valueProvider.value(propertyName);
+                if (null == value) {
+                    continue;
+                }
+                try {
+                    property.getWriteMethod().invoke(bean, Convert.parse(property.getPropertyType(), value));
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        } catch (Exception e) {
+            throw new ToolBoxException(e);
+        }
+        return bean;
+    }
+
+    /**
+     * 对象转Map
+     *
+     * @param bean bean对象
+     * @return Map
+     */
+    public static <T> Map<String, Object> beanToMap(T bean) {
+        return beanToMap(bean, false);
+    }
+
+    /**
+     * 对象转Map
+     *
+     * @param bean bean对象
+     * @return Map
+     */
+    public static <T> List<Map<String, Object>> listToMapList(List<T> bean) {
+        ArrayList<Map<String, Object>> maps = new ArrayList<>();
+        for (T t : bean) {
+            maps.add(beanToMap(bean, false));
+        }
+        return maps;
+    }
+
+    /**
+     * 对象转Map
+     *
+     * @param bean              bean对象
+     * @param isToUnderlineCase 是否转换为下划线模式
+     * @return Map
+     */
+    public static <T> Map<String, Object> beanToMap(T bean, boolean isToUnderlineCase) {
+
+        if (bean == null) {
+            return null;
+        }
+        Map<String, Object> map = new HashMap<String, Object>();
+        try {
+            final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(bean.getClass());
+            for (PropertyDescriptor property : propertyDescriptors) {
+                String key = property.getName();
+                // 过滤class属性
+                if (false == key.equals("class")) {
+                    // 得到property对应的getter方法
+                    Method getter = property.getReadMethod();
+                    Object value = getter.invoke(bean);
+                    if (null != value) {
+                        map.put(isToUnderlineCase ? StrKit.toUnderlineCase(key) : key, value);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new ToolBoxException(e);
+        }
+        return map;
+    }
+
+    /**
+     * 复制Bean对象属性
+     *
+     * @param source 源Bean对象
+     * @param target 目标Bean对象
+     */
+    public static void copyProperties(Object source, Object target) {
+        copyProperties(source, target, CopyOptions.create());
+    }
+
+    /**
+     * 复制Bean对象属性<br>
+     * 限制类用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类
+     *
+     * @param source           源Bean对象
+     * @param target           目标Bean对象
+     * @param ignoreProperties 不拷贝的的属性列表
+     */
+    public static void copyProperties(Object source, Object target, String... ignoreProperties) {
+        copyProperties(source, target, CopyOptions.create().setIgnoreProperties(ignoreProperties));
+    }
+
+    /**
+     * 复制Bean对象属性<br>
+     * 限制类用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类
+     *
+     * @param source      源Bean对象
+     * @param target      目标Bean对象
+     * @param copyOptions 拷贝选项,见 {@link CopyOptions}
+     */
+    public static void copyProperties(Object source, Object target, CopyOptions copyOptions) {
+        if (null == copyOptions) {
+            copyOptions = new CopyOptions();
+        }
+
+        Class<?> actualEditable = target.getClass();
+        if (copyOptions.editable != null) {
+            //检查限制类是否为target的父类或接口
+            if (!copyOptions.editable.isInstance(target)) {
+                throw new IllegalArgumentException(StrKit.format("Target class [{}] not assignable to Editable class [{}]", target.getClass().getName(), copyOptions.editable.getName()));
+            }
+            actualEditable = copyOptions.editable;
+        }
+        PropertyDescriptor[] targetPds = null;
+        Map<String, PropertyDescriptor> sourcePdMap;
+        try {
+            sourcePdMap = getFieldNamePropertyDescriptorMap(source.getClass());
+            targetPds = getPropertyDescriptors(actualEditable);
+        } catch (IntrospectionException e) {
+            throw new ToolBoxException(e);
+        }
+
+        HashSet<String> ignoreSet = copyOptions.ignoreProperties != null ? CollectionKit.newHashSet(copyOptions.ignoreProperties) : null;
+        for (PropertyDescriptor targetPd : targetPds) {
+            Method writeMethod = targetPd.getWriteMethod();
+            if (writeMethod != null && (ignoreSet == null || false == ignoreSet.contains(targetPd.getName()))) {
+                PropertyDescriptor sourcePd = sourcePdMap.get(targetPd.getName());
+                if (sourcePd != null) {
+                    Method readMethod = sourcePd.getReadMethod();
+                    // 源对象字段的getter方法返回值必须可转换为目标对象setter方法的第一个参数
+                    if (readMethod != null && ClassKit.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
+                        try {
+                            Object value = ClassKit.setAccessible(readMethod).invoke(source);
+                            if (null != value || false == copyOptions.isIgnoreNullValue) {
+                                ClassKit.setAccessible(writeMethod).invoke(target, value);
+                            }
+                        } catch (Throwable ex) {
+                            throw new ToolBoxException(ex, "Copy property [{}] to [{}] error: {}", sourcePd.getName(), targetPd.getName(), ex.getMessage());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 值提供者,用于提供Bean注入时参数对应值得抽象接口<br>
+     * 继承或匿名实例化此接口<br>
+     * 在Bean注入过程中,Bean获得字段名,通过外部方式根据这个字段名查找相应的字段值,然后注入Bean<br>
+     *
+     * @author Looly
+     */
+    public static interface ValueProvider {
+        /**
+         * 获取值
+         *
+         * @param name Bean对象中参数名
+         * @return 对应参数名的值
+         */
+        public Object value(String name);
+    }
+
+    /**
+     * 属性拷贝选项<br>
+     * 包括:<br>
+     * 1、限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类<br>
+     * 2、是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null<br>
+     * 3、忽略的属性列表,设置一个属性列表,不拷贝这些属性值<br>
+     *
+     * @author Looly
+     */
+    public static class CopyOptions {
+        /**
+         * 限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类
+         */
+        private Class<?> editable;
+        /**
+         * 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
+         */
+        private boolean isIgnoreNullValue;
+        /**
+         * 忽略的属性列表,设置一个属性列表,不拷贝这些属性值
+         */
+        private String[] ignoreProperties;
+
+        /**
+         * 创建拷贝选项
+         *
+         * @return 拷贝选项
+         */
+        public static CopyOptions create() {
+            return new CopyOptions();
+        }
+
+        /**
+         * 创建拷贝选项
+         *
+         * @param editable          限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性
+         * @param isIgnoreNullValue 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
+         * @param ignoreProperties  忽略的属性列表,设置一个属性列表,不拷贝这些属性值
+         * @return 拷贝选项
+         */
+        public static CopyOptions create(Class<?> editable, boolean isIgnoreNullValue, String... ignoreProperties) {
+            return new CopyOptions(editable, isIgnoreNullValue, ignoreProperties);
+        }
+
+        /**
+         * 构造拷贝选项
+         */
+        public CopyOptions() {
+        }
+
+        /**
+         * 构造拷贝选项
+         *
+         * @param editable          限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性
+         * @param isIgnoreNullValue 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
+         * @param ignoreProperties  忽略的属性列表,设置一个属性列表,不拷贝这些属性值
+         */
+        public CopyOptions(Class<?> editable, boolean isIgnoreNullValue, String... ignoreProperties) {
+            this.editable = editable;
+            this.isIgnoreNullValue = isIgnoreNullValue;
+            this.ignoreProperties = ignoreProperties;
+        }
+
+        /**
+         * 设置限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性
+         *
+         * @param editable 限制的类或接口
+         * @return CopyOptions
+         */
+        public CopyOptions setEditable(Class<?> editable) {
+            this.editable = editable;
+            return this;
+        }
+
+        /**
+         * 设置是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
+         *
+         * @param isIgnoreNullVall 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
+         * @return CopyOptions
+         */
+        public CopyOptions setIgnoreNullValue(boolean isIgnoreNullVall) {
+            this.isIgnoreNullValue = isIgnoreNullVall;
+            return this;
+        }
+
+        /**
+         * 设置忽略的属性列表,设置一个属性列表,不拷贝这些属性值
+         *
+         * @param ignoreProperties 忽略的属性列表,设置一个属性列表,不拷贝这些属性值
+         * @return CopyOptions
+         */
+        public CopyOptions setIgnoreProperties(String... ignoreProperties) {
+            this.ignoreProperties = ignoreProperties;
+            return this;
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java
new file mode 100644
index 0000000..805fc35
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java
@@ -0,0 +1,206 @@
+package com.stylefeng.guns.core.support;
+
+
+import com.stylefeng.guns.core.support.exception.ToolBoxException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * 类工具类
+ * 1、扫描指定包下的所有类<br>
+ * 参考 http://www.oschina.net/code/snippet_234657_22722
+ * @author seaside_hi, xiaoleilu, chill
+ *
+ */
+public class ClassKit {
+	
+	private ClassKit() {
+		// 静态类不可实例化
+	}
+	
+	/**
+	 * 是否为标准的类<br>
+	 * 这个类必须:<br>
+	 * 1、非接口 2、非抽象类 3、非Enum枚举 4、非数组 5、非注解 6、非原始类型(int, long等)
+	 * 
+	 * @param clazz 类
+	 * @return 是否为标准类
+	 */
+	public static boolean isNormalClass(Class<?> clazz) {
+		return null != clazz && false == clazz.isInterface() && false == isAbstract(clazz) && false == clazz.isEnum() && false == clazz.isArray() && false == clazz.isAnnotation() && false == clazz
+				.isSynthetic() && false == clazz.isPrimitive();
+	}
+	
+	/**
+	 * 是否为抽象类
+	 * 
+	 * @param clazz 类
+	 * @return 是否为抽象类
+	 */
+	public static boolean isAbstract(Class<?> clazz) {
+		return Modifier.isAbstract(clazz.getModifiers());
+	}
+	
+	/**
+	 * 实例化对象
+	 * 
+	 * @param clazz 类名
+	 * @return 对象
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T newInstance(String clazz) {
+		if (null == clazz)
+			return null;
+		try {
+			return (T) Class.forName(clazz).newInstance();
+		} catch (Exception e) {
+			throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
+		}
+	}
+
+	/**
+	 * 实例化对象
+	 * 
+	 * @param clazz 类
+	 * @return 对象
+	 */
+	public static <T> T newInstance(Class<T> clazz) {
+		if (null == clazz)
+			return null;
+		try {
+			return (T) clazz.newInstance();
+		} catch (Exception e) {
+			throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
+		}
+	}
+
+	/**
+	 * 实例化对象
+	 * 
+	 * @param clazz 类
+	 * @return 对象
+	 */
+	public static <T> T newInstance(Class<T> clazz, Object... params) {
+		if (null == clazz)
+			return null;
+		if (CollectionKit.isEmpty(params)) {
+			return newInstance(clazz);
+		}
+		try {
+			return clazz.getDeclaredConstructor(getClasses(params)).newInstance(params);
+		} catch (Exception e) {
+			throw new ToolBoxException(StrKit.format("Instance class [{}] error!", clazz), e);
+		}
+	}
+	
+	/**
+	 * 获得对象数组的类数组
+	 * @param objects 对象数组
+	 * @return 类数组
+	 */
+	public static Class<?>[] getClasses(Object... objects){
+		Class<?>[] classes = new Class<?>[objects.length];
+		for (int i = 0; i < objects.length; i++) {
+			classes[i] = objects[i].getClass();
+		}
+		return classes;
+	}
+	
+	/**
+	 * 检查目标类是否可以从原类转化<br>
+	 * 转化包括:<br>
+	 * 1、原类是对象,目标类型是原类型实现的接口<br>
+	 * 2、目标类型是原类型的父类<br>
+	 * 3、两者是原始类型或者包装类型(相互转换)
+	 * 
+	 * @param targetType 目标类型
+	 * @param sourceType 原类型
+	 * @return 是否可转化
+	 */
+	public static boolean isAssignable(Class<?> targetType, Class<?> sourceType) {
+		if (null == targetType || null == sourceType) {
+			return false;
+		}
+
+		// 对象类型
+		if (targetType.isAssignableFrom(sourceType)) {
+			return true;
+		}
+
+		// 基本类型
+		if (targetType.isPrimitive()) {
+			// 原始类型
+			Class<?> resolvedPrimitive = BasicType.wrapperPrimitiveMap.get(sourceType);
+			if (resolvedPrimitive != null && targetType.equals(resolvedPrimitive)) {
+				return true;
+			}
+		} else {
+			// 包装类型
+			Class<?> resolvedWrapper = BasicType.primitiveWrapperMap.get(sourceType);
+			if (resolvedWrapper != null && targetType.isAssignableFrom(resolvedWrapper)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * 设置方法为可访问
+	 * 
+	 * @param method 方法
+	 * @return 方法
+	 */
+	public static Method setAccessible(Method method) {
+		if (null != method && ClassKit.isNotPublic(method)) {
+			method.setAccessible(true);
+		}
+		return method;
+	}
+	
+	/**
+	 * 指定类是否为非public
+	 * 
+	 * @param clazz 类
+	 * @return 是否为非public
+	 */
+	public static boolean isNotPublic(Class<?> clazz) {
+		return false == isPublic(clazz);
+	}
+
+	/**
+	 * 指定方法是否为非public
+	 * 
+	 * @param method 方法
+	 * @return 是否为非public
+	 */
+	public static boolean isNotPublic(Method method) {
+		return false == isPublic(method);
+	}
+	
+	/**
+	 * 指定类是否为Public
+	 * 
+	 * @param clazz 类
+	 * @return 是否为public
+	 */
+	public static boolean isPublic(Class<?> clazz) {
+		if (null == clazz) {
+			throw new NullPointerException("Class to provided is null.");
+		}
+		return Modifier.isPublic(clazz.getModifiers());
+	}
+	
+	/**
+	 * 指定方法是否为Public
+	 * 
+	 * @param method 方法
+	 * @return 是否为public
+	 */
+	public static boolean isPublic(Method method) {
+		if (null == method) {
+			throw new NullPointerException("Method to provided is null.");
+		}
+		return isPublic(method.getDeclaringClass());
+	}
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java
new file mode 100644
index 0000000..15063e4
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java
@@ -0,0 +1,801 @@
+package com.stylefeng.guns.core.support;
+
+
+import com.stylefeng.guns.core.support.exception.ToolBoxException;
+
+import java.lang.reflect.Array;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * 集合相关工具类,包括数组
+ * 
+ * @author xiaoleilu
+ * 
+ */
+public class CollectionKit {
+	
+	private CollectionKit() {
+		// 静态类不可实例化
+	}
+	
+	/**
+	 * 以 conjunction 为分隔符将集合转换为字符串
+	 * 
+	 * @param <T> 被处理的集合
+	 * @param collection 集合
+	 * @param conjunction 分隔符
+	 * @return 连接后的字符串
+	 */
+	public static <T> String join(Iterable<T> collection, String conjunction) {
+		StringBuilder sb = new StringBuilder();
+		boolean isFirst = true;
+		for (T item : collection) {
+			if (isFirst) {
+				isFirst = false;
+			} else {
+				sb.append(conjunction);
+			}
+			sb.append(item);
+		}
+		return sb.toString();
+	}
+	
+	/**
+	 * 以 conjunction 为分隔符将数组转换为字符串
+	 * 
+	 * @param <T> 被处理的集合
+	 * @param array 数组
+	 * @param conjunction 分隔符
+	 * @return 连接后的字符串
+	 */
+	public static <T> String join(T[] array, String conjunction) {
+		StringBuilder sb = new StringBuilder();
+		boolean isFirst = true;
+		for (T item : array) {
+			if (isFirst) {
+				isFirst = false;
+			} else {
+				sb.append(conjunction);
+			}
+			sb.append(item);
+		}
+		return sb.toString();
+	}
+	
+	/**
+	 * 将多个集合排序并显示不同的段落(分页)
+	 * @param pageNo 页码
+	 * @param numPerPage 每页的条目数
+	 * @param comparator 比较器
+	 * @param colls 集合数组
+	 * @return 分页后的段落内容
+	 */
+	@SafeVarargs
+	public static <T> List<T> sortPageAll(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) {
+		final List<T> result = new ArrayList<T>();
+		for (Collection<T> coll : colls) {
+			result.addAll(coll);
+		}
+		
+		Collections.sort(result, comparator);
+		
+		//第一页且数目少于第一页显示的数目
+		if(pageNo <=1 && result.size() <= numPerPage) {
+			return result;
+		}
+		
+		final int[] startEnd = PageKit.transToStartEnd(pageNo, numPerPage);
+		return result.subList(startEnd[0], startEnd[1]);
+	}
+
+	/**
+	 * 将多个集合排序并显示不同的段落(分页)
+	 * @param pageNo 页码
+	 * @param numPerPage 每页的条目数
+	 * @param comparator 比较器
+	 * @param colls 集合数组
+	 * @return 分业后的段落内容
+	 */
+//	@SafeVarargs
+//	public static <T> List<T> sortPageAll2(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) {
+//		BoundedPriorityQueue<T> queue = new BoundedPriorityQueue<T>(pageNo * numPerPage);
+//		for (Collection<T> coll : colls) {
+//			queue.addAll(coll);
+//		}
+//
+//		//第一页且数目少于第一页显示的数目
+//		if(pageNo <=1 && queue.size() <= numPerPage) {
+//			return queue.toList();
+//		}
+//
+//		final int[] startEnd = PageKit.transToStartEnd(pageNo, numPerPage);
+//		return queue.toList().subList(startEnd[0], startEnd[1]);
+//	}
+
+	/**
+	 * 将Set排序(根据Entry的值)
+	 *
+	 * @param set 被排序的Set
+	 * @return 排序后的Set
+	 */
+	public static List<Entry<Long, Long>> sortEntrySetToList(Set<Entry<Long, Long>> set) {
+		List<Entry<Long, Long>> list = new LinkedList<Entry<Long, Long>>(set);
+		Collections.sort(list, new Comparator<Entry<Long, Long>>(){
+
+			@Override
+			public int compare(Entry<Long, Long> o1, Entry<Long, Long> o2) {
+				if (o1.getValue() > o2.getValue()){
+					return 1;
+				}
+				if (o1.getValue() < o2.getValue()){
+					return -1;
+				}
+				return 0;
+			}
+		});
+		return list;
+	}
+
+	/**
+	 * 切取部分数据
+	 *
+	 * @param <T> 集合元素类型
+	 * @param surplusAlaDatas 原数据
+	 * @param partSize 每部分数据的长度
+	 * @return 切取出的数据或null
+	 */
+	public static <T> List<T> popPart(Stack<T> surplusAlaDatas, int partSize) {
+		if (surplusAlaDatas == null || surplusAlaDatas.size() <= 0){
+			return null;
+		}
+
+		final List<T> currentAlaDatas = new ArrayList<T>();
+		int size = surplusAlaDatas.size();
+		// 切割
+		if (size > partSize) {
+			for (int i = 0; i < partSize; i++) {
+				currentAlaDatas.add(surplusAlaDatas.pop());
+			}
+		} else {
+			for (int i = 0; i < size; i++) {
+				currentAlaDatas.add(surplusAlaDatas.pop());
+			}
+		}
+		return currentAlaDatas;
+	}
+
+	/**
+	 * 切取部分数据
+	 *
+	 * @param <T> 集合元素类型
+	 * @param surplusAlaDatas 原数据
+	 * @param partSize 每部分数据的长度
+	 * @return 切取出的数据或null
+	 */
+	public static <T> List<T> popPart(Deque<T> surplusAlaDatas, int partSize) {
+		if (surplusAlaDatas == null || surplusAlaDatas.size() <= 0){
+			return null;
+		}
+
+		final List<T> currentAlaDatas = new ArrayList<T>();
+		int size = surplusAlaDatas.size();
+		// 切割
+		if (size > partSize) {
+			for (int i = 0; i < partSize; i++) {
+				currentAlaDatas.add(surplusAlaDatas.pop());
+			}
+		} else {
+			for (int i = 0; i < size; i++) {
+				currentAlaDatas.add(surplusAlaDatas.pop());
+			}
+		}
+		return currentAlaDatas;
+	}
+
+	/**
+	 * 新建一个HashMap
+	 *
+	 * @return HashMap对象
+	 */
+	public static <T, K> HashMap<T, K> newHashMap() {
+		return new HashMap<T, K>();
+	}
+
+	/**
+	 * 新建一个HashMap
+	 * @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75
+	 * @return HashMap对象
+	 */
+	public static <T, K> HashMap<T, K> newHashMap(int size) {
+		return new HashMap<T, K>((int)(size / 0.75));
+	}
+
+	/**
+	 * 新建一个HashSet
+	 *
+	 * @return HashSet对象
+	 */
+	public static <T> HashSet<T> newHashSet() {
+		return new HashSet<T>();
+	}
+
+	/**
+	 * 新建一个HashSet
+	 *
+	 * @return HashSet对象
+	 */
+	@SafeVarargs
+	public static <T> HashSet<T> newHashSet(T... ts) {
+		HashSet<T> set = new HashSet<T>();
+		for (T t : ts) {
+			set.add(t);
+		}
+		return set;
+	}
+
+	/**
+	 * 新建一个ArrayList
+	 *
+	 * @return ArrayList对象
+	 */
+	public static <T> ArrayList<T> newArrayList() {
+		return new ArrayList<T>();
+	}
+
+	/**
+	 * 新建一个ArrayList
+	 *
+	 * @return ArrayList对象
+	 */
+	@SafeVarargs
+	public static <T> ArrayList<T> newArrayList(T... values) {
+		return new ArrayList<T>(Arrays.asList(values));
+	}
+
+	/**
+	 * 将新元素添加到已有数组中<br/>
+	 * 添加新元素会生成一个新的数组,不影响原数组
+	 *
+	 * @param buffer 已有数组
+	 * @param newElement 新元素
+	 * @return 新数组
+	 */
+	public static <T> T[] append(T[] buffer, T newElement) {
+		T[] t = resize(buffer, buffer.length + 1, newElement.getClass());
+		t[buffer.length] = newElement;
+		return t;
+	}
+
+	/**
+	 * 生成一个新的重新设置大小的数组
+	 *
+	 * @param buffer 原数组
+	 * @param newSize 新的数组大小
+	 * @param componentType 数组元素类型
+	 * @return 调整后的新数组
+	 */
+	public static <T> T[] resize(T[] buffer, int newSize, Class<?> componentType) {
+		T[] newArray = newArray(componentType, newSize);
+		System.arraycopy(buffer, 0, newArray, 0, buffer.length >= newSize ? newSize : buffer.length);
+		return newArray;
+	}
+
+	/**
+	 * 新建一个空数组
+	 * @param componentType 元素类型
+	 * @param newSize 大小
+	 * @return 空数组
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T[] newArray(Class<?> componentType, int newSize) {
+		return (T[]) Array.newInstance(componentType, newSize);
+	}
+
+	/**
+	 * 生成一个新的重新设置大小的数组<br/>
+	 * 新数组的类型为原数组的类型
+	 *
+	 * @param buffer 原数组
+	 * @param newSize 新的数组大小
+	 * @return 调整后的新数组
+	 */
+	public static <T> T[] resize(T[] buffer, int newSize) {
+		return resize(buffer, newSize, buffer.getClass().getComponentType());
+	}
+
+	/**
+	 * 将多个数组合并在一起<br>
+	 * 忽略null的数组
+	 *
+	 * @param arrays 数组集合
+	 * @return 合并后的数组
+	 */
+	@SafeVarargs
+	public static <T> T[] addAll(T[]... arrays) {
+		if (arrays.length == 1) {
+			return arrays[0];
+		}
+
+		int length = 0;
+		for (T[] array : arrays) {
+			if(array == null) {
+				continue;
+			}
+			length += array.length;
+		}
+		T[] result = newArray(arrays.getClass().getComponentType().getComponentType(), length);
+
+		length = 0;
+		for (T[] array : arrays) {
+			if(array == null) {
+				continue;
+			}
+			System.arraycopy(array, 0, result, length, array.length);
+			length += array.length;
+		}
+		return result;
+	}
+
+	/**
+	 * 克隆数组
+	 * @param array 被克隆的数组
+	 * @return 新数组
+	 */
+	public static <T> T[] clone(T[] array) {
+		if (array == null) {
+			return null;
+		}
+		return array.clone();
+	}
+
+	/**
+	 * 生成一个数字列表<br>
+	 * 自动判定正序反序
+	 * @param excludedEnd 结束的数字(不包含)
+	 * @return 数字列表
+	 */
+	public static int[] range(int excludedEnd) {
+		return range(0, excludedEnd, 1);
+	}
+
+	/**
+	 * 生成一个数字列表<br>
+	 * 自动判定正序反序
+	 * @param includedStart 开始的数字(包含)
+	 * @param excludedEnd 结束的数字(不包含)
+	 * @return 数字列表
+	 */
+	public static int[] range(int includedStart, int excludedEnd) {
+		return range(includedStart, excludedEnd, 1);
+	}
+
+	/**
+	 * 生成一个数字列表<br>
+	 * 自动判定正序反序
+	 * @param includedStart 开始的数字(包含)
+	 * @param excludedEnd 结束的数字(不包含)
+	 * @param step 步进
+	 * @return 数字列表
+	 */
+	public static int[] range(int includedStart, int excludedEnd, int step) {
+		if(includedStart > excludedEnd) {
+			int tmp = includedStart;
+			includedStart = excludedEnd;
+			excludedEnd = tmp;
+		}
+
+		if(step <=0) {
+			step = 1;
+		}
+
+		int deviation = excludedEnd - includedStart;
+		int length = deviation / step;
+		if(deviation % step != 0) {
+			length += 1;
+		}
+		int[] range = new int[length];
+		for(int i = 0; i < length; i++) {
+			range[i] = includedStart;
+			includedStart += step;
+		}
+		return range;
+	}
+
+	/**
+	 * 截取数组的部分
+	 * @param list 被截取的数组
+	 * @param start 开始位置(包含)
+	 * @param end 结束位置(不包含)
+	 * @return 截取后的数组,当开始位置超过最大时,返回null
+	 */
+	public static <T> List<T> sub(List<T> list, int start, int end) {
+		if(list == null || list.isEmpty()) {
+			return null;
+		}
+
+		if(start < 0) {
+			start = 0;
+		}
+		if(end < 0) {
+			end = 0;
+		}
+
+		if(start > end) {
+			int tmp = start;
+			start = end;
+			end = tmp;
+		}
+
+		final int size = list.size();
+		if(end > size) {
+			if(start >= size) {
+				return null;
+			}
+			end = size;
+		}
+
+		return list.subList(start, end);
+	}
+
+	/**
+	 * 截取集合的部分
+	 * @param list 被截取的数组
+	 * @param start 开始位置(包含)
+	 * @param end 结束位置(不包含)
+	 * @return 截取后的数组,当开始位置超过最大时,返回null
+	 */
+	public static <T> List<T> sub(Collection<T> list, int start, int end) {
+		if(list == null || list.isEmpty()) {
+			return null;
+		}
+
+		return sub(new ArrayList<T>(list), start, end);
+	}
+
+	/**
+	 * 数组是否为空
+	 * @param array 数组
+	 * @return 是否为空
+	 */
+	public static <T> boolean isEmpty(T[] array) {
+		return array == null || array.length == 0;
+	}
+
+	/**
+	 * 数组是否为非空
+	 * @param array 数组
+	 * @return 是否为非空
+	 */
+	public static <T> boolean isNotEmpty(T[] array) {
+		return false == isEmpty(array);
+	}
+
+	/**
+	 * 集合是否为空
+	 * @param collection 集合
+	 * @return 是否为空
+	 */
+	public static boolean isEmpty(Collection<?> collection) {
+		return collection == null || collection.isEmpty();
+	}
+
+	/**
+	 * 集合是否为非空
+	 * @param collection 集合
+	 * @return 是否为非空
+	 */
+	public static boolean isNotEmpty(Collection<?> collection) {
+		return false == isEmpty(collection);
+	}
+
+	/**
+	 * Map是否为空
+	 * @param map 集合
+	 * @return 是否为空
+	 */
+	public static boolean isEmpty(Map<?, ?> map) {
+		return map == null || map.isEmpty();
+	}
+
+	/**
+	 * Map是否为非空
+	 * @param map 集合
+	 * @return 是否为非空
+	 */
+	public static <T> boolean isNotEmpty(Map<?, ?> map) {
+		return false == isEmpty(map);
+	}
+
+	/**
+	 * 映射键值(参考Python的zip()函数)<br>
+	 * 例如:<br>
+	 * 		keys =    [a,b,c,d]<br>
+	 *		values = [1,2,3,4]<br>
+	 * 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
+	 * 如果两个数组长度不同,则只对应最短部分
+	 * @param keys 键列表
+	 * @param values 值列表
+	 * @return Map
+	 */
+	public static <T, K> Map<T, K> zip(T[] keys, K[] values) {
+		if(isEmpty(keys) || isEmpty(values)) {
+			return null;
+		}
+
+		final int size = Math.min(keys.length, values.length);
+		final Map<T, K> map = new HashMap<T, K>((int)(size / 0.75));
+		for(int i = 0; i < size; i++) {
+			map.put(keys[i], values[i]);
+		}
+
+		return map;
+	}
+
+	/**
+	 * 映射键值(参考Python的zip()函数)<br>
+	 * 例如:<br>
+	 * 		keys =    a,b,c,d<br>
+	 *		values = 1,2,3,4<br>
+	 *		delimiter = ,
+	 * 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
+	 * 如果两个数组长度不同,则只对应最短部分
+	 * @param keys 键列表
+	 * @param values 值列表
+	 * @return Map
+	 */
+	public static Map<String, String> zip(String keys, String values, String delimiter) {
+		return zip(StrKit.split(keys, delimiter), StrKit.split(values, delimiter));
+	}
+	
+	/**
+	 * 映射键值(参考Python的zip()函数)<br>
+	 * 例如:<br>
+	 * 		keys =    [a,b,c,d]<br>
+	 *		values = [1,2,3,4]<br>
+	 * 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
+	 * 如果两个数组长度不同,则只对应最短部分
+	 * @param keys 键列表
+	 * @param values 值列表
+	 * @return Map
+	 */
+	public static <T, K> Map<T, K> zip(Collection<T> keys, Collection<K> values) {
+		if(isEmpty(keys) || isEmpty(values)) {
+			return null;
+		}
+		
+		final List<T> keyList = new ArrayList<T>(keys);
+		final List<K> valueList = new ArrayList<K>(values);
+		
+		final int size = Math.min(keys.size(), values.size());
+		final Map<T, K> map = new HashMap<T, K>((int)(size / 0.75));
+		for(int i = 0; i < size; i++) {
+			map.put(keyList.get(i), valueList.get(i));
+		}
+		
+		return map;
+	}
+	
+	/**
+	 * 数组中是否包含元素
+	 * @param array 数组
+	 * @param value 被检查的元素
+	 * @return 是否包含
+	 */
+	public static <T> boolean contains(T[] array, T value) {
+		final Class<?> componetType = array.getClass().getComponentType();
+		boolean isPrimitive = false;
+		if(null != componetType) {
+			isPrimitive = componetType.isPrimitive();
+		}
+		for (T t : array) {
+			if(t == value) {
+				return true;
+			}else if(false == isPrimitive && null != value && value.equals(t)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * 将Entry集合转换为HashMap
+	 * @param entryCollection entry集合
+	 * @return Map
+	 */
+	public static <T, K> HashMap<T, K> toMap(Collection<Entry<T, K>> entryCollection) {
+		HashMap<T,K> map = new HashMap<T, K>();
+		for (Entry<T, K> entry : entryCollection) {
+			map.put(entry.getKey(), entry.getValue());
+		}
+		return map;
+	}
+	
+	/**
+	 * 将集合转换为排序后的TreeSet
+	 * @param collection 集合
+	 * @param comparator 比较器
+	 * @return treeSet
+	 */
+	public static <T> TreeSet<T> toTreeSet(Collection<T> collection, Comparator<T> comparator){
+		final TreeSet<T> treeSet = new TreeSet<T>(comparator);
+		for (T t : collection) {
+			treeSet.add(t);
+		}
+		return treeSet;
+	}
+	
+	/**
+	 * 排序集合
+	 * @param collection 集合
+	 * @param comparator 比较器
+	 * @return treeSet
+	 */
+	public static <T> List<T> sort(Collection<T> collection, Comparator<T> comparator){
+		List<T> list = new ArrayList<T>(collection);
+		Collections.sort(list, comparator);
+		return list;
+	}
+	
+	//------------------------------------------------------------------- 基本类型的数组转换为包装类型数组
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Integer[] wrap(int... values){
+		final int length = values.length;
+		Integer[] array = new Integer[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Long[] wrap(long... values){
+		final int length = values.length;
+		Long[] array = new Long[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Character[] wrap(char... values){
+		final int length = values.length;
+		Character[] array = new Character[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Byte[] wrap(byte... values){
+		final int length = values.length;
+		Byte[] array = new Byte[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Short[] wrap(short... values){
+		final int length = values.length;
+		Short[] array = new Short[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Float[] wrap(float... values){
+		final int length = values.length;
+		Float[] array = new Float[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Double[] wrap(double... values){
+		final int length = values.length;
+		Double[] array = new Double[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 将基本类型数组包装为包装类型
+	 * @param values 基本类型数组
+	 * @return 包装类型数组
+	 */
+	public static Boolean[] wrap(boolean... values){
+		final int length = values.length;
+		Boolean[] array = new Boolean[length];
+		for(int i = 0; i < length; i++){
+			array[i] = values[i];
+		}
+		return array;
+	}
+	
+	/**
+	 * 判定给定对象是否为数组类型
+	 * @param obj 对象
+	 * @return 是否为数组类型
+	 */
+	public static boolean isArray(Object obj){
+		return obj.getClass().isArray();
+	}
+	
+	/**
+	 * 数组或集合转String
+	 * 
+	 * @param obj 集合或数组对象
+	 * @return 数组字符串,与集合转字符串格式相同
+	 */
+	public static String toString(Object obj) {
+		if (null == obj) {
+			return null;
+		}
+		if (isArray(obj)) {
+			try {
+				return Arrays.deepToString((Object[]) obj);
+			} catch (Exception e) {
+				final String className = obj.getClass().getComponentType().getName();
+				switch (className) {
+					case "long":
+						return Arrays.toString((long[]) obj);
+					case "int":
+						return Arrays.toString((int[]) obj);
+					case "short":
+						return Arrays.toString((short[]) obj);
+					case "char":
+						return Arrays.toString((char[]) obj);
+					case "byte":
+						return Arrays.toString((byte[]) obj);
+					case "boolean":
+						return Arrays.toString((boolean[]) obj);
+					case "float":
+						return Arrays.toString((float[]) obj);
+					case "double":
+						return Arrays.toString((double[]) obj);
+					default:
+						throw new ToolBoxException(e);
+				}
+			}
+		}
+		return obj.toString();
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java
new file mode 100644
index 0000000..e055458
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java
@@ -0,0 +1,67 @@
+package com.stylefeng.guns.core.support;
+
+import java.util.Date;
+
+/**
+ * 封装java.util.Date
+ * @author xiaoleilu
+ *
+ */
+public class DateTime extends Date{
+	private static final long serialVersionUID = -5395712593979185936L;
+	
+	/**
+	 * 转换JDK date为 DateTime
+	 * @param date JDK Date
+	 * @return DateTime
+	 */
+	public static DateTime parse(Date date) {
+		return new DateTime(date);
+	}
+	
+	/**
+	 * 当前时间
+	 */
+	public DateTime() {
+		super();
+	}
+	
+	/**
+	 * 给定日期的构造
+	 * @param date 日期
+	 */
+	public DateTime(Date date) {
+		this(date.getTime());
+	}
+	
+	/**
+	 * 给定日期毫秒数的构造
+	 * @param timeMillis 日期毫秒数
+	 */
+	public DateTime(long timeMillis) {
+		super(timeMillis);
+	}
+	
+	@Override
+	public String toString() {
+		return DateTimeKit.formatDateTime(this);
+	}
+	
+	public String toString(String format) {
+		return DateTimeKit.format(this, format);
+	}
+	
+	/**
+	 * @return 输出精确到毫秒的标准日期形式
+	 */
+	public String toMsStr() {
+		return DateTimeKit.format(this, DateTimeKit.NORM_DATETIME_MS_PATTERN);
+	}
+	
+	/**   
+	 * @return java.util.Date
+	*/
+	public Date toDate() {
+		return new Date(this.getTime());
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java
new file mode 100644
index 0000000..0edfc9c
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java
@@ -0,0 +1,665 @@
+package com.stylefeng.guns.core.support;
+
+import com.stylefeng.guns.core.support.exception.ToolBoxException;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+
+/**
+ * 时间工具类
+ * @author xiaoleilu
+ */
+public class DateTimeKit {
+	/** 毫秒 */
+	public final static long MS = 1;
+	/** 每秒钟的毫秒数 */
+	public final static long SECOND_MS = MS * 1000;
+	/** 每分钟的毫秒数 */
+	public final static long MINUTE_MS = SECOND_MS * 60;
+	/** 每小时的毫秒数 */
+	public final static long HOUR_MS = MINUTE_MS * 60;
+	/** 每天的毫秒数 */
+	public final static long DAY_MS = HOUR_MS * 24;
+
+	/** 标准日期格式 */
+	public final static String NORM_DATE_PATTERN = "yyyy-MM-dd";
+	/** 标准时间格式 */
+	public final static String NORM_TIME_PATTERN = "HH:mm:ss";
+	/** 标准日期时间格式,精确到分 */
+	public final static String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
+	/** 标准日期时间格式,精确到秒 */
+	public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+	/** 标准日期时间格式,精确到毫秒 */
+	public final static String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
+	/** HTTP头中日期时间格式 */
+	public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";
+
+	/** 标准日期(不含时间)格式化器 */
+	// private final static SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat(NORM_DATE_PATTERN);
+	private static ThreadLocal<SimpleDateFormat> NORM_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>(){
+		synchronized protected SimpleDateFormat initialValue() {
+			return new SimpleDateFormat(NORM_DATE_PATTERN);
+		};
+	};
+	/** 标准时间格式化器 */
+	// private final static SimpleDateFormat NORM_TIME_FORMAT = new SimpleDateFormat(NORM_TIME_PATTERN);
+	private static ThreadLocal<SimpleDateFormat> NORM_TIME_FORMAT = new ThreadLocal<SimpleDateFormat>(){
+		synchronized protected SimpleDateFormat initialValue() {
+			return new SimpleDateFormat(NORM_TIME_PATTERN);
+		};
+	};
+	/** 标准日期时间格式化器 */
+	// private final static SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat(NORM_DATETIME_PATTERN);
+	private static ThreadLocal<SimpleDateFormat> NORM_DATETIME_FORMAT = new ThreadLocal<SimpleDateFormat>(){
+		synchronized protected SimpleDateFormat initialValue() {
+			return new SimpleDateFormat(NORM_DATETIME_PATTERN);
+		};
+	};
+	/** HTTP日期时间格式化器 */
+	// private final static SimpleDateFormat HTTP_DATETIME_FORMAT = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);
+	private static ThreadLocal<SimpleDateFormat> HTTP_DATETIME_FORMAT = new ThreadLocal<SimpleDateFormat>(){
+		synchronized protected SimpleDateFormat initialValue() {
+			return new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);
+		};
+	};
+
+	/**
+	 * 当前时间,格式 yyyy-MM-dd HH:mm:ss
+	 * 
+	 * @return 当前时间的标准形式字符串
+	 */
+	public static String now() {
+		return formatDateTime(new DateTime());
+	}
+
+	/**
+	 * 当前时间long
+	 *
+	 * @param isNano 是否为高精度时间
+	 * @return 时间
+	 */
+	public static long current(boolean isNano) {
+		return isNano ? System.nanoTime() : System.currentTimeMillis();
+	}
+
+	/**
+	 * 当前日期,格式 yyyy-MM-dd
+	 *
+	 * @return 当前日期的标准形式字符串
+	 */
+	public static String today() {
+		return formatDate(new DateTime());
+	}
+
+	/**
+	 * @return 当前月份
+	 */
+	public static int thisMonth() {
+		return month(date());
+	}
+
+	/**
+	 * @return 今年
+	 */
+	public static int thisYear() {
+		return year(date());
+	}
+
+	/**
+	 * @return 当前时间
+	 */
+	public static DateTime date() {
+		return new DateTime();
+	}
+
+	/**
+	 * Long类型时间转为Date
+	 *
+	 * @param date Long类型Date(Unix时间戳)
+	 * @return 时间对象
+	 */
+	public static DateTime date(long date) {
+		return new DateTime(date);
+	}
+
+	/**
+	 * 转换为Calendar对象
+	 *
+	 * @param date 日期对象
+	 * @return Calendar对象
+	 */
+	public static Calendar toCalendar(Date date) {
+		final Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		return cal;
+	}
+
+	/**
+	 * 获得月份,从1月开始计数
+	 *
+	 * @param date 日期
+	 * @return 月份
+	 */
+	public static int month(Date date) {
+		return toCalendar(date).get(Calendar.MONTH) + 1;
+	}
+
+	/**
+	 * 获得年
+	 *
+	 * @param date 日期
+	 * @return 年
+	 */
+	public static int year(Date date) {
+		return toCalendar(date).get(Calendar.YEAR);
+	}
+
+	/**
+	 * 获得季节
+	 *
+	 * @param date 日期
+	 * @return 第几个季节
+	 */
+	public static int season(Date date) {
+		return toCalendar(date).get(Calendar.MONTH) / 3 + 1;
+	}
+
+	/**
+	 * 获得指定日期年份和季节<br>
+	 * 格式:[20131]表示2013年第一季度
+	 *
+	 * @param date 日期
+	 * @return Season ,类似于 20132
+	 */
+	public static String yearAndSeason(Date date) {
+		return yearAndSeason(toCalendar(date));
+	}
+
+	/**
+	 * 获得指定日期区间内的年份和季节<br>
+	 *
+	 * @param startDate 其实日期(包含)
+	 * @param endDate 结束日期(包含)
+	 * @return Season列表 ,元素类似于 20132
+	 */
+	public static LinkedHashSet<String> yearAndSeasons(Date startDate, Date endDate) {
+		final LinkedHashSet<String> seasons = new LinkedHashSet<String>();
+		if (startDate == null || endDate == null) {
+			return seasons;
+		}
+
+		final Calendar cal = Calendar.getInstance();
+		cal.setTime(startDate);
+		while (true) {
+			// 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环
+			if (startDate.after(endDate)) {
+				startDate = endDate;
+			}
+
+			seasons.add(yearAndSeason(cal));
+
+			if (startDate.equals(endDate)) {
+				break;
+			}
+
+			cal.add(Calendar.MONTH, 3);
+			startDate = cal.getTime();
+		}
+
+		return seasons;
+	}
+
+	// ------------------------------------ Format start ----------------------------------------------
+	/**
+	 * 根据特定格式格式化日期
+	 *
+	 * @param date 被格式化的日期
+	 * @param format 格式
+	 * @return 格式化后的字符串
+	 */
+	public static String format(Date date, String format) {
+		return new SimpleDateFormat(format).format(date);
+	}
+
+	/**
+	 * 格式 yyyy-MM-dd HH:mm:ss
+	 *
+	 * @param date 被格式化的日期
+	 * @return 格式化后的日期
+	 */
+	public static String formatDateTime(Date date) {
+		if(null == date){
+			return null;
+		}
+		return NORM_DATETIME_FORMAT.get().format(date);
+	}
+
+	/**
+	 * 格式 yyyy-MM-dd
+	 *
+	 * @param date 被格式化的日期
+	 * @return 格式化后的字符串
+	 */
+	public static String formatDate(Date date) {
+		if(null == date){
+			return null;
+		}
+		return NORM_DATE_FORMAT.get().format(date);
+	}
+
+	/**
+	 * 格式化为Http的标准日期格式
+	 *
+	 * @param date 被格式化的日期
+	 * @return HTTP标准形式日期字符串
+	 */
+	public static String formatHttpDate(Date date) {
+		if(null == date){
+			return null;
+		}
+		return HTTP_DATETIME_FORMAT.get().format(date);
+	}
+	// ------------------------------------ Format end ----------------------------------------------
+
+	// ------------------------------------ Parse start ----------------------------------------------
+
+	/**
+	 * 构建DateTime对象
+	 *
+	 * @param dateStr Date字符串
+	 * @param simpleDateFormat 格式化器
+	 * @return DateTime对象
+	 */
+	public static DateTime parse(String dateStr, SimpleDateFormat simpleDateFormat) {
+		try {
+			return new DateTime(simpleDateFormat.parse(dateStr));
+		} catch (Exception e) {
+			throw new ToolBoxException(StrKit.format("Parse [{}] with format [{}] error!", dateStr, simpleDateFormat.toPattern()), e);
+		}
+	}
+
+	/**
+	 * 将特定格式的日期转换为Date对象
+	 *
+	 * @param dateString 特定格式的日期
+	 * @param format 格式,例如yyyy-MM-dd
+	 * @return 日期对象
+	 */
+	public static DateTime parse(String dateString, String format) {
+		return parse(dateString, new SimpleDateFormat(format));
+	}
+
+	/**
+	 * 格式yyyy-MM-dd HH:mm:ss
+	 *
+	 * @param dateString 标准形式的时间字符串
+	 * @return 日期对象
+	 */
+	public static DateTime parseDateTime(String dateString) {
+		return parse(dateString, NORM_DATETIME_FORMAT.get());
+	}
+
+	/**
+	 * 格式yyyy-MM-dd
+	 *
+	 * @param dateString 标准形式的日期字符串
+	 * @return 日期对象
+	 */
+	public static DateTime parseDate(String dateString) {
+		return parse(dateString, NORM_DATE_FORMAT.get());
+	}
+
+	/**
+	 * 格式HH:mm:ss
+	 *
+	 * @param timeString 标准形式的日期字符串
+	 * @return 日期对象
+	 */
+	public static DateTime parseTime(String timeString) {
+		return parse(timeString, NORM_TIME_FORMAT.get());
+	}
+
+	/**
+	 * 格式:<br>
+	 * 1、yyyy-MM-dd HH:mm:ss<br>
+	 * 2、yyyy-MM-dd<br>
+	 * 3、HH:mm:ss<br>
+	 * 4、yyyy-MM-dd HH:mm 5、yyyy-MM-dd HH:mm:ss.SSS
+	 *
+	 * @param dateStr 日期字符串
+	 * @return 日期
+	 */
+	public static DateTime parse(String dateStr) {
+		if (null == dateStr) {
+			return null;
+		}
+		dateStr = dateStr.trim();
+		int length = dateStr.length();
+		try {
+			if (length == NORM_DATETIME_PATTERN.length()) {
+				return parseDateTime(dateStr);
+			} else if (length == NORM_DATE_PATTERN.length()) {
+				return parseDate(dateStr);
+			} else if (length == NORM_TIME_PATTERN.length()) {
+				return parseTime(dateStr);
+			} else if (length == NORM_DATETIME_MINUTE_PATTERN.length()) {
+				return parse(dateStr, NORM_DATETIME_MINUTE_PATTERN);
+			} else if (length >= NORM_DATETIME_MS_PATTERN.length() - 2) {
+				return parse(dateStr, NORM_DATETIME_MS_PATTERN);
+			}
+		} catch (Exception e) {
+			throw new ToolBoxException(StrKit.format("Parse [{}] with format normal error!", dateStr));
+		}
+
+		// 没有更多匹配的时间格式
+		throw new ToolBoxException(StrKit.format(" [{}] format is not fit for date pattern!", dateStr));
+	}
+	// ------------------------------------ Parse end ----------------------------------------------
+
+	// ------------------------------------ Offset start ----------------------------------------------
+	/**
+	 * 获取某天的开始时间
+	 *
+	 * @param date 日期
+	 * @return 某天的开始时间
+	 */
+	public static DateTime getBeginTimeOfDay(Date date) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		calendar.set(Calendar.HOUR_OF_DAY, 0);
+		calendar.set(Calendar.MINUTE, 0);
+		calendar.set(Calendar.SECOND, 0);
+		calendar.set(Calendar.MILLISECOND, 0);
+		return new DateTime(calendar.getTime());
+	}
+
+	/**
+	 * 获取某天的结束时间
+	 *
+	 * @param date 日期
+	 * @return 某天的结束时间
+	 */
+	public static DateTime getEndTimeOfDay(Date date) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		calendar.set(Calendar.HOUR_OF_DAY, 23);
+		calendar.set(Calendar.MINUTE, 59);
+		calendar.set(Calendar.SECOND, 59);
+		calendar.set(Calendar.MILLISECOND, 999);
+		return new DateTime(calendar.getTime());
+	}
+
+	/**
+	 * 昨天
+	 *
+	 * @return 昨天
+	 */
+	public static DateTime yesterday() {
+		return offsiteDay(new DateTime(), -1);
+	}
+
+	/**
+	 * 上周
+	 *
+	 * @return 上周
+	 */
+	public static DateTime lastWeek() {
+		return offsiteWeek(new DateTime(), -1);
+	}
+
+	/**
+	 * 上个月
+	 *
+	 * @return 上个月
+	 */
+	public static DateTime lastMouth() {
+		return offsiteMonth(new DateTime(), -1);
+	}
+
+	/**
+	 * 偏移天
+	 *
+	 * @param date 日期
+	 * @param offsite 偏移天数,正数向未来偏移,负数向历史偏移
+	 * @return 偏移后的日期
+	 */
+	public static DateTime offsiteDay(Date date, int offsite) {
+		return offsiteDate(date, Calendar.DAY_OF_YEAR, offsite);
+	}
+
+	/**
+	 * 偏移周
+	 *
+	 * @param date 日期
+	 * @param offsite 偏移周数,正数向未来偏移,负数向历史偏移
+	 * @return 偏移后的日期
+	 */
+	public static DateTime offsiteWeek(Date date, int offsite) {
+		return offsiteDate(date, Calendar.WEEK_OF_YEAR, offsite);
+	}
+
+	/**
+	 * 偏移月
+	 *
+	 * @param date 日期
+	 * @param offsite 偏移月数,正数向未来偏移,负数向历史偏移
+	 * @return 偏移后的日期
+	 */
+	public static DateTime offsiteMonth(Date date, int offsite) {
+		return offsiteDate(date, Calendar.MONTH, offsite);
+	}
+
+	/**
+	 * 获取指定日期偏移指定时间后的时间
+	 *
+	 * @param date 基准日期
+	 * @param calendarField 偏移的粒度大小(小时、天、月等)使用Calendar中的常数
+	 * @param offsite 偏移量,正数为向后偏移,负数为向前偏移
+	 * @return 偏移后的日期
+	 */
+	public static DateTime offsiteDate(Date date, int calendarField, int offsite) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		cal.add(calendarField, offsite);
+		return new DateTime(cal.getTime());
+	}
+	// ------------------------------------ Offset end ----------------------------------------------
+
+	/**
+	 * 判断两个日期相差的时长<br/>
+	 * 返回 minuend - subtrahend 的差
+	 * 
+	 * @param subtrahend 减数日期
+	 * @param minuend 被减数日期
+	 * @param diffField 相差的选项:相差的天、小时
+	 * @return 日期差
+	 */
+	public static long diff(Date subtrahend, Date minuend, long diffField) {
+		long diff = minuend.getTime() - subtrahend.getTime();
+		return diff / diffField;
+	}
+
+	/**
+	 * 计时,常用于记录某段代码的执行时间,单位:纳秒
+	 * 
+	 * @param preTime 之前记录的时间
+	 * @return 时间差,纳秒
+	 */
+	public static long spendNt(long preTime) {
+		return System.nanoTime() - preTime;
+	}
+
+	/**
+	 * 计时,常用于记录某段代码的执行时间,单位:毫秒
+	 * 
+	 * @param preTime 之前记录的时间
+	 * @return 时间差,毫秒
+	 */
+	public static long spendMs(long preTime) {
+		return System.currentTimeMillis() - preTime;
+	}
+
+	/**
+	 * 格式化成yyMMddHHmm后转换为int型
+	 * 
+	 * @param date 日期
+	 * @return int
+	 */
+	public static int toIntSecond(Date date) {
+		return Integer.parseInt(format(date, "yyMMddHHmm"));
+	}
+
+	/**
+	 * 计算指定指定时间区间内的周数
+	 * 
+	 * @param start 开始时间
+	 * @param end 结束时间
+	 * @return 周数
+	 */
+	public static int weekCount(Date start, Date end) {
+		final Calendar startCalendar = Calendar.getInstance();
+		startCalendar.setTime(start);
+		final Calendar endCalendar = Calendar.getInstance();
+		endCalendar.setTime(end);
+
+		final int startWeekofYear = startCalendar.get(Calendar.WEEK_OF_YEAR);
+		final int endWeekofYear = endCalendar.get(Calendar.WEEK_OF_YEAR);
+
+		int count = endWeekofYear - startWeekofYear + 1;
+
+		if (Calendar.SUNDAY != startCalendar.get(Calendar.DAY_OF_WEEK)) {
+			count--;
+		}
+
+		return count;
+	}
+
+	/**
+	 * 计时器<br>
+	 * 计算某个过程话费的时间,精确到毫秒
+	 * 
+	 * @return Timer
+	 */
+	public static Timer timer() {
+		return new Timer();
+
+	}
+	
+	/**
+	 * 生日转为年龄,计算法定年龄
+	 * @param birthDay 生日,标准日期字符串
+	 * @return 年龄
+	 * @throws Exception
+	 */
+	public static int ageOfNow(String birthDay) {
+		return ageOfNow(parse(birthDay));
+	}
+
+	/**
+	 * 生日转为年龄,计算法定年龄
+	 * @param birthDay 生日
+	 * @return 年龄
+	 * @throws Exception
+	 */
+	public static int ageOfNow(Date birthDay) {
+		return age(birthDay,date());
+	}
+	
+	/**
+	 * 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄
+	 * @param birthDay 生日
+	 * @param dateToCompare 需要对比的日期
+	 * @return 年龄
+	 * @throws Exception
+	 */
+	public static int age(Date birthDay, Date dateToCompare) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(dateToCompare);
+
+		if (cal.before(birthDay)) {
+			throw new IllegalArgumentException(StrKit.format("Birthday is after date {}!", formatDate(dateToCompare)));
+		}
+
+		int year = cal.get(Calendar.YEAR);
+		int month = cal.get(Calendar.MONTH);
+		int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
+
+		cal.setTime(birthDay);
+		int age = year - cal.get(Calendar.YEAR);
+		
+		int monthBirth = cal.get(Calendar.MONTH);
+		if (month == monthBirth) {
+			int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
+			if (dayOfMonth < dayOfMonthBirth) {
+				//如果生日在当月,但是未达到生日当天的日期,年龄减一
+				age--;
+			}
+		} else if (month < monthBirth){
+			//如果当前月份未达到生日的月份,年龄计算减一
+			age--;
+		}
+
+		return age;
+	}
+
+	/**
+	 * 计时器<br>
+	 * 计算某个过程话费的时间,精确到毫秒
+	 * 
+	 * @author Looly
+	 *
+	 */
+	public static class Timer {
+		private long time;
+		private boolean isNano;
+
+		public Timer() {
+			this(false);
+		}
+
+		public Timer(boolean isNano) {
+			this.isNano = isNano;
+			start();
+		}
+
+		/**
+		 * @return 开始计时并返回当前时间
+		 */
+		public long start() {
+			time = current(isNano);
+			return time;
+		}
+
+		/**
+		 * @return 重新计时并返回从开始到当前的持续时间
+		 */
+		public long durationRestart() {
+			long now = current(isNano);
+			long d = now - time;
+			time = now;
+			return d;
+		}
+
+		/**
+		 * @return 从开始到当前的持续时间
+		 */
+		public long duration() {
+			return current(isNano) - time;
+		}
+	}
+
+	// ------------------------------------------------------------------------ Private method start
+	/**
+	 * 获得指定日期年份和季节<br>
+	 * 格式:[20131]表示2013年第一季度
+	 * 
+	 * @param cal 日期
+	 */
+	private static String yearAndSeason(Calendar cal) {
+		return new StringBuilder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString();
+	}
+	// ------------------------------------------------------------------------ Private method end
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java
new file mode 100644
index 0000000..61dcc03
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java
@@ -0,0 +1,254 @@
+package com.stylefeng.guns.core.support;
+
+import java.nio.charset.Charset;
+
+/**
+ * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br>
+ * 例如十进制数57,在二进制写作111001,在16进制写作39。<br>
+ * 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br>
+ * 
+ * 参考:https://my.oschina.net/xinxingegeya/blog/287476
+ * 
+ * @author Looly
+ *
+ */
+public class HexKit {
+
+	/**
+	 * 用于建立十六进制字符的输出的小写字符数组
+	 */
+	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+	/**
+	 * 用于建立十六进制字符的输出的大写字符数组
+	 */
+	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+	//---------------------------------------------------------------------------------------------------- encode
+	/**
+	 * 将字节数组转换为十六进制字符数组
+	 *
+	 * @param data byte[]
+	 * @return 十六进制char[]
+	 */
+	public static char[] encodeHex(byte[] data) {
+		return encodeHex(data, true);
+	}
+	
+	/**
+	 * 将字节数组转换为十六进制字符数组
+	 *
+	 * @param str 字符串
+	 * @param charset 编码
+	 * @return 十六进制char[]
+	 */
+	public static char[] encodeHex(String str, Charset charset) {
+		return encodeHex(StrKit.getBytes(str, charset), true);
+	}
+
+	/**
+	 * 将字节数组转换为十六进制字符数组
+	 *
+	 * @param data byte[]
+	 * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
+	 * @return 十六进制char[]
+	 */
+	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+	}
+
+	/**
+	 * 将字节数组转换为十六进制字符串
+	 *
+	 * @param data byte[]
+	 * @return 十六进制String
+	 */
+	public static String encodeHexStr(byte[] data) {
+		return encodeHexStr(data, true);
+	}
+
+	/**
+	 * 将字节数组转换为十六进制字符串
+	 *
+	 * @param data byte[]
+	 * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
+	 * @return 十六进制String
+	 */
+	public static String encodeHexStr(byte[] data, boolean toLowerCase) {
+		return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+	}
+	
+	//---------------------------------------------------------------------------------------------------- decode
+	/**
+	 * 将十六进制字符数组转换为字符串
+	 *
+	 * @param hexStr 十六进制String
+	 * @param charset 编码
+	 * @return 字符串
+	 */
+	public static String decodeHexStr(String hexStr, Charset charset) {
+		if(StrKit.isEmpty(hexStr)){
+			return hexStr;
+		}
+		return decodeHexStr(hexStr.toCharArray(), charset);
+	}
+	
+	/**
+	 * 将十六进制字符数组转换为字符串
+	 *
+	 * @param hexData 十六进制char[]
+	 * @param charset 编码
+	 * @return 字符串
+	 */
+	public static String decodeHexStr(char[] hexData, Charset charset) {
+		return StrKit.str(decodeHex(hexData), charset);
+	}
+
+	/**
+	 * 将十六进制字符数组转换为字节数组
+	 *
+	 * @param hexData 十六进制char[]
+	 * @return byte[]
+	 * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
+	 */
+	public static byte[] decodeHex(char[] hexData) {
+
+		int len = hexData.length;
+
+		if ((len & 0x01) != 0) {
+			throw new RuntimeException("Odd number of characters.");
+		}
+
+		byte[] out = new byte[len >> 1];
+
+		// two characters form the hex value.
+		for (int i = 0, j = 0; j < len; i++) {
+			int f = toDigit(hexData[j], j) << 4;
+			j++;
+			f = f | toDigit(hexData[j], j);
+			j++;
+			out[i] = (byte) (f & 0xFF);
+		}
+
+		return out;
+	}
+	
+	//---------------------------------------------------------------------------------------- Private method start
+	/**
+	 * 将字节数组转换为十六进制字符串
+	 *
+	 * @param data byte[]
+	 * @param toDigits 用于控制输出的char[]
+	 * @return 十六进制String
+	 */
+	private static String encodeHexStr(byte[] data, char[] toDigits) {
+		return new String(encodeHex(data, toDigits));
+	}
+	
+	/**
+	 * 将字节数组转换为十六进制字符数组
+	 *
+	 * @param data byte[]
+	 * @param toDigits 用于控制输出的char[]
+	 * @return 十六进制char[]
+	 */
+	private static char[] encodeHex(byte[] data, char[] toDigits) {
+		int l = data.length;
+		char[] out = new char[l << 1];
+		// two characters form the hex value.
+		for (int i = 0, j = 0; i < l; i++) {
+			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+			out[j++] = toDigits[0x0F & data[i]];
+		}
+		return out;
+	}
+
+	/**
+	 * 将十六进制字符转换成一个整数
+	 *
+	 * @param ch 十六进制char
+	 * @param index 十六进制字符在字符数组中的位置
+	 * @return 一个整数
+	 * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
+	 */
+	private static int toDigit(char ch, int index) {
+		int digit = Character.digit(ch, 16);
+		if (digit == -1) {
+			throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index);
+		}
+		return digit;
+	}
+	//---------------------------------------------------------------------------------------- Private method end
+	
+	
+	
+	/**
+	 * 2进制转16进制
+	 * @param bString 2进制字符串
+	 * @return
+	 */
+	public static String binary2Hex(String bString) {
+		if (bString == null || bString.equals("") || bString.length() % 8 != 0)
+			return null;
+		StringBuffer tmp = new StringBuffer();
+		int iTmp = 0;
+		for (int i = 0; i < bString.length(); i += 4) {
+			iTmp = 0;
+			for (int j = 0; j < 4; j++) {
+				iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1);
+			}
+			tmp.append(Integer.toHexString(iTmp));
+		}
+		return tmp.toString();
+	}
+
+	/**
+	 * 16进制转2进制
+	 * @param hexString
+	 * @return
+	 */
+	public static String hex2Binary(String hexString) {
+		if (hexString == null || hexString.length() % 2 != 0)
+			return null;
+		String bString = "", tmp;
+		for (int i = 0; i < hexString.length(); i++) {
+			tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
+			bString += tmp.substring(tmp.length() - 4);
+		}
+		return bString;
+	}
+
+	/**
+	 * 将二进制转换成16进制
+	 * @param buf
+	 * @return
+	 */
+	public static String binary2Hex(byte buf[]) {
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < buf.length; i++) {
+			String hex = Integer.toHexString(buf[i] & 0xFF);
+			if (hex.length() == 1) {
+				hex = '0' + hex;
+			}
+			sb.append(hex.toUpperCase());
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 将16进制转换为二进制
+	 * @param hexStr
+	 * @return
+	 */
+	public static byte[] hex2Byte(String hexStr) {
+		if (hexStr.length() < 1)
+			return null;
+		byte[] result = new byte[hexStr.length() / 2];
+		for (int i = 0; i < hexStr.length() / 2; i++) {
+			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
+			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
+			result[i] = (byte) (high * 16 + low);
+		}
+		return result;
+	}
+	
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java
new file mode 100644
index 0000000..be94455
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.support;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Enumeration;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class HttpKit {
+
+    public static String getIp(){
+       return HttpKit.getRequest().getRemoteHost();
+    }
+
+    /**
+     * 获取所有请求的值
+     */
+    public static Map<String, String> getRequestParameters() {
+        HashMap<String, String> values = new HashMap<>();
+        HttpServletRequest request = HttpKit.getRequest();
+        Enumeration enums = request.getParameterNames();
+        while ( enums.hasMoreElements()){
+            String paramName = (String) enums.nextElement();
+            String paramValue = request.getParameter(paramName);
+            values.put(paramName, paramValue);
+        }
+        return values;
+    }
+
+    /**
+     * 获取 HttpServletRequest
+     */
+    public static HttpServletResponse getResponse() {
+        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+        return response;
+    }
+
+    /**
+     * 获取 包装防Xss Sql注入的 HttpServletRequest
+     * @return request
+     */
+    public static HttpServletRequest getRequest() {
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        return new WafRequestWrapper(request);
+    }
+
+    /**
+     * 向指定URL发送GET方法的请求
+     *
+     * @param url 发送请求的URL
+     * @param param 请求参数
+     * @return URL 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, Map<String, String> param) {
+        String result = "";
+        BufferedReader in = null;
+        try {
+            StringBuffer query = new StringBuffer();
+
+            for (Map.Entry<String, String> kv : param.entrySet()) {
+                query.append(URLEncoder.encode(kv.getKey(), "UTF-8") + "=");
+                query.append(URLEncoder.encode(kv.getValue(), "UTF-8") + "&");
+            }
+            if (query.lastIndexOf("&") > 0) {
+                query.deleteCharAt(query.length() - 1);
+            }
+
+            String urlNameString = url + "?" + query.toString();
+            URL realUrl = new URL(urlNameString);
+            // 打开和URL之间的连接
+            URLConnection connection = realUrl.openConnection();
+            // 设置通用的请求属性
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            // 建立实际的连接
+            connection.connect();
+            // 获取所有响应头字段
+            Map<String, List<String>> map = connection.getHeaderFields();
+            // 遍历所有的响应头字段
+            for (String key : map.keySet()) {
+                System.out.println(key + "--->" + map.get(key));
+            }
+            // 定义 BufferedReader输入流来读取URL的响应
+            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+            String line;
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+        } catch (Exception e) {
+            System.out.println("发送GET请求出现异常!" + e);
+            e.printStackTrace();
+        }
+        // 使用finally块来关闭输入流
+        finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (Exception e2) {
+                e2.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param  请求参数
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendPost(String url, Map<String, String> param) {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        String result = "";
+        try {
+            String para = "";
+            for (String key : param.keySet()) {
+                para += (key + "=" + param.get(key) + "&");
+            }
+            if (para.lastIndexOf("&") > 0) {
+                para = para.substring(0, para.length() - 1);
+            }
+            String urlNameString = url + "?" + para;
+            URL realUrl = new URL(urlNameString);
+            // 打开和URL之间的连接
+            URLConnection conn = realUrl.openConnection();
+            // 设置通用的请求属性
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            // 发送POST请求必须设置如下两行
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            // 获取URLConnection对象对应的输出流
+            out = new PrintWriter(conn.getOutputStream());
+            // 发送请求参数
+            out.print(param);
+            // flush输出流的缓冲
+            out.flush();
+            // 定义BufferedReader输入流来读取URL的响应
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+            String line;
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+        } catch (Exception e) {
+            System.out.println("发送 POST 请求出现异常!" + e);
+            e.printStackTrace();
+        }
+        // 使用finally块来关闭输出流、输入流
+        finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+                if (in != null) {
+                    in.close();
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java
new file mode 100644
index 0000000..d0f83e4
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java
@@ -0,0 +1,22 @@
+package com.stylefeng.guns.core.support;
+
+/**
+ * 一些通用的函数
+ * 
+ * @author Looly
+ *
+ */
+public class ObjectKit {
+	/**
+	 * 比较两个对象是否相等。<br>
+	 * 相同的条件有两个,满足其一即可:<br>
+	 * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
+	 * 
+	 * @param obj1 对象1
+	 * @param obj2 对象2
+	 * @return 是否相等
+	 */
+	public static boolean equals(Object obj1, Object obj2) {
+		return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java
new file mode 100644
index 0000000..a57a9c2
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java
@@ -0,0 +1,57 @@
+package com.stylefeng.guns.core.support;
+
+/**
+ * 分页工具类
+ * 
+ * @author xiaoleilu
+ * 
+ */
+public class PageKit {
+
+	/**
+	 * 将页数和每页条目数转换为开始位置和结束位置<br>
+	 * 此方法用于不包括结束位置的分页方法<br>
+	 * 例如:<br>
+	 * 页码:1,每页10 -> [0, 10]<br>
+	 * 页码:2,每页10 -> [10, 20]<br>
+	 * 。。。<br>
+	 * 
+	 * @param pageNo
+	 *            页码(从1计数)
+	 * @param countPerPage
+	 *            每页条目数
+	 * @return 第一个数为开始位置,第二个数为结束位置
+	 */
+	public static int[] transToStartEnd(int pageNo, int countPerPage) {
+		if (pageNo < 1) {
+			pageNo = 1;
+		}
+
+		if (countPerPage < 1) {
+			countPerPage = 0;
+//			LogKit.warn("Count per page  [" + countPerPage + "] is not valid!");
+		}
+
+		int start = (pageNo - 1) * countPerPage;
+		int end = start + countPerPage;
+
+		return new int[] { start, end };
+	}
+
+	/**
+	 * 根据总数计算总页数
+	 * 
+	 * @param totalCount
+	 *            总数
+	 * @param numPerPage
+	 *            每页数
+	 * @return 总页数
+	 */
+	public static int totalPage(int totalCount, int numPerPage) {
+		if (numPerPage == 0) {
+			return 0;
+		}
+		return totalCount % numPerPage == 0 ? (totalCount / numPerPage)
+				: (totalCount / numPerPage + 1);
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java
new file mode 100644
index 0000000..49aa9ab
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java
@@ -0,0 +1,1370 @@
+package com.stylefeng.guns.core.support;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * 字符串工具类
+ * 
+ * @author xiaoleilu
+ *
+ */
+public class StrKit {
+
+	public static final String SPACE = " ";
+	public static final String DOT = ".";
+	public static final String SLASH = "/";
+	public static final String BACKSLASH = "\\";
+	public static final String EMPTY = "";
+	public static final String CRLF = "\r\n";
+	public static final String NEWLINE = "\n";
+	public static final String UNDERLINE = "_";
+	public static final String COMMA = ",";
+
+	public static final String HTML_NBSP = "&nbsp;";
+	public static final String HTML_AMP = "&amp";
+	public static final String HTML_QUOTE = "&quot;";
+	public static final String HTML_LT = "&lt;";
+	public static final String HTML_GT = "&gt;";
+
+	public static final String EMPTY_JSON = "{}";
+
+
+	/**
+	 * 首字母变小写
+	 */
+	public static String firstCharToLowerCase(String str) {
+		char firstChar = str.charAt(0);
+		if (firstChar >= 'A' && firstChar <= 'Z') {
+			char[] arr = str.toCharArray();
+			arr[0] += ('a' - 'A');
+			return new String(arr);
+		}
+		return str;
+	}
+	
+	/**
+	 * 首字母变大写
+	 */
+	public static String firstCharToUpperCase(String str) {
+		char firstChar = str.charAt(0);
+		if (firstChar >= 'a' && firstChar <= 'z') {
+			char[] arr = str.toCharArray();
+			arr[0] -= ('a' - 'A');
+			return new String(arr);
+		}
+		return str;
+	}
+
+	// ------------------------------------------------------------------------ Blank
+	/**
+	 * 字符串是否为空白 空白的定义如下: <br>
+	 * 1、为null <br>
+	 * 2、为不可见字符(如空格)<br>
+	 * 3、""<br>
+	 * 
+	 * @param str 被检测的字符串
+	 * @return 是否为空
+	 */
+	public static boolean isBlank(String str) {
+		int length;
+		if ((str == null) || ((length = str.length()) == 0)) {
+			return true;
+		}
+		for (int i = 0; i < length; i++) {
+			// 只要有一个非空字符即为非空字符串
+			if (false == Character.isWhitespace(str.charAt(i))) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * 字符串是否为非空白 空白的定义如下: <br>
+	 * 1、不为null <br>
+	 * 2、不为不可见字符(如空格)<br>
+	 * 3、不为""<br>
+	 * 
+	 * @param str 被检测的字符串
+	 * @return 是否为非空
+	 */
+	public static boolean notBlank(String str) {
+		return false == isBlank(str);
+	}
+
+	/**
+	 * 是否包含空字符串
+	 * 
+	 * @param strs 字符串列表
+	 * @return 是否包含空字符串
+	 */
+	public static boolean hasBlank(String... strs) {
+		if (CollectionKit.isEmpty(strs)) {
+			return true;
+		}
+		for (String str : strs) {
+			if (isBlank(str)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 给定所有字符串是否为空白
+	 * 
+	 * @param strs 字符串
+	 * @return 所有字符串是否为空白
+	 */
+	public static boolean isAllBlank(String... strs) {
+		if (CollectionKit.isEmpty(strs)) {
+			return true;
+		}
+		for (String str : strs) {
+			if (notBlank(str)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	// ------------------------------------------------------------------------ Empty
+	/**
+	 * 字符串是否为空,空的定义如下 1、为null <br>
+	 * 2、为""<br>
+	 * 
+	 * @param str 被检测的字符串
+	 * @return 是否为空
+	 */
+	public static boolean isEmpty(String str) {
+		return str == null || str.length() == 0;
+	}
+
+	/**
+	 * 字符串是否为非空白 空白的定义如下: <br>
+	 * 1、不为null <br>
+	 * 2、不为""<br>
+	 * 
+	 * @param str 被检测的字符串
+	 * @return 是否为非空
+	 */
+	public static boolean isNotEmpty(String str) {
+		return false == isEmpty(str);
+	}
+
+	/**
+	 * 当给定字符串为null时,转换为Empty
+	 * 
+	 * @param str 被转换的字符串
+	 * @return 转换后的字符串
+	 */
+	public static String nullToEmpty(String str) {
+		return nullToDefault(str, EMPTY);
+	}
+
+	/**
+	 * 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。
+	 * 
+	 * <pre>
+	 * nullToDefault(null, &quot;default&quot;)  = &quot;default&quot;
+	 * nullToDefault(&quot;&quot;, &quot;default&quot;)    = &quot;&quot;
+	 * nullToDefault(&quot;  &quot;, &quot;default&quot;)  = &quot;  &quot;
+	 * nullToDefault(&quot;bat&quot;, &quot;default&quot;) = &quot;bat&quot;
+	 * </pre>
+	 * 
+	 * @param str 要转换的字符串
+	 * @param defaultStr 默认字符串
+	 * 
+	 * @return 字符串本身或指定的默认字符串
+	 */
+	public static String nullToDefault(String str, String defaultStr) {
+		return (str == null) ? defaultStr : str;
+	}
+
+	/**
+	 * 当给定字符串为空字符串时,转换为<code>null</code>
+	 * 
+	 * @param str 被转换的字符串
+	 * @return 转换后的字符串
+	 */
+	public static String emptyToNull(String str) {
+		return isEmpty(str) ? null : str;
+	}
+
+	/**
+	 * 是否包含空字符串
+	 * 
+	 * @param strs 字符串列表
+	 * @return 是否包含空字符串
+	 */
+	public static boolean hasEmpty(String... strs) {
+		if (CollectionKit.isEmpty(strs)) {
+			return true;
+		}
+
+		for (String str : strs) {
+			if (isEmpty(str)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 是否全部为空字符串
+	 * 
+	 * @param strs 字符串列表
+	 * @return 是否全部为空字符串
+	 */
+	public static boolean isAllEmpty(String... strs) {
+		if (CollectionKit.isEmpty(strs)) {
+			return true;
+		}
+
+		for (String str : strs) {
+			if (isNotEmpty(str)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	// ------------------------------------------------------------------------ Trim
+	/**
+	 * 除去字符串头尾部的空白,如果字符串是<code>null</code>,依然返回<code>null</code>。
+	 * 
+	 * <p>
+	 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。
+	 * 
+	 * <pre>
+	 * trim(null)          = null
+	 * trim(&quot;&quot;)            = &quot;&quot;
+	 * trim(&quot;     &quot;)       = &quot;&quot;
+	 * trim(&quot;abc&quot;)         = &quot;abc&quot;
+	 * trim(&quot;    abc    &quot;) = &quot;abc&quot;
+	 * </pre>
+	 * 
+	 * </p>
+	 * 
+	 * @param str 要处理的字符串
+	 * 
+	 * @return 除去空白的字符串,如果原字串为<code>null</code>,则返回<code>null</code>
+	 */
+	public static String trim(String str) {
+		return (null == str) ? null : trim(str, 0);
+	}
+
+	/**
+	 * 给定字符串数组全部做去首尾空格
+	 * 
+	 * @param strs 字符串数组
+	 */
+	public static void trim(String[] strs) {
+		if (null == strs) {
+			return;
+		}
+		String str;
+		for (int i = 0; i < strs.length; i++) {
+			str = strs[i];
+			if (null != str) {
+				strs[i] = str.trim();
+			}
+		}
+	}
+
+	/**
+	 * 除去字符串头部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。
+	 * 
+	 * <p>
+	 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。
+	 * 
+	 * <pre>
+	 * trimStart(null)         = null
+	 * trimStart(&quot;&quot;)           = &quot;&quot;
+	 * trimStart(&quot;abc&quot;)        = &quot;abc&quot;
+	 * trimStart(&quot;  abc&quot;)      = &quot;abc&quot;
+	 * trimStart(&quot;abc  &quot;)      = &quot;abc  &quot;
+	 * trimStart(&quot; abc &quot;)      = &quot;abc &quot;
+	 * </pre>
+	 * 
+	 * </p>
+	 * 
+	 * @param str 要处理的字符串
+	 * 
+	 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回 <code>null</code>
+	 */
+	public static String trimStart(String str) {
+		return trim(str, -1);
+	}
+
+	/**
+	 * 除去字符串尾部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。
+	 * 
+	 * <p>
+	 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。
+	 * 
+	 * <pre>
+	 * trimEnd(null)       = null
+	 * trimEnd(&quot;&quot;)         = &quot;&quot;
+	 * trimEnd(&quot;abc&quot;)      = &quot;abc&quot;
+	 * trimEnd(&quot;  abc&quot;)    = &quot;  abc&quot;
+	 * trimEnd(&quot;abc  &quot;)    = &quot;abc&quot;
+	 * trimEnd(&quot; abc &quot;)    = &quot; abc&quot;
+	 * </pre>
+	 * 
+	 * </p>
+	 * 
+	 * @param str 要处理的字符串
+	 * 
+	 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回 <code>null</code>
+	 */
+	public static String trimEnd(String str) {
+		return trim(str, 1);
+	}
+
+	/**
+	 * 除去字符串头尾部的空白符,如果字符串是<code>null</code>,依然返回<code>null</code>。
+	 * 
+	 * @param str 要处理的字符串
+	 * @param mode <code>-1</code>表示trimStart,<code>0</code>表示trim全部, <code>1</code>表示trimEnd
+	 * 
+	 * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code>
+	 */
+	public static String trim(String str, int mode) {
+		if (str == null) {
+			return null;
+		}
+
+		int length = str.length();
+		int start = 0;
+		int end = length;
+
+		// 扫描字符串头部
+		if (mode <= 0) {
+			while ((start < end) && (Character.isWhitespace(str.charAt(start)))) {
+				start++;
+			}
+		}
+
+		// 扫描字符串尾部
+		if (mode >= 0) {
+			while ((start < end) && (Character.isWhitespace(str.charAt(end - 1)))) {
+				end--;
+			}
+		}
+
+		if ((start > 0) || (end < length)) {
+			return str.substring(start, end);
+		}
+
+		return str;
+	}
+	
+	/**
+	 * 是否以指定字符串开头
+	 * @param str 被监测字符串
+	 * @param prefix 开头字符串
+	 * @param isIgnoreCase 是否忽略大小写
+	 * @return 是否以指定字符串开头
+	 */
+	public static boolean startWith(String str, String prefix, boolean isIgnoreCase){
+		if(isIgnoreCase){
+			return str.toLowerCase().startsWith(prefix.toLowerCase());
+		}else{
+			return str.startsWith(prefix);
+		}
+	}
+	
+	/**
+	 * 是否以指定字符串结尾
+	 * @param str 被监测字符串
+	 * @param suffix 结尾字符串
+	 * @param isIgnoreCase 是否忽略大小写
+	 * @return 是否以指定字符串结尾
+	 */
+	public static boolean endWith(String str, String suffix, boolean isIgnoreCase){
+		if(isIgnoreCase){
+			return str.toLowerCase().endsWith(suffix.toLowerCase());
+		}else{
+			return str.endsWith(suffix);
+		}
+	}
+	
+	/**
+	 * 是否包含特定字符,忽略大小写,如果给定两个参数都为<code>null</code>,返回true
+	 * @param str 被检测字符串
+	 * @param testStr 被测试是否包含的字符串
+	 * @return 是否包含
+	 */
+	public static boolean containsIgnoreCase(String str, String testStr){
+		if(null == str){
+			//如果被监测字符串和 
+			return null == testStr;
+		}
+		return str.toLowerCase().contains(testStr.toLowerCase());
+	}
+
+	/**
+	 * 获得set或get方法对应的标准属性名<br/>
+	 * 例如:setName 返回 name
+	 * 
+	 * @param getOrSetMethodName
+	 * @return 如果是set或get方法名,返回field, 否则null
+	 */
+	public static String getGeneralField(String getOrSetMethodName) {
+		if (getOrSetMethodName.startsWith("get") || getOrSetMethodName.startsWith("set")) {
+			return cutPreAndLowerFirst(getOrSetMethodName, 3);
+		}
+		return null;
+	}
+
+	/**
+	 * 生成set方法名<br/>
+	 * 例如:name 返回 setName
+	 * 
+	 * @param fieldName 属性名
+	 * @return setXxx
+	 */
+	public static String genSetter(String fieldName) {
+		return upperFirstAndAddPre(fieldName, "set");
+	}
+
+	/**
+	 * 生成get方法名
+	 * 
+	 * @param fieldName 属性名
+	 * @return getXxx
+	 */
+	public static String genGetter(String fieldName) {
+		return upperFirstAndAddPre(fieldName, "get");
+	}
+
+	/**
+	 * 去掉首部指定长度的字符串并将剩余字符串首字母小写<br/>
+	 * 例如:str=setName, preLength=3 -> return name
+	 * 
+	 * @param str 被处理的字符串
+	 * @param preLength 去掉的长度
+	 * @return 处理后的字符串,不符合规范返回null
+	 */
+	public static String cutPreAndLowerFirst(String str, int preLength) {
+		if (str == null) {
+			return null;
+		}
+		if (str.length() > preLength) {
+			char first = Character.toLowerCase(str.charAt(preLength));
+			if (str.length() > preLength + 1) {
+				return first + str.substring(preLength + 1);
+			}
+			return String.valueOf(first);
+		}
+		return null;
+	}
+
+	/**
+	 * 原字符串首字母大写并在其首部添加指定字符串 例如:str=name, preString=get -> return getName
+	 * 
+	 * @param str 被处理的字符串
+	 * @param preString 添加的首部
+	 * @return 处理后的字符串
+	 */
+	public static String upperFirstAndAddPre(String str, String preString) {
+		if (str == null || preString == null) {
+			return null;
+		}
+		return preString + upperFirst(str);
+	}
+
+	/**
+	 * 大写首字母<br>
+	 * 例如:str = name, return Name
+	 * 
+	 * @param str 字符串
+	 * @return 字符串
+	 */
+	public static String upperFirst(String str) {
+		return Character.toUpperCase(str.charAt(0)) + str.substring(1);
+	}
+
+	/**
+	 * 小写首字母<br>
+	 * 例如:str = Name, return name
+	 * 
+	 * @param str 字符串
+	 * @return 字符串
+	 */
+	public static String lowerFirst(String str) {
+		if(isBlank(str)){
+			return str;
+		}
+		return Character.toLowerCase(str.charAt(0)) + str.substring(1);
+	}
+
+	/**
+	 * 去掉指定前缀
+	 * 
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @return 切掉后的字符串,若前缀不是 preffix, 返回原字符串
+	 */
+	public static String removePrefix(String str, String prefix) {
+		if(isEmpty(str) || isEmpty(prefix)){
+			return str;
+		}
+		
+		if (str.startsWith(prefix)) {
+			return str.substring(prefix.length());
+		}
+		return str;
+	}
+
+	/**
+	 * 忽略大小写去掉指定前缀
+	 * 
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @return 切掉后的字符串,若前缀不是 prefix, 返回原字符串
+	 */
+	public static String removePrefixIgnoreCase(String str, String prefix) {
+		if(isEmpty(str) || isEmpty(prefix)){
+			return str;
+		}
+		
+		if (str.toLowerCase().startsWith(prefix.toLowerCase())) {
+			return str.substring(prefix.length());
+		}
+		return str;
+	}
+
+	/**
+	 * 去掉指定后缀
+	 * 
+	 * @param str 字符串
+	 * @param suffix 后缀
+	 * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
+	 */
+	public static String removeSuffix(String str, String suffix) {
+		if(isEmpty(str) || isEmpty(suffix)){
+			return str;
+		}
+		
+		if (str.endsWith(suffix)) {
+			return str.substring(0, str.length() - suffix.length());
+		}
+		return str;
+	}
+	
+	/**
+	 * 获得字符串对应byte数组
+	 * @param str 字符串
+	 * @param charset 编码,如果为<code>null</code>使用系统默认编码
+	 * @return bytes
+	 */
+	public static byte[] getBytes(String str, Charset charset){
+		if(null == str){
+			return null;
+		}
+		return null == charset ? str.getBytes() : str.getBytes(charset);
+	}
+
+	/**
+	 * 忽略大小写去掉指定后缀
+	 * 
+	 * @param str 字符串
+	 * @param suffix 后缀
+	 * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
+	 */
+	public static String removeSuffixIgnoreCase(String str, String suffix) {
+		if(isEmpty(str) || isEmpty(suffix)){
+			return str;
+		}
+		
+		if (str.toLowerCase().endsWith(suffix.toLowerCase())) {
+			return str.substring(0, str.length() - suffix.length());
+		}
+		return str;
+	}
+	
+	/**
+	 * 如果给定字符串不是以prefix开头的,在开头补充 prefix
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @return 补充后的字符串
+	 */
+	public static String addPrefixIfNot(String str, String prefix){
+		if(isEmpty(str) || isEmpty(prefix)){
+			return str;
+		}
+		if(false == str.startsWith(prefix)){
+			str = prefix + str;
+		}
+		return str;
+	}
+	
+	/**
+	 * 如果给定字符串不是以suffix结尾的,在尾部补充 suffix
+	 * @param str 字符串
+	 * @param suffix 后缀
+	 * @return 补充后的字符串
+	 */
+	public static String addSuffixIfNot(String str, String suffix){
+		if(isEmpty(str) || isEmpty(suffix)){
+			return str;
+		}
+		if(false == str.endsWith(suffix)){
+			str += suffix;
+		}
+		return str;
+	}
+
+	/**
+	 * 清理空白字符
+	 * 
+	 * @param str 被清理的字符串
+	 * @return 清理后的字符串
+	 */
+	public static String cleanBlank(String str) {
+		if (str == null) {
+			return null;
+		}
+
+		return str.replaceAll("\\s*", EMPTY);
+	}
+
+	/**
+	 * 切分字符串<br>
+	 * a#b#c -> [a,b,c] <br>
+	 * a##b#c -> [a,"",b,c]
+	 * 
+	 * @param str 被切分的字符串
+	 * @param separator 分隔符字符
+	 * @return 切分后的集合
+	 */
+	public static List<String> split(String str, char separator) {
+		return split(str, separator, 0);
+	}
+
+	/**
+	 * 切分字符串
+	 * 
+	 * @param str 被切分的字符串
+	 * @param separator 分隔符字符
+	 * @param limit 限制分片数
+	 * @return 切分后的集合
+	 */
+	public static List<String> split(String str, char separator, int limit) {
+		if (str == null) {
+			return null;
+		}
+		List<String> list = new ArrayList<String>(limit == 0 ? 16 : limit);
+		if (limit == 1) {
+			list.add(str);
+			return list;
+		}
+
+		boolean isNotEnd = true; // 未结束切分的标志
+		int strLen = str.length();
+		StringBuilder sb = new StringBuilder(strLen);
+		for (int i = 0; i < strLen; i++) {
+			char c = str.charAt(i);
+			if (isNotEnd && c == separator) {
+				list.add(sb.toString());
+				// 清空StringBuilder
+				sb.delete(0, sb.length());
+
+				// 当达到切分上限-1的量时,将所剩字符全部作为最后一个串
+				if (limit != 0 && list.size() == limit - 1) {
+					isNotEnd = false;
+				}
+			} else {
+				sb.append(c);
+			}
+		}
+		list.add(sb.toString());// 加入尾串
+		return list;
+	}
+
+	/**
+	 * 切分字符串<br>
+	 * from jodd
+	 * 
+	 * @param str 被切分的字符串
+	 * @param delimiter 分隔符
+	 * @return 字符串
+	 */
+	public static String[] split(String str, String delimiter) {
+		if (str == null) {
+			return null;
+		}
+		if (str.trim().length() == 0) {
+			return new String[] { str };
+		}
+
+		int dellen = delimiter.length(); // del length
+		int maxparts = (str.length() / dellen) + 2; // one more for the last
+		int[] positions = new int[maxparts];
+
+		int i, j = 0;
+		int count = 0;
+		positions[0] = -dellen;
+		while ((i = str.indexOf(delimiter, j)) != -1) {
+			count++;
+			positions[count] = i;
+			j = i + dellen;
+		}
+		count++;
+		positions[count] = str.length();
+
+		String[] result = new String[count];
+
+		for (i = 0; i < count; i++) {
+			result[i] = str.substring(positions[i] + dellen, positions[i + 1]);
+		}
+		return result;
+	}
+
+	/**
+	 * 改进JDK subString<br>
+	 * index从0开始计算,最后一个字符为-1<br>
+	 * 如果from和to位置一样,返回 "" <br>
+	 * 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br>
+	 * 如果经过修正的index中from大于to,则互换from和to
+	 * example: <br>
+	 * 	abcdefgh 2 3 -> c <br>
+	 * 	abcdefgh 2 -3 -> cde <br>
+	 * 
+	 * @param string String
+	 * @param fromIndex 开始的index(包括)
+	 * @param toIndex 结束的index(不包括)
+	 * @return 字串
+	 */
+	public static String sub(String string, int fromIndex, int toIndex) {
+		int len = string.length();
+		if (fromIndex < 0) {
+			fromIndex = len + fromIndex;
+			if(fromIndex < 0 ) { 
+				fromIndex = 0;
+			}
+		} else if(fromIndex >= len) {
+			fromIndex = len -1;
+		}
+		if (toIndex < 0) {
+			toIndex = len + toIndex;
+			if(toIndex < 0) {
+				toIndex = len;
+			}
+		} else if(toIndex > len) {
+			toIndex = len;
+		}
+		if (toIndex < fromIndex) {
+			int tmp = fromIndex;
+			fromIndex = toIndex;
+			toIndex = tmp;
+		}
+		if (fromIndex == toIndex) {
+			return EMPTY;
+		}
+		char[] strArray = string.toCharArray();
+		char[] newStrArray = Arrays.copyOfRange(strArray, fromIndex, toIndex);
+		return new String(newStrArray);
+	}
+
+	/**
+	 * 切割前部分
+	 * 
+	 * @param string 字符串
+	 * @param toIndex 切割到的位置(不包括)
+	 * @return 切割后的字符串
+	 */
+	public static String subPre(String string, int toIndex) {
+		return sub(string, 0, toIndex);
+	}
+
+	/**
+	 * 切割后部分
+	 * 
+	 * @param string 字符串
+	 * @param fromIndex 切割开始的位置(包括)
+	 * @return 切割后的字符串
+	 */
+	public static String subSuf(String string, int fromIndex) {
+		if (isEmpty(string)) {
+			return null;
+		}
+		return sub(string, fromIndex, string.length());
+	}
+
+	/**
+	 * 给定字符串是否被字符包围
+	 * 
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @param suffix 后缀
+	 * @return 是否包围,空串不包围
+	 */
+	public static boolean isSurround(String str, String prefix, String suffix) {
+		if (StrKit.isBlank(str)) {
+			return false;
+		}
+		if (str.length() < (prefix.length() + suffix.length())) {
+			return false;
+		}
+
+		return str.startsWith(prefix) && str.endsWith(suffix);
+	}
+
+	/**
+	 * 给定字符串是否被字符包围
+	 * 
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @param suffix 后缀
+	 * @return 是否包围,空串不包围
+	 */
+	public static boolean isSurround(String str, char prefix, char suffix) {
+		if (StrKit.isBlank(str)) {
+			return false;
+		}
+		if (str.length() < 2) {
+			return false;
+		}
+
+		return str.charAt(0) == prefix && str.charAt(str.length() - 1) == suffix;
+	}
+
+	/**
+	 * 重复某个字符
+	 * 
+	 * @param c 被重复的字符
+	 * @param count 重复的数目
+	 * @return 重复字符字符串
+	 */
+	public static String repeat(char c, int count) {
+		char[] result = new char[count];
+		for (int i = 0; i < count; i++) {
+			result[i] = c;
+		}
+		return new String(result);
+	}
+
+	/**
+	 * 重复某个字符串
+	 * 
+	 * @param str 被重复的字符
+	 * @param count 重复的数目
+	 * @return 重复字符字符串
+	 */
+	public static String repeat(String str, int count) {
+
+		// 检查
+		final int len = str.length();
+		final long longSize = (long) len * (long) count;
+		final int size = (int) longSize;
+		if (size != longSize) {
+			throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize);
+		}
+
+		final char[] array = new char[size];
+		str.getChars(0, len, array, 0);
+		int n;
+		for (n = len; n < size - n; n <<= 1) {// n <<= 1相当于n *2
+			System.arraycopy(array, 0, array, n, n);
+		}
+		System.arraycopy(array, 0, array, n, size - n);
+		return new String(array);
+	}
+
+	/**
+	 * 比较两个字符串(大小写敏感)。
+	 * 
+	 * <pre>
+	 * equals(null, null)   = true
+	 * equals(null, &quot;abc&quot;)  = false
+	 * equals(&quot;abc&quot;, null)  = false
+	 * equals(&quot;abc&quot;, &quot;abc&quot;) = true
+	 * equals(&quot;abc&quot;, &quot;ABC&quot;) = false
+	 * </pre>
+	 * 
+	 * @param str1 要比较的字符串1
+	 * @param str2 要比较的字符串2
+	 * 
+	 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
+	 */
+	public static boolean equals(String str1, String str2) {
+		if (str1 == null) {
+			return str2 == null;
+		}
+
+		return str1.equals(str2);
+	}
+
+	/**
+	 * 比较两个字符串(大小写不敏感)。
+	 * 
+	 * <pre>
+	 * equalsIgnoreCase(null, null)   = true
+	 * equalsIgnoreCase(null, &quot;abc&quot;)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, null)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
+	 * </pre>
+	 * 
+	 * @param str1 要比较的字符串1
+	 * @param str2 要比较的字符串2
+	 * 
+	 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
+	 */
+	public static boolean equalsIgnoreCase(String str1, String str2) {
+		if (str1 == null) {
+			return str2 == null;
+		}
+
+		return str1.equalsIgnoreCase(str2);
+	}
+
+	/**
+	 * 格式化文本, {} 表示占位符<br>
+	 * 例如:format("aaa {} ccc", "bbb")   ---->    aaa bbb ccc
+	 * 
+	 * @param template 文本模板,被替换的部分用 {} 表示
+	 * @param values 参数值
+	 * @return 格式化后的文本
+	 */
+	public static String format(String template, Object... values) {
+		if (CollectionKit.isEmpty(values) || isBlank(template)) {
+			return template;
+		}
+
+		final StringBuilder sb = new StringBuilder();
+		final int length = template.length();
+
+		int valueIndex = 0;
+		char currentChar;
+		for (int i = 0; i < length; i++) {
+			if (valueIndex >= values.length) {
+				sb.append(sub(template, i, length));
+				break;
+			}
+
+			currentChar = template.charAt(i);
+			if (currentChar == '{') {
+				final char nextChar = template.charAt(++i);
+				if (nextChar == '}') {
+					sb.append(values[valueIndex++]);
+				} else {
+					sb.append('{').append(nextChar);
+				}
+			} else {
+				sb.append(currentChar);
+			}
+
+		}
+
+		return sb.toString();
+	}
+
+	/**
+	 * 格式化文本,使用 {varName} 占位<br>
+	 * map = {a: "aValue", b: "bValue"}
+	 * format("{a} and {b}", map)    ---->    aValue and bValue
+	 * 
+	 * @param template 文本模板,被替换的部分用 {key} 表示
+	 * @param map 参数值对
+	 * @return 格式化后的文本
+	 */
+	public static String format(String template, Map<?, ?> map) {
+		if (null == map || map.isEmpty()) {
+			return template;
+		}
+
+		for (Entry<?, ?> entry : map.entrySet()) {
+			template = template.replace("{" + entry.getKey() + "}", entry.getValue().toString());
+		}
+		return template;
+	}
+	
+	/**
+	 * 编码字符串
+	 * 
+	 * @param str 字符串
+	 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+	 * @return 编码后的字节码
+	 */
+	public static byte[] bytes(String str, String charset) {
+		return bytes(str, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+	}
+
+	/**
+	 * 编码字符串
+	 * 
+	 * @param str 字符串
+	 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+	 * @return 编码后的字节码
+	 */
+	public static byte[] bytes(String str, Charset charset) {
+		if (str == null) {
+			return null;
+		}
+
+		if (null == charset) {
+			return str.getBytes();
+		}
+		return str.getBytes(charset);
+	}
+	
+	/**
+	 * 将byte数组转为字符串
+	 * 
+	 * @param bytes byte数组
+	 * @param charset 字符集
+	 * @return 字符串
+	 */
+	public static String str(byte[] bytes, String charset) {
+		return str(bytes, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+	}
+
+	/**
+	 * 解码字节码
+	 * 
+	 * @param data 字符串
+	 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+	 * @return 解码后的字符串
+	 */
+	public static String str(byte[] data, Charset charset) {
+		if (data == null) {
+			return null;
+		}
+
+		if (null == charset) {
+			return new String(data);
+		}
+		return new String(data, charset);
+	}
+	
+	/**
+	 * 将编码的byteBuffer数据转换为字符串
+	 * @param data 数据
+	 * @param charset 字符集,如果为空使用当前系统字符集
+	 * @return 字符串
+	 */
+	public static String str(ByteBuffer data, String charset){
+		if(data == null) {
+			return null;
+		}
+		
+		return str(data, Charset.forName(charset));
+	}
+	
+	/**
+	 * 将编码的byteBuffer数据转换为字符串
+	 * @param data 数据
+	 * @param charset 字符集,如果为空使用当前系统字符集
+	 * @return 字符串
+	 */
+	public static String str(ByteBuffer data, Charset charset){
+		if(null == charset) {
+			charset = Charset.defaultCharset();
+		}
+		return charset.decode(data).toString();
+	}
+	
+	/**
+	 * 字符串转换为byteBuffer
+	 * @param str 字符串
+	 * @param charset 编码
+	 * @return byteBuffer
+	 */
+	public static ByteBuffer byteBuffer(String str, String charset) {
+		return ByteBuffer.wrap(StrKit.bytes(str, charset));
+	}
+
+	/**
+	 * 以 conjunction 为分隔符将多个对象转换为字符串
+	 * 
+	 * @param conjunction 分隔符
+	 * @param objs 数组
+	 * @return 连接后的字符串
+	 */
+	public static String join(String conjunction, Object... objs) {
+		StringBuilder sb = new StringBuilder();
+		boolean isFirst = true;
+		for (Object item : objs) {
+			if (isFirst) {
+				isFirst = false;
+			} else {
+				sb.append(conjunction);
+			}
+			sb.append(item);
+		}
+		return sb.toString();
+	}
+	
+	/**
+	 * 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
+	 * 例如:HelloWorld->hello_world
+	 *
+	 * @param camelCaseStr 转换前的驼峰式命名的字符串
+	 * @return 转换后下划线大写方式命名的字符串
+	 */
+	public static String toUnderlineCase(String camelCaseStr) {
+		if (camelCaseStr == null) {
+			return null;
+		}
+
+		final int length = camelCaseStr.length();
+		StringBuilder sb = new StringBuilder();
+		char c;
+		boolean isPreUpperCase = false;
+		for (int i = 0; i < length; i++) {
+			c = camelCaseStr.charAt(i);
+			boolean isNextUpperCase = true;
+			if (i < (length - 1)) {
+				isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1));
+			}
+			if (Character.isUpperCase(c)) {
+				if (!isPreUpperCase || !isNextUpperCase) {
+					if (i > 0) sb.append(UNDERLINE);
+				}
+				isPreUpperCase = true;
+			} else {
+				isPreUpperCase = false;
+			}
+			sb.append(Character.toLowerCase(c));
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 将下划线方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
+	 * 例如:hello_world->HelloWorld
+	 *
+	 * @param name 转换前的下划线大写方式命名的字符串
+	 * @return 转换后的驼峰式命名的字符串
+	 */
+	public static String toCamelCase(String name) {
+		if (name == null) {
+			return null;
+		}
+		if (name.contains(UNDERLINE)) {
+			name = name.toLowerCase();
+
+			StringBuilder sb = new StringBuilder(name.length());
+			boolean upperCase = false;
+			for (int i = 0; i < name.length(); i++) {
+				char c = name.charAt(i);
+
+				if (c == '_') {
+					upperCase = true;
+				} else if (upperCase) {
+					sb.append(Character.toUpperCase(c));
+					upperCase = false;
+				} else {
+					sb.append(c);
+				}
+			}
+			return sb.toString();
+		} else
+			return name;
+	}
+
+	/**
+	 * 包装指定字符串
+	 * 
+	 * @param str 被包装的字符串
+	 * @param prefix 前缀
+	 * @param suffix 后缀
+	 * @return 包装后的字符串
+	 */
+	public static String wrap(String str, String prefix, String suffix) {
+		return format("{}{}{}", prefix, str, suffix);
+	}
+
+	/**
+	 * 指定字符串是否被包装
+	 * 
+	 * @param str 字符串
+	 * @param prefix 前缀
+	 * @param suffix 后缀
+	 * @return 是否被包装
+	 */
+	public static boolean isWrap(String str, String prefix, String suffix) {
+		return str.startsWith(prefix) && str.endsWith(suffix);
+	}
+
+	/**
+	 * 指定字符串是否被同一字符包装(前后都有这些字符串)
+	 * 
+	 * @param str 字符串
+	 * @param wrapper 包装字符串
+	 * @return 是否被包装
+	 */
+	public static boolean isWrap(String str, String wrapper) {
+		return isWrap(str, wrapper, wrapper);
+	}
+
+	/**
+	 * 指定字符串是否被同一字符包装(前后都有这些字符串)
+	 * 
+	 * @param str 字符串
+	 * @param wrapper 包装字符
+	 * @return 是否被包装
+	 */
+	public static boolean isWrap(String str, char wrapper) {
+		return isWrap(str, wrapper, wrapper);
+	}
+
+	/**
+	 * 指定字符串是否被包装
+	 * 
+	 * @param str 字符串
+	 * @param prefixChar 前缀
+	 * @param suffixChar 后缀
+	 * @return 是否被包装
+	 */
+	public static boolean isWrap(String str, char prefixChar, char suffixChar) {
+		return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar;
+	}
+
+	/**
+	 * 补充字符串以满足最小长度 StrUtil.padPre("1", 3, '0');//"001"
+	 * 
+	 * @param str 字符串
+	 * @param minLength 最小长度
+	 * @param padChar 补充的字符
+	 * @return 补充后的字符串
+	 */
+	public static String padPre(String str, int minLength, char padChar) {
+		if (str.length() >= minLength) {
+			return str;
+		}
+		StringBuilder sb = new StringBuilder(minLength);
+		for (int i = str.length(); i < minLength; i++) {
+			sb.append(padChar);
+		}
+		sb.append(str);
+		return sb.toString();
+	}
+
+	/**
+	 * 补充字符串以满足最小长度 StrUtil.padEnd("1", 3, '0');//"100"
+	 * 
+	 * @param str 字符串
+	 * @param minLength 最小长度
+	 * @param padChar 补充的字符
+	 * @return 补充后的字符串
+	 */
+	public static String padEnd(String str, int minLength, char padChar) {
+		if (str.length() >= minLength) {
+			return str;
+		}
+		StringBuilder sb = new StringBuilder(minLength);
+		sb.append(str);
+		for (int i = str.length(); i < minLength; i++) {
+			sb.append(padChar);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 创建StringBuilder对象
+	 * 
+	 * @return StringBuilder对象
+	 */
+	public static StringBuilder builder() {
+		return new StringBuilder();
+	}
+
+	/**
+	 * 创建StringBuilder对象
+	 * 
+	 * @return StringBuilder对象
+	 */
+	public static StringBuilder builder(int capacity) {
+		return new StringBuilder(capacity);
+	}
+
+	/**
+	 * 创建StringBuilder对象
+	 * 
+	 * @return StringBuilder对象
+	 */
+	public static StringBuilder builder(String... strs) {
+		final StringBuilder sb = new StringBuilder();
+		for (String str : strs) {
+			sb.append(str);
+		}
+		return sb;
+	}
+
+	/**
+	 * 获得StringReader
+	 * 
+	 * @param str 字符串
+	 * @return StringReader
+	 */
+	public static StringReader getReader(String str) {
+		return new StringReader(str);
+	}
+
+	/**
+	 * 获得StringWriter
+	 * 
+	 * @return StringWriter
+	 */
+	public static StringWriter getWriter() {
+		return new StringWriter();
+	}
+
+		/**
+	 * 编码字符串
+	 * 
+	 * @param str 字符串
+	 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+	 * @return 编码后的字节码
+	 */
+	public static byte[] encode(String str, String charset) {
+		if (str == null) {
+			return null;
+		}
+
+		if(isBlank(charset)) {
+			return str.getBytes();
+		}
+		try {
+			return str.getBytes(charset);
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(format("Charset [{}] unsupported!", charset));
+		}
+	}
+
+	/**
+	 * 解码字节码
+	 * 
+	 * @param data 字符串
+	 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+	 * @return 解码后的字符串
+	 */
+	public static String decode(byte[] data, String charset) {
+		if (data == null) {
+			return null;
+		}
+
+		if(isBlank(charset)) {
+			return new String(data);
+		}
+		try {
+			return new String(data, charset);
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(format("Charset [{}] unsupported!", charset));
+		}
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java
new file mode 100644
index 0000000..3af28f4
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) 2011-2014, hubin (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.support;
+
+import java.util.regex.Pattern;
+
+/**
+ * Web防火墙工具类
+ * <p>
+ * @author   hubin
+ * @Date	 2014-5-8 	 
+ */
+public class WafKit {
+
+	/**
+	 * @Description 过滤XSS脚本内容
+	 * @param value
+	 * 				待处理内容
+	 * @return
+	 */
+	public static String stripXSS(String value) {
+		String rlt = null;
+
+		if (null != value) {
+			// NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
+			// avoid encoded attacks.
+			// value = ESAPI.encoder().canonicalize(value);
+
+			// Avoid null characters
+			rlt = value.replaceAll("", "");
+
+			// Avoid anything between script tags
+			Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid anything in a src='...' type of expression
+			/*scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");*/
+
+			// Remove any lonesome </script> tag
+			scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Remove any lonesome <script ...> tag
+			scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid eval(...) expressions
+			scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid expression(...) expressions
+			scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid javascript:... expressions
+			scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid vbscript:... expressions
+			scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+
+			// Avoid onload= expressions
+			scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE
+					| Pattern.MULTILINE | Pattern.DOTALL);
+			rlt = scriptPattern.matcher(rlt).replaceAll("");
+		}
+		
+		return rlt;
+	}
+
+	/**
+	 * @Description 过滤SQL注入内容
+	 * @param value
+	 * 				待处理内容
+	 * @return
+	 */
+	public static String stripSqlInjection(String value) {
+		return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)", ""); //value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
+	}
+
+	/**
+	 * @Description 过滤SQL/XSS注入内容
+	 * @param value
+	 * 				待处理内容
+	 * @return
+	 */
+	public static String stripSqlXSS(String value) {
+		return stripXSS(stripSqlInjection(value));
+	}
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java
new file mode 100644
index 0000000..42a2e91
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java
@@ -0,0 +1,149 @@
+/**
+ * Copyright (c) 2011-2014, hubin (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.stylefeng.guns.core.support;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Request请求过滤包装
+ * <p>
+ * @author   hubin
+ * @Date	 2014-5-8 	 
+ */
+public class WafRequestWrapper extends HttpServletRequestWrapper {
+
+	private boolean filterXSS = true;
+
+	private boolean filterSQL = true;
+
+
+	public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {
+		super(request);
+		this.filterXSS = filterXSS;
+		this.filterSQL = filterSQL;
+	}
+
+
+	public WafRequestWrapper(HttpServletRequest request) {
+		this(request, true, true);
+	}
+
+
+	/**
+	 * @Description 数组参数过滤
+	 * @param parameter
+	 * 				过滤参数
+	 * @return
+	 */
+	@Override
+	public String[] getParameterValues(String parameter) {
+		String[] values = super.getParameterValues(parameter);
+		if ( values == null ) {
+			return null;
+		}
+
+		int count = values.length;
+		String[] encodedValues = new String[count];
+		for ( int i = 0 ; i < count ; i++ ) {
+			encodedValues[i] = filterParamString(values[i]);
+		}
+
+		return encodedValues;
+	}
+
+	@Override
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public Map getParameterMap() {
+		Map<String, String[]> primary = super.getParameterMap();
+		Map<String, String[]> result = new HashMap<String, String[]>(primary.size());
+		for ( Map.Entry<String, String[]> entry : primary.entrySet() ) {
+			result.put(entry.getKey(), filterEntryString(entry.getValue()));
+		}
+		return result;
+
+	}
+	
+	protected String[] filterEntryString(String[] rawValue) {
+		for ( int i = 0 ; i < rawValue.length ; i++ ) {
+			rawValue[i] = filterParamString(rawValue[i]);
+		}
+		return rawValue;
+	}
+
+	/**
+	 * @Description 参数过滤
+	 * @param parameter
+	 * 				过滤参数
+	 * @return
+	 */
+	@Override
+	public String getParameter(String parameter) {
+		return filterParamString(super.getParameter(parameter));
+	}
+
+
+	/**
+	 * @Description 请求头过滤 
+	 * @param name
+	 * 				过滤内容
+	 * @return
+	 */
+	@Override
+	public String getHeader(String name) {
+		return filterParamString(super.getHeader(name));
+	}
+
+
+	/**
+	 * @Description Cookie内容过滤
+	 * @return
+	 */
+	@Override
+	public Cookie[] getCookies() {
+		Cookie[] existingCookies = super.getCookies();
+		if (existingCookies != null) {
+			for (int i = 0 ; i < existingCookies.length ; ++i) {
+				Cookie cookie = existingCookies[i];
+				cookie.setValue(filterParamString(cookie.getValue()));
+			}
+		}
+		return existingCookies;
+	}
+
+	/**
+	 * @Description 过滤字符串内容
+	 * @param rawValue
+	 * 				待处理内容
+	 * @return
+	 */
+	protected String filterParamString(String rawValue) {
+		if (null == rawValue) {
+			return null;
+		}
+		String tmpStr = rawValue;
+		if (this.filterXSS) {
+			tmpStr = WafKit.stripXSS(rawValue);
+		}
+		if (this.filterSQL) {
+			tmpStr = WafKit.stripSqlInjection(tmpStr);
+		}
+		return tmpStr;
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java
new file mode 100644
index 0000000..9580b7b
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.support.exception;
+
+import com.stylefeng.guns.core.support.StrKit;
+
+/**
+ * 工具类初始化异常
+ */
+public class ToolBoxException extends RuntimeException{
+	private static final long serialVersionUID = 8247610319171014183L;
+
+	public ToolBoxException(Throwable e) {
+		super(e.getMessage(), e);
+	}
+	
+	public ToolBoxException(String message) {
+		super(message);
+	}
+	
+	public ToolBoxException(String messageTemplate, Object... params) {
+		super(StrKit.format(messageTemplate, params));
+	}
+	
+	public ToolBoxException(String message, Throwable throwable) {
+		super(message, throwable);
+	}
+	
+	public ToolBoxException(Throwable throwable, String messageTemplate, Object... params) {
+		super(StrKit.format(messageTemplate, params), throwable);
+	}
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java
new file mode 100644
index 0000000..06558b4
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java
@@ -0,0 +1,1060 @@
+package com.stylefeng.guns.core.util;
+
+import com.stylefeng.guns.core.support.*;
+import com.stylefeng.guns.core.support.exception.ToolBoxException;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.Set;
+
+
+/**
+ * 类型转换器
+ * 
+ * @author xiaoleilu
+ * 
+ */
+public class Convert {
+	
+
+	private Convert() {
+		// 静态类不可实例化
+	}
+
+	/**
+	 * 强制转换类型
+	 * 
+	 * @param clazz 被转换成的类型
+	 * @param value 需要转换的对象
+	 * @return 转换后的对象
+	 */
+	public static Object parse(Class<?> clazz, Object value) {
+		try {
+			if (clazz.isAssignableFrom(String.class)) {
+				// ----2016-12-19---zhuangqian----防止beetlsql对空字符串不检测导致无法入库的问题----
+				if (StrKit.isBlank(String.valueOf(value)))
+					return " ";
+				else
+					return String.valueOf(value);
+			}
+			return clazz.cast(value);
+		} catch (ClassCastException e) {
+			String valueStr = String.valueOf(value);
+
+			Object result = parseBasic(clazz, valueStr);
+			if (result != null) {
+				return result;
+			}
+
+			if (Date.class.isAssignableFrom(clazz)) {
+				// 判断标准日期
+				// ----2016-11-24---zhuangqian----需要加toDate(),不然beetlsql转换date类型的时候会报错----
+				return DateTimeKit.parse(valueStr).toDate();
+			} else if (clazz == BigInteger.class) {
+				// 数学计算数字
+				return new BigInteger(valueStr);
+			} else if (clazz == BigDecimal.class) {
+				// 数学计算数字
+				return new BigDecimal(valueStr);
+			} else if (clazz == byte[].class) {
+				// 流,由于有字符编码问题,在此使用系统默认
+				return valueStr.getBytes();
+			}
+			// 未找到可转换的类型,返回原值
+			return (StrKit.isBlank(valueStr)) ? null : value;
+		}
+	}
+
+	/**
+	 * 转换基本类型<br>
+	 * 将字符串转换为原始类型或包装类型
+	 * 
+	 * @param clazz 转换到的类,可以是原始类型类,也可以是包装类型类
+	 * @param valueStr 被转换的字符串
+	 * @return 转换后的对象,如果非基本类型,返回null
+	 */
+	public static Object parseBasic(Class<?> clazz, String valueStr) {
+		if (null == clazz || null == valueStr) {
+			return null;
+		}
+
+		if (StrKit.isBlank(valueStr)) return null;
+		
+		BasicType basicType = null;
+		try {
+			basicType = BasicType.valueOf(clazz.getSimpleName().toUpperCase());
+		} catch (Exception e) {
+			// 非基本类型数据
+			return null;
+		}
+
+		switch (basicType) {
+			case BYTE:
+				if (clazz == byte.class) {
+					return Byte.parseByte(valueStr);
+				}
+				return Byte.valueOf(valueStr);
+			case SHORT:
+				if (clazz == short.class) {
+					return Short.parseShort(valueStr);
+				}
+				return Short.valueOf(valueStr);
+			case INT:
+				return Integer.parseInt(valueStr);
+			case INTEGER:
+				return Integer.valueOf(valueStr);
+			case LONG:
+				if (clazz == long.class) {
+					return new BigDecimal(valueStr).longValue();
+				}
+				return Long.valueOf(valueStr);
+			case DOUBLE:
+				if (clazz == double.class) {
+					return new BigDecimal(valueStr).doubleValue();
+				}
+			case FLOAT:
+				if (clazz == float.class) {
+					return Float.parseFloat(valueStr);
+				}
+				return Float.valueOf(valueStr);
+			case BOOLEAN:
+				if (clazz == boolean.class) {
+					return Boolean.parseBoolean(valueStr);
+				}
+				return Boolean.valueOf(valueStr);
+			case CHAR:
+				return valueStr.charAt(0);
+			case CHARACTER:
+				return Character.valueOf(valueStr.charAt(0));
+			default:
+				return null;
+		}
+	}
+
+	/**
+	 * 转换为字符串<br>
+	 * 如果给定的值为null,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static String toStr(Object value, String defaultValue) {
+		if (null == value) {
+			return defaultValue;
+		}
+		if (value instanceof String) {
+			return (String) value;
+		} else if (CollectionKit.isArray(value)) {
+			return CollectionKit.toString(value);
+		}
+		return value.toString();
+	}
+
+	/**
+	 * 转换为字符串<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static String toStr(Object value) {
+		return toStr(value, null);
+	}
+
+	/**
+	 * 转换为字符<br>
+	 * 如果给定的值为null,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Character toChar(Object value, Character defaultValue) {
+		if (null == value) {
+			return defaultValue;
+		}
+		if (value instanceof Character) {
+			return (Character) value;
+		}
+
+		final String valueStr = toStr(value, null);
+		return StrKit.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+	}
+
+	/**
+	 * 转换为字符<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Character toChar(Object value) {
+		return toChar(value, null);
+	}
+
+	/**
+	 * 转换为byte<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Byte toByte(Object value, Byte defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Byte) {
+			return (Byte) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).byteValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return Byte.parseByte(valueStr);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为byte<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Byte toByte(Object value) {
+		return toByte(value, null);
+	}
+
+	/**
+	 * 转换为Short<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Short toShort(Object value, Short defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Short) {
+			return (Short) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).shortValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return Short.parseShort(valueStr.trim());
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为Short<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Short toShort(Object value) {
+		return toShort(value, null);
+	}
+
+	/**
+	 * 转换为Number<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Number toNumber(Object value, Number defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Number) {
+			return (Number) value;
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return NumberFormat.getInstance().parse(valueStr);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为Number<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Number toNumber(Object value) {
+		return toNumber(value, null);
+	}
+
+	/**
+	 * 转换为int<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Integer toInt(Object value, Integer defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Integer) {
+			return (Integer) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).intValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return Integer.parseInt(valueStr.trim());
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为int<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Integer toInt(Object value) {
+		return toInt(value, null);
+	}
+
+	/**
+	 * 转换为Integer数组<br>
+	 * 
+	 * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
+	 * @param values 被转换的值
+	 * @return 结果
+	 */
+	public static Integer[] toIntArray(boolean isIgnoreConvertError, Object... values) {
+		if (CollectionKit.isEmpty(values)) {
+			return new Integer[] {};
+		}
+		final Integer[] ints = new Integer[values.length];
+		for (int i = 0; i < values.length; i++) {
+			final Integer v = toInt(values[i], null);
+			if (null == v && isIgnoreConvertError == false) {
+				throw new ToolBoxException(StrKit.format("Convert [{}] to Integer error!", values[i]));
+			}
+			ints[i] = v;
+		}
+		return ints;
+	}
+	
+	
+	/**
+	 * 转换为Integer数组<br>
+	 * 
+	 * @param split 被转换的值
+	 * @return 结果
+	 */
+	public static Integer[] toIntArray(String str) {
+		return toIntArray(",", str);
+	}
+	
+	/**
+	 * 转换为Integer数组<br>
+	 * 
+	 * @param split 分隔符
+	 * @param split 被转换的值
+	 * @return 结果
+	 */
+	public static Integer[] toIntArray(String split, String str) {
+		if (StrKit.isEmpty(str)) {
+			return new Integer[] {};
+		}
+		String[] arr = str.split(split);
+		final Integer[] ints = new Integer[arr.length];
+		for (int i = 0; i < arr.length; i++) {
+			final Integer v = toInt(arr[i], 0);
+			ints[i] = v;
+		}
+		return ints;
+	}
+	
+	/**
+	 * 转换为String数组<br>
+	 * 
+	 * @param split 被转换的值
+	 * @return 结果
+	 */
+	public static String[] toStrArray(String str) {
+		return toStrArray("", str);
+	}
+	
+	/**
+	 * 转换为String数组<br>
+	 * 
+	 * @param split 分隔符
+	 * @param split 被转换的值
+	 * @return 结果
+	 */
+	public static String[] toStrArray(String split, String str) {
+		return str.split(split);
+	}
+
+	/**
+	 * 转换为long<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Long toLong(Object value, Long defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Long) {
+			return (Long) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).longValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			// 支持科学计数法
+			return new BigDecimal(valueStr.trim()).longValue();
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为long<br>
+	 * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Long toLong(Object value) {
+		return toLong(value, null);
+	}
+
+	/**
+	 * 转换为Long数组<br>
+	 * 
+	 * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
+	 * @param values 被转换的值
+	 * @return 结果
+	 */
+	public static Long[] toLongArray(boolean isIgnoreConvertError, Object... values) {
+		if (CollectionKit.isEmpty(values)) {
+			return new Long[] {};
+		}
+		final Long[] longs = new Long[values.length];
+		for (int i = 0; i < values.length; i++) {
+			final Long v = toLong(values[i], null);
+			if (null == v && isIgnoreConvertError == false) {
+				throw new ToolBoxException(StrKit.format("Convert [{}] to Long error!", values[i]));
+			}
+			longs[i] = v;
+		}
+		return longs;
+	}
+
+	/**
+	 * 转换为double<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Double toDouble(Object value, Double defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Double) {
+			return (Double) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).doubleValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			// 支持科学计数法
+			return new BigDecimal(valueStr.trim()).doubleValue();
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为double<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Double toDouble(Object value) {
+		return toDouble(value, null);
+	}
+
+	/**
+	 * 转换为Double数组<br>
+	 * 
+	 * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
+	 * @param values 被转换的值
+	 * @return 结果
+	 */
+	public static Double[] toDoubleArray(boolean isIgnoreConvertError, Object... values) {
+		if (CollectionKit.isEmpty(values)) {
+			return new Double[] {};
+		}
+		final Double[] doubles = new Double[values.length];
+		for (int i = 0; i < values.length; i++) {
+			final Double v = toDouble(values[i], null);
+			if (null == v && isIgnoreConvertError == false) {
+				throw new ToolBoxException(StrKit.format("Convert [{}] to Double error!", values[i]));
+			}
+			doubles[i] = v;
+		}
+		return doubles;
+	}
+
+	/**
+	 * 转换为Float<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Float toFloat(Object value, Float defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Float) {
+			return (Float) value;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).floatValue();
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return Float.parseFloat(valueStr.trim());
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为Float<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Float toFloat(Object value) {
+		return toFloat(value, null);
+	}
+
+	/**
+	 * 转换为Float数组<br>
+	 * 
+	 * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
+	 * @param values 被转换的值
+	 * @return 结果
+	 */
+	public static <T> Float[] toFloatArray(boolean isIgnoreConvertError, Object... values) {
+		if (CollectionKit.isEmpty(values)) {
+			return new Float[] {};
+		}
+		final Float[] floats = new Float[values.length];
+		for (int i = 0; i < values.length; i++) {
+			final Float v = toFloat(values[i], null);
+			if (null == v && isIgnoreConvertError == false) {
+				throw new ToolBoxException(StrKit.format("Convert [{}] to Float error!", values[i]));
+			}
+			floats[i] = v;
+		}
+		return floats;
+	}
+
+	/**
+	 * 转换为boolean<br>
+	 * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static Boolean toBool(Object value, Boolean defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof Boolean) {
+			return (Boolean) value;
+		}
+		String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		valueStr = valueStr.trim().toLowerCase();
+		switch (valueStr) {
+			case "true":
+				return true;
+			case "false":
+				return false;
+			case "yes":
+				return true;
+			case "ok":
+				return true;
+			case "no":
+				return false;
+			case "1":
+				return true;
+			case "0":
+				return false;
+			default:
+				return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为boolean<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static Boolean toBool(Object value) {
+		return toBool(value, null);
+	}
+
+	/**
+	 * 转换为Boolean数组<br>
+	 * 
+	 * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
+	 * @param values 被转换的值
+	 * @return 结果
+	 */
+	public static Boolean[] toBooleanArray(boolean isIgnoreConvertError, Object... values) {
+		if (CollectionKit.isEmpty(values)) {
+			return new Boolean[] {};
+		}
+		final Boolean[] bools = new Boolean[values.length];
+		for (int i = 0; i < values.length; i++) {
+			final Boolean v = toBool(values[i], null);
+			if (null == v && isIgnoreConvertError == false) {
+				throw new ToolBoxException(StrKit.format("Convert [{}] to Boolean error!", values[i]));
+			}
+			bools[i] = v;
+		}
+		return bools;
+	}
+
+	/**
+	 * 转换为Enum对象<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 
+	 * @param clazz Enum的Class
+	 * @param value 值
+	 * @param defaultValue 默认值
+	 * @return Enum
+	 */
+	public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (clazz.isAssignableFrom(value.getClass())) {
+			@SuppressWarnings("unchecked")
+			E myE = (E) value;
+			return myE;
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return Enum.valueOf(clazz, valueStr);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为Enum对象<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 
+	 * @param clazz Enum的Class
+	 * @param value 值
+	 * @return Enum
+	 */
+	public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) {
+		return toEnum(clazz, value, null);
+	}
+
+	/**
+	 * 转换为BigInteger<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof BigInteger) {
+			return (BigInteger) value;
+		}
+		if (value instanceof Long) {
+			return BigInteger.valueOf((Long) value);
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return new BigInteger(valueStr);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为BigInteger<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static BigInteger toBigInteger(Object value) {
+		return toBigInteger(value, null);
+	}
+
+	/**
+	 * 转换为BigDecimal<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @param defaultValue 转换错误时的默认值
+	 * @return 结果
+	 */
+	public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		if (value instanceof BigDecimal) {
+			return (BigDecimal) value;
+		}
+		if (value instanceof Long) {
+			return new BigDecimal((Long) value);
+		}
+		if (value instanceof Double) {
+			return new BigDecimal((Double) value);
+		}
+		if (value instanceof Integer) {
+			return new BigDecimal((Integer) value);
+		}
+		final String valueStr = toStr(value, null);
+		if (StrKit.isBlank(valueStr)) {
+			return defaultValue;
+		}
+		try {
+			return new BigDecimal(valueStr);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 转换为BigDecimal<br>
+	 * 如果给定的值为空,或者转换失败,返回默认值<br>
+	 * 转换失败不会报错
+	 * 
+	 * @param value 被转换的值
+	 * @return 结果
+	 */
+	public static BigDecimal toBigDecimal(Object value) {
+		return toBigDecimal(value, null);
+	}
+
+	// ----------------------------------------------------------------------- 全角半角转换
+	/**
+	 * 半角转全角
+	 * 
+	 * @param input String.
+	 * @return 全角字符串.
+	 */
+	public static String toSBC(String input) {
+		return toSBC(input, null);
+	}
+
+	/**
+	 * 半角转全角
+	 * 
+	 * @param input String
+	 * @param notConvertSet 不替换的字符集合
+	 * @return 全角字符串.
+	 */
+	public static String toSBC(String input, Set<Character> notConvertSet) {
+		char c[] = input.toCharArray();
+		for (int i = 0; i < c.length; i++) {
+			if (null != notConvertSet && notConvertSet.contains(c[i])) {
+				// 跳过不替换的字符
+				continue;
+			}
+
+			if (c[i] == ' ') {
+				c[i] = '\u3000';
+			} else if (c[i] < '\177') {
+				c[i] = (char) (c[i] + 65248);
+
+			}
+		}
+		return new String(c);
+	}
+
+	/**
+	 * 全角转半角
+	 * 
+	 * @param input String.
+	 * @return 半角字符串
+	 */
+	public static String toDBC(String input) {
+		return toDBC(input, null);
+	}
+
+	/**
+	 * 替换全角为半角
+	 * 
+	 * @param text 文本
+	 * @param notConvertSet 不替换的字符集合
+	 * @return 替换后的字符
+	 */
+	public static String toDBC(String text, Set<Character> notConvertSet) {
+		char c[] = text.toCharArray();
+		for (int i = 0; i < c.length; i++) {
+			if (null != notConvertSet && notConvertSet.contains(c[i])) {
+				// 跳过不替换的字符
+				continue;
+			}
+
+			if (c[i] == '\u3000') {
+				c[i] = ' ';
+			} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
+				c[i] = (char) (c[i] - 65248);
+			}
+		}
+		String returnString = new String(c);
+
+		return returnString;
+	}
+
+	// --------------------------------------------------------------------- hex
+	/**
+	 * 字符串转换成十六进制字符串
+	 * 
+	 * @param str 待转换的ASCII字符串
+	 * @return 16进制字符串
+	 */
+	public static String toHex(String str) {
+		return HexKit.encodeHexStr(str.getBytes());
+	}
+
+	/**
+	 * byte数组转16进制串
+	 * 
+	 * @param bytes 被转换的byte数组
+	 * @return 转换后的值
+	 */
+	public static String toHex(byte[] bytes) {
+		return HexKit.encodeHexStr(bytes);
+	}
+
+	/**
+	 * Hex字符串转换为Byte值
+	 * 
+	 * @param src Byte字符串,每个Byte之间没有分隔符
+	 * @return byte[]
+	 */
+	public static byte[] hexToBytes(String src) {
+		return HexKit.decodeHex(src.toCharArray());
+	}
+
+	/**
+	 * 十六进制转换字符串
+	 * 
+	 * @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
+	 * @param charset 编码 {@link Charset}
+	 * @return 对应的字符串
+	 */
+	public static String hexStrToStr(String hexStr, Charset charset) {
+		return HexKit.decodeHexStr(hexStr, charset);
+	}
+
+	/**
+	 * String的字符串转换成unicode的String
+	 * 
+	 * @param strText 全角字符串
+	 * @return String 每个unicode之间无分隔符
+	 * @throws Exception
+	 */
+	public static String strToUnicode(String strText) throws Exception {
+		char c;
+		StringBuilder str = new StringBuilder();
+		int intAsc;
+		String strHex;
+		for (int i = 0; i < strText.length(); i++) {
+			c = strText.charAt(i);
+			intAsc = (int) c;
+			strHex = Integer.toHexString(intAsc);
+			if (intAsc > 128)
+				str.append("\\u" + strHex);
+			else // 低位在前面补00
+				str.append("\\u00" + strHex);
+		}
+		return str.toString();
+	}
+
+	/**
+	 * unicode的String转换成String的字符串
+	 * 
+	 * @param hex 16进制值字符串 (一个unicode为2byte)
+	 * @return String 全角字符串
+	 */
+	public static String unicodeToStr(String hex) {
+		int t = hex.length() / 6;
+		StringBuilder str = new StringBuilder();
+		for (int i = 0; i < t; i++) {
+			String s = hex.substring(i * 6, (i + 1) * 6);
+			// 高位需要补上00再转
+			String s1 = s.substring(2, 4) + "00";
+			// 低位直接转
+			String s2 = s.substring(4);
+			// 将16进制的string转为int
+			int n = Integer.valueOf(s1, 16) + Integer.valueOf(s2, 16);
+			// 将int转换为字符
+			char[] chars = Character.toChars(n);
+			str.append(new String(chars));
+		}
+		return str.toString();
+	}
+
+	/**
+	 * 给定字符串转换字符编码<br/>
+	 * 如果参数为空,则返回原字符串,不报错。
+	 * 
+	 * @param str 被转码的字符串
+	 * @param sourceCharset 原字符集
+	 * @param destCharset 目标字符集
+	 * @return 转换后的字符串
+	 */
+	public static String convertCharset(String str, String sourceCharset, String destCharset) {
+		if (StrKit.hasBlank(str, sourceCharset, destCharset)) {
+			return str;
+		}
+
+		try {
+			return new String(str.getBytes(sourceCharset), destCharset);
+		} catch (UnsupportedEncodingException e) {
+			return str;
+		}
+	}
+
+	/**
+	 * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+	 * 
+	 * @param n 数字
+	 * @return 中文大写数字
+	 */
+	public static String digitUppercase(double n) {
+		String fraction[] = { "角", "分" };
+		String digit[] = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
+		String unit[][] = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };
+
+		String head = n < 0 ? "负" : "";
+		n = Math.abs(n);
+
+		String s = "";
+		for (int i = 0; i < fraction.length; i++) {
+			s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+		}
+		if (s.length() < 1) {
+			s = "整";
+		}
+		int integerPart = (int) Math.floor(n);
+
+		for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
+			String p = "";
+			for (int j = 0; j < unit[1].length && n > 0; j++) {
+				p = digit[integerPart % 10] + unit[1][j] + p;
+				integerPart = integerPart / 10;
+			}
+			s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+		}
+		return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+	}
+	
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java
new file mode 100644
index 0000000..a0f832a
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java
@@ -0,0 +1,250 @@
+/**
+ * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+public class DateUtil {
+
+    /**
+     * 获取YYYY格式
+     */
+    public static String getYear() {
+        return formatDate(new Date(), "yyyy");
+    }
+
+    /**
+     * 获取YYYY格式
+     */
+    public static String getYear(Date date) {
+        return formatDate(date, "yyyy");
+    }
+
+    /**
+     * 获取YYYY-MM-DD格式
+     */
+    public static String getDay() {
+        return formatDate(new Date(), "yyyy-MM-dd");
+    }
+
+    /**
+     * 获取YYYY-MM-DD格式
+     */
+    public static String getDay(Date date) {
+        return formatDate(date, "yyyy-MM-dd");
+    }
+
+    /**
+     * 获取YYYYMMDD格式
+     */
+    public static String getDays() {
+        return formatDate(new Date(), "yyyyMMdd");
+    }
+
+    /**
+     * 获取YYYYMMDD格式
+     */
+    public static String getDays(Date date) {
+        return formatDate(date, "yyyyMMdd");
+    }
+
+    /**
+     * 获取YYYY-MM-DD HH:mm:ss格式
+     */
+    public static String getTime() {
+        return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
+    }
+
+    /**
+     * 获取YYYY-MM-DD HH:mm:ss.SSS格式
+     */
+    public static String getMsTime() {
+        return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
+    }
+
+    /**
+     * 获取YYYYMMDDHHmmss格式
+     */
+    public static String getAllTime() {
+        return formatDate(new Date(), "yyyyMMddHHmmss");
+    }
+
+    /**
+     * 获取YYYY-MM-DD HH:mm:ss格式
+     */
+    public static String getTime(Date date) {
+        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
+    }
+
+    public static String formatDate(Date date, String pattern) {
+        String formatDate = null;
+        if (StringUtils.isNotBlank(pattern)) {
+            formatDate = DateFormatUtils.format(date, pattern);
+        } else {
+            formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
+        }
+        return formatDate;
+    }
+
+    /**
+     * 日期比较,如果s>=e 返回true 否则返回false)
+     *
+     * @author luguosui
+     */
+    public static boolean compareDate(String s, String e) {
+        if (parseDate(s) == null || parseDate(e) == null) {
+            return false;
+        }
+        return parseDate(s).getTime() >= parseDate(e).getTime();
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static Date parseDate(String date) {
+        return parse(date, "yyyy-MM-dd");
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static Date parseTimeMinutes(String date) {
+        return parse(date, "yyyy-MM-dd HH:mm");
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static Date parseTime(String date) {
+        return parse(date, "yyyy-MM-dd HH:mm:ss");
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static Date parse(String date, String pattern) {
+        try {
+            return DateUtils.parseDate(date, pattern);
+        } catch (ParseException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static String format(Date date, String pattern) {
+        return DateFormatUtils.format(date, pattern);
+    }
+
+    /**
+     * 把日期转换为Timestamp
+     */
+    public static Timestamp format(Date date) {
+        return new Timestamp(date.getTime());
+    }
+
+    /**
+     * 校验日期是否合法
+     */
+    public static boolean isValidDate(String s) {
+        return parse(s, "yyyy-MM-dd HH:mm:ss") != null;
+    }
+
+    /**
+     * 校验日期是否合法
+     */
+    public static boolean isValidDate(String s, String pattern) {
+        return parse(s, pattern) != null;
+    }
+
+    public static int getDiffYear(String startTime, String endTime) {
+        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            int years = (int) (((fmt.parse(endTime).getTime() - fmt.parse(
+                    startTime).getTime()) / (1000 * 60 * 60 * 24)) / 365);
+            return years;
+        } catch (Exception e) {
+            // 如果throw java.text.ParseException或者NullPointerException,就说明格式不对
+            return 0;
+        }
+    }
+
+    /**
+     * <li>功能描述:时间相减得到天数
+     */
+    public static long getDaySub(String beginDateStr, String endDateStr) {
+        long day = 0;
+        SimpleDateFormat format = new SimpleDateFormat(
+                "yyyy-MM-dd");
+        Date beginDate = null;
+        Date endDate = null;
+
+        try {
+            beginDate = format.parse(beginDateStr);
+            endDate = format.parse(endDateStr);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        day = (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
+        // System.out.println("相隔的天数="+day);
+
+        return day;
+    }
+
+    /**
+     * 得到n天之后的日期
+     */
+    public static String getAfterDayDate(String days) {
+        int daysInt = Integer.parseInt(days);
+
+        Calendar canlendar = Calendar.getInstance(); // java.util包
+        canlendar.add(Calendar.DATE, daysInt); // 日期减 如果不够减会将月变动
+        Date date = canlendar.getTime();
+
+        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateStr = sdfd.format(date);
+
+        return dateStr;
+    }
+
+    /**
+     * 得到n天之后是周几
+     */
+    public static String getAfterDayWeek(String days) {
+        int daysInt = Integer.parseInt(days);
+
+        Calendar canlendar = Calendar.getInstance(); // java.util包
+        canlendar.add(Calendar.DATE, daysInt); // 日期减 如果不够减会将月变动
+        Date date = canlendar.getTime();
+
+        SimpleDateFormat sdf = new SimpleDateFormat("E");
+        String dateStr = sdf.format(date);
+
+        return dateStr;
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java
new file mode 100644
index 0000000..f876183
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java
@@ -0,0 +1,73 @@
+package com.stylefeng.guns.core.util;
+
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.core.exception.GunsExceptionEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+public class FileUtil {
+
+    private static Logger log = LoggerFactory.getLogger(FileUtil.class);
+
+    /**
+     * NIO way
+     */
+    public static byte[] toByteArray(String filename) {
+
+        File f = new File(filename);
+        if (!f.exists()) {
+            log.error("文件未找到!" + filename);
+            throw new GunsException(GunsExceptionEnum.FILE_NOT_FOUND);
+        }
+        FileChannel channel = null;
+        FileInputStream fs = null;
+        try {
+            fs = new FileInputStream(f);
+            channel = fs.getChannel();
+            ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
+            while ((channel.read(byteBuffer)) > 0) {
+                // do nothing
+                // System.out.println("reading");
+            }
+            return byteBuffer.array();
+        } catch (IOException e) {
+            throw new GunsException(GunsExceptionEnum.FILE_READING_ERROR);
+        } finally {
+            try {
+                channel.close();
+            } catch (IOException e) {
+                throw new GunsException(GunsExceptionEnum.FILE_READING_ERROR);
+            }
+            try {
+                fs.close();
+            } catch (IOException e) {
+                throw new GunsException(GunsExceptionEnum.FILE_READING_ERROR);
+            }
+        }
+    }
+
+    /**
+     * 删除目录
+     *
+     * @author fengshuonan
+     * @Date 2017/10/30 下午4:15
+     */
+    public static boolean deleteDir(File dir) {
+        if (dir.isDirectory()) {
+            String[] children = dir.list();
+            for (int i = 0; i < children.length; i++) {
+                boolean success = deleteDir(new File(dir, children[i]));
+                if (!success) {
+                    return false;
+                }
+            }
+        }
+        return dir.delete();
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java
new file mode 100644
index 0000000..6eb8d80
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java
@@ -0,0 +1,26 @@
+package com.stylefeng.guns.core.util;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * 非Controller中获取当前session的工具类
+ *
+ * @author fengshuonan
+ * @date 2016年11月28日 上午10:24:31
+ */
+public class HttpSessionHolder {
+
+    private static ThreadLocal<HttpSession> tl = new ThreadLocal<HttpSession>();
+
+    public static void put(HttpSession s) {
+        tl.set(s);
+    }
+
+    public static HttpSession get() {
+        return tl.get();
+    }
+
+    public static void remove() {
+        tl.remove();
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java
new file mode 100644
index 0000000..77c3393
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java
@@ -0,0 +1,20 @@
+package com.stylefeng.guns.core.util;
+
+import com.baomidou.mybatisplus.toolkit.IdWorker;
+
+/**
+ * 唯一id生成器
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 11:10
+ */
+public class IdGenerator {
+
+    public static String getId() {
+        return String.valueOf(IdWorker.getId());
+    }
+
+    public static long getIdLong() {
+        return IdWorker.getId();
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java
new file mode 100644
index 0000000..87e21bd
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java
@@ -0,0 +1,39 @@
+package com.stylefeng.guns.core.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * MD5加密类(封装jdk自带的md5加密方法)
+ *
+ * @author fengshuonan
+ * @date 2016年12月2日 下午4:14:22
+ */
+public class MD5Util {
+
+    public static String encrypt(String source) {
+        return encodeMd5(source.getBytes());
+    }
+
+    private static String encodeMd5(byte[] source) {
+        try {
+            return encodeHex(MessageDigest.getInstance("MD5").digest(source));
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+    }
+
+    private static String encodeHex(byte[] bytes) {
+        StringBuffer buffer = new StringBuffer(bytes.length * 2);
+        for (int i = 0; i < bytes.length; i++) {
+            if (((int) bytes[i] & 0xff) < 0x10)
+                buffer.append("0");
+            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
+        }
+        return buffer.toString();
+    }
+
+    public static void main(String[] args) {
+        System.out.println(encrypt("123456"));
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java
new file mode 100644
index 0000000..6213b66
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java
@@ -0,0 +1,89 @@
+package com.stylefeng.guns.core.util;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+/**
+ * 数字格式化的类
+ *
+ * @author fengshuonan
+ * @date 2016年11月30日 下午5:58:40
+ */
+public class NumUtil {
+
+    /**
+     * @Description 保留指定位数的小数(少的位数不补零)
+     * @author fengshuonan
+     */
+    public static String keepRandomPoint(Double value, int n) {
+        if (value == null) {
+            value = 0.00;
+            return new BigDecimal(value).setScale(n, RoundingMode.HALF_UP).toString();
+        } else {
+            return new BigDecimal(value).setScale(n, RoundingMode.HALF_UP).toString();
+        }
+    }
+
+    /**
+     * @Description 浮点保留两位小数(少的位数不补零)
+     * @author fengshuonan
+     */
+    public static String keep2Point(double value) {
+        return keepRandomPoint(value, 2);
+    }
+
+    /**
+     * @Description 浮点保留1位小数(少的位数不补零)
+     * @author fengshuonan
+     */
+    public static String keep1Point(double value) {
+        return keepRandomPoint(value, 1);
+    }
+
+    /**
+     * @Description 浮点保留任意位小数(少位补零)
+     * @author fengshuonan
+     */
+    public static String keepRandomPointZero(double value, int n) {
+        DecimalFormat df = new DecimalFormat("#0.00");
+        return df.format(Double.valueOf(keepRandomPoint(value, n)));
+    }
+
+    /**
+     * @Description 浮点保留两位小数(少位补零)
+     * @author fengshuonan
+     */
+    public static String keep2PointZero(double value) {
+        return keepRandomPointZero(value, 2);
+    }
+
+    /**
+     * @Description 获取任意小数点位的百分比表示
+     * @author fengshuonan
+     */
+    public static String percentRandomPoint(double value, int n) {
+        NumberFormat percent = NumberFormat.getPercentInstance();
+        percent.setGroupingUsed(false);
+        percent.setMaximumFractionDigits(n);
+        return percent.format(value);
+    }
+
+    /**
+     * @Description 百分比保留两位小数
+     * @author fengshuonan
+     */
+    public static String percent2Point(double value) {
+        return percentRandomPoint(value, 2);
+    }
+
+    /**
+     * @Description 获取格式化经纬度后的小数(保留3位)
+     * @author fengshuonan
+     */
+    public static String latLngPoint(double value) {
+        return keepRandomPoint(value, 3);
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java
new file mode 100644
index 0000000..f8592e0
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java
@@ -0,0 +1,206 @@
+package com.stylefeng.guns.core.util;
+
+import java.util.Random;
+
+/***
+ * 
+ * 得到中文首字母
+ * 
+ * @author lxm_09
+ * 
+ */
+
+public class PingYinUtil {
+
+	public static void main(String[] args) {
+		String str = "这是一个测试";
+		System.out.println("中文首字母:" + getPYIndexStr(str, true));
+	}
+
+	/**
+	 * 返回首字母
+	 */
+	public static String getPYIndexStr(String strChinese, boolean bUpCase) {
+		try {
+			StringBuffer buffer = new StringBuffer();
+			byte b[] = strChinese.getBytes("GBK");// 把中文转化成byte数组
+			for (int i = 0; i < b.length; i++) {
+				if ((b[i] & 255) > 128) {
+					int char1 = b[i++] & 255;
+					char1 <<= 8;// 左移运算符用“<<”表示,是将运算符左边的对象,向左移动运算符右边指定的位数,并且在低位补零。其实,向左移n位,就相当于乘上2的n次方
+					int chart = char1 + (b[i] & 255);
+					buffer.append(getPYIndexChar((char) chart, bUpCase));
+					continue;
+				}
+				char c = (char) b[i];
+				if (!Character.isJavaIdentifierPart(c))// 确定指定字符是否可以是 Java
+														// 标识符中首字符以外的部分。
+					c = 'A';
+				buffer.append(c);
+			}
+			return buffer.toString();
+		} catch (Exception e) {
+			System.out.println((new StringBuilder()).append("\u53D6\u4E2D\u6587\u62FC\u97F3\u6709\u9519")
+					.append(e.getMessage()).toString());
+		}
+		return null;
+	}
+
+	/**
+	 * 得到首字母
+	 */
+	private static char getPYIndexChar(char strChinese, boolean bUpCase) {
+
+		int charGBK = strChinese;
+
+		char result;
+
+		if (charGBK >= 45217 && charGBK <= 45252)
+
+			result = 'A';
+
+		else
+
+		if (charGBK >= 45253 && charGBK <= 45760)
+
+			result = 'B';
+
+		else
+
+		if (charGBK >= 45761 && charGBK <= 46317)
+
+			result = 'C';
+
+		else
+
+		if (charGBK >= 46318 && charGBK <= 46825)
+
+			result = 'D';
+
+		else
+
+		if (charGBK >= 46826 && charGBK <= 47009)
+
+			result = 'E';
+
+		else
+
+		if (charGBK >= 47010 && charGBK <= 47296)
+
+			result = 'F';
+
+		else
+
+		if (charGBK >= 47297 && charGBK <= 47613)
+
+			result = 'G';
+
+		else
+
+		if (charGBK >= 47614 && charGBK <= 48118)
+
+			result = 'H';
+
+		else
+
+		if (charGBK >= 48119 && charGBK <= 49061)
+
+			result = 'J';
+
+		else
+
+		if (charGBK >= 49062 && charGBK <= 49323)
+
+			result = 'K';
+
+		else
+
+		if (charGBK >= 49324 && charGBK <= 49895)
+
+			result = 'L';
+
+		else
+
+		if (charGBK >= 49896 && charGBK <= 50370)
+
+			result = 'M';
+
+		else
+
+		if (charGBK >= 50371 && charGBK <= 50613)
+
+			result = 'N';
+
+		else
+
+		if (charGBK >= 50614 && charGBK <= 50621)
+
+			result = 'O';
+
+		else
+
+		if (charGBK >= 50622 && charGBK <= 50905)
+
+			result = 'P';
+
+		else
+
+		if (charGBK >= 50906 && charGBK <= 51386)
+
+			result = 'Q';
+
+		else
+
+		if (charGBK >= 51387 && charGBK <= 51445)
+
+			result = 'R';
+
+		else
+
+		if (charGBK >= 51446 && charGBK <= 52217)
+
+			result = 'S';
+
+		else
+
+		if (charGBK >= 52218 && charGBK <= 52697)
+
+			result = 'T';
+
+		else
+
+		if (charGBK >= 52698 && charGBK <= 52979)
+
+			result = 'W';
+
+		else
+
+		if (charGBK >= 52980 && charGBK <= 53688)
+
+			result = 'X';
+
+		else
+
+		if (charGBK >= 53689 && charGBK <= 54480)
+
+			result = 'Y';
+
+		else
+
+		if (charGBK >= 54481 && charGBK <= 55289)
+
+			result = 'Z';
+
+		else
+
+			result = (char) (65 + (new Random()).nextInt(25));
+
+		if (!bUpCase)
+
+			result = Character.toLowerCase(result);
+
+		return result;
+
+	}
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java
new file mode 100644
index 0000000..14d6e55
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java
@@ -0,0 +1,32 @@
+package com.stylefeng.guns.core.util;
+
+import com.alibaba.fastjson.JSON;
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.core.exception.GunsExceptionEnum;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * 渲染工具类
+ *
+ * @author stylefeng
+ * @date 2017-08-25 14:13
+ */
+public class RenderUtil {
+
+    /**
+     * 渲染json对象
+     */
+    public static void renderJson(HttpServletResponse response, Object jsonObject) {
+        try {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("UTF-8");
+            PrintWriter writer = response.getWriter();
+            writer.write(JSON.toJSONString(jsonObject));
+        } catch (IOException e) {
+            throw new GunsException(GunsExceptionEnum.WRITE_ERROR);
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java
new file mode 100644
index 0000000..dc735af
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java
@@ -0,0 +1,38 @@
+package com.stylefeng.guns.core.util;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+import java.io.IOException;
+
+/**
+ * 资源文件相关的操作类
+ *
+ * @author fengshuonan
+ * @date 2016年11月17日 下午10:09:23
+ */
+public class ResKit {
+
+    /**
+     * @Description 批量获取ClassPath下的资源文件
+     * @author fengshuonan
+     */
+    public static Resource[] getClassPathResources(String pattern) {
+        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+        try {
+            return resolver.getResources(pattern);
+        } catch (IOException e) {
+            throw new RuntimeException("加载resource文件时,找不到文件,所找文件为:" + pattern);
+        }
+    }
+
+    /**
+     * @Description 批量获取ClassPath下的资源文件
+     * @author fengshuonan
+     */
+    public static String getClassPathFile(String file) {
+		//return ResKit.class.getClassLoader().getResource(file).getPath();
+        return Thread.currentThread().getContextClassLoader().getResource(file).getPath();
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java
new file mode 100644
index 0000000..41659db
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java
@@ -0,0 +1,58 @@
+package com.stylefeng.guns.core.util;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+/**
+ * 对比两个对象的变化的工具类
+ *
+ * @author fengshuonan
+ * @Date 2017/3/31 10:36
+ */
+public class SimpleContrast {
+
+    //记录每个修改字段的分隔符
+    public static final String separator = ";;;";
+
+    /**
+     * 比较两个对象,并返回不一致的信息
+     *
+     * @author stylefeng
+     * @Date 2017/5/9 19:34
+     */
+    public static String contrastObj(Object pojo1, Object pojo2) {
+        String str = "";
+        try {
+            Class clazz = pojo1.getClass();
+            Field[] fields = pojo1.getClass().getDeclaredFields();
+            int i = 1;
+            for (Field field : fields) {
+                if ("serialVersionUID".equals(field.getName())) {
+                    continue;
+                }
+                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
+                Method getMethod = pd.getReadMethod();
+                Object o1 = getMethod.invoke(pojo1);
+                Object o2 = getMethod.invoke(pojo2);
+                if (o1 == null || o2 == null) {
+                    continue;
+                }
+                if (o1 instanceof Date) {
+                    o1 = DateUtil.getDay((Date) o1);
+                }
+                if (!o1.toString().equals(o2.toString())) {
+                    if (i != 1) {
+                        str += separator;
+                    }
+                    str += "字段名称" + field.getName() + ",旧值:" + o1 + ",新值:" + o2;
+                    i++;
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return str;
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java
new file mode 100644
index 0000000..9074c41
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java
@@ -0,0 +1,46 @@
+package com.stylefeng.guns.core.util;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean
+ *
+ * @author fengshuonan
+ * @date 2016年11月27日 下午3:32:11
+ */
+@Component
+public class SpringContextHolder implements ApplicationContextAware {
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+    public static ApplicationContext getApplicationContext() {
+        assertApplicationContext();
+        return applicationContext;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String beanName) {
+        assertApplicationContext();
+        return (T) applicationContext.getBean(beanName);
+    }
+
+    public static <T> T getBean(Class<T> requiredType) {
+        assertApplicationContext();
+        return applicationContext.getBean(requiredType);
+    }
+
+    private static void assertApplicationContext() {
+        if (SpringContextHolder.applicationContext == null) {
+            throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
+        }
+    }
+
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java
new file mode 100644
index 0000000..3c6132e
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java
@@ -0,0 +1,35 @@
+package com.stylefeng.guns.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * sql语句工具类
+ *
+ * @author fengshuonan
+ * @date 2016年12月6日 下午1:01:54
+ */
+public class SqlUtil {
+
+    /**
+     * @Description 根据集合的大小,输出相应个数"?"
+     * @author fengshuonan
+     */
+    public static String parse(List<?> list) {
+        String str = "";
+        if (list != null && list.size() > 0) {
+            str = str + "?";
+            for (int i = 1; i < list.size(); i++) {
+                str = str + ",?";
+            }
+        }
+        return str;
+    }
+
+    public static void main(String[] args) {
+        ArrayList<Object> arrayList = new ArrayList<>();
+        arrayList.add(2);
+        arrayList.add(2);
+        System.out.println(parse(arrayList));
+    }
+}
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java
new file mode 100644
index 0000000..0347ac2
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java
@@ -0,0 +1,582 @@
+/**
+ * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.stylefeng.guns.core.util;
+
+import com.stylefeng.guns.core.support.StrKit;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * 高频方法集合类
+ */
+public class ToolUtil {
+
+    /**
+     * 获取随机位数的字符串
+     *
+     * @author fengshuonan
+     * @Date 2017/8/24 14:09
+     */
+    public static String getRandomString(int length) {
+        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
+        Random random = new Random();
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            int number = random.nextInt(base.length());
+            sb.append(base.charAt(number));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 判断一个对象是否是时间类型
+     *
+     * @author stylefeng
+     * @Date 2017/4/18 12:55
+     */
+    public static String dateType(Object o) {
+        if (o instanceof Date) {
+            return DateUtil.getDay((Date) o);
+        } else {
+            return o.toString();
+        }
+    }
+
+    /**
+     * 获取异常的具体信息
+     *
+     * @author fengshuonan
+     * @Date 2017/3/30 9:21
+     * @version 2.0
+     */
+    public static String getExceptionMsg(Exception e) {
+        StringWriter sw = new StringWriter();
+        try {
+            e.printStackTrace(new PrintWriter(sw));
+        } finally {
+            try {
+                sw.close();
+            } catch (IOException e1) {
+                e1.printStackTrace();
+            }
+        }
+        return sw.getBuffer().toString().replaceAll("\\$", "T");
+    }
+
+    /**
+     * 比较两个对象是否相等。<br>
+     * 相同的条件有两个,满足其一即可:<br>
+     * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
+     *
+     * @param obj1 对象1
+     * @param obj2 对象2
+     * @return 是否相等
+     */
+    public static boolean equals(Object obj1, Object obj2) {
+        return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
+    }
+
+    /**
+     * 计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度
+     *
+     * @param obj 被计算长度的对象
+     * @return 长度
+     */
+    public static int length(Object obj) {
+        if (obj == null) {
+            return 0;
+        }
+        if (obj instanceof CharSequence) {
+            return ((CharSequence) obj).length();
+        }
+        if (obj instanceof Collection) {
+            return ((Collection<?>) obj).size();
+        }
+        if (obj instanceof Map) {
+            return ((Map<?, ?>) obj).size();
+        }
+
+        int count;
+        if (obj instanceof Iterator) {
+            Iterator<?> iter = (Iterator<?>) obj;
+            count = 0;
+            while (iter.hasNext()) {
+                count++;
+                iter.next();
+            }
+            return count;
+        }
+        if (obj instanceof Enumeration) {
+            Enumeration<?> enumeration = (Enumeration<?>) obj;
+            count = 0;
+            while (enumeration.hasMoreElements()) {
+                count++;
+                enumeration.nextElement();
+            }
+            return count;
+        }
+        if (obj.getClass().isArray() == true) {
+            return Array.getLength(obj);
+        }
+        return -1;
+    }
+
+    /**
+     * 对象中是否包含元素
+     *
+     * @param obj     对象
+     * @param element 元素
+     * @return 是否包含
+     */
+    public static boolean contains(Object obj, Object element) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof String) {
+            if (element == null) {
+                return false;
+            }
+            return ((String) obj).contains(element.toString());
+        }
+        if (obj instanceof Collection) {
+            return ((Collection<?>) obj).contains(element);
+        }
+        if (obj instanceof Map) {
+            return ((Map<?, ?>) obj).values().contains(element);
+        }
+
+        if (obj instanceof Iterator) {
+            Iterator<?> iter = (Iterator<?>) obj;
+            while (iter.hasNext()) {
+                Object o = iter.next();
+                if (equals(o, element)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        if (obj instanceof Enumeration) {
+            Enumeration<?> enumeration = (Enumeration<?>) obj;
+            while (enumeration.hasMoreElements()) {
+                Object o = enumeration.nextElement();
+                if (equals(o, element)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        if (obj.getClass().isArray() == true) {
+            int len = Array.getLength(obj);
+            for (int i = 0; i < len; i++) {
+                Object o = Array.get(obj, i);
+                if (equals(o, element)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 对象是否不为空(新增)
+     *
+     * @param obj String,List,Map,Object[],int[],long[]
+     * @return
+     */
+    public static boolean isNotEmpty(Object o) {
+        return !isEmpty(o);
+    }
+
+    /**
+     * 对象是否为空
+     *
+     * @param obj String,List,Map,Object[],int[],long[]
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    public static boolean isEmpty(Object o) {
+        if (o == null) {
+            return true;
+        }
+        if (o instanceof String) {
+            if (o.toString().trim().equals("")) {
+                return true;
+            }
+        } else if (o instanceof List) {
+            if (((List) o).size() == 0) {
+                return true;
+            }
+        } else if (o instanceof Map) {
+            if (((Map) o).size() == 0) {
+                return true;
+            }
+        } else if (o instanceof Set) {
+            if (((Set) o).size() == 0) {
+                return true;
+            }
+        } else if (o instanceof Object[]) {
+            if (((Object[]) o).length == 0) {
+                return true;
+            }
+        } else if (o instanceof int[]) {
+            if (((int[]) o).length == 0) {
+                return true;
+            }
+        } else if (o instanceof long[]) {
+            if (((long[]) o).length == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 对象组中是否存在 Empty Object
+     *
+     * @param os 对象组
+     * @return
+     */
+    public static boolean isOneEmpty(Object... os) {
+        for (Object o : os) {
+            if (isEmpty(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 对象组中是否全是 Empty Object
+     *
+     * @param os
+     * @return
+     */
+    public static boolean isAllEmpty(Object... os) {
+        for (Object o : os) {
+            if (!isEmpty(o)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 是否为数字
+     *
+     * @param obj
+     * @return
+     */
+    public static boolean isNum(Object obj) {
+        try {
+            Integer.parseInt(obj.toString());
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 如果为空, 则调用默认值
+     *
+     * @param str
+     * @return
+     */
+    public static Object getValue(Object str, Object defaultValue) {
+        if (isEmpty(str)) {
+            return defaultValue;
+        }
+        return str;
+    }
+
+    /**
+     * 格式化文本
+     *
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param values   参数值
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Object... values) {
+        return StrKit.format(template, values);
+    }
+
+    /**
+     * 格式化文本
+     *
+     * @param template 文本模板,被替换的部分用 {key} 表示
+     * @param map      参数值对
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Map<?, ?> map) {
+        return StrKit.format(template, map);
+    }
+
+    /**
+     * 强转->string,并去掉多余空格
+     *
+     * @param str
+     * @return
+     */
+    public static String toStr(Object str) {
+        return toStr(str, "");
+    }
+
+    /**
+     * 强转->string,并去掉多余空格
+     *
+     * @param str
+     * @param defaultValue
+     * @return
+     */
+    public static String toStr(Object str, String defaultValue) {
+        if (null == str) {
+            return defaultValue;
+        }
+        return str.toString().trim();
+    }
+
+    /**
+     * 强转->int
+     *
+     * @param obj
+     * @return
+     */
+//	public static int toInt(Object value) {
+//		return toInt(value, -1);
+//	}
+
+    /**
+     * 强转->int
+     *
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+//	public static int toInt(Object value, int defaultValue) {
+//		return Convert.toInt(value, defaultValue);
+//	}
+
+    /**
+     * 强转->long
+     *
+     * @param obj
+     * @return
+     */
+//	public static long toLong(Object value) {
+//		return toLong(value, -1);
+//	}
+
+    /**
+     * 强转->long
+     *
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+//	public static long toLong(Object value, long defaultValue) {
+//		return Convert.toLong(value, defaultValue);
+//	}
+//
+//	public static String encodeUrl(String url) {
+//		return URLKit.encode(url, CharsetKit.UTF_8);
+//	}
+//
+//	public static String decodeUrl(String url) {
+//		return URLKit.decode(url, CharsetKit.UTF_8);
+//	}
+
+    /**
+     * map的key转为小写
+     *
+     * @param map
+     * @return Map<String , Object>
+     */
+    public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) {
+        Map<String, Object> tempMap = new HashMap<>();
+        for (String key : map.keySet()) {
+            tempMap.put(key.toLowerCase(), map.get(key));
+        }
+        return tempMap;
+    }
+
+    /**
+     * 获取map中第一个数据值
+     *
+     * @param <K> Key的类型
+     * @param <V> Value的类型
+     * @param map 数据源
+     * @return 返回的值
+     */
+    public static <K, V> V getFirstOrNull(Map<K, V> map) {
+        V obj = null;
+        for (Entry<K, V> entry : map.entrySet()) {
+            obj = entry.getValue();
+            if (obj != null) {
+                break;
+            }
+        }
+        return obj;
+    }
+
+    /**
+     * 创建StringBuilder对象
+     *
+     * @return StringBuilder对象
+     */
+    public static StringBuilder builder(String... strs) {
+        final StringBuilder sb = new StringBuilder();
+        for (String str : strs) {
+            sb.append(str);
+        }
+        return sb;
+    }
+
+    /**
+     * 创建StringBuilder对象
+     *
+     * @return StringBuilder对象
+     */
+    public static void builder(StringBuilder sb, String... strs) {
+        for (String str : strs) {
+            sb.append(str);
+        }
+    }
+
+    /**
+     * 去掉指定后缀
+     *
+     * @param str    字符串
+     * @param suffix 后缀
+     * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
+     */
+    public static String removeSuffix(String str, String suffix) {
+        if (isEmpty(str) || isEmpty(suffix)) {
+            return str;
+        }
+
+        if (str.endsWith(suffix)) {
+            return str.substring(0, str.length() - suffix.length());
+        }
+        return str;
+    }
+
+    /**
+     * 当前时间
+     *
+     * @author stylefeng
+     * @Date 2017/5/7 21:56
+     */
+    public static String currentTime() {
+        return DateUtil.getTime();
+    }
+
+    /**
+     * 首字母大写
+     *
+     * @author stylefeng
+     * @Date 2017/5/7 22:01
+     */
+    public static String firstLetterToUpper(String val) {
+        return StrKit.firstCharToUpperCase(val);
+    }
+
+    /**
+     * 首字母小写
+     *
+     * @author stylefeng
+     * @Date 2017/5/7 22:02
+     */
+    public static String firstLetterToLower(String val) {
+        return StrKit.firstCharToLowerCase(val);
+    }
+
+    /**
+     * 判断是否是windows操作系统
+     *
+     * @author stylefeng
+     * @Date 2017/5/24 22:34
+     */
+    public static Boolean isWinOs() {
+        String os = System.getProperty("os.name");
+        if (os.toLowerCase().startsWith("win")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 获取临时目录
+     *
+     * @author stylefeng
+     * @Date 2017/5/24 22:35
+     */
+    public static String getTempPath() {
+        return System.getProperty("java.io.tmpdir");
+    }
+
+    /**
+     * 把一个数转化为int
+     *
+     * @author fengshuonan
+     * @Date 2017/11/15 下午11:10
+     */
+    public static Integer toInt(Object val) {
+        if (val instanceof Double) {
+            BigDecimal bigDecimal = new BigDecimal((Double) val);
+            return bigDecimal.intValue();
+        } else {
+            return Integer.valueOf(val.toString());
+        }
+
+    }
+
+    /**
+     * 获取项目路径
+     */
+    public static String getWebRootPath(String filePath) {
+        try {
+            String path = ToolUtil.class.getClassLoader().getResource("").toURI().getPath();
+            path = path.replace("/WEB-INF/classes/", "");
+            path = path.replace("/target/classes/", "");
+            path = path.replace("file:/", "");
+            if (ToolUtil.isEmpty(filePath)) {
+                return path;
+            } else {
+                return path + "/" + filePath;
+            }
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 获取文件后缀名 不包含点
+     */
+    public static String getFileSuffix(String fileWholeName) {
+        if (ToolUtil.isEmpty(fileWholeName)) {
+            return "none";
+        }
+        int lastIndexOf = fileWholeName.lastIndexOf(".");
+        return fileWholeName.substring(lastIndexOf + 1);
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java
new file mode 100644
index 0000000..ec44eb2
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java
@@ -0,0 +1,42 @@
+package com.stylefeng.guns.core.xss;
+
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.List;
+
+
+public class XssFilter implements Filter {
+
+    FilterConfig filterConfig = null;
+
+    private List<String> urlExclusion = null;
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+        this.filterConfig = filterConfig;
+    }
+
+    public void destroy() {
+        this.filterConfig = null;
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String servletPath = httpServletRequest.getServletPath();
+
+        if (urlExclusion != null && urlExclusion.contains(servletPath)) {
+            chain.doFilter(request, response);
+        } else {
+            chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
+        }
+    }
+
+    public List<String> getUrlExclusion() {
+        return urlExclusion;
+    }
+
+    public void setUrlExclusion(List<String> urlExclusion) {
+        this.urlExclusion = urlExclusion;
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..693b828
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java
@@ -0,0 +1,87 @@
+package com.stylefeng.guns.core.xss;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
+
+        super(servletRequest);
+
+    }
+
+    public String[] getParameterValues(String parameter) {
+
+        String[] values = super.getParameterValues(parameter);
+
+        if (values == null) {
+
+            return null;
+
+        }
+
+        int count = values.length;
+
+        String[] encodedValues = new String[count];
+
+        for (int i = 0; i < count; i++) {
+
+            encodedValues[i] = cleanXSS(values[i]);
+
+        }
+
+        return encodedValues;
+
+    }
+
+    public String getParameter(String parameter) {
+
+        String value = super.getParameter(parameter);
+
+        if (value == null) {
+
+            return null;
+
+        }
+
+        return cleanXSS(value);
+
+    }
+
+    public String getHeader(String name) {
+
+        String value = super.getHeader(name);
+
+        if (value == null)
+
+            return null;
+
+        return cleanXSS(value);
+
+    }
+
+    private String cleanXSS(String value) {
+
+        //You'll need to remove the spaces from the html entities below
+
+        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
+
+        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
+
+        value = value.replaceAll("'", "& #39;");
+
+        value = value.replaceAll("eval\\((.*)\\)", "");
+
+        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
+
+        value = value.replaceAll("script", "");
+
+        return value;
+
+    }
+
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/resources/META-INF/spring.factories b/DriverOKTravel/guns-core/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..0dc03f2
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,6 @@
+# AutoConfiguration
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.stylefeng.guns.core.base.controller.GlobalController,\
+com.stylefeng.guns.core.config.DefaultFastjsonConfig,\
+com.stylefeng.guns.core.config.DefaultProperties,\
+com.stylefeng.guns.core.config.DefaultWebConfig
\ No newline at end of file
diff --git a/DriverOKTravel/guns-core/src/main/resources/default-config.properties b/DriverOKTravel/guns-core/src/main/resources/default-config.properties
new file mode 100644
index 0000000..8d458f7
--- /dev/null
+++ b/DriverOKTravel/guns-core/src/main/resources/default-config.properties
@@ -0,0 +1,36 @@
+#\u8FD9\u4E2A\u914D\u7F6E\u6587\u4EF6\u91CC\u5199\u5176\u4ED6\u9879\u76EE\u53EF\u80FD\u5171\u7528\u7684\u914D\u7F6E,\u53EF\u4EE5\u5728application.yml\u4E2D\u914D\u7F6E\u4FE1\u606F\u8986\u76D6\u8FD9\u91CC\u7684\u914D\u7F6E
+
+
+######################### springs\u9ED8\u8BA4\u914D\u7F6E #########################
+spring.aop.proxy-target-class=true
+
+
+###################### mybatis-plus\u9ED8\u8BA4\u914D\u7F6E #######################
+mybatis-plus.mapper-locations=classpath*:com/stylefeng/guns/**/mapping/*.xml
+# 0:\u6570\u636E\u5E93ID\u81EA\u589E   1:\u7528\u6237\u8F93\u5165id  2:\u5168\u5C40\u552F\u4E00id(IdWorker)  3:\u5168\u5C40\u552F\u4E00ID(uuid)
+mybatis-plus.global-config.id-type=0
+mybatis-plus.global-config.db-column-underline=false
+mybatis-plus.global-config.refresh-mapper=true
+mybatis-plus.global-config.logic-delete-value=0
+mybatis-plus.global-config.logic-not-delete-value=1
+mybatis-plus.global-config.sql-injector=com.baomidou.mybatisplus.mapper.LogicSqlInjector
+mybatis-plus.configuration.map-underscore-to-camel-case=false
+#\u914D\u7F6E\u7684\u7F13\u5B58\u7684\u5168\u5C40\u5F00\u5173
+mybatis-plus.configuration.cache-enabled=true
+# \u5EF6\u65F6\u52A0\u8F7D\u7684\u5F00\u5173
+mybatis-plus.configuration.lazyLoadingEnabled=true
+# \u5F00\u542F\u7684\u8BDD\uFF0C\u5EF6\u65F6\u52A0\u8F7D\u4E00\u4E2A\u5C5E\u6027\u65F6\u4F1A\u52A0\u8F7D\u8BE5\u5BF9\u8C61\u5168\u90E8\u5C5E\u6027\uFF0C\u5426\u5219\u6309\u9700\u52A0\u8F7D\u5C5E\u6027
+mybatis-plus.configuration.multipleResultSetsEnabled=true
+# \u6253\u5370sql\u8BED\u53E5,\u8C03\u8BD5\u7528
+mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
+
+
+########################## beetl\u9ED8\u8BA4\u914D\u7F6E ###########################
+#\u5F00\u59CB\u7ED3\u675F\u6807\u7B7E(yaml\u4E0D\u5141\u8BB8@\u5F00\u5934)
+beetl.delimiter-statement-start=@
+beetl.delimiter-statement-end=null
+#\u81EA\u5B9A\u4E49\u6807\u7B7E\u6587\u4EF6Root\u76EE\u5F55\u548C\u540E\u7F00
+beetl.resource-tagroot=common/tags
+beetl.resource-tagsuffix=tag
+#\u662F\u5426\u68C0\u6D4B\u6587\u4EF6\u53D8\u5316,\u5F00\u53D1\u7528true\u5408\u9002\uFF0C\u4F46\u7EBF\u4E0A\u8981\u6539\u4E3Afalse
+beetl.resource-auto-check=true
\ No newline at end of file
diff --git a/DriverOKTravel/guns-generator/pom.xml b/DriverOKTravel/guns-generator/pom.xml
new file mode 100644
index 0000000..1328611
--- /dev/null
+++ b/DriverOKTravel/guns-generator/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>guns-generator</artifactId>
+    <packaging>jar</packaging>
+
+    <name>guns-generator</name>
+    <description>代码生成器</description>
+
+    <parent>
+        <groupId>com.stylefeng</groupId>
+        <artifactId>guns-parent</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.stylefeng</groupId>
+            <artifactId>guns-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ibeetl</groupId>
+            <artifactId>beetl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generate</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java
new file mode 100644
index 0000000..bcd169b
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java
@@ -0,0 +1,30 @@
+package com.stylefeng.guns.generator.action;
+
+
+import com.stylefeng.guns.generator.action.config.GunsGeneratorConfig;
+
+/**
+ * 代码生成器,可以生成实体,dao,service,controller,html,js
+ *
+ * @author stylefeng
+ * @Date 2017/5/21 12:38
+ */
+public class GunsCodeGenerator {
+
+    public static void main(String[] args) {
+
+        /**
+         * Mybatis-Plus的代码生成器:
+         *      mp的代码生成器可以生成实体,mapper,mapper对应的xml,service
+         */
+        GunsGeneratorConfig gunsGeneratorConfig = new GunsGeneratorConfig();
+        gunsGeneratorConfig.doMpGeneration();
+
+        /**
+         * guns的生成器:
+         *      guns的代码生成器可以生成controller,html页面,页面对应的js
+         */
+        gunsGeneratorConfig.doGunsGeneration();
+    }
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java
new file mode 100644
index 0000000..e50b78a
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java
@@ -0,0 +1,109 @@
+package com.stylefeng.guns.generator.action.config;
+
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.PackageConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.stylefeng.guns.core.util.FileUtil;
+import com.stylefeng.guns.generator.engine.SimpleTemplateEngine;
+import com.stylefeng.guns.generator.engine.base.GunsTemplateEngine;
+import com.stylefeng.guns.generator.engine.config.ContextConfig;
+import com.stylefeng.guns.generator.engine.config.SqlConfig;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * 代码生成的抽象配置
+ *
+ * @author fengshuonan
+ * @date 2017-10-28-下午8:22
+ */
+public abstract class AbstractGeneratorConfig {
+
+    /**
+     * mybatis-plus代码生成器配置
+     */
+    GlobalConfig globalConfig = new GlobalConfig();
+
+    DataSourceConfig dataSourceConfig = new DataSourceConfig();
+
+    StrategyConfig strategyConfig = new StrategyConfig();
+
+    PackageConfig packageConfig = new PackageConfig();
+
+    TableInfo tableInfo = null;
+
+    /**
+     * Guns代码生成器配置
+     */
+    ContextConfig contextConfig = new ContextConfig();
+
+    SqlConfig sqlConfig = new SqlConfig();
+
+    protected abstract void config();
+
+    public void init() {
+        config();
+
+        packageConfig.setService(contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".service");
+        packageConfig.setServiceImpl(contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".service.impl");
+
+        //controller没用掉,生成之后会自动删掉
+        packageConfig.setController("TTT");
+
+        if (!contextConfig.getEntitySwitch()) {
+            packageConfig.setEntity("TTT");
+        }
+
+        if (!contextConfig.getDaoSwitch()) {
+            packageConfig.setMapper("TTT");
+            packageConfig.setXml("TTT");
+        }
+
+        if (!contextConfig.getServiceSwitch()) {
+            packageConfig.setService("TTT");
+            packageConfig.setServiceImpl("TTT");
+        }
+
+    }
+
+    /**
+     * 删除不必要的代码
+     */
+    public void destory() {
+        String outputDir = globalConfig.getOutputDir() + "/TTT";
+        FileUtil.deleteDir(new File(outputDir));
+    }
+
+    public AbstractGeneratorConfig() {
+    }
+
+    public void doMpGeneration() {
+        init();
+        AutoGenerator autoGenerator = new AutoGenerator();
+        autoGenerator.setGlobalConfig(globalConfig);
+        autoGenerator.setDataSource(dataSourceConfig);
+        autoGenerator.setStrategy(strategyConfig);
+        autoGenerator.setPackageInfo(packageConfig);
+        autoGenerator.execute();
+        destory();
+
+        //获取table信息,用于guns代码生成
+        List<TableInfo> tableInfoList = autoGenerator.getConfig().getTableInfoList();
+        if (tableInfoList != null && tableInfoList.size() > 0) {
+            this.tableInfo = tableInfoList.get(0);
+        }
+    }
+
+    public void doGunsGeneration() {
+        GunsTemplateEngine GunsTemplateEngine = new SimpleTemplateEngine();
+        GunsTemplateEngine.setContextConfig(contextConfig);
+        sqlConfig.setConnection(dataSourceConfig.getConn());
+        GunsTemplateEngine.setSqlConfig(sqlConfig);
+        GunsTemplateEngine.setTableInfo(tableInfo);
+        GunsTemplateEngine.start();
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java
new file mode 100644
index 0000000..43012ab
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java
@@ -0,0 +1,81 @@
+package com.stylefeng.guns.generator.action.config;
+
+import com.baomidou.mybatisplus.generator.config.rules.DbType;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+
+/**
+ * 默认的代码生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-10-28-下午8:27
+ */
+public class GunsGeneratorConfig extends AbstractGeneratorConfig {
+
+    protected void globalConfig() {
+        globalConfig.setOutputDir("D:\\ttt");//写自己项目的绝对路径,注意具体到java目录
+        globalConfig.setFileOverride(true);
+        globalConfig.setEnableCache(false);
+        globalConfig.setBaseResultMap(true);
+        globalConfig.setBaseColumnList(true);
+        globalConfig.setOpen(false);
+        globalConfig.setAuthor("stylefeng");
+    }
+
+    protected void dataSourceConfig() {
+        dataSourceConfig.setDbType(DbType.MYSQL);
+        dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
+        dataSourceConfig.setUsername("root");
+        dataSourceConfig.setPassword("root");
+        dataSourceConfig.setUrl("jdbc:mysql://127.0.0.1:3306/guns?characterEncoding=utf8");
+    }
+
+    protected void strategyConfig() {
+        strategyConfig.setTablePrefix(new String[]{"sys_"});// 此处可以修改为您的表前缀
+        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
+    }
+
+    protected void packageConfig() {
+        packageConfig.setParent(null);
+        packageConfig.setEntity("com.stylefeng.guns.admin.common.persistence.model");
+        packageConfig.setMapper("com.stylefeng.guns.admin.common.persistence.dao");
+        packageConfig.setXml("com.stylefeng.guns.admin.common.persistence.dao.mapping");
+    }
+
+    protected void contextConfig() {
+        contextConfig.setProPackage("com.stylefeng.guns.admin");
+        contextConfig.setCoreBasePackage("com.stylefeng.guns.core");
+        contextConfig.setBizChName("字典管理");
+        contextConfig.setBizEnName("sysDict");
+        contextConfig.setModuleName("system");
+        contextConfig.setProjectPath("D:\\ideaSpace\\guns\\guns-admin");//写自己项目的绝对路径
+        contextConfig.setEntityName("SysDict");
+        sqlConfig.setParentMenuName(null);//这里写已有菜单的名称,当做父节点
+
+        /**
+         * mybatis-plus 生成器开关
+         */
+        contextConfig.setEntitySwitch(true);
+        contextConfig.setDaoSwitch(true);
+        contextConfig.setServiceSwitch(true);
+
+        /**
+         * guns 生成器开关
+         */
+        contextConfig.setControllerSwitch(true);
+        contextConfig.setIndexPageSwitch(true);
+        contextConfig.setAddPageSwitch(true);
+        contextConfig.setEditPageSwitch(true);
+        contextConfig.setJsSwitch(true);
+        contextConfig.setInfoJsSwitch(true);
+        contextConfig.setSqlSwitch(true);
+    }
+
+    @Override
+    protected void config() {
+        globalConfig();
+        dataSourceConfig();
+        strategyConfig();
+        packageConfig();
+        contextConfig();
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java
new file mode 100644
index 0000000..6b821f5
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java
@@ -0,0 +1,97 @@
+package com.stylefeng.guns.generator.action.config;
+
+import com.baomidou.mybatisplus.generator.config.rules.DbType;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.stylefeng.guns.core.support.StrKit;
+import com.stylefeng.guns.core.util.ToolUtil;
+import com.stylefeng.guns.generator.action.model.GenQo;
+
+import java.io.File;
+
+/**
+ * 默认的代码生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-10-28-下午8:27
+ */
+public class WebGeneratorConfig extends AbstractGeneratorConfig {
+
+    private GenQo genQo;
+
+    public WebGeneratorConfig(GenQo genQo) {
+        this.genQo = genQo;
+    }
+
+    @Override
+    protected void config() {
+        /**
+         * 数据库配置
+         */
+        dataSourceConfig.setDbType(DbType.MYSQL);
+        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
+        dataSourceConfig.setUsername(genQo.getUserName());
+        dataSourceConfig.setPassword(genQo.getPassword());
+        dataSourceConfig.setUrl(genQo.getUrl());
+
+        /**
+         * 全局配置
+         */
+        globalConfig.setOutputDir(genQo.getProjectPath() + File.separator + "src" + File.separator + "main" + File.separator + "java");
+        globalConfig.setFileOverride(true);
+        globalConfig.setEnableCache(false);
+        globalConfig.setBaseResultMap(true);
+        globalConfig.setBaseColumnList(true);
+        globalConfig.setOpen(false);
+        globalConfig.setAuthor(genQo.getAuthor());
+        contextConfig.setProPackage(genQo.getProjectPackage());
+        contextConfig.setCoreBasePackage(genQo.getCorePackage());
+
+        /**
+         * 生成策略
+         */
+        if (genQo.getIgnoreTabelPrefix() != null) {
+            strategyConfig.setTablePrefix(new String[]{genQo.getIgnoreTabelPrefix()});
+        }
+        strategyConfig.setInclude(new String[]{genQo.getTableName()});
+        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
+        packageConfig.setParent(null);
+        packageConfig.setEntity(genQo.getProjectPackage() + ".modular.system.model");
+        packageConfig.setMapper(genQo.getProjectPackage() + ".modular.system.dao");
+        packageConfig.setXml(genQo.getProjectPackage() + ".modular.system.dao.mapping");
+
+        /**
+         * 业务代码配置
+         */
+        contextConfig.setBizChName(genQo.getBizName());
+        contextConfig.setModuleName(genQo.getModuleName());
+        contextConfig.setProjectPath(genQo.getProjectPath());//写自己项目的绝对路径
+        if(ToolUtil.isEmpty(genQo.getIgnoreTabelPrefix())){
+            String entityName = StrKit.toCamelCase(genQo.getTableName());
+            contextConfig.setEntityName(StrKit.firstCharToUpperCase(entityName));
+            contextConfig.setBizEnName(StrKit.firstCharToLowerCase(entityName));
+        }else{
+            String entiyName = StrKit.toCamelCase(StrKit.removePrefix(genQo.getTableName(), genQo.getIgnoreTabelPrefix()));
+            contextConfig.setEntityName(StrKit.firstCharToUpperCase(entiyName));
+            contextConfig.setBizEnName(StrKit.firstCharToLowerCase(entiyName));
+        }
+        sqlConfig.setParentMenuName(genQo.getParentMenuName());//这里写已有菜单的名称,当做父节点
+
+        /**
+         * mybatis-plus 生成器开关
+         */
+        contextConfig.setEntitySwitch(genQo.getEntitySwitch());
+        contextConfig.setDaoSwitch(genQo.getDaoSwitch());
+        contextConfig.setServiceSwitch(genQo.getServiceSwitch());
+
+        /**
+         * guns 生成器开关
+         */
+        contextConfig.setControllerSwitch(genQo.getControllerSwitch());
+        contextConfig.setIndexPageSwitch(genQo.getIndexPageSwitch());
+        contextConfig.setAddPageSwitch(genQo.getAddPageSwitch());
+        contextConfig.setEditPageSwitch(genQo.getEditPageSwitch());
+        contextConfig.setJsSwitch(genQo.getJsSwitch());
+        contextConfig.setInfoJsSwitch(genQo.getInfoJsSwitch());
+        contextConfig.setSqlSwitch(genQo.getSqlSwitch());
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java
new file mode 100644
index 0000000..b09d948
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java
@@ -0,0 +1,297 @@
+package com.stylefeng.guns.generator.action.model;
+
+/**
+ * 代码生成的查询参数
+ *
+ * @author fengshuonan
+ * @date 2017-11-30-下午2:05
+ */
+public class GenQo {
+
+    /**
+     * 数据库账号
+     */
+    private String userName;
+
+    /**
+     * 数据库密码
+     */
+    private String password;
+
+    /**
+     * 数据库url
+     */
+    private String url;
+
+    /**
+     * 项目地址
+     */
+    private String projectPath;
+
+    /**
+     * 作者
+     */
+    private String author;
+
+    /**
+     * 项目的包
+     */
+    private String projectPackage;
+
+    /**
+     * 核心模块的包
+     */
+    private String corePackage;
+
+    /**
+     * 表名称
+     */
+    private String tableName;
+
+    /**
+     * 忽略的表前缀
+     */
+    private String ignoreTabelPrefix;
+
+    /**
+     * 业务名称
+     */
+    private String bizName;
+
+    /**
+     * 模块名
+     */
+    private String moduleName;
+    
+    /**
+     * 父级菜单名称
+     */
+    private String parentMenuName;
+
+    /**
+     * 是否生成控制器代码开关
+     */
+    private Boolean controllerSwitch = false;
+
+    /**
+     * 主页
+     */
+    private Boolean indexPageSwitch = false;
+
+    /**
+     * 添加页面
+     */
+    private Boolean addPageSwitch = false;
+
+    /**
+     * 编辑页面
+     */
+    private Boolean editPageSwitch = false;
+
+    /**
+     * 主页的js
+     */
+    private Boolean jsSwitch = false;
+
+    /**
+     * 详情页面js
+     */
+    private Boolean infoJsSwitch = false;
+
+    /**
+     * dao的开关
+     */
+    private Boolean daoSwitch = false;
+
+    /**
+     * service
+     */
+    private Boolean serviceSwitch = false;
+
+    /**
+     * 生成实体的开关
+     */
+    private Boolean entitySwitch = false;
+
+    /**
+     * 生成sql的开关
+     */
+    private Boolean sqlSwitch = false;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getProjectPath() {
+        return projectPath;
+    }
+
+    public void setProjectPath(String projectPath) {
+        this.projectPath = projectPath;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public String getCorePackage() {
+        return corePackage;
+    }
+
+    public void setCorePackage(String corePackage) {
+        this.corePackage = corePackage;
+    }
+
+    public String getProjectPackage() {
+
+        return projectPackage;
+    }
+
+    public void setProjectPackage(String projectPackage) {
+        this.projectPackage = projectPackage;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public void setTableName(String tableName) {
+        this.tableName = tableName;
+    }
+
+    public String getIgnoreTabelPrefix() {
+        return ignoreTabelPrefix;
+    }
+
+    public void setIgnoreTabelPrefix(String ignoreTabelPrefix) {
+        this.ignoreTabelPrefix = ignoreTabelPrefix;
+    }
+
+    public String getBizName() {
+        return bizName;
+    }
+
+    public void setBizName(String bizName) {
+        this.bizName = bizName;
+    }
+
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    public Boolean getControllerSwitch() {
+        return controllerSwitch;
+    }
+
+    public void setControllerSwitch(Boolean controllerSwitch) {
+        this.controllerSwitch = controllerSwitch;
+    }
+
+    public Boolean getIndexPageSwitch() {
+        return indexPageSwitch;
+    }
+
+    public void setIndexPageSwitch(Boolean indexPageSwitch) {
+        this.indexPageSwitch = indexPageSwitch;
+    }
+
+    public Boolean getAddPageSwitch() {
+        return addPageSwitch;
+    }
+
+    public void setAddPageSwitch(Boolean addPageSwitch) {
+        this.addPageSwitch = addPageSwitch;
+    }
+
+    public Boolean getEditPageSwitch() {
+        return editPageSwitch;
+    }
+
+    public void setEditPageSwitch(Boolean editPageSwitch) {
+        this.editPageSwitch = editPageSwitch;
+    }
+
+    public Boolean getJsSwitch() {
+        return jsSwitch;
+    }
+
+    public void setJsSwitch(Boolean jsSwitch) {
+        this.jsSwitch = jsSwitch;
+    }
+
+    public Boolean getInfoJsSwitch() {
+        return infoJsSwitch;
+    }
+
+    public void setInfoJsSwitch(Boolean infoJsSwitch) {
+        this.infoJsSwitch = infoJsSwitch;
+    }
+
+    public Boolean getDaoSwitch() {
+        return daoSwitch;
+    }
+
+    public void setDaoSwitch(Boolean daoSwitch) {
+        this.daoSwitch = daoSwitch;
+    }
+
+    public Boolean getServiceSwitch() {
+        return serviceSwitch;
+    }
+
+    public void setServiceSwitch(Boolean serviceSwitch) {
+        this.serviceSwitch = serviceSwitch;
+    }
+
+    public Boolean getEntitySwitch() {
+        return entitySwitch;
+    }
+
+    public void setEntitySwitch(Boolean entitySwitch) {
+        this.entitySwitch = entitySwitch;
+    }
+
+    public Boolean getSqlSwitch() {
+        return sqlSwitch;
+    }
+
+    public void setSqlSwitch(Boolean sqlSwitch) {
+        this.sqlSwitch = sqlSwitch;
+    }
+
+    public String getParentMenuName() {
+        return parentMenuName;
+    }
+
+    public void setParentMenuName(String parentMenuName) {
+        this.parentMenuName = parentMenuName;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java
new file mode 100644
index 0000000..9e057c7
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java
@@ -0,0 +1,70 @@
+package com.stylefeng.guns.generator.engine;
+
+
+import com.stylefeng.guns.core.util.ToolUtil;
+import com.stylefeng.guns.generator.engine.base.GunsTemplateEngine;
+
+/**
+ * 通用的模板生成引擎
+ *
+ * @author fengshuonan
+ * @date 2017-05-09 20:32
+ */
+public class SimpleTemplateEngine extends GunsTemplateEngine {
+
+    @Override
+    protected void generatePageEditHtml() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPageEditPathTemplate(),
+                super.getContextConfig().getBizEnName(), super.getContextConfig().getBizEnName());
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/page_edit.html.btl", path);
+        System.out.println("生成编辑页面成功!");
+    }
+
+    @Override
+    protected void generatePageAddHtml() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPageAddPathTemplate(),
+                super.getContextConfig().getBizEnName(), super.getContextConfig().getBizEnName());
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/page_add.html.btl", path);
+        System.out.println("生成添加页面成功!");
+    }
+
+    @Override
+    protected void generatePageInfoJs() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPageInfoJsPathTemplate(),
+                super.getContextConfig().getBizEnName(), super.getContextConfig().getBizEnName());
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/page_info.js.btl", path);
+        System.out.println("生成页面详情js成功!");
+    }
+
+    @Override
+    protected void generatePageJs() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPageJsPathTemplate(),
+                super.getContextConfig().getBizEnName(), super.getContextConfig().getBizEnName());
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/page.js.btl", path);
+        System.out.println("生成页面js成功!");
+    }
+
+    @Override
+    protected void generatePageHtml() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPagePathTemplate(),
+                super.getContextConfig().getBizEnName(), super.getContextConfig().getBizEnName());
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/page.html.btl", path);
+        System.out.println("生成页面成功!");
+    }
+
+    @Override
+    protected void generateController() {
+        String controllerPath = ToolUtil.format(super.getContextConfig().getProjectPath() + super.getControllerConfig().getControllerPathTemplate(),
+                ToolUtil.firstLetterToUpper(super.getContextConfig().getBizEnName()));
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/Controller.java.btl", controllerPath);
+        System.out.println("生成控制器成功!");
+    }
+
+    @Override
+    protected void generateSqls() {
+        String path = ToolUtil.format(super.getContextConfig().getProjectPath() + super.sqlConfig.getSqlPathTemplate(),
+                ToolUtil.firstLetterToUpper(super.getContextConfig().getBizEnName()));
+        generateFile(super.getContextConfig().getTemplatePrefixPath() + "/menu_sql.sql.btl", path);
+        System.out.println("生成sql成功!");
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java
new file mode 100644
index 0000000..ef2512e
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java
@@ -0,0 +1,115 @@
+package com.stylefeng.guns.generator.engine.base;
+
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.stylefeng.guns.generator.engine.config.*;
+
+/**
+ * 模板生成父类
+ *
+ * @author fengshuonan
+ * @date 2017-05-08 20:17
+ */
+public class AbstractTemplateEngine {
+
+    protected ContextConfig contextConfig;                //全局配置
+    protected ControllerConfig controllerConfig;          //控制器的配置
+    protected PageConfig pageConfig;                      //页面的控制器
+    protected DaoConfig daoConfig;                        //Dao配置
+    protected ServiceConfig serviceConfig;                //Service配置
+    protected SqlConfig sqlConfig;                        //sql配置
+    protected TableInfo tableInfo;                        //表的信息
+
+    public void initConfig() {
+        if (this.contextConfig == null) {
+            this.contextConfig = new ContextConfig();
+        }
+        if (this.controllerConfig == null) {
+            this.controllerConfig = new ControllerConfig();
+        }
+        if (this.pageConfig == null) {
+            this.pageConfig = new PageConfig();
+        }
+        if (this.daoConfig == null) {
+            this.daoConfig = new DaoConfig();
+        }
+        if (this.serviceConfig == null) {
+            this.serviceConfig = new ServiceConfig();
+        }
+        if (this.sqlConfig == null) {
+            this.sqlConfig = new SqlConfig();
+        }
+        this.contextConfig.init();
+
+        this.controllerConfig.setContextConfig(this.contextConfig);
+        this.controllerConfig.init();
+
+        this.serviceConfig.setContextConfig(this.contextConfig);
+        this.serviceConfig.init();
+
+        this.daoConfig.setContextConfig(this.contextConfig);
+        this.daoConfig.init();
+
+        this.pageConfig.setContextConfig(this.contextConfig);
+        this.pageConfig.init();
+
+        this.sqlConfig.setContextConfig(this.contextConfig);
+        this.sqlConfig.init();
+    }
+
+    public PageConfig getPageConfig() {
+        return pageConfig;
+    }
+
+    public void setPageConfig(PageConfig pageConfig) {
+        this.pageConfig = pageConfig;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+
+    public ControllerConfig getControllerConfig() {
+        return controllerConfig;
+    }
+
+    public void setControllerConfig(ControllerConfig controllerConfig) {
+        this.controllerConfig = controllerConfig;
+    }
+
+    public DaoConfig getDaoConfig() {
+        return daoConfig;
+    }
+
+    public void setDaoConfig(DaoConfig daoConfig) {
+        this.daoConfig = daoConfig;
+    }
+
+    public ServiceConfig getServiceConfig() {
+        return serviceConfig;
+    }
+
+    public void setServiceConfig(ServiceConfig serviceConfig) {
+        this.serviceConfig = serviceConfig;
+    }
+
+    public SqlConfig getSqlConfig() {
+        return sqlConfig;
+    }
+
+    public void setSqlConfig(SqlConfig sqlConfig) {
+        this.sqlConfig = sqlConfig;
+    }
+
+    public TableInfo getTableInfo() {
+        return tableInfo;
+    }
+
+    public void setTableInfo(TableInfo tableInfo) {
+        this.tableInfo = tableInfo;
+    }
+}
+
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java
new file mode 100644
index 0000000..4d3ab84
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java
@@ -0,0 +1,126 @@
+package com.stylefeng.guns.generator.engine.base;
+
+import com.stylefeng.guns.core.util.ToolUtil;
+import com.sun.javafx.PlatformUtil;
+import org.beetl.core.Configuration;
+import org.beetl.core.GroupTemplate;
+import org.beetl.core.Template;
+import org.beetl.core.resource.ClasspathResourceLoader;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * ADI项目模板生成 引擎
+ *
+ * @author fengshuonan
+ * @date 2017-05-07 22:15
+ */
+public abstract class GunsTemplateEngine extends AbstractTemplateEngine {
+
+    private GroupTemplate groupTemplate;
+
+    public GunsTemplateEngine() {
+        initBeetlEngine();
+    }
+
+    protected void initBeetlEngine() {
+        Properties properties = new Properties();
+        properties.put("RESOURCE.root", "");
+        properties.put("DELIMITER_STATEMENT_START", "<%");
+        properties.put("DELIMITER_STATEMENT_END", "%>");
+        properties.put("HTML_TAG_FLAG", "##");
+        Configuration cfg = null;
+        try {
+            cfg = new Configuration(properties);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader();
+        groupTemplate = new GroupTemplate(resourceLoader, cfg);
+        groupTemplate.registerFunctionPackage("tool", new ToolUtil());
+    }
+
+    protected void configTemplate(Template template) {
+        template.binding("controller", super.controllerConfig);
+        template.binding("context", super.contextConfig);
+        template.binding("dao", super.daoConfig);
+        template.binding("service", super.serviceConfig);
+        template.binding("sqls", super.sqlConfig);
+        template.binding("table", super.tableInfo);
+    }
+
+    protected void generateFile(String template, String filePath) {
+        Template pageTemplate = groupTemplate.getTemplate(template);
+        configTemplate(pageTemplate);
+        if (PlatformUtil.isWindows()) {
+            filePath = filePath.replaceAll("/+|\\\\+", "\\\\");
+        } else {
+            filePath = filePath.replaceAll("/+|\\\\+", "/");
+        }
+        File file = new File(filePath);
+        File parentFile = file.getParentFile();
+        if (!parentFile.exists()) {
+            parentFile.mkdirs();
+        }
+        FileOutputStream fileOutputStream = null;
+        try {
+            fileOutputStream = new FileOutputStream(file);
+            pageTemplate.renderTo(fileOutputStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                fileOutputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public void start() {
+        //配置之间的相互依赖
+        super.initConfig();
+
+        //生成模板
+        if (super.contextConfig.getControllerSwitch()) {
+            generateController();
+        }
+        if (super.contextConfig.getIndexPageSwitch()) {
+            generatePageHtml();
+        }
+        if (super.contextConfig.getAddPageSwitch()) {
+            generatePageAddHtml();
+        }
+        if (super.contextConfig.getEditPageSwitch()) {
+            generatePageEditHtml();
+        }
+        if (super.contextConfig.getJsSwitch()) {
+            generatePageJs();
+        }
+        if (super.contextConfig.getInfoJsSwitch()) {
+            generatePageInfoJs();
+        }
+        if (super.contextConfig.getSqlSwitch()) {
+            generateSqls();
+        }
+    }
+
+    protected abstract void generatePageEditHtml();
+
+    protected abstract void generatePageAddHtml();
+
+    protected abstract void generatePageInfoJs();
+
+    protected abstract void generatePageJs();
+
+    protected abstract void generatePageHtml();
+
+    protected abstract void generateController();
+
+    protected abstract void generateSqls();
+
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java
new file mode 100644
index 0000000..d8403d8
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java
@@ -0,0 +1,214 @@
+package com.stylefeng.guns.generator.engine.config;
+
+
+import com.stylefeng.guns.core.util.ToolUtil;
+
+/**
+ * 全局配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-08 20:21
+ */
+public class ContextConfig {
+
+    private String templatePrefixPath = "gunsTemplate/advanced";
+    private String projectPath = "D:\\ideaSpace\\guns";//模板输出的项目目录
+    private String bizChName;   //业务名称
+    private String bizEnName;   //业务英文名称
+    private String bizEnBigName;//业务英文名称(大写)
+    private String moduleName = "system";  //模块名称
+
+    private String proPackage = "com.stylefeng.guns.admin";
+    private String coreBasePackage = "com.stylefeng.guns.core";
+    private String modelPackageName = "com.stylefeng.guns.modular.system.model";        //model的包名
+    private String modelMapperPackageName = "com.stylefeng.guns.modular.system.dao";    //model的dao
+    private String entityName;              //实体的名称
+
+    private Boolean controllerSwitch = true;    //是否生成控制器代码开关
+    private Boolean indexPageSwitch = true;     //主页
+    private Boolean addPageSwitch = true;       //添加页面
+    private Boolean editPageSwitch = true;      //编辑页面
+    private Boolean jsSwitch = true;            //js
+    private Boolean infoJsSwitch = true;        //详情页面js
+    private Boolean daoSwitch = true;           //dao
+    private Boolean serviceSwitch = true;       //service
+    private Boolean entitySwitch = true;        //生成实体的开关
+    private Boolean sqlSwitch = true;           //生成sql的开关
+
+    public void init() {
+        if (entityName == null) {
+            entityName = bizEnBigName;
+        }
+        modelPackageName = proPackage + "." + "modular.system.model";
+        modelMapperPackageName = proPackage + "." + "modular.system.dao";
+    }
+
+    public String getBizEnBigName() {
+        return bizEnBigName;
+    }
+
+    public void setBizEnBigName(String bizEnBigName) {
+        this.bizEnBigName = bizEnBigName;
+    }
+
+    public String getBizChName() {
+        return bizChName;
+    }
+
+    public void setBizChName(String bizChName) {
+        this.bizChName = bizChName;
+    }
+
+    public String getBizEnName() {
+        return bizEnName;
+    }
+
+    public void setBizEnName(String bizEnName) {
+        this.bizEnName = bizEnName;
+        this.bizEnBigName = ToolUtil.firstLetterToUpper(this.bizEnName);
+    }
+
+    public String getProjectPath() {
+        return projectPath;
+    }
+
+    public void setProjectPath(String projectPath) {
+        this.projectPath = projectPath;
+    }
+
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    public Boolean getControllerSwitch() {
+        return controllerSwitch;
+    }
+
+    public void setControllerSwitch(Boolean controllerSwitch) {
+        this.controllerSwitch = controllerSwitch;
+    }
+
+    public Boolean getIndexPageSwitch() {
+        return indexPageSwitch;
+    }
+
+    public void setIndexPageSwitch(Boolean indexPageSwitch) {
+        this.indexPageSwitch = indexPageSwitch;
+    }
+
+    public Boolean getAddPageSwitch() {
+        return addPageSwitch;
+    }
+
+    public void setAddPageSwitch(Boolean addPageSwitch) {
+        this.addPageSwitch = addPageSwitch;
+    }
+
+    public Boolean getEditPageSwitch() {
+        return editPageSwitch;
+    }
+
+    public void setEditPageSwitch(Boolean editPageSwitch) {
+        this.editPageSwitch = editPageSwitch;
+    }
+
+    public Boolean getJsSwitch() {
+        return jsSwitch;
+    }
+
+    public void setJsSwitch(Boolean jsSwitch) {
+        this.jsSwitch = jsSwitch;
+    }
+
+    public Boolean getInfoJsSwitch() {
+        return infoJsSwitch;
+    }
+
+    public void setInfoJsSwitch(Boolean infoJsSwitch) {
+        this.infoJsSwitch = infoJsSwitch;
+    }
+
+    public Boolean getDaoSwitch() {
+        return daoSwitch;
+    }
+
+    public void setDaoSwitch(Boolean daoSwitch) {
+        this.daoSwitch = daoSwitch;
+    }
+
+    public Boolean getServiceSwitch() {
+        return serviceSwitch;
+    }
+
+    public void setServiceSwitch(Boolean serviceSwitch) {
+        this.serviceSwitch = serviceSwitch;
+    }
+
+    public String getTemplatePrefixPath() {
+        return templatePrefixPath;
+    }
+
+    public void setTemplatePrefixPath(String templatePrefixPath) {
+        this.templatePrefixPath = templatePrefixPath;
+    }
+
+    public String getModelPackageName() {
+        return modelPackageName;
+    }
+
+    public void setModelPackageName(String modelPackageName) {
+        this.modelPackageName = modelPackageName;
+    }
+
+    public String getEntityName() {
+        return entityName;
+    }
+
+    public void setEntityName(String entityName) {
+        this.entityName = entityName;
+    }
+
+    public String getModelMapperPackageName() {
+        return modelMapperPackageName;
+    }
+
+    public void setModelMapperPackageName(String modelMapperPackageName) {
+        this.modelMapperPackageName = modelMapperPackageName;
+    }
+
+    public Boolean getEntitySwitch() {
+        return entitySwitch;
+    }
+
+    public void setEntitySwitch(Boolean entitySwitch) {
+        this.entitySwitch = entitySwitch;
+    }
+
+    public Boolean getSqlSwitch() {
+        return sqlSwitch;
+    }
+
+    public void setSqlSwitch(Boolean sqlSwitch) {
+        this.sqlSwitch = sqlSwitch;
+    }
+
+    public String getProPackage() {
+        return proPackage;
+    }
+
+    public void setProPackage(String proPackage) {
+        this.proPackage = proPackage;
+    }
+
+    public String getCoreBasePackage() {
+        return coreBasePackage;
+    }
+
+    public void setCoreBasePackage(String coreBasePackage) {
+        this.coreBasePackage = coreBasePackage;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java
new file mode 100644
index 0000000..8775b3c
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java
@@ -0,0 +1,70 @@
+package com.stylefeng.guns.generator.engine.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 控制器模板生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-07 22:12
+ */
+public class ControllerConfig {
+
+    private ContextConfig contextConfig;
+
+    private String controllerPathTemplate;
+    private String packageName;//包名称
+    private List<String> imports;//所引入的包
+
+    public void init() {
+        ArrayList<String> imports = new ArrayList<>();
+        imports.add(contextConfig.getCoreBasePackage() + ".base.controller.BaseController");
+        imports.add("org.springframework.stereotype.Controller");
+        imports.add("org.springframework.web.bind.annotation.RequestMapping");
+        imports.add("org.springframework.web.bind.annotation.ResponseBody");
+        imports.add("org.springframework.ui.Model");
+        imports.add("org.springframework.web.bind.annotation.PathVariable");
+        imports.add("org.springframework.beans.factory.annotation.Autowired");
+        imports.add(contextConfig.getProPackage() + ".core.log.LogObjectHolder");
+        imports.add("org.springframework.web.bind.annotation.RequestParam");
+        imports.add(contextConfig.getModelPackageName() + "." + contextConfig.getEntityName());
+        imports.add(contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".service" + ".I" + contextConfig.getEntityName() + "Service");
+        this.imports = imports;
+        this.packageName = contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".controller";
+        this.controllerPathTemplate = "\\src\\main\\java\\"+contextConfig.getProPackage().replaceAll("\\.","\\\\")+"\\modular\\" + contextConfig.getModuleName() + "\\controller\\{}Controller.java";
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public List<String> getImports() {
+        return imports;
+    }
+
+    public void setImports(List<String> imports) {
+        this.imports = imports;
+    }
+
+    public String getControllerPathTemplate() {
+        return controllerPathTemplate;
+    }
+
+    public void setControllerPathTemplate(String controllerPathTemplate) {
+        this.controllerPathTemplate = controllerPathTemplate;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java
new file mode 100644
index 0000000..00e3092
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java
@@ -0,0 +1,55 @@
+package com.stylefeng.guns.generator.engine.config;
+
+/**
+ * Dao模板生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-07 22:12
+ */
+public class DaoConfig {
+
+    private ContextConfig contextConfig;
+
+    private String daoPathTemplate;
+    private String xmlPathTemplate;
+
+    private String packageName;
+
+    public void init() {
+        this.daoPathTemplate = "\\src\\main\\java\\" + contextConfig.getProPackage().replaceAll("\\.", "\\\\") + "\\modular\\" + contextConfig.getModuleName() + "\\dao\\{}Dao.java";
+        this.xmlPathTemplate = "\\src\\main\\java\\" + contextConfig.getProPackage().replaceAll("\\.", "\\\\") + "\\modular\\" + contextConfig.getModuleName() + "\\dao\\mapping\\{}Dao.xml";
+        this.packageName = contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".dao";
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getDaoPathTemplate() {
+        return daoPathTemplate;
+    }
+
+    public void setDaoPathTemplate(String daoPathTemplate) {
+        this.daoPathTemplate = daoPathTemplate;
+    }
+
+    public String getXmlPathTemplate() {
+        return xmlPathTemplate;
+    }
+
+    public void setXmlPathTemplate(String xmlPathTemplate) {
+        this.xmlPathTemplate = xmlPathTemplate;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java
new file mode 100644
index 0000000..2770128
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java
@@ -0,0 +1,203 @@
+package com.stylefeng.guns.generator.engine.config;
+
+import com.baomidou.mybatisplus.activerecord.Model;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.enums.IdType;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 菜单表
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2017-07-11
+ */
+public class Menu extends Model<Menu> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+    /**
+     * 菜单编号
+     */
+    private String code;
+    /**
+     * 菜单父编号
+     */
+    private String pcode;
+    /**
+     * 当前菜单的所有父菜单编号
+     */
+    private String pcodes;
+    /**
+     * 菜单名称
+     */
+    private String name;
+    /**
+     * 菜单图标
+     */
+    private String icon;
+    /**
+     * url地址
+     */
+    private String url;
+    /**
+     * 菜单排序号
+     */
+    private Integer num;
+    /**
+     * 菜单层级
+     */
+    private Integer levels;
+    /**
+     * 是否是菜单(1:是  0:不是)
+     */
+    private Integer ismenu;
+    /**
+     * 备注
+     */
+    private String tips;
+    /**
+     * 菜单状态 :  1:启用   0:不启用
+     */
+    private Integer status;
+    /**
+     * 是否打开:    1:打开   0:不打开
+     */
+    private Integer isopen;
+
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getPcode() {
+        return pcode;
+    }
+
+    public void setPcode(String pcode) {
+        this.pcode = pcode;
+    }
+
+    public String getPcodes() {
+        return pcodes;
+    }
+
+    public void setPcodes(String pcodes) {
+        this.pcodes = pcodes;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getIcon() {
+        return icon;
+    }
+
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public Integer getNum() {
+        return num;
+    }
+
+    public void setNum(Integer num) {
+        this.num = num;
+    }
+
+    public Integer getLevels() {
+        return levels;
+    }
+
+    public void setLevels(Integer levels) {
+        this.levels = levels;
+    }
+
+    public Integer getIsmenu() {
+        return ismenu;
+    }
+
+    public void setIsmenu(Integer ismenu) {
+        this.ismenu = ismenu;
+    }
+
+    public String getTips() {
+        return tips;
+    }
+
+    public void setTips(String tips) {
+        this.tips = tips;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public Integer getIsopen() {
+        return isopen;
+    }
+
+    public void setIsopen(Integer isopen) {
+        this.isopen = isopen;
+    }
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    @Override
+    public String toString() {
+        return "Menu{" +
+                "id=" + id +
+                ", code=" + code +
+                ", pcode=" + pcode +
+                ", pcodes=" + pcodes +
+                ", name=" + name +
+                ", icon=" + icon +
+                ", url=" + url +
+                ", num=" + num +
+                ", levels=" + levels +
+                ", ismenu=" + ismenu +
+                ", tips=" + tips +
+                ", status=" + status +
+                ", isopen=" + isopen +
+                "}";
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java
new file mode 100644
index 0000000..a3324ea
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java
@@ -0,0 +1,74 @@
+package com.stylefeng.guns.generator.engine.config;
+
+/**
+ * 页面 模板生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-07 22:12
+ */
+public class PageConfig {
+
+    private ContextConfig contextConfig;
+
+    private String pagePathTemplate;
+    private String pageAddPathTemplate;
+    private String pageEditPathTemplate;
+    private String pageJsPathTemplate;
+    private String pageInfoJsPathTemplate;
+
+    public void init() {
+        pagePathTemplate = "\\src\\main\\webapp\\WEB-INF\\view\\" + contextConfig.getModuleName() + "\\{}\\{}.html";
+        pageAddPathTemplate = "\\src\\main\\webapp\\WEB-INF\\view\\" + contextConfig.getModuleName() + "\\{}\\{}_add.html";
+        pageEditPathTemplate = "\\src\\main\\webapp\\WEB-INF\\view\\" + contextConfig.getModuleName() + "\\{}\\{}_edit.html";
+        pageJsPathTemplate = "\\src\\main\\webapp\\static\\modular\\" + contextConfig.getModuleName() + "\\{}\\{}.js";
+        pageInfoJsPathTemplate = "\\src\\main\\webapp\\static\\modular\\" + contextConfig.getModuleName() + "\\{}\\{}_info.js";
+    }
+
+    public String getPagePathTemplate() {
+        return pagePathTemplate;
+    }
+
+    public void setPagePathTemplate(String pagePathTemplate) {
+        this.pagePathTemplate = pagePathTemplate;
+    }
+
+    public String getPageJsPathTemplate() {
+        return pageJsPathTemplate;
+    }
+
+    public void setPageJsPathTemplate(String pageJsPathTemplate) {
+        this.pageJsPathTemplate = pageJsPathTemplate;
+    }
+
+    public String getPageAddPathTemplate() {
+        return pageAddPathTemplate;
+    }
+
+    public void setPageAddPathTemplate(String pageAddPathTemplate) {
+        this.pageAddPathTemplate = pageAddPathTemplate;
+    }
+
+    public String getPageEditPathTemplate() {
+        return pageEditPathTemplate;
+    }
+
+    public void setPageEditPathTemplate(String pageEditPathTemplate) {
+        this.pageEditPathTemplate = pageEditPathTemplate;
+    }
+
+    public String getPageInfoJsPathTemplate() {
+        return pageInfoJsPathTemplate;
+    }
+
+    public void setPageInfoJsPathTemplate(String pageInfoJsPathTemplate) {
+        this.pageInfoJsPathTemplate = pageInfoJsPathTemplate;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java
new file mode 100644
index 0000000..e6cc865
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java
@@ -0,0 +1,91 @@
+package com.stylefeng.guns.generator.engine.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service模板生成的配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-07 22:12
+ */
+public class ServiceConfig {
+
+    private ContextConfig contextConfig;
+
+    private String servicePathTemplate;
+    private String serviceImplPathTemplate;
+
+    private String packageName;
+
+    private List<String> serviceInterfaceImports;
+    private List<String> serviceImplImports;
+
+    public void init() {
+        ArrayList<String> imports = new ArrayList<>();
+        imports.add("org.springframework.stereotype.Service");
+        imports.add("com.baomidou.mybatisplus.service.impl.ServiceImpl");
+        imports.add(contextConfig.getModelPackageName() + "." + contextConfig.getEntityName());
+        imports.add(contextConfig.getModelMapperPackageName() + "." + contextConfig.getEntityName() + "Mapper");
+        imports.add(contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".service.I" + contextConfig.getBizEnBigName() + "Service");
+        this.serviceImplImports = imports;
+
+        ArrayList<String> interfaceImports = new ArrayList<>();
+        interfaceImports.add("com.baomidou.mybatisplus.service.IService");
+        interfaceImports.add(contextConfig.getModelPackageName() + "." + contextConfig.getEntityName());
+        this.serviceInterfaceImports = interfaceImports;
+
+        this.servicePathTemplate = "\\src\\main\\java\\" + contextConfig.getProPackage().replaceAll("\\.", "\\\\") + "\\modular\\" + contextConfig.getModuleName() + "\\service\\I{}Service.java";
+        this.serviceImplPathTemplate = "\\src\\main\\java\\" + contextConfig.getProPackage().replaceAll("\\.", "\\\\") + "\\modular\\" + contextConfig.getModuleName() + "\\service\\impl\\{}ServiceImpl.java";
+        this.packageName = contextConfig.getProPackage() + ".modular." + contextConfig.getModuleName() + ".service";
+    }
+
+
+    public String getServicePathTemplate() {
+        return servicePathTemplate;
+    }
+
+    public void setServicePathTemplate(String servicePathTemplate) {
+        this.servicePathTemplate = servicePathTemplate;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getServiceImplPathTemplate() {
+        return serviceImplPathTemplate;
+    }
+
+    public void setServiceImplPathTemplate(String serviceImplPathTemplate) {
+        this.serviceImplPathTemplate = serviceImplPathTemplate;
+    }
+
+    public List<String> getServiceImplImports() {
+        return serviceImplImports;
+    }
+
+    public void setServiceImplImports(List<String> serviceImplImports) {
+        this.serviceImplImports = serviceImplImports;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+
+    public List<String> getServiceInterfaceImports() {
+        return serviceInterfaceImports;
+    }
+
+    public void setServiceInterfaceImports(List<String> serviceInterfaceImports) {
+        this.serviceInterfaceImports = serviceInterfaceImports;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java
new file mode 100644
index 0000000..ec64b55
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java
@@ -0,0 +1,194 @@
+package com.stylefeng.guns.generator.engine.config;
+
+import com.baomidou.mybatisplus.toolkit.IdWorker;
+import com.stylefeng.guns.core.constant.IsMenu;
+import com.stylefeng.guns.core.util.ToolUtil;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 全局配置
+ *
+ * @author fengshuonan
+ * @date 2017-05-08 20:21
+ */
+public class SqlConfig {
+
+    private String sqlPathTemplate;
+
+    private ContextConfig contextConfig;
+
+    private Connection connection;
+
+    private String parentMenuName;
+
+    private List<Menu> menus = new ArrayList<>(6);
+
+    public void init() {
+
+        this.sqlPathTemplate = "\\src\\main\\java\\{}.sql";
+
+        if (parentMenuName == null) {
+            return;
+        }
+
+        //根据父菜单查询数据库中的pcode和pcodes
+        String[] pcodeAndPcodes = getPcodeAndPcodes();
+        if (pcodeAndPcodes == null) {
+            System.err.println("父级菜单名称输入有误!!!!");
+            return;
+        }
+
+        //业务菜单
+        Menu menu = new Menu();
+        menu.setId(IdWorker.getId());
+        menu.setCode(contextConfig.getBizEnName());
+        menu.setPcode(pcodeAndPcodes[0]);
+        menu.setPcodes(pcodeAndPcodes[1] + "[" + pcodeAndPcodes[0] + "],");
+        menu.setName(contextConfig.getBizChName());
+        menu.setIcon("");
+        menu.setUrl("/" + contextConfig.getBizEnName());
+        menu.setNum(99);
+
+        if (parentMenuName.equals("顶级")) {
+            menu.setLevels(1);
+        } else {
+            menu.setLevels(2);
+        }
+        menu.setIsmenu(IsMenu.YES.getCode());
+        menu.setStatus(1);
+        menu.setIsopen(0);
+        menus.add(menu);
+
+        //列表
+        Menu list = createSubMenu(menu);
+        list.setCode(contextConfig.getBizEnName() + "_list");
+        list.setName(contextConfig.getBizChName() + "列表");
+        list.setUrl("/" + contextConfig.getBizEnName() + "/list");
+        menus.add(list);
+
+        //添加
+        Menu add = createSubMenu(menu);
+        add.setCode(contextConfig.getBizEnName() + "_add");
+        add.setName(contextConfig.getBizChName() + "添加");
+        add.setUrl("/" + contextConfig.getBizEnName() + "/add");
+        menus.add(add);
+
+        //更新
+        Menu update = createSubMenu(menu);
+        update.setCode(contextConfig.getBizEnName() + "_update");
+        update.setName(contextConfig.getBizChName() + "更新");
+        update.setUrl("/" + contextConfig.getBizEnName() + "/update");
+        menus.add(update);
+
+        //删除
+        Menu delete = createSubMenu(menu);
+        delete.setCode(contextConfig.getBizEnName() + "_delete");
+        delete.setName(contextConfig.getBizChName() + "删除");
+        delete.setUrl("/" + contextConfig.getBizEnName() + "/delete");
+        menus.add(delete);
+
+        //详情
+        Menu detail = createSubMenu(menu);
+        detail.setCode(contextConfig.getBizEnName() + "_detail");
+        detail.setName(contextConfig.getBizChName() + "详情");
+        detail.setUrl("/" + contextConfig.getBizEnName() + "/detail");
+        menus.add(detail);
+    }
+
+    private Menu createSubMenu(Menu parentMenu) {
+        Menu menu = new Menu();
+        menu.setId(IdWorker.getId());
+        menu.setPcode(parentMenu.getCode());
+        menu.setPcodes(parentMenu.getPcodes() + "[" + parentMenu.getCode() + "],");
+        menu.setIcon("");
+        menu.setNum(99);
+        menu.setLevels(parentMenu.getLevels() + 1);
+        menu.setIsmenu(IsMenu.NO.getCode());
+        menu.setStatus(1);
+        menu.setIsopen(0);
+        return menu;
+    }
+
+    public String[] getPcodeAndPcodes() {
+        if (parentMenuName.equals("顶级")) {
+            return new String[]{"0", ""};
+        }
+        PreparedStatement preparedStatement = null;
+        try {
+            preparedStatement = connection.prepareStatement("select * from sys_menu where name like ?");
+            preparedStatement.setString(1, "%" + parentMenuName + "%");
+            ResultSet results = preparedStatement.executeQuery();
+            while (results.next()) {
+                String pcode = results.getString("code");
+                String pcodes = results.getString("pcodes");
+                if (ToolUtil.isNotEmpty(pcode) && ToolUtil.isNotEmpty(pcodes)) {
+                    String[] strings = {pcode, pcodes};
+                    return strings;
+                } else {
+                    return null;
+                }
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        } finally {
+            // 释放资源
+            try {
+                if (preparedStatement != null) {
+                    preparedStatement.close();
+                }
+                if (connection != null) {
+                    connection.close();
+                }
+            } catch (SQLException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    public ContextConfig getContextConfig() {
+        return contextConfig;
+    }
+
+    public void setContextConfig(ContextConfig contextConfig) {
+        this.contextConfig = contextConfig;
+    }
+
+    public String getParentMenuName() {
+        return parentMenuName;
+    }
+
+    public void setParentMenuName(String parentMenuName) {
+        this.parentMenuName = parentMenuName;
+    }
+
+    public Connection getConnection() {
+        return connection;
+    }
+
+    public void setConnection(Connection connection) {
+        this.connection = connection;
+    }
+
+    public String getSqlPathTemplate() {
+        return sqlPathTemplate;
+    }
+
+    public void setSqlPathTemplate(String sqlPathTemplate) {
+        this.sqlPathTemplate = sqlPathTemplate;
+    }
+
+    public List<Menu> getMenus() {
+        return menus;
+    }
+
+    public void setMenus(List<Menu> menus) {
+        this.menus = menus;
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl
new file mode 100644
index 0000000..a187a36
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl
@@ -0,0 +1,96 @@
+package ${controller.packageName};
+
+<% for(import in controller.imports!){ %>
+import ${import};
+<% } %>
+
+/**
+ * ${context.bizChName}控制器
+ *
+ * @author fengshuonan
+ * @Date ${tool.currentTime()}
+ */
+@Controller
+@RequestMapping("/${context.bizEnName}")
+public class ${context.bizEnBigName}Controller extends BaseController {
+
+    private String PREFIX = "/${context.moduleName}/${context.bizEnName}/";
+
+    @Autowired
+    private I${context.entityName}Service ${context.bizEnName}Service;
+
+    /**
+     * 跳转到${context.bizChName}首页
+     */
+    @RequestMapping("")
+    public String index() {
+        return PREFIX + "${context.bizEnName}.html";
+    }
+
+    /**
+     * 跳转到添加${context.bizChName}
+     */
+    @RequestMapping("/${context.bizEnName}_add")
+    public String ${context.bizEnName}Add() {
+        return PREFIX + "${context.bizEnName}_add.html";
+    }
+
+    /**
+     * 跳转到修改${context.bizChName}
+     */
+    @RequestMapping("/${context.bizEnName}_update/{${context.bizEnName}Id}")
+    public String ${context.bizEnName}Update(@PathVariable Integer ${context.bizEnName}Id, Model model) {
+        ${context.entityName} ${context.bizEnName} = ${context.bizEnName}Service.selectById(${context.bizEnName}Id);
+        model.addAttribute("item",${context.bizEnName});
+        LogObjectHolder.me().set(${context.bizEnName});
+        return PREFIX + "${context.bizEnName}_edit.html";
+    }
+
+    /**
+     * 获取${context.bizChName}列表
+     */
+    @RequestMapping(value = "/list")
+    @ResponseBody
+    public Object list(String condition) {
+        return ${context.bizEnName}Service.selectList(null);
+    }
+
+    /**
+     * 新增${context.bizChName}
+     */
+    @RequestMapping(value = "/add")
+    @ResponseBody
+    public Object add(${context.entityName} ${context.bizEnName}) {
+        ${context.bizEnName}Service.insert(${context.bizEnName});
+        return SUCCESS_TIP;
+    }
+
+    /**
+     * 删除${context.bizChName}
+     */
+    @RequestMapping(value = "/delete")
+    @ResponseBody
+    public Object delete(@RequestParam Integer ${context.bizEnName}Id) {
+        ${context.bizEnName}Service.deleteById(${context.bizEnName}Id);
+        return SUCCESS_TIP;
+    }
+
+    /**
+     * 修改${context.bizChName}
+     */
+    @RequestMapping(value = "/update")
+    @ResponseBody
+    public Object update(${context.entityName} ${context.bizEnName}) {
+        ${context.bizEnName}Service.updateById(${context.bizEnName});
+        return SUCCESS_TIP;
+    }
+
+    /**
+     * ${context.bizChName}详情
+     */
+    @RequestMapping(value = "/detail/{${context.bizEnName}Id}")
+    @ResponseBody
+    public Object detail(@PathVariable("${context.bizEnName}Id") Integer ${context.bizEnName}Id) {
+        return ${context.bizEnName}Service.selectById(${context.bizEnName}Id);
+    }
+}
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl
new file mode 100644
index 0000000..07b094c
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl
@@ -0,0 +1,3 @@
+<% for(menu in sqls.menus!){ %>
+INSERT INTO `guns`.`sys_menu` (`id`, `code`, `pcode`, `pcodes`, `name`, `icon`, `url`, `num`, `levels`, `ismenu`, `tips`, `status`, `isopen`) VALUES ('${menu.id}', '${menu.code}', '${menu.pcode}', '${menu.pcodes}', '${menu.name}', '${menu.icon}', '${menu.url}', '${menu.num}', '${menu.levels}', '${menu.ismenu}', NULL, '${menu.status}', '${menu.isopen}');
+<% } %>
\ No newline at end of file
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl
new file mode 100644
index 0000000..b21f29e
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl
@@ -0,0 +1,38 @@
+@layout("/common/_container.html"){
+<div class="row">
+    <div class="col-sm-12">
+        <div class="ibox float-e-margins">
+            <div class="ibox-title">
+                <h5>${context.bizChName}管理</h5>
+            </div>
+            <div class="ibox-content">
+                <div class="row row-lg">
+                    <div class="col-sm-12">
+                        <div class="row">
+                            <div class="col-sm-3">
+                                <#NameCon id="condition" name="名称" />
+                            </div>
+                            <div class="col-sm-3">
+                                <#button name="搜索" icon="fa-search" clickFun="${context.bizEnBigName}.search()"/>
+                            </div>
+                        </div>
+                        <div class="hidden-xs" id="${context.bizEnBigName}TableToolbar" role="group">
+                            @if(shiro.hasPermission("/${context.bizEnName}/add")){
+                                <#button name="添加" icon="fa-plus" clickFun="${context.bizEnBigName}.openAdd${context.bizEnBigName}()"/>
+                            @}
+                            @if(shiro.hasPermission("/${context.bizEnName}/update")){
+                                <#button name="修改" icon="fa-edit" clickFun="${context.bizEnBigName}.open${context.bizEnBigName}Detail()" space="true"/>
+                            @}
+                            @if(shiro.hasPermission("/${context.bizEnName}/delete")){
+                                <#button name="删除" icon="fa-remove" clickFun="${context.bizEnBigName}.delete()" space="true"/>
+                            @}
+                        </div>
+                        <#table id="${context.bizEnBigName}Table"/>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script src="\${ctxPath}/static/modular/${context.moduleName}/${context.bizEnName}/${context.bizEnName}.js"></script>
+@}
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl
new file mode 100644
index 0000000..71c6477
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl
@@ -0,0 +1,102 @@
+/**
+ * ${context.bizChName}管理初始化
+ */
+var ${context.bizEnBigName} = {
+    id: "${context.bizEnBigName}Table",	//表格id
+    seItem: null,		//选中的条目
+    table: null,
+    layerIndex: -1
+};
+
+/**
+ * 初始化表格的列
+ */
+${context.bizEnBigName}.initColumn = function () {
+    return [
+        {field: 'selectItem', radio: true},
+        <% for(item in table.fields!){ %>
+        <% if(itemLP.last != true){ %>
+            {title: '${item.comment}', field: '${item.propertyName}', visible: true, align: 'center', valign: 'middle'},
+        <% }else{ %>
+            {title: '${item.comment}', field: '${item.propertyName}', visible: true, align: 'center', valign: 'middle'}
+        <% }} %>
+    ];
+};
+
+/**
+ * 检查是否选中
+ */
+${context.bizEnBigName}.check = function () {
+    var selected = $('#' + this.id).bootstrapTable('getSelections');
+    if(selected.length == 0){
+        Feng.info("请先选中表格中的某一记录!");
+        return false;
+    }else{
+        ${context.bizEnBigName}.seItem = selected[0];
+        return true;
+    }
+};
+
+/**
+ * 点击添加${context.bizChName}
+ */
+${context.bizEnBigName}.openAdd${context.bizEnBigName} = function () {
+    var index = layer.open({
+        type: 2,
+        title: '添加${context.bizChName}',
+        area: ['800px', '420px'], //宽高
+        fix: false, //不固定
+        maxmin: true,
+        content: Feng.ctxPath + '/${context.bizEnName}/${context.bizEnName}_add'
+    });
+    this.layerIndex = index;
+};
+
+/**
+ * 打开查看${context.bizChName}详情
+ */
+${context.bizEnBigName}.open${context.bizEnBigName}Detail = function () {
+    if (this.check()) {
+        var index = layer.open({
+            type: 2,
+            title: '${context.bizChName}详情',
+            area: ['800px', '420px'], //宽高
+            fix: false, //不固定
+            maxmin: true,
+            content: Feng.ctxPath + '/${context.bizEnName}/${context.bizEnName}_update/' + ${context.bizEnBigName}.seItem.id
+        });
+        this.layerIndex = index;
+    }
+};
+
+/**
+ * 删除${context.bizChName}
+ */
+${context.bizEnBigName}.delete = function () {
+    if (this.check()) {
+        var ajax = new $ax(Feng.ctxPath + "/${context.bizEnName}/delete", function (data) {
+            Feng.success("删除成功!");
+            ${context.bizEnBigName}.table.refresh();
+        }, function (data) {
+            Feng.error("删除失败!" + data.responseJSON.message + "!");
+        });
+        ajax.set("${context.bizEnName}Id",this.seItem.id);
+        ajax.start();
+    }
+};
+
+/**
+ * 查询${context.bizChName}列表
+ */
+${context.bizEnBigName}.search = function () {
+    var queryData = {};
+    queryData['condition'] = $("#condition").val();
+    ${context.bizEnBigName}.table.refresh({query: queryData});
+};
+
+$(function () {
+    var defaultColunms = ${context.bizEnBigName}.initColumn();
+    var table = new BSTable(${context.bizEnBigName}.id, "/${context.bizEnName}/list", defaultColunms);
+    table.setPaginationType("client");
+    ${context.bizEnBigName}.table = table.init();
+});
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl
new file mode 100644
index 0000000..1b8d41e
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl
@@ -0,0 +1,41 @@
+@layout("/common/_container.html"){
+<div class="ibox float-e-margins">
+    <div class="ibox-content">
+        <div class="form-horizontal">
+
+            <div class="row">
+                <div class="col-sm-6 b-r">
+                    <% var leftSize = tool.toInt((table.fields.~size + 1) / 2); %>
+                    <% var rightSize = tool.toInt(table.fields.~size - leftSize); %>
+                    <% for(var i=0;i<leftSize;i++){ %>
+                        <% if(i != (leftSize-1) ){ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" underline="true"/>
+                        <% }else{ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}"/>
+                        <% } %>
+                    <% } %>
+                </div>
+
+                <div class="col-sm-6">
+                    <% for(var i=leftSize;i<table.fields.~size;i++){ %>
+                        <% if(i != (rightSize-1) ){ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" underline="true"/>
+                        <% }else{ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}"/>
+                        <% } %>
+                    <% } %>
+                </div>
+            </div>
+
+            <div class="row btn-group-m-t">
+                <div class="col-sm-10">
+                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="${context.bizEnBigName}InfoDlg.addSubmit()"/>
+                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="${context.bizEnBigName}InfoDlg.close()"/>
+                </div>
+            </div>
+        </div>
+
+    </div>
+</div>
+<script src="\${ctxPath}/static/modular/${context.moduleName}/${context.bizEnName}/${context.bizEnName}_info.js"></script>
+@}
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl
new file mode 100644
index 0000000..7839f5b
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl
@@ -0,0 +1,41 @@
+@layout("/common/_container.html"){
+<div class="ibox float-e-margins">
+    <div class="ibox-content">
+        <div class="form-horizontal">
+
+            <div class="row">
+                <div class="col-sm-6 b-r">
+                    <% var leftSize = tool.toInt((table.fields.~size + 1) / 2); %>
+                    <% var rightSize = tool.toInt(table.fields.~size - leftSize); %>
+                    <% for(var i=0;i<leftSize;i++){ %>
+                        <% if(i != (leftSize-1) ){ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" value="\${item.${table.fields[i].propertyName}}" underline="true"/>
+                        <% }else{ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" value="\${item.${table.fields[i].propertyName}}" />
+                        <% } %>
+                    <% } %>
+                </div>
+
+                <div class="col-sm-6">
+                    <% for(var i=leftSize;i<table.fields.~size;i++){ %>
+                        <% if(i != (table.fields.~size-1) ){ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" value="\${item.${table.fields[i].propertyName}}" underline="true"/>
+                        <% }else{ %>
+                            <#input id="${table.fields[i].propertyName}" name="${table.fields[i].comment}" value="\${item.${table.fields[i].propertyName}}" />
+                        <% } %>
+                    <% } %>
+                </div>
+            </div>
+
+            <div class="row btn-group-m-t">
+                <div class="col-sm-10">
+                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="${context.bizEnBigName}InfoDlg.editSubmit()"/>
+                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="${context.bizEnBigName}InfoDlg.close()"/>
+                </div>
+            </div>
+        </div>
+
+    </div>
+</div>
+<script src="\${ctxPath}/static/modular/${context.moduleName}/${context.bizEnName}/${context.bizEnName}_info.js"></script>
+@}
diff --git a/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl
new file mode 100644
index 0000000..7430b88
--- /dev/null
+++ b/DriverOKTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl
@@ -0,0 +1,98 @@
+/**
+ * 初始化${context.bizChName}详情对话框
+ */
+var ${context.bizEnBigName}InfoDlg = {
+    ${context.bizEnName}InfoData : {}
+};
+
+/**
+ * 清除数据
+ */
+${context.bizEnBigName}InfoDlg.clearData = function() {
+    this.${context.bizEnName}InfoData = {};
+}
+
+/**
+ * 设置对话框中的数据
+ *
+ * @param key 数据的名称
+ * @param val 数据的具体值
+ */
+${context.bizEnBigName}InfoDlg.set = function(key, val) {
+    this.${context.bizEnName}InfoData[key] = (typeof val == "undefined") ? $("#" + key).val() : val;
+    return this;
+}
+
+/**
+ * 设置对话框中的数据
+ *
+ * @param key 数据的名称
+ * @param val 数据的具体值
+ */
+${context.bizEnBigName}InfoDlg.get = function(key) {
+    return $("#" + key).val();
+}
+
+/**
+ * 关闭此对话框
+ */
+${context.bizEnBigName}InfoDlg.close = function() {
+    parent.layer.close(window.parent.${context.bizEnBigName}.layerIndex);
+}
+
+/**
+ * 收集数据
+ */
+${context.bizEnBigName}InfoDlg.collectData = function() {
+    this
+    <% for(item in table.fields!){ %>
+    <% if(itemLP.last != true){ %>
+    .set('${item.propertyName}')
+    <% }else{ %>
+    .set('${item.propertyName}');
+    <% }} %>
+}
+
+/**
+ * 提交添加
+ */
+${context.bizEnBigName}InfoDlg.addSubmit = function() {
+
+    this.clearData();
+    this.collectData();
+
+    //提交信息
+    var ajax = new $ax(Feng.ctxPath + "/${context.bizEnName}/add", function(data){
+        Feng.success("添加成功!");
+        window.parent.${context.bizEnBigName}.table.refresh();
+        ${context.bizEnBigName}InfoDlg.close();
+    },function(data){
+        Feng.error("添加失败!" + data.responseJSON.message + "!");
+    });
+    ajax.set(this.${context.bizEnName}InfoData);
+    ajax.start();
+}
+
+/**
+ * 提交修改
+ */
+${context.bizEnBigName}InfoDlg.editSubmit = function() {
+
+    this.clearData();
+    this.collectData();
+
+    //提交信息
+    var ajax = new $ax(Feng.ctxPath + "/${context.bizEnName}/update", function(data){
+        Feng.success("修改成功!");
+        window.parent.${context.bizEnBigName}.table.refresh();
+        ${context.bizEnBigName}InfoDlg.close();
+    },function(data){
+        Feng.error("修改失败!" + data.responseJSON.message + "!");
+    });
+    ajax.set(this.${context.bizEnName}InfoData);
+    ajax.start();
+}
+
+$(function() {
+
+});
diff --git a/DriverOKTravel/guns-rest/db/guns_rest.sql b/DriverOKTravel/guns-rest/db/guns_rest.sql
new file mode 100644
index 0000000..4cc1588
--- /dev/null
+++ b/DriverOKTravel/guns-rest/db/guns_rest.sql
@@ -0,0 +1,38 @@
+/*
+ Navicat MySQL Data Transfer
+
+ Source Server         : localhost
+ Source Server Type    : MySQL
+ Source Server Version : 50721
+ Source Host           : localhost:3306
+ Source Schema         : guns_rest
+
+ Target Server Type    : MySQL
+ Target Server Version : 50721
+ File Encoding         : 65001
+
+ Date: 26/01/2018 21:16:47
+*/
+
+DROP DATABASE IF EXISTS guns_rest;
+CREATE DATABASE IF NOT EXISTS guns_rest DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for user
+-- ----------------------------
+DROP TABLE IF EXISTS `user`;
+CREATE TABLE `user`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `userName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of user
+-- ----------------------------
+INSERT INTO `user` VALUES (1, 'admin');
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/DriverOKTravel/guns-rest/pom.xml b/DriverOKTravel/guns-rest/pom.xml
new file mode 100644
index 0000000..e6eac88
--- /dev/null
+++ b/DriverOKTravel/guns-rest/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.stylefeng.guns</groupId>
+    <artifactId>guns-rest</artifactId>
+    <version>0.0.1</version>
+    <packaging>jar</packaging>
+
+    <name>guns-rest</name>
+    <description>guns REST服务器</description>
+
+    <parent>
+        <groupId>com.stylefeng</groupId>
+        <artifactId>guns-parent</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.stylefeng</groupId>
+            <artifactId>guns-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java
new file mode 100644
index 0000000..e093dc4
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java
@@ -0,0 +1,12 @@
+package com.stylefeng.guns.rest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class GunsRestApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GunsRestApplication.class, args);
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java
new file mode 100644
index 0000000..60fbf5e
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java
@@ -0,0 +1,19 @@
+package com.stylefeng.guns.rest;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * Guns REST Web程序启动类
+ *
+ * @author fengshuonan
+ * @date 2017年9月29日09:00:42
+ */
+public class GunsRestServletInitializer extends SpringBootServletInitializer {
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+        return builder.sources(GunsRestApplication.class);
+    }
+
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java
new file mode 100644
index 0000000..07dde86
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java
@@ -0,0 +1,50 @@
+package com.stylefeng.guns.rest.common;
+
+/**
+ * 测试用的
+ *
+ * @author fengshuonan
+ * @date 2017-08-25 16:47
+ */
+public class SimpleObject {
+
+    private String user;
+
+    private String name;
+
+    private String tips;
+
+    private Integer age;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getTips() {
+        return tips;
+    }
+
+    public void setTips(String tips) {
+        this.tips = tips;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public void setUser(String user) {
+        this.user = user;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java
new file mode 100644
index 0000000..50674dc
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java
@@ -0,0 +1,35 @@
+package com.stylefeng.guns.rest.common.aop;
+
+import com.stylefeng.guns.core.aop.BaseControllerExceptionHandler;
+import com.stylefeng.guns.core.base.tips.ErrorTip;
+import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
+import io.jsonwebtoken.JwtException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
+ *
+ * @author fengshuonan
+ * @date 2016年11月12日 下午3:19:56
+ */
+@ControllerAdvice
+public class GlobalExceptionHandler extends BaseControllerExceptionHandler {
+
+    private Logger log = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 拦截jwt相关异常
+     */
+    @ExceptionHandler(JwtException.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ResponseBody
+    public ErrorTip jwtException(JwtException e) {
+        return new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage());
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java
new file mode 100644
index 0000000..8251960
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java
@@ -0,0 +1,55 @@
+package com.stylefeng.guns.rest.common.exception;
+
+import com.stylefeng.guns.core.exception.ServiceExceptionEnum;
+
+/**
+ * 所有业务异常的枚举
+ *
+ * @author fengshuonan
+ * @date 2016年11月12日 下午5:04:51
+ */
+public enum BizExceptionEnum implements ServiceExceptionEnum {
+
+    /**
+     * token异常
+     */
+    TOKEN_EXPIRED(600, "token过期"),
+    TOKEN_ERROR(600, "token验证失败"),
+
+    /**
+     * 签名异常
+     */
+    SIGN_ERROR(700, "签名验证失败"),
+
+    /**
+     * 其他
+     */
+    AUTH_REQUEST_ERROR(400, "账号密码错误");
+
+    BizExceptionEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    private Integer code;
+
+    private String message;
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java
new file mode 100644
index 0000000..e1ab00a
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java
@@ -0,0 +1,16 @@
+package com.stylefeng.guns.rest.common.persistence.dao;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.stylefeng.guns.rest.common.persistence.model.User;
+
+/**
+ * <p>
+  *  Mapper 接口
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2017-08-23
+ */
+public interface UserMapper extends BaseMapper<User> {
+
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml
new file mode 100644
index 0000000..fddd3fa
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.stylefeng.guns.rest.common.persistence.dao.UserMapper">
+
+	<!-- 通用查询映射结果 -->
+	<resultMap id="BaseResultMap" type="com.stylefeng.guns.rest.common.persistence.model.User">
+		<id column="id" property="id" />
+		<result column="userName" property="userName" />
+	</resultMap>
+
+</mapper>
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java
new file mode 100644
index 0000000..dd876ae
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java
@@ -0,0 +1,51 @@
+package com.stylefeng.guns.rest.common.persistence.model;
+
+import com.baomidou.mybatisplus.activerecord.Model;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2017-08-23
+ */
+public class User extends Model<User> {
+
+    private static final long serialVersionUID = 1L;
+
+	private Long id;
+	private String userName;
+
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public String getUserName() {
+		return userName;
+	}
+
+	public void setUserName(String userName) {
+		this.userName = userName;
+	}
+
+	@Override
+	protected Serializable pkVal() {
+		return this.id;
+	}
+
+	@Override
+	public String toString() {
+		return "User{" +
+			"id=" + id +
+			", userName=" + userName +
+			"}";
+	}
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java
new file mode 100644
index 0000000..ddec398
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java
@@ -0,0 +1,28 @@
+package com.stylefeng.guns.rest.config;
+
+import com.stylefeng.guns.core.config.DefaultFastjsonConfig;
+import com.stylefeng.guns.rest.config.properties.RestProperties;
+import com.stylefeng.guns.rest.modular.auth.converter.WithSignMessageConverter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 签名校验messageConverter
+ *
+ * @author fengshuonan
+ * @date 2017-08-25 16:04
+ */
+@Configuration
+public class MessageConverConfig {
+
+    @Bean
+    @ConditionalOnProperty(prefix = RestProperties.REST_PREFIX, name = "sign-open", havingValue = "true", matchIfMissing = true)
+    public WithSignMessageConverter withSignMessageConverter() {
+        WithSignMessageConverter withSignMessageConverter = new WithSignMessageConverter();
+        DefaultFastjsonConfig defaultFastjsonConfig = new DefaultFastjsonConfig();
+        withSignMessageConverter.setFastJsonConfig(defaultFastjsonConfig.fastjsonConfig());
+        withSignMessageConverter.setSupportedMediaTypes(defaultFastjsonConfig.getSupportedMediaType());
+        return withSignMessageConverter;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..db4bbaf
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java
@@ -0,0 +1,25 @@
+package com.stylefeng.guns.rest.config;
+
+import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * MybatisPlus配置
+ *
+ * @author stylefeng
+ * @Date 2017年8月23日12:51:41
+ */
+@Configuration
+@MapperScan(basePackages = {"com.stylefeng.guns.rest.*.dao", "com.stylefeng.guns.rest.common.persistence.dao"})
+public class MybatisPlusConfig {
+
+    /**
+     * mybatis-plus分页插件
+     */
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        return new PaginationInterceptor();
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java
new file mode 100644
index 0000000..30fcc1f
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java
@@ -0,0 +1,30 @@
+package com.stylefeng.guns.rest.config;
+
+import com.stylefeng.guns.rest.config.properties.RestProperties;
+import com.stylefeng.guns.rest.modular.auth.filter.AuthFilter;
+import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
+import com.stylefeng.guns.rest.modular.auth.security.impl.Base64SecurityAction;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * web配置
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 15:48
+ */
+@Configuration
+public class WebConfig {
+
+    @Bean
+    @ConditionalOnProperty(prefix = RestProperties.REST_PREFIX, name = "auth-open", havingValue = "true", matchIfMissing = true)
+    public AuthFilter jwtAuthenticationTokenFilter() {
+        return new AuthFilter();
+    }
+
+    @Bean
+    public DataSecurityAction dataSecurityAction() {
+        return new Base64SecurityAction();
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java
new file mode 100644
index 0000000..b7dfd2e
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java
@@ -0,0 +1,71 @@
+package com.stylefeng.guns.rest.config.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * jwt相关配置
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 9:23
+ */
+@Configuration
+@ConfigurationProperties(prefix = JwtProperties.JWT_PREFIX)
+public class JwtProperties {
+
+    public static final String JWT_PREFIX = "jwt";
+
+    private String header = "Authorization";
+
+    private String secret = "defaultSecret";
+
+    private Long expiration = 604800L;
+
+    private String authPath = "auth";
+
+    private String md5Key = "randomKey";
+
+    public static String getJwtPrefix() {
+        return JWT_PREFIX;
+    }
+
+    public String getHeader() {
+        return header;
+    }
+
+    public void setHeader(String header) {
+        this.header = header;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public Long getExpiration() {
+        return expiration;
+    }
+
+    public void setExpiration(Long expiration) {
+        this.expiration = expiration;
+    }
+
+    public String getAuthPath() {
+        return authPath;
+    }
+
+    public void setAuthPath(String authPath) {
+        this.authPath = authPath;
+    }
+
+    public String getMd5Key() {
+        return md5Key;
+    }
+
+    public void setMd5Key(String md5Key) {
+        this.md5Key = md5Key;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java
new file mode 100644
index 0000000..bab1c51
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java
@@ -0,0 +1,37 @@
+package com.stylefeng.guns.rest.config.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 项目相关配置
+ *
+ * @author fengshuonan
+ * @date 2017年10月23日16:44:15
+ */
+@Configuration
+@ConfigurationProperties(prefix = RestProperties.REST_PREFIX)
+public class RestProperties {
+
+    public static final String REST_PREFIX = "rest";
+
+    private boolean authOpen = true;
+
+    private boolean signOpen = true;
+
+    public boolean isAuthOpen() {
+        return authOpen;
+    }
+
+    public void setAuthOpen(boolean authOpen) {
+        this.authOpen = authOpen;
+    }
+
+    public boolean isSignOpen() {
+        return signOpen;
+    }
+
+    public void setSignOpen(boolean signOpen) {
+        this.signOpen = signOpen;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java
new file mode 100644
index 0000000..6f35656
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java
@@ -0,0 +1,44 @@
+package com.stylefeng.guns.rest.modular.auth.controller;
+
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
+import com.stylefeng.guns.rest.modular.auth.controller.dto.AuthRequest;
+import com.stylefeng.guns.rest.modular.auth.controller.dto.AuthResponse;
+import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
+import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 请求验证的
+ *
+ * @author fengshuonan
+ * @Date 2017/8/24 14:22
+ */
+@RestController
+public class AuthController {
+
+    @Autowired
+    private JwtTokenUtil jwtTokenUtil;
+
+    @Resource(name = "simpleValidator")
+    private IReqValidator reqValidator;
+
+    @RequestMapping(value = "${jwt.auth-path}")
+    public ResponseEntity<?> createAuthenticationToken(AuthRequest authRequest) {
+
+        boolean validate = reqValidator.validate(authRequest);
+
+        if (validate) {
+            final String randomKey = jwtTokenUtil.getRandomKey();
+            final String token = jwtTokenUtil.generateToken(authRequest.getUserName(), randomKey);
+            return ResponseEntity.ok(new AuthResponse(token, randomKey));
+        } else {
+            throw new GunsException(BizExceptionEnum.AUTH_REQUEST_ERROR);
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java
new file mode 100644
index 0000000..65f58ba
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java
@@ -0,0 +1,41 @@
+package com.stylefeng.guns.rest.modular.auth.controller.dto;
+
+import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
+
+/**
+ * 认证的请求dto
+ *
+ * @author fengshuonan
+ * @Date 2017/8/24 14:00
+ */
+public class AuthRequest implements Credence {
+
+    private String userName;
+    private String password;
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    @Override
+    public String getCredenceName() {
+        return this.userName;
+    }
+
+    @Override
+    public String getCredenceCode() {
+        return this.password;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java
new file mode 100644
index 0000000..80cd71c
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java
@@ -0,0 +1,37 @@
+package com.stylefeng.guns.rest.modular.auth.controller.dto;
+
+import java.io.Serializable;
+
+/**
+ * 认证的响应结果
+ *
+ * @author fengshuonan
+ * @Date 2017/8/24 13:58
+ */
+public class AuthResponse implements Serializable {
+
+    private static final long serialVersionUID = 1250166508152483573L;
+
+    /**
+     * jwt token
+     */
+    private final String token;
+
+    /**
+     * 用于客户端混淆md5加密
+     */
+    private final String randomKey;
+
+    public AuthResponse(String token, String randomKey) {
+        this.token = token;
+        this.randomKey = randomKey;
+    }
+
+    public String getToken() {
+        return this.token;
+    }
+
+    public String getRandomKey() {
+        return randomKey;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java
new file mode 100644
index 0000000..d654c3e
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java
@@ -0,0 +1,30 @@
+package com.stylefeng.guns.rest.modular.auth.converter;
+
+/**
+ * 基础的传输bean
+ *
+ * @author fengshuonan
+ * @date 2017-08-25 15:52
+ */
+public class BaseTransferEntity {
+
+    private String object; //base64编码的json字符串
+
+    private String sign;   //签名
+
+    public String getObject() {
+        return object;
+    }
+
+    public void setObject(String object) {
+        this.object = object;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java
new file mode 100644
index 0000000..0df6a7b
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java
@@ -0,0 +1,64 @@
+package com.stylefeng.guns.rest.modular.auth.converter;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import com.stylefeng.guns.core.exception.GunsException;
+import com.stylefeng.guns.core.support.HttpKit;
+import com.stylefeng.guns.core.util.MD5Util;
+import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
+import com.stylefeng.guns.rest.config.properties.JwtProperties;
+import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
+import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpInputMessage;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Type;
+
+/**
+ * 带签名的http信息转化器
+ *
+ * @author fengshuonan
+ * @date 2017-08-25 15:42
+ */
+public class WithSignMessageConverter extends FastJsonHttpMessageConverter {
+
+    @Autowired
+    JwtProperties jwtProperties;
+
+    @Autowired
+    JwtTokenUtil jwtTokenUtil;
+
+    @Autowired
+    DataSecurityAction dataSecurityAction;
+
+    @Override
+    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
+
+        InputStream in = inputMessage.getBody();
+        Object o = JSON.parseObject(in, super.getFastJsonConfig().getCharset(), BaseTransferEntity.class, super.getFastJsonConfig().getFeatures());
+
+        //先转化成原始的对象
+        BaseTransferEntity baseTransferEntity = (BaseTransferEntity) o;
+
+        //校验签名
+        String token = HttpKit.getRequest().getHeader(jwtProperties.getHeader()).substring(7);
+        String md5KeyFromToken = jwtTokenUtil.getMd5KeyFromToken(token);
+
+        String object = baseTransferEntity.getObject();
+        String json = dataSecurityAction.unlock(object);
+        String encrypt = MD5Util.encrypt(object + md5KeyFromToken);
+
+        if (encrypt.equals(baseTransferEntity.getSign())) {
+            System.out.println("签名校验成功!");
+        } else {
+            System.out.println("签名校验失败,数据被改动过!");
+            throw new GunsException(BizExceptionEnum.SIGN_ERROR);
+        }
+
+        //校验签名后再转化成应该的对象
+        return JSON.parseObject(json, type);
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java
new file mode 100644
index 0000000..756a0b8
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java
@@ -0,0 +1,66 @@
+package com.stylefeng.guns.rest.modular.auth.filter;
+
+import com.stylefeng.guns.core.base.tips.ErrorTip;
+import com.stylefeng.guns.core.util.RenderUtil;
+import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
+import com.stylefeng.guns.rest.config.properties.JwtProperties;
+import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
+import io.jsonwebtoken.JwtException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 对客户端请求的jwt token验证过滤器
+ *
+ * @author fengshuonan
+ * @Date 2017/8/24 14:04
+ */
+public class AuthFilter extends OncePerRequestFilter {
+
+    private final Log logger = LogFactory.getLog(this.getClass());
+
+    @Autowired
+    private JwtTokenUtil jwtTokenUtil;
+
+    @Autowired
+    private JwtProperties jwtProperties;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        if (request.getServletPath().equals("/" + jwtProperties.getAuthPath())) {
+            chain.doFilter(request, response);
+            return;
+        }
+        final String requestHeader = request.getHeader(jwtProperties.getHeader());
+        String authToken = null;
+        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
+            authToken = requestHeader.substring(7);
+
+            //验证token是否过期,包含了验证jwt是否正确
+            try {
+                boolean flag = jwtTokenUtil.isTokenExpired(authToken);
+                if (flag) {
+                    RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
+                    return;
+                }
+            } catch (JwtException e) {
+                //有异常就是token解析失败
+                RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
+                return;
+            }
+        } else {
+            //header没有带Bearer字段
+            RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
+            return;
+        }
+        chain.doFilter(request, response);
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java
new file mode 100644
index 0000000..83205f4
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java
@@ -0,0 +1,31 @@
+package com.stylefeng.guns.rest.modular.auth.security;
+
+/**
+ * <pre>
+ * 信息传递的保护措施(传递的数据为json)
+ *
+ * 说明:
+ * 可以根据实际开发时的需要,编写自己的数据加密方案,只需实现此类,并在WebConfig下配置您所编写的实现类即可
+ * </pre>
+ *
+ * @author fengshuonan
+ * @date 2017-09-18 20:41
+ */
+public interface DataSecurityAction {
+
+    /**
+     * 执行数据的保护措施
+     *
+     * @author stylefeng
+     * @Date 2017/9/18 20:42
+     */
+    String doAction(String beProtected);
+
+    /**
+     * 解除保护
+     *
+     * @author stylefeng
+     * @Date 2017/9/18 20:45
+     */
+    String unlock(String securityCode);
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java
new file mode 100644
index 0000000..c4169d7
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java
@@ -0,0 +1,24 @@
+package com.stylefeng.guns.rest.modular.auth.security.impl;
+
+import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
+import org.springframework.util.Base64Utils;
+
+/**
+ * 对数据进行base64编码的方式
+ *
+ * @author fengshuonan
+ * @date 2017-09-18 20:43
+ */
+public class Base64SecurityAction implements DataSecurityAction {
+
+    @Override
+    public String doAction(String beProtected) {
+        return Base64Utils.encodeToString(beProtected.getBytes());
+    }
+
+    @Override
+    public String unlock(String securityCode) {
+        byte[] bytes = Base64Utils.decodeFromString(securityCode);
+        return new String(bytes);
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java
new file mode 100644
index 0000000..34f331e
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java
@@ -0,0 +1,140 @@
+package com.stylefeng.guns.rest.modular.auth.util;
+
+import com.stylefeng.guns.core.util.ToolUtil;
+import com.stylefeng.guns.rest.config.properties.JwtProperties;
+import io.jsonwebtoken.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>jwt token工具类</p>
+ * <pre>
+ *     jwt的claim里一般包含以下几种数据:
+ *         1. iss -- token的发行者
+ *         2. sub -- 该JWT所面向的用户
+ *         3. aud -- 接收该JWT的一方
+ *         4. exp -- token的失效时间
+ *         5. nbf -- 在此时间段之前,不会被处理
+ *         6. iat -- jwt发布时间
+ *         7. jti -- jwt唯一标识,防止重复使用
+ * </pre>
+ *
+ * @author fengshuonan
+ * @Date 2017/8/25 10:59
+ */
+@Component
+public class JwtTokenUtil {
+
+    @Autowired
+    private JwtProperties jwtProperties;
+
+    /**
+     * 获取用户名从token中
+     */
+    public String getUsernameFromToken(String token) {
+        return getClaimFromToken(token).getSubject();
+    }
+
+    /**
+     * 获取jwt发布时间
+     */
+    public Date getIssuedAtDateFromToken(String token) {
+        return getClaimFromToken(token).getIssuedAt();
+    }
+
+    /**
+     * 获取jwt失效时间
+     */
+    public Date getExpirationDateFromToken(String token) {
+        return getClaimFromToken(token).getExpiration();
+    }
+
+    /**
+     * 获取jwt接收者
+     */
+    public String getAudienceFromToken(String token) {
+        return getClaimFromToken(token).getAudience();
+    }
+
+    /**
+     * 获取私有的jwt claim
+     */
+    public String getPrivateClaimFromToken(String token, String key) {
+        return getClaimFromToken(token).get(key).toString();
+    }
+
+    /**
+     * 获取md5 key从token中
+     */
+    public String getMd5KeyFromToken(String token) {
+        return getPrivateClaimFromToken(token, jwtProperties.getMd5Key());
+    }
+
+    /**
+     * 获取jwt的payload部分
+     */
+    public Claims getClaimFromToken(String token) {
+        return Jwts.parser()
+                .setSigningKey(jwtProperties.getSecret())
+                .parseClaimsJws(token)
+                .getBody();
+    }
+
+    /**
+     * 解析token是否正确,不正确会报异常<br>
+     */
+    public void parseToken(String token) throws JwtException {
+        Jwts.parser().setSigningKey(jwtProperties.getSecret()).parseClaimsJws(token).getBody();
+    }
+
+    /**
+     * <pre>
+     *  验证token是否失效
+     *  true:过期   false:没过期
+     * </pre>
+     */
+    public Boolean isTokenExpired(String token) {
+        try {
+            final Date expiration = getExpirationDateFromToken(token);
+            return expiration.before(new Date());
+        } catch (ExpiredJwtException expiredJwtException) {
+            return true;
+        }
+    }
+
+    /**
+     * 生成token(通过用户名和签名时候用的随机数)
+     */
+    public String generateToken(String userName, String randomKey) {
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(jwtProperties.getMd5Key(), randomKey);
+        return doGenerateToken(claims, userName);
+    }
+
+    /**
+     * 生成token
+     */
+    private String doGenerateToken(Map<String, Object> claims, String subject) {
+        final Date createdDate = new Date();
+        final Date expirationDate = new Date(createdDate.getTime() + jwtProperties.getExpiration() * 1000);
+
+        return Jwts.builder()
+                .setClaims(claims)
+                .setSubject(subject)
+                .setIssuedAt(createdDate)
+                .setExpiration(expirationDate)
+                .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
+                .compact();
+    }
+
+    /**
+     * 获取混淆MD5签名用的随机字符串
+     */
+    public String getRandomKey() {
+        return ToolUtil.getRandomString(6);
+    }
+}
\ No newline at end of file
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java
new file mode 100644
index 0000000..4ac6925
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java
@@ -0,0 +1,22 @@
+package com.stylefeng.guns.rest.modular.auth.validator;
+
+import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
+
+/**
+ * <p>验证请求/auth接口时,请求参数的正确性</p>
+ * <p>
+ * <p>如果想拓展验证方法只需实现这个接口,然后在AuthenticationRestController类中注意相应实现的本接口的类即可</p>
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 11:48
+ */
+public interface IReqValidator {
+
+    /**
+     * 通过请求参数验证
+     *
+     * @author fengshuonan
+     * @Date 2017/8/23 11:49
+     */
+    boolean validate(Credence credence);
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java
new file mode 100644
index 0000000..ee37ac5
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java
@@ -0,0 +1,20 @@
+package com.stylefeng.guns.rest.modular.auth.validator.dto;
+
+/**
+ * 验证的凭据
+ *
+ * @author fengshuonan
+ * @date 2017-08-27 13:27
+ */
+public interface Credence {
+
+    /**
+     * 凭据名称
+     */
+    String getCredenceName();
+
+    /**
+     * 密码或者是其他的验证码之类的
+     */
+    String getCredenceCode();
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java
new file mode 100644
index 0000000..dba2f16
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java
@@ -0,0 +1,35 @@
+package com.stylefeng.guns.rest.modular.auth.validator.impl;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.stylefeng.guns.rest.common.persistence.dao.UserMapper;
+import com.stylefeng.guns.rest.common.persistence.model.User;
+import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
+import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 账号密码验证
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 12:34
+ */
+@Service
+public class DbValidator implements IReqValidator {
+
+    @Autowired
+    UserMapper userMapper;
+
+    @Override
+    public boolean validate(Credence credence) {
+        List<User> users = userMapper.selectList(new EntityWrapper<User>().eq("userName", credence.getCredenceName()));
+        if (users != null && users.size() > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java
new file mode 100644
index 0000000..36a9aac
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java
@@ -0,0 +1,32 @@
+package com.stylefeng.guns.rest.modular.auth.validator.impl;
+
+import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
+import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
+import org.springframework.stereotype.Service;
+
+/**
+ * 直接验证账号密码是不是admin
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 12:34
+ */
+@Service
+public class SimpleValidator implements IReqValidator {
+
+    private static String USER_NAME = "admin";
+
+    private static String PASSWORD = "admin";
+
+    @Override
+    public boolean validate(Credence credence) {
+
+        String userName = credence.getCredenceName();
+        String password = credence.getCredenceCode();
+
+        if (USER_NAME.equals(userName) && PASSWORD.equals(password)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java
new file mode 100644
index 0000000..75003c8
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java
@@ -0,0 +1,24 @@
+package com.stylefeng.guns.rest.modular.example;
+
+import com.stylefeng.guns.rest.common.SimpleObject;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 常规控制器
+ *
+ * @author fengshuonan
+ * @date 2017-08-23 16:02
+ */
+@Controller
+@RequestMapping("/hello")
+public class ExampleController {
+
+    @RequestMapping("")
+    public ResponseEntity hello(@RequestBody SimpleObject simpleObject) {
+        System.out.println(simpleObject.getUser());
+        return ResponseEntity.ok("请求成功!");
+    }
+}
diff --git a/DriverOKTravel/guns-rest/src/main/resources/application.yml b/DriverOKTravel/guns-rest/src/main/resources/application.yml
new file mode 100644
index 0000000..84653e1
--- /dev/null
+++ b/DriverOKTravel/guns-rest/src/main/resources/application.yml
@@ -0,0 +1,40 @@
+rest:
+  auth-open: true #jwt鉴权机制是否开启(true或者false)
+  sign-open: true #签名机制是否开启(true或false)
+
+jwt:
+  header: Authorization   #http请求头所需要的字段
+  secret: mySecret        #jwt秘钥
+  expiration: 604800      #7天 单位:秒
+  auth-path: auth         #认证请求的路径
+  md5-key: randomKey      #md5加密混淆key
+
+server:
+  port: 8080 #项目端口
+
+mybatis-plus:
+  mapper-locations: classpath*:com/stylefeng/guns/rest/**/mapping/*.xml
+  typeAliasesPackage: com.stylefeng.guns.rest.common.persistence.model
+  global-config:
+    id-type: 0  #0:数据库ID自增   1:用户输入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)
+    db-column-underline: false
+    refresh-mapper: true
+  configuration:
+    map-underscore-to-camel-case: false
+    cache-enabled: true #配置的缓存的全局开关
+    lazyLoadingEnabled: true #延时加载的开关
+    multipleResultSetsEnabled: true #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用
+
+spring:
+  datasource:
+      url: jdbc:mysql://127.0.0.1:3306/guns_rest?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=UTC
+      username: root
+      password: root
+      filters: log4j,wall,mergeStat
+
+logging:
+  level.root: info
+  level.com.stylefeng: debug
+  path: logs/
+  file: guns-rest.log
\ No newline at end of file

--
Gitblit v1.7.1