首先來看看配置中心數據庫的設計。java
CREATE TABLE `message` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '消息體id', `project_name` varchar(200) DEFAULT NULL COMMENT '項目名稱', `env_value` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'local' COMMENT '環境,dev平常,gray灰度,online線上,local本地', `property_value` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'preperties 中的value', `config_value` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '配置中心配置的須要注入的值', `remote_address` varchar(100) DEFAULT NULL COMMENT '客戶端 session key', `creator` bigint(20) DEFAULT NULL COMMENT '建立人', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間', `modifier` bigint(20) DEFAULT NULL COMMENT '修改人', `gmt_modify` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間', `config_version` int(11) NOT NULL DEFAULT '1' COMMENT '樂觀鎖,版本', `is_deleted` int(1) NOT NULL DEFAULT '0' COMMENT '邏輯刪除,0未刪除,1已刪除', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='消息體'; 複製代碼
project_name
:項目名稱,不一樣的項目可能有名字相同的配置,因此用來區分。
env_value
:當前環境,我以爲既然是配置中心,就應該接管全部配置,不須要用戶再寫三個
application.properties
文件來區分。這個極大的簡化了多環境項目。
property_value
:這個東西其實就是
application.properties
裏面配置的值,舉個栗子🌰,好比你在
application.properties
寫了一個這個配置
mina.config.name=data1
,那麼
data1
就是
property_value
。
config_value
:就是你真正要配置的值,就是用來替換
data1
的值。
remote_address
:這個是客戶端的地址,主要是當服務端更改了配置項,來主動向客戶端推送的。是的,這個配置中心既有推的模式,也有拉的模式。
而後用咱們很是熟悉的Mybatis-Plus
代碼生成器,生成一下代碼。
生成後的效果:
git
首先要把 Message
這個類移動到Base
模塊中,由於客戶端發送消息,也須要使用這個類。
最後效果:
github
由於使用了SpringBoot
,接下來咱們使用配置類的方式來整合Mina
。web
由於有不少配置屬性,我不想用戶全都寫到application.properties
中,並且若是用戶在application.properties
中寫配置屬性的時候,能出現提示就更好了。spring
因此首先要建立一個類:MinaServerProperty
數據庫
package com.lww.mina.config;
import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author lww * @date 2020-07-05 16:13 */ @ConfigurationProperties(prefix = "mina.server") public class MinaServerProperty { /** * 服務器監聽端口,默認 9123 */ private Integer port = 9123; /** * 服務器ip地址,默認 127.0.0.1 */ private String address = "127.0.0.1"; /** * 緩衝區大小,默認2048 */ private Integer readBufferSize = 2048; /** * 空閒時間,單位秒 默認 5 秒沒操做就進入空閒狀態 */ private Integer idelTimeOut = 5; /** * 初始化線程池大小,默認10 */ private Integer corePoolSize = 10; /** * 最大線程數,默認20 */ private Integer maximumPoolSize = 20; /** * 初始化用戶名 */ private String username; /** * 初始化密碼 */ private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getPort() { return port; } public void setPort(Integer port) { this.port = port; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getReadBufferSize() { return readBufferSize; } public void setReadBufferSize(Integer readBufferSize) { this.readBufferSize = readBufferSize; } public Integer getIdelTimeOut() { return idelTimeOut; } public void setIdelTimeOut(Integer idelTimeOut) { this.idelTimeOut = idelTimeOut; } public Integer getCorePoolSize() { return corePoolSize; } public void setCorePoolSize(Integer corePoolSize) { this.corePoolSize = corePoolSize; } public Integer getMaximumPoolSize() { return maximumPoolSize; } public void setMaximumPoolSize(Integer maximumPoolSize) { this.maximumPoolSize = maximumPoolSize; } } 複製代碼
這個註解配合@EnableConfigurationProperties
這個一塊兒使用,能夠在項目裏生成以下的文件:
/META-INF/spring-configuration-metadata.json
apache
注意:要使用Maven的編譯命令,或者打包命令纔會在
target
或者jar
包中建立/META-INF/spring-configuration-metadata.json
這個文件,還有這裏不要用lombok
,老老實實的寫getter
和setter
,否則是沒有提示的。json
{
"groups": [ { "name": "mina.server", "type": "com.lww.mina.config.MinaServerProperty", "sourceType": "com.lww.mina.config.MinaServerProperty" } ], "properties": [ { "name": "mina.server.address", "type": "java.lang.String", "description": "服務器ip地址,默認 127.0.0.1", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": "127.0.0.1" }, { "name": "mina.server.core-pool-size", "type": "java.lang.Integer", "description": "初始化線程池大小,默認10", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": 10 }, { "name": "mina.server.idel-time-out", "type": "java.lang.Integer", "description": "空閒時間,單位秒 默認 5 秒沒操做就進入空閒狀態", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": 5 }, { "name": "mina.server.maximum-pool-size", "type": "java.lang.Integer", "description": "最大線程數,默認20", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": 20 }, { "name": "mina.server.password", "type": "java.lang.String", "description": "初始化密碼", "sourceType": "com.lww.mina.config.MinaServerProperty" }, { "name": "mina.server.port", "type": "java.lang.Integer", "description": "服務器監聽端口,默認 9123", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": 9123 }, { "name": "mina.server.read-buffer-size", "type": "java.lang.Integer", "description": "緩衝區大小,默認2048", "sourceType": "com.lww.mina.config.MinaServerProperty", "defaultValue": 2048 }, { "name": "mina.server.username", "type": "java.lang.String", "description": "初始化用戶名", "sourceType": "com.lww.mina.config.MinaServerProperty" } ], "hints": [] } 複製代碼
當用戶在application.properties
裏配置屬性時,會有提示:服務器
application.properties
里名稱是
mina.server
前綴加上屬性的名稱,若是是駝峯命名的,則用
-
分隔開,如
mina.server.read-buffer-size
。
javadoc
,在
application.properties
裏的提示就是這些東西。
package com.lww.mina.config;
import javax.annotation.Resource; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.filter.logging.LoggingFilter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author lww * @date 2020-07-05 16:13 */ @Configuration @EnableConfigurationProperties(MinaServerProperty.class) public class MinaServerConfig { @Resource private MinaServerProperty config; /** * 配置mina的多線程過濾器 */ @Bean public ExecutorFilter executorFilter() { //設置初始化線程數,最大線程數 return new ExecutorFilter(config.getCorePoolSize(), config.getMaximumPoolSize()); } /** * 配置mina的日誌過濾器 */ @Bean public LoggingFilter loggingFilter() { return new LoggingFilter(); } } 複製代碼
固然配置類不會這麼簡單,咱們如今能配的東西很少。如今有不少東西沒有寫,等寫好以後再把配置補上。session
在客戶端與服務端的通信中,在底層實際上是二進制數據,Mina提供了TextLineCodecFactory
,根據換行符的編碼器,雖然通常場景夠用,可是仍是不知足咱們的需求,爲了更好的解決半包和粘包,咱們須要自定義協議。
解決半包粘包的方式有不少種,咱們採用添加消息頭的方式,消息頭中包含消息的長度,還有類型。
package com.lww.mina.protocol;
import lombok.Data; import org.apache.commons.lang3.StringUtils; /** * @author lww * @date 2020-07-05 17:47 */ @Data public class MessagePack { /** * 數據總長度 */ private int len; /** * 模塊代碼 */ private int module; /** * 包體 Message json格式 */ private String body; /** * 包頭長度 */ public static final int PACK_HEAD_LEN = 8; /** * 最大長度 */ public static final int MAX_LEN = 9999; public MessagePack(int module, String body) { this.module = module; this.body = body; // 總長度 this.len = PACK_HEAD_LEN + (StringUtils.isBlank(body) ? 0 : body.getBytes().length); } } 複製代碼
一個 int
類型佔4個字節,因此長度加上模塊就佔8個byte
,包頭長度就是8。而Message
則轉爲Json存儲在body
中。
第二章先寫到這裏,咱們自定義了消息協議和Mina的配置類,用戶在application.properties
中配置時,會有提示。
第三章會建立自定義的編碼解碼器,還有心跳檢測,在第三章咱們基本能夠完成Mina的配置類,敬請期待。
對啦,歡迎你們關注個人公衆號,共同窗習,一塊兒進步。加油🤣
本文使用 mdnice 排版