前言:
想必大家对于XXX-spring-boot-starter这一串都很熟悉,当我们在springboot当中需要使用某一个插件的时候,往往只需要几步:
1.引入相关依赖
2.添加配置
3.使用
通过上面简单的几步,就能够进行使用了!接下来我就将结合我开发中的一个实例带大家走一遍封装一个自定starter的流程!
适用场景:
1.当我们项目存在一些通用的配置、组件、工具类、依赖等,可能会被多个项目用到,可以抽取出来封装成一个 Starter,便于复用。
2.一些复杂的配置和初始化操作,可以通过封装成 Starter,简化应用项目中的配置。
3.统一团队内的技术规范,封装一些常用的功能,减少重复劳动,提高开发效率。
我的场景引入:
公司使用的MQ是Kafka,Kafka当中,没有对延时队列的支持,为此叫我开发了一款简易版本的MQ,支持发布订阅模式,消息延时消费,ack机制,重试机制,持久化机制等。
在其中,消费者生产者与MQ之间的连接,消息推送,都通过websocket完成,那为了避免每次使用都要去集成一次websocket,以及写一堆消费、推送相关的代码,所以我决定自定义一个starter,来简化操作。
实现步骤:
1.创建项目并引入相关依赖:
在我这因为需要使用到websocket和Lombok相关的东西,所以也进行了引入,这里主要的就是spring-boot-xxx的几个依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2.代码 - 配置代码写入:
这里主要做的就是把你原来可能要重复写的,进行抽取,我这下面一大堆主要就是针对具体使用需要做的配置:建立连接,消息监听处理器等。大家可以结合自己的场景去进行拓展编写。
@Slf4j
@Component
public class ConnectComponent {
@Value("${easy-mq.baseURI}")
private String BASE_URI;
@Value("${spring.application.name}")
private String SERVERNAME;
@Value("${easy-mq.topics}")
private String TOPICS;
@Value("${easy-mq.connectFlag}")
private Boolean connectFlag = Boolean.FALSE;
@Autowired
private EasyMQAllocation easyMQAllocation;
private final Map<String, ConnectBase> connections = new ConcurrentHashMap<>();
public String getBaseUri() {
return "ws://" + BASE_URI + "/";
}
public Map<String, String> getConnectURIMap() {
if (TOPICS.isEmpty()) {
return new HashMap<>();
}
String[] topicArr = TOPICS.split(",");
Map<String, String> map = new HashMap<>();
for (String topic : topicArr) {
if (topic.isEmpty()) {
continue;
}
// 拼接连接地址
String uri = getBaseUri() + topic + "/" + SERVERNAME;
map.put(topic, uri);
}
return map;
}
@Bean
public Map<String, ConnectBase> webSocketClients() {
log.info("Initializing websocket connections with identifiers...");
if (!connectFlag) {
return connections;
}
Map<String, String> connectURIMap = getConnectURIMap();
if (connectURIMap.isEmpty()) {
return connections;
}
Set<String> keySet = connectURIMap.keySet();
for (String topicName : keySet) {
log.info("init websocket connect to : {}------------ ", connectURIMap.get(topicName));
try {
ListenerHandler listenerHandler;
try {
String className = easyMQAllocation.getListeners().get(topicName);
Class<?> clazz = Class.forName(className);
listenerHandler = (ListenerHandler) clazz.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
log.error("Failed to instantiate handler for topic: {}", topicName, e);
// 通过反射的方式获取失败,使用默认的
listenerHandler = new BaseListenerHandler();
}
ConnectBase webSocketClient = new ConnectBase(new URI(connectURIMap.get(topicName)), listenerHandler);
webSocketClient.connect();
connections.put(topicName, webSocketClient);
} catch (URISyntaxException e) {
throw new RuntimeException();
}
}
return connections;
}
}
3.在 resources/META-INF 目录下创建 spring.factories 文件:
在这个文件中声明你的自动配置类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.mao.easymq.entity.EasyMQAllocation,com.mao.easymq.connect.ConnectComponent
4.打包发布:
略
如上就完成我们的一个自定义starter了
使用:
既然完成了封装,那么就要使用起来了,具体怎么使用呢,其实就和使用别的starter一样:
1.引入依赖:
<dependencies>
<dependency>
<groupId>com.mao</groupId>
<artifactId>easymq-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.填写配置:
easy-mq:
connectFlag: true
baseURI: 127.0.0.1:12121/easyMQ
topics: popupPb
listeners:
popupPb: com.mao.testStarter.all.PopUpListenerHandler
3.可能存在的一些别的操作:
比方说我这是需要去实现我的消息监听处理器处理消息:
@Slf4j
public class PopUpListenerHandler implements ListenerHandler {
@Override
public Boolean messageOperate(String msg) {
log.info("使用自定义的监听处理器处理消息:{}", msg);
return Boolean.TRUE;
}
}
如上就结束了,可以直接启动项目进行测试了。
last:
实际的一个自定义starter,代码肯定不是上面展示的那么点,大家可以随便用一个小例子先尝试尝试,毕竟工作中你可以装菜,但是真让你上了你不能不会啊!
附上一个我的上面starter的git地址,里面还有对websocket的相关操作,感兴趣的可以去看看: