From 8502471a053d7c267e02017ef560137c4dd3340d Mon Sep 17 00:00:00 2001 From: zer0Black <694429613@qq.com> Date: Tue, 5 Apr 2022 22:07:12 +0800 Subject: [PATCH] =?UTF-8?q?2.4.6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jero-boot/README.md | 2 +- .../jero-system-cloud-api/pom.xml | 2 +- .../jero/common/system/api/ISysBaseAPI.java | 103 +++++++- .../api/fallback/SysBaseAPIFallback.java | 46 ++++ .../java/com/jero/config/FeignConfig.java | 110 ++++++++- .../jero-system-local-api/pom.xml | 2 +- .../jero/common/system/api/ISysBaseAPI.java | 42 ++++ .../jero-boot-base/jero-boot-base-api/pom.xml | 2 +- .../jero-boot-base-core/pom.xml | 7 +- .../java/com/jero/common/api/CommonAPI.java | 25 ++ .../com/jero/common/aspect/DictAspect.java | 231 ++++++++++++++++-- .../jero/common/constant/CommonConstant.java | 2 + .../common/es/JeroElasticsearchTemplate.java | 24 ++ .../common/system/query/QueryCondition.java | 18 +- .../common/system/query/QueryGenerator.java | 39 +-- .../jero/common/system/vo/DictModelMany.java | 18 ++ .../system/vo/DynamicDataSourceModel.java | 4 - .../com/jero/common/util/CommonUtils.java | 61 +++-- .../java/com/jero/common/util/DateUtils.java | 4 + .../java/com/jero/common/util/MinioUtil.java | 5 +- .../com/jero/common/util/PathMatcherUtil.java | 84 +++++++ .../com/jero/common/util/ReflectHelper.java | 17 ++ .../common/util/dynamic/db/DbTypeUtils.java | 39 +++ .../common/util/dynamic/db/DynamicDBUtil.java | 3 +- .../common/util/filter/FileTypeFilter.java | 164 +++++++++++++ .../com/jero/common/util/oss/OssBootUtil.java | 7 + .../common/util/security/SecurityTools.java | 5 +- .../util/security/entity/SecurityResp.java | 2 +- .../java/com/jero/config/DruidConfig.java | 12 +- .../java/com/jero/config/StaticConfig.java | 5 + .../jero/config/mybatis/JeroTenantParser.java | 130 ---------- .../config/mybatis/MybatisPlusConfig.java | 142 ----------- .../config/mybatis/MybatisPlusSaasConfig.java | 70 ++++++ .../com/jero/config/shiro/ShiroConfig.java | 4 +- .../com/jero/config/shiro/ShiroRealm.java | 13 +- .../jero/config/shiro/filters/JwtFilter.java | 7 +- .../interceptor/SignAuthConfiguration.java | 26 ++ .../sign/interceptor/SignAuthInterceptor.java | 73 ++++++ .../BodyReaderHttpServletRequestWrapper.java | 107 ++++++++ .../com/jero/config/sign/util/HttpUtils.java | 184 ++++++++++++++ .../com/jero/config/sign/util/SignUtil.java | 56 +++++ .../modules/base/mapper/BaseCommonMapper.java | 4 +- .../jero-boot-base-generater-core/pom.xml | 2 +- .../jero-boot-base-generater/pom.xml | 2 +- .../jero-boot-base-tools/pom.xml | 8 +- .../mqtoken/TransmitUserTokenFilter.java | 43 ++++ .../config/mqtoken/UserTokenContext.java | 22 ++ .../jero/common/constant/CacheConstant.java | 11 +- jero-boot/jero-boot-base/pom.xml | 2 +- jero-boot/jero-boot-module-demo/pom.xml | 2 +- .../modules/demo/test/entity/JeroDemo.java | 3 + .../demo/test/mapper/xml/JeroDemoMapper.xml | 6 +- jero-boot/jero-boot-module-system/Dockerfile | 4 +- jero-boot/jero-boot-module-system/pom.xml | 6 +- .../api/controller/SystemAPIController.java | 220 ++++++++++++----- .../service/impl/QuartzJobServiceImpl.java | 6 + .../controller/SysAnnouncementController.java | 9 + .../controller/SysDepartController.java | 10 +- .../system/controller/SysDictController.java | 65 ++--- .../controller/SysDictItemController.java | 8 +- .../controller/SysTenantController.java | 25 +- .../system/controller/SysUserController.java | 57 ++--- .../controller/SysUserOnlineController.java | 128 ++++++++++ .../modules/system/mapper/SysDictMapper.java | 42 +++- .../modules/system/mapper/SysUserMapper.java | 1 + .../system/mapper/xml/SysDictMapper.xml | 56 ++++- .../system/mapper/xml/SysLogMapper.xml | 42 ++-- .../system/service/ISysDictService.java | 38 ++- .../system/service/ISysTenantService.java | 27 ++ .../system/service/impl/LoginServiceImpl.java | 29 ++- .../system/service/impl/SysBaseApiImpl.java | 84 +++++++ .../service/impl/SysDictServiceImpl.java | 38 +++ .../service/impl/SysLogServiceImpl.java | 5 +- .../service/impl/SysTenantServiceImpl.java | 43 +++- .../jero/modules/system/util/XSSUtils.java | 44 ++++ .../modules/system/vo/SysUserOnlineVO.java | 60 +++++ jero-boot/jero-boot-single-startup/pom.xml | 2 +- .../src/main/resources/application-dev.yml | 13 +- .../src/main/resources/application-prod.yml | 17 +- .../src/main/resources/application-test.yml | 11 +- .../src/main/resources/banner.txt | 2 +- .../jero-boot-starter-cloud/nacos/jeecg.yaml} | 2 +- .../nacos/jero-dev.yaml | 50 +++- .../nacos/jero-gateway-router.json | 16 +- .../jero-boot-starter-cloud}/pom.xml | 7 +- .../java/com/jero/config/FeignConfig.java | 161 ++++++++++++ .../cloud/config/PersonBeanConfiguration.java | 0 .../cloud/feign/IJeroFeignService.java | 2 +- .../cloud/feign/impl/JeroFeignService.java | 4 +- .../src/main/resources/bootstrap.yml | 0 .../jero-boot-starter-job/pom.xml | 2 +- .../jero-boot-starter-lock/pom.xml | 2 +- .../jero-boot-starter-rabbitmq/pom.xml | 2 +- .../rabbitmq/client/RabbitMqClient.java | 16 +- .../rabbitmq/config/RabbitMqConfig.java | 13 +- .../rabbitmq/core/BaseRabbiMqHandler.java | 4 + jero-boot/jero-boot-starter/pom.xml | 3 +- .../java/com/jero/config/FeignConfig.java | 76 ------ .../jero-cloud-gateway/Dockerfile | 4 +- .../jero-cloud-gateway/pom.xml | 17 +- .../filter/SentinelFilterContextConfig.java | 24 ++ .../com/jero/handler/LoderRouderHandler.java | 4 +- .../com/jero/loader/DynamicRouteLoader.java | 3 + .../jero-cloud-monitor/pom.xml | 2 +- .../jero-cloud-sentinel/pom.xml | 111 +++++++++ .../JeroSentinelDashboardApplication.java | 49 ++++ .../src/main/resources/application.properties | 28 +++ .../jero-cloud-system-start/Dockerfile | 4 +- .../jero-cloud-system-start/pom.xml | 6 +- .../jero-cloud-xxljob/Dockerfile | 4 +- .../jero-cloud-xxljob/pom.xml | 2 +- jero-boot/jero-cloud-module/pom.xml | 4 +- jero-boot/pom.xml | 36 ++- 113 files changed, 3031 insertions(+), 721 deletions(-) create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DictModelMany.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/PathMatcherUtil.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DbTypeUtils.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/filter/FileTypeFilter.java delete mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/JeroTenantParser.java delete mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusConfig.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusSaasConfig.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthConfiguration.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthInterceptor.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/BodyReaderHttpServletRequestWrapper.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/HttpUtils.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/SignUtil.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/TransmitUserTokenFilter.java create mode 100644 jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/UserTokenContext.java create mode 100644 jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserOnlineController.java create mode 100644 jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/util/XSSUtils.java create mode 100644 jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/vo/SysUserOnlineVO.java rename jero-boot/{jero-cloud-module/jero-cloud-feign-config/nacos/jero.yaml => jero-boot-starter/jero-boot-starter-cloud/nacos/jeecg.yaml} (99%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/nacos/jero-dev.yaml (81%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/nacos/jero-gateway-router.json (82%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/pom.xml (90%) create mode 100644 jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/config/FeignConfig.java rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/src/main/java/com/jero/starter/cloud/config/PersonBeanConfiguration.java (100%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java (70%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java (97%) rename jero-boot/{jero-cloud-module/jero-cloud-feign-config => jero-boot-starter/jero-boot-starter-cloud}/src/main/resources/bootstrap.yml (100%) delete mode 100644 jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/config/FeignConfig.java create mode 100644 jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/filter/SentinelFilterContextConfig.java create mode 100644 jero-boot/jero-cloud-module/jero-cloud-sentinel/pom.xml create mode 100644 jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/java/com.alibaba.csp.sentinel.dashboard/JeroSentinelDashboardApplication.java create mode 100644 jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/resources/application.properties diff --git a/jero-boot/README.md b/jero-boot/README.md index c7abfa8c..c34a14d0 100644 --- a/jero-boot/README.md +++ b/jero-boot/README.md @@ -1,7 +1,7 @@ jero-boot 低代码开发平台 =============== -当前最新版本: 2.4.3(发布日期:20210126) +当前最新版本: 2.4.6(发布日期:20220405) ## 后端技术架构 diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/pom.xml index a2a9f17a..dc65c8e4 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/pom.xml @@ -5,7 +5,7 @@ jero-boot-base-api com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java index ffc6c3e6..46dab11f 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java @@ -9,10 +9,7 @@ import com.jero.common.system.api.factory.SysBaseAPIFallbackFactory; import com.jero.common.system.vo.*; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @@ -109,6 +106,14 @@ public interface ISysBaseAPI extends CommonAPI { @GetMapping("/sys/api/queryDictItemsByCode") List queryDictItemsByCode(@RequestParam("code") String code); + /** + * 获取有效的数据字典项 + * @param code + * @return + */ + @GetMapping("/sys/api/queryEnableDictItemsByCode") + public List queryEnableDictItemsByCode(@RequestParam("code") String code); + /** 11查询所有的父级字典,按照create_time排序 */ @GetMapping("/sys/api/queryAllDict") List queryAllDict(); @@ -385,30 +390,31 @@ public interface ISysBaseAPI extends CommonAPI { * @return */ @GetMapping("/sys/api/queryUsersByUsernames") - List queryUsersByUsernames(String usernames); + List queryUsersByUsernames(@RequestParam("usernames") String usernames); /** * 37根据多个用户ID(逗号分隔),查询返回多个用户信息 * @param ids * @return */ - @GetMapping("/sys/api/queryUsersByIds") - List queryUsersByIds(String ids); + @RequestMapping("/sys/api/queryUsersByIds") + List queryUsersByIds(@RequestParam("ids") String ids); /** * 38根据多个部门编码(逗号分隔),查询返回多个部门信息 * @param orgCodes * @return */ - @GetMapping("/sys/api/queryDepartsByOrgcodes") - List queryDepartsByOrgcodes(String orgCodes); + @RequestMapping("/sys/api/queryDepartsByOrgcodes") + List queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes); + /** * 39根据多个部门编码(逗号分隔),查询返回多个部门信息 * @param ids * @return */ @GetMapping("/sys/api/queryDepartsByOrgIds") - List queryDepartsByOrgIds(String ids); + List queryDepartsByOrgIds(@RequestParam("ids") String ids); /** * 40发送邮件消息 @@ -445,4 +451,81 @@ public interface ISysBaseAPI extends CommonAPI { */ @GetMapping("/sys/api/getDeptUserByOrgCode") List getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode); + + /** + * 42 查询分类字典翻译 + */ + @GetMapping("/sys/api/loadCategoryDictItem") + List loadCategoryDictItem(@RequestParam("ids") String ids); + + /** + * 43 根据字典code加载字典text + * + * @param dictCode 顺序:tableName,text,code + * @param keys 要查询的key + * @return + */ + @GetMapping("/sys/api/loadDictItem") + List loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys); + + /** + * 44 根据字典code查询字典项 + * + * @param dictCode 顺序:tableName,text,code + * @param dictCode 要查询的key + * @return + */ + @GetMapping("/sys/api/getDictItems") + List getDictItems(@RequestParam("dictCode") String dictCode); + + /** + * 45 根据多个字典code查询多个字典项 + * + * @param dictCodeList + * @return key = dictCode ; value=对应的字典项 + */ + @RequestMapping("/sys/api/getManyDictItems") + Map> getManyDictItems(@RequestParam("dictCodeList") List dictCodeList); + + /** + * 46 【JSearchSelectTag下拉搜索组件专用接口】 + * 大数据量的字典表 走异步加载 即前端输入内容过滤数据 + * + * @param dictCode 字典code格式:table,text,code + * @param keyword 过滤关键字 + * @return + */ + @GetMapping("/sys/api/loadDictItemByKeyword") + List loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize); + + /** + * 47 根据多个部门id(逗号分隔),查询返回多个部门信息 + * @param ids + * @return + */ + @GetMapping("/sys/api/queryDepartsByIds") + List queryDepartsByIds(@RequestParam("ids") String ids); + + /** + * 48 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割 + * @param dictCodes + * @param keys + * @return + */ + @Override + @GetMapping("/sys/api/translateManyDict") + Map> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys); + + /** + * 49 字典表的 翻译,可批量 + * @param table + * @param text + * @param code + * @param keys 多个用逗号分割 + * @return + */ + @Override + @GetMapping("/sys/api/translateDictFromTableByKeys") + List translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys); + } diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/fallback/SysBaseAPIFallback.java b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/fallback/SysBaseAPIFallback.java index 14fe0152..d7ba9812 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/fallback/SysBaseAPIFallback.java +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/common/system/api/fallback/SysBaseAPIFallback.java @@ -72,6 +72,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI { return null; } + @Override + public List queryEnableDictItemsByCode(String code) { + return null; + } + @Override public List queryAllDict() { return null; @@ -255,6 +260,22 @@ public class SysBaseAPIFallback implements ISysBaseAPI { public List queryDepartsByOrgcodes(String orgCodes) { return null; } + + @Override + public List queryDepartsByIds(String ids) { + return null; + } + + @Override + public Map> translateManyDict(String dictCodes, String keys) { + return null; + } + + @Override + public List translateDictFromTableByKeys(String table, String text, String code, String keys) { + return null; + } + @Override public void sendEmailMsg(String email,String title,String content) { @@ -279,4 +300,29 @@ public class SysBaseAPIFallback implements ISysBaseAPI { public List queryDepartsByOrgIds(String ids) { return null; } + + @Override + public List loadCategoryDictItem(String ids) { + return null; + } + + @Override + public List loadDictItem(String dictCode, String keys) { + return null; + } + + @Override + public List getDictItems(String dictCode) { + return null; + } + + @Override + public Map> getManyDictItems(List dictCodeList) { + return null; + } + + @Override + public List loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) { + return null; + } } diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/config/FeignConfig.java b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/config/FeignConfig.java index 5cfcef31..1e6e6dbd 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/config/FeignConfig.java +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-cloud-api/src/main/java/com/jero/config/FeignConfig.java @@ -1,25 +1,48 @@ package com.jero.config; -import feign.Feign; -import feign.Logger; -import feign.RequestInterceptor; -import feign.codec.Encoder; -import feign.form.spring.SpringFormEncoder; -import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.SortedMap; + +import javax.servlet.http.HttpServletRequest; + import com.jero.common.constant.CommonConstant; +import com.jero.common.util.DateUtils; +import com.jero.common.util.PathMatcherUtil; +import com.jero.common.config.mqtoken.UserTokenContext; +import com.jero.config.sign.interceptor.SignAuthConfiguration; +import com.jero.config.sign.util.HttpUtils; +import com.jero.config.sign.util.SignUtil; import org.springframework.beans.factory.ObjectFactory; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; +import org.springframework.http.MediaType; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer; + +import feign.Feign; +import feign.Logger; +import feign.RequestInterceptor; +import feign.codec.Decoder; +import feign.codec.Encoder; +import feign.form.spring.SpringFormEncoder; +import lombok.extern.slf4j.Slf4j; @ConditionalOnClass(Feign.class) @@ -34,13 +57,42 @@ public class FeignConfig { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (null != attributes) { HttpServletRequest request = attributes.getRequest(); - log.info("Feign request: {}", request.getRequestURI()); + log.debug("Feign request: {}", request.getRequestURI()); // 将token信息放入header中 String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); - if(token==null){ + if(token==null || "".equals(token)){ token = request.getParameter("token"); } - log.info("Feign request token: {}", token); + log.debug("Feign request token: {}", token); + requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); + + //根据URL地址过滤请求 【字典表参数签名验证】 + if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList),requestTemplate.path())) { + try { + log.info("============================ [begin] fegin api url ============================"); + log.info(requestTemplate.path()); + log.info(requestTemplate.method()); + String queryLine = requestTemplate.queryLine(); + if(queryLine!=null && queryLine.startsWith("?")){ + queryLine = queryLine.substring(1); + } + log.info(queryLine); + if(requestTemplate.body()!=null){ + log.info(new String(requestTemplate.body())); + } + SortedMap allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method()); + String sign = SignUtil.getParamsSign(allParams); + log.info(" Feign request params sign: {}",sign); + log.info("============================ [end] fegin api url ============================"); + requestTemplate.header(CommonConstant.X_SIGN, sign); + requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString()); + } catch (IOException e) { + e.printStackTrace(); + } + } + }else{ + String token = UserTokenContext.getToken(); + log.debug("Feign request token: {}", token); requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); } }; @@ -72,4 +124,42 @@ public class FeignConfig { public Encoder multipartFormEncoder(ObjectFactory messageConverters) { return new SpringFormEncoder(new SpringEncoder(messageConverters)); } + + // update-begin--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ---------- + @Bean + public Encoder feignEncoder() { + return new SpringEncoder(feignHttpMessageConverter()); + } + + @Bean + public Decoder feignDecoder() { + return new SpringDecoder(feignHttpMessageConverter()); + } + + /** + * 设置解码器为fastjson + * + * @return + */ + private ObjectFactory feignHttpMessageConverter() { + final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter()); + return () -> httpMessageConverters; + } + + private FastJsonHttpMessageConverter getFastJsonConverter() { + FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); + + List supportedMediaTypes = new ArrayList<>(); + MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE); + supportedMediaTypes.add(mediaTypeJson); + converter.setSupportedMediaTypes(supportedMediaTypes); + FastJsonConfig config = new FastJsonConfig(); + config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer()); + config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); + converter.setFastJsonConfig(config); + + return converter; + } + // update-end--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ---------- + } diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/pom.xml index 85edf930..daec5360 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/pom.xml @@ -5,7 +5,7 @@ jero-boot-base-api com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java index d0579f51..a2a56fec 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java +++ b/jero-boot/jero-boot-base/jero-boot-base-api/jero-system-local-api/src/main/java/com/jero/common/system/api/ISysBaseAPI.java @@ -305,4 +305,46 @@ public interface ISysBaseAPI extends CommonAPI { * @param orgCode */ List getDeptUserByOrgCode(String orgCode); + + + /** + * 查询分类字典翻译 + */ + List loadCategoryDictItem(String ids); + + /** + * 根据字典code加载字典text + * + * @param dictCode 顺序:tableName,text,code + * @param keys 要查询的key + * @return + */ + List loadDictItem(String dictCode, String keys); + + /** + * 根据字典code查询字典项 + * + * @param dictCode 顺序:tableName,text,code + * @param dictCode 要查询的key + * @return + */ + List getDictItems(String dictCode); + + /** + * 根据多个字典code查询多个字典项 + * @param dictCodeList + * @return key = dictCode ; value=对应的字典项 + */ + Map> getManyDictItems(List dictCodeList); + + /** + * 【JSearchSelectTag下拉搜索组件专用接口】 + * 大数据量的字典表 走异步加载 即前端输入内容过滤数据 + * + * @param dictCode 字典code格式:table,text,code + * @param keyword 过滤关键字 + * @return + */ + List loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize); + } diff --git a/jero-boot/jero-boot-base/jero-boot-base-api/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-api/pom.xml index a71b27b3..113a5a5c 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-api/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-api/pom.xml @@ -5,7 +5,7 @@ jero-boot-base com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-core/pom.xml index fd9ff99a..4828d9e7 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-core/pom.xml @@ -4,7 +4,7 @@ com.jero.boot jero-boot-base - 2.4.3 + 2.4.6 4.0.0 @@ -14,7 +14,7 @@ aliyun aliyun Repository - http://maven.aliyun.com/nexus/content/groups/public + https://maven.aliyun.com/repository/public false @@ -22,7 +22,7 @@ jeecg jeecg Repository - http://maven.jeecg.org/nexus/content/repositories/jeecg + https://maven.jeecg.org/nexus/content/repositories/jeecg false @@ -108,6 +108,7 @@ ${dynamic-datasource-spring-boot-starter.version} + mysql diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/api/CommonAPI.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/api/CommonAPI.java index e76148d0..bf7df1f2 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/api/CommonAPI.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/api/CommonAPI.java @@ -3,6 +3,7 @@ package com.jero.common.api; import com.jero.common.system.vo.*; import java.util.List; +import java.util.Map; import java.util.Set; public interface CommonAPI { @@ -85,6 +86,13 @@ public interface CommonAPI { */ public List queryDictItemsByCode(String code); + /** + * 获取有效的数据字典项 + * @param code + * @return + */ + public List queryEnableDictItemsByCode(String code); + /** * 13获取表数据字典 * @param table @@ -94,4 +102,21 @@ public interface CommonAPI { */ List queryTableDictItemsByCode(String table, String text, String code); + /** + * 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割 + * @param dictCodes 例如:user_status,sex + * @param keys 例如:1,2,0 + * @return + */ + Map> translateManyDict(String dictCodes, String keys); + + /** + * 15 字典表的 翻译,可批量 + * @param table + * @param text + * @param code + * @param keys 多个用逗号分割 + * @return + */ + List translateDictFromTableByKeys(String table, String text, String code, String keys); } diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/aspect/DictAspect.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/aspect/DictAspect.java index 0b6079b7..0ddc899b 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/aspect/DictAspect.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/aspect/DictAspect.java @@ -1,5 +1,6 @@ package com.jero.common.aspect; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.fasterxml.jackson.annotation.JsonFormat; @@ -14,7 +15,7 @@ import com.jero.common.api.CommonAPI; import com.jero.common.api.vo.Result; import com.jero.common.aspect.annotation.Dict; import com.jero.common.constant.CommonConstant; -import com.jero.modules.base.service.BaseCommonService; +import com.jero.common.system.vo.DictModel; import com.jero.common.util.oConvertUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -22,9 +23,11 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; + +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; /** * @Description: 字典aop类 @@ -49,14 +52,14 @@ public class DictAspect { @Around("excudeService()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { - long time1=System.currentTimeMillis(); + long time1=System.currentTimeMillis(); Object result = pjp.proceed(); long time2=System.currentTimeMillis(); log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms"); long start=System.currentTimeMillis(); this.parseDictText(result); long end=System.currentTimeMillis(); - log.debug("解析注入JSON数据 耗时"+(end-start)+"ms"); + log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms"); return result; } @@ -86,32 +89,46 @@ public class DictAspect { if (result instanceof Result) { if (((Result) result).getResult() instanceof IPage) { List items = new ArrayList<>(); + + //step.1 筛选出加了 Dict 注解的字段列表 + List dictFieldList = new ArrayList<>(); + // 字典数据列表, key = 字典code,value=数据列表 + Map> dataListMap = new HashMap<>(); + for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) { ObjectMapper mapper = new ObjectMapper(); String json="{}"; try { //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat - json = mapper.writeValueAsString(record); + json = mapper.writeValueAsString(record); } catch (JsonProcessingException e) { log.error("json解析失败"+e.getMessage(),e); } JSONObject item = JSONObject.parseObject(json); //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ //for (Field field : record.getClass().getDeclaredFields()) { + // 遍历所有字段,把字典Code取出来,放到 map 里 for (Field field : oConvertUtils.getAllFields(record)) { - //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ + String value = item.getString(field.getName()); + if (oConvertUtils.isEmpty(value)) { + continue; + } + //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ if (field.getAnnotation(Dict.class) != null) { + if (!dictFieldList.contains(field)) { + dictFieldList.add(field); + } String code = field.getAnnotation(Dict.class).dicCode(); String text = field.getAnnotation(Dict.class).dicText(); String table = field.getAnnotation(Dict.class).dictTable(); - String key = String.valueOf(item.get(field.getName())); - //翻译字典值对应的txt - String textValue = translateDictValue(code, text, table, key); - - log.debug(" 字典Val : "+ textValue); - log.debug(" __翻译字典字段__ "+field.getName() + CommonConstant.DICT_TEXT_SUFFIX+": "+ textValue); - item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); + List dataList; + String dictCode = code; + if (!StringUtils.isEmpty(table)) { + dictCode = String.format("%s,%s,%s", table, text, code); + } + dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>()); + this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(","))); } //date类型默认转换string格式化日期 if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){ @@ -121,12 +138,194 @@ public class DictAspect { } items.add(item); } + + //step.2 调用翻译方法,一次性翻译 + Map> translText = this.translateAllDict(dataListMap); + + //step.3 将翻译结果填充到返回结果里 + for (JSONObject record : items) { + for (Field field : dictFieldList) { + String code = field.getAnnotation(Dict.class).dicCode(); + String text = field.getAnnotation(Dict.class).dicText(); + String table = field.getAnnotation(Dict.class).dictTable(); + + String fieldDictCode = code; + if (!StringUtils.isEmpty(table)) { + fieldDictCode = String.format("%s,%s,%s", table, text, code); + } + + String value = record.getString(field.getName()); + if (oConvertUtils.isNotEmpty(value)) { + List dictModels = translText.get(fieldDictCode); + if(dictModels==null || dictModels.size()==0){ + continue; + } + + String textValue = this.translDictText(dictModels, value); + log.debug(" 字典Val : " + textValue); + log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue); + + // TODO-sun 测试输出,待删 + log.debug(" ---- dictCode: " + fieldDictCode); + log.debug(" ---- value: " + value); + log.debug(" ----- text: " + textValue); + log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels)); + + record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); + } + } + } + ((IPage) ((Result) result).getResult()).setRecords(items); } } } + /** + * list 去重添加 + */ + private void listAddAllDeduplicate(List dataList, List addList) { + // 筛选出dataList中没有的数据 + List filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList()); + dataList.addAll(filterList); + } + + /** + * 一次性把所有的字典都翻译了 + * 1. 所有的普通数据字典的所有数据只执行一次SQL + * 2. 表字典相同的所有数据只执行一次SQL + * @param dataListMap + * @return + */ + private Map> translateAllDict(Map> dataListMap) { + // 翻译后的字典文本,key=dictCode + Map> translText = new HashMap<>(); + // 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询) + List needTranslData = new ArrayList<>(); + //step.1 先通过redis中获取缓存字典数据 + for (String dictCode : dataListMap.keySet()) { + List dataList = dataListMap.get(dictCode); + if (dataList.size() == 0) { + continue; + } + // 表字典需要翻译的数据 + List needTranslDataTable = new ArrayList<>(); + for (String s : dataList) { + String data = s.trim(); + if (data.length() == 0) { + continue; //跳过循环 + } + if (dictCode.contains(",")) { + String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data); + if (redisTemplate.hasKey(keyString)) { + try { + String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); + List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); + list.add(new DictModel(data, text)); + } catch (Exception e) { + log.warn(e.getMessage()); + } + } else if (!needTranslDataTable.contains(data)) { + // 去重添加 + needTranslDataTable.add(data); + } + } else { + String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data); + if (redisTemplate.hasKey(keyString)) { + try { + String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); + List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); + list.add(new DictModel(data, text)); + } catch (Exception e) { + log.warn(e.getMessage()); + } + } else if (!needTranslData.contains(data)) { + // 去重添加 + needTranslData.add(data); + } + } + + } + //step.2 调用数据库翻译表字典 + if (needTranslDataTable.size() > 0) { + String[] arr = dictCode.split(","); + String table = arr[0], text = arr[1], code = arr[2]; + String values = String.join(",", needTranslDataTable); + log.info("translateDictFromTableByKeys.dictCode:" + dictCode); + log.info("translateDictFromTableByKeys.values:" + values); + List texts = commonAPI.translateDictFromTableByKeys(table, text, code, values); + log.info("translateDictFromTableByKeys.result:" + texts); + List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); + list.addAll(texts); + + // 做 redis 缓存 + for (DictModel dict : texts) { + String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue()); + try { + redisTemplate.opsForValue().set(redisKey, dict.getText()); + } catch (Exception e) { + log.warn(e.getMessage(), e); + } + } + } + } + + //step.3 调用数据库进行翻译普通字典 + if (needTranslData.size() > 0) { + List dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{})); + // 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典 + List filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList()); + String dictCodes = String.join(",", filterDictCodes); + String values = String.join(",", needTranslData); + log.info("translateManyDict.dictCodes:" + dictCodes); + log.info("translateManyDict.values:" + values); + Map> manyDict = commonAPI.translateManyDict(dictCodes, values); + log.info("translateManyDict.result:" + manyDict); + for (String dictCode : manyDict.keySet()) { + List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); + List newList = manyDict.get(dictCode); + list.addAll(newList); + + // 做 redis 缓存 + for (DictModel dict : newList) { + String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue()); + try { + redisTemplate.opsForValue().set(redisKey, dict.getText()); + } catch (Exception e) { + log.warn(e.getMessage(), e); + } + } + } + } + return translText; + } + + /** + * 字典值替换文本 + * + * @param dictModels + * @param values + * @return + */ + private String translDictText(List dictModels, String values) { + List result = new ArrayList<>(); + + // 允许多个逗号分隔,允许传数组对象 + String[] splitVal = values.split(","); + for (String val : splitVal) { + String dictText = val; + for (DictModel dict : dictModels) { + if (val.equals(dict.getValue())) { + dictText = dict.getText(); + break; + } + } + result.add(dictText); + } + return String.join(",", result); + } + /** * 翻译字典文本 * @param code @@ -135,6 +334,7 @@ public class DictAspect { * @param key * @return */ + @Deprecated private String translateDictValue(String code, String text, String table, String key) { if(oConvertUtils.isEmpty(key)) { return null; @@ -186,3 +386,4 @@ public class DictAspect { } } + diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/constant/CommonConstant.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/constant/CommonConstant.java index 612ca8cb..46c84f25 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/constant/CommonConstant.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/constant/CommonConstant.java @@ -290,6 +290,8 @@ public interface CommonConstant { public final static String X_ACCESS_TOKEN = "X-Access-Token"; + public final static String X_SIGN = "X-Sign"; + public final static String X_TIMESTAMP = "X-TIMESTAMP"; /** * 多租户 请求头 diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/es/JeroElasticsearchTemplate.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/es/JeroElasticsearchTemplate.java index 56798b08..8cc46d67 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/es/JeroElasticsearchTemplate.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/es/JeroElasticsearchTemplate.java @@ -26,6 +26,8 @@ public class JeroElasticsearchTemplate { /** es服务地址 */ private String baseUrl; private final String FORMAT_JSON = "format=json"; + /** Elasticsearch 的版本号 */ + private String version = null; // ElasticSearch 最大可返回条目数 public static final int ES_MAX_SIZE = 10000; @@ -37,15 +39,32 @@ public class JeroElasticsearchTemplate { // 验证配置的ES地址是否有效 if (checkEnabled) { try { + this.getElasticsearchVersion(); RestUtil.get(this.getBaseUrl().toString()); log.info("ElasticSearch 服务连接成功"); + log.info("ElasticSearch version: " + this.version); } catch (Exception e) { + this.version = ""; log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!"); } } } } + /** + * 获取 Elasticsearch 的版本号信息,失败返回null + */ + private void getElasticsearchVersion() { + if (this.version == null) { + String url = this.getBaseUrl().toString(); + JSONObject result = RestUtil.get(url); + if (result != null) { + JSONObject v = result.getJSONObject("version"); + this.version = v.getString("number"); + } + } + } + public StringBuilder getBaseUrl(String indexName, String typeName) { typeName = typeName.trim().toLowerCase(); return this.getBaseUrl(indexName).append("/").append(typeName); @@ -185,6 +204,11 @@ public class JeroElasticsearchTemplate { */ public JSONObject getIndexMapping(String indexName, String typeName) { String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString(); + // 针对 es 7.x 版本做兼容 + this.getElasticsearchVersion(); + if (oConvertUtils.isNotEmpty(this.version) && this.version.startsWith("7")) { + url += "&include_type_name=true"; + } log.info("getIndexMapping-url:" + url); /* * 参考返回JSON结构: diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryCondition.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryCondition.java index 448449ac..6ca4e165 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryCondition.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryCondition.java @@ -5,9 +5,15 @@ import java.io.Serializable; public class QueryCondition implements Serializable { private static final long serialVersionUID = 4740166316629191651L; - + private String field; + /** 组件的类型(例如:input、select、radio) */ private String type; + /** + * 对应的数据库字段的类型 + * 支持:int、bigDecimal、short、long、float、double、boolean + */ + private String dbType; private String rule; private String val; @@ -27,6 +33,14 @@ public class QueryCondition implements Serializable { this.type = type; } + public String getDbType() { + return dbType; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + public String getRule() { return rule; } @@ -49,7 +63,7 @@ public class QueryCondition implements Serializable { if(field == null || "".equals(field)){ return ""; } - sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.val); + sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.dbType).append(" ").append(this.val); return sb.toString(); } } diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryGenerator.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryGenerator.java index a2ce164b..a902e202 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryGenerator.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/query/QueryGenerator.java @@ -1,21 +1,5 @@ package com.jero.common.system.query; -import com.alibaba.fastjson.JSON; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.beanutils.PropertyUtils; -import com.jero.common.constant.CommonConstant; -import com.jero.common.constant.DataBaseConstant; -import com.jero.common.system.util.JeroDataAutorUtils; -import com.jero.common.system.util.JwtUtil; -import com.jero.common.system.vo.SysPermissionDataRuleModel; -import com.jero.common.util.CommonUtils; -import com.jero.common.util.DateUtils; -import com.jero.common.util.SqlInjectionUtil; -import com.jero.common.util.oConvertUtils; -import org.springframework.util.NumberUtils; - import java.beans.PropertyDescriptor; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; @@ -28,6 +12,25 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.apache.commons.beanutils.PropertyUtils; +import com.jero.common.constant.CommonConstant; +import com.jero.common.constant.DataBaseConstant; +import com.jero.common.system.util.JeroDataAutorUtils; +import com.jero.common.system.util.JwtUtil; +import com.jero.common.system.vo.SysPermissionDataRuleModel; +import com.jero.common.util.CommonUtils; +import com.jero.common.util.DateUtils; +import com.jero.common.util.SqlInjectionUtil; +import com.jero.common.util.oConvertUtils; +import org.springframework.util.NumberUtils; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; + +import lombok.extern.slf4j.Slf4j; + @Slf4j public class QueryGenerator { public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN"; @@ -238,12 +241,12 @@ public class QueryGenerator { // queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(column)); String columnStr = oConvertUtils.camelToUnderline(column); String[] columnArray = columnStr.split(","); - queryWrapper.orderByAsc(columnArray); + queryWrapper.orderByAsc(Arrays.asList(columnArray)); } else { // queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(column)); String columnStr = oConvertUtils.camelToUnderline(column); String[] columnArray = columnStr.split(","); - queryWrapper.orderByDesc(columnArray); + queryWrapper.orderByDesc(Arrays.asList(columnArray)); } //update-end--Author:scott Date:20210531 for:36 多条件排序无效问题修正------- } diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DictModelMany.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DictModelMany.java new file mode 100644 index 00000000..e761b2c5 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DictModelMany.java @@ -0,0 +1,18 @@ +package com.jero.common.system.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 查询多个字典时用到 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class DictModelMany extends DictModel { + + /** + * 字典code,根据多个字段code查询时才用到,用于区分不同的字典选项 + */ + private String dictCode; + +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DynamicDataSourceModel.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DynamicDataSourceModel.java index 38b46040..cdb36aa4 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DynamicDataSourceModel.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/system/vo/DynamicDataSourceModel.java @@ -36,10 +36,6 @@ public class DynamicDataSourceModel { * 数据源地址 */ private java.lang.String dbUrl; - /** - * 数据库名称 - */ - private java.lang.String dbName; /** * 用户名 */ diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/CommonUtils.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/CommonUtils.java index 05c6e199..7f1390d8 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/CommonUtils.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/CommonUtils.java @@ -1,30 +1,31 @@ package com.jero.common.util; +import java.io.*; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.sql.DataSource; + import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; -import lombok.extern.slf4j.Slf4j; import com.jero.common.constant.CommonConstant; import com.jero.common.constant.DataBaseConstant; import com.jero.common.exception.JeroBootException; +import com.jero.common.util.filter.FileTypeFilter; import com.jero.common.util.oss.OssBootUtil; import org.jeecgframework.poi.util.PoiPublicUtil; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; -import javax.sql.DataSource; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; + +import lombok.extern.slf4j.Slf4j; @Slf4j public class CommonUtils { @@ -134,6 +135,9 @@ public class CommonUtils { */ public static String uploadLocal(MultipartFile mf,String bizPath, String uploadpath){ try { + //update-begin-author:liusq date:20210809 for: 过滤上传文件类型 + FileTypeFilter.fileTypeFilter(mf); + //update-end-author:liusq date:20210809 for: 过滤上传文件类型 String ctxPath = uploadpath; String fileName = null; File file = new File(ctxPath + File.separator + bizPath + File.separator ); @@ -162,11 +166,20 @@ public class CommonUtils { return dbpath; } catch (IOException e) { log.error(e.getMessage(), e); + } catch (Exception e) { + log.error(e.getMessage(), e); } return ""; } /** 当前系统数据库类型 */ private static String DB_TYPE = ""; + private static DbType dbTypeEnum = null; + + /** + * 全局获取平台数据库类型(作废了) + * @return + */ + @Deprecated public static String getDatabaseType() { if(oConvertUtils.isNotEmpty(DB_TYPE)){ return DB_TYPE; @@ -181,6 +194,24 @@ public class CommonUtils { } } + /** + * 全局获取平台数据库类型(对应mybaisPlus枚举) + * @return + */ + public static DbType getDatabaseTypeEnum() { + if (oConvertUtils.isNotEmpty(dbTypeEnum)) { + return dbTypeEnum; + } + try { + DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class); + dbTypeEnum = JdbcUtils.getDbType(dataSource.getConnection().getMetaData().getURL()); + return dbTypeEnum; + } catch (SQLException e) { + log.warn(e.getMessage(), e); + return null; + } + } + /** * 获取数据库类型 * @param dataSource diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/DateUtils.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/DateUtils.java index 5f8e01cf..4fc23f7c 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/DateUtils.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/DateUtils.java @@ -621,6 +621,10 @@ public class DateUtils extends PropertyEditorSupport { return 0; } + public static Long getCurrentTimestamp() { + return Long.valueOf(DateUtils.yyyymmddhhmmss.get().format(new Date())); + } + /** * String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd * HH:mm:ss“ * @param text String类型的时间值 diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/MinioUtil.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/MinioUtil.java index 080344f7..12efa1a8 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/MinioUtil.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/MinioUtil.java @@ -1,11 +1,11 @@ package com.jero.common.util; +import com.jero.common.util.filter.FileTypeFilter; import io.minio.*; import lombok.extern.slf4j.Slf4j; import com.jero.common.util.filter.StrAttackFilter; import org.springframework.web.multipart.MultipartFile; -import javax.validation.constraints.Null; import java.io.InputStream; import java.net.URLDecoder; @@ -69,6 +69,9 @@ public class MinioUtil { minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build()); log.info("create a new bucket."); } + //update-begin-author:liusq date:20210809 for: 过滤上传文件类型 + FileTypeFilter.fileTypeFilter(file); + //update-end-author:liusq date:20210809 for: 过滤上传文件类型 InputStream stream = file.getInputStream(); // 获取文件名 String orgName = file.getOriginalFilename(); diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/PathMatcherUtil.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/PathMatcherUtil.java new file mode 100644 index 00000000..4de3df74 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/PathMatcherUtil.java @@ -0,0 +1,84 @@ +package com.jero.common.util; + +import java.util.Collection; +import java.util.Map; + +import org.springframework.util.AntPathMatcher; + +/** + * 使用Spring自身提供的地址匹配工具匹配URL + */ +public class PathMatcherUtil { + + public static void main(String[] args) { + String url = "/sys/dict/loadDictOrderByValue/tree,s2,2"; + String p = "/sys/dict/loadDictOrderByValue/*"; + + System.out.println(PathMatcherUtil.match(p,url)); + } + + /** + * 实际验证路径匹配权限 + * + * @param matchPath 权限url + * @param path 访问路径 + * @return 是否拥有权限 + */ + public static boolean match(String matchPath, String path) { + SpringAntMatcher springAntMatcher = new SpringAntMatcher(matchPath, true); + return springAntMatcher.matches(path); + } + + /** + * 实际验证路径匹配权限 + * + * @param list 权限url + * @param path 访问路径 + * @return 是否拥有权限 + */ + public static boolean matches(Collection list, String path) { + for (String s : list) { + SpringAntMatcher springAntMatcher = new SpringAntMatcher(s, true); + if (springAntMatcher.matches(path)) { + return true; + } + } + return false; + } + + /** + * 地址表达式匹配工具 + */ + private static class SpringAntMatcher implements Matcher { + private final AntPathMatcher antMatcher; + private final String pattern; + + private SpringAntMatcher(String pattern, boolean caseSensitive) { + this.pattern = pattern; + this.antMatcher = createMatcher(caseSensitive); + } + + @Override + public boolean matches(String path) { + return this.antMatcher.match(this.pattern, path); + } + + @Override + public Map extractUriTemplateVariables(String path) { + return this.antMatcher.extractUriTemplateVariables(this.pattern, path); + } + + private static AntPathMatcher createMatcher(boolean caseSensitive) { + AntPathMatcher matcher = new AntPathMatcher(); + matcher.setTrimTokens(false); + matcher.setCaseSensitive(caseSensitive); + return matcher; + } + } + + private interface Matcher { + boolean matches(String var1); + + Map extractUriTemplateVariables(String var1); + } +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/ReflectHelper.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/ReflectHelper.java index 0a9d5fe9..268a75db 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/ReflectHelper.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/ReflectHelper.java @@ -192,6 +192,23 @@ public class ReflectHelper { } } + /** + * 获取属性值 + */ + public static Object getFieldVal(String fieldName, Object o) { + try { + // 暴力反射获取属性 + Field filed = o.getClass().getDeclaredField(fieldName); + // 设置反射时取消Java的访问检查,暴力访问 + filed.setAccessible(true); + Object val = filed.get(o); + return val; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /** * 获取属性名数组 */ diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DbTypeUtils.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DbTypeUtils.java new file mode 100644 index 00000000..7ef19146 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DbTypeUtils.java @@ -0,0 +1,39 @@ +package com.jero.common.util.dynamic.db; + +import com.baomidou.mybatisplus.annotation.DbType; + +/** + * 数据库类型判断 + * 【有些数据库引擎是一样的,以达到复用目的】 + */ +public class DbTypeUtils { + + public static boolean dbTypeIsMySQL(DbType dbType) { + return dbTypeIf(dbType, DbType.MYSQL, DbType.MARIADB, DbType.CLICK_HOUSE, DbType.SQLITE); + } + + public static boolean dbTypeIsOracle(DbType dbType) { + return dbTypeIf(dbType, DbType.ORACLE, DbType.ORACLE_12C, DbType.DM); + } + + public static boolean dbTypeIsSQLServer(DbType dbType) { + return dbTypeIf(dbType, DbType.SQL_SERVER, DbType.SQL_SERVER2005); + } + + public static boolean dbTypeIsPostgre(DbType dbType) { + return dbTypeIf(dbType, DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.GAUSS); + } + + /** + * 判断数据库类型 + */ + public static boolean dbTypeIf(DbType dbType, DbType... correctTypes) { + for (DbType type : correctTypes) { + if (type.equals(dbType)) { + return true; + } + } + return false; + } + +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DynamicDBUtil.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DynamicDBUtil.java index d87da3c2..b2cb6af0 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DynamicDBUtil.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/dynamic/db/DynamicDBUtil.java @@ -49,7 +49,7 @@ public class DynamicDBUtil { dataSource.setBreakAfterAcquireFailure(true); dataSource.setConnectionErrorRetryAttempts(0); dataSource.setUsername(dbUser); - dataSource.setMaxWait(60000); + dataSource.setMaxWait(30000); dataSource.setPassword(dbPassword); log.info("******************************************"); @@ -151,6 +151,7 @@ public class DynamicDBUtil { list = findList(dbKey, sql, param); if (oConvertUtils.listIsEmpty(list)) { log.error("Except one, but not find actually"); + return null; } if (list.size() > 1) { log.error("Except one, but more than one actually"); diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/filter/FileTypeFilter.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/filter/FileTypeFilter.java new file mode 100644 index 00000000..03da12f4 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/filter/FileTypeFilter.java @@ -0,0 +1,164 @@ +package com.jero.common.util.filter; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; + +/** + * @Description: TODO + * @author: lsq + * @date: 2021年08月09日 15:29 + */ +public class FileTypeFilter { + + //文件后缀 + private static String[] forbidType = {"jsp","php"}; + + // 初始化文件头类型,不够的自行补充 + final static HashMap fileTypeMap = new HashMap<>(); + + static { + fileTypeMap.put("3c25402070616765206c", "jsp"); + fileTypeMap.put("3c3f7068700a0a2f2a2a0a202a205048", "php"); + /* fileTypeMap.put("ffd8ffe000104a464946", "jpg"); + fileTypeMap.put("89504e470d0a1a0a0000", "png"); + fileTypeMap.put("47494638396126026f01", "gif"); + fileTypeMap.put("49492a00227105008037", "tif"); + fileTypeMap.put("424d228c010000000000", "bmp"); + fileTypeMap.put("424d8240090000000000", "bmp"); + fileTypeMap.put("424d8e1b030000000000", "bmp"); + fileTypeMap.put("41433130313500000000", "dwg"); + fileTypeMap.put("3c21444f435459504520", "html"); + fileTypeMap.put("3c21646f637479706520", "htm"); + fileTypeMap.put("48544d4c207b0d0a0942", "css"); + fileTypeMap.put("696b2e71623d696b2e71", "js"); + fileTypeMap.put("7b5c727466315c616e73", "rtf"); + fileTypeMap.put("38425053000100000000", "psd"); + fileTypeMap.put("46726f6d3a203d3f6762", "eml"); + fileTypeMap.put("d0cf11e0a1b11ae10000", "doc"); + fileTypeMap.put("5374616E64617264204A", "mdb"); + fileTypeMap.put("252150532D41646F6265", "ps"); + fileTypeMap.put("255044462d312e350d0a", "pdf"); + fileTypeMap.put("2e524d46000000120001", "rmvb"); + fileTypeMap.put("464c5601050000000900", "flv"); + fileTypeMap.put("00000020667479706d70", "mp4"); + fileTypeMap.put("49443303000000002176", "mp3"); + fileTypeMap.put("000001ba210001000180", "mpg"); + fileTypeMap.put("3026b2758e66cf11a6d9", "wmv"); + fileTypeMap.put("52494646e27807005741", "wav"); + fileTypeMap.put("52494646d07d60074156", "avi"); + fileTypeMap.put("4d546864000000060001", "mid"); + fileTypeMap.put("504b0304140000000800", "zip"); + fileTypeMap.put("526172211a0700cf9073", "rar"); + fileTypeMap.put("235468697320636f6e66", "ini"); + fileTypeMap.put("504b03040a0000000000", "jar"); + fileTypeMap.put("4d5a9000030000000400", "exe"); + fileTypeMap.put("3c25402070616765206c", "jsp"); + fileTypeMap.put("4d616e69666573742d56", "mf"); + fileTypeMap.put("3c3f786d6c2076657273", "xml"); + fileTypeMap.put("494e5345525420494e54", "sql"); + fileTypeMap.put("7061636b616765207765", "java"); + fileTypeMap.put("406563686f206f66660d", "bat"); + fileTypeMap.put("1f8b0800000000000000", "gz"); + fileTypeMap.put("6c6f67346a2e726f6f74", "properties"); + fileTypeMap.put("cafebabe0000002e0041", "class"); + fileTypeMap.put("49545346030000006000", "chm"); + fileTypeMap.put("04000000010000001300", "mxp"); + fileTypeMap.put("504b0304140006000800", "docx"); + fileTypeMap.put("6431303a637265617465", "torrent"); + fileTypeMap.put("6D6F6F76", "mov"); + fileTypeMap.put("FF575043", "wpd"); + fileTypeMap.put("CFAD12FEC5FD746F", "dbx"); + fileTypeMap.put("2142444E", "pst"); + fileTypeMap.put("AC9EBD8F", "qdf"); + fileTypeMap.put("E3828596", "pwl"); + fileTypeMap.put("2E7261FD", "ram");*/ + } + + /** + * @param fileName + * @return String + * @description 通过文件后缀名获取文件类型 + */ + private static String getFileTypeBySuffix(String fileName) { + return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()); + } + + /** + * 文件类型过滤 + * + * @param file + */ + public static void fileTypeFilter(MultipartFile file) throws Exception { + String suffix = getFileType(file); + for (String type : forbidType) { + if (type.contains(suffix)) { + throw new Exception("上传失败,文件类型异常:" + suffix); + } + } + } + + /** + * 通过读取文件头部获得文件类型 + * + * @param file + * @return 文件类型 + * @throws Exception + */ + + private static String getFileType(MultipartFile file) throws Exception { + String fileExtendName = null; + InputStream is; + try { + //is = new FileInputStream(file); + is = file.getInputStream(); + byte[] b = new byte[10]; + is.read(b, 0, b.length); + String fileTypeHex = String.valueOf(bytesToHexString(b)); + Iterator keyIter = fileTypeMap.keySet().iterator(); + while (keyIter.hasNext()) { + String key = keyIter.next(); + // 验证前5个字符比较 + if (key.toLowerCase().startsWith(fileTypeHex.toLowerCase().substring(0, 5)) + || fileTypeHex.toLowerCase().substring(0, 5).startsWith(key.toLowerCase())) { + fileExtendName = fileTypeMap.get(key); + break; + } + } + // 如果不是上述类型,则判断扩展名 + if (StringUtils.isBlank(fileExtendName)) { + String fileName = file.getOriginalFilename(); + return getFileTypeBySuffix(fileName); + } + is.close(); + return fileExtendName; + } catch (Exception exception) { + throw new Exception(exception.getMessage(), exception); + } + } + + /** + * 获得文件头部字符串 + * + * @param src + * @return + */ + private static String bytesToHexString(byte[] src) { + StringBuilder stringBuilder = new StringBuilder(); + if (src == null || src.length <= 0) { + return null; + } + for (int i = 0; i < src.length; i++) { + int v = src[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString(); + } +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/oss/OssBootUtil.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/oss/OssBootUtil.java index 174835b1..8f5acc04 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/oss/OssBootUtil.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/oss/OssBootUtil.java @@ -6,6 +6,7 @@ import com.aliyun.oss.common.auth.DefaultCredentialProvider; import com.aliyun.oss.model.CannedAccessControlList; import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.PutObjectResult; +import com.jero.common.util.filter.FileTypeFilter; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.util.http.fileupload.FileItemStream; import com.jero.common.util.CommonUtils; @@ -110,6 +111,9 @@ public class OssBootUtil { if("" == orgName){ orgName=file.getName(); } + //update-begin-author:liusq date:20210809 for: 过滤上传文件类型 + FileTypeFilter.fileTypeFilter(file); + //update-end-author:liusq date:20210809 for: 过滤上传文件类型 orgName = CommonUtils.getFileName(orgName); String fileName = orgName.indexOf(".")==-1 ?orgName + "_" + System.currentTimeMillis() @@ -136,6 +140,9 @@ public class OssBootUtil { } catch (IOException e) { e.printStackTrace(); return null; + }catch (Exception e) { + e.printStackTrace(); + return null; } return FILE_URL; } diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/SecurityTools.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/SecurityTools.java index 677f2218..e61e541e 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/SecurityTools.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/SecurityTools.java @@ -8,9 +8,8 @@ import cn.hutool.crypto.asymmetric.RSA; import cn.hutool.crypto.asymmetric.Sign; import cn.hutool.crypto.asymmetric.SignAlgorithm; import cn.hutool.crypto.symmetric.AES; -import cn.hutool.json.JSONObject; import com.jero.common.util.security.entity.*; - +import com.alibaba.fastjson.JSONObject; import javax.crypto.SecretKey; import java.security.KeyPair; @@ -34,7 +33,7 @@ public class SecurityTools { String dencrptValue =aes.decryptStr(data); //log.info("解密后报文"+dencrptValue); - resp.setData(new JSONObject(dencrptValue)); + resp.setData(JSONObject.parseObject(dencrptValue)); boolean verify = sign.verify(dencrptValue.getBytes(), Base64Decoder.decode(signData)); resp.setSuccess(verify); diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/entity/SecurityResp.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/entity/SecurityResp.java index 2d2e99e7..49aa665e 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/entity/SecurityResp.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/common/util/security/entity/SecurityResp.java @@ -1,6 +1,6 @@ package com.jero.common.util.security.entity; -import cn.hutool.json.JSONObject; +import com.alibaba.fastjson.JSONObject; import lombok.Data; @Data diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/DruidConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/DruidConfig.java index 3c4b0e2e..1cba97d1 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/DruidConfig.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/DruidConfig.java @@ -1,8 +1,9 @@ package com.jero.config; -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; -import com.alibaba.druid.util.Utils; +import java.io.IOException; + +import javax.servlet.*; + import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -10,8 +11,9 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import javax.servlet.*; -import java.io.IOException; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.util.Utils; @Configuration @AutoConfigureAfter(DruidDataSourceAutoConfigure.class) diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/StaticConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/StaticConfig.java index d7eb5054..4369ebab 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/StaticConfig.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/StaticConfig.java @@ -20,6 +20,11 @@ public class StaticConfig { @Value(value = "${spring.mail.username}") private String emailFrom; + /** + * 签名密钥串 + */ + @Value(value = "${jero.signatureSecret}") + private String signatureSecret; /*@Bean public void initStatic() { diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/JeroTenantParser.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/JeroTenantParser.java deleted file mode 100644 index 4a3f856d..00000000 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/JeroTenantParser.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.jero.config.mybatis; - -import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; -import net.sf.jsqlparser.expression.BinaryExpression; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.Parenthesis; -import net.sf.jsqlparser.expression.operators.conditional.AndExpression; -import net.sf.jsqlparser.expression.operators.conditional.OrExpression; -import net.sf.jsqlparser.expression.operators.relational.*; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.select.*; - -import java.util.List; - -/** - * 复写租户条件 - */ -public class JeroTenantParser extends TenantSqlParser { - - /** - * @param expression - * @param table - * @return - */ - protected Expression processTableAlias(Expression expression, Table table) { - String tableAliasName; - if (table.getAlias() == null) { - tableAliasName = table.getName(); - } else { - tableAliasName = table.getAlias().getName(); - } - - // in - if (expression instanceof InExpression) { - InExpression in = (InExpression) expression; - if (in.getLeftExpression() instanceof Column) { - setTableAliasNameForColumn((Column) in.getLeftExpression(), tableAliasName); - } - - // 比较操作 - } else if (expression instanceof BinaryExpression) { - BinaryExpression compare = (BinaryExpression) expression; - if (compare.getLeftExpression() instanceof Column) { - setTableAliasNameForColumn((Column) compare.getLeftExpression(), tableAliasName); - } else if (compare.getRightExpression() instanceof Column) { - setTableAliasNameForColumn((Column) compare.getRightExpression(), tableAliasName); - } - - // between - } else if (expression instanceof Between) { - Between between = (Between) expression; - if (between.getLeftExpression() instanceof Column) { - setTableAliasNameForColumn((Column) between.getLeftExpression(), tableAliasName); - } - } - return expression; - } - - private void setTableAliasNameForColumn(Column column, String tableAliasName) { - column.setColumnName(tableAliasName + "." + column.getColumnName()); - } - - /** - * 默认是按 tenant_id=1 按等于条件追加 - * - * @param currentExpression 现有的条件:比如你原来的sql查询条件 - * @param table - * @return - */ - @Override - protected Expression builderExpression(Expression currentExpression, Table table) { - final Expression tenantExpression = this.getTenantHandler().getTenantId(true); - Expression appendExpression; - if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) { - appendExpression = new EqualsTo(); - ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table)); - ((EqualsTo) appendExpression).setRightExpression(tenantExpression); - } else { - appendExpression = processTableAlias(tenantExpression, table); - } - if (currentExpression == null) { - return appendExpression; - } - if (currentExpression instanceof BinaryExpression) { - BinaryExpression binaryExpression = (BinaryExpression) currentExpression; - if (binaryExpression.getLeftExpression() instanceof FromItem) { - processFromItem((FromItem) binaryExpression.getLeftExpression()); - } - if (binaryExpression.getRightExpression() instanceof FromItem) { - processFromItem((FromItem) binaryExpression.getRightExpression()); - } - } else if (currentExpression instanceof InExpression) { - InExpression inExp = (InExpression) currentExpression; - ItemsList rightItems = inExp.getRightItemsList(); - if (rightItems instanceof SubSelect) { - processSelectBody(((SubSelect) rightItems).getSelectBody()); - } - } - if (currentExpression instanceof OrExpression) { - return new AndExpression(new Parenthesis(currentExpression), appendExpression); - } else { - return new AndExpression(currentExpression, appendExpression); - } - } - - @Override - protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) { - FromItem fromItem = plainSelect.getFromItem(); - if (fromItem instanceof Table) { - Table fromTable = (Table) fromItem; - if (!this.getTenantHandler().doTableFilter(fromTable.getName())) { - plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable)); - if (addColumn) { - plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.getTenantHandler().getTenantIdColumn()))); - } - } - } else { - processFromItem(fromItem); - } - List joins = plainSelect.getJoins(); - if (joins != null && joins.size() > 0) { - joins.forEach(j -> { - processJoin(j); - processFromItem(j.getRightItem()); - }); - } - } - -} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusConfig.java deleted file mode 100644 index d90d84df..00000000 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusConfig.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.jero.config.mybatis; - -import com.baomidou.mybatisplus.core.parser.ISqlParser; -import com.baomidou.mybatisplus.core.parser.ISqlParserFilter; -import com.baomidou.mybatisplus.core.toolkit.PluginUtils; -import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; -import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; -import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.LongValue; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.InExpression; -import net.sf.jsqlparser.schema.Column; -import org.apache.ibatis.reflection.MetaObject; -import com.jero.common.util.oConvertUtils; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.ArrayList; -import java.util.List; - -/** - * 单数据源配置(jero.datasource.open = false时生效) - * @Author zhoujf - * - */ -@Configuration -@MapperScan(value={"com.jero.**.mapper*"}) -public class MybatisPlusConfig { - - /** - * tenant_id 字段名 - */ - public static final String tenant_field = "tenant_id"; - - /** - * 有哪些表需要做多租户 这些表需要添加一个字段 ,字段名和tenant_field对应的值一样 - */ - private static final List tenantTable = new ArrayList(); - /** - * ddl 关键字 判断不走多租户的sql过滤 - */ - private static final List DDL_KEYWORD = new ArrayList(); - static { - tenantTable.add("jee_bug_danbiao"); - DDL_KEYWORD.add("alter"); - } - - /** - * 多租户属于 SQL 解析部分,依赖 MP 分页插件 - */ - @Bean - public PaginationInterceptor paginationInterceptor() { - PaginationInterceptor paginationInterceptor = new PaginationInterceptor().setLimit(-1); - //多租户配置 配置后每次执行sql会走一遍他的转化器 如果不需要多租户功能 可以将其注释 - tenantConfig(paginationInterceptor); - return paginationInterceptor; - } - - /** - * 多租户的配置 - * @param paginationInterceptor - */ - private void tenantConfig(PaginationInterceptor paginationInterceptor){ - /* - * 【测试多租户】 SQL 解析处理拦截器
- * 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )
- */ - List sqlParserList = new ArrayList<>(); - TenantSqlParser tenantSqlParser = new JeroTenantParser(); - tenantSqlParser.setTenantHandler(new TenantHandler() { - - @Override - public Expression getTenantId(boolean select) { - String tenant_id = oConvertUtils.getString(TenantContext.getTenant(),"0"); - return new LongValue(tenant_id); - } - @Override - public String getTenantIdColumn() { - return tenant_field; - } - - @Override - public boolean doTableFilter(String tableName) { - //true则不加租户条件查询 false则加 - // return excludeTable.contains(tableName); - if(tenantTable.contains(tableName)){ - return false; - } - return true; - } - - private Expression in(String ids){ - final InExpression inExpression = new InExpression(); - inExpression.setLeftExpression(new Column(getTenantIdColumn())); - final ExpressionList itemsList = new ExpressionList(); - final List inValues = new ArrayList<>(2); - for(String id:ids.split(",")){ - inValues.add(new LongValue(id)); - } - itemsList.setExpressions(inValues); - inExpression.setRightItemsList(itemsList); - return inExpression; - } - - }); - - sqlParserList.add(tenantSqlParser); - paginationInterceptor.setSqlParserList(sqlParserList); - paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() { - @Override - public boolean doFilter(MetaObject metaObject) { - String sql = (String) metaObject.getValue(PluginUtils.DELEGATE_BOUNDSQL_SQL); - for(String tableName: tenantTable){ - String sql_lowercase = sql.toLowerCase(); - if(sql_lowercase.indexOf(tableName.toLowerCase())>=0){ - for(String key: DDL_KEYWORD){ - if(sql_lowercase.indexOf(key)>=0){ - return true; - } - } - return false; - } - } - /*if ("mapper路径.方法名".equals(ms.getId())) { - //使用这种判断也可以避免走此过滤器 - return true; - }*/ - return true; - } - }); - } -// /** -// * mybatis-plus SQL执行效率插件【生产环境可以关闭】 -// */ -// @Bean -// public PerformanceInterceptor performanceInterceptor() { -// return new PerformanceInterceptor(); -// } - -} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusSaasConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusSaasConfig.java new file mode 100644 index 00000000..34b60cca --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/mybatis/MybatisPlusSaasConfig.java @@ -0,0 +1,70 @@ +package com.jero.config.mybatis; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import com.jero.common.util.oConvertUtils; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * 单数据源配置(jeecg.datasource.open = false时生效) + * @Author zhoujf + * + */ +@Configuration +@MapperScan(value={"com.jero.modules.**.mapper*"}) +public class MybatisPlusSaasConfig { + /** + * tenant_id 字段名 + */ + private static final String TENANT_FIELD_NAME = "tenant_id"; + /** + * 哪些表需要做多租户 表需要添加一个字段 tenant_id + */ + private static final List tenantTable = new ArrayList(); + + static { + tenantTable.add("demo"); + } + + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor + interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() { + @Override + public Expression getTenantId() { + String tenant_id = oConvertUtils.getString(TenantContext.getTenant(),"0"); + return new LongValue(tenant_id); + } + + @Override + public String getTenantIdColumn(){ + return TENANT_FIELD_NAME; + } + + // 返回 true 表示不走租户逻辑 + @Override + public boolean ignoreTable(String tableName) { + for(String temp: tenantTable){ + if(temp.equalsIgnoreCase(tableName)){ + return false; + } + } + return true; + } + })); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } + +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java index 80e9be79..15d3d9c5 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java @@ -84,7 +84,6 @@ public class ShiroConfig { filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录 filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在 filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册 - filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息 filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号 filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码 filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码 @@ -102,6 +101,7 @@ public class ShiroConfig { filterChainDefinitionMap.put("/**/*.png", "anon"); filterChainDefinitionMap.put("/**/*.ico", "anon"); + //排除字体格式的后缀 filterChainDefinitionMap.put("/**/*.ttf", "anon"); filterChainDefinitionMap.put("/**/*.woff", "anon"); filterChainDefinitionMap.put("/**/*.woff2", "anon"); @@ -135,7 +135,7 @@ public class ShiroConfig { // 添加自己的过滤器并且取名为jwt Map filterMap = new HashMap(1); - //如果cloudServer为空 则说明是单体 需要加载跨域配置 + //如果cloudServer为空 则说明是单体 需要加载跨域配置【微服务跨域切换】 Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY); filterMap.put("jwt", new JwtFilter(cloudServer==null)); shiroFilterFactoryBean.setFilters(filterMap); diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroRealm.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroRealm.java index a41e5d0c..5e2f6522 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroRealm.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroRealm.java @@ -18,6 +18,7 @@ import com.jero.common.system.vo.LoginUser; import com.jero.common.util.RedisUtil; import com.jero.common.util.SpringContextUtils; import com.jero.common.util.oConvertUtils; +import com.jero.config.mybatis.TenantContext; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -126,7 +127,17 @@ public class ShiroRealm extends AuthorizingRealm { if (!jwtTokenRefresh(token, username, loginUser.getPassword())) { throw new AuthenticationException("Token失效,请重新登录!"); } - + //update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致 + String userTenantIds = loginUser.getRelTenantIds(); + if(oConvertUtils.isNotEmpty(userTenantIds)){ + String contextTenantId = TenantContext.getTenant(); + if(oConvertUtils.isNotEmpty(contextTenantId) && !"0".equals(contextTenantId)){ + if(String.join(",",userTenantIds).indexOf(contextTenantId)<0){ + throw new AuthenticationException("用户租户信息变更,请重新登陆!"); + } + } + } + //update-end-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致 return loginUser; } diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/filters/JwtFilter.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/filters/JwtFilter.java index 161eeef8..a1780b8d 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/filters/JwtFilter.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/filters/JwtFilter.java @@ -1,5 +1,6 @@ package com.jero.config.shiro.filters; +import com.jero.common.util.oConvertUtils; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; @@ -22,6 +23,10 @@ import javax.servlet.http.HttpServletResponse; @Slf4j public class JwtFilter extends BasicHttpAuthenticationFilter { + /** + * 默认开启跨域设置(使用单体) + * 微服务情况下,此属性设置为false + */ private boolean allowOrigin = true; public JwtFilter(){} @@ -55,7 +60,7 @@ public class JwtFilter extends BasicHttpAuthenticationFilter { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String token = httpServletRequest.getHeader(CommonConstant.X_ACCESS_TOKEN); // update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数 - if(token == null){ + if (oConvertUtils.isEmpty(token)) { token = httpServletRequest.getParameter("token"); } // update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数 diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthConfiguration.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthConfiguration.java new file mode 100644 index 00000000..d7a04148 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthConfiguration.java @@ -0,0 +1,26 @@ +package com.jero.config.sign.interceptor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 签名 拦截器配置 + */ +@Configuration +public class SignAuthConfiguration implements WebMvcConfigurer { + public static String[] urlList = new String[] {"/sys/dict/getDictItems/*", "/sys/dict/loadDict/*", + "/sys/dict/loadDictOrderByValue/*", "/sys/dict/loadDictItem/*", "/sys/dict/loadTreeData", + "/sys/api/queryTableDictItemsByCode", "/sys/api/queryFilterTableDictInfo", "/sys/api/queryTableDictByKeys", + "/sys/api/translateDictFromTable", "/sys/api/translateDictFromTableByKeys"}; + @Bean + public SignAuthInterceptor signAuthInterceptor() { + return new SignAuthInterceptor(); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(signAuthInterceptor()).addPathPatterns(urlList); + } +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthInterceptor.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthInterceptor.java new file mode 100644 index 00000000..7ee3d932 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/interceptor/SignAuthInterceptor.java @@ -0,0 +1,73 @@ +package com.jero.config.sign.interceptor; + +import java.io.PrintWriter; +import java.util.SortedMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.jero.common.api.vo.Result; +import com.jero.common.constant.CommonConstant; +import com.jero.common.util.DateUtils; +import com.jero.config.sign.util.BodyReaderHttpServletRequestWrapper; +import com.jero.config.sign.util.HttpUtils; +import com.jero.config.sign.util.SignUtil; +import org.springframework.web.servlet.HandlerInterceptor; + +import com.alibaba.fastjson.JSON; + +import lombok.extern.slf4j.Slf4j; + +/** + * 签名拦截器 + * @author qinfeng + */ +@Slf4j +public class SignAuthInterceptor implements HandlerInterceptor { + /** + * 5分钟有效期 + */ + private final static long MAX_EXPIRE = 5 * 60; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + log.info("request URI = " + request.getRequestURI()); + HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); + //获取全部参数(包括URL和body上的) + SortedMap allParams = HttpUtils.getAllParams(requestWrapper); + //对参数进行签名验证 + String headerSign = request.getHeader(CommonConstant.X_SIGN); + String timesTamp = request.getHeader(CommonConstant.X_TIMESTAMP); + + //1.校验时间有消息 + try { + DateUtils.parseDate(timesTamp, "yyyyMMddHHmmss"); + } catch (Exception e) { + throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP格式必须为:yyyyMMddHHmmss"); + } + Long clientTimestamp = Long.parseLong(timesTamp); + //判断时间戳 timestamp=201808091113 + if ((DateUtils.getCurrentTimestamp() - clientTimestamp) > MAX_EXPIRE) { + throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP已过期"); + } + + //2.校验签名 + boolean isSigned = SignUtil.verifySign(allParams,headerSign); + + if (isSigned) { + log.debug("Sign 签名通过!Header Sign : {}",headerSign); + return true; + } else { + log.error("request URI = " + request.getRequestURI()); + log.error("Sign 签名校验失败!Header Sign : {}",headerSign); + //校验失败返回前端 + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + PrintWriter out = response.getWriter(); + Result result = Result.error("Sign签名校验失败!"); + out.print(JSON.toJSON(result)); + return false; + } + } + +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/BodyReaderHttpServletRequestWrapper.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 00000000..f90b769e --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,107 @@ +package com.jero.config.sign.util; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.*; +import java.nio.charset.Charset; + +/** + * 保存过滤器里面的流 + * + * @author jero + * @date 20210621 + */ +public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { + + private final byte[] body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) { + + super(request); + String sessionStream = getBodyString(request); + body = sessionStream.getBytes(Charset.forName("UTF-8")); + } + + /** + * 获取请求Body + * + * @param request + * @return + */ + public String getBodyString(final ServletRequest request) { + + StringBuilder sb = new StringBuilder(); + try (InputStream inputStream = cloneInputStream(request.getInputStream()); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))) { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + return sb.toString(); + } + + /** + * Description: 复制输入流
+ * + * @param inputStream + * @return
+ */ + public InputStream cloneInputStream(ServletInputStream inputStream) { + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + try { + while ((len = inputStream.read(buffer)) > -1) { + byteArrayOutputStream.write(buffer, 0, len); + } + byteArrayOutputStream.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + return new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + } + + @Override + public BufferedReader getReader() { + + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() { + + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + return new ServletInputStream() { + + @Override + public int read() { + + return bais.read(); + } + + @Override + public boolean isFinished() { + + return false; + } + + @Override + public boolean isReady() { + + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + }; + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/HttpUtils.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/HttpUtils.java new file mode 100644 index 00000000..4daed574 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/HttpUtils.java @@ -0,0 +1,184 @@ +package com.jero.config.sign.util; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import com.jero.common.util.oConvertUtils; +import org.springframework.http.HttpMethod; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * http 工具类 获取请求中的参数 + * + * @author jeecg + * @date 20210621 + */ +@Slf4j +public class HttpUtils { + + /** + * 将URL的参数和body参数合并 + * + * @author jeecg + * @date 20210621 + * @param request + */ + public static SortedMap getAllParams(HttpServletRequest request) throws IOException { + + SortedMap result = new TreeMap<>(); + // 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username + String pathVariable = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1); + if (pathVariable.contains(",")) { + log.info(" pathVariable: {}",pathVariable); + String deString = URLDecoder.decode(pathVariable, "UTF-8"); + log.info(" pathVariable decode: {}",deString); + result.put(SignUtil.xPathVariable, deString); + } + // 获取URL上的参数 + Map urlParams = getUrlParams(request); + for (Map.Entry entry : urlParams.entrySet()) { + result.put((String)entry.getKey(), (String)entry.getValue()); + } + Map allRequestParam = new HashMap<>(16); + // get请求不需要拿body参数 + if (!HttpMethod.GET.name().equals(request.getMethod())) { + allRequestParam = getAllRequestParam(request); + } + // 将URL的参数和body参数进行合并 + if (allRequestParam != null) { + for (Map.Entry entry : allRequestParam.entrySet()) { + result.put((String)entry.getKey(), (String)entry.getValue()); + } + } + return result; + } + + /** + * 将URL的参数和body参数合并 + * + * @author jeecg + * @date 20210621 + * @param queryString + */ + public static SortedMap getAllParams(String url, String queryString, byte[] body, String method) + throws IOException { + + SortedMap result = new TreeMap<>(); + // 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username + String pathVariable = url.substring(url.lastIndexOf("/") + 1); + if (pathVariable.contains(",")) { + log.info(" pathVariable: {}",pathVariable); + String deString = URLDecoder.decode(pathVariable, "UTF-8"); + log.info(" pathVariable decode: {}",deString); + result.put(SignUtil.xPathVariable, deString); + } + // 获取URL上的参数 + Map urlParams = getUrlParams(queryString); + for (Map.Entry entry : urlParams.entrySet()) { + result.put((String)entry.getKey(), (String)entry.getValue()); + } + Map allRequestParam = new HashMap<>(16); + // get请求不需要拿body参数 + if (!HttpMethod.GET.name().equals(method)) { + allRequestParam = getAllRequestParam(body); + } + // 将URL的参数和body参数进行合并 + if (allRequestParam != null) { + for (Map.Entry entry : allRequestParam.entrySet()) { + result.put((String)entry.getKey(), (String)entry.getValue()); + } + } + return result; + } + + /** + * 获取 Body 参数 + * + * @date 15:04 20210621 + * @param request + */ + public static Map getAllRequestParam(final HttpServletRequest request) throws IOException { + + BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + String str = ""; + StringBuilder wholeStr = new StringBuilder(); + // 一行一行的读取body体里面的内容; + while ((str = reader.readLine()) != null) { + wholeStr.append(str); + } + // 转化成json对象 + return JSONObject.parseObject(wholeStr.toString(), Map.class); + } + + /** + * 获取 Body 参数 + * + * @date 15:04 20210621 + * @param body + */ + public static Map getAllRequestParam(final byte[] body) throws IOException { + if(body==null){ + return null; + } + String wholeStr = new String(body); + // 转化成json对象 + return JSONObject.parseObject(wholeStr.toString(), Map.class); + } + + /** + * 将URL请求参数转换成Map + * + * @param request + */ + public static Map getUrlParams(HttpServletRequest request) { + Map result = new HashMap<>(16); + if (oConvertUtils.isEmpty(request.getQueryString())) { + return result; + } + String param = ""; + try { + param = URLDecoder.decode(request.getQueryString(), "utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + String[] params = param.split("&"); + for (String s : params) { + int index = s.indexOf("="); + result.put(s.substring(0, index), s.substring(index + 1)); + } + return result; + } + + /** + * 将URL请求参数转换成Map + * + * @param queryString + */ + public static Map getUrlParams(String queryString) { + Map result = new HashMap<>(16); + if (oConvertUtils.isEmpty(queryString)) { + return result; + } + String param = ""; + try { + param = URLDecoder.decode(queryString, "utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + String[] params = param.split("&"); + for (String s : params) { + int index = s.indexOf("="); + result.put(s.substring(0, index), s.substring(index + 1)); + } + return result; + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/SignUtil.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/SignUtil.java new file mode 100644 index 00000000..f2e58f61 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/sign/util/SignUtil.java @@ -0,0 +1,56 @@ +package com.jero.config.sign.util; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import com.jero.common.exception.JeroBootException; +import com.jero.common.util.SpringContextUtils; +import com.jero.common.util.oConvertUtils; +import com.jero.config.StaticConfig; +import org.springframework.util.DigestUtils; +import org.springframework.util.StringUtils; + +import java.util.SortedMap; + +/** + * 签名工具类 + * + * @author jeecg + * @date 20210621 + */ +@Slf4j +public class SignUtil { + public static final String xPathVariable = "x-path-variable"; + + /** + * @param params + * 所有的请求参数都会在这里进行排序加密 + * @return 验证签名结果 + */ + public static boolean verifySign(SortedMap params,String headerSign) { + if (params == null || StringUtils.isEmpty(headerSign)) { + return false; + } + // 把参数加密 + String paramsSign = getParamsSign(params); + log.info("Param Sign : {}", paramsSign); + return !StringUtils.isEmpty(paramsSign) && headerSign.equals(paramsSign); + } + + /** + * @param params + * 所有的请求参数都会在这里进行排序加密 + * @return 得到签名 + */ + public static String getParamsSign(SortedMap params) { + //去掉 Url 里的时间戳 + params.remove("_t"); + String paramsJsonStr = JSONObject.toJSONString(params); + log.info("Param paramsJsonStr : {}", paramsJsonStr); + StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class); + String signatureSecret = staticConfig.getSignatureSecret(); + if(oConvertUtils.isEmpty(signatureSecret) || signatureSecret.contains("${")){ + throw new JeroBootException("签名密钥 ${jeecg.signatureSecret} 缺少配置 !!"); + } + return DigestUtils.md5DigestAsHex((paramsJsonStr + signatureSecret).getBytes()).toUpperCase(); + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/modules/base/mapper/BaseCommonMapper.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/modules/base/mapper/BaseCommonMapper.java index 9d301535..00f6d28a 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/modules/base/mapper/BaseCommonMapper.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/modules/base/mapper/BaseCommonMapper.java @@ -1,6 +1,6 @@ package com.jero.modules.base.mapper; -import com.baomidou.mybatisplus.annotation.SqlParser; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Param; import com.jero.common.api.dto.LogDTO; @@ -10,7 +10,7 @@ public interface BaseCommonMapper { * 保存日志 * @param dto */ - @SqlParser(filter=true) + @InterceptorIgnore void saveLog(@Param("dto")LogDTO dto); } diff --git a/jero-boot/jero-boot-base/jero-boot-base-generater-core/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-generater-core/pom.xml index 76a5bf12..d7ab8d99 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-generater-core/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-generater-core/pom.xml @@ -5,7 +5,7 @@ jero-boot-base com.jero.boot - 2.4.3 + 2.4.6 4.0.0 代码生成核心模块 diff --git a/jero-boot/jero-boot-base/jero-boot-base-generater/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-generater/pom.xml index 8aa53dc8..509c64bc 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-generater/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-generater/pom.xml @@ -5,7 +5,7 @@ jero-boot-base com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-base/jero-boot-base-tools/pom.xml b/jero-boot/jero-boot-base/jero-boot-base-tools/pom.xml index 5d79c593..18ab484d 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-tools/pom.xml +++ b/jero-boot/jero-boot-base/jero-boot-base-tools/pom.xml @@ -4,7 +4,7 @@ com.jero.boot jero-boot-base - 2.4.3 + 2.4.6 4.0.0 公共模块 @@ -29,7 +29,11 @@ cn.hutool - hutool-all + hutool-core + + + cn.hutool + hutool-crypto diff --git a/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/TransmitUserTokenFilter.java b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/TransmitUserTokenFilter.java new file mode 100644 index 00000000..f72c6222 --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/TransmitUserTokenFilter.java @@ -0,0 +1,43 @@ +package com.jero.common.config.mqtoken; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 存放token到上下文供队列调用feign使用 + * @author zyf + */ +public class TransmitUserTokenFilter implements Filter { + + private static String X_ACCESS_TOKEN="X-Access-Token"; + + public TransmitUserTokenFilter() { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + this.initUserInfo((HttpServletRequest) request); + chain.doFilter(request, response); + } + + private void initUserInfo(HttpServletRequest request) { + String token = request.getHeader(X_ACCESS_TOKEN); + if (token!=null) { + try { + //将token放入上下文中 + UserTokenContext.setToken(token); + } catch (Exception e) { + + } + } + } + + @Override + public void destroy() { + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/UserTokenContext.java b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/UserTokenContext.java new file mode 100644 index 00000000..46e78c2a --- /dev/null +++ b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/config/mqtoken/UserTokenContext.java @@ -0,0 +1,22 @@ +package com.jero.common.config.mqtoken; + + +/** + * 用户token上下文 + * @author zyf + */ +public class UserTokenContext { + + private static ThreadLocal userToken = new ThreadLocal(); + + public UserTokenContext() { + } + + public static String getToken(){ + return userToken.get(); + } + + public static void setToken(String token){ + userToken.set(token); + } +} diff --git a/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/constant/CacheConstant.java b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/constant/CacheConstant.java index 8a456dc6..46fb6fbc 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/constant/CacheConstant.java +++ b/jero-boot/jero-boot-base/jero-boot-base-tools/src/main/java/com/jero/common/constant/CacheConstant.java @@ -8,13 +8,18 @@ package com.jero.common.constant; public interface CacheConstant { /** - * 字典信息缓存 + * 字典信息缓存(含禁用的字典项) */ - public static final String SYS_DICT_CACHE = "sys:cache:dict"; + public static final String SYS_DICT_CACHE = "sys:cache:dict"; + + /** + * 字典信息缓存 status为有效的 + */ + public static final String SYS_ENABLE_DICT_CACHE = "sys:cache:dictEnable"; /** * 表字典信息缓存 */ - public static final String SYS_DICT_TABLE_CACHE = "sys:cache:dictTable"; + public static final String SYS_DICT_TABLE_CACHE = "sys:cache:dictTable"; public static final String SYS_DICT_TABLE_BY_KEYS_CACHE = SYS_DICT_TABLE_CACHE + "ByKeys"; /** diff --git a/jero-boot/jero-boot-base/pom.xml b/jero-boot/jero-boot-base/pom.xml index f15f6df0..5671738b 100644 --- a/jero-boot/jero-boot-base/pom.xml +++ b/jero-boot/jero-boot-base/pom.xml @@ -5,7 +5,7 @@ com.jero.boot jero-boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-module-demo/pom.xml b/jero-boot/jero-boot-module-demo/pom.xml index 9c0fea5a..f478de15 100644 --- a/jero-boot/jero-boot-module-demo/pom.xml +++ b/jero-boot/jero-boot-module-demo/pom.xml @@ -5,7 +5,7 @@ com.jero.boot jero-boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/entity/JeroDemo.java b/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/entity/JeroDemo.java index 871addbc..17c3e3a8 100644 --- a/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/entity/JeroDemo.java +++ b/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/entity/JeroDemo.java @@ -75,4 +75,7 @@ public class JeroDemo extends JeroEntity implements Serializable { /** 个人简介 */ @ApiModelProperty(value = "个人简介") private java.lang.String content; + + @ApiModelProperty(value = "租户ID") + private java.lang.Integer tenantId; } diff --git a/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/mapper/xml/JeroDemoMapper.xml b/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/mapper/xml/JeroDemoMapper.xml index 8b360601..b7767e3d 100644 --- a/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/mapper/xml/JeroDemoMapper.xml +++ b/jero-boot/jero-boot-module-demo/src/main/java/com/jero/modules/demo/test/mapper/xml/JeroDemoMapper.xml @@ -22,13 +22,13 @@ - + select DISTINCT perms from sys_user_role sur, sys_role_permission srp, sys_permission sp where sur.role_id = srp.role_id and sp.id = srp.permission_id - and user_id = #{userId} + and sur.user_id = #{userId} and sp.perms like concat(concat('%',#{permsPrefix}),'%') \ No newline at end of file diff --git a/jero-boot/jero-boot-module-system/Dockerfile b/jero-boot/jero-boot-module-system/Dockerfile index 95d65cc7..b791e726 100644 --- a/jero-boot/jero-boot-module-system/Dockerfile +++ b/jero-boot/jero-boot-module-system/Dockerfile @@ -10,6 +10,6 @@ WORKDIR /jero-boot EXPOSE 8080 -ADD ./target/jero-boot-module-system-2.4.3.jar ./ +ADD ./target/jero-boot-module-system-2.4.6.jar ./ -CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jero-boot-module-system-2.4.3.jar \ No newline at end of file +CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jero-boot-module-system-2.4.6.jar \ No newline at end of file diff --git a/jero-boot/jero-boot-module-system/pom.xml b/jero-boot/jero-boot-module-system/pom.xml index cb0fc4ee..d5d0d981 100644 --- a/jero-boot/jero-boot-module-system/pom.xml +++ b/jero-boot/jero-boot-module-system/pom.xml @@ -4,7 +4,7 @@ com.jero.boot jero-boot - 2.4.3 + 2.4.6 4.0.0 @@ -14,7 +14,7 @@ aliyun aliyun Repository - http://maven.aliyun.com/nexus/content/groups/public + https://maven.aliyun.com/repository/public false @@ -22,7 +22,7 @@ jeecg jeecg Repository - http://maven.jeecg.org/nexus/content/repositories/jeecg + https://maven.jeecg.org/nexus/content/repositories/jeecg false diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/api/controller/SystemAPIController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/api/controller/SystemAPIController.java index 8c3a0746..4d2e0275 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/api/controller/SystemAPIController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/api/controller/SystemAPIController.java @@ -145,6 +145,16 @@ public class SystemAPIController { return sysBaseAPI.queryDictItemsByCode(code); } + /** + * 获取有效的数据字典 + * @param code + * @return + */ + @GetMapping("/queryEnableDictItemsByCode") + List queryEnableDictItemsByCode(@RequestParam("code") String code){ + return sysBaseAPI.queryEnableDictItemsByCode(code); + } + /** 查询所有的父级字典,按照create_time排序 */ @GetMapping("/queryAllDict") List queryAllDict(){ @@ -160,18 +170,6 @@ public class SystemAPIController { return sysBaseAPI.queryAllDSysCategory(); } - /** - * 获取表数据字典 - * @param table - * @param text - * @param code - * @return - */ - @GetMapping("/queryTableDictItemsByCode") - List queryTableDictItemsByCode(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code){ - return sysBaseAPI.queryTableDictItemsByCode(table, text, code); - } - /** * 查询所有部门 作为字典信息 id -->value,departName -->text * @return @@ -181,34 +179,6 @@ public class SystemAPIController { return sysBaseAPI.queryAllDepartBackDictModel(); } - - /** - * 查询表字典 支持过滤数据 - * @param table - * @param text - * @param code - * @param filterSql - * @return - */ - @GetMapping("/queryFilterTableDictInfo") - List queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql){ - return sysBaseAPI.queryFilterTableDictInfo(table, text, code, filterSql); - } - - /** - * 查询指定table的 text code 获取字典,包含text和value - * @param table - * @param text - * @param code - * @param keyArray - * @return - */ - @Deprecated - @GetMapping("/queryTableDictByKeys") - public List queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray){ - return sysBaseAPI.queryTableDictByKeys(table, text, code, keyArray); - } - /** * 获取所有角色 带参 * roleIds 默认选中角色 @@ -449,19 +419,6 @@ public class SystemAPIController { return sysBaseAPI.getCacheUser(username); } - /** - * 字典表的 翻译 - * @param table - * @param text - * @param code - * @param key - * @return - */ - @GetMapping("/translateDictFromTable") - public String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key){ - return sysBaseAPI.translateDictFromTable(table, text, code, key); - } - /** * 普通字典的翻译 * @param code @@ -479,8 +436,8 @@ public class SystemAPIController { * @param usernames * @return */ - @GetMapping("/queryUsersByUsernames") - List queryUsersByUsernames(String usernames){ + @RequestMapping("/queryUsersByUsernames") + List queryUsersByUsernames(@RequestParam("usernames") String usernames){ return this.sysBaseAPI.queryUsersByUsernames(usernames); } @@ -489,8 +446,8 @@ public class SystemAPIController { * @param ids * @return */ - @GetMapping("/queryUsersByIds") - List queryUsersByIds(String ids){ + @RequestMapping("/queryUsersByIds") + List queryUsersByIds(@RequestParam("ids") String ids){ return this.sysBaseAPI.queryUsersByIds(ids); } @@ -500,18 +457,18 @@ public class SystemAPIController { * @return */ @GetMapping("/queryDepartsByOrgcodes") - List queryDepartsByOrgcodes(String orgCodes){ + List queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes){ return this.sysBaseAPI.queryDepartsByOrgcodes(orgCodes); } /** * 39根据多个部门ID(逗号分隔),查询返回多个部门信息 - * @param orgCodes + * @param ids * @return */ @GetMapping("/queryDepartsByIds") - List queryDepartsByIds(String orgCodes){ - return this.sysBaseAPI.queryDepartsByIds(orgCodes); + List queryDepartsByIds(@RequestParam("ids") String ids){ + return this.sysBaseAPI.queryDepartsByIds(ids); } /** @@ -555,4 +512,145 @@ public class SystemAPIController { return this.sysBaseAPI.getDeptUserByOrgCode(orgCode); } + /** + * 查询分类字典翻译 + * + * @param ids 分类字典表id + * @return + */ + @GetMapping("/loadCategoryDictItem") + public List loadCategoryDictItem(@RequestParam("ids") String ids) { + return sysBaseAPI.loadCategoryDictItem(ids); + } + + /** + * 根据字典code加载字典text + * + * @param dictCode 顺序:tableName,text,code + * @param keys 要查询的key + * @return + */ + @GetMapping("/loadDictItem") + public List loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys) { + return sysBaseAPI.loadDictItem(dictCode, keys); + } + + /** + * 根据字典code查询字典项 + * + * @param dictCode 顺序:tableName,text,code + * @param dictCode 要查询的key + * @return + */ + @GetMapping("/getDictItems") + public List getDictItems(@RequestParam("dictCode") String dictCode) { + return sysBaseAPI.getDictItems(dictCode); + } + + /** + * 根据多个字典code查询多个字典项 + * + * @param dictCodeList + * @return key = dictCode ; value=对应的字典项 + */ + @RequestMapping("/getManyDictItems") + public Map> getManyDictItems(@RequestParam("dictCodeList") List dictCodeList) { + return sysBaseAPI.getManyDictItems(dictCodeList); + } + + /** + * 【下拉搜索】 + * 大数据量的字典表 走异步加载,即前端输入内容过滤数据 + * + * @param dictCode 字典code格式:table,text,code + * @param keyword 过滤关键字 + * @return + */ + @GetMapping("/loadDictItemByKeyword") + public List loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize) { + return sysBaseAPI.loadDictItemByKeyword(dictCode, keyword, pageSize); + } + + /** + * 48 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割 + * @param dictCodes + * @param keys + * @return + */ + @GetMapping("/translateManyDict") + public Map> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys){ + return this.sysBaseAPI.translateManyDict(dictCodes, keys); + } + + + /** + * 获取表数据字典 【接口签名验证】 + * @param table + * @param text + * @param code + * @return + */ + @GetMapping("/queryTableDictItemsByCode") + List queryTableDictItemsByCode(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code){ + return sysBaseAPI.queryTableDictItemsByCode(table, text, code); + } + + /** + * 查询表字典 支持过滤数据 【接口签名验证】 + * @param table + * @param text + * @param code + * @param filterSql + * @return + */ + @GetMapping("/queryFilterTableDictInfo") + List queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql){ + return sysBaseAPI.queryFilterTableDictInfo(table, text, code, filterSql); + } + + /** + * 【接口签名验证】 + * 查询指定table的 text code 获取字典,包含text和value + * @param table + * @param text + * @param code + * @param keyArray + * @return + */ + @Deprecated + @GetMapping("/queryTableDictByKeys") + public List queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray){ + return sysBaseAPI.queryTableDictByKeys(table, text, code, keyArray); + } + + + /** + * 字典表的 翻译【接口签名验证】 + * @param table + * @param text + * @param code + * @param key + * @return + */ + @GetMapping("/translateDictFromTable") + public String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key){ + return sysBaseAPI.translateDictFromTable(table, text, code, key); + } + + + /** + * 【接口签名验证】 + * 49 字典表的 翻译,可批量 + * + * @param table + * @param text + * @param code + * @param keys 多个用逗号分割 + * @return + */ + @GetMapping("/translateDictFromTableByKeys") + public List translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys) { + return this.sysBaseAPI.translateDictFromTableByKeys(table, text, code, keys); + } + } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/quartz/service/impl/QuartzJobServiceImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/quartz/service/impl/QuartzJobServiceImpl.java index fc56862b..41d8d7eb 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/quartz/service/impl/QuartzJobServiceImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/quartz/service/impl/QuartzJobServiceImpl.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.annotation.Transactional; /** * @Description: 定时任务在线管理 @@ -42,6 +43,7 @@ public class QuartzJobServiceImpl extends ServiceImpl add(@RequestBody SysAnnouncement sysAnnouncement) { Result result = new Result(); try { + // update-begin-author:liusq date:20210804 for:标题处理xss攻击的问题 + String title = XSSUtils.striptXSS(sysAnnouncement.getTitile()); + sysAnnouncement.setTitile(title); + // update-end-author:liusq date:20210804 for:标题处理xss攻击的问题 sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString()); sysAnnouncement.setSendStatus(CommonSendStatus.UNPUBLISHED_STATUS_0);//未发布 sysAnnouncementService.saveAnnouncement(sysAnnouncement); @@ -133,6 +138,10 @@ public class SysAnnouncementController { if(sysAnnouncementEntity==null) { result.error500("未找到对应实体"); }else { + // update-begin-author:liusq date:20210804 for:标题处理xss攻击的问题 + String title = XSSUtils.striptXSS(sysAnnouncement.getTitile()); + sysAnnouncement.setTitile(title); + // update-end-author:liusq date:20210804 for:标题处理xss攻击的问题 boolean ok = sysAnnouncementService.upDateAnnouncement(sysAnnouncement); //TODO 返回false说明什么? if(ok) { diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDepartController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDepartController.java index e527a213..c6823c23 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDepartController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDepartController.java @@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.jero.common.system.vo.SysDepartTreeModel; +import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import com.jero.common.api.vo.Result; import com.jero.common.constant.CacheConstant; @@ -75,8 +76,13 @@ public class SysDepartController { LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal(); try { if(oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals( CommonConstant.USER_IDENTITY_2 )){ - List list = sysDepartService.queryMyDeptTreeList(user.getDepartIds()); - result.setResult(list); + //update-begin--Author:liusq Date:20210624 for:部门查询ids为空后的前端显示问题 issues/I3UD06 + String departIds = user.getDepartIds(); + if(StringUtils.isNotBlank(departIds)){ + List list = sysDepartService.queryMyDeptTreeList(departIds); + result.setResult(list); + } + //update-end--Author:liusq Date:20210624 for:部门查询ids为空后的前端显示问题 issues/I3UD06 result.setMessage(CommonConstant.USER_IDENTITY_2.toString()); result.setSuccess(true); }else{ diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictController.java index 6f831abd..9bbd8713 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictController.java @@ -116,34 +116,6 @@ public class SysDictController { return result; } - /** - * 获取字典数据 - * @param dictCode 字典code - * @param dictCode 表名,文本字段,code字段 | 举例:sys_user,realname,id - * @return - */ - @ApiOperation(value = "字典控制器-根据字典编码获取字典数据", notes = "字典控制器-根据字典编码获取字典数据") - @RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET) - public Result> getDictItems(@PathVariable String dictCode, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) { - log.info(" dictCode : "+ dictCode); - Result> result = new Result>(); - try { - List ls = sysDictService.getDictItems(dictCode); - if (ls == null) { - result.error500("字典Code格式不正确!"); - return result; - } - result.setSuccess(true); - result.setResult(ls); - log.debug(result.toString()); - } catch (Exception e) { - log.error(e.getMessage(), e); - result.error500("操作失败"); - return result; - } - return result; - } - /** * 获取全部字典数据 * @@ -181,6 +153,34 @@ public class SysDictController { } /** + * 获取字典数据 【接口签名验证】 + * @param dictCode 字典code + * @param dictCode 表名,文本字段,code字段 | 举例:sys_user,realname,id + * @return + */ + @RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET) + public Result> getDictItems(@PathVariable String dictCode, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) { + log.info(" dictCode : "+ dictCode); + Result> result = new Result>(); + try { + List ls = sysDictService.getDictItems(dictCode); + if (ls == null) { + result.error500("字典Code格式不正确!"); + return result; + } + result.setSuccess(true); + result.setResult(ls); + log.debug(result.toString()); + } catch (Exception e) { + log.error(e.getMessage(), e); + result.error500("操作失败"); + return result; + } + return result; + } + + /** + * 【接口签名验证】 * 【JSearchSelectTag下拉搜索组件专用接口】 * 大数据量的字典表 走异步加载 即前端输入内容过滤数据 * @param dictCode 字典code格式:table,text,code @@ -251,7 +251,7 @@ public class SysDictController { } /** - * + *【接口签名验证】 * 根据字典code加载字典text 返回 * @param dictCode 顺序:tableName,text,code * @param keys 要查询的key @@ -288,6 +288,7 @@ public class SysDictController { } /** + * 【接口签名验证】 * 根据表名——显示字段-存储字段 pid 加载树形数据 */ @ApiOperation(value = "字典控制器-根据表名—显示字段-存储字段 pid 加载树形数据", notes = "字典控制器-根据表名—显示字段-存储字段 pid 加载树形数据") @@ -384,7 +385,7 @@ public class SysDictController { */ @ApiOperation(value = "字典控制器-删除字典", notes = "字典控制器-删除字典") @DeleteMapping(value = "/delete") - @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result delete(@RequestParam(name="id",required=true) String id) { Result result = new Result(); boolean ok = sysDictService.removeById(id); @@ -403,7 +404,7 @@ public class SysDictController { */ @ApiOperation(value = "字典控制器-批量字典", notes = "字典控制器-批量字典") @DeleteMapping(value = "/deleteBatch") - @CacheEvict(value= CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { Result result = new Result(); if(oConvertUtils.isEmpty(ids)) { @@ -548,7 +549,7 @@ public class SysDictController { } /** - * 取回 + * 逻辑删除的字段,进行取回 * @param id * @return */ diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictItemController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictItemController.java index 17ae15ab..4a2f3dbe 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictItemController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysDictItemController.java @@ -76,7 +76,7 @@ public class SysDictItemController { //@RequiresRoles({"admin"}) @RequiresPermissions("sys:dict:list") @RequestMapping(value = "/add", method = RequestMethod.POST) - @CacheEvict(value= CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result add(@RequestBody SysDictItem sysDictItem) { Result result = new Result(); try { @@ -98,7 +98,7 @@ public class SysDictItemController { //@RequiresRoles({"admin"}) @RequiresPermissions("sys:dict:list") @RequestMapping(value = "/edit", method = RequestMethod.PUT) - @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result edit(@RequestBody SysDictItem sysDictItem) { Result result = new Result(); SysDictItem sysdict = sysDictItemService.getById(sysDictItem.getId()); @@ -123,7 +123,7 @@ public class SysDictItemController { //@RequiresRoles({"admin"}) @RequiresPermissions("sys:dict:list") @RequestMapping(value = "/delete", method = RequestMethod.DELETE) - @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result delete(@RequestParam(name="id",required=true) String id) { Result result = new Result(); SysDictItem joinSystem = sysDictItemService.getById(id); @@ -146,7 +146,7 @@ public class SysDictItemController { //@RequiresRoles({"admin"}) @RequiresPermissions("sys:dict:list") @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE) - @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { Result result = new Result(); if(ids==null || "".equals(ids.trim())) { diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysTenantController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysTenantController.java index aa8de2e5..1b7a2a47 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysTenantController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysTenantController.java @@ -15,6 +15,7 @@ import com.jero.modules.system.service.ISysTenantService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -99,7 +100,7 @@ public class SysTenantController { */ @RequestMapping(value = "/delete", method = RequestMethod.DELETE) public Result delete(@RequestParam(name="id",required=true) String id) { - sysTenantService.removeById(id); + sysTenantService.removeTenantById(id); return Result.OK("删除成功"); } @@ -114,9 +115,25 @@ public class SysTenantController { if(oConvertUtils.isEmpty(ids)) { result.error500("未选中租户!"); }else { - List ls = Arrays.asList(ids.split(",")); - sysTenantService.removeByIds(ls); - result.success("删除成功!"); + String[] ls = ids.split(","); + // 过滤掉已被引用的租户 + List idList = new ArrayList<>(); + for (String id : ls) { + int userCount = sysTenantService.countUserLinkTenant(id); + if (userCount == 0) { + idList.add(id); + } + } + if (idList.size() > 0) { + sysTenantService.removeByIds(idList); + if (ls.length == idList.size()) { + result.success("删除成功!"); + } else { + result.success("部分删除成功!(被引用的租户无法删除)"); + } + }else { + result.error500("选择的租户都已被引用,无法删除!"); + } } return result; } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserController.java index 8d14cd63..0d29f24c 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserController.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserController.java @@ -944,43 +944,6 @@ public class SysUserController { return result; } - /** - * 根据用户名或手机号查询用户信息 - * @param - * @return - */ - @RequiresPermissions("sys:user:list") - @GetMapping("/querySysUser") - public Result> querySysUser(SysUser sysUser) { - String phone = sysUser.getPhone(); - String username = sysUser.getUsername(); - Result> result = new Result>(); - Map map = new HashMap(); - if (oConvertUtils.isNotEmpty(phone)) { - SysUser user = sysUserService.getUserByPhone(phone); - if(user!=null) { - map.put("username",user.getUsername()); - map.put("phone",user.getPhone()); - result.setSuccess(true); - result.setResult(map); - return result; - } - } - if (oConvertUtils.isNotEmpty(username)) { - SysUser user = sysUserService.getUserByName(username); - if(user!=null) { - map.put("username",user.getUsername()); - map.put("phone",user.getPhone()); - result.setSuccess(true); - result.setResult(map); - return result; - } - } - result.setSuccess(false); - result.setMessage("验证失败"); - return result; - } - /** * 用户手机号验证 */ @@ -1031,7 +994,7 @@ public class SysUserController { result.setSuccess(false); return result; } - if(!smscode.equals(object)) { + if(!smscode.equals(object.toString())) { result.setMessage("短信验证码不匹配!"); result.setSuccess(false); return result; @@ -1355,7 +1318,7 @@ public class SysUserController { result.setSuccess(false); return result; } - if(!smscode.equals(object)) { + if(!smscode.equals(object.toString())) { result.setMessage("短信验证码不匹配!"); result.setSuccess(false); return result; @@ -1368,5 +1331,21 @@ public class SysUserController { sysUserService.updateById(user); return Result.OK("手机号设置成功!"); } + + /** + * 根据对象里面的属性值作in查询 属性可能会变 用户组件用到 + * @param sysUser + * @return + */ + @GetMapping("/getMultiUser") + public List getMultiUser(SysUser sysUser){ + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(sysUser, null); + List ls = this.sysUserService.list(queryWrapper); + for(SysUser user: ls){ + user.setPassword(null); + user.setSalt(null); + } + return ls; + } } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserOnlineController.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserOnlineController.java new file mode 100644 index 00000000..f22b5019 --- /dev/null +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/SysUserOnlineController.java @@ -0,0 +1,128 @@ +package com.jero.modules.system.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.apache.shiro.SecurityUtils; +import com.jero.common.api.vo.Result; +import com.jero.common.constant.CacheConstant; +import com.jero.common.constant.CommonConstant; +import com.jero.common.system.api.ISysBaseAPI; +import com.jero.common.system.util.JwtUtil; +import com.jero.common.system.vo.LoginUser; +import com.jero.common.util.RedisUtil; +import com.jero.common.util.oConvertUtils; +import com.jero.modules.base.service.BaseCommonService; +import com.jero.modules.system.service.ISysUserService; +import com.jero.modules.system.vo.SysUserOnlineVO; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @Description: 在线用户 + * @Author: chenli + * @Date: 2020-06-07 + * @Version: V1.0 + */ +@RestController +@RequestMapping("/sys/online") +@Slf4j +public class SysUserOnlineController { + + @Autowired + private RedisUtil redisUtil; + + @Autowired + public RedisTemplate redisTemplate; + + @Autowired + public ISysUserService userService; + + @Autowired + private ISysBaseAPI sysBaseAPI; + + @Resource + private BaseCommonService baseCommonService; + + @RequestMapping(value = "/list", method = RequestMethod.GET) + public Result> list(@RequestParam(name="username", required=false) String username, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize) { + Collection keys = redisTemplate.keys(CommonConstant.PREFIX_USER_TOKEN + "*"); + SysUserOnlineVO online; + List onlineList = new ArrayList(); + for (String key : keys) { + online = new SysUserOnlineVO(); + String token = (String) redisUtil.get(key); + if (!StringUtils.isEmpty(token)){ + online.setToken(token); + LoginUser loginUser = sysBaseAPI.getUserByName(JwtUtil.getUsername(token)); + BeanUtils.copyProperties(loginUser, online); + if (StringUtils.isNotEmpty(username)) { + if (StringUtils.equals(username, online.getUsername())) { + onlineList.add(online); + } + } else { + onlineList.add(online); + } + } + } + + Page page = new Page(pageNo, pageSize); + int count = onlineList.size(); + List pages = new ArrayList<>(); + //计算当前页第一条数据的下标 + int currId = pageNo>1 ? (pageNo-1)*pageSize:0; + for (int i=0; i> result = new Result>(); + result.setSuccess(true); + result.setResult(page); + return result; + } + + /** + * 强退用户 + */ + @RequestMapping(value = "/forceLogout",method = RequestMethod.POST) + public Result forceLogout(@RequestBody SysUserOnlineVO online) { + //用户退出逻辑 + if(oConvertUtils.isEmpty(online.getToken())) { + return Result.error("退出登录失败!"); + } + String username = JwtUtil.getUsername(online.getToken()); + LoginUser sysUser = sysBaseAPI.getUserByName(username); + if(sysUser!=null) { + baseCommonService.addLog("强制: "+sysUser.getRealname()+"退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser); + log.info(" 强制 "+sysUser.getRealname()+"退出成功! "); + //清空用户登录Token缓存 + redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + online.getToken()); + //清空用户登录Shiro权限缓存 + redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId()); + //清空用户的缓存信息(包括部门信息),例如sys:cache:user:: + redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername())); + //调用shiro的logout + SecurityUtils.getSubject().logout(); + return Result.ok("退出登录成功!"); + }else { + return Result.error("Token无效!"); + } + } +} diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysDictMapper.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysDictMapper.java index 74790f66..1aa57bb2 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysDictMapper.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysDictMapper.java @@ -5,6 +5,7 @@ import java.util.Map; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.jero.common.system.vo.DictModelMany; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.ResultType; import org.apache.ibatis.annotations.Select; @@ -31,12 +32,29 @@ public interface SysDictMapper extends BaseMapper { * 重复检查SQL * @return */ + @Deprecated public Long duplicateCheckCountSql(DuplicateCheckVo duplicateCheckVo); - + @Deprecated public Long duplicateCheckCountSqlNoDataId(DuplicateCheckVo duplicateCheckVo); public List queryDictItemsByCode(@Param("code") String code); + /** + * 查询有效的数据字典项 + * @param code + * @return + */ + List queryEnableDictItemsByCode(@Param("code") String code); + + + /** + * 通过多个字典code获取字典数据 + * + * @param dictCodeList + * @return + */ + public List queryDictItemsByCodeList(@Param("dictCodeList") List dictCodeList); + @Deprecated public List queryTableDictItemsByCode(@Param("table") String table,@Param("text") String text,@Param("code") String code); @@ -49,9 +67,29 @@ public interface SysDictMapper extends BaseMapper { public String queryDictTextByKey(@Param("code") String code,@Param("key") String key); + /** + * 可通过多个字典code查询翻译文本 + * @param dictCodeList 多个字典code + * @param keys 数据列表 + * @return + */ + List queryManyDictByKeys(@Param("dictCodeList") List dictCodeList, @Param("keys") List keys); + @Deprecated public String queryTableDictTextByKey(@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("key") String key); + /** + * 通过查询指定table的 text code key 获取字典值,可批量查询 + * + * @param table + * @param text + * @param code + * @param keys + * @return + */ + @Deprecated + List queryTableDictTextByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keys") List keys); + @Deprecated public List queryTableDictByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keyArray") String[] keyArray); @@ -163,6 +201,7 @@ public interface SysDictMapper extends BaseMapper { * @param filterSql * @return */ + @Deprecated IPage queryTableDictWithFilter(Page page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql); /** @@ -173,5 +212,6 @@ public interface SysDictMapper extends BaseMapper { * @param filterSql * @return */ + @Deprecated List queryAllTableDictItems(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql); } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysUserMapper.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysUserMapper.java index 0032e1c0..db14aad4 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysUserMapper.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/SysUserMapper.java @@ -131,6 +131,7 @@ public interface SysUserMapper extends BaseMapper { int deleteLogicDeleted(@Param("userIds") String userIds); /** 更新空字符串为null【此写法有sql注入风险,禁止随便用】 */ + @Deprecated int updateNullByEmptyString(@Param("fieldName") String fieldName); /** diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/xml/SysDictMapper.xml b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/xml/SysDictMapper.xml index e109acb1..fe5108d9 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/xml/SysDictMapper.xml +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/mapper/xml/SysDictMapper.xml @@ -8,7 +8,32 @@ where dict_id = (select id from sys_dict where dict_code = #{code}) order by s.sort_order asc - + + + + + + + + + + + + - - select count(*) as visit - ,count(distinct(ip)) as ip - ,DATE_FORMAT(create_time, '%Y-%m-%d') as tian - ,DATE_FORMAT(create_time, '%m-%d') as type - from sys_log - where log_type = 1 and create_time >= #{dayStart} and create_time < #{dayEnd} - group by tian,type - order by tian asc + + select count(*) as visit + ,count(distinct(ip)) as ip + ,DATE_FORMAT(create_time, '%Y-%m-%d') as tian + ,DATE_FORMAT(create_time, '%m-%d') as type + from sys_log + where log_type = 1 and create_time >= #{dayStart} and create_time < #{dayEnd} + group by tian,type + order by tian asc - + + select count(*) as visit + ,count(distinct(ip)) as ip + ,to_char(create_time, 'yyyy-mm-dd') as tian + ,to_char(create_time, 'mm-dd') as type + from sys_log + where log_type = 1 and create_time >= #{dayStart} and create_time < #{dayEnd} + group by to_char(create_time, 'yyyy-mm-dd'),to_char(create_time, 'mm-dd') + order by to_char(create_time, 'yyyy-mm-dd') asc + + select count(*) as visit ,count(distinct(ip)) as ip ,to_char(create_time, 'yyyy-mm-dd') as tian ,to_char(create_time, 'mm-dd') as type from sys_log where log_type = 1 and create_time >= #{dayStart} and create_time < #{dayEnd} - group by to_char(create_time, 'yyyy-mm-dd'),to_char(create_time, 'mm-dd') - order by to_char(create_time, 'yyyy-mm-dd') asc - - - select count(*) as visit - ,count(distinct(ip)) as ip - ,to_char(create_time, 'yyyy-mm-dd') as tian - ,to_char(create_time, 'mm-dd') as type - from sys_log - where log_type = 1 and create_time >= #{dayStart} and create_time < #{dayEnd} group by tian,type order by tian asc - + select count(*) as visit ,count(distinct(ip)) as ip ,CONVERT(varchar(100), create_time, 23) as tian diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysDictService.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysDictService.java index 441978b0..65a8bf49 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysDictService.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysDictService.java @@ -22,7 +22,22 @@ public interface ISysDictService extends IService { public List queryDictItemsByCode(String code); - public Map> queryAllDictItems(); + /** + * 查询有效的数据字典项 + * @param code + * @return + */ + List queryEnableDictItemsByCode(String code); + + /** + * 通过多个字典code获取字典数据 + * + * @param dictCodeList + * @return key = 字典code,value=对应的字典选项 + */ + Map> queryDictItemsByCodeList(List dictCodeList); + + public Map> queryAllDictItems(); @Deprecated List queryTableDictItemsByCode(String table, String text, String code); @@ -32,9 +47,28 @@ public interface ISysDictService extends IService { public String queryDictTextByKey(String code, String key); - @Deprecated + /** + * 可通过多个字典code查询翻译文本 + * @param dictCodeList 多个字典code + * @param keys 数据列表 + * @return + */ + Map> queryManyDictByKeys(List dictCodeList, List keys); + + @Deprecated String queryTableDictTextByKey(String table, String text, String code, String key); + /** + * 通过查询指定table的 text code key 获取字典值,可批量查询 + * + * @param table + * @param text + * @param code + * @param keys + * @return + */ + List queryTableDictTextByKeys(String table, String text, String code, List keys); + @Deprecated List queryTableDictByKeys(String table, String text, String code, String keys); diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysTenantService.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysTenantService.java index 0d4fef0c..827c6333 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysTenantService.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/ISysTenantService.java @@ -3,6 +3,33 @@ package com.jero.modules.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jero.modules.system.entity.SysTenant; +import java.util.Collection; +import java.util.List; + public interface ISysTenantService extends IService { + /** + * 查询有效的租户 + * + * @param idList + * @return + */ + List queryEffectiveTenant(Collection idList); + + /** + * 返回某个租户被多少个用户引用了 + * + * @param id + * @return + */ + int countUserLinkTenant(String id); + + /** + * 根据ID删除租户,会判断是否已被引用 + * + * @param id + * @return + */ + boolean removeTenantById(String id); + } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/LoginServiceImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/LoginServiceImpl.java index c7cce4ef..1631cf5f 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/LoginServiceImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/LoginServiceImpl.java @@ -16,6 +16,7 @@ import com.jero.common.util.*; import com.jero.common.util.encryption.EncryptedString; import com.jero.modules.base.service.BaseCommonService; import com.jero.modules.system.entity.SysDepart; +import com.jero.modules.system.entity.SysTenant; import com.jero.modules.system.entity.SysUser; import com.jero.modules.system.model.SysLoginModel; import com.jero.modules.system.model.TreeSelectModel; @@ -52,6 +53,8 @@ public class LoginServiceImpl implements ILoginService { @Autowired private ISysDepartService sysDepartService; @Autowired + private ISysTenantService sysTenantService; + @Autowired private ISysDictService sysDictService; @Resource private BaseCommonService baseCommonService; @@ -457,11 +460,6 @@ public class LoginServiceImpl implements ILoginService { private Result userInfo(SysUser sysUser, Result result) { String syspassword = sysUser.getPassword(); String username = sysUser.getUsername(); - // 生成token - String token = JwtUtil.sign(username, syspassword); - // 设置token缓存有效时间 - redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); - redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000); // 获取用户部门信息 JSONObject obj = new JSONObject(); @@ -482,6 +480,27 @@ public class LoginServiceImpl implements ILoginService { // update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去 obj.put("multi_depart", 2); } + + // update-begin--Author:sunjianlei Date:20210802 for:获取用户租户信息 + String tenantIds = sysUser.getRelTenantIds(); + if (oConvertUtils.isNotEmpty(tenantIds)) { + List tenantIdList = Arrays.asList(tenantIds.split(",")); + // 该方法仅查询有效的租户,如果返回0个就说明所有的租户均无效。 + List tenantList = sysTenantService.queryEffectiveTenant(tenantIdList); + if (tenantList.size() == 0) { + result.error500("与该用户关联的租户均已被冻结,无法登录!"); + return result; + } else { + obj.put("tenantList", tenantList); + } + } + // update-end--Author:sunjianlei Date:20210802 for:获取用户租户信息 + // 生成token + String token = JwtUtil.sign(username, syspassword); + // 设置token缓存有效时间 + redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); + redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000); + obj.put("token", token); obj.put("userInfo", sysUser); obj.put("sysAllDictItems", sysDictService.queryAllDictItems()); diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysBaseApiImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysBaseApiImpl.java index 5133f4a8..198598cb 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysBaseApiImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysBaseApiImpl.java @@ -93,6 +93,9 @@ public class SysBaseApiImpl implements ISysBaseAPI { @Autowired private ISysPermissionDataRuleService sysPermissionDataRuleService; + @Autowired + ISysCategoryService sysCategoryService; + @Override @Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username") public LoginUser getUserByName(String username) { @@ -272,6 +275,12 @@ public class SysBaseApiImpl implements ISysBaseAPI { return sysDictService.queryDictItemsByCode(code); } + @Override + @Cacheable(value = CacheConstant.SYS_ENABLE_DICT_CACHE,key = "#code", unless = "#result == null ") + public List queryEnableDictItemsByCode(String code) { + return sysDictService.queryEnableDictItemsByCode(code); + } + @Override public List queryTableDictItemsByCode(String table, String text, String code) { //update-begin-author:taoyan date:20200820 for:【Online+系统】字典表加权限控制机制逻辑,想法不错 LOWCOD-799 @@ -1055,5 +1064,80 @@ public class SysBaseApiImpl implements ISysBaseAPI { } return null; } + /** + * 查询分类字典翻译 + * + * @param ids 分类字典表id + * @return + */ + @Override + public List loadCategoryDictItem(String ids) { + return sysCategoryService.loadDictItem(ids, false); + } + + /** + * 根据字典code加载字典text + * + * @param dictCode 顺序:tableName,text,code + * @param keys 要查询的key + * @return + */ + @Override + public List loadDictItem(String dictCode, String keys) { + String[] params = dictCode.split(","); + return sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys, false); + } + + /** + * 根据字典code查询字典项 + * + * @param dictCode 顺序:tableName,text,code + * @param dictCode 要查询的key + * @return + */ + @Override + public List getDictItems(String dictCode) { + List ls = sysDictService.getDictItems(dictCode); + if (ls == null) { + ls = new ArrayList<>(); + } + return ls; + } + + /** + * 根据多个字典code查询多个字典项 + * + * @param dictCodeList + * @return key = dictCode ; value=对应的字典项 + */ + @Override + public Map> getManyDictItems(List dictCodeList) { + return sysDictService.queryDictItemsByCodeList(dictCodeList); + } + + /** + * 【下拉搜索】 + * 大数据量的字典表 走异步加载,即前端输入内容过滤数据 + * + * @param dictCode 字典code格式:table,text,code + * @param keyword 过滤关键字 + * @return + */ + @Override + public List loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) { + return sysDictService.loadDict(dictCode, keyword, pageSize); + } + + @Override + public Map> translateManyDict(String dictCodes, String keys) { + List dictCodeList = Arrays.asList(dictCodes.split(",")); + List values = Arrays.asList(keys.split(",")); + return sysDictService.queryManyDictByKeys(dictCodeList, values); + } + + @Override + public List translateDictFromTableByKeys(String table, String text, String code, String keys) { + return sysDictService.queryTableDictTextByKeys(table, text, code, Arrays.asList(keys.split(","))); + } } \ No newline at end of file diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysDictServiceImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysDictServiceImpl.java index 9679ed19..ba3e5415 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysDictServiceImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysDictServiceImpl.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jero.common.system.vo.DictModelMany; import com.jero.common.util.SqlInjectionUtil; import lombok.extern.slf4j.Slf4j; import com.jero.common.constant.CacheConstant; @@ -60,6 +61,25 @@ public class SysDictServiceImpl extends ServiceImpl impl return sysDictMapper.queryDictItemsByCode(code); } + @Override + @Cacheable(value = CacheConstant.SYS_ENABLE_DICT_CACHE,key = "#code", unless = "#result == null ") + public List queryEnableDictItemsByCode(String code) { + log.debug("无缓存dictCache的时候调用这里!"); + return sysDictMapper.queryEnableDictItemsByCode(code); + } + + @Override + public Map> queryDictItemsByCodeList(List dictCodeList) { + List list = sysDictMapper.queryDictItemsByCodeList(dictCodeList); + Map> dictMap = new HashMap<>(); + for (DictModelMany dict : list) { + List dictItemList = dictMap.computeIfAbsent(dict.getDictCode(), i -> new ArrayList<>()); + dict.setDictCode(null); + dictItemList.add(new DictModel(dict.getValue(), dict.getText())); + } + return dictMap; + } + @Override public Map> queryAllDictItems() { Map> res = new HashMap>(); @@ -96,6 +116,17 @@ public class SysDictServiceImpl extends ServiceImpl impl return sysDictMapper.queryDictTextByKey(code, key); } + @Override + public Map> queryManyDictByKeys(List dictCodeList, List keys) { + List list = sysDictMapper.queryManyDictByKeys(dictCodeList, keys); + Map> dictMap = new HashMap<>(); + for (DictModelMany dict : list) { + List dictItemList = dictMap.computeIfAbsent(dict.getDictCode(), i -> new ArrayList<>()); + dictItemList.add(new DictModel(dict.getValue(), dict.getText())); + } + return dictMap; + } + /** * 通过查询指定table的 text code 获取字典 * dictTableCache采用redis缓存有效期10分钟 @@ -133,6 +164,11 @@ public class SysDictServiceImpl extends ServiceImpl impl return sysDictMapper.queryTableDictTextByKey(table,text,code,key); } + @Override + public List queryTableDictTextByKeys(String table, String text, String code, List keys) { + return sysDictMapper.queryTableDictTextByKeys(table, text, code, keys); + } + @Override public List queryTableDictByKeys(String table, String text, String code, String keys) { return this.queryTableDictByKeys(table, text, code, keys, true); @@ -406,6 +442,7 @@ public class SysDictServiceImpl extends ServiceImpl impl public void refreshCache() { //清空字典缓存 Set keys = redisTemplate.keys(CacheConstant.SYS_DICT_CACHE + "*"); + Set keys7 = redisTemplate.keys(CacheConstant.SYS_ENABLE_DICT_CACHE + "*"); Set keys2 = redisTemplate.keys(CacheConstant.SYS_DICT_TABLE_CACHE + "*"); Set keys21 = redisTemplate.keys(CacheConstant.SYS_DICT_TABLE_BY_KEYS_CACHE + "*"); Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*"); @@ -419,5 +456,6 @@ public class SysDictServiceImpl extends ServiceImpl impl redisTemplate.delete(keys4); redisTemplate.delete(keys5); redisTemplate.delete(keys6); + redisTemplate.delete(keys7); } } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysLogServiceImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysLogServiceImpl.java index fc25d3d9..9a119665 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysLogServiceImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysLogServiceImpl.java @@ -7,6 +7,7 @@ import java.util.Map; import javax.annotation.Resource; +import com.baomidou.mybatisplus.annotation.DbType; import com.jero.common.system.api.ISysBaseAPI; import com.jero.common.util.CommonUtils; import com.jero.modules.system.entity.SysLog; @@ -60,7 +61,7 @@ public class SysLogServiceImpl extends ServiceImpl impleme @Override public List> findVisitCount(Date dayStart, Date dayEnd) { - String dbType = CommonUtils.getDatabaseType(); - return sysLogMapper.findVisitCount(dayStart, dayEnd,dbType); + DbType dbType = CommonUtils.getDatabaseTypeEnum(); + return sysLogMapper.findVisitCount(dayStart, dayEnd,dbType.getDb()); } } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysTenantServiceImpl.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysTenantServiceImpl.java index 26dd764a..cfea215c 100644 --- a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysTenantServiceImpl.java +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/service/impl/SysTenantServiceImpl.java @@ -1,15 +1,56 @@ package com.jero.modules.system.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jero.common.constant.CommonConstant; +import com.jero.common.exception.JeroBootException; +import com.jero.modules.system.entity.SysUser; +import com.jero.modules.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import com.jero.modules.system.entity.SysTenant; import com.jero.modules.system.mapper.SysTenantMapper; import com.jero.modules.system.service.ISysTenantService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Collection; +import java.util.List; + @Service @Slf4j public class SysTenantServiceImpl extends ServiceImpl implements ISysTenantService { - + + @Autowired + ISysUserService userService; + + @Override + public List queryEffectiveTenant(Collection idList) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SysTenant::getId, idList); + queryWrapper.eq(SysTenant::getStatus, CommonConstant.STATUS_1); + //此处查询忽略时间条件 + return super.list(queryWrapper); + } + + @Override + public int countUserLinkTenant(String id) { + LambdaQueryWrapper userQueryWrapper = new LambdaQueryWrapper<>(); + userQueryWrapper.eq(SysUser::getRelTenantIds, id); + userQueryWrapper.or().like(SysUser::getRelTenantIds, "%," + id); + userQueryWrapper.or().like(SysUser::getRelTenantIds, id + ",%"); + userQueryWrapper.or().like(SysUser::getRelTenantIds, "%," + id + ",%"); + // 查找出已被关联的用户数量 + return userService.count(userQueryWrapper); + } + + @Override + public boolean removeTenantById(String id) { + // 查找出已被关联的用户数量 + int userCount = this.countUserLinkTenant(id); + if (userCount > 0) { + throw new JeroBootException("该租户已被引用,无法删除!"); + } + return super.removeById(id); + } } diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/util/XSSUtils.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/util/XSSUtils.java new file mode 100644 index 00000000..5508f065 --- /dev/null +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/util/XSSUtils.java @@ -0,0 +1,44 @@ +package com.jero.modules.system.util; + +import org.springframework.web.util.HtmlUtils; + +import java.util.regex.Pattern; + +/** + * @Description: 工具类XSSUtils,现在的做法是替换成空字符,CSDN的是进行转义,比如文字开头的"<"转成< + * @author: lsq + * @date: 2021年07月26日 19:13 + */ +public class XSSUtils { + public static String striptXSS(String value) { + if (value != null) { + value = value.replaceAll(" ", ""); + Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); + value = scriptPattern.matcher(value).replaceAll(""); + scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); + value = scriptPattern.matcher(value).replaceAll(""); + } + return HtmlUtils.htmlEscape(value); + } + + public static void main(String[] args) { + String s = striptXSS("javascript:eval()\\\\."); + System.err.println("s======>" + s); + } +} diff --git a/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/vo/SysUserOnlineVO.java b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/vo/SysUserOnlineVO.java new file mode 100644 index 00000000..d4ddaa92 --- /dev/null +++ b/jero-boot/jero-boot-module-system/src/main/java/com/jero/modules/system/vo/SysUserOnlineVO.java @@ -0,0 +1,60 @@ +package com.jero.modules.system.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import com.jero.common.aspect.annotation.Dict; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * + * @Author: chenli + * @Date: 2020-06-07 + * @Version: V1.0 + */ +@Data +public class SysUserOnlineVO { + /** + * 会话id + */ + private String id; + + /** + * 会话编号 + */ + private String token; + + /** + * 用户名 + */ + private String username; + + /** + * 用户名 + */ + private String realname; + + /** + * 头像 + */ + private String avatar; + + /** + * 生日 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date birthday; + + /** + * 性别(1:男 2:女) + */ + @Dict(dicCode = "sex") + private Integer sex; + + /** + * 手机号 + */ + private String phone; +} diff --git a/jero-boot/jero-boot-single-startup/pom.xml b/jero-boot/jero-boot-single-startup/pom.xml index d28db47d..6050932b 100644 --- a/jero-boot/jero-boot-single-startup/pom.xml +++ b/jero-boot/jero-boot-single-startup/pom.xml @@ -5,7 +5,7 @@ jero-boot com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml b/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml index 1fc0a974..07ad748f 100644 --- a/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml +++ b/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml @@ -39,7 +39,7 @@ spring: quartz: job-store-type: jdbc initialize-schema: embedded - #设置自动启动,默认为 true + #定时任务启动开关,true-开 false-关 auto-startup: true #启动时更新己存在的Job overwrite-existing-jobs: true @@ -118,7 +118,7 @@ spring: timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 - validationQuery: SELECT 1 FROM DUAL + validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false @@ -176,6 +176,8 @@ mybatis-plus: call-setters-on-nulls: true #jero专用配置 jero : + # 签名密钥串(前后端要一致,正式发布请自行修改) + signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: local path : @@ -191,7 +193,7 @@ jero : accessKey: ?? secretKey: ?? bucketName: jeroos - staticDomain: ?? + staticDomain: jerodev # ElasticSearch 6设置 elasticsearch: cluster-name: jero-ES @@ -236,11 +238,11 @@ jero : port: 30007 logPath: logs/jero/job/jobhandler/ logRetentionDays: 30 - #自定义路由配置 yml nacos database route: config: data-id: jero-gateway-router group: DEFAULT_GROUP + #自定义路由配置 yml nacos database data-type: yml #分布式锁配置 redisson: @@ -261,6 +263,9 @@ logging: com.jero.modules.system.mapper : info #swagger knife4j: + #开启增强配置 + enable: true + #开启生产环境屏蔽 production: false basic: enable: false diff --git a/jero-boot/jero-boot-single-startup/src/main/resources/application-prod.yml b/jero-boot/jero-boot-single-startup/src/main/resources/application-prod.yml index b7112cfa..f568b45c 100644 --- a/jero-boot/jero-boot-single-startup/src/main/resources/application-prod.yml +++ b/jero-boot/jero-boot-single-startup/src/main/resources/application-prod.yml @@ -39,7 +39,7 @@ spring: quartz: job-store-type: jdbc initialize-schema: embedded - #设置自动启动,默认为 true + #定时任务启动开关,true-开 false-关 auto-startup: true #启动时更新己存在的Job overwrite-existing-jobs: true @@ -172,6 +172,8 @@ mybatis-plus: call-setters-on-nulls: true #jero专用配置 jero : + # 签名密钥串(前后端要一致,正式发布请自行修改) + signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: alioss path : @@ -183,15 +185,15 @@ jero : excludeUrls: /test/jeroDemo/demo3,/test/jeroDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/** #阿里云oss存储配置 oss: - endpoint: oss-cn-beijing.aliyuncs.com accessKey: ?? secretKey: ?? - bucketName: jeroos + endpoint: oss-cn-beijing.aliyuncs.com + bucketName: jero staticDomain: https://static.jero.com # ElasticSearch 设置 elasticsearch: cluster-name: jero-ES - cluster-nodes: 111.225.222.176:9200 + cluster-nodes: ?? check-enabled: true # 表单设计器配置 desform: @@ -232,11 +234,11 @@ jero : port: 30007 logPath: logs/jero/job/jobhandler/ logRetentionDays: 30 - #自定义路由配置 yml nacos database route: config: data-id: jero-gateway-router group: DEFAULT_GROUP + #自定义路由配置 yml nacos database data-type: yml #分布式锁配置 redisson: @@ -257,7 +259,10 @@ logging: com.jero.modules.system.mapper : info #swagger knife4j: - production: false + #开启增强配置 + enable: true + #开启生产环境屏蔽 + production: true basic: enable: true username: jero diff --git a/jero-boot/jero-boot-single-startup/src/main/resources/application-test.yml b/jero-boot/jero-boot-single-startup/src/main/resources/application-test.yml index ac7de9c8..781a87eb 100644 --- a/jero-boot/jero-boot-single-startup/src/main/resources/application-test.yml +++ b/jero-boot/jero-boot-single-startup/src/main/resources/application-test.yml @@ -39,7 +39,7 @@ spring: quartz: job-store-type: jdbc initialize-schema: embedded - #设置自动启动,默认为 true + #定时任务启动开关,true-开 false-关 auto-startup: true #启动时更新己存在的Job overwrite-existing-jobs: true @@ -172,6 +172,8 @@ mybatis-plus: call-setters-on-nulls: true #jero专用配置 jero : + # 签名密钥串(前后端要一致,正式发布请自行修改) + signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: local path : @@ -232,12 +234,12 @@ jero : port: 30007 logPath: logs/jero/job/jobhandler/ logRetentionDays: 30 - #自定义路由配置 yml nacos database route: config: data-id: jero-gateway-router group: DEFAULT_GROUP - data-type: yml + #自定义路由配置 yml nacos database + data-type: database #分布式锁配置 redisson: address: 127.0.0.1:4780 @@ -257,6 +259,9 @@ cas: prefixUrl: http://cas.example.org:8443/cas #swagger knife4j: + #开启增强配置 + enable: true + #开启生产环境屏蔽 production: false basic: enable: false diff --git a/jero-boot/jero-boot-single-startup/src/main/resources/banner.txt b/jero-boot/jero-boot-single-startup/src/main/resources/banner.txt index 08cb8a0c..bf9441c3 100644 --- a/jero-boot/jero-boot-single-startup/src/main/resources/banner.txt +++ b/jero-boot/jero-boot-single-startup/src/main/resources/banner.txt @@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE} ${AnsiColor.BRIGHT_GREEN} -jero Boot Version: 2.4.3 +jero Boot Version: 2.4.6 Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version} ${AnsiColor.BLACK} diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero.yaml b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jeecg.yaml similarity index 99% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero.yaml rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jeecg.yaml index 7018e6b7..17a444bc 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero.yaml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jeecg.yaml @@ -29,7 +29,7 @@ spring: max-request-size: 10MB mail: host: smtp.163.com - username: test@163.com + username: jeroos@163.com password: ?? properties: mail: diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-dev.yaml b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-dev.yaml similarity index 81% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-dev.yaml rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-dev.yaml index 07e86623..47852fd3 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-dev.yaml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-dev.yaml @@ -35,9 +35,9 @@ spring: datasource: master: - url: jdbc:mysql://127.0.0.1:3306/jero-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai - username: root - password: root + url: jdbc:mysql://${MYSQL-HOST:jero-boot-mysql}:${MYSQL-PORT:3306}/${MYSQL-DB:jero-boot}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai + username: ${MYSQL-USER:root} + password: ${MYSQL-PWD:root} driver-class-name: com.mysql.cj.jdbc.Driver # 多数据源配置 #multi-datasource1: @@ -48,7 +48,7 @@ spring: #redis 配置 redis: database: 0 - host: 127.0.0.1 + host: jero-boot-redis lettuce: pool: max-active: 8 #最大连接数据库连接数,设 0 为没有限制 @@ -57,10 +57,10 @@ spring: min-idle: 0 #最小等待连接中的数量,设 0 为没有限制 shutdown-timeout: 100ms password: - port: 4780 + port: 6379 #rabbitmq配置 rabbitmq: - host: 127.0.0.1 + host: jero-boot-rabbitmq username: guest password: guest port: 5672 @@ -77,6 +77,9 @@ spring: #是否支持重试 retry: enabled: true +#minidao +minidao : + base-package: com.jero.modules.jmreport.* #jero专用配置 jero : # 本地:local\Minio:minio\阿里云:alioss @@ -87,13 +90,13 @@ jero : #webapp文件路径 webapp: D://opt//webapp shiro: - excludeUrls: /test/jeroDemo/demo3,/test/jeroDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/** + excludeUrls: /test/jeroDemo/demo3,/test/jeroDemo/redisDemo/**,/category/**,/map/**,/jmreport/bigscreen2/** #阿里云oss存储配置 oss: endpoint: oss-cn-beijing.aliyuncs.com accessKey: ?? secretKey: ?? - bucketName: jeroos + bucketName: jerodev staticDomain: ?? # ElasticSearch 6设置 elasticsearch: @@ -106,6 +109,9 @@ jero : theme-color: "#1890ff" # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置) upload-type: system + map: + # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home + baidu: ?? # 在线预览文件服务器地址配置 file-view-domain: 127.0.0.1:8012 # minio文件上传 @@ -129,7 +135,7 @@ jero : #xxl-job配置 xxljob: enabled: false - adminAddresses: http://127.0.0.1:9080/xxl-job-admin + adminAddresses: http://jero-boot-xxljob:9080/xxl-job-admin appname: ${spring.application.name} accessToken: '' logPath: logs/jero/job/jobhandler/ @@ -142,7 +148,7 @@ jero : data-type: yml #分布式锁配置 redisson: - address: 127.0.0.1:4780 + address: jero-boot-redis:6379 password: type: STANDALONE enabled: true @@ -157,7 +163,7 @@ cas: knife4j: production: false basic: - enable: false + enable: true username: jero password: jero1314 @@ -182,3 +188,25 @@ justauth: type: default prefix: 'demo::' timeout: 1h +#第三方APP对接 +third-app: + enabled: false + type: + #企业微信 + WECHAT_ENTERPRISE: + enabled: false + #CORP_ID + client-id: ?? + #SECRET + client-secret: ?? + agent-id: ?? + #自建应用秘钥(新版企微需要配置) + # agent-app-secret: ?? + #钉钉 + DINGTALK: + enabled: false + # appKey + client-id: ?? + # appSecret + client-secret: ?? + agent-id: ?? diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-gateway-router.json b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-gateway-router.json similarity index 82% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-gateway-router.json rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-gateway-router.json index 22323330..a9120ced 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/nacos/jero-gateway-router.json +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/nacos/jero-gateway-router.json @@ -1,5 +1,5 @@ [{ - "id": "jero-system", + "id": "jeecg-system", "order": 0, "predicates": [{ "name": "Path", @@ -18,9 +18,9 @@ } }], "filters": [], - "uri": "lb://jero-system" + "uri": "lb://jeecg-system" }, { - "id": "jero-demo", + "id": "jeecg-demo", "order": 1, "predicates": [{ "name": "Path", @@ -32,9 +32,9 @@ } }], "filters": [], - "uri": "lb://jero-demo" + "uri": "lb://jeecg-demo" }, { - "id": "jero-system-websocket", + "id": "jeecg-system-websocket", "order": 2, "predicates": [{ "name": "Path", @@ -45,9 +45,9 @@ } }], "filters": [], - "uri": "lb:ws://jero-system" + "uri": "lb:ws://jeecg-system" }, { - "id": "jero-demo-websocket", + "id": "jeecg-demo-websocket", "order": 3, "predicates": [{ "name": "Path", @@ -56,5 +56,5 @@ } }], "filters": [], - "uri": "lb:ws://jero-demo" + "uri": "lb:ws://jeecg-demo" }] \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/pom.xml b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/pom.xml similarity index 90% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/pom.xml rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/pom.xml index 389e89e5..2a6d29be 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/pom.xml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/pom.xml @@ -3,13 +3,12 @@ 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"> - jero-cloud-module + jero-boot-starter com.jero.boot - 2.4.3 + 2.4.6 4.0.0 - - jero-cloud-feign-config + jero-boot-starter-cloud diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/config/FeignConfig.java b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/config/FeignConfig.java new file mode 100644 index 00000000..f5b73e94 --- /dev/null +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/config/FeignConfig.java @@ -0,0 +1,161 @@ +package com.jero.config; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer; +import feign.Feign; +import feign.Logger; +import feign.RequestInterceptor; +import feign.codec.Decoder; +import feign.codec.Encoder; +import feign.form.spring.SpringFormEncoder; +import lombok.extern.slf4j.Slf4j; +import com.jero.common.config.mqtoken.UserTokenContext; +import com.jero.common.constant.CommonConstant; +import com.jero.common.util.DateUtils; +import com.jero.common.util.PathMatcherUtil; +import com.jero.config.sign.interceptor.SignAuthConfiguration; +import com.jero.config.sign.util.HttpUtils; +import com.jero.config.sign.util.SignUtil; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.cloud.openfeign.support.SpringDecoder; +import org.springframework.cloud.openfeign.support.SpringEncoder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Scope; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.SortedMap; + +@ConditionalOnClass(Feign.class) +@AutoConfigureBefore(FeignAutoConfiguration.class) +@Slf4j +@Configuration +public class FeignConfig { + + @Bean + public RequestInterceptor requestInterceptor() { + return requestTemplate -> { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (null != attributes) { + HttpServletRequest request = attributes.getRequest(); + log.debug("Feign request: {}", request.getRequestURI()); + // 将token信息放入header中 + String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); + if(token==null || "".equals(token)){ + token = request.getParameter("token"); + } + log.debug("Feign request token: {}", token); + requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); + + //根据URL地址过滤请求 【字典表参数签名验证】 + if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList),requestTemplate.path())) { + try { + log.info("============================ [begin] fegin starter url ============================"); + log.info(requestTemplate.path()); + log.info(requestTemplate.method()); + String queryLine = requestTemplate.queryLine(); + if(queryLine!=null && queryLine.startsWith("?")){ + queryLine = queryLine.substring(1); + } + log.info(queryLine); + if(requestTemplate.body()!=null){ + log.info(new String(requestTemplate.body())); + } + SortedMap allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method()); + String sign = SignUtil.getParamsSign(allParams); + log.info(" Feign request params sign: {}",sign); + log.info("============================ [end] fegin starter url ============================"); + requestTemplate.header(CommonConstant.X_SIGN, sign); + requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString()); + } catch (IOException e) { + e.printStackTrace(); + } + } + }else{ + String token = UserTokenContext.getToken(); + log.debug("Feign request token: {}", token); + requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); + } + }; + } + + + + /** + * Feign 客户端的日志记录,默认级别为NONE + * Logger.Level 的具体级别如下: + * NONE:不记录任何信息 + * BASIC:仅记录请求方法、URL以及响应状态码和执行时间 + * HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息 + * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据 + */ + @Bean + Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + + /** + * Feign支持文件上传 + * @param messageConverters + * @return + */ + @Bean + @Primary + @Scope("prototype") + public Encoder multipartFormEncoder(ObjectFactory messageConverters) { + return new SpringFormEncoder(new SpringEncoder(messageConverters)); + } + + // update-begin--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ---------- + @Bean + public Encoder feignEncoder() { + return new SpringEncoder(feignHttpMessageConverter()); + } + + @Bean + public Decoder feignDecoder() { + return new SpringDecoder(feignHttpMessageConverter()); + } + + /** + * 设置解码器为fastjson + * + * @return + */ + private ObjectFactory feignHttpMessageConverter() { + final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter()); + return () -> httpMessageConverters; + } + + private FastJsonHttpMessageConverter getFastJsonConverter() { + FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); + + List supportedMediaTypes = new ArrayList<>(); + MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE); + supportedMediaTypes.add(mediaTypeJson); + converter.setSupportedMediaTypes(supportedMediaTypes); + FastJsonConfig config = new FastJsonConfig(); + config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer()); + config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); + converter.setFastJsonConfig(config); + + return converter; + } + // update-end--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ---------- + +} diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/config/PersonBeanConfiguration.java b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/config/PersonBeanConfiguration.java similarity index 100% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/config/PersonBeanConfiguration.java rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/config/PersonBeanConfiguration.java diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java similarity index 70% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java index e24947ed..74e1d6bc 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/IJeroFeignService.java @@ -1,4 +1,4 @@ -package com.jero.starter.cloud. feign; +package com.jero.starter.cloud.feign; public interface IJeroFeignService { diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java similarity index 97% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java index 741a3dd0..aa837af1 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java +++ b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/java/com/jero/starter/cloud/feign/impl/JeroFeignService.java @@ -1,6 +1,8 @@ package com.jero.starter.cloud.feign.impl; -import feign.*; +import feign.Client; +import feign.Contract; +import feign.Feign; import feign.codec.Decoder; import feign.codec.Encoder; import lombok.extern.slf4j.Slf4j; diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/resources/bootstrap.yml b/jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/resources/bootstrap.yml similarity index 100% rename from jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/resources/bootstrap.yml rename to jero-boot/jero-boot-starter/jero-boot-starter-cloud/src/main/resources/bootstrap.yml diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-job/pom.xml b/jero-boot/jero-boot-starter/jero-boot-starter-job/pom.xml index 713a789c..fcca1d0c 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-job/pom.xml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-job/pom.xml @@ -5,7 +5,7 @@ jero-boot-starter com.jero.boot - 2.4.3 + 2.4.6 4.0.0 jero-boot-starter-job diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-lock/pom.xml b/jero-boot/jero-boot-starter/jero-boot-starter-lock/pom.xml index f7a58b31..a9bfb4d1 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-lock/pom.xml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-lock/pom.xml @@ -5,7 +5,7 @@ jero-boot-starter com.jero.boot - 2.4.3 + 2.4.6 4.0.0 jero-boot-starter-lock diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/pom.xml b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/pom.xml index 1fe2430c..fcd8aafb 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/pom.xml +++ b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/pom.xml @@ -5,7 +5,7 @@ jero-boot-starter com.jero.boot - 2.4.3 + 2.4.6 4.0.0 jero-boot-starter-rabbitmq diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/client/RabbitMqClient.java b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/client/RabbitMqClient.java index 80ca9b09..17a0ecec 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/client/RabbitMqClient.java +++ b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/client/RabbitMqClient.java @@ -28,6 +28,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Properties; /** * 消息队列客户端 @@ -91,11 +92,16 @@ public class RabbitMqClient { rabbitAdmin.declareExchange(directExchange); if (ObjectUtil.isNotEmpty(queues)) { for (String queueName : queues) { - Queue queue = new Queue(queueName); - addQueue(queue); - Binding binding = BindingBuilder.bind(queue).to(directExchange).with(queueName); - rabbitAdmin.declareBinding(binding); - log.info("队列创建成功:" + queueName); + Properties result = rabbitAdmin.getQueueProperties(queueName); + if (ObjectUtil.isEmpty(result)) { + Queue queue = new Queue(queueName); + addQueue(queue); + Binding binding = BindingBuilder.bind(queue).to(directExchange).with(queueName); + rabbitAdmin.declareBinding(binding); + log.info("创建队列:" + queueName); + }else{ + log.info("已有队列:" + queueName); + } } } } diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/config/RabbitMqConfig.java b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/config/RabbitMqConfig.java index b738670c..ff3233a1 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/config/RabbitMqConfig.java +++ b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/config/RabbitMqConfig.java @@ -1,7 +1,9 @@ package com.jero.boot.starter.rabbitmq.config; +import java.util.UUID; import com.jero.boot.starter.rabbitmq.event.JeroRemoteApplicationEvent; +import com.jero.common.config.mqtoken.TransmitUserTokenFilter; import org.springframework.amqp.core.AcknowledgeMode; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitAdmin; @@ -11,8 +13,6 @@ import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.UUID; - /** * 消息队列配置类 * @@ -31,7 +31,14 @@ public class RabbitMqConfig { return rabbitAdmin; } - + /** + * 注入获取token过滤器 + * @return + */ + @Bean + public TransmitUserTokenFilter transmitUserInfoFromHttpHeader(){ + return new TransmitUserTokenFilter(); + } @Bean public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) { diff --git a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/core/BaseRabbiMqHandler.java b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/core/BaseRabbiMqHandler.java index 6c0f01c7..3b3aca59 100644 --- a/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/core/BaseRabbiMqHandler.java +++ b/jero-boot/jero-boot-starter/jero-boot-starter-rabbitmq/src/main/java/com/jero/boot/starter/rabbitmq/core/BaseRabbiMqHandler.java @@ -3,14 +3,18 @@ package com.jero.boot.starter.rabbitmq.core; import com.rabbitmq.client.Channel; import lombok.extern.slf4j.Slf4j; import com.jero.boot.starter.rabbitmq.listenter.MqListener; +import com.jero.common.config.mqtoken.UserTokenContext; import java.io.IOException; @Slf4j public class BaseRabbiMqHandler { + private String token= UserTokenContext.getToken(); + public void onMessage(T t, Long deliveryTag, Channel channel, MqListener mqListener) { try { + UserTokenContext.setToken(token); mqListener.handler(t, channel); channel.basicAck(deliveryTag, false); } catch (Exception e) { diff --git a/jero-boot/jero-boot-starter/pom.xml b/jero-boot/jero-boot-starter/pom.xml index dcdb3c84..9db03bf5 100644 --- a/jero-boot/jero-boot-starter/pom.xml +++ b/jero-boot/jero-boot-starter/pom.xml @@ -4,7 +4,7 @@ com.jero.boot jero-boot - 2.4.3 + 2.4.6 4.0.0 jero-boot-starter @@ -16,6 +16,7 @@ + jero-boot-starter-cloud jero-boot-starter-job jero-boot-starter-lock jero-boot-starter-rabbitmq diff --git a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/config/FeignConfig.java b/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/config/FeignConfig.java deleted file mode 100644 index e005ae37..00000000 --- a/jero-boot/jero-cloud-module/jero-cloud-feign-config/src/main/java/com/jero/config/FeignConfig.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.jero.config; - -import feign.Feign; -import feign.Logger; -import feign.RequestInterceptor; -import feign.codec.Encoder; -import feign.form.spring.SpringFormEncoder; -import lombok.extern.slf4j.Slf4j; -import com.jero.common.constant.CommonConstant; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.http.HttpMessageConverters; -import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.cloud.openfeign.support.SpringEncoder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.Scope; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; - - -@ConditionalOnClass(Feign.class) -@AutoConfigureBefore(FeignAutoConfiguration.class) -@Slf4j -@Configuration -public class FeignConfig { - - @Bean - public RequestInterceptor requestInterceptor() { - return requestTemplate -> { - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (null != attributes) { - HttpServletRequest request = attributes.getRequest(); - log.info("Feign request: {}", request.getRequestURI()); - // 将token信息放入header中 - String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); - if(token==null){ - token = request.getParameter("token"); - } - log.info("Feign request token: {}", token); - requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token); - } - }; - } - - - - /** - * Feign 客户端的日志记录,默认级别为NONE - * Logger.Level 的具体级别如下: - * NONE:不记录任何信息 - * BASIC:仅记录请求方法、URL以及响应状态码和执行时间 - * HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息 - * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据 - */ - @Bean - Logger.Level feignLoggerLevel() { - return Logger.Level.FULL; - } - - /** - * Feign支持文件上传 - * @param messageConverters - * @return - */ - @Bean - @Primary - @Scope("prototype") - public Encoder multipartFormEncoder(ObjectFactory messageConverters) { - return new SpringFormEncoder(new SpringEncoder(messageConverters)); - } -} diff --git a/jero-boot/jero-cloud-module/jero-cloud-gateway/Dockerfile b/jero-boot/jero-cloud-module/jero-cloud-gateway/Dockerfile index 9ba86743..93c975b0 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-gateway/Dockerfile +++ b/jero-boot/jero-cloud-module/jero-cloud-gateway/Dockerfile @@ -10,6 +10,6 @@ WORKDIR /jero-cloud-gateway EXPOSE 9999 -ADD ./target/jero-cloud-gateway-2.4.3.jar ./ +ADD ./target/jero-cloud-gateway-2.4.6.jar ./ -CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-gateway-2.4.3.jar \ No newline at end of file +CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-gateway-2.4.6.jar \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-gateway/pom.xml b/jero-boot/jero-cloud-module/jero-cloud-gateway/pom.xml index 9a1e8c9a..0ef69aec 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-gateway/pom.xml +++ b/jero-boot/jero-cloud-module/jero-cloud-gateway/pom.xml @@ -5,7 +5,7 @@ jero-cloud-module com.jero.boot - 2.4.3 + 2.4.6 4.0.0 @@ -14,7 +14,7 @@ com.jero.boot - jero-cloud-feign-config + jero-boot-starter-cloud com.jero.boot @@ -27,6 +27,19 @@ org.springframework.cloud spring-cloud-starter-gateway + + + com.alibaba.cloud + spring-cloud-alibaba-sentinel-gateway + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + com.alibaba.csp + sentinel-web-servlet + org.springframework.boot diff --git a/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/filter/SentinelFilterContextConfig.java b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/filter/SentinelFilterContextConfig.java new file mode 100644 index 00000000..70cf5dcc --- /dev/null +++ b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/filter/SentinelFilterContextConfig.java @@ -0,0 +1,24 @@ +package com.jero.filter; + +import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Administrator + */ +@Configuration +public class SentinelFilterContextConfig { + @Bean + public FilterRegistrationBean sentinelFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new CommonFilter()); + registration.addUrlPatterns("/*"); + // 入口资源关闭聚合 + registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); + registration.setName("sentinelFilter"); + registration.setOrder(1); + return registration; + } +} \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/handler/LoderRouderHandler.java b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/handler/LoderRouderHandler.java index 64b89e9f..2f72b4cd 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/handler/LoderRouderHandler.java +++ b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/handler/LoderRouderHandler.java @@ -1,8 +1,8 @@ package com.jero.handler; -import lombok.extern.slf4j.Slf4j; -import com.jero.boot.starter.redis.listener.JeroRedisListerer; import com.jero.common.base.BaseMap; +import com.jero.common.modules.redis.listener.JeroRedisListerer; +import lombok.extern.slf4j.Slf4j; import com.jero.loader.DynamicRouteLoader; import org.springframework.stereotype.Component; diff --git a/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/loader/DynamicRouteLoader.java b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/loader/DynamicRouteLoader.java index a1aabb09..c4fb61d1 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/loader/DynamicRouteLoader.java +++ b/jero-boot/jero-cloud-module/jero-cloud-gateway/src/main/java/com/jero/loader/DynamicRouteLoader.java @@ -1,5 +1,6 @@ package com.jero.loader; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -8,6 +9,8 @@ import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; import com.google.common.collect.Lists; +import com.jero.common.constant.CacheConstant; +import com.jero.common.util.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import com.jero.config.GatewayRoutersConfiguration; diff --git a/jero-boot/jero-cloud-module/jero-cloud-monitor/pom.xml b/jero-boot/jero-cloud-module/jero-cloud-monitor/pom.xml index cd21e00f..c278b042 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-monitor/pom.xml +++ b/jero-boot/jero-cloud-module/jero-cloud-monitor/pom.xml @@ -5,7 +5,7 @@ jero-cloud-module com.jero.boot - 2.4.3 + 2.4.6 4.0.0 jero-cloud-monitor diff --git a/jero-boot/jero-cloud-module/jero-cloud-sentinel/pom.xml b/jero-boot/jero-cloud-module/jero-cloud-sentinel/pom.xml new file mode 100644 index 00000000..a950756d --- /dev/null +++ b/jero-boot/jero-cloud-module/jero-cloud-sentinel/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + jero-cloud-module + com.jero.boot + 2.4.6 + + jero-cloud-sentinel + jero-cloud-sentinel + sentinel启动模块 + + + + aliyun + aliyun Repository + https://maven.aliyun.com/repository/public + + false + + + + jeecg + jeecg Repository + https://maven.jeecg.org/nexus/content/repositories/jeecg + + false + + + + + + + org.jeecgframework.cloud + sentinel-dashboard + 1.8.2 + + + com.alibaba.csp + sentinel-datasource-nacos + + + com.alibaba.csp + sentinel-core + + + com.alibaba.csp + sentinel-web-servlet + + + com.alibaba.csp + sentinel-transport-simple-http + + + com.alibaba.csp + sentinel-parameter-flow-control + + + com.alibaba.csp + sentinel-api-gateway-adapter-common + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-undertow + + + + commons-lang + commons-lang + 2.6 + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + org.apache.httpcomponents + httpcore + 4.4.5 + + + org.apache.httpcomponents + httpasyncclient + 4.1.3 + + + org.apache.httpcomponents + httpcore-nio + 4.4.6 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/java/com.alibaba.csp.sentinel.dashboard/JeroSentinelDashboardApplication.java b/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/java/com.alibaba.csp.sentinel.dashboard/JeroSentinelDashboardApplication.java new file mode 100644 index 00000000..5da9dfbc --- /dev/null +++ b/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/java/com.alibaba.csp.sentinel.dashboard/JeroSentinelDashboardApplication.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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.alibaba.csp.sentinel.dashboard; + +import com.alibaba.csp.sentinel.init.InitExecutor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.Environment; + +/** + * Sentinel dashboard application. + * + * @author Carpenter Lee + */ +@SpringBootApplication +@Slf4j +public class JeroSentinelDashboardApplication { + + public static void main(String[] args) { + System.setProperty("csp.sentinel.app.type", "1"); + triggerSentinelInit(); + ConfigurableApplicationContext application = SpringApplication.run(JeroSentinelDashboardApplication.class, args); + Environment env = application.getEnvironment(); + String port = env.getProperty("server.port"); + log.info("\n----------------------------------------------------------\n\t" + + "Application SentinelDashboard is running! Access URLs:\n\t" + + "Local: \t\thttp://localhost:" + port + "/\n\t" + + "----------------------------------------------------------"); + } + + private static void triggerSentinelInit() { + new Thread(() -> InitExecutor.doInit()).start(); + } +} diff --git a/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/resources/application.properties b/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/resources/application.properties new file mode 100644 index 00000000..1d74c179 --- /dev/null +++ b/jero-boot/jero-cloud-module/jero-cloud-sentinel/src/main/resources/application.properties @@ -0,0 +1,28 @@ +#spring settings +spring.http.encoding.force=true +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true + +#cookie name setting +server.servlet.session.cookie.name=sentinel_dashboard_cookie +#spring.cloud.nacos.config.server-addr=127.0.0.1:8848 +#spring.cloud.nacos.config.namespace= +#spring.cloud.nacos.config.group-id=DEFAULT_GROUP +server.port=8087 + +#logging settings +logging.level.org.springframework.web=INFO +logging.file=${user.home}/logs/csp/sentinel-dashboard.log +logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n +#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + +#auth settings +auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version +auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png +# If auth.enabled=false, Sentinel console disable login +auth.username=sentinel +auth.password=sentinel + +# Inject the dashboard version. It's required to enable +# filtering in pom.xml for this resource file. +sentinel.dashboard.version=1.8.2 \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-system-start/Dockerfile b/jero-boot/jero-cloud-module/jero-cloud-system-start/Dockerfile index e286f750..81a6979c 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-system-start/Dockerfile +++ b/jero-boot/jero-cloud-module/jero-cloud-system-start/Dockerfile @@ -10,6 +10,6 @@ WORKDIR /jero-cloud-system EXPOSE 7001 -ADD ./target/jero-cloud-system-start-2.4.3.jar ./ +ADD ./target/jero-cloud-system-start-2.4.6.jar ./ -CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-system-start-2.4.3.jar \ No newline at end of file +CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-system-start-2.4.6.jar \ No newline at end of file diff --git a/jero-boot/jero-cloud-module/jero-cloud-system-start/pom.xml b/jero-boot/jero-cloud-module/jero-cloud-system-start/pom.xml index bc80fe2e..62fd7690 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-system-start/pom.xml +++ b/jero-boot/jero-cloud-module/jero-cloud-system-start/pom.xml @@ -5,17 +5,17 @@ jero-cloud-module com.jero.boot - 2.4.3 + 2.4.6 4.0.0 jero-cloud-system-start System项目微服务启动 - + com.jero.boot - jero-cloud-feign-config + jero-boot-starter-cloud diff --git a/jero-boot/jero-cloud-module/jero-cloud-xxljob/Dockerfile b/jero-boot/jero-cloud-module/jero-cloud-xxljob/Dockerfile index 61b4faea..1cccef10 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-xxljob/Dockerfile +++ b/jero-boot/jero-cloud-module/jero-cloud-xxljob/Dockerfile @@ -10,7 +10,7 @@ WORKDIR /jero-cloud-xxljob EXPOSE 9080 -ADD ./target/jero-cloud-xxljob-2.4.3.jar ./ +ADD ./target/jero-cloud-xxljob-2.4.6.jar ./ -CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-xxljob-2.4.3.jar +CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jero-cloud-xxljob-2.4.6.jar diff --git a/jero-boot/jero-cloud-module/jero-cloud-xxljob/pom.xml b/jero-boot/jero-cloud-module/jero-cloud-xxljob/pom.xml index df625d70..f2520106 100644 --- a/jero-boot/jero-cloud-module/jero-cloud-xxljob/pom.xml +++ b/jero-boot/jero-cloud-module/jero-cloud-xxljob/pom.xml @@ -5,7 +5,7 @@ jero-cloud-module com.jero.boot - 2.4.3 + 2.4.6 4.0.0 diff --git a/jero-boot/jero-cloud-module/pom.xml b/jero-boot/jero-cloud-module/pom.xml index c5dcd780..370c0ffe 100644 --- a/jero-boot/jero-cloud-module/pom.xml +++ b/jero-boot/jero-cloud-module/pom.xml @@ -5,7 +5,7 @@ jero-boot com.jero.boot - 2.4.3 + 2.4.6 4.0.0 @@ -16,7 +16,7 @@ jero-cloud-gateway jero-cloud-monitor jero-cloud-xxljob - jero-cloud-feign-config + jero-cloud-sentinel \ No newline at end of file diff --git a/jero-boot/pom.xml b/jero-boot/pom.xml index bb83770d..57c611a6 100644 --- a/jero-boot/pom.xml +++ b/jero-boot/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.jero.boot jero-boot - 2.4.3 + 2.4.6 pom @@ -13,7 +13,7 @@ - 2.4.3 + 2.4.6 1.8 UTF-8 Hoxton.SR8 @@ -21,17 +21,17 @@ 2.2.0 1.2.75 2.0.4 - 2.0.4 + 2.0.9 42.2.6 11.2.0.3 4.0 8.0.21 3.2.0 - 5.3.8 + 5.3.8 3.13.6 1.9.4 29.0-jre - 3.4.1 + 3.4.3.1 1.1.22 2.6 2.1.0 @@ -50,10 +50,10 @@ jero-boot-base jero-boot-module-demo jero-boot-module-system - jero-boot-starter jero-boot-single-startup + jero-boot-starter jero-cloud-module @@ -75,7 +75,7 @@ aliyun aliyun Repository - http://maven.aliyun.com/nexus/content/groups/public + https://maven.aliyun.com/repository/public false @@ -95,7 +95,7 @@ jeecg jeecg Repository - http://maven.jeecg.org/nexus/content/repositories/jeecg + https://maven.jeecg.org/nexus/content/repositories/jeecg false @@ -175,7 +175,7 @@ com.jero.boot - jero-cloud-feign-config + jero-boot-starter-cloud ${jero.version} @@ -236,7 +236,17 @@ cn.hutool hutool-all - ${hutool-all.version} + ${hutool.version} + + + cn.hutool + hutool-core + ${hutool.version} + + + cn.hutool + hutool-crypto + ${hutool.version} @@ -365,7 +375,7 @@ dev - jeecg + jero 127.0.0.1:8848 @@ -383,7 +393,7 @@ test - jeecg + jero 127.0.0.1:8848 @@ -401,7 +411,7 @@ prod - jeecg + jero 127.0.0.1:8848