xuhy
2024-05-13 d508174005d03f3845044e0658d43cf92c9befe8
manage-core
128个文件已添加
14161 ■■■■■ 已修改文件
ManagementNTTravel/guns-core/guns-core.iml 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/pom.xml 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java 508 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java 801 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java 1370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java 1060 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java 353 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ExcelExportUtil.java 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java 582 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/resources/META-INF/spring.factories 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/src/main/resources/default-config.properties 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/guns-generator.iml 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/pom.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/guns-rest.iml 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/pom.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-rest/src/main/resources/application.yml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementNTTravel/guns-core/guns-core.iml
New file
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="web" name="Web">
      <configuration>
        <webroots />
      </configuration>
    </facet>
    <facet type="Spring" name="Spring">
      <configuration />
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
    <output url="file://$MODULE_DIR$/target/classes" />
    <output-test url="file://$MODULE_DIR$/target/test-classes" />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <excludeFolder url="file://$MODULE_DIR$/target" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatisplus-spring-boot-starter:1.0.5" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-support:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:1.1" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-generate:2.3" level="project" />
    <orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
    <orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
    <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.11" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
    <orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.8.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:2.7.9" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:druid:1.1.10" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.47" level="project" />
    <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework.boot:spring-boot-starter-web:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework.boot:spring-boot-starter-json:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.5" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.5" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.32" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.32" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.32" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.hibernate.validator:hibernate-validator:6.0.11.Final" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework:spring-web:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework:spring-webmvc:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.aspectj:aspectjweaver:1.8.13" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.zxing:core:3.2.1" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.ehcache:ehcache:3.3.1" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: org.springframework:spring-context-support:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="PROVIDED" name="Maven: net.sf.ehcache:ehcache-core:2.6.11" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi:3.9" level="project" />
    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:3.9" level="project" />
    <orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />
    <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.4.01" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi-examples:3.9" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi-excelant:3.9" level="project" />
    <orderEntry type="library" name="Maven: org.apache.ant:ant:1.8.2" level="project" />
    <orderEntry type="library" name="Maven: org.apache.ant:ant-launcher:1.8.2" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:3.9" level="project" />
    <orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:2.3.0" level="project" />
    <orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
    <orderEntry type="library" name="Maven: org.apache.poi:poi-scratchpad:3.9" level="project" />
    <orderEntry type="library" name="Maven: com.huaweicloud:esdk-obs-java:3.19.5" level="project" />
    <orderEntry type="library" name="Maven: com.jamesmurty.utils:java-xmlbuilder:1.1" level="project" />
    <orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.8.1" level="project" />
    <orderEntry type="library" name="Maven: com.squareup.okio:okio:1.14.0" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.10.0" level="project" />
  </component>
</module>
ManagementNTTravel/guns-core/pom.xml
New file
@@ -0,0 +1,156 @@
<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>
        <!--导出Excel工具类-->
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-examples -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-examples</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-excelant -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.9</version>
        </dependency>
        <!--华为云的obs-->
        <dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java</artifactId>
            <version>3.19.5</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
</project>
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java
New file
@@ -0,0 +1,11 @@
package com.stylefeng.guns.core;
/**
 * 此类用来获取core模块的包路径
 *
 * @author fengshuonan
 * @Date 2017/12/5 下午12:44
 */
public class CoreFlag {
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java
New file
@@ -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());
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java
New file
@@ -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";
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java
New file
@@ -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 = "操作成功";
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java
New file
@@ -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);
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java
New file
@@ -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);
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java
New file
@@ -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();
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java
New file
@@ -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);
            }
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java
New file
@@ -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 "";
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java
New file
@@ -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) {
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java
New file
@@ -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;
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java
New file
@@ -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();
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java
New file
@@ -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 "";
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java
New file
@@ -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);
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java
New file
@@ -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 + "]";
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java
New file
@@ -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);
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java
New file
@@ -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;
  }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java
New file
@@ -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);
    }
  }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java
New file
@@ -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());
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java
New file
@@ -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;
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java
New file
@@ -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());
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java
New file
@@ -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());
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java
New file
@@ -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
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java
New file
@@ -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));
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java
New file
@@ -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));
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java
New file
@@ -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("^整$", "零元整");
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java
New file
@@ -0,0 +1,353 @@
/**
 * 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;
import java.util.TimeZone;
public class DateUtil {
    private static TimeZone tz = TimeZone.getTimeZone("GMT+8");
    /**
     * 获取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 Date getAfterDayDate(Integer daysInt) {
        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 date;
    }
    /**
     * 得到n天之后的日期
     */
    public static String getAfterDayDate(String days, String pattern) {
        int daysInt = Integer.parseInt(days);
        Calendar canlendar = Calendar.getInstance(); // java.util包
        canlendar.add(Calendar.DATE, daysInt); // 日期减 如果不够减会将月变动
        Date date = canlendar.getTime();
        SimpleDateFormat sdfd = new SimpleDateFormat(pattern == null ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd");
        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;
    }
    /**
     * 得到系统日期
     *
     * @return
     */
    public static Date getDate() {
        TimeZone.setDefault(tz);
        return new Date();
    }
    /**
     * 字符串日期转Date yyyy-MM-dd HH:mm:ss
     * @param dateStr
     * @return
     */
    public static Date getDate_str3(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(tz);
        if ("".equals(dateStr)) {
            dateStr = sdf.format(DateUtil.getDate());
        }
        Date date = null;
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
    /**
     * 获取当前毫秒数
     * @return long
     */
    public static long getCurMilli() {
        long millisecond = 0;
        Calendar cal = Calendar.getInstance();
        millisecond = cal.getTimeInMillis();
        return millisecond;
    }
    /**
     * 毫秒转Date
     * @param dateStr
     * @return
     */
    public static Date getDate_strYMdHms(Long dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (dateStr == null) {
            dateStr = DateUtil.getCurMilli();
        }
        Date date = null;
        try {
            date = sdf.parse(sdf.format(new Date(dateStr)));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
    /**
     * 得到系统Calendar日期
     * @return
     */
    public static Calendar getCalendar() {
        TimeZone.setDefault(tz);
        Calendar cal = Calendar.getInstance();
        return cal;
    }
    /**
     *
     * 获取之前几天日期
     * @param pattern yyyy-MM-dd(默认)
     * @param few 之前几天
     */
    public static String beforeFewDayStr(String pattern, Integer few) {
        if(pattern == null || "".equals(pattern)){
            pattern = "yyyy-MM-dd";
        }
        Calendar c = getCalendar();
        c.add(Calendar.DATE,-few);
        return new SimpleDateFormat(pattern).format(c.getTime());
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ExcelExportUtil.java
New file
@@ -0,0 +1,271 @@
package com.stylefeng.guns.core.util;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
/**
 * Excel报表导出工具类
 */
public class ExcelExportUtil {
    /**
     * 简单模板excel导出功能
     * @param fileName 报表文件名
     * @param sheetName 报表表名
     * @param dataList 报表数据(包含行头和列内容)
     * @param request
     * @param response
     * @throws IOException
     */
    public static void easySheet(String fileName, String sheetName, List<List<String>> dataList, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //设置响应头,输出文件
        setResponseHeader(response, fileName);
        HSSFWorkbook  workbook = new HSSFWorkbook();
        Sheet sheet = null;
        HSSFCellStyle style = workbook.createCellStyle();
        // 创建字体对象
        Font ztFont = workbook.createFont();
        ztFont.setItalic(true);                     // 设置字体为斜体字
        ztFont.setColor(Font.COLOR_RED);            // 将字体设置为“红色”
        ztFont.setFontHeightInPoints((short)22);    // 将字体大小设置为18px
        ztFont.setFontName("华文行楷");             // 将“华文行楷”字体应用到当前单元格上
        ztFont.setUnderline(Font.U_DOUBLE);         // 添加(Font.U_SINGLE单条下划线/Font.U_DOUBLE双条下划线)
        style.setFont(ztFont);                    // 将字体应用到样式上面
//        // 设置单元格边框样式
//        style.setBorderBottom(CellStyle.BORDER_THICK);
//        style.setBorderTop(CellStyle.BORDER_DASHED);
//        style.setBorderLeft(CellStyle.BORDER_DOUBLE);
//        style.setBorderRight(CellStyle.BORDER_THIN);
//
//        // 设置单元格边框颜色
//        style.setBottomBorderColor(HSSFColor.ORANGE.index);
//        style.setTopBorderColor(HSSFColor.ORANGE.index);
//        style.setLeftBorderColor(HSSFColor.ORANGE.index);
//
//        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
//        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
//        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//
//        // 设置单元格内容垂直对其方式
//        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        sheet = workbook.createSheet(sheetName);//设置表明
        sheet.setDefaultColumnWidth(15);//setColumnWidth设置cell的宽度
        sheet.setDefaultRowHeightInPoints(20);
        //填充报表数据
        for (int y = 0; y < dataList.size(); y++) {
            List<String> cellList = dataList.get(y);
            Row row = sheet.createRow(y);
            for (int x = 0; x < cellList.size(); x++) {
                row.createCell(x).setCellValue(cellList.get(x));
            }
        }
        OutputStream outStream = response.getOutputStream();
        try {
            workbook.write(outStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        outStream.flush();
        outStream.close();
    }
    /**
     * 复杂杂模板excel导出(合并单元格、设置表格样式等)
     * @param request
     * @param response
     * @throws IOException
     */
    public static void carSheet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HSSFWorkbook  workbook = new HSSFWorkbook();
        Sheet sheet = null;
        HSSFCellStyle style = workbook.createCellStyle();
        /** 创建字体对象   */
        Font ztFont = workbook.createFont();
        ztFont.setItalic(true);                     // 设置字体为斜体字
        ztFont.setColor(Font.COLOR_RED);            // 将字体设置为“红色”
        ztFont.setFontHeightInPoints((short)22);    // 将字体大小设置为18px
        ztFont.setFontName("华文行楷");             // 将“华文行楷”字体应用到当前单元格上
        ztFont.setUnderline(Font.U_DOUBLE);         // 添加(Font.U_SINGLE单条下划线/Font.U_DOUBLE双条下划线)
        //ztFont.setStrikeout(true);                  // 是否添加删除线
        style.setFont(ztFont);                    // 将字体应用到样式上面
        //ztCell.setCellStyle(ztStyle);               // 样式应用到该单元格上
        /** 设置单元格边框样式   */
        // CellStyle.BORDER_DOUBLE      双边线
        // CellStyle.BORDER_THIN        细边线
        // CellStyle.BORDER_MEDIUM      中等边线
        // CellStyle.BORDER_DASHED      虚线边线
        // CellStyle.BORDER_HAIR        小圆点虚线边线
        // CellStyle.BORDER_THICK       粗边线
        style.setBorderBottom(CellStyle.BORDER_THICK);
        style.setBorderTop(CellStyle.BORDER_DASHED);
        style.setBorderLeft(CellStyle.BORDER_DOUBLE);
        style.setBorderRight(CellStyle.BORDER_THIN);
        // 设置单元格边框颜色
        style.setBottomBorderColor(HSSFColor.ORANGE.index);
        style.setTopBorderColor(HSSFColor.ORANGE.index);
        style.setLeftBorderColor(HSSFColor.ORANGE.index);
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        // 设置单元格内容水平对其方式
        // XSSFCellStyle.ALIGN_CENTER       居中对齐
        // XSSFCellStyle.ALIGN_LEFT         左对齐
        // XSSFCellStyle.ALIGN_RIGHT        右对齐
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 设置单元格内容垂直对其方式
        // XSSFCellStyle.VERTICAL_TOP       上对齐
        // XSSFCellStyle.VERTICAL_CENTER    中对齐
        // XSSFCellStyle.VERTICAL_BOTTOM    下对齐
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        sheet = workbook.createSheet("测试数据导出");
        sheet.setDefaultColumnWidth(14);//setColumnWidth设置cell的宽度
        sheet.setDefaultRowHeightInPoints(20);
        //sheet.setColumnWidth(0, 12 * 256);//setColumnWidth设置cell的宽度
        Row row = sheet.createRow(0);
        //heightInPoints 设置的值永远是height属性值的20倍
        row.setHeightInPoints(20);
        row.createCell(0).setCellValue("用户代码");
        //合并单元格 (起始行,结束行,起始列,结束列)
        sheet.addMergedRegion(new CellRangeAddress(0,(short)1,0,(short)(0)));
        row.createCell(1).setCellValue("用户名");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)1,1,(short)(1)));
        row.createCell(2).setCellValue("资金总额");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)1,2,(short)(2)));
        row.createCell(3).setCellValue("可用金额");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)1,3,(short)(3)));
        row.createCell(4).setCellValue("冻结");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)1,4,(short)(4)));
        row.createCell(5).setCellValue("收入");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)0,5,(short)(11)));
        row.createCell(12).setCellValue("待收");
        sheet.addMergedRegion(new CellRangeAddress(0,(short)0,12,(short)(14)));
        Row row1 = sheet.createRow(1);
        row1.setHeightInPoints(20);
        row1.createCell(5).setCellValue("总计");
        row1.createCell(6).setCellValue("本金");
        row1.createCell(7).setCellValue("利息");
        row1.createCell(8).setCellValue("提前还款罚息");
        row1.createCell(9).setCellValue("逾期罚息");
        row1.createCell(10).setCellValue("奖励");
        row1.createCell(11).setCellValue("活动");
        row1.createCell(12).setCellValue("总计");
        row1.createCell(13).setCellValue("本金");
        row1.createCell(14).setCellValue("利息");
        row = sheet.createRow(2);
        //heightInPoints 设置的值永远是height属性值的20倍
        row.setHeightInPoints(20);
        row.createCell(0).setCellValue("测试");
        row.createCell(1).setCellValue("测试数据");
        row.createCell(2).setCellValue(Double.parseDouble("7599.68"));
        row.createCell(3).setCellValue(Double.parseDouble("8599.68"));
        row.createCell(4).setCellValue(Double.parseDouble("9599.68"));
        row.createCell(5).setCellValue(Double.parseDouble("9699.68"));
        row.createCell(6).setCellValue(Double.parseDouble("9799.68"));
        row.createCell(7).setCellValue(Double.parseDouble("9899.68"));
        row.createCell(8).setCellValue(Double.parseDouble("9999.68"));
        row.createCell(9).setCellValue(Double.parseDouble("17599.68"));
        row.createCell(10).setCellValue(Double.parseDouble("12599.68"));
        row.createCell(11).setCellValue(Double.parseDouble("17599.68"));
        row.createCell(12).setCellValue(Double.parseDouble("17699.68"));
        row.createCell(13).setCellValue(Double.parseDouble("17799.68"));
        row.createCell(14).setCellValue(Double.parseDouble("17899.68"));
        row = sheet.createRow(3);
        row.setHeightInPoints(20);
        row.createCell(0).setCellValue("测试2");
        row.createCell(1).setCellValue("测试数据3");
        row.createCell(2).setCellValue(Double.parseDouble("7599.61"));
        row.createCell(3).setCellValue(Double.parseDouble("8599.62"));
        row.createCell(4).setCellValue(Double.parseDouble("9599.63"));
        row.createCell(5).setCellValue(Double.parseDouble("9699.64"));
        row.createCell(6).setCellValue(Double.parseDouble("9799.65"));
        row.createCell(7).setCellValue(Double.parseDouble("9899.66"));
        row.createCell(8).setCellValue(Double.parseDouble("9999.67"));
        row.createCell(9).setCellValue(Double.parseDouble("17599.88"));
        row.createCell(10).setCellValue(Double.parseDouble("12599.69"));
        row.createCell(11).setCellValue(Double.parseDouble("17599.70"));
        row.createCell(12).setCellValue(Double.parseDouble("17699.71"));
        row.createCell(13).setCellValue(Double.parseDouble("17799.72"));
        row.createCell(14).setCellValue(Double.parseDouble("17899.73"));
        OutputStream outStream = new FileOutputStream(new File(request.getSession().getServletContext().getRealPath("/resource/xls/finance.xls")));
        try {
            workbook.write(outStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        outStream.flush();
        outStream.close();
        /*int z = 2;
        DecimalFormat df = new DecimalFormat("#,##0.00");
        for (Iterator<Object> it = objPageView.getRecords().iterator(); it.hasNext();) {
            row = sheet.createRow(z);
            Object[] obj = (Object[])it.next();
            row.createCell(0).setCellValue(obj[2] != null ? obj[2].toString() : null);
            row.createCell(1).setCellValue(obj[1] != null ? obj[1].toString() : null);
            row.createCell(2).setCellValue(df.format(Double.parseDouble(obj[4].toString())+Double.parseDouble(obj[11].toString())+Double.parseDouble(obj[12].toString())));
            row.createCell(3).setCellValue(df.format(Double.parseDouble(obj[4].toString())));
            row.createCell(4).setCellValue(df.format(Double.parseDouble(obj[11].toString())));
            row.createCell(5).setCellValue(df.format(Double.parseDouble(obj[6].toString())));
            row.createCell(6).setCellValue(df.format(Double.parseDouble(obj[7].toString())));
            row.createCell(7).setCellValue(df.format(Double.parseDouble(obj[8].toString())));
            row.createCell(8).setCellValue(df.format(Double.parseDouble(obj[15].toString())));
            row.createCell(9).setCellValue(df.format(Double.parseDouble(obj[16].toString())));
            row.createCell(10).setCellValue(df.format(Double.parseDouble(obj[9].toString())));
            row.createCell(11).setCellValue(df.format(Double.parseDouble(obj[10].toString())));
            row.createCell(12).setCellValue(df.format(Double.parseDouble(obj[12].toString())));
            row.createCell(13).setCellValue(df.format(Double.parseDouble(obj[13].toString())));
            row.createCell(14).setCellValue(df.format(Double.parseDouble(obj[14].toString())));
            z++;
        }
            row = sheet.createRow(z);
            row.createCell(1).setCellValue("总计");
            row.createCell(2).setCellValue(df.format(fundsAccountTotal.getTotal()));
            row.createCell(3).setCellValue(df.format(fundsAccountTotal.getBalance()));
            row.createCell(4).setCellValue(df.format(fundsAccountTotal.getFrost()));
            row.createCell(5).setCellValue(df.format(fundsAccountTotal.getIncome()));
            row.createCell(6).setCellValue(df.format(fundsAccountTotal.getIncomeCapital()));
            row.createCell(7).setCellValue(df.format(fundsAccountTotal.getIncomeInterest()));
            row.createCell(8).setCellValue(df.format(fundsAccountTotal.getIncomePrepayment()));
            row.createCell(9).setCellValue(df.format(fundsAccountTotal.getIncomeOverdue()));
            row.createCell(10).setCellValue(df.format(fundsAccountTotal.getIncomeAward()));
            row.createCell(11).setCellValue(df.format(fundsAccountTotal.getIncomeActivity()));
            row.createCell(12).setCellValue(df.format(fundsAccountTotal.getAwait()));
            row.createCell(13).setCellValue(df.format(fundsAccountTotal.getAwaitCapital()));
            row.createCell(14).setCellValue(df.format(fundsAccountTotal.getAwaitInterest()));*/
    }
    /**
     * 设置响应头
     * @param response
     */
    public static void setResponseHeader(HttpServletResponse response,String excelName) {
        response.setContentType("application/octet-stream;charset=ISO8859-1");
        try {
            excelName = new String(excelName.getBytes("gb2312"),"ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename="+excelName+URLEncoder.encode(".xls", "ISO8859-1"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java
New file
@@ -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"));
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java
New file
@@ -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);
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java
New file
@@ -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!");
        }
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java
New file
@@ -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));
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-core/src/main/resources/META-INF/spring.factories
New file
@@ -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
ManagementNTTravel/guns-core/src/main/resources/default-config.properties
New file
@@ -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
ManagementNTTravel/guns-generator/guns-generator.iml
New file
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="Spring" name="Spring">
      <configuration />
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
    <output url="file://$MODULE_DIR$/target/classes" />
    <output-test url="file://$MODULE_DIR$/target/test-classes" />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <excludeFolder url="file://$MODULE_DIR$/target" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="module" module-name="guns-core (2)" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatisplus-spring-boot-starter:1.0.5" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:1.1" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
    <orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
    <orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
    <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.11" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
    <orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.8.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:2.7.9" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:druid:1.1.10" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.47" level="project" />
    <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
    <orderEntry type="library" name="Maven: com.ibeetl:beetl:2.8.5" level="project" />
    <orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.2" level="project" />
    <orderEntry type="library" name="Maven: org.abego.treelayout:org.abego.treelayout.core:1.0.1" level="project" />
    <orderEntry type="library" name="Maven: org.antlr:antlr4-annotations:4.2" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-generate:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-support:2.3" level="project" />
  </component>
</module>
ManagementNTTravel/guns-generator/pom.xml
New file
@@ -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>
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java
New file
@@ -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());
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java
New file
@@ -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成功!");
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java
New file
@@ -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();
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java
New file
@@ -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 +
                "}";
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl
New file
@@ -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);
    }
}
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl
New file
@@ -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}');
<% } %>
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl
New file
@@ -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>
@}
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl
New file
@@ -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();
});
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl
New file
@@ -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>
@}
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl
New file
@@ -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>
@}
ManagementNTTravel/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl
New file
@@ -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() {
});
ManagementNTTravel/guns-rest/guns-rest.iml
New file
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="web" name="Web">
      <configuration>
        <webroots />
      </configuration>
    </facet>
    <facet type="Spring" name="Spring">
      <configuration />
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
    <output url="file://$MODULE_DIR$/target/classes" />
    <output-test url="file://$MODULE_DIR$/target/test-classes" />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <excludeFolder url="file://$MODULE_DIR$/target" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.10.0" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
    <orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.32" level="project" />
    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.32" level="project" />
    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.32" level="project" />
    <orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.11.Final" level="project" />
    <orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
    <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-web:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.9.1" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.15.0" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.7.11" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.7.11" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.8.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.5.1" level="project" />
    <orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.0" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.5" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.5" level="project" />
    <orderEntry type="module" module-name="guns-core (2)" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatisplus-spring-boot-starter:1.0.5" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-support:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:2.3" level="project" />
    <orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:1.1" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
    <orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-generate:2.3" level="project" />
    <orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
    <orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
    <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.11" level="project" />
    <orderEntry type="library" scope="RUNTIME" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.0.4.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:2.7.9" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.0.5.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:druid:1.1.10" level="project" />
    <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.47" level="project" />
    <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
    <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" />
  </component>
</module>
ManagementNTTravel/guns-rest/pom.xml
New file
@@ -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>
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestApplication.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/GunsRestServletInitializer.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/SimpleObject.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/aop/GlobalExceptionHandler.java
New file
@@ -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());
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/exception/BizExceptionEnum.java
New file
@@ -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(700, "token过期"),
    TOKEN_ERROR(700, "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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/UserMapper.java
New file
@@ -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> {
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/dao/mapping/UserMapper.xml
New file
@@ -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>
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/common/persistence/model/User.java
New file
@@ -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 +
            "}";
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MessageConverConfig.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/MybatisPlusConfig.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/WebConfig.java
New file
@@ -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();
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/JwtProperties.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/config/properties/RestProperties.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/AuthController.java
New file
@@ -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);
        }
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthRequest.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/controller/dto/AuthResponse.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/BaseTransferEntity.java
New file
@@ -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;
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/converter/WithSignMessageConverter.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/filter/AuthFilter.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/DataSecurityAction.java
New file
@@ -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);
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/security/impl/Base64SecurityAction.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/util/JwtTokenUtil.java
New file
@@ -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);
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/IReqValidator.java
New file
@@ -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);
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/dto/Credence.java
New file
@@ -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();
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/DbValidator.java
New file
@@ -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;
        }
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/auth/validator/impl/SimpleValidator.java
New file
@@ -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;
        }
    }
}
ManagementNTTravel/guns-rest/src/main/java/com/stylefeng/guns/rest/modular/example/ExampleController.java
New file
@@ -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("请求成功!");
    }
}
ManagementNTTravel/guns-rest/src/main/resources/application.yml
New file
@@ -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