From f1119a54a2580f4b0e7a075bd9f808308e76afdb Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Thu, 10 Jul 2025 18:30:39 +0800 Subject: [PATCH] =?UTF-8?q?7.10=20DDD=E5=B7=A5=E7=A8=8B=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96+=E5=BE=AE=E4=BF=A1=E5=85=AC=E4=BC=97=E5=8F=B7?= =?UTF-8?q?=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 40 ++++ docs/dev-ops/app/start.sh | 20 ++ docs/dev-ops/app/stop.sh | 1 + docs/dev-ops/docker-compose-app.yml | 27 +++ .../docker-compose-environment-aliyun.yml | 87 ++++++++ docs/dev-ops/docker-compose-environment.yml | 86 ++++++++ .../dev-ops/mysql/sql/xfg-frame-archetype.sql | 108 ++++++++++ pay-mall-api/pom.xml | 38 ++++ .../java/edu/whut/api/dto/package-info.java | 4 + .../main/java/edu/whut/api/package-info.java | 4 + .../java/edu/whut/api/response/Response.java | 22 ++ pay-mall-app/Dockerfile | 17 ++ pay-mall-app/pom.xml | 137 ++++++++++++ .../src/main/java/edu/whut/Application.java | 15 ++ .../java/edu/whut/config/GuavaConfig.java | 20 ++ .../edu/whut/config/ThreadPoolConfig.java | 50 +++++ .../config/ThreadPoolConfigProperties.java | 26 +++ .../java/edu/whut/config/package-info.java | 6 + .../src/main/java/edu/whut/package-info.java | 4 + .../src/main/resources/application-dev.yml | 48 +++++ .../src/main/resources/application-prod.yml | 41 ++++ .../src/main/resources/application-test.yml | 41 ++++ .../src/main/resources/application.yml | 5 + .../src/main/resources/logback-spring.xml | 113 ++++++++++ .../mybatis/config/mybatis-config.xml | 9 + .../mybatis/mapper/frame_case_mapper.xml | 25 +++ .../src/test/java/edu/whut/test/ApiTest.java | 19 ++ pay-mall-domain/pom.xml | 75 +++++++ .../whut/domain/xxx/adapter/package-info.java | 4 + .../domain/xxx/adapter/port/package-info.java | 4 + .../xxx/adapter/repository/package-info.java | 5 + .../xxx/model/aggregate/package-info.java | 7 + .../domain/xxx/model/entity/package-info.java | 7 + .../domain/xxx/model/valobj/package-info.java | 6 + .../whut/domain/xxx/service/package-info.java | 1 + .../yyy/adapter/repository/package-info.java | 0 .../yyy/model/aggregate/package-info.java | 7 + .../domain/yyy/model/entity/package-info.java | 7 + .../domain/yyy/model/valobj/package-info.java | 6 + .../whut/domain/yyy/service/package-info.java | 1 + pay-mall-infrastructure/pom.xml | 46 ++++ .../adapter/port/package-info.java | 4 + .../adapter/repository/package-info.java | 4 + .../whut/infrastructure/dao/package-info.java | 4 + .../infrastructure/dao/po/package-info.java | 4 + .../gateway/dto/package-info.java | 0 .../infrastructure/gateway/package-info.java | 4 + .../infrastructure/redis/package-info.java | 4 + pay-mall-trigger/pom.xml | 63 ++++++ .../trigger/http/WeixinPortalController.java | 76 +++++++ .../edu/whut/trigger/http/package-info.java | 4 + .../edu/whut/trigger/job/package-info.java | 4 + .../whut/trigger/listener/package-info.java | 5 + pay-mall-types/pom.xml | 53 +++++ .../java/edu/whut/types/common/Constants.java | 7 + .../edu/whut/types/enums/ResponseCode.java | 20 ++ .../whut/types/exception/AppException.java | 46 ++++ .../whut/types/weixin/MessageTextEntity.java | 118 ++++++++++ .../edu/whut/types/weixin/SignatureUtil.java | 68 ++++++ .../java/edu/whut/types/weixin/XmlUtil.java | 151 +++++++++++++ pom.xml | 203 ++++++++++++++++++ 61 files changed, 2031 insertions(+) create mode 100644 .gitignore create mode 100644 docs/dev-ops/app/start.sh create mode 100644 docs/dev-ops/app/stop.sh create mode 100644 docs/dev-ops/docker-compose-app.yml create mode 100644 docs/dev-ops/docker-compose-environment-aliyun.yml create mode 100644 docs/dev-ops/docker-compose-environment.yml create mode 100644 docs/dev-ops/mysql/sql/xfg-frame-archetype.sql create mode 100644 pay-mall-api/pom.xml create mode 100644 pay-mall-api/src/main/java/edu/whut/api/dto/package-info.java create mode 100644 pay-mall-api/src/main/java/edu/whut/api/package-info.java create mode 100644 pay-mall-api/src/main/java/edu/whut/api/response/Response.java create mode 100644 pay-mall-app/Dockerfile create mode 100644 pay-mall-app/pom.xml create mode 100644 pay-mall-app/src/main/java/edu/whut/Application.java create mode 100644 pay-mall-app/src/main/java/edu/whut/config/GuavaConfig.java create mode 100644 pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfig.java create mode 100644 pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfigProperties.java create mode 100644 pay-mall-app/src/main/java/edu/whut/config/package-info.java create mode 100644 pay-mall-app/src/main/java/edu/whut/package-info.java create mode 100644 pay-mall-app/src/main/resources/application-dev.yml create mode 100644 pay-mall-app/src/main/resources/application-prod.yml create mode 100644 pay-mall-app/src/main/resources/application-test.yml create mode 100644 pay-mall-app/src/main/resources/application.yml create mode 100644 pay-mall-app/src/main/resources/logback-spring.xml create mode 100644 pay-mall-app/src/main/resources/mybatis/config/mybatis-config.xml create mode 100644 pay-mall-app/src/main/resources/mybatis/mapper/frame_case_mapper.xml create mode 100644 pay-mall-app/src/test/java/edu/whut/test/ApiTest.java create mode 100644 pay-mall-domain/pom.xml create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/port/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/repository/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/aggregate/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/entity/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/valobj/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/xxx/service/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/yyy/adapter/repository/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/aggregate/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/entity/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/valobj/package-info.java create mode 100644 pay-mall-domain/src/main/java/edu/whut/domain/yyy/service/package-info.java create mode 100644 pay-mall-infrastructure/pom.xml create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/port/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/po/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/dto/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/package-info.java create mode 100644 pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/redis/package-info.java create mode 100644 pay-mall-trigger/pom.xml create mode 100644 pay-mall-trigger/src/main/java/edu/whut/trigger/http/WeixinPortalController.java create mode 100644 pay-mall-trigger/src/main/java/edu/whut/trigger/http/package-info.java create mode 100644 pay-mall-trigger/src/main/java/edu/whut/trigger/job/package-info.java create mode 100644 pay-mall-trigger/src/main/java/edu/whut/trigger/listener/package-info.java create mode 100644 pay-mall-types/pom.xml create mode 100644 pay-mall-types/src/main/java/edu/whut/types/common/Constants.java create mode 100644 pay-mall-types/src/main/java/edu/whut/types/enums/ResponseCode.java create mode 100644 pay-mall-types/src/main/java/edu/whut/types/exception/AppException.java create mode 100644 pay-mall-types/src/main/java/edu/whut/types/weixin/MessageTextEntity.java create mode 100644 pay-mall-types/src/main/java/edu/whut/types/weixin/SignatureUtil.java create mode 100644 pay-mall-types/src/main/java/edu/whut/types/weixin/XmlUtil.java create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..613ee2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +/data/ +/.idea/ diff --git a/docs/dev-ops/app/start.sh b/docs/dev-ops/app/start.sh new file mode 100644 index 0000000..368087e --- /dev/null +++ b/docs/dev-ops/app/start.sh @@ -0,0 +1,20 @@ +CONTAINER_NAME=pay-mall +IMAGE_NAME=system/pay-mall:1.0-SNAPSHOT +PORT=8091 + +echo "容器部署开始 ${CONTAINER_NAME}" + +# 停止容器 +docker stop ${CONTAINER_NAME} + +# 删除容器 +docker rm ${CONTAINER_NAME} + +# 启动容器 +docker run --name ${CONTAINER_NAME} \ +-p ${PORT}:${PORT} \ +-d ${IMAGE_NAME} + +echo "容器部署成功 ${CONTAINER_NAME}" + +docker logs -f ${CONTAINER_NAME} \ No newline at end of file diff --git a/docs/dev-ops/app/stop.sh b/docs/dev-ops/app/stop.sh new file mode 100644 index 0000000..67c51b4 --- /dev/null +++ b/docs/dev-ops/app/stop.sh @@ -0,0 +1 @@ +docker stop pay-mall \ No newline at end of file diff --git a/docs/dev-ops/docker-compose-app.yml b/docs/dev-ops/docker-compose-app.yml new file mode 100644 index 0000000..a0f9f05 --- /dev/null +++ b/docs/dev-ops/docker-compose-app.yml @@ -0,0 +1,27 @@ +# /usr/local/bin/docker-compose -f /docs/dev-ops/environment/environment-docker-compose-2.4.yml up -d +version: '3.8' +# docker-compose -f docker-compose-app.yml up -d +# 你需要修改system为你自身系统的仓库名 +services: + pay-mall: + image: system/pay-mall:1.0-SNAPSHOT + container_name: pay-mall + restart: on-failure + ports: + - "8092:8092" + environment: + - TZ=PRC + - SERVER_PORT=8091 + volumes: + - ./log:/data/log + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - my-network + +networks: + my-network: + driver: bridge diff --git a/docs/dev-ops/docker-compose-environment-aliyun.yml b/docs/dev-ops/docker-compose-environment-aliyun.yml new file mode 100644 index 0000000..87bdbe0 --- /dev/null +++ b/docs/dev-ops/docker-compose-environment-aliyun.yml @@ -0,0 +1,87 @@ +# 命令执行 docker-compose -f docker-compose-environment-aliyun.yml up -d +# docker 代理和使用文档;https://bugstack.cn/md/road-map/docker.html +version: '3.9' +services: + mysql: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32 + container_name: mysql + command: --default-authentication-plugin=mysql_native_password + restart: always + environment: + TZ: Asia/Shanghai + MYSQL_ROOT_PASSWORD: 123456 + ports: + - "13306:3306" + volumes: + - ./mysql/sql:/docker-entrypoint-initdb.d + healthcheck: + test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ] + interval: 5s + timeout: 10s + retries: 10 + start_period: 15s + networks: + - my-network + + # phpmyadmin https://hub.docker.com/_/phpmyadmin + phpmyadmin: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/phpmyadmin:5.2.1 + container_name: phpmyadmin + hostname: phpmyadmin + ports: + - 8899:80 + environment: + - PMA_HOST=mysql + - PMA_PORT=3306 + - MYSQL_ROOT_PASSWORD=123qwe!@#QWE + depends_on: + mysql: + condition: service_healthy + networks: + - my-network + + # Redis + redis: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2 + container_name: redis + restart: always + hostname: redis + privileged: true + ports: + - 16379:6379 + volumes: + - ./redis/redis.conf:/usr/local/etc/redis/redis.conf + command: redis-server /usr/local/etc/redis/redis.conf + networks: + - my-network + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + interval: 10s + timeout: 5s + retries: 3 + + # RedisAdmin https://github.com/joeferner/redis-commander + # 账密 admin/admin + redis-admin: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis-commander:0.8.0 + container_name: redis-admin + hostname: redis-commander + restart: always + ports: + - 8081:8081 + environment: + - REDIS_HOSTS=local:redis:6379 + - HTTP_USER=admin + - HTTP_PASSWORD=admin + - LANG=C.UTF-8 + - LANGUAGE=C.UTF-8 + - LC_ALL=C.UTF-8 + networks: + - my-network + depends_on: + redis: + condition: service_healthy + +networks: + my-network: + driver: bridge \ No newline at end of file diff --git a/docs/dev-ops/docker-compose-environment.yml b/docs/dev-ops/docker-compose-environment.yml new file mode 100644 index 0000000..2a270b8 --- /dev/null +++ b/docs/dev-ops/docker-compose-environment.yml @@ -0,0 +1,86 @@ +# 命令执行 docker-compose -f docker-compose-environment-aliyun.yml up -d +# docker 代理和使用文档;https://bugstack.cn/md/road-map/docker.html +version: '3.9' +services: + mysql: + image: mysql:8.0.32 + container_name: mysql + command: --default-authentication-plugin=mysql_native_password + restart: always + environment: + TZ: Asia/Shanghai + MYSQL_ROOT_PASSWORD: 123456 + ports: + - "13306:3306" + volumes: + - ./mysql/sql:/docker-entrypoint-initdb.d + healthcheck: + test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ] + interval: 5s + timeout: 10s + retries: 10 + start_period: 15s + networks: + - my-network + + # phpmyadmin https://hub.docker.com/_/phpmyadmin + phpmyadmin: + image: phpmyadmin:5.2.1 + container_name: phpmyadmin + hostname: phpmyadmin + ports: + - 8899:80 + environment: + - PMA_HOST=mysql + - PMA_PORT=3306 + - MYSQL_ROOT_PASSWORD=123456 + depends_on: + mysql: + condition: service_healthy + networks: + - my-network + + # Redis + redis: + image: redis:6.2 + container_name: redis + restart: always + hostname: redis + privileged: true + ports: + - 16379:6379 + volumes: + - ./redis/redis.conf:/usr/local/etc/redis/redis.conf + command: redis-server /usr/local/etc/redis/redis.conf + networks: + - my-network + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + interval: 10s + timeout: 5s + retries: 3 + + # RedisAdmin https://github.com/joeferner/redis-commander + redis-admin: + image: spryker/redis-commander:0.8.0 + container_name: redis-admin + hostname: redis-commander + restart: always + ports: + - 8081:8081 + environment: + - REDIS_HOSTS=local:redis:6379 + - HTTP_USER=admin + - HTTP_PASSWORD=admin + - LANG=C.UTF-8 + - LANGUAGE=C.UTF-8 + - LC_ALL=C.UTF-8 + networks: + - my-network + depends_on: + redis: + condition: service_healthy + +networks: + my-network: + driver: bridge \ No newline at end of file diff --git a/docs/dev-ops/mysql/sql/xfg-frame-archetype.sql b/docs/dev-ops/mysql/sql/xfg-frame-archetype.sql new file mode 100644 index 0000000..8b598d3 --- /dev/null +++ b/docs/dev-ops/mysql/sql/xfg-frame-archetype.sql @@ -0,0 +1,108 @@ +/* + Navicat Premium Data Transfer + + Source Server : 127.0.0.1 + Source Server Type : MySQL + Source Server Version : 50639 + Source Host : localhost:3306 + Source Schema : road-map + + Target Server Type : MySQL + Target Server Version : 50639 + File Encoding : 65001 + + Date: 15/07/2023 09:26:39 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +CREATE database if NOT EXISTS `xfg_frame_archetype` default character set utf8mb4 collate utf8mb4_0900_ai_ci; +use `xfg_frame_archetype`; + +-- ---------------------------- +-- Table structure for employee +-- ---------------------------- +DROP TABLE IF EXISTS `employee`; +CREATE TABLE `employee` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `employee_number` varchar(16) NOT NULL DEFAULT '' COMMENT '雇员ID', + `employee_name` varchar(32) NOT NULL DEFAULT '' COMMENT '雇员姓名', + `employee_level` varchar(8) NOT NULL DEFAULT '' COMMENT '雇员级别', + `employee_title` varchar(16) NOT NULL DEFAULT '' COMMENT '雇员岗位Title', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_employee_number` (`employee_number`) +) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of employee +-- ---------------------------- +BEGIN; +INSERT INTO `employee` VALUES (1, '10000001', 'sXvfDpsWnJdLsCVk64tJgw==', 'T-3', '中级工程师', '2023-07-14 15:26:26', '2023-07-14 15:26:26'); +INSERT INTO `employee` VALUES (2, '10000010', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-14 15:34:40', '2023-07-14 15:34:40'); +INSERT INTO `employee` VALUES (3, '10000011', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-14 15:34:40', '2023-07-14 15:34:40'); +INSERT INTO `employee` VALUES (4, '10000012', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-14 15:34:40', '2023-07-14 15:34:40'); +INSERT INTO `employee` VALUES (5, '10000013', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-14 15:34:40', '2023-07-14 15:34:40'); +INSERT INTO `employee` VALUES (6, '10000014', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-14 15:34:40', '2023-07-14 15:34:40'); +INSERT INTO `employee` VALUES (9, '10000002', 'sXvfDpsWnJdLsCVk64tJgw==', 'T2', '见习工程师', '2023-07-15 07:42:52', '2023-07-15 07:42:52'); +INSERT INTO `employee` VALUES (22, '10000015', 'hMCgLG6WV3CsNBQ1UD6PEQ==', 'T2', '见习工程师', '2023-07-15 08:02:31', '2023-07-15 08:02:31'); +INSERT INTO `employee` VALUES (23, '10000016', 'hMCgLG6WV3CsNBQ1UD6PEQ==', 'T2', '见习工程师', '2023-07-15 08:02:31', '2023-07-15 08:02:31'); +INSERT INTO `employee` VALUES (24, '10000017', 'hMCgLG6WV3CsNBQ1UD6PEQ==', 'T2', '见习工程师', '2023-07-15 08:02:31', '2023-07-15 08:02:31'); +INSERT INTO `employee` VALUES (39, '10000022', 'GyG+V0r6mBCNsdusuKl03g==', 'T1', '实习工程师', '2023-07-15 09:17:49', '2023-07-15 09:17:49'); +COMMIT; + +-- ---------------------------- +-- Table structure for employee_salary +-- ---------------------------- +DROP TABLE IF EXISTS `employee_salary`; +CREATE TABLE `employee_salary` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `employee_number` varchar(16) NOT NULL DEFAULT '' COMMENT '雇员编号', + `salary_total_amount` decimal(8,2) NOT NULL COMMENT '薪资总额', + `salary_merit_amount` decimal(8,2) NOT NULL COMMENT '绩效工资', + `salary_base_amount` decimal(8,2) NOT NULL COMMENT '基础工资', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_employee_number` (`employee_number`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of employee_salary +-- ---------------------------- +BEGIN; +INSERT INTO `employee_salary` VALUES (1, '10000001', 5100.00, 1020.00, 4080.00, '2023-07-14 16:09:06', '2023-07-14 16:09:06'); +INSERT INTO `employee_salary` VALUES (2, '10000010', 5000.00, 1000.00, 4000.00, '2023-07-14 16:17:10', '2023-07-14 16:17:10'); +INSERT INTO `employee_salary` VALUES (3, '10000011', 5000.00, 1000.00, 4000.00, '2023-07-14 16:17:10', '2023-07-14 16:17:10'); +INSERT INTO `employee_salary` VALUES (4, '10000012', 5000.00, 1000.00, 4000.00, '2023-07-14 16:17:10', '2023-07-14 16:17:10'); +INSERT INTO `employee_salary` VALUES (5, '10000013', 5000.00, 1000.00, 4000.00, '2023-07-14 16:17:10', '2023-07-14 16:17:10'); +INSERT INTO `employee_salary` VALUES (6, '10000014', 5000.00, 1000.00, 4000.00, '2023-07-14 16:17:10', '2023-07-14 16:17:10'); +INSERT INTO `employee_salary` VALUES (8, '10000022', 100.00, 10.00, 90.00, '2023-07-15 09:17:49', '2023-07-15 09:17:49'); +COMMIT; + +-- ---------------------------- +-- Table structure for employee_salary_adjust +-- ---------------------------- +DROP TABLE IF EXISTS `employee_salary_adjust`; +CREATE TABLE `employee_salary_adjust` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `employee_number` varchar(16) NOT NULL DEFAULT '' COMMENT '雇员编号', + `adjust_order_id` varchar(32) NOT NULL DEFAULT '' COMMENT '调薪单号', + `adjust_total_amount` decimal(8,2) NOT NULL COMMENT '总额调薪', + `adjust_base_amount` decimal(8,2) NOT NULL COMMENT '基础调薪', + `adjust_merit_amount` decimal(8,2) NOT NULL COMMENT '绩效调薪', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_order_id` (`adjust_order_id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of employee_salary_adjust +-- ---------------------------- +BEGIN; +INSERT INTO `employee_salary_adjust` VALUES (1, '10000001', '109089990198888811', 1000.00, 800.00, 200.00, '2023-07-14 16:55:53', '2023-07-14 16:55:53'); +INSERT INTO `employee_salary_adjust` VALUES (2, '10000001', '100908977676001', 100.00, 20.00, 80.00, '2023-07-14 21:57:39', '2023-07-14 21:57:39'); +COMMIT; \ No newline at end of file diff --git a/pay-mall-api/pom.xml b/pay-mall-api/pom.xml new file mode 100644 index 0000000..cb6db6b --- /dev/null +++ b/pay-mall-api/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-api + + + + org.projectlombok + lombok + 1.18.26 + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + diff --git a/pay-mall-api/src/main/java/edu/whut/api/dto/package-info.java b/pay-mall-api/src/main/java/edu/whut/api/dto/package-info.java new file mode 100644 index 0000000..e19888a --- /dev/null +++ b/pay-mall-api/src/main/java/edu/whut/api/dto/package-info.java @@ -0,0 +1,4 @@ +/** + * 数据传输对象 xxxRequestDTO xxxResponseDTO + */ +package edu.whut.api.dto; \ No newline at end of file diff --git a/pay-mall-api/src/main/java/edu/whut/api/package-info.java b/pay-mall-api/src/main/java/edu/whut/api/package-info.java new file mode 100644 index 0000000..d4d52da --- /dev/null +++ b/pay-mall-api/src/main/java/edu/whut/api/package-info.java @@ -0,0 +1,4 @@ +/** + * 定义api接口 + */ +package edu.whut.api; \ No newline at end of file diff --git a/pay-mall-api/src/main/java/edu/whut/api/response/Response.java b/pay-mall-api/src/main/java/edu/whut/api/response/Response.java new file mode 100644 index 0000000..5452cd0 --- /dev/null +++ b/pay-mall-api/src/main/java/edu/whut/api/response/Response.java @@ -0,0 +1,22 @@ +package edu.whut.api.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Response implements Serializable { + + private static final long serialVersionUID = 7000723935764546321L; + + private String code; + private String info; + private T data; + +} diff --git a/pay-mall-app/Dockerfile b/pay-mall-app/Dockerfile new file mode 100644 index 0000000..326c3ab --- /dev/null +++ b/pay-mall-app/Dockerfile @@ -0,0 +1,17 @@ +# 基础镜像 +FROM openjdk:8-jre-slim + +# 作者 +MAINTAINER smile + +# 配置 +ENV PARAMS="" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 添加应用 +ADD target/pay-mall-app.jar /pay-mall-app.jar + +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /pay-mall-app.jar $PARAMS"] \ No newline at end of file diff --git a/pay-mall-app/pom.xml b/pay-mall-app/pom.xml new file mode 100644 index 0000000..e0fa5ad --- /dev/null +++ b/pay-mall-app/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-app + + jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.tomcat.embed + tomcat-embed-core + + + org.springframework.boot + spring-boot-configuration-processor + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + + mysql + mysql-connector-java + + + com.alibaba + fastjson + + + org.apache.commons + commons-lang3 + + + org.projectlombok + lombok + + + com.google.guava + guava + + + junit + junit + test + + + io.jsonwebtoken + jjwt + + + com.auth0 + java-jwt + + + commons-codec + commons-codec + + + com.squareup.retrofit2 + converter-gson + 2.9.0 + + + + + edu.whut + pay-mall-trigger + + + edu.whut + pay-mall-infrastructure + + + + + pay-mall-app + + + src/main/resources + true + + **/** + + + + + + src/test/resources + true + + **/** + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.6 + + true + false + + **/*Test.java + + + + + org.springframework.boot + spring-boot-maven-plugin + + edu.whut.Application + JAR + + + + + + diff --git a/pay-mall-app/src/main/java/edu/whut/Application.java b/pay-mall-app/src/main/java/edu/whut/Application.java new file mode 100644 index 0000000..474acfa --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/Application.java @@ -0,0 +1,15 @@ +package edu.whut; + +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@Configurable +public class Application { + + public static void main(String[] args){ + SpringApplication.run(Application.class); + } + +} diff --git a/pay-mall-app/src/main/java/edu/whut/config/GuavaConfig.java b/pay-mall-app/src/main/java/edu/whut/config/GuavaConfig.java new file mode 100644 index 0000000..a411e36 --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/config/GuavaConfig.java @@ -0,0 +1,20 @@ +package edu.whut.config; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +@Configuration +public class GuavaConfig { + + @Bean(name = "cache") + public Cache cache() { + return CacheBuilder.newBuilder() + .expireAfterWrite(3, TimeUnit.SECONDS) + .build(); + } + +} diff --git a/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfig.java b/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfig.java new file mode 100644 index 0000000..005571a --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfig.java @@ -0,0 +1,50 @@ +package edu.whut.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +import java.util.concurrent.*; + +@Slf4j +@EnableAsync +@Configuration +@EnableConfigurationProperties(ThreadPoolConfigProperties.class) +public class ThreadPoolConfig { + + @Bean + @ConditionalOnMissingBean(ThreadPoolExecutor.class) + public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + // 实例化策略 + RejectedExecutionHandler handler; + switch (properties.getPolicy()){ + case "AbortPolicy": + handler = new ThreadPoolExecutor.AbortPolicy(); + break; + case "DiscardPolicy": + handler = new ThreadPoolExecutor.DiscardPolicy(); + break; + case "DiscardOldestPolicy": + handler = new ThreadPoolExecutor.DiscardOldestPolicy(); + break; + case "CallerRunsPolicy": + handler = new ThreadPoolExecutor.CallerRunsPolicy(); + break; + default: + handler = new ThreadPoolExecutor.AbortPolicy(); + break; + } + // 创建线程池 + return new ThreadPoolExecutor(properties.getCorePoolSize(), + properties.getMaxPoolSize(), + properties.getKeepAliveTime(), + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(properties.getBlockQueueSize()), + Executors.defaultThreadFactory(), + handler); + } + +} diff --git a/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfigProperties.java b/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfigProperties.java new file mode 100644 index 0000000..db297b7 --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/config/ThreadPoolConfigProperties.java @@ -0,0 +1,26 @@ +package edu.whut.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "thread.pool.executor.config", ignoreInvalidFields = true) +public class ThreadPoolConfigProperties { + + /** 核心线程数 */ + private Integer corePoolSize = 20; + /** 最大线程数 */ + private Integer maxPoolSize = 200; + /** 最大等待时间 */ + private Long keepAliveTime = 10L; + /** 最大队列数 */ + private Integer blockQueueSize = 5000; + /* + * AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 + * DiscardPolicy:直接丢弃任务,但是不会抛出异常 + * DiscardOldestPolicy:将最早进入队列的任务删除,之后再尝试加入队列的任务被拒绝 + * CallerRunsPolicy:如果任务添加线程池失败,那么主线程自己执行该任务 + * */ + private String policy = "AbortPolicy"; + +} diff --git a/pay-mall-app/src/main/java/edu/whut/config/package-info.java b/pay-mall-app/src/main/java/edu/whut/config/package-info.java new file mode 100644 index 0000000..727ed2e --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/config/package-info.java @@ -0,0 +1,6 @@ +/** + * 1. 用于管理引入的Jar所需的资源启动或者初始化处理 + * 2. 如果有AOP切面,可以再建一个aop包,来写切面逻辑 + */ +package edu.whut.config; + diff --git a/pay-mall-app/src/main/java/edu/whut/package-info.java b/pay-mall-app/src/main/java/edu/whut/package-info.java new file mode 100644 index 0000000..2c94a72 --- /dev/null +++ b/pay-mall-app/src/main/java/edu/whut/package-info.java @@ -0,0 +1,4 @@ +/** + * 应用启动层,注意Application所在的包路径,是在上一层。这样才能扫描到其他 module + * */ +package edu.whut; \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/application-dev.yml b/pay-mall-app/src/main/resources/application-dev.yml new file mode 100644 index 0000000..9eebd99 --- /dev/null +++ b/pay-mall-app/src/main/resources/application-dev.yml @@ -0,0 +1,48 @@ +server: + port: 8092 + +# 线程池配置 +thread: + pool: + executor: + config: + core-pool-size: 20 + max-pool-size: 50 + keep-alive-time: 5000 + block-queue-size: 5000 + policy: CallerRunsPolicy + +# 数据库配置;启动时配置数据库资源信息 +spring: + datasource: + username: root + password: 123456 + url: jdbc:mysql://127.0.0.1:13306/pay-mall?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + pool-name: Retail_HikariCP + minimum-idle: 15 #最小空闲连接数量 + idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟) + maximum-pool-size: 25 #连接池最大连接数,默认是10 + auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true + max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 + connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000 + connection-test-query: SELECT 1 + type: com.zaxxer.hikari.HikariDataSource + +# MyBatis 配置【如需使用记得打开】 +#mybatis: +# mapper-locations: classpath:/mybatis/mapper/*.xml +# config-location: classpath:/mybatis/config/mybatis-config.xml + +# 微信公众号对接 +weixin: + config: + originalid: gh_b748269e1f4c + token: b8b6 + +# 日志 +logging: + level: + root: info + config: classpath:logback-spring.xml \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/application-prod.yml b/pay-mall-app/src/main/resources/application-prod.yml new file mode 100644 index 0000000..26df58f --- /dev/null +++ b/pay-mall-app/src/main/resources/application-prod.yml @@ -0,0 +1,41 @@ +server: + port: 8092 + +# 线程池配置 +thread: + pool: + executor: + config: + core-pool-size: 20 + max-pool-size: 50 + keep-alive-time: 5000 + block-queue-size: 5000 + policy: CallerRunsPolicy + +# 数据库配置 +#spring: +# datasource: +# username: root +# password: 123456 +# url: jdbc:mysql://127.0.0.1:3306/pay-mall?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true +# driver-class-name: com.mysql.cj.jdbc.Driver +# hikari: +# pool-name: Retail_HikariCP +# minimum-idle: 15 #最小空闲连接数量 +# idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟) +# maximum-pool-size: 25 #连接池最大连接数,默认是10 +# auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true +# max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 +# connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000 +# connection-test-query: SELECT 1 +# type: com.zaxxer.hikari.HikariDataSource + +#mybatis: +# mapper-locations: classpath:/mybatis/mapper/*.xml +# config-location: classpath:/mybatis/config/mybatis-config.xml + +# 日志 +logging: + level: + root: info + config: classpath:logback-spring.xml \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/application-test.yml b/pay-mall-app/src/main/resources/application-test.yml new file mode 100644 index 0000000..26df58f --- /dev/null +++ b/pay-mall-app/src/main/resources/application-test.yml @@ -0,0 +1,41 @@ +server: + port: 8092 + +# 线程池配置 +thread: + pool: + executor: + config: + core-pool-size: 20 + max-pool-size: 50 + keep-alive-time: 5000 + block-queue-size: 5000 + policy: CallerRunsPolicy + +# 数据库配置 +#spring: +# datasource: +# username: root +# password: 123456 +# url: jdbc:mysql://127.0.0.1:3306/pay-mall?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true +# driver-class-name: com.mysql.cj.jdbc.Driver +# hikari: +# pool-name: Retail_HikariCP +# minimum-idle: 15 #最小空闲连接数量 +# idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟) +# maximum-pool-size: 25 #连接池最大连接数,默认是10 +# auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true +# max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 +# connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000 +# connection-test-query: SELECT 1 +# type: com.zaxxer.hikari.HikariDataSource + +#mybatis: +# mapper-locations: classpath:/mybatis/mapper/*.xml +# config-location: classpath:/mybatis/config/mybatis-config.xml + +# 日志 +logging: + level: + root: info + config: classpath:logback-spring.xml \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/application.yml b/pay-mall-app/src/main/resources/application.yml new file mode 100644 index 0000000..da00f44 --- /dev/null +++ b/pay-mall-app/src/main/resources/application.yml @@ -0,0 +1,5 @@ +spring: + config: + name: pay-mall-app + profiles: + active: dev diff --git a/pay-mall-app/src/main/resources/logback-spring.xml b/pay-mall-app/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..932ad72 --- /dev/null +++ b/pay-mall-app/src/main/resources/logback-spring.xml @@ -0,0 +1,113 @@ + + + + + logback + + + + + + + + + + + + info + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + + + + + ./data/log/log_info.log + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + + ./data/log/log-info-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + 10GB + + + + + + + ./data/log/log_error.log + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n + UTF-8 + + + + ./data/log/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 7 + 5GB + + + + WARN + + + + + + + 0 + + 8192 + + true + + false + + + + + + 0 + + 1024 + + true + + false + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/mybatis/config/mybatis-config.xml b/pay-mall-app/src/main/resources/mybatis/config/mybatis-config.xml new file mode 100644 index 0000000..ed8ee96 --- /dev/null +++ b/pay-mall-app/src/main/resources/mybatis/config/mybatis-config.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/pay-mall-app/src/main/resources/mybatis/mapper/frame_case_mapper.xml b/pay-mall-app/src/main/resources/mybatis/mapper/frame_case_mapper.xml new file mode 100644 index 0000000..4e14eaf --- /dev/null +++ b/pay-mall-app/src/main/resources/mybatis/mapper/frame_case_mapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + INSERT INTO table(a,b,c) VALUES(#{a}, #{b}, #{c}) + + + + UPDATE table SET a = #{a} WHERE b = #{b} + + + + + diff --git a/pay-mall-app/src/test/java/edu/whut/test/ApiTest.java b/pay-mall-app/src/test/java/edu/whut/test/ApiTest.java new file mode 100644 index 0000000..025c536 --- /dev/null +++ b/pay-mall-app/src/test/java/edu/whut/test/ApiTest.java @@ -0,0 +1,19 @@ +package edu.whut.test; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class ApiTest { + + @Test + public void test() { + log.info("测试完成"); + } + +} diff --git a/pay-mall-domain/pom.xml b/pay-mall-domain/pom.xml new file mode 100644 index 0000000..e321001 --- /dev/null +++ b/pay-mall-domain/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-domain + + + + org.projectlombok + lombok + + + com.alibaba + fastjson + + + org.apache.commons + commons-lang3 + + + com.google.guava + guava + + + io.jsonwebtoken + jjwt + + + com.auth0 + java-jwt + + + commons-codec + commons-codec + + + + edu.whut + pay-mall-types + + + + + pay-mall-domain + + + org.apache.maven.plugins + maven-archetype-plugin + 3.2.0 + + + + create-from-project + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${java.version} + + + + + + diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/package-info.java new file mode 100644 index 0000000..ba422f3 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/package-info.java @@ -0,0 +1,4 @@ +/** + * 外部接口适配器层;当需要调用外部接口时,则创建出这一层,并定义接口,之后由基础设施层的 adapter 层具体实现 + */ +package edu.whut.domain.xxx.adapter; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/port/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/port/package-info.java new file mode 100644 index 0000000..8f3e273 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/port/package-info.java @@ -0,0 +1,4 @@ +/** + * 外部接口适配器层;当需要调用外部接口时,则创建出这一层,并定义接口,之后由基础设施层的 adapter 层具体实现 + */ +package edu.whut.domain.xxx.adapter.port; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/repository/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/repository/package-info.java new file mode 100644 index 0000000..4fc83a4 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/adapter/repository/package-info.java @@ -0,0 +1,5 @@ +/** + * 仓储服务 + * 1. 定义仓储接口,之后由基础设施层做具体实现 + */ +package edu.whut.domain.xxx.adapter.repository; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/aggregate/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/aggregate/package-info.java new file mode 100644 index 0000000..d2ee6fb --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/aggregate/package-info.java @@ -0,0 +1,7 @@ +/** + * 聚合对象; + * 1. 聚合实体和值对象 + * 2. 聚合是聚合的对象,和提供基础处理对象的方法。但不建议在聚合中引入仓储和接口来做过大的逻辑。而这些复杂的操作应该放到service中处理 + * 3. 对象名称 XxxAggregate + */ +package edu.whut.domain.xxx.model.aggregate; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/entity/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/entity/package-info.java new file mode 100644 index 0000000..a7a8ce5 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/entity/package-info.java @@ -0,0 +1,7 @@ +/** + * 实体对象; + * 1. 一般和数据库持久化对象1v1的关系,但因各自开发系统的不同,也有1vn的可能。 + * 2. 如果是老系统改造,那么旧的库表冗余了太多的字段,可能会有nv1的情况 + * 3. 对象名称 XxxEntity + */ +package edu.whut.domain.xxx.model.entity; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/valobj/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/valobj/package-info.java new file mode 100644 index 0000000..f34a181 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/model/valobj/package-info.java @@ -0,0 +1,6 @@ +/** + * 值对象; + * 1. 用于描述对象属性的值,如一个库表中有json后者一个字段多个属性信息的枚举对象 + * 2. 对象名称如;XxxVO + */ +package edu.whut.domain.xxx.model.valobj; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/xxx/service/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/service/package-info.java new file mode 100644 index 0000000..a82b91f --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/xxx/service/package-info.java @@ -0,0 +1 @@ +package edu.whut.domain.xxx.service; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/yyy/adapter/repository/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/adapter/repository/package-info.java new file mode 100644 index 0000000..e69de29 diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/aggregate/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/aggregate/package-info.java new file mode 100644 index 0000000..a338f2b --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/aggregate/package-info.java @@ -0,0 +1,7 @@ +/** + * 聚合对象; + * 1. 聚合实体和值对象 + * 2. 聚合是聚合的对象,和提供基础处理对象的方法。但不建议在聚合中引入仓储和接口来做过大的逻辑。而这些复杂的操作应该放到service中处理 + * 3. 对象名称 XxxAggregate + */ +package edu.whut.domain.yyy.model.aggregate; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/entity/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/entity/package-info.java new file mode 100644 index 0000000..1d9a9d6 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/entity/package-info.java @@ -0,0 +1,7 @@ +/** + * 实体对象; + * 1. 一般和数据库持久化对象1v1的关系,但因各自开发系统的不同,也有1vn的可能。 + * 2. 如果是老系统改造,那么旧的库表冗余了太多的字段,可能会有nv1的情况 + * 3. 对象名称 XxxEntity + */ +package edu.whut.domain.yyy.model.entity; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/valobj/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/valobj/package-info.java new file mode 100644 index 0000000..ecb5669 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/model/valobj/package-info.java @@ -0,0 +1,6 @@ +/** + * 值对象; + * 1. 用于描述对象属性的值,如一个库表中有json后者一个字段多个属性信息的枚举对象 + * 2. 对象名称如;XxxVO + */ +package edu.whut.domain.yyy.model.valobj; \ No newline at end of file diff --git a/pay-mall-domain/src/main/java/edu/whut/domain/yyy/service/package-info.java b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/service/package-info.java new file mode 100644 index 0000000..ab79c10 --- /dev/null +++ b/pay-mall-domain/src/main/java/edu/whut/domain/yyy/service/package-info.java @@ -0,0 +1 @@ +package edu.whut.domain.yyy.service; \ No newline at end of file diff --git a/pay-mall-infrastructure/pom.xml b/pay-mall-infrastructure/pom.xml new file mode 100644 index 0000000..a6cbe6d --- /dev/null +++ b/pay-mall-infrastructure/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-infrastructure + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + org.projectlombok + lombok + + + + edu.whut + pay-mall-domain + + + + + pay-mall-infrastructure + + + org.apache.maven.plugins + maven-archetype-plugin + 3.2.0 + + + + create-from-project + + + + + + + + diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/port/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/port/package-info.java new file mode 100644 index 0000000..429f503 --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/port/package-info.java @@ -0,0 +1,4 @@ +/** + * 实现对外部的api调用,类的名称为 XxxPort 接口定义在 domain 中 + */ +package edu.whut.infrastructure.adapter.port; \ No newline at end of file diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/package-info.java new file mode 100644 index 0000000..14b6868 --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/adapter/repository/package-info.java @@ -0,0 +1,4 @@ +/** + * 仓储实现;用于实现 domain 中定义的仓储接口,如;IXxxRepository 在 Repository 中调用服务 + */ +package edu.whut.infrastructure.adapter.repository; \ No newline at end of file diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/package-info.java new file mode 100644 index 0000000..8e44e5b --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/package-info.java @@ -0,0 +1,4 @@ +/** + * DAO 接口;IXxxDao + */ +package edu.whut.infrastructure.dao; \ No newline at end of file diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/po/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/po/package-info.java new file mode 100644 index 0000000..ddeef77 --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/dao/po/package-info.java @@ -0,0 +1,4 @@ +/** + * 持久化对象;XxxPO 最后的 PO 是大写,UserPO + */ +package edu.whut.infrastructure.dao.po; \ No newline at end of file diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/dto/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/dto/package-info.java new file mode 100644 index 0000000..e69de29 diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/package-info.java new file mode 100644 index 0000000..15d30fd --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/gateway/package-info.java @@ -0,0 +1,4 @@ +/** + * 定义http、rpc接口,调用外部。在 adapter 中调用这部分内容。 + */ +package edu.whut.infrastructure.gateway; \ No newline at end of file diff --git a/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/redis/package-info.java b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/redis/package-info.java new file mode 100644 index 0000000..582d29d --- /dev/null +++ b/pay-mall-infrastructure/src/main/java/edu/whut/infrastructure/redis/package-info.java @@ -0,0 +1,4 @@ +/** + * 提供redis链接配置 + */ +package edu.whut.infrastructure.redis; \ No newline at end of file diff --git a/pay-mall-trigger/pom.xml b/pay-mall-trigger/pom.xml new file mode 100644 index 0000000..0862007 --- /dev/null +++ b/pay-mall-trigger/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-trigger + + + + org.springframework.boot + spring-boot-starter-web + + + com.alibaba + fastjson + + + org.springframework + spring-tx + + + org.apache.commons + commons-lang3 + + + + + edu.whut + pay-mall-api + + + edu.whut + pay-mall-types + + + edu.whut + pay-mall-domain + + + + + pay-mall-trigger + + + org.apache.maven.plugins + maven-archetype-plugin + 3.2.0 + + + + create-from-project + + + + + + + + diff --git a/pay-mall-trigger/src/main/java/edu/whut/trigger/http/WeixinPortalController.java b/pay-mall-trigger/src/main/java/edu/whut/trigger/http/WeixinPortalController.java new file mode 100644 index 0000000..e72cc43 --- /dev/null +++ b/pay-mall-trigger/src/main/java/edu/whut/trigger/http/WeixinPortalController.java @@ -0,0 +1,76 @@ +package edu.whut.trigger.http; +import edu.whut.types.weixin.MessageTextEntity; +import edu.whut.types.weixin.SignatureUtil; +import edu.whut.types.weixin.XmlUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; + +/** + * https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index 平台地址 + */ +@Slf4j +@RestController() +@CrossOrigin("*") +@RequestMapping("/api/v1/weixin/portal/") +public class WeixinPortalController { + + @Value("${weixin.config.originalid}") + private String originalid; + @Value("${weixin.config.token}") + private String token; + + @GetMapping(value = "receive", produces = "text/plain;charset=utf-8") + public String validate(@RequestParam(value = "signature", required = false) String signature, + @RequestParam(value = "timestamp", required = false) String timestamp, + @RequestParam(value = "nonce", required = false) String nonce, + @RequestParam(value = "echostr", required = false) String echostr) { + try { + log.info("微信公众号验签信息开始 [{}, {}, {}, {}]", signature, timestamp, nonce, echostr); + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("请求参数非法,请核实!"); + } + boolean check = SignatureUtil.check(token, signature, timestamp, nonce); + log.info("微信公众号验签信息完成 check:{}", check); + if (!check) { + return null; + } + return echostr; + } catch (Exception e) { + log.error("微信公众号验签信息失败 [{}, {}, {}, {}]", signature, timestamp, nonce, echostr, e); + return null; + } + } + + @PostMapping(value = "receive", produces = "application/xml; charset=UTF-8") + public String post(@RequestBody String requestBody, + @RequestParam("signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce, + @RequestParam("openid") String openid, + @RequestParam(name = "encrypt_type", required = false) String encType, + @RequestParam(name = "msg_signature", required = false) String msgSignature) { + try { + log.info("接收微信公众号信息请求{}开始 {}", openid, requestBody); + // 消息转换 + MessageTextEntity message = XmlUtil.xmlToBean(requestBody, MessageTextEntity.class); + return buildMessageTextEntity(openid, "你好," + message.getContent()); + } catch (Exception e) { + log.error("接收微信公众号信息请求{}失败 {}", openid, requestBody, e); + return ""; + } + } + + private String buildMessageTextEntity(String openid, String content) { + MessageTextEntity res = new MessageTextEntity(); + // 公众号分配的ID + res.setFromUserName(originalid); + res.setToUserName(openid); + res.setCreateTime(String.valueOf(System.currentTimeMillis() / 1000L)); + res.setMsgType("text"); + res.setContent(content); + return XmlUtil.beanToXml(res); + } + +} diff --git a/pay-mall-trigger/src/main/java/edu/whut/trigger/http/package-info.java b/pay-mall-trigger/src/main/java/edu/whut/trigger/http/package-info.java new file mode 100644 index 0000000..40cb8a7 --- /dev/null +++ b/pay-mall-trigger/src/main/java/edu/whut/trigger/http/package-info.java @@ -0,0 +1,4 @@ +/** + * HTTP 接口服务 + */ +package edu.whut.trigger.http; \ No newline at end of file diff --git a/pay-mall-trigger/src/main/java/edu/whut/trigger/job/package-info.java b/pay-mall-trigger/src/main/java/edu/whut/trigger/job/package-info.java new file mode 100644 index 0000000..ac4b97b --- /dev/null +++ b/pay-mall-trigger/src/main/java/edu/whut/trigger/job/package-info.java @@ -0,0 +1,4 @@ +/** + * 任务服务,可以选择使用 Spring 默认提供的 Schedule https://bugstack.cn/md/road-map/quartz.html + */ +package edu.whut.trigger.job; \ No newline at end of file diff --git a/pay-mall-trigger/src/main/java/edu/whut/trigger/listener/package-info.java b/pay-mall-trigger/src/main/java/edu/whut/trigger/listener/package-info.java new file mode 100644 index 0000000..b23264d --- /dev/null +++ b/pay-mall-trigger/src/main/java/edu/whut/trigger/listener/package-info.java @@ -0,0 +1,5 @@ +/** + * 监听服务;在单体服务中,解耦流程。类似MQ的使用,如Spring的Event,Guava的事件总线都可以。如果使用了 Redis 那么也可以有发布/订阅使用。 + * Guava:https://bugstack.cn/md/road-map/guava.html + */ +package edu.whut.trigger.listener; \ No newline at end of file diff --git a/pay-mall-types/pom.xml b/pay-mall-types/pom.xml new file mode 100644 index 0000000..bf1f4d5 --- /dev/null +++ b/pay-mall-types/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + + + pay-mall-types + + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + + + com.thoughtworks.xstream + xstream + + + dom4j + dom4j + + + org.apache.commons + commons-lang3 + + + + + pay-mall-types + + + org.apache.maven.plugins + maven-archetype-plugin + 3.2.0 + + + + create-from-project + + + + + + + + diff --git a/pay-mall-types/src/main/java/edu/whut/types/common/Constants.java b/pay-mall-types/src/main/java/edu/whut/types/common/Constants.java new file mode 100644 index 0000000..381d140 --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/common/Constants.java @@ -0,0 +1,7 @@ +package edu.whut.types.common; + +public class Constants { + + public final static String SPLIT = ","; + +} diff --git a/pay-mall-types/src/main/java/edu/whut/types/enums/ResponseCode.java b/pay-mall-types/src/main/java/edu/whut/types/enums/ResponseCode.java new file mode 100644 index 0000000..8189263 --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/enums/ResponseCode.java @@ -0,0 +1,20 @@ +package edu.whut.types.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public enum ResponseCode { + + SUCCESS("0000", "成功"), + UN_ERROR("0001", "未知失败"), + ILLEGAL_PARAMETER("0002", "非法参数"), + ; + + private String code; + private String info; + +} diff --git a/pay-mall-types/src/main/java/edu/whut/types/exception/AppException.java b/pay-mall-types/src/main/java/edu/whut/types/exception/AppException.java new file mode 100644 index 0000000..d06854e --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/exception/AppException.java @@ -0,0 +1,46 @@ +package edu.whut.types.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class AppException extends RuntimeException { + + private static final long serialVersionUID = 5317680961212299217L; + + /** 异常码 */ + private String code; + + /** 异常信息 */ + private String info; + + public AppException(String code) { + this.code = code; + } + + public AppException(String code, Throwable cause) { + this.code = code; + super.initCause(cause); + } + + public AppException(String code, String message) { + this.code = code; + this.info = message; + } + + public AppException(String code, String message, Throwable cause) { + this.code = code; + this.info = message; + super.initCause(cause); + } + + @Override + public String toString() { + return "edu.whut.x.api.types.exception.XApiException{" + + "code='" + code + '\'' + + ", info='" + info + '\'' + + '}'; + } + +} diff --git a/pay-mall-types/src/main/java/edu/whut/types/weixin/MessageTextEntity.java b/pay-mall-types/src/main/java/edu/whut/types/weixin/MessageTextEntity.java new file mode 100644 index 0000000..75d9a44 --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/weixin/MessageTextEntity.java @@ -0,0 +1,118 @@ +package edu.whut.types.weixin; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("xml") +public class MessageTextEntity { + + @XStreamAlias("ToUserName") + private String toUserName; + + @XStreamAlias("FromUserName") + private String fromUserName; + + @XStreamAlias("CreateTime") + private String createTime; + + @XStreamAlias("MsgType") + private String msgType; + + @XStreamAlias("Event") + private String event; + + @XStreamAlias("EventKey") + private String eventKey; + + @XStreamAlias("MsgId") + private String msgId; + + @XStreamAlias("Status") + private String status; + + @XStreamAlias("Ticket") + private String ticket; + + @XStreamAlias("Content") + private String content; + + // Getters and Setters + public String getToUserName() { + return toUserName; + } + + public void setToUserName(String toUserName) { + this.toUserName = toUserName; + } + + public String getFromUserName() { + return fromUserName; + } + + public void setFromUserName(String fromUserName) { + this.fromUserName = fromUserName; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getMsgType() { + return msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } + + public String getMsgId() { + return msgId; + } + + public void setMsgId(String msgId) { + this.msgId = msgId; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getEventKey() { + return eventKey; + } + + public void setEventKey(String eventKey) { + this.eventKey = eventKey; + } + + public String getTicket() { + return ticket; + } + + public void setTicket(String ticket) { + this.ticket = ticket; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} \ No newline at end of file diff --git a/pay-mall-types/src/main/java/edu/whut/types/weixin/SignatureUtil.java b/pay-mall-types/src/main/java/edu/whut/types/weixin/SignatureUtil.java new file mode 100644 index 0000000..5ba7698 --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/weixin/SignatureUtil.java @@ -0,0 +1,68 @@ +package edu.whut.types.weixin; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class SignatureUtil { + /** + * 验证签名 + */ + public static boolean check(String token, String signature, String timestamp, String nonce) { + String[] arr = new String[]{token, timestamp, nonce}; + // 将token、timestamp、nonce三个参数进行字典序排序 + sort(arr); + StringBuilder content = new StringBuilder(); + for (String s : arr) { + content.append(s); + } + MessageDigest md; + String tmpStr = null; + try { + md = MessageDigest.getInstance("SHA-1"); + // 将三个参数字符串拼接成一个字符串进行sha1加密 + byte[] digest = md.digest(content.toString().getBytes()); + tmpStr = byteToStr(digest); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 + return tmpStr != null && tmpStr.equals(signature.toUpperCase()); + } + + /** + * 将字节数组转换为十六进制字符串 + */ + private static String byteToStr(byte[] byteArray) { + StringBuilder strDigest = new StringBuilder(); + for (byte b : byteArray) { + strDigest.append(byteToHexStr(b)); + } + return strDigest.toString(); + } + + /** + * 将字节转换为十六进制字符串 + */ + private static String byteToHexStr(byte mByte) { + char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + char[] tempArr = new char[2]; + tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; + tempArr[1] = Digit[mByte & 0X0F]; + return new String(tempArr); + } + + /** + * 进行字典排序 + */ + private static void sort(String[] str) { + for (int i = 0; i < str.length - 1; i++) { + for (int j = i + 1; j < str.length; j++) { + if (str[j].compareTo(str[i]) < 0) { + String temp = str[i]; + str[i] = str[j]; + str[j] = temp; + } + } + } + } +} diff --git a/pay-mall-types/src/main/java/edu/whut/types/weixin/XmlUtil.java b/pay-mall-types/src/main/java/edu/whut/types/weixin/XmlUtil.java new file mode 100644 index 0000000..8a405ae --- /dev/null +++ b/pay-mall-types/src/main/java/edu/whut/types/weixin/XmlUtil.java @@ -0,0 +1,151 @@ +package edu.whut.types.weixin; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.core.util.QuickWriter; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.xml.DomDriver; +import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; +import com.thoughtworks.xstream.io.xml.XppDriver; +import com.thoughtworks.xstream.security.AnyTypePermission; +import org.apache.commons.lang3.StringUtils; +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +import javax.servlet.http.HttpServletRequest; +import java.io.InputStream; +import java.io.Writer; +import java.util.*; + +public class XmlUtil { + + /** + * 解析微信发来的请求(xml) + */ + @SuppressWarnings("unchecked") + public static Map xmlToMap(HttpServletRequest request) throws Exception { + // 从request中取得输入流 + try (InputStream inputStream = request.getInputStream()) { + // 将解析结果存储在HashMap中 + Map map = new HashMap<>(); + // 读取输入流 + SAXReader reader = new SAXReader(); + // 得到xml文档 + Document document = reader.read(inputStream); + // 得到xml根元素 + Element root = document.getRootElement(); + // 得到根元素的所有子节点 + List elementList = root.elements(); + // 遍历所有子节点 + for (Element e : elementList) + map.put(e.getName(), e.getText()); + // 释放资源 + inputStream.close(); + return map; + } + } + + /** + * 将map转化成xml响应给微信服务器 + */ + static String mapToXML(Map map) { + StringBuffer sb = new StringBuffer(); + sb.append(""); + mapToXML2(map, sb); + sb.append(""); + try { + return sb.toString(); + } catch (Exception e) { + return null; + } + } + + private static void mapToXML2(Map map, StringBuffer sb) { + Set set = map.keySet(); + for (Object o : set) { + String key = (String) o; + Object value = map.get(key); + if (null == value) + value = ""; + if (value.getClass().getName().equals("java.util.ArrayList")) { + ArrayList list = (ArrayList) map.get(key); + sb.append("<").append(key).append(">"); + for (Object o1 : list) { + HashMap hm = (HashMap) o1; + mapToXML2(hm, sb); + } + sb.append(""); + + } else { + if (value instanceof HashMap) { + sb.append("<").append(key).append(">"); + mapToXML2((HashMap) value, sb); + sb.append(""); + } else { + sb.append("<").append(key).append(">"); + } + + } + + } + } + + public static XStream getMyXStream() { + return new XStream(new XppDriver() { + @Override + public HierarchicalStreamWriter createWriter(Writer out) { + return new PrettyPrintWriter(out) { + // 对所有xml节点都增加CDATA标记 + boolean cdata = true; + + @Override + public void startNode(String name, Class clazz) { + super.startNode(name, clazz); + } + + @Override + protected void writeText(QuickWriter writer, String text) { + if (cdata && !StringUtils.isNumeric(text)) { + writer.write(""); + } else { + writer.write(text); + } + } + }; + } + }); + } + + /** + * bean转成微信的xml消息格式 + */ + public static String beanToXml(Object object) { + XStream xStream = getMyXStream(); + xStream.alias("xml", object.getClass()); + xStream.processAnnotations(object.getClass()); + String xml = xStream.toXML(object); + if (!StringUtils.isEmpty(xml)) { + return xml; + } else { + return null; + } + } + + /** + * xml转成bean泛型方法 + */ + public static T xmlToBean(String resultXml, Class clazz) { + // XStream对象设置默认安全防护,同时设置允许的类 + XStream stream = new XStream(new DomDriver()); + stream.addPermission(AnyTypePermission.ANY); + XStream.setupDefaultSecurity(stream); + stream.allowTypes(new Class[]{clazz}); + stream.processAnnotations(new Class[]{clazz}); + stream.setMode(XStream.NO_REFERENCES); + stream.alias("xml", clazz); + return (T) stream.fromXML(resultXml); + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..93dc316 --- /dev/null +++ b/pom.xml @@ -0,0 +1,203 @@ + + + 4.0.0 + + edu.whut + pay-mall + 1.0-SNAPSHOT + pom + + + pay-mall-api + pay-mall-app + pay-mall-domain + pay-mall-trigger + pay-mall-infrastructure + pay-mall-types + + + + + nexus-aliyun + nexus-aliyun + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + + 1.8 + UTF-8 + 8 + 8 + UTF-8 + + + + + xiaofuge + 184172133@qq.com + fuzhengwei + https://github.com/fuzhengwei + + + + + + Apache License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0 + + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.12 + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.4 + + + + mysql + mysql-connector-java + 8.0.22 + + + com.alibaba + fastjson + 2.0.28 + + + org.apache.commons + commons-lang3 + 3.9 + + + com.google.guava + guava + 32.1.3-jre + + + dom4j + dom4j + 1.6.1 + + + com.thoughtworks.xstream + xstream + 1.4.10 + + + io.jsonwebtoken + jjwt + 0.9.1 + + + com.auth0 + java-jwt + 4.4.0 + + + commons-codec + commons-codec + 1.15 + + + + + edu.whut + pay-mall-api + 1.0-SNAPSHOT + + + edu.whut + pay-mall-domain + 1.0-SNAPSHOT + + + edu.whut + pay-mall-infrastructure + 1.0-SNAPSHOT + + + edu.whut + pay-mall-types + 1.0-SNAPSHOT + + + edu.whut + pay-mall-trigger + 1.0-SNAPSHOT + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + UTF-8 + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + + + + + + dev + + true + + + -Xms1G -Xmx1G -server -XX:MaxPermSize=256M -Xss256K -Dspring.profiles.active=test -XX:+DisableExplicitGC -XX:+UseG1GC -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs/pay-mall-boot -Xloggc:/export/Logs/pay-mall-boot/gc-pay-mall-boot.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps + dev + + + + test + + -Xms1G -Xmx1G -server -XX:MaxPermSize=256M -Xss256K -Dspring.profiles.active=test -XX:+DisableExplicitGC -XX:+UseG1GC -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs/pay-mall-boot -Xloggc:/export/Logs/pay-mall-boot/gc-pay-mall-boot.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps + test + + + + prod + + -Xms6G -Xmx6G -server -XX:MaxPermSize=256M -Xss256K -Dspring.profiles.active=release -XX:+DisableExplicitGC -XX:+UseG1GC -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs/fq-mall-activity-app -Xloggc:/export/Logs/pay-mall-boot/gc-pay-mall-boot.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps + prod + + + + +