QAs = QA.getQAs(getQAListPort);
+ return QAs;
+ }
+}
diff --git a/qa-service/qa-service-application/src/main/java/com/example/application/service/UpdateQAService.java b/qa-service/qa-service-application/src/main/java/com/example/application/service/UpdateQAService.java
new file mode 100644
index 0000000..d908f68
--- /dev/null
+++ b/qa-service/qa-service-application/src/main/java/com/example/application/service/UpdateQAService.java
@@ -0,0 +1,26 @@
+package com.example.application.service;
+
+import com.example.application.command.UpdateQACommand;
+import com.example.application.port.in.UpdateQAUseCase;
+import com.example.qa.service.domain.QA;
+import com.example.qa.service.domain.port.UpdateQAPort;
+import com.example.qa.service.domain.valueobject.*;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+/**
+ * @author lizishan
+ */
+@Service
+public class UpdateQAService implements UpdateQAUseCase {
+ @Resource
+ private UpdateQAPort updateQAPort;
+
+ @Override
+ public QA updateQA(UpdateQACommand command) {
+ QA QA = new QA(
+ new QAId(command.id()),
+ new Question(command.question()),
+ new Answer(command.answer()));
+ return updateQAPort.updateQA(QA);
+ }
+}
diff --git a/qa-service/qa-service-bootstrap/src/main/resources/application.properties b/qa-service/qa-service-bootstrap/src/main/resources/application.properties
new file mode 100644
index 0000000..e073491
--- /dev/null
+++ b/qa-service/qa-service-bootstrap/src/main/resources/application.properties
@@ -0,0 +1,27 @@
+server.port=28080
+
+spring.application.name=user-service
+
+
+# Nacos认证信息
+spring.cloud.nacos.discovery.username=nacos
+spring.cloud.nacos.discovery.password=nacos
+# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
+spring.cloud.nacos.discovery.server-addr=192.168.168.128:8848
+# 注册到 nacos 的指定 namespace,默认为 public
+spring.cloud.nacos.discovery.namespace=public
+
+# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
+# Nacos认证信息
+spring.cloud.nacos.config.username=nacos
+spring.cloud.nacos.config.password=nacos
+spring.cloud.nacos.config.contextPath=/nacos
+# 设置配置中心服务端地址
+spring.cloud.nacos.config.server-addr=192.168.168.128::8848
+# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
+# spring.cloud.nacos.config.namespace=
+spring.config.import=nacos:${spring.application.name}.properties?refresh=true
+
+
+
+
diff --git a/qa-service/qa-service-common/src/main/java/com/example/qa/service/common/IdWorker.java b/qa-service/qa-service-common/src/main/java/com/example/qa/service/common/IdWorker.java
new file mode 100644
index 0000000..ac96e23
--- /dev/null
+++ b/qa-service/qa-service-common/src/main/java/com/example/qa/service/common/IdWorker.java
@@ -0,0 +1,199 @@
+package com.example.qa.service.common;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+
+/**
+ * @author wuyunbin
+ * 名称:IdWorker.java
+ * 描述:分布式自增长ID
+ *
+ * Twitter的 Snowflake JAVA实现方案
+ *
+ * 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
+ * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
+ * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
+ * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
+ * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
+ * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
+ * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
+ *
+ * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
+ * @author Polim
+ */
+public class IdWorker {
+ /**
+ * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+ */
+ private final static long TWEPOCH = 1288834974657L;
+
+ /**
+ * 机器标识位数
+ */
+ private final static long WORKER_ID_BITS = 5L;
+
+ /**
+ * 数据中心标识位数
+ */
+ private final static long DATA_CENTER_ID_BITS = 5L;
+
+ /**
+ * 机器ID最大值
+ */
+ private final static long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS);
+
+ /**
+ * 数据中心ID最大值
+ */
+ private final static long MAX_DATACENTER_ID = -1L ^ (-1L << DATA_CENTER_ID_BITS);
+
+ /**
+ * 毫秒内自增位
+ */
+ private final static long SEQUENCE_BITS = 12L;
+
+ /**
+ * 机器ID偏左移12位
+ */
+ private final static long WORKER_ID_SHIFT = SEQUENCE_BITS;
+
+ /**
+ * 数据中心ID左移17位
+ */
+ private final static long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
+
+ /**
+ * 时间毫秒左移22位
+ */
+ private final static long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
+
+ private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
+
+ /**
+ * 上次生产id时间戳
+ */
+ private static long lastTimestamp = -1L;
+
+ /**
+ * 0,并发控制
+ */
+ private long sequence = 0L;
+
+ private final long workerId;
+
+ /**
+ * 数据标识id部分
+ */
+ private final long datacenterId;
+
+ public IdWorker() {
+ this.datacenterId = getDatacenterId();
+ this.workerId = getMaxWorkerId(datacenterId);
+ }
+
+ /**
+ * @param workerId 工作机器ID
+ * @param datacenterId 序列号
+ */
+ public IdWorker(long workerId, long datacenterId) {
+ if (workerId > MAX_WORKER_ID || workerId < 0) {
+ throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID));
+ }
+ if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
+ throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", MAX_DATACENTER_ID));
+ }
+ this.workerId = workerId;
+ this.datacenterId = datacenterId;
+ }
+
+ /**
+ * 获取下一个ID
+ *
+ * @return
+ */
+ public synchronized long nextId() {
+ long timestamp = timeGen();
+ if (timestamp < lastTimestamp) {
+ throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+ }
+
+ if (lastTimestamp == timestamp) {
+ // 当前毫秒内,则+1
+ sequence = (sequence + 1) & SEQUENCE_MASK;
+ if (sequence == 0) {
+ // 当前毫秒内计数满了,则等待下一秒
+ timestamp = tilNextMillis(lastTimestamp);
+ }
+ } else {
+ sequence = 0L;
+ }
+ lastTimestamp = timestamp;
+ // ID偏移组合生成最终的ID,并返回ID
+
+ return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT)
+ | (datacenterId << DATACENTER_ID_SHIFT)
+ | (workerId << WORKER_ID_SHIFT) | sequence;
+ }
+
+ private long tilNextMillis(final long lastTimestamp) {
+ long timestamp = this.timeGen();
+ while (timestamp <= lastTimestamp) {
+ timestamp = this.timeGen();
+ }
+ return timestamp;
+ }
+
+ private long timeGen() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ *
+ * 获取 MAX_WORKER_ID
+ *
+ */
+ protected static long getMaxWorkerId(long datacenterId) {
+ StringBuilder mpid = new StringBuilder();
+ mpid.append(datacenterId);
+ String name = ManagementFactory.getRuntimeMXBean().getName();
+ if (!name.isEmpty()) {
+ /*
+ * GET jvmPid
+ */
+ mpid.append(name.split("@")[0]);
+ }
+ /*
+ * MAC + PID 的 hashcode 获取16个低位
+ */
+ return (mpid.toString().hashCode() & 0xffff) % (IdWorker.MAX_WORKER_ID + 1);
+ }
+
+ /**
+ *
+ * 数据标识id部分
+ *
+ */
+ protected static long getDatacenterId() {
+ long id = 0L;
+ try {
+ InetAddress ip = InetAddress.getLocalHost();
+ NetworkInterface network = NetworkInterface.getByInetAddress(ip);
+ if (network == null) {
+ id = 1L;
+ } else {
+ byte[] mac = network.getHardwareAddress();
+ id = ((0x000000FF & (long) mac[mac.length - 1])
+ | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
+ id = id % (IdWorker.MAX_DATACENTER_ID + 1);
+ }
+ } catch (Exception e) {
+ System.out.println(" getDatacenterId: " + e.getMessage());
+ }
+ return id;
+ }
+
+
+
+
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/QA.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/QA.java
new file mode 100644
index 0000000..c40b3bb
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/QA.java
@@ -0,0 +1,48 @@
+package com.example.qa.service.domain;
+
+import com.example.qa.service.common.IdWorker;
+import com.example.qa.service.domain.port.GetQAListPort;
+import com.example.qa.service.domain.valueobject.Answer;
+import com.example.qa.service.domain.valueobject.QAId;
+import com.example.qa.service.domain.valueobject.Question;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.List;
+
+@Setter
+@Getter
+@ToString
+/**
+ * @author yangwenkai
+ * QA类
+ */
+public class QA {
+ private QAId id;
+ private Question question;
+ private Answer answer;
+
+ public QA() {
+ }
+
+ public QA(QAId id, Question question, Answer answer) {
+ this.id = id;
+ this.question = question;
+ this.answer = answer;
+ }
+
+ public QA(Question question, Answer answer) {
+ this.id= genId();
+ this.question = question;
+ this.answer = answer;
+ }
+
+ public static List getQAs(GetQAListPort getQAListPort){
+ return getQAListPort.getQAs();
+ }
+
+ public QAId genId(){
+ return new QAId(new IdWorker().nextId());
+ }
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/CreateQAPort.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/CreateQAPort.java
new file mode 100644
index 0000000..aeb293a
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/CreateQAPort.java
@@ -0,0 +1,11 @@
+package com.example.qa.service.domain.port;
+
+import com.example.qa.service.domain.QA;
+
+/**
+ * @author yangwenkai
+ * 创建QA的端口
+ */
+public interface CreateQAPort {
+ QA createQA(QA qa);
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/DeleteQAPort.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/DeleteQAPort.java
new file mode 100644
index 0000000..2ea8e47
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/DeleteQAPort.java
@@ -0,0 +1,8 @@
+package com.example.qa.service.domain.port;
+
+/**
+ * @author qiuyujie
+ */
+public interface DeleteQAPort {
+ void deleteQA(Long id);
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAByIdPort.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAByIdPort.java
new file mode 100644
index 0000000..fdc3b92
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAByIdPort.java
@@ -0,0 +1,10 @@
+package com.example.qa.service.domain.port;
+
+import com.example.qa.service.domain.QA;
+
+/**
+ * @author dengli
+ */
+public interface GetQAByIdPort {
+ QA getQAById(long id);
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAListPort.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAListPort.java
new file mode 100644
index 0000000..3fc891d
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/GetQAListPort.java
@@ -0,0 +1,11 @@
+package com.example.qa.service.domain.port;
+
+import com.example.qa.service.domain.QA;
+
+import java.util.List;
+/**
+ * @author wangqingqing
+ */
+public interface GetQAListPort {
+ List getQAs();
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/UpdateQAPort.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/UpdateQAPort.java
new file mode 100644
index 0000000..5713b79
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/port/UpdateQAPort.java
@@ -0,0 +1,9 @@
+package com.example.qa.service.domain.port;
+
+import com.example.qa.service.domain.QA;
+/**
+ * @author lizishan
+ */
+public interface UpdateQAPort {
+ QA updateQA(QA qa);
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Answer.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Answer.java
new file mode 100644
index 0000000..8a34b3c
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Answer.java
@@ -0,0 +1,10 @@
+package com.example.qa.service.domain.valueobject;
+
+/**
+ * @author qiuyujie
+ */
+public record Answer(String answer) {
+ public String getValue() {
+ return answer;
+ }
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/QAId.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/QAId.java
new file mode 100644
index 0000000..a423600
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/QAId.java
@@ -0,0 +1,10 @@
+package com.example.qa.service.domain.valueobject;
+
+/**
+ * @author dengli
+ */
+public record QAId(long id) {
+ public long getValue() {
+ return id;
+ }
+}
diff --git a/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Question.java b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Question.java
new file mode 100644
index 0000000..773a8f9
--- /dev/null
+++ b/qa-service/qa-service-domain/src/main/java/com/example/qa/service/domain/valueobject/Question.java
@@ -0,0 +1,9 @@
+package com.example.qa.service.domain.valueobject;
+/**
+ * @author wangqingqing
+ */
+public record Question(String question) {
+ public String getValue() {
+ return question;
+ }
+}
--
Gitee
From 1d805cee0913e3c0b73de462ba03a9ebecc02f84 Mon Sep 17 00:00:00 2001
From: Xiaya_kevin <1415130181@qq.com>
Date: Wed, 10 Sep 2025 17:36:41 +0800
Subject: [PATCH 2/2] =?UTF-8?q?fix(qa-service-bootstrap):=20AI=E8=AF=B4?=
=?UTF-8?q?=E8=BF=99=E4=B8=AA=E5=8F=8C=E5=86=92=E5=8F=B7=E8=A6=81=E5=8E=BB?=
=?UTF-8?q?=E6=8E=89=E4=B8=80=E4=B8=AA=E5=86=92=E5=8F=B7=EF=BC=9B=E6=8A=8A?=
=?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=BC=8F=E6=8E=89=E7=9A=84user=E6=94=B9?=
=?UTF-8?q?=E5=9B=9E=E6=9D=A5=E4=BA=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/compiler.xml | 8 ------
.idea/encodings.xml | 4 ---
.idea/gradle.xml | 6 -----
.idea/misc.xml | 6 -----
qa-service/pom.xml | 2 +-
.../src/main/resources/application.properties | 27 -------------------
6 files changed, 1 insertion(+), 52 deletions(-)
delete mode 100644 .idea/compiler.xml
delete mode 100644 .idea/encodings.xml
delete mode 100644 .idea/gradle.xml
delete mode 100644 .idea/misc.xml
delete mode 100644 qa-service/qa-service-bootstrap/src/main/resources/application.properties
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index a1757ae..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index da0415a..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index c4be5fb..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 7280f00..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/qa-service/pom.xml b/qa-service/pom.xml
index 28b1393..7ba8bd5 100644
--- a/qa-service/pom.xml
+++ b/qa-service/pom.xml
@@ -79,7 +79,7 @@
spring-boot-maven-plugin
${spring-boot.version}
- com.example.user-service.user-serviceApplication
+ com.example.qa-service.qa-serviceApplication
true
diff --git a/qa-service/qa-service-bootstrap/src/main/resources/application.properties b/qa-service/qa-service-bootstrap/src/main/resources/application.properties
deleted file mode 100644
index e073491..0000000
--- a/qa-service/qa-service-bootstrap/src/main/resources/application.properties
+++ /dev/null
@@ -1,27 +0,0 @@
-server.port=28080
-
-spring.application.name=user-service
-
-
-# Nacos认证信息
-spring.cloud.nacos.discovery.username=nacos
-spring.cloud.nacos.discovery.password=nacos
-# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
-spring.cloud.nacos.discovery.server-addr=192.168.168.128:8848
-# 注册到 nacos 的指定 namespace,默认为 public
-spring.cloud.nacos.discovery.namespace=public
-
-# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
-# Nacos认证信息
-spring.cloud.nacos.config.username=nacos
-spring.cloud.nacos.config.password=nacos
-spring.cloud.nacos.config.contextPath=/nacos
-# 设置配置中心服务端地址
-spring.cloud.nacos.config.server-addr=192.168.168.128::8848
-# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
-# spring.cloud.nacos.config.namespace=
-spring.config.import=nacos:${spring.application.name}.properties?refresh=true
-
-
-
-
--
Gitee