目標:減少重複程式碼,提高開發效率,專案地址:github.com/neatlife/jf…
歡迎star,歡迎pr(求star, 求star, 求star)
可封裝功能列表
E文 | 功能 | 目前作用 |
---|---|---|
controller | 控制器父類 | 簡化控制器裡的常見操作 |
exception | 異常 | 統一全域性業務異常操作 |
handler | 異常攔截 | 全域性異常攔截到日誌裡 |
http | 請求響應實體 | 統一全域性響應實體 |
hystrix | hystrix事件攔截 | 熔斷時傳送報警郵件 |
jpa | jpa非業務重複程式碼封裝 | 自動給deleted_at, updated_at, created_at賦值 |
json | 響應json資料的二次處理 | 自動格式化金額小數位數 |
listener | spring boot框架事件 | 在框架啟動時給util注入service例項 |
logback | 自定義logback日誌輸出 | 將日誌輸出到elk的redis,方便elk統一進行日誌處理 |
model | 基礎jpa實體 | 包含deleted_at, updated_at, created_at欄位的實體 |
redis | 自定義redis序列化和反序列化操作 | 使用GenericJackson2JsonRedisSerializer序列化redis值,提高可讀性 |
request | 自定請求資料的解析 | 處理json請求 |
springfox | 自定義springfox文件解析 | ApiClass支援文件描述引用 |
util | 常用工具收集 | 比如json, http請求等常用工具類 |
validator | 請求引數自定義校驗 | 檢查引數長度 |
apiversion | 支援不同的api的版本到不同的控制器邏輯 | 參考 MainController |
目前已經實現上面列表中的所有功能並開源
一些關鍵的點
json & http客戶端的封裝
json & http客戶端經常使用,自行編寫容易踩坑,所以直接拿dew框架的工具類進行了整合
需要同時發出多個http請求時可以使用parallelStream()技術,可顯著減少請求總時長
List<String> paramList = ...
paramList.parallelStream().forEach(param -> {
http post with param
})
複製程式碼
經測試, 26個請求,使用parallelStream將請求總時間從23.803減少到1.731秒
MapperUtil工具類的封裝
因為java裡物件複製非常頻繁,所以封裝了MapperUtil, 雖然複製物件只需下面兩行程式碼
Class1 class1 = new Class1();
BeanUtils.copyProperties(source, class1);
複製程式碼
但是由於非常頻繁的類似程式碼,一個專案專案可能出現上千次這種複製,所以將上面兩行程式碼合併成了一行
Class1 class1 = MapperUtil.to(source, class1);
複製程式碼
核心實現程式碼如下:
public static <SOURCE, TARGET> TARGET to(SOURCE source, Class<TARGET> targetClass) {
TARGET target = BeanUtils.instantiateClass(targetClass);
BeanUtils.copyProperties(source, target);
return target;
}
複製程式碼
雖然使用了反射技術,但經過測試無效能問題
elk日誌
使用redis進行了日誌中轉,所以logstash需要從redis讀取日誌輸出到elasticsearch
logstash從redis讀取日誌輸出到elasticsearch的配置
input {
redis {
data_type => "list"
key => "logstash"
host => "127.0.0.1"
port => 6379
threads => 5
codec => "json"
}
}
filter {
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logstash-%{type}-%{+YYYY.MM.dd}"
document_type => "%{type}"
workers => 1
template_overwrite => true
}
stdout{}
}
複製程式碼
因為elasticsearch裡日誌會越來越大,所以需要定時清理,定時清理elasticsearch資料
參考:www.jianshu.com/p/458421dac…
核心程式碼如下
#!/bin/bash
# filename:deleteEsData.sh
# 每天2點定時刪除es中指定日期的資料
# crontab: 0 2 * * * sh /home/scripts/deleteEsData.sh >> /home/scripts/logs/deleteEsData.run.log 2>&1
# 如今天是2017-09-21 50天前是2017.08.02
# createdate: 20190921
today=`date +%Y-%m-%d`;
echo "今天是${today}"
# 不指定引數時,預設刪除daynum天前以logs-開頭的資料
daynum=51
# 當引數個數大於1時,提示引數錯誤
if [ $# -gt 1 ] ;then
echo "要麼不傳引數,要麼只傳1個引數!"
exit 101;
fi
# 當引數個數為1時,獲取指定的引數
if [ $# == 1 ] ;then
daynum=$1
fi
esday=`date -d '-'"${daynum}"' day' +%Y.%m.%d`;
echo "${daynum}天前是${esday}"
curl -XDELETE http://127.0.0.1:9200/logs-${esday}
echo "${esday} 的log刪除執行完成"
複製程式碼
全域性業務異常
定義全域性業務異常,方便進行全域性業務異常的捕獲和統一處理 ControllerExceptionHandler
核心處理邏輯如下:
@ExceptionHandler({BusinessRuntimeException.class})
@ResponseBody
public Response handlerBusinessException(BusinessRuntimeException ex) {
return new Response<Map>(HttpCode.SUCCESS.toString(), ex.getMessage(), Maps.newHashMap());
}
複製程式碼
這樣的好處是方便對錯誤的返回資料進行格式化
利用框架事件,簡化util
RedisUtil工具類需要RedisTemplate操作例項物件,如果在RedisUtil使用Autowired自動注入RedisTemplate,則需要RedisUtil也是Service,這將RedisUtil的呼叫變得複雜化了(使用前必須先注入RedisUtil以獲取RedisTemplate物件) 利用框架事件,可在框架啟動時,獲取RedisTemplate物件,手動注入RedisUtil裡
核心實現程式碼如下:
@Component
public class ApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
private final RedisTemplate redisTemplate;
private final JFrameworkConfig jFrameworkConfig;
@Autowired
public ApplicationStartedEventListener(RedisTemplate redisTemplate, JFrameworkConfig jFrameworkConfig) {
this.redisTemplate = redisTemplate;
this.jFrameworkConfig = jFrameworkConfig;
}
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
RedisUtil.setRedisTemplate(redisTemplate);
LockUtil.setRedisTemplate(redisTemplate);
DingTalkUtil.setDdUrl(jFrameworkConfig.getNotification().getDingTalkUrl());
}
}
複製程式碼
docker 映象倉庫選擇
自行搭建映象倉庫不如使用免費穩定的來得高效可靠
可以直接使用了aliyun提供的免費docker映象倉庫
自動維護created_at, updated_at, deleted_at欄位
採用了jpa的事件機制,在建立,修改,刪除事件發生時自動進行維護
核心程式碼如下:
@PrePersist
public void touchCreated(BaseEntity target) {
target.setCreatedAt(DateUtil.currentSecond());
target.setUpdatedAt(DateUtil.currentSecond());
}
@PreUpdate
public void touchUpdate(BaseEntity target) {
target.setUpdatedAt(DateUtil.currentSecond());
}
@PreRemove
public void touchDeleted(BaseEntity target) {
target.setDeletedAt(DateUtil.currentSecond());
}
複製程式碼
ci/cd的選擇
目前ci/cd工具選擇非常多,但在生產裡用得最多的應該是gitlab和jenkins
目前仍然採用jenkins作為ci/cd工具,gitlab的ci目前個人認為仍然不夠成熟
程式碼質量檢測
可以直接試用sonarkube的開放服務,無需自行搭建:
打包分發
一般框架會作為專案的基礎依賴,那麼能夠非常方便的下載這個框架就非常重要了
目前nexus私服仍然是首選,可以使用docker搭建nexus私服:
version: "3"
services:
nexus:
image: sonatype/nexus3
environment:
- INSTALL4J_ADD_VM_PARAMS=-Xms512m -Xmx768m -XX:MaxDirectMemorySize=1g -Djava.util.prefs.userRoot=/nexus-data/javaprefs
volumes:
- ./nexus-data:/nexus-data
ports:
- "8081:8081"
複製程式碼
微服務
由於是微服務形式的部署,所以日誌,配置都需要中心化,k8s也是標配
日誌選經典的elk
配置中心選擇apollo
部署平臺可以選擇k8s,或者k8s上的istio,目前使用k8s
微服務的k8s模版參考 應用: raw.githubusercontent.com/neatlife/jf… 閘道器: raw.githubusercontent.com/neatlife/jf…
核心區別是kind欄位,閘道器是 DaemonSet 應用是 Deployment
專案參考
完成框架的封裝必然少不了很多參考,即使這是個小框架
以下是參考列表
- github.com/kmtong/logb…
- github.com/looly/hutoo…
- github.com/gudaoxuri/d…
- github.com/gudaoxuri/d…
- github.com/xdd-organ/x…
- github.com/indrabasak/…
- github.com/ityouknow/s…
- github.com/WellJay/spr…
目前文章還在持續更新中,如果對框架開發感興趣,可加作者微信探討,也可提pr,issue等