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 0000000000000000000000000000000000000000..d908f68854c34ca7f754bb93f0b71e72dabcd597
--- /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-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 0000000000000000000000000000000000000000..ac96e23534a47e45c5d6fb06dbe2a4b3838df792
--- /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 0000000000000000000000000000000000000000..c40b3bb8b50adb5ed894a91f9236691c5fa3da7b
--- /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 0000000000000000000000000000000000000000..aeb293a24a7b7f71effce1863e805726e786cf58
--- /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 0000000000000000000000000000000000000000..2ea8e475eb4d2f5e5df59009a0a16960b9b998ff
--- /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 0000000000000000000000000000000000000000..fdc3b92c6866260c51aaeeaa7d8a5bc90486037b
--- /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 0000000000000000000000000000000000000000..3fc891d5e12b7ecac4e4b6afdba25780db31b214
--- /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 0000000000000000000000000000000000000000..5713b796ac0f3a0ec2fc46c8336bcfcc2357ede6
--- /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 0000000000000000000000000000000000000000..8a34b3c6566dccc0ca7ffc28636c7f2a0de8e817
--- /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 0000000000000000000000000000000000000000..a423600d57ed7a90faf87eace687a414c0b76d37
--- /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 0000000000000000000000000000000000000000..773a8f95b7ddc44f57555c60fc3f4ff3b5d71a60
--- /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;
+ }
+}
diff --git a/user-service/user-service-domain/src/main/java/com/example/user/service/domain/User.java b/user-service/user-service-domain/src/main/java/com/example/user/service/domain/User.java
index e5e3e37fef4e8839ffb9c6bf9ca9b71b43003bbf..0de0058917c0c373427ab2fe0a7948c6baea327d 100644
--- a/user-service/user-service-domain/src/main/java/com/example/user/service/domain/User.java
+++ b/user-service/user-service-domain/src/main/java/com/example/user/service/domain/User.java
@@ -1,9 +1,11 @@
package com.example.user.service.domain;
import com.example.user.service.common.IdWorker;
+import com.example.user.service.domain.port.GetUserByIdPort;
import com.example.user.service.domain.port.GetUserByNamePort;
import com.example.user.service.domain.port.GetUserListPort;
import com.example.user.service.domain.valueobject.*;
+import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -21,10 +23,25 @@ public class User {
private Email email;
//todo 需要修改会Password类型
private String password;
+
+ // 字段注入方式 - 通过@Resource或@Autowired注解注入
+ private GetUserByNamePort getUserByNamePort;
+ private GetUserListPort getUserListPort;
public User() {
}
+ // 构造函数注入方式
+ public User(UserId id, UserName name, UserAge age, Email email,
+ GetUserByNamePort getUserByNamePort, GetUserListPort getUserListPort) {
+ this.id = id;
+ this.name = name;
+ this.age = age;
+ this.email = email;
+ this.getUserByNamePort = getUserByNamePort;
+ this.getUserListPort = getUserListPort;
+ }
+
public User(UserId id, UserName name, UserAge age, Email email) {
this.id = id;
this.name = name;
@@ -39,14 +56,58 @@ public class User {
this.email = email;
}
+ // Setter方法注入方式
+ public void setGetUserByNamePort(GetUserByNamePort getUserByNamePort) {
+ this.getUserByNamePort = getUserByNamePort;
+ }
+
+ public void setGetUserListPort(GetUserListPort getUserListPort) {
+ this.getUserListPort = getUserListPort;
+ }
+
+ // 使用字段注入的业务方法
+ public User getUserByNameWithFieldInjection(String name) {
+ if (getUserByNamePort == null) {
+ throw new IllegalStateException("GetUserByNamePort依赖未注入");
+ }
+ return getUserByNamePort.getUserByName(name);
+ }
+
+ // 使用构造函数注入的业务方法
+ public static User getUserByNameWithConstructorInjection(String name, GetUserByNamePort getUserByNamePort) {
+ return getUserByNamePort.getUserByName(name);
+ }
+
+ // 使用setter注入的业务方法
+ public User getUserByNameWithSetterInjection(String name) {
+ if (getUserByNamePort == null) {
+ throw new IllegalStateException("GetUserByNamePort依赖未注入,请先调用setGetUserByNamePort方法");
+ }
+ return getUserByNamePort.getUserByName(name);
+ }
public static List getUsers(GetUserListPort getUserListPort){
return getUserListPort.getUsers();
}
+ @Resource
+ private GetUserByIdPort getUserByIdPort;
+
+ // 静态字段注入 - 用于静态方法
+ private static GetUserByNamePort staticGetUserByNamePort;
+
+ // 静态注入方法 - 由Spring容器调用
+ @Resource
+ public void setStaticGetUserByNamePort(GetUserByNamePort getUserByNamePort) {
+ User.staticGetUserByNamePort = getUserByNamePort;
+ }
- public static User getUserByName(String name, GetUserByNamePort getUserByNamePort){
- User user = getUserByNamePort.getUserByName(name,getUserByNamePort);
+ // 静态方法 - 只使用name参数,通过静态字段获取依赖
+ public static User getUserByName(String name){
+ if (staticGetUserByNamePort == null) {
+ throw new IllegalStateException("GetUserByNamePort依赖未注入,请确保Spring容器已初始化");
+ }
+ User user = staticGetUserByNamePort.getUserByName(name);
return user;
}