From daa67be8145771bc4e5514011eb075a430a0c847 Mon Sep 17 00:00:00 2001 From: xlj Date: Mon, 9 Feb 2026 13:04:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E4=BD=93=E5=8C=96=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assembly/assembly.xml | 108 ++++++ assembly/pom.xml | 63 ++++ cdaxxt-bootstrap/pom.xml | 72 ++++ .../java/com/tobacco/mp/BasisApplication.java | 19 ++ .../BizworksApiGatewayConfiguration.java | 24 ++ .../com/tobacco/mp/config/CorsFilter.java | 52 +++ .../com/tobacco/mp/config/RedisConfig.java | 107 ++++++ .../tobacco/mp/config/RequestInterceptor.java | 19 ++ .../com/tobacco/mp/config/ServerRunner.java | 20 ++ .../com/tobacco/mp/config/WebMvcConfig.java | 43 +++ .../src/main/resources/application.yml | 106 ++++++ .../src/main/resources/templates/word.html | 212 ++++++++++++ cdaxxt-business/pom.xml | 45 +++ .../mp/controller/PlatformController.java | 75 +++++ .../tobacco/mp/dto/PlatformMessageDTO.java | 47 +++ .../com/tobacco/mp/dto/PlatformNoticeDTO.java | 55 +++ .../com/tobacco/mp/dto/PlatformTaskDTO.java | 92 +++++ .../tobacco/mp/dto/PlatformTaskHandleDTO.java | 50 +++ .../java/com/tobacco/mp/entity/SysUser.java | 202 +++++++++++ .../com/tobacco/mp/mapper/SysUserMapper.java | 22 ++ .../com/tobacco/mp/mapper/SysUserMapper.xml | 20 ++ .../mp/model/PlatformReceiverInfo.java | 14 + .../mp/model/PlatformResponseCode.java | 23 ++ .../mp/service/PlatformMessageService.java | 136 ++++++++ .../mp/service/PlatformUserService.java | 127 +++++++ .../tobacco/mp/service/SchedulerService.java | 30 ++ .../tobacco/mp/service/SysUserService.java | 39 +++ cdaxxt-common/pom.xml | 32 ++ .../tobacco/mp/annotation/AuthOperation.java | 14 + .../tobacco/mp/annotation/LogOperation.java | 14 + .../tobacco/mp/annotation/OpenOperation.java | 14 + .../tobacco/mp/annotation/PassOperation.java | 14 + .../com/tobacco/mp/constant/Constant.java | 24 ++ .../java/com/tobacco/mp/constant/Symbol.java | 35 ++ .../tobacco/mp/enums/ResponseCodeEnum.java | 48 +++ .../java/com/tobacco/mp/enums/TipEnum.java | 41 +++ .../mp/exception/ServiceException.java | 32 ++ .../main/java/com/tobacco/mp/model/Json.java | 54 +++ .../com/tobacco/mp/model/ResponseResult.java | 93 +++++ .../com/tobacco/mp/utils/AnnotationUtil.java | 172 ++++++++++ .../java/com/tobacco/mp/utils/JWTUtil.java | 108 ++++++ .../main/java/com/tobacco/mp/utils/Maps.java | 80 +++++ .../java/com/tobacco/mp/utils/Objects.java | 249 ++++++++++++++ .../com/tobacco/mp/utils/PasswordUtil.java | 163 +++++++++ .../java/com/tobacco/mp/utils/RandomUtil.java | 95 ++++++ .../java/com/tobacco/mp/utils/RedisUtils.java | 317 ++++++++++++++++++ cdaxxt-core/pom.xml | 44 +++ pom.xml | 282 ++++++++++++++++ 48 files changed, 3747 insertions(+) create mode 100644 assembly/assembly.xml create mode 100644 assembly/pom.xml create mode 100644 cdaxxt-bootstrap/pom.xml create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/BasisApplication.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/BizworksApiGatewayConfiguration.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/CorsFilter.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RedisConfig.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RequestInterceptor.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/ServerRunner.java create mode 100644 cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/WebMvcConfig.java create mode 100644 cdaxxt-bootstrap/src/main/resources/application.yml create mode 100644 cdaxxt-bootstrap/src/main/resources/templates/word.html create mode 100644 cdaxxt-business/pom.xml create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/controller/PlatformController.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformMessageDTO.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformNoticeDTO.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskDTO.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskHandleDTO.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/entity/SysUser.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.xml create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformReceiverInfo.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformResponseCode.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformMessageService.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformUserService.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/service/SchedulerService.java create mode 100644 cdaxxt-business/src/main/java/com/tobacco/mp/service/SysUserService.java create mode 100644 cdaxxt-common/pom.xml create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/annotation/AuthOperation.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/annotation/LogOperation.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/annotation/OpenOperation.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/annotation/PassOperation.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/constant/Constant.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/constant/Symbol.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/enums/ResponseCodeEnum.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/enums/TipEnum.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/exception/ServiceException.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/model/Json.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/model/ResponseResult.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/AnnotationUtil.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/JWTUtil.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/Maps.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/Objects.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/PasswordUtil.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/RandomUtil.java create mode 100644 cdaxxt-common/src/main/java/com/tobacco/mp/utils/RedisUtils.java create mode 100644 cdaxxt-core/pom.xml create mode 100644 pom.xml diff --git a/assembly/assembly.xml b/assembly/assembly.xml new file mode 100644 index 0000000..4a86351 --- /dev/null +++ b/assembly/assembly.xml @@ -0,0 +1,108 @@ + + + + bin + + + + zip + + + + false + + + + + + + false + true + lib + provided + + + false + true + lib + system + + + false + true + lib + runtime + + + + + + true + + integration-platform-access:cdaxxt-bootstrap + integration-platform-access:cdaxxt-business + integration-platform-access:cdaxxt-common + integration-platform-access:cdaxxt-core + + + + + + + + + ${project.basedir} + + + README* + LICENSE* + NOTICE* + + + + + + ../cdaxxt-bootstrap/src/main/resources + config + + *.yml + + + + + + ../cdaxxt-bootstrap/src/main/resources/bin + + + 777 + + 777 + + + + + ../cdaxxt-bootstrap/target + + + *.jar + + + + + \ No newline at end of file diff --git a/assembly/pom.xml b/assembly/pom.xml new file mode 100644 index 0000000..8b4c042 --- /dev/null +++ b/assembly/pom.xml @@ -0,0 +1,63 @@ + + + + integration-platform-access + com.tobacco.mp + 1.0-SNAPSHOT + + 4.0.0 + + assembly + + + + com.tobacco.mp + cdaxxt-bootstrap + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-business + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-common + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-core + 1.0-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4.1 + + + make-assembly + package + + single + + + assembly-package + + assembly.xml + + + + + + + + + + \ No newline at end of file diff --git a/cdaxxt-bootstrap/pom.xml b/cdaxxt-bootstrap/pom.xml new file mode 100644 index 0000000..e11082c --- /dev/null +++ b/cdaxxt-bootstrap/pom.xml @@ -0,0 +1,72 @@ + + + + integration-platform-access + com.tobacco.mp + 1.0-SNAPSHOT + + 4.0.0 + + cdaxxt-bootstrap + + + + com.tobacco.mp + cdaxxt-common + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-business + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-core + 1.0-SNAPSHOT + + + + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/*.* + static/** + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + false + + + true + + lib/ + + com.tobacco.mp.BasisApplication + + + + + + + + + \ No newline at end of file diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/BasisApplication.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/BasisApplication.java new file mode 100644 index 0000000..6125367 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/BasisApplication.java @@ -0,0 +1,19 @@ +package com.tobacco.mp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableScheduling +@EnableFeignClients(basePackages = {"com.tobacco.mp.uc.client.api","com.tobacco.mp.auth.businessdomain.auth.client.api","com.tobacco.mp.mcext.client.api","com.tobacco.mp.ttc.client.api"}) +@EnableAsync +@SpringBootApplication(scanBasePackages = {"com.tobacco.mp"}) +public class BasisApplication { + + public static void main(String[] args) { + SpringApplication.run(BasisApplication.class, args); + } + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/BizworksApiGatewayConfiguration.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/BizworksApiGatewayConfiguration.java new file mode 100644 index 0000000..e0cecd4 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/BizworksApiGatewayConfiguration.java @@ -0,0 +1,24 @@ +package com.tobacco.mp.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * 阿里云网关包扫描配置 + */ +@Slf4j +@Configuration +@ConditionalOnExpression("'ali'.equals('${bizworks-api-gateway.type}') and 'true'.equals('${bizworks-api-gateway.enable}') ") +@ComponentScan("com.bizworks.ubcp.apiclient.feign") +public class BizworksApiGatewayConfiguration { + + @Bean + public String init(){ + log.info("开启阿里网关模式"); + return null; + } + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/CorsFilter.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/CorsFilter.java new file mode 100644 index 0000000..352a116 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/CorsFilter.java @@ -0,0 +1,52 @@ +package com.tobacco.mp.config; + +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 跨域处理机制 + */ +@Component +public class CorsFilter implements Filter { + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + throws IOException, ServletException { + HttpServletResponse response = (HttpServletResponse) res; + HttpServletRequest request = (HttpServletRequest) req; + String origin = request.getHeader("Origin"); + String allowHeaders = request.getHeader("Access-Control-Request-Headers"); + if (!StringUtils.isEmpty(origin)) { + response.setHeader("Access-Control-Allow-Origin", origin); + } else { + response.setHeader("Access-Control-Allow-Origin", "*"); + } + if (!StringUtils.isEmpty(allowHeaders)) { + response.setHeader("Access-Control-Allow-Headers", allowHeaders); + } else { + response.setHeader("Access-Control-Allow-Headers", "*"); + } + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + if ("OPTIONS".equals(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + } else { + chain.doFilter(req, res); + } + } + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RedisConfig.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RedisConfig.java new file mode 100644 index 0000000..49ca6a7 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RedisConfig.java @@ -0,0 +1,107 @@ +package com.tobacco.mp.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis配置 + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RequestInterceptor.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RequestInterceptor.java new file mode 100644 index 0000000..45fc787 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/RequestInterceptor.java @@ -0,0 +1,19 @@ +package com.tobacco.mp.config; + +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 请求拦截器处理 + */ +public class RequestInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 请求拦截处理 + return true; + } + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/ServerRunner.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/ServerRunner.java new file mode 100644 index 0000000..4bd30ad --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/ServerRunner.java @@ -0,0 +1,20 @@ +package com.tobacco.mp.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + + +@Slf4j +@Component +public class ServerRunner implements CommandLineRunner { + + + @Override + public void run(String... args) throws Exception { + // 服务器成功启动加载其他 + + } + + +} diff --git a/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/WebMvcConfig.java b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/WebMvcConfig.java new file mode 100644 index 0000000..dc94773 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/java/com/tobacco/mp/config/WebMvcConfig.java @@ -0,0 +1,43 @@ +package com.tobacco.mp.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @Author XiongLiJian + * @Date 2021/12/28 15:36 + * @Description 资源管理配置 + * @Version 1.0 + **/ +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + /** + * 声明需要放行的swagger资源路径 + */ + private String[] newPassPath = new String[]{"/login", "/swagger-ui.html/**", "/v2/**","/files/**", "/webjars/**", "/swagger-resources/**", + "/**.js", "/static/**", "/images/**", "/index.html", "/css/**", "/js/**", "/file/**"}; + + + /** + * 添加资源站点 + * @param registry + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + + } + + /** + * 注册拦截器 + * @param registry + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册拦截器 + registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**").excludePathPatterns(newPassPath); + } + +} diff --git a/cdaxxt-bootstrap/src/main/resources/application.yml b/cdaxxt-bootstrap/src/main/resources/application.yml new file mode 100644 index 0000000..aec6e39 --- /dev/null +++ b/cdaxxt-bootstrap/src/main/resources/application.yml @@ -0,0 +1,106 @@ +server: + host: 0.0.0.0 + port: 8049 + compression: + enabled: true + servlet: + context-path: /mosty-platform + +spring: + aop: + auto: true + application: + name: integration-platform-access + jackson: + date-format: yyyy-MM-dd HH:mm:ss + resources: + static-locations: classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/, classpath:/templates/ + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql://47.108.232.77:4407/mosty_jcgl_gs?autoReconnect=true&failOverReadOnly=false&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai + username: root + password: Mosty@888 + druid: # 以下参数针对每个库可以重新设置druid参数 + # 使用druid数据源 + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + host: 47.108.232.77 + port: 6379 + password: sczy@2022 + timeout: 10000 + max-active: 100 + min-idle: 0 + max-idle: 20 + max-wait: 30000 + sxExpire: 1800 + database: 12 + thymeleaf: + prefix: classpath:/templates/ + mode: HTML5 + suffix: .html + encoding: UTF-8 + cache: false + servlet: + content-type: text/html + enabled: true + +# mybatis +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl + map-underscore-to-camel-case: true + cache-enabled: false + global-config: + db-config: + logic-delete-field: actived + logic-delete-value: 0 + logic-not-delete-value: 1 + table-underline: true + update-strategy: ignored + banner: false + +logging: + file: + name: ${user.dir}/logs/${spring.application.name}/${spring.application.name}.log + level: + org.springframework.cloud.openfeign: DEBUG + feign: DEBUG + +#feign: +# client: +# config: +# default: +# contract: org.springframework.cloud.openfeign.support.SpringMvcContract + +bizworks: + clientId: 6f938da0e22911f0bc71bc16950a55fb + +bizworks-api-gateway: + enable: true + type: ali + disSignService: + signature: + - host: api.gansu-ywzt.zgs.yun + appKey: 1762305806807768 + appSecret: 5e1385488c054e9980bf0bf8e68c10a5 + bizId: + service: tobacco-mp-uc-client + + diff --git a/cdaxxt-bootstrap/src/main/resources/templates/word.html b/cdaxxt-bootstrap/src/main/resources/templates/word.html new file mode 100644 index 0000000..892688a --- /dev/null +++ b/cdaxxt-bootstrap/src/main/resources/templates/word.html @@ -0,0 +1,212 @@ + + + + + toWord + + + + +
+
+

+ 下载文档 +
+
+
+ +

+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
接口描述
URL
请求方式
请求类型
返回类型
参数名数据类型参数类型是否必填说明
状态码描述说明
返回属性名类型说明
示例
请求参数
返回值
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cdaxxt-business/pom.xml b/cdaxxt-business/pom.xml new file mode 100644 index 0000000..d97de3f --- /dev/null +++ b/cdaxxt-business/pom.xml @@ -0,0 +1,45 @@ + + + + integration-platform-access + com.tobacco.mp + 1.0-SNAPSHOT + + 4.0.0 + + cdaxxt-business + + + + com.tobacco.mp + cdaxxt-common + 1.0-SNAPSHOT + + + com.tobacco.mp + cdaxxt-core + 1.0-SNAPSHOT + + + + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/* + + + + + + + \ No newline at end of file diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/controller/PlatformController.java b/cdaxxt-business/src/main/java/com/tobacco/mp/controller/PlatformController.java new file mode 100644 index 0000000..7f9022f --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/controller/PlatformController.java @@ -0,0 +1,75 @@ +package com.tobacco.mp.controller; + +import com.alibaba.fastjson.JSONObject; +import com.tobacco.mp.dto.PlatformMessageDTO; +import com.tobacco.mp.dto.PlatformNoticeDTO; +import com.tobacco.mp.dto.PlatformTaskDTO; +import com.tobacco.mp.dto.PlatformTaskHandleDTO; +import com.tobacco.mp.service.PlatformMessageService; +import com.tobacco.mp.service.PlatformUserService; +import com.tobacco.mp.model.ResponseResult; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +// 一体化平台对接 +@RestController +@AllArgsConstructor +@RequestMapping("/platform") +public class PlatformController { + + @Resource + PlatformUserService userService; + + @Resource + PlatformMessageService messageService; + + // 查询一体化平台的用户列表 + @GetMapping(value = "/getUserList") + public ResponseResult getUserList() { + userService.getUserList(); + return ResponseResult.success(); + } + + // 查询一体化平台的用户ID + @GetMapping(value = "/getUserIdByAccount") + public ResponseResult getUserIdByAccount(@RequestParam String loginName) { + return ResponseResult.success(userService.getUserIdByAccount(loginName)); + } + + // 一体化平台身份令牌认证 + @GetMapping(value = "/tokenAccess") + public ResponseResult tokenAccess(@RequestParam String token) { + return ResponseResult.success(userService.tokenAccess(token)); + } + + // 向一体化平台发送消息 + @PostMapping(value = "/sendMessage") + public ResponseResult sendMessage(@RequestBody PlatformMessageDTO dataDTO) { + messageService.sendMessage(dataDTO); + return ResponseResult.success(); + } + + // 向一体化平台发送通知/公告 + @PostMapping(value = "/sendNotice") + public ResponseResult sendNotice(@RequestBody PlatformNoticeDTO dataDTO) { + messageService.sendNotice(dataDTO); + return ResponseResult.success(); + } + + // 向一体化平台发送待办 + @PostMapping(value = "/sendToDo") + public ResponseResult sendToDo(@RequestBody PlatformTaskDTO taskDTO) { + messageService.sendToDo(taskDTO); + return ResponseResult.success(); + } + + // 向一体化平台发送待办处置信息 + @PostMapping(value = "/sendHandleToDo") + public ResponseResult sendHandleToDo(@RequestBody PlatformTaskHandleDTO handleDTO) { + messageService.sendHandleToDo(handleDTO); + return ResponseResult.success(); + } + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformMessageDTO.java b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformMessageDTO.java new file mode 100644 index 0000000..ee781d7 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformMessageDTO.java @@ -0,0 +1,47 @@ +package com.tobacco.mp.dto; + +import com.tobacco.mp.model.PlatformReceiverInfo; +import lombok.Data; + +import java.util.List; + +@Data +public class PlatformMessageDTO { + + // 事件编码 + private String eventCode; + + // 消息类型,值范围: 10-系统消息 20-流程通知 30-赋能通知 + private String msgType; + + // 消息标题 + private String msgTitle; + + // 消息内容 + private String msgContent; + + // 消息链接 + private String msgLink; + + // 发送者名称 + private String senderName; + + // 发送者ID + private String senderId; + + // 来源应用ID + private String fromAppId; + + // 来源应用名称 + private String fromAppName; + + // 来源业务id + private String fromBusiId; + + // 消息重要程度:URGENT-紧急 IMPORTANT-重要 NORMAL-普通 + private String msgPriority = "NORMAL"; + + // 消息接收人列表 + private List msgUserList; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformNoticeDTO.java b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformNoticeDTO.java new file mode 100644 index 0000000..028527f --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformNoticeDTO.java @@ -0,0 +1,55 @@ +package com.tobacco.mp.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +@Data +public class PlatformNoticeDTO { + + // 公告标题* + private String title; + + // 通知公告类型* + private String type; + + // 公告来源* (PORTAL-门户维护,API-系统接入) + private String source; + + // 内容类型* (TEXT-文字内容,LINK-跳转链接) + private String contentType; + + // 公告内容* + private String content; + + // 跳转链接url* + private String linkUrl; + + // 发布方式* (IMMEDIATE:立即发布;SCHEDULE:定时发布) + private String publishType; + + // 定时发布时间* + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date scheduleTime; + + // 有效期类型* (PERMANENT-永久有效,TEMPORARY-非永久有效) + private String expiryType; + + // 有效期截止时间 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date expiryDate; + + // 可见范围类型* (ALL-全省可见,CITY:全市可见,DEPT-下级组织可见) + private String visibleType; + + // 创建人名称* + private String creatorName; + + // 创建人用户id* + private String creatorId; + + // 应用id* + private String clientId; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskDTO.java b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskDTO.java new file mode 100644 index 0000000..c0fc20c --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskDTO.java @@ -0,0 +1,92 @@ +package com.tobacco.mp.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class PlatformTaskDTO { + + // 任务名称* + private String taskName; + + // 任务描述* + private String taskDesc; + + // 业务主键* + private String businessId; + + // 需要关联的流程实例 + private String processId; + + // 需要关联的流程名称 + private String processName; + + // 会签分组标记,用于记录任务所属的会签分组,也可用于其他分组(按需维护) + private String taskCollaborateId; + + // 需要关联的流程任务实例 + private String processTaskId; + + // 待办类型 (字典TTC_TODO_TYPE) + private String todoType; + + // 业务类型 + private String bizType; + + // 紧急程度* (1高2中3低) + private int todoPriority = 2; + + // 中台消息中心的模板编码,发通知消息时,未指定模板则使用该默认模板 + private String eventCode; + + // 上级任务ID,有撤回场景时需要维护 + private String preTaskId; + + // 创建人账号ID* + private String createUserId; + + // 是否开始节点 + private Boolean isStart; + + // 是否结束节点 + private Boolean isEnd; + + // 相关附件 + private List attachmentPath; + + // 系统需要在业务中台AppId* (用户中心完成应用系统注册,得到appId) + private String createAppId; + + //系统需要在业务中台AppId* (用户中心完成应用系统注册,得到appId) + private String handleAppId; + + // 任务处理地址* + private String optAddress; + + // 移动任务处理地址,模糊查询* + private String optAddressMobile; + + // 拓展属性配置 + private String extraConfig; + + // 处理截止时间 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date deadline; + + // 移交前任务ID + private String translateOriginId; + + // 创建时间 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date gmtCreate; + + // 操作人ID* + private String optUserId; + + // 操作人名称 + private String optUserName; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskHandleDTO.java b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskHandleDTO.java new file mode 100644 index 0000000..b26f6d8 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/dto/PlatformTaskHandleDTO.java @@ -0,0 +1,50 @@ +package com.tobacco.mp.dto; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class PlatformTaskHandleDTO { + + // 待办任务ID* + private String todoTaskId; + + // 实际处理人ID* + private String handleUserId; + + // 相关附件 + private List attachmentPath; + + // 处理结果,字典TTC_TASK_OPT_RESULT + private String optResult; + + // 处理意见 + private String optComment; + + // 操作人ID* + private String optUserId; + + // 操作人名称 + private String optUserName; + + // 是否发送待办通知 (false或null则根据任务自动通知配置情况发送消息) + private Boolean sendNotification; + + // 中台消息模板,发送通知时有效,不传值则使用任务设置的默认模板 + private String eventCode; + + // 消息接收人 + private String receiverId; + + // 消息额外参数,不同消息类型的个性化参数与模板的动态参数 + private Map extraProps; + + // 任务处理地址 + private String optAddress; + + // 移动任务处理地址,模糊查询 + private String optAddressMobile; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/entity/SysUser.java b/cdaxxt-business/src/main/java/com/tobacco/mp/entity/SysUser.java new file mode 100644 index 0000000..f327686 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/entity/SysUser.java @@ -0,0 +1,202 @@ +package com.tobacco.mp.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Accessors(chain = true) +@TableName(value = "sys_user") +public class SysUser implements Serializable { + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.INPUT) + @ApiModelProperty(value = "用户ID") + private String id; + + @TableField(value = "position_type") + @ApiModelProperty(value = "岗位类型") + private String positionType; + + @TableField(value = "position_id") + @ApiModelProperty(value = "岗位ID") + private String positionId; + + @TableField(value = "position_name") + @ApiModelProperty(value = "岗位名称") + private String positionName; + + @TableField(value = "is_virtual_user") + @ApiModelProperty(value = "是否虚拟用户:1、是 2、不是") + private String isVirtualUser; + + @TableField(value = "login_name") + @ApiModelProperty(value = "登录账号") + private String loginName; + + @TableField(value = "password") + @ApiModelProperty(value = "密码") + private String password; + + @TableField(value = "user_name") + @ApiModelProperty(value = "用户昵称") + private String userName; + + @TableField(value = "user_type") + @ApiModelProperty(value = "用户类型(00系统用户 01注册用户)") + private String userType; + + @TableField(value = "email") + @ApiModelProperty(value = "用户邮箱") + private String email; + + @TableField(value = "mobile", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "移动电话") + private String mobile; + + @TableField(value = "tele_phone", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "电话号码") + private String telePhone; + + @TableField(value = "id_entity_card") + @ApiModelProperty(value = "身份证号") + private String idEntityCard; + + @TableField(value = "in_dust_rial_id") + @ApiModelProperty(value = "行业号码(如:警号)") + private String inDustRialId; + + @TableField(value = "sex") + @ApiModelProperty(value = "用户性别(0男 1女 2未知)") + private String sex; + + @TableField(value = "nation", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "民族") + private String nation; + + @TableField(value = "politic", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "政治面貌") + private String politic; + + @TableField(value = "marital") + @ApiModelProperty(value = "婚姻状态") + private String marital; + + @TableField(value = "type") + @ApiModelProperty(value = "人员类别") + private String type; + + @TableField(value = "type_name") + @ApiModelProperty(value = "人员类别中文") + private String typeName; + + @TableField(value = "whcd", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "文化程度") + private String whcd; + + @TableField(value = "user_no", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "排序") + private Integer userNo; + + @TableField(value = "bz", updateStrategy = FieldStrategy.IGNORED) + @ApiModelProperty(value = "备注") + private String bz; + + @TableField(value = "birthday") + @ApiModelProperty(value = "出生日期") + private String birthday; + + @TableField(value = "begin_time") + @ApiModelProperty(value = " 用户有效开始时间,默认为当前日期(用户可改)") + private Date beginTime; + + @TableField(value = "end_time") + @ApiModelProperty(value = " 用户有效结束时间,默认空") + private Date endTime; + + @TableField(value = "salt") + @ApiModelProperty(value = "盐加密") + private String salt; + + @TableField("duty_code") + @ApiModelProperty("职务code") + private String dutyCode; + + @TableField("duty_name") + @ApiModelProperty("职务名称") + private String dutyName; + + @TableField("outsourcing_level") + @ApiModelProperty("D_BZ_ZYWHRYLB-聘用人员类别 1.在岗在册 2.劳务派遣 3.业务外包") + private String outsourcingLevel; + + @TableField("long_term_sick_leave") + @ApiModelProperty(" 是否长期病假人员") + private String longTermSickLeave; + + @TableField("platform_user_id") + @ApiModelProperty(" 业务中台用户ID") + private String platformUserId; + + @TableField(value = "xzcs") + @ApiModelProperty(value = "选择次数") + private Integer xzcs; + + @TableField(value = "xt_zxbz") + private Integer xtZxbz; + + @TableField(value = "xt_zxyz") + private String xtZxyz; + + @TableField(value = "xt_cjsj") + private Date xtCjsj; + + @TableField(value = "xt_lrsj") + private Date xtLrsj; + + @TableField(value = "xt_lrrxm") + private String xtLrrxm; + + @TableField(value = "xt_lrrid") + private String xtLrrid; + + @TableField(value = "xt_lrrbm") + private String xtLrrbm; + + @TableField(value = "xt_lrrbmid") + private String xtLrrbmid; + + @TableField(value = "xt_lrip") + private String xtLrip; + + @TableField(value = "xt_zhxgsj") + private Date xtZhxgsj; + + @TableField(value = "xt_zhxgrxm") + private String xtZhxgrxm; + + @TableField(value = "xt_zhxgid") + private String xtZhxgid; + + @TableField(value = "xt_zhxgrbm") + private String xtZhxgrbm; + + @TableField(value = "xt_zhxgrbmid") + private String xtZhxgrbmid; + + @TableField(value = "xt_zhxgrip") + private String xtZhxgrip; + + @TableField(value = "xt_city_code") + private String xtCityCode; + + @TableField(value = "xt_city_name") + private String xtCityName; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.java b/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.java new file mode 100644 index 0000000..e7808f3 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.java @@ -0,0 +1,22 @@ +package com.tobacco.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tobacco.mp.entity.SysUser; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SysUserMapper extends BaseMapper { + + // 获取业务中台用户ID为空的用户账号列表 + List getNullPlatformUserId(); + + // 给用户绑定业务中台的用户ID + void setPlatformUserId(@Param("userName") String userName, @Param("platformUserId") String platformUserId); + + // 更新任务的一体化平台ID + void updateRwPlatformId(@Param("rwId") String rwId, @Param("platformId") String platformId); + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.xml b/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.xml new file mode 100644 index 0000000..6cf8c56 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/mapper/SysUserMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + UPDATE mosty_base_gs.sys_user SET platform_user_id = #{platformUserId} WHERE user_name = #{userName} + + + + + UPDATE mosty_jcgl_gs.tb_rw SET platform_id = #{platformId} WHERE id = #{rwId} + + + diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformReceiverInfo.java b/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformReceiverInfo.java new file mode 100644 index 0000000..07ab332 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformReceiverInfo.java @@ -0,0 +1,14 @@ +package com.tobacco.mp.model; + +import lombok.Data; + +@Data +public class PlatformReceiverInfo { + + // 接收者名称 + private String receiverName; + + // 接收者ID + private String receiverId; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformResponseCode.java b/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformResponseCode.java new file mode 100644 index 0000000..60facec --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/model/PlatformResponseCode.java @@ -0,0 +1,23 @@ +package com.tobacco.mp.model; + +/** + * 一体化平台响应状态码 + */ +public class PlatformResponseCode { + + // 成功 + public static final String SUCCESS = "200"; + + // 未授权 + public static final String UNAUTHORIZED = "401"; + + // 禁止访问 + public static final String ACCESS_DENIED = "403"; + + // 资源不存在 + public static final String NOT_EXIST = "404"; + + // 服务异常 + public static final String SERVICE_EXCEPTION = "500"; + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformMessageService.java b/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformMessageService.java new file mode 100644 index 0000000..2fcf293 --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformMessageService.java @@ -0,0 +1,136 @@ +package com.tobacco.mp.service; + +import com.alibaba.bizworks.core.runtime.common.SingleResponse; +import com.tobacco.mp.dto.PlatformMessageDTO; +import com.tobacco.mp.dto.PlatformNoticeDTO; +import com.tobacco.mp.dto.PlatformTaskDTO; +import com.tobacco.mp.dto.PlatformTaskHandleDTO; +import com.tobacco.mp.mcext.client.api.McExtNoticeServiceAPI; +import com.tobacco.mp.mcext.client.api.MessageSendExtServiceAPI; +import com.tobacco.mp.mcext.client.api.message.dto.SendMessageDTO; +import com.tobacco.mp.mcext.client.api.message.req.SendInternalMessageRequest; +import com.tobacco.mp.mcext.client.api.notice.dto.CreateNoticeResponse; +import com.tobacco.mp.mcext.client.api.notice.req.CreateNoticeRequest; +import com.tobacco.mp.model.PlatformResponseCode; +import com.tobacco.mp.ttc.client.api.TodoTaskApi; +import com.tobacco.mp.ttc.client.api.enums.TaskHandleTargetTypeEnum; +import com.tobacco.mp.ttc.client.api.task.dto.TodoTaskDTO; +import com.tobacco.mp.ttc.client.api.task.req.CreateTaskRequest; +import com.tobacco.mp.ttc.client.api.task.req.SubmitTaskRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Service +public class PlatformMessageService { + + @Resource + private MessageSendExtServiceAPI messageSendExtServiceAPI; + + @Resource + private McExtNoticeServiceAPI mcExtNoticeServiceAPI; + + @Resource + private TodoTaskApi todoTaskApi; + + @Resource + private SysUserService sysUserService; + + @Value("${bizworks.clientId}") + private String clientId; + + + /** + * 发送消息 + * @param messageDTO + */ + public void sendMessage(PlatformMessageDTO messageDTO) { + // 构建消息请求参数 + SendInternalMessageRequest request = new SendInternalMessageRequest(); + BeanUtils.copyProperties(messageDTO, request, "msgUserList"); + request.setFromAppId(clientId); + request.setFromAppName("安管平台应用"); + List msgUserList = new ArrayList<>(); + BeanUtils.copyProperties(messageDTO.getMsgUserList(), msgUserList); + request.setMsgUserList(msgUserList); + // 发送消息请求 + SingleResponse response = messageSendExtServiceAPI.sendInternalMessage(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + log.info("消息【{}】请求处理成功", messageDTO.getMsgTitle()); + } else { + log.error("消息【{}】请求处理失败。失败原因:{}", messageDTO.getMsgTitle(), response.getMessage()); + } + } + + /** + * 发送通知/公告 + * @param noticeDTO + */ + public void sendNotice(PlatformNoticeDTO noticeDTO) { + // 构建通知/公告请求参数 + CreateNoticeRequest request = new CreateNoticeRequest(); + BeanUtils.copyProperties(noticeDTO, request); + request.setSource("API"); + request.setClientId(clientId); + // 发送通知/公告请求 + SingleResponse response = mcExtNoticeServiceAPI.createNotice(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + log.info("通知【{}】请求处理成功", noticeDTO.getTitle()); + } else { + log.error("通知【{}】请求处理失败。失败原因:{}", noticeDTO.getTitle(), response.getMessage()); + } + } + + /** + * 创建待办任务 + * @param taskDTO + */ + public void sendToDo(PlatformTaskDTO taskDTO) { + // 构建待办任务请求参数 + CreateTaskRequest request = new CreateTaskRequest(); + BeanUtils.copyProperties(taskDTO, request); + request.setHandleTargetId(taskDTO.getOptUserId()); + request.setHandleTargetType(TaskHandleTargetTypeEnum.USER); + request.setCreateAppId(clientId); + request.setHandleAppId(clientId); + // 发送待办任务请求 + SingleResponse response = todoTaskApi.createTask(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + TodoTaskDTO todoTaskDTO = response.getData(); + if (todoTaskDTO != null && StringUtils.isNotEmpty(todoTaskDTO.getId())) { + sysUserService.updateRwPlatformId(taskDTO.getBusinessId(), todoTaskDTO.getId()); + } + log.info("待办【{}】请求处理成功", taskDTO.getTaskName()); + } else { + log.error("待办【{}】请求处理失败。失败原因:{}", taskDTO.getTaskName(), response.getMessage()); + } + } + + /** + * 处置待办 + * @param handleDTO + */ + public void sendHandleToDo(PlatformTaskHandleDTO handleDTO) { + // 处置待办参数校验 + if (StringUtils.isEmpty(handleDTO.getTodoTaskId())) { + return; + } + // 构建处置待办请求参数 + SubmitTaskRequest request = new SubmitTaskRequest(); + BeanUtils.copyProperties(handleDTO, request); + // 发送处置待办请求 + SingleResponse response = todoTaskApi.submitTask(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + log.info("待办处理【{}】请求处理成功", handleDTO.getTodoTaskId()); + } else { + log.error("待办处理【{}】请求处理失败。失败原因:{}", handleDTO.getTodoTaskId(), response.getMessage()); + } + } + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformUserService.java b/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformUserService.java new file mode 100644 index 0000000..2a206cf --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/service/PlatformUserService.java @@ -0,0 +1,127 @@ +package com.tobacco.mp.service; + +import com.alibaba.bizworks.core.runtime.common.MultiDataDTO; +import com.alibaba.bizworks.core.runtime.common.MultiResponse; +import com.alibaba.bizworks.core.runtime.common.SingleResponse; +import com.alibaba.fastjson.JSONObject; +import com.tobacco.mp.auth.businessdomain.auth.client.api.SsoAuthI; +import com.tobacco.mp.auth.businessdomain.auth.client.api.auth.dto.TokenCheckResultDTO; +import com.tobacco.mp.auth.businessdomain.auth.client.api.auth.req.CheckTokenRequest; +import com.tobacco.mp.constant.Constant; +import com.tobacco.mp.model.PlatformResponseCode; +import com.tobacco.mp.uc.client.api.UserServiceAPI; +import com.tobacco.mp.uc.client.api.user.dto.GetUserByUserCodeDTO; +import com.tobacco.mp.uc.client.api.user.dto.UserDTO; +import com.tobacco.mp.uc.client.api.user.req.GetUserByUserCodeRequest; +import com.tobacco.mp.uc.client.api.user.req.PageQueryUserRequest; +import com.tobacco.mp.utils.JWTUtil; +import com.tobacco.mp.utils.RandomUtil; +import com.tobacco.mp.utils.RedisUtils; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; + +@Slf4j +@Service +public class PlatformUserService { + + @Resource + private UserServiceAPI userServiceAPI; + + @Resource + private SsoAuthI ssoAuthI; + + @Resource + private RedisUtils redisUtils; + + @Value("${bizworks.clientId}") + private String clientId; + + /** + * 查询一体化平台的用户ID + * @param loginName + * @return + */ + public String getUserIdByAccount(String loginName) { + // 构建查询平台用户请求参数 + GetUserByUserCodeRequest request = new GetUserByUserCodeRequest(); + request.setUserCode(loginName); + // 发送查询平台用户请求 + SingleResponse response = userServiceAPI.getUserByUserCode(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + GetUserByUserCodeDTO userDTO = response.getData(); + if (userDTO != null && StringUtils.isNotEmpty(userDTO.getUserId())) { + return userDTO.getUserId(); + } + } else { + log.error("获取中台用户[{}]请求处理失败。失败原因:{}", loginName, response.getMessage()); + } + return null; + } + + /** + * 查询一体化平台的用户列表 + */ + public void getUserList() { + // 构建查询平台用户列表请求参数 + PageQueryUserRequest request = new PageQueryUserRequest(); + request.setPageNumber(1); + request.setPageSize(10); + request.setManageUnitId("12"); + // 发送查询平台用户列表请求 + MultiResponse response = userServiceAPI.pageQueryUser(request); + if (response.getCode().equals(PlatformResponseCode.SUCCESS)) { + MultiDataDTO userDTO = response.getData(); + if (userDTO != null && !CollectionUtils.isEmpty(userDTO.getItems())) { + for (UserDTO user : userDTO.getItems()) { + System.out.println("userId:" + user.getUserId() + ", userName:" + user.getLoginName()); + } + } + } else { + log.error("分页获取中台用户请求处理失败。失败原因:{}", response.getMessage()); + } + } + + /** + * 校验本系统登录页面的token(一体化平台的token)信息 + * @param token + * @return + */ + public JSONObject tokenAccess(String token) { + // 声明响应数据(用户名和系统登录校验码) + JSONObject jsonObject = new JSONObject(); + String account = ""; + + // 给一体化平台发送解析请求以验证令牌获取用户名 + SingleResponse singleResponse = ssoAuthI.checkToken(new CheckTokenRequest(token, clientId)); + if (singleResponse.getCode().equals(PlatformResponseCode.SUCCESS)) { + TokenCheckResultDTO data = singleResponse.getData(); + if (data != null && StringUtils.isNotEmpty(data.getUserInfo())) { + Claims claims = JWTUtil.verifyJWTToken(data.getUserInfo(), JWTUtil.PUBLIC_KEY_STR); + account = claims.get("account", String.class); + } else { + log.error("请求一体化平台响应数据:{}", JSONObject.toJSONString(data)); + return jsonObject; + } + } else { + log.error("鉴权请求处理失败。失败原因:{}", singleResponse.getMessage()); + return jsonObject; + } + + // 验证通过后,给页面返回用户名和本系统登录校验码 + if (StringUtils.isNotEmpty(account)) { + String verifyCode = RandomUtil.generateLowerString(16); + redisUtils.set(Constant.LOGIN_VERIFY_CODE + account, verifyCode, 30); + jsonObject.put("userName", account); + jsonObject.put("verifyCode", verifyCode); + log.info("--------一体化平台成功鉴权!----------"); + } + + return jsonObject; + } + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/service/SchedulerService.java b/cdaxxt-business/src/main/java/com/tobacco/mp/service/SchedulerService.java new file mode 100644 index 0000000..4cb33de --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/service/SchedulerService.java @@ -0,0 +1,30 @@ +package com.tobacco.mp.service; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +@Service +public class SchedulerService { + + @Resource + SysUserService sysUserService; + + @Resource + PlatformUserService platformUserService; + + /** + * 刷新用户业务中台的ID + */ + // @Scheduled(cron = "0 0 3 * * ?") + public void refreshUserPlatformId() { + List userNames = sysUserService.getNullPlatformUserId(); + for (String userName : userNames) { + String platformUserId = platformUserService.getUserIdByAccount(userName); + sysUserService.setPlatformUserId(userName, platformUserId); + } + } + +} diff --git a/cdaxxt-business/src/main/java/com/tobacco/mp/service/SysUserService.java b/cdaxxt-business/src/main/java/com/tobacco/mp/service/SysUserService.java new file mode 100644 index 0000000..18fb4eb --- /dev/null +++ b/cdaxxt-business/src/main/java/com/tobacco/mp/service/SysUserService.java @@ -0,0 +1,39 @@ +package com.tobacco.mp.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.tobacco.mp.entity.SysUser; +import com.tobacco.mp.mapper.SysUserMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SysUserService extends ServiceImpl { + + /** + * 获取业务中台用户ID为空的用户账号列表 + * @return + */ + public List getNullPlatformUserId() { + return this.baseMapper.getNullPlatformUserId(); + } + + /** + * 给用户绑定业务中台的用户ID + * @param userName + * @param platformUserId + */ + public void setPlatformUserId(String userName, String platformUserId) { + this.baseMapper.setPlatformUserId(userName, platformUserId); + } + + /** + * 更新任务的一体化平台ID + * @param rwId + * @param platformId + */ + public void updateRwPlatformId(String rwId, String platformId) { + this.baseMapper.updateRwPlatformId(rwId, platformId); + } + +} diff --git a/cdaxxt-common/pom.xml b/cdaxxt-common/pom.xml new file mode 100644 index 0000000..79df900 --- /dev/null +++ b/cdaxxt-common/pom.xml @@ -0,0 +1,32 @@ + + + + integration-platform-access + com.tobacco.mp + 1.0-SNAPSHOT + + 4.0.0 + + cdaxxt-common + + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/* + + + + + + + \ No newline at end of file diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/AuthOperation.java b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/AuthOperation.java new file mode 100644 index 0000000..ba1c817 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/AuthOperation.java @@ -0,0 +1,14 @@ +package com.tobacco.mp.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 【允许已登录的社会用户访问的接口】使用该注解(无效) + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthOperation { +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/LogOperation.java b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/LogOperation.java new file mode 100644 index 0000000..0d8fd8b --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/LogOperation.java @@ -0,0 +1,14 @@ +package com.tobacco.mp.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 【需要记录操作日志】使用该注解 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface LogOperation { +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/OpenOperation.java b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/OpenOperation.java new file mode 100644 index 0000000..a2096ab --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/OpenOperation.java @@ -0,0 +1,14 @@ +package com.tobacco.mp.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 【需要开放第三方对接的接口】使用该注解 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface OpenOperation { +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/PassOperation.java b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/PassOperation.java new file mode 100644 index 0000000..4ed2106 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/annotation/PassOperation.java @@ -0,0 +1,14 @@ +package com.tobacco.mp.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 【不需要登录就能访问的接口】使用该注解 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface PassOperation { +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Constant.java b/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Constant.java new file mode 100644 index 0000000..733dad8 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Constant.java @@ -0,0 +1,24 @@ +package com.tobacco.mp.constant; + +/** + * 基础常量信息 + */ +public class Constant { + + + /********************************************缓存key***********************************************/ + public static final String LOGIN_VERIFY_CODE = "LoginVerifyCode:"; + public static final String JWT_USER = "JwtUser:"; + + /*************************************************************************************************/ + + + public static final String DEFAULT_IP = "0.0.0.0"; + + /** 开放的API */ + public static final String OPEN_API = "OPENAPI"; + + /** 开放的应用 */ + public static final String OPEN_APP = "OPENAPP"; + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Symbol.java b/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Symbol.java new file mode 100644 index 0000000..3105155 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/constant/Symbol.java @@ -0,0 +1,35 @@ +package com.tobacco.mp.constant; + +/** + * @Author XiongLiJian + * @Date 2021/6/4 9:31 + * @Description 符号工具类 + * @Version 1.0 + **/ +public class Symbol { + + /** 符号:[-] */ + public static final String ACROSS = "-"; + + /** 符号:[_] */ + public static final String LOW_ACROSS = "_"; + + /** 符号[.] */ + public static final String POINT = "."; + + /** 符号[:] */ + public static final String COLON = ":"; + + /** 逗号[,] */ + public static final String COMMA = ","; + + /** 斜杠 */ + public static final String SLASH = "/"; + + /** 逗号[@] */ + public static final String A2 = "@"; + + /** 符号[;] */ + public static final String SEMICOLON = ";"; + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/enums/ResponseCodeEnum.java b/cdaxxt-common/src/main/java/com/tobacco/mp/enums/ResponseCodeEnum.java new file mode 100644 index 0000000..0abac37 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/enums/ResponseCodeEnum.java @@ -0,0 +1,48 @@ +package com.tobacco.mp.enums; + +/** + * 响应码管理 + * @Author: XiongLiJian + * @Date: 2020/12/29 09:14 + */ +public enum ResponseCodeEnum { + + NORMAL(200, "ok"), + REQUEST_PARAM_ERROR(400, "请求参数错误!"), + SYSTEM_NO_LOGIN(401, "系统未登录!"), + USER_ALREADY_DISABLED(402, "该用户已被禁用!"), + NO_ACCESS_PERMISSION(403, "没有访问权限!"), + REQUEST_RESOURCE_NO_EXIST(404, "请求的资源不存在!"), + REQUEST_METHOD_ERROR(405, "请求方式错误"), + SYSTEM_ERROR(500, "系统错误"), + SYSTEM_TIP(501, "系统提示"), + + ; + + /** 响应码 */ + private Integer code; + /** 响应信息 */ + private String msg; + + ResponseCodeEnum(Integer code, String msg) { + this.code = code; + this.msg = msg; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/enums/TipEnum.java b/cdaxxt-common/src/main/java/com/tobacco/mp/enums/TipEnum.java new file mode 100644 index 0000000..d3b57de --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/enums/TipEnum.java @@ -0,0 +1,41 @@ +package com.tobacco.mp.enums; + +/** + * @Author XiongLiJian + * @Date 2021/12/29 9:25 + * @Description 消息提示 + * @Version 1.0 + **/ +public enum TipEnum { + + BATCH_DELETE_DATA_ERROR("批量删除解析错误!"), + FILE_NOT_SURE("请指定一个文件进行操作!"), + SYSTEM_ERROR("系统出现错误!"), + USERNAME_NOT_EXIST("用户名不存在!"), + PLEASE_WAIT_REPEAT_LOGIN("该账号今天重复多次密码错误,请30分钟后重新登录!"), + ACCOUNT_PASSWORD_ERROR("账号或密码错误!"), + ACCESS_FILE_ERROR("权限模板文件解析异常!"), + ACCESS_API_ERROR("权限映射解析异常!"), + ROLE_PERSON_NUM_EXSIT("角色下存在人员无法删除!"), + DATA_SHEET_IMPORT_ERROR("数据导入解析错误!"), + USERNAME_IS_REPEAT("该用户名已存在!"), + NOT_MODIFY_SYSTEM_ROLE("不能操作系统超级管理员!"), + CHECK_CODE_REPEAT("请不要频繁生成校验码!"), + + ; + + private String msg; + + TipEnum(String msg) { + this.msg = msg; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/exception/ServiceException.java b/cdaxxt-common/src/main/java/com/tobacco/mp/exception/ServiceException.java new file mode 100644 index 0000000..45dc56c --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/exception/ServiceException.java @@ -0,0 +1,32 @@ +package com.tobacco.mp.exception; + +import com.tobacco.mp.enums.ResponseCodeEnum; +import com.tobacco.mp.enums.TipEnum; +import lombok.Data; + +/** + * @Author XiongLiJian + * @Date 2021/6/3 17:53 + * @Description 服务器异常 + * @Version 1.0 + **/ +@Data +public class ServiceException extends RuntimeException { + + private static final long serialVersionUID = 6165589759025169495L; + + private Integer code = ResponseCodeEnum.SYSTEM_TIP.getCode(); + + private String message; + + public ServiceException(TipEnum tipEnum) { + super(tipEnum.getMsg()); + this.message = tipEnum.getMsg(); + } + + public ServiceException(String message) { + super(message); + this.message = message; + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/model/Json.java b/cdaxxt-common/src/main/java/com/tobacco/mp/model/Json.java new file mode 100644 index 0000000..233bcfc --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/model/Json.java @@ -0,0 +1,54 @@ +package com.tobacco.mp.model; + +import com.tobacco.mp.enums.ResponseCodeEnum; +import lombok.Data; + +@Data +public class Json { + + private boolean success; + + private Integer code; + + private String message; + + private T data; + + public static Json success() { + return success(null); + } + + public static Json success(Object data) { + Json json = new Json(); + json.setSuccess(true); + json.setCode(ResponseCodeEnum.NORMAL.getCode()); + json.setMessage(ResponseCodeEnum.NORMAL.getMsg()); + json.setData(data); + return json; + } + + public static Json fail(ResponseCodeEnum responseCodeEnum) { + Json json = new Json(); + json.setSuccess(false); + json.setCode(responseCodeEnum.getCode()); + json.setMessage(responseCodeEnum.getMsg()); + return json; + } + + public static Json fail(Integer code, String message) { + Json json = new Json(); + json.setCode(code); + json.setMessage(message); + json.setSuccess(false); + return json; + } + + public static Json fail(String message) { + Json json = new Json(); + json.setCode(ResponseCodeEnum.SYSTEM_TIP.getCode()); + json.setMessage(message); + json.setSuccess(false); + return json; + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/model/ResponseResult.java b/cdaxxt-common/src/main/java/com/tobacco/mp/model/ResponseResult.java new file mode 100644 index 0000000..f5a9b1c --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/model/ResponseResult.java @@ -0,0 +1,93 @@ +package com.tobacco.mp.model; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Objects; + +@Data +@SuppressWarnings("unused") +public class ResponseResult implements Serializable { + + /** 调用成功编码 */ + private static final int SUCCESS_CODE = 10000; + + /** 调用失败编码 */ + private static final int FAIL_CODE = -1; + + /** 编号 */ + private int code = SUCCESS_CODE; + + /** 消息 */ + private String message; + + /** 数据 */ + private T data; + + public ResponseResult() { + } + + public ResponseResult(T data) { + this.message = "OK"; + this.data = data; + } + + public ResponseResult(int code, String msg) { + this.code = code; + this.message = msg; + this.data = null; + } + + public ResponseResult(int code, String msg, T data) { + this.code = code; + this.message = msg; + this.data = data; + } + + public static ResponseResult success() { + return new ResponseResult(SUCCESS_CODE, "OK", null); + } + + public static ResponseResult success(int code, String message, T data) { + return new ResponseResult(code, message, data); + } + + public static ResponseResult success(String message, T data) { + return new ResponseResult(SUCCESS_CODE, message, data); + } + + public static ResponseResult success(T data) { + return new ResponseResult(SUCCESS_CODE, "OK", data); + } + + public static ResponseResult fail(String message) { + return new ResponseResult(FAIL_CODE, message, (Object)null); + } + + public static ResponseResult fail(int code, String message) { + return new ResponseResult(code, message, (Object)null); + } + + public static ResponseResult fail(int code, String message, T t) { + return new ResponseResult(code, message, t); + } + + public boolean isSuccess() { + return SUCCESS_CODE == code; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) { + return false; + } + ResponseResult that = (ResponseResult) o; + return Objects.equals(code, that.code) && Objects.equals(message, that.message) && Objects.equals(data, that.data); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, data); + } +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/AnnotationUtil.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/AnnotationUtil.java new file mode 100644 index 0000000..77268bd --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/AnnotationUtil.java @@ -0,0 +1,172 @@ +package com.tobacco.mp.utils; + +import com.tobacco.mp.annotation.AuthOperation; +import com.tobacco.mp.annotation.OpenOperation; +import com.tobacco.mp.annotation.PassOperation; +import com.tobacco.mp.constant.Constant; +import com.tobacco.mp.constant.Symbol; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.*; + +import java.lang.reflect.Method; +import java.util.*; + +@Slf4j +@Component +public class AnnotationUtil { + + @Autowired + RedisUtils redisUtils; + + private final String RESOURCE_PATTERN = "com/tobacco/mp/**/controller/*.class"; + + public static List PASS_API; + + public static List AUTH_API; + + /** + * 加载自定义注解 + */ + public void loadCustomAnnotation() { + Map> mapApis = getAccessAnnotations(RESOURCE_PATTERN); + // 获取开放给第三方的接口数据 + if (mapApis.get(OpenOperation.class.getName()) != null) { + redisUtils.set(Constant.OPEN_API, StringUtils.toString(mapApis.get(OpenOperation.class.getName()))); + } + // 不需要登录就能访问的接口 + PASS_API = mapApis.get(PassOperation.class.getName()); + if (PASS_API == null) { + PASS_API = new ArrayList<>(); + } + // 允许已登录的社会用户访问的接口 + AUTH_API = mapApis.get(AuthOperation.class.getName()); + if (AUTH_API == null) { + AUTH_API = new ArrayList<>(); + } + } + + /** + * 获取指定路径下OpenOperation注解下的uri接口 + * @return + */ + private Map> getAccessAnnotations(String resourcePattern) { + + ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + Map> map = new HashMap<>(); + + try { + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resourcePattern; + Resource[] resources = resourcePatternResolver.getResources(pattern); + MetadataReaderFactory readerfactory = new CachingMetadataReaderFactory(resourcePatternResolver); + for (Resource resource : resources) { + // 读取类信息 + MetadataReader reader = readerfactory.getMetadataReader(resource); + // 扫描到的class + String classname = reader.getClassMetadata().getClassName(); + Class clazz = Class.forName(classname); + Method[] methods = clazz.getMethods(); + for (Method method: methods) { + OpenOperation openAnno = method.getAnnotation(OpenOperation.class); + // 判断是否有指定主解 + if (openAnno != null) { + // 获取注解的方法与接口请求注解 + String api = getApi(clazz, method); + List openApi = map.get(OpenOperation.class.getName()); + if (CollectionUtils.isEmpty(openApi)) { + openApi = new ArrayList<>(); + map.put(OpenOperation.class.getName(), openApi); + } + openApi.add(api); + } + AuthOperation authAnno = method.getAnnotation(AuthOperation.class); + // 判断是否有指定主解 + if (authAnno != null) { + // 获取注解的方法与接口请求注解 + String api = getApi(clazz, method); + List authApi = map.get(AuthOperation.class.getName()); + if (CollectionUtils.isEmpty(authApi)) { + authApi = new ArrayList<>(); + map.put(AuthOperation.class.getName(), authApi); + } + authApi.add(api); + } + PassOperation passAnno = method.getAnnotation(PassOperation.class); + // 判断是否有指定主解 + if (passAnno != null) { + // 获取注解的方法与接口请求注解 + String api = getApi(clazz, method); + List passApi = map.get(PassOperation.class.getName()); + if (CollectionUtils.isEmpty(passApi)) { + passApi = new ArrayList<>(); + map.put(PassOperation.class.getName(), passApi); + } + passApi.add(api); + } + } + } + } catch (Exception e) { + + } + + return map; + + } + + /** + * 获取api接口 + * @param + * @param + */ + private String getApi(Class clazz, Method method) { + RequestMapping request = clazz.getDeclaredAnnotation(RequestMapping.class); + if (request != null) { + String api = request.value().length > 0 ? request.value()[0] : ""; + if (!api.contains(Symbol.SLASH)) { + api = Symbol.SLASH + api; + } + String name = ""; + // 获取方法的接口路由 + GetMapping getAnn = method.getAnnotation(GetMapping.class); + if (getAnn != null) { + name = getAnn.value().length > 0 ? getAnn.value()[0] : ""; + if (!name.contains(Symbol.SLASH)) { + name = Symbol.SLASH + name; + } + } + PostMapping postAnn = method.getAnnotation(PostMapping.class); + if (postAnn != null) { + name = postAnn.value().length > 0 ? postAnn.value()[0] : ""; + if (!name.contains(Symbol.SLASH)) { + name = Symbol.SLASH + name; + } + } + DeleteMapping deleteAnn = method.getAnnotation(DeleteMapping.class); + if (deleteAnn != null) { + name = deleteAnn.value().length > 0 ? deleteAnn.value()[0] : ""; + if (!name.contains(Symbol.SLASH)) { + name = Symbol.SLASH + name; + } + } + PutMapping putAnn = method.getAnnotation(PutMapping.class); + if (putAnn != null) { + name = putAnn.value().length > 0 ? putAnn.value()[0] : ""; + if (!name.contains(Symbol.SLASH)) { + name = Symbol.SLASH + name; + } + } + api += name; + return api; + } + return UUID.randomUUID().toString(); + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/JWTUtil.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/JWTUtil.java new file mode 100644 index 0000000..9cb44d9 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/JWTUtil.java @@ -0,0 +1,108 @@ +package com.tobacco.mp.utils; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class JWTUtil { + + // 公钥 + public static String PUBLIC_KEY_STR = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHOi7T3dx95MADXlRPkLeFS+08f7dGg6RxbG5gug+yQLnw1ARNDYx6zK0gtHU+qmUlBCVqHS5vqAt73ydDKUGY9IgdMcxWtbPj456wF7W86xDv6EfiV/G9ZRVvPWmgNUxw1RXtQa91sIuyCxp4xIFd43wROxWUbmN+Omiv2ZYqYBquSdmzslL1dDypPCZ53ZCs1aY6TodbhndySp8E7YAhw8o+F2uGPW9p1Xz1w4hIZBo10b49rOpR5h0t2U4OloBbAC8Too6Smb5ZdYseUZLLD+PW1O0l7uMBlmJuqjPXRUxuTwXUO+EA4Z/ymBXalE4Zi3uEomISqWajSDPOG4pwIDAQAB"; + + /** + * 从Base64编码的字符串加载公钥 + * @param publicKeyStr Base64编码的公钥字符串 + * @return PublicKey对象 + */ + public static PublicKey loadPublicKey(String publicKeyStr) throws Exception { + // 移除PEM格式的标记 + String publicKeyPEM = publicKeyStr + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replaceAll("\\s", ""); + // Base64解码 + byte[] encoded = Base64.getDecoder().decode(publicKeyPEM); + // 创建公钥规范 + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); + // 根据算法获取KeyFactory + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePublic(keySpec); + } + + /** + * 验证JWT令牌 + * @param token JWT令牌字符串 + * @param publicKey 公钥 + * @return Claims 声明信息 + */ + public static Claims verifyJWT(String token, PublicKey publicKey) { + return Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody(); + } + + /** + * 验证令牌签名信息 + * @param token 令牌 + * @param publicKeyStr 公钥字符串 + * @return + */ + public static Claims verifyJWTToken(String token, String publicKeyStr) { + try { + // 加载公钥 + PublicKey publicKey = loadPublicKey(publicKeyStr); + // 验证JWT + return Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody(); + } catch (io.jsonwebtoken.security.SignatureException e) { + throw new RuntimeException("无效的签名", e); + } catch (io.jsonwebtoken.ExpiredJwtException e) { + throw new RuntimeException("令牌已过期", e); + } catch (io.jsonwebtoken.MalformedJwtException e) { + throw new RuntimeException("无效的令牌格式", e); + } catch (Exception e) { + throw new RuntimeException("令牌验证失败", e); + } + } + + /** + * 读取txt文件的内容 + * @param file 想要读取的文件对象 + * @return 返回文件内容 + */ + public static String readTxt(File file) { + StringBuilder result = new StringBuilder(); + try { + // 构造一个BufferedReader类来读取文件 + BufferedReader br = new BufferedReader(new FileReader(file)); + String s = null; + // 使用readLine方法,一次读一行 + while ((s = br.readLine()) != null) { + result.append(System.lineSeparator()+s); + } + br.close(); + } catch(Exception e) { + e.printStackTrace(); + } + return result.toString(); + } + + public static void main(String[] args) { + String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHOi7T3dx95MADXlRPkLeFS+08f7dGg6RxbG5gug+yQLnw1ARNDYx6zK0gtHU+qmUlBCVqHS5vqAt73ydDKUGY9IgdMcxWtbPj456wF7W86xDv6EfiV/G9ZRVvPWmgNUxw1RXtQa91sIuyCxp4xIFd43wROxWUbmN+Omiv2ZYqYBquSdmzslL1dDypPCZ53ZCs1aY6TodbhndySp8E7YAhw8o+F2uGPW9p1Xz1w4hIZBo10b49rOpR5h0t2U4OloBbAC8Too6Smb5ZdYseUZLLD+PW1O0l7uMBlmJuqjPXRUxuTwXUO+EA4Z/ymBXalE4Zi3uEomISqWajSDPOG4pwIDAQAB"; + String jwtToken = "eyJhbGciOiJSUzI1NiJ9.eyJlbXBsb3llZUpvYklkIjoiNjIxMzI1MDMwNzAwMDAwMDAwMSIsIm1hbmFnZVVuaXRJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDExNjIwNTAxIiwib3JpZ2luQXBwIjoiYzQ1Y2I1YzMwZDQzNGMyNDlkZWYyZGNiMzM2ODg4NGQiLCJ0YXJnZXRDbGllbnRzIjoiNmY5MzhkYTBlMjI5MTFmMGJjNzFiYzE2OTUwYTU1ZmIiLCJlbXBsb3llZUlkIjoiMDAwMDAwMDAwMDAwMDAwMDEwNjIwNTAxMDAwMDA0MjIiLCJ1c2VyVHlwZSI6IjAwMDAwMSIsInVzZXJOYW1lIjoi5p2c5YevIiwib3JnVW5pdElkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAxMTYyMDUwMTAxMDciLCJnbXRDcmVhdGUiOiIyMDI1LTEyLTI2IDA4OjAxOjA5IiwidXNlcklkIjoiNjIxMzIzMDIyMzAwMDAwMDAzNDAwMDAiLCJhY2NvdW50IjoiRFVLQUkifQ.LzvpEPcGBeOnfV0tcO9yl11PeWuGQR0lzrRAmdUAcSGhvL-J_UF57P4_Q64qfMrzotoSEiVKiCErs4XcgexDFg4WIpx-wbZWdaQ7zIaFMWY-4eVe3R8Th72ABohwuQ7YRFJuWuNE21m3olfqbnbQ1DztDlsWrjd0l6LohrycK9A0teCAlP4Hhjl9kjT2UrRnMFVep1t5dTz8oPSE4KXNjseG8aTBGYbg304JYFQSfkdn3rB6ucp9FG0b9HGrpw1kCdq16m2VXGmKlqGizrOFw30SEZ9z9dABWiNMZjt3AqhY1ByNFtx0bNY-51DOdfVHeWTUDqItuwOak86r-ZVH_w"; + try { + Claims claims = verifyJWTToken(jwtToken, publicKeyStr); + String account = claims.get("account", String.class); + System.out.println("验证成功!"); + System.out.println("account: " + account); + System.out.println("过期时间: " + claims.getExpiration()); + } catch (Exception e) { + System.err.println("验证失败: " + e.getMessage()); + } + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Maps.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Maps.java new file mode 100644 index 0000000..7ba7079 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Maps.java @@ -0,0 +1,80 @@ +package com.tobacco.mp.utils; + +import com.alibaba.fastjson.JSON; + +import java.util.*; + +public class Maps { + + /** + * json去除key-value处理 + * @param json + * @return + */ + public static String jsonRemoveKey(String json, String key) { + Map map = JSON.parseObject(json); + Iterator> iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + if (entry.getKey() != null && entry.getKey().equals(key)) { + map.remove(key); + break; + } + } + return JSON.toJSONString(map); + } + + /** + * 默认采用HashMap + * @param args + * @return + */ + public static Map map(Object ... args){ + Map map = new HashMap(); + fillMap(map, args); + return map; + } + + /** + * 默认采用HashMap + * @param args + * @return + */ + public static Map map(Class kClazz,Class vClassz,Object ... args){ + Map map = new HashMap(); + if (args.length % 2 == 0){ + for (int i = 0;i < args.length; i+=2){ + map.put((K)args[i], (V)args[i+1]); + } + } + return map; + } + + public static Map treemap(Object ... args){ + Map map = new TreeMap(); + fillMap(map, args); + return map; + } + + public static Map copy(Map source){ + if (source == null){ + return Collections.emptyMap(); + } + if (source instanceof LinkedHashMap){ + return new LinkedHashMap(source); + } else if (source instanceof TreeMap){ + return new TreeMap(source); + } else { + return new HashMap(source); + } + } + + private static void fillMap(Map target,Object ... args){ + if (args.length % 2 == 0){ + for (int i = 0;i < args.length; i+=2){ + target.put(args[i], args[i+1]); + } + } + } +} + diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Objects.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Objects.java new file mode 100644 index 0000000..2638d43 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/Objects.java @@ -0,0 +1,249 @@ +package com.tobacco.mp.utils; + + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +/** + * + */ +public final class Objects { + public static List take(List list, String name, Class clazz) { + try { + List values = new ArrayList<>(); + for (Object item : list) { + + Object valueObj = PropertyUtils.getProperty(item, name); + T value = (T) valueObj; + if (value != null) { + values.add(value); + } + } + return values; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static Map index(List list, String name, Class clazz) { + try { + Map index = new HashMap<>(); + for (T t : list) { + Object valueObj = PropertyUtils.getProperty(t, name); + I key = (I) valueObj; + index.put(key, t); + } + return index; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + /** + * @param target + * @param source + * @param mapKey 默认两个对象之间通过mapKey关联,即source中对应的是id,target中对应的对象的属性是mapKey.replace("Id") + */ + public static void orm(List target, List source, String mapKey) { + try { + String defaultID = "id"; + Map index = index(source, defaultID, Object.class); + String name = mapKey.substring(0, mapKey.length() - defaultID.length()); + for (Object t : target) { + Object mapValue = PropertyUtils.getProperty(t, mapKey); + Object value = index.get(mapValue); + PropertyUtils.setProperty(t, name, value); + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static void orm(List target, List source, String mapKey, String name) { + try { + String defaultID = "id"; + Map index = index(source, defaultID, Object.class); + for (Object t : target) { + Object mapValue = PropertyUtils.getProperty(t, mapKey); + if(mapValue != null) { + Object value = index.get(Long.parseLong(mapValue.toString())); + PropertyUtils.setProperty(t, name, value); + } + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static boolean isEmpty(Object value) { + if (value == null) { + return true; + } + if (value instanceof Integer) { + return value.equals(Integer.valueOf(0)); + } else if (value instanceof String) { + return StringUtils.isEmpty(value.toString()); + } + return false; + } + + + public static Map group(List list, String prop) { + try { + Map groupIndex = new HashMap<>(); + for (Object item : list) { + Object value = PropertyUtils.getProperty(item, prop); + if (value != null) { + List group = groupIndex.get(value); + if (group == null) { + group = new LinkedList(); + groupIndex.put(value, group); + } + group.add(item); + } + } + return groupIndex; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + /** + * list去重 + * @param list + * @return + */ + public static List removeDuplicate(List list) { + for ( int i = 0 ; i < list.size() - 1 ; i ++ ) { + for ( int j = list.size() - 1 ; j > i; j -- ) { + if (list.get(j).equals(list.get(i))) { + list.remove(j); + } + } + } + return list; + } + + /** + * 检查一个列表对象是否有数据 + * @param objs + * @return + */ + public static boolean checkObjFieldIsData(Collection objs, String...keys) { + try { + for (T obj : objs) { + if (checkObjField(obj, keys)) { + return true; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + + /** + * 检查一个列表对象是否有数据 + * @param objs false 表示 + * @return + */ + public static boolean checkObjFieldIsData(Map> objs, String...keys) { + try { + Iterator>> iter = objs.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry> entry = iter.next(); + for (Object obj : entry.getValue()) { + if (checkObjField(obj, keys)) { + return true; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * 去掉设备类型没有在线率的统计 + * @param map + */ + public static void deleteNullDeviceType(Map> map, String...keys) { + List eventTypes = new ArrayList<>(); + Iterator>> iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry> entry = iter.next(); + boolean result = checkObjFieldIsData(entry.getValue(), keys); + if (!result) { + eventTypes.add(entry.getKey()); + } + } + for (Integer s: eventTypes) { + map.remove(s); + } + } + + /** + * 检测对象是否有数据 + * @param obj + * @return + * @throws IllegalAccessException + */ + private static boolean checkObjField(Object obj, String...keys) throws IllegalAccessException{ + for (Field f : obj.getClass().getDeclaredFields()) { + f.setAccessible(true); + if (keys != null) { + boolean isCheck = true; + for (String key : keys) { + if (key.equals(f.getName())) { + isCheck = false; + break; + } + } + if (!isCheck) { + continue; + } + } + if (obj instanceof String && f.get(obj) != null) { + if (!"".equals(String.valueOf(f.get(obj)))) { + return true; + } + } else if (obj instanceof Number && f.get(obj) != null) { + if (!"0".equals(String.valueOf(f.get(obj)))) { + return true; + } + } else if (f.get(obj) != null) { + if (!"0".equals(String.valueOf(f.get(obj)))) { + return true; + } + } + } + return false; + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/PasswordUtil.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/PasswordUtil.java new file mode 100644 index 0000000..fd89296 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/PasswordUtil.java @@ -0,0 +1,163 @@ +package com.tobacco.mp.utils; + +import javax.crypto.Cipher; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.xml.bind.DatatypeConverter; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.security.MessageDigest; +import java.security.SecureRandom; + +/** + * 加密加盐工具 + */ +public class PasswordUtil { + + public static final String ALGORITHM = "PBEWITHMD5andDES"; + + public static final int ITERATION_COUNT = 100; + + public static final String PRIVATE_KRY = "MD5"; + + public static byte[] initSalt() throws Exception { + // 实例化安全随机数 + SecureRandom random = new SecureRandom(); + return random.generateSeed(8); + } + + /** + * md5加密处理 + * @param s + * @return + */ + private static String md5(String s) { + try { + // MessageDigest是封装md5算法的工具对象还支持SHA算法 + MessageDigest md = MessageDigest.getInstance("MD5"); + // 通过digest拿到的任意字符串,得到的bates都是等长的 + byte[] bytes = md.digest(s.getBytes(StandardCharsets.UTF_8)); + return toHex(bytes); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 二进制转十六进制 + * @param bytes 二进制数据 + * @return + */ + private static String toHex(byte[] bytes) { + // 把二进制转换成十六进制字符串 + char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + StringBuilder ret = new StringBuilder(bytes.length * 2); + // 循环判断是为了补位操作 + for (int i = 0; i < bytes.length; i++) { + ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]); + ret.append(HEX_DIGITS[bytes[i] & 0x0f]); + } + return ret.toString(); + } + + /** + * 对密码进行加密加盐操作 + * @param password + * @return + */ + public static String encode(String password, String salt) { + //加密 + String hexPwd = md5(password); + //加盐操作 + StringBuilder builder = new StringBuilder(hexPwd); + builder.insert(18, salt); + //返回加密加盐后的字符串 + return builder.toString(); + } + + /** + * 校对密码是否匹配,匹配则返回true + * @param password + * @param dbPassword + * @return + */ + public static boolean match(String password, String dbPassword) { + StringBuilder builder = new StringBuilder(dbPassword); + //去盐操作,生成md5加密后原始字符 + builder.replace(18, 26, ""); + //加密新密码,生成md5加密字符 + password = md5(password); + //校对加密字符与原始字符是否匹配 + return password.equals(builder.toString()); + } + + /*** + * 转换密钥函数 + * @param password 密码 + * @return 密钥 + */ + private static Key toKey(String password) throws Exception { + //密钥材料 + PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); + //实例化 + SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); + //生成密钥 + return factory.generateSecret(keySpec); + } + + /*** + * @Deprecated 加密函数 + * @param data 待加密数据 + */ + public static String newEncrypt(String data, String salt) throws Exception { + // 盐加密转换为数组类型 + byte[] saltByte = salt.getBytes(); + // 通过私钥拿到密钥 + Key key = toKey(PRIVATE_KRY); + // 创建算法实体类 + PBEParameterSpec spec = new PBEParameterSpec(saltByte, ITERATION_COUNT); + // 创建加密实体类 + Cipher cipher = Cipher.getInstance(ALGORITHM); + // 通过私钥和算法类初始化加密构造 + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + // 方法需要数组 这里直接封装好了 + return DatatypeConverter.printBase64Binary(cipher.doFinal(data.getBytes())); + } + + + /*** + * @Deprecated 解密函数 + * @param encrypt 待解密数据 + */ + public static String newDecrypt(String encrypt, String salt) { + try { + // 盐加密转换为数组类型 + byte[] saltByte = salt.getBytes(); + // 通过私钥拿到密钥 + Key key = toKey(PRIVATE_KRY); + // 创建算法实体类 + PBEParameterSpec spec = new PBEParameterSpec(saltByte, ITERATION_COUNT); + // 创建加密实体类 + Cipher cipher = Cipher.getInstance(ALGORITHM); + // 通过私钥和算法类初始化加密构造 + cipher.init(Cipher.DECRYPT_MODE, key, spec); + // 方法需要数组 这里直接封装好了 + byte[] decode = DatatypeConverter.parseBase64Binary(encrypt); + return new String(cipher.doFinal(decode)); + } catch (Exception e) { + e.printStackTrace(); + return salt; + } + } + + public static void main(String[] args) throws Exception { +// String salt = RandomUtil.generateString(8); +// String salt = "UhHoJ6Z8"; +// String password = "123456"; +// System.err.println("盐值:" + salt); +// System.err.println("密码:" + newEncrypt(password, salt)); +// System.err.println(newDecrypt("qYc/bjJN5cI+bQjFQaEoMA==","WZIpOlpa")); + System.err.println(newDecrypt("fihwsY8n4KDkh0wCaKrZpQ==", "sUio5KqE")); + } +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RandomUtil.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RandomUtil.java new file mode 100644 index 0000000..e50a74e --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RandomUtil.java @@ -0,0 +1,95 @@ +package com.tobacco.mp.utils; + +import java.util.Random; + +/** + * 随机数工具 + */ +public class RandomUtil { + + public static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + public static final String LETTERCHAR = "abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /** + * 返回一个定长的随机字符串(只包含大小写字母、数字) + * @param length 随机字符串长度 + * @return 随机字符串 + */ + public static String generateString(int length) { + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length()))); + } + return sb.toString(); + } + + /** + * 返回一个定长的随机纯字母字符串(只包含大小写字母) + * @param length 随机字符串长度 + * @return 随机字符串 + */ + public static String generateMixString(int length) { + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(ALLCHAR.charAt(random.nextInt(LETTERCHAR.length()))); + } + return sb.toString(); + } + + /** + * 返回一个定长的随机纯大写字母字符串(只包含大小写字母) + * @param length 随机字符串长度 + * @return 随机字符串 + */ + public static String generateLowerString(int length) { + return generateMixString(length).toLowerCase(); + } + + /** + * 返回一个定长的随机纯小写字母字符串(只包含大小写字母) + * @param length 随机字符串长度 + * @return 随机字符串 + */ + public static String generateUpperString(int length) { + return generateMixString(length).toUpperCase(); + } + + /** + * 生成一个定长的纯0字符串 + * @param length 字符串长度 + * @return 纯0字符串 + */ + public static String generateZeroString(int length) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) { + sb.append('0'); + } + return sb.toString(); + } + + /** + * 根据数字生成一个定长的字符串,长度不够前面补0 + * @param num 数字 + * @param fixdLenth 字符串长度 + * @return 定长的字符串 + */ + public static String toFixdLengthString(long num, int fixdLenth) { + StringBuilder sb = new StringBuilder(); + String strNum = String.valueOf(num); + if (fixdLenth - strNum.length() >= 0) { + sb.append(generateZeroString(fixdLenth - strNum.length())); + } else { + throw new RuntimeException("将数字" + num + "转化为长度为" + fixdLenth + "的字符串发生异常!"); + } + sb.append(strNum); + return sb.toString(); + } + + public static void main(String[] args) { + System.out.println("定长的随机字符串(只包含大小写字母、数字):" + generateString(10)); + } + +} diff --git a/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RedisUtils.java b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RedisUtils.java new file mode 100644 index 0000000..fdd9cd3 --- /dev/null +++ b/cdaxxt-common/src/main/java/com/tobacco/mp/utils/RedisUtils.java @@ -0,0 +1,317 @@ +package com.tobacco.mp.utils; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Redis工具 + */ +@Component(value = "redisUtils") +public class RedisUtils { + + @Resource + private RedisTemplate redisTemplate; + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete(CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 设置过期时间 + * @param key + * @param expireTime + * @param unit + */ + public void setExpire(String key, Long expireTime, TimeUnit unit) { + redisTemplate.expire(key, expireTime, unit); + } + + /** + * 递增 + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + /** + * 获取redis中缓存信息 + * @return + */ + public List getRedisCacheMessage() { + List list = new ArrayList<>(); + Set keys = redisTemplate.keys("*"); + Iterator iterator = keys.iterator(); + while (iterator.hasNext()) { + list.add(iterator.next()); + } + return list; + } + +} diff --git a/cdaxxt-core/pom.xml b/cdaxxt-core/pom.xml new file mode 100644 index 0000000..2a7c5cb --- /dev/null +++ b/cdaxxt-core/pom.xml @@ -0,0 +1,44 @@ + + + + integration-platform-access + com.tobacco.mp + 1.0-SNAPSHOT + + 4.0.0 + + cdaxxt-core + + + + com.tobacco.mp + cdaxxt-common + 1.0-SNAPSHOT + + + org.thymeleaf + thymeleaf-spring5 + + + + + + + src/main/java + + **/*.xml + + + + src/main/resources + + **/* + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..62af77d --- /dev/null +++ b/pom.xml @@ -0,0 +1,282 @@ + + + 4.0.0 + + com.tobacco.mp + integration-platform-access + pom + 1.0-SNAPSHOT + + + cdaxxt-bootstrap + cdaxxt-business + cdaxxt-common + cdaxxt-core + assembly + + + + + org.springframework.boot + spring-boot-starter-parent + 2.3.4.RELEASE + + + + + 1.8 + + + + + org.apache.shiro + shiro-spring + 1.6.0 + + + org.springframework.boot + spring-boot-starter-web + + + mysql + mysql-connector-java + 5.1.49 + runtime + + + com.baomidou + mybatis-plus-boot-starter + 3.4.0 + + + tomcat-jdbc + org.apache.tomcat + + + + + org.apache.velocity + velocity-engine-core + 2.0 + + + com.baomidou + mybatis-plus-generator + 3.4.0 + + + com.alibaba + druid-spring-boot-starter + 1.1.13 + + + org.projectlombok + lombok + true + + + org.apache.commons + commons-lang3 + 3.11 + + + + commons-beanutils + commons-beanutils + 1.9.3 + + + + org.apache.commons + commons-collections4 + 4.4 + + + com.alibaba + fastjson + 1.2.47 + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework + spring-context-support + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + cn.hutool + hutool-all + 4.5.16 + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.security + spring-security-core + 5.3.4.RELEASE + + + org.springframework.boot + spring-boot-starter-aop + test + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.cloud + spring-cloud-starter-openfeign + 2.2.5.RELEASE + + + org.springframework.boot + spring-boot-starter-webflux + + + io.github.openfeign + feign-httpclient + 11.8 + + + com.google.guava + guava + 31.1-jre + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime + + + + + + + com.aliyun.bizworks + ubcp-api-client + 1.13.0-SNAPSHOT + + + + com.tobacco.mp + tobacco-mp-uc-client + 2.6.8-RELEASE + + + + com.alibaba.bizworks + core-common + 1.17.1 + + + + com.tobacco.mp + tobacco-mp-auth-client + 1.0.0-SNAPSHOT + + + + com.tobacco.mp + tobacco-mp-mcext-client + 1.0.0-SNAPSHOT + + + + com.tobacco.mp + tobacco-mp-ttc-client + 1.0.0-SNAPSHOT + + + + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + ${java.version} + ${java.version} + UTF-8 + + -parameters + + false + + + + + + + + \ No newline at end of file