feat(mq-starter): 多模块脚手架 + core 信封/SPI/注解

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 04:41:54 +08:00
parent 69db3fdd01
commit 491b83de94
12 changed files with 172 additions and 0 deletions

18
mq-starter-core/pom.xml Normal file
View File

@@ -0,0 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent><groupId>com.njcn</groupId><artifactId>mq-starter</artifactId><version>1.0.0-SNAPSHOT</version></parent>
<artifactId>mq-starter-core</artifactId>
<dependencies>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>${autoconfigure.version}</version></dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency>
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool.version}</version></dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><optional>true</optional></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>${springboot.version}</version><optional>true</optional></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${springboot.version}</version><scope>test</scope></dependency>
</dependencies>
<build><plugins>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId></plugin>
</plugins></build>
</project>

View File

@@ -0,0 +1,16 @@
package com.njcn.mq.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MqListener {
String topic();
String group();
int concurrency() default 1;
int batchSize() default 1;
int maxRetry() default 3;
String tag() default "*";
}

View File

@@ -0,0 +1,13 @@
package com.njcn.mq.core;
import java.util.Map;
/** @MqListener 方法可选第二参,只读暴露信封元数据。 */
public class MqContext {
private final MqMessage message;
public MqContext(MqMessage message) { this.message = message; }
public String getKey() { return message.getKey(); }
public String getTag() { return message.getTag(); }
public String getSource() { return message.getSource(); }
public long getTimestamp() { return message.getTimestamp(); }
public Map<String, String> getHeaders() { return message.getHeaders(); }
}

View File

@@ -0,0 +1,23 @@
package com.njcn.mq.core;
import lombok.Builder;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data
@Builder
public class MqMessage {
private String key;
private String tag;
private String source;
private long timestamp;
private Map<String, String> headers;
private Object payload;
public static MqMessage of(String key, String tag, Object payload) {
return MqMessage.builder()
.key(key).tag(tag == null ? "" : tag).source("")
.timestamp(System.currentTimeMillis())
.headers(new HashMap<>(4)).payload(payload).build();
}
}

View File

@@ -0,0 +1,8 @@
package com.njcn.mq.spi;
import com.njcn.mq.core.MqMessage;
public interface MqDriver {
void send(String topic, MqMessage message);
void subscribe(MqSubscription subscription);
void stop();
}

View File

@@ -0,0 +1,6 @@
package com.njcn.mq.spi;
import com.njcn.mq.core.MqMessage;
public interface MqMessageListener {
void onMessage(MqMessage message) throws Exception;
}

View File

@@ -0,0 +1,16 @@
package com.njcn.mq.spi;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class MqSubscription {
private String topic;
private String group;
private String tag;
private Class<?> payloadType;
private int concurrency;
private int batchSize;
private int maxRetry;
private MqMessageListener listener;
}

View File

@@ -0,0 +1,16 @@
package com.njcn.mq.core;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MqMessageTest {
@Test
void of_setsKeyTagPayload_andContextReflectsThem() {
MqMessage m = MqMessage.of("k1", "nodeA", "hello");
assertEquals("k1", m.getKey());
assertEquals("nodeA", m.getTag());
assertEquals("hello", m.getPayload());
MqContext ctx = new MqContext(m);
assertEquals("k1", ctx.getKey());
assertEquals("nodeA", ctx.getTag());
}
}