還在苦撐場站運營?試試 100Charge:若依 + SpringBoot + Netty 加持的超級數字化平臺
隨著新能源汽車保有量持續上漲,充電基礎設施的建設速度已成為產業能否健康發展的關鍵指標。很多中小充電場站負責人都面臨同一個難題:設備接入要靠專業團隊、系統改造成本高、用戶找樁困難、訂單數據散落難統計……這些問題使得原本應該“自動化、高效率”的充電運營變得極度繁瑣。
100Charge 正是為解決這些真實痛點而生。平臺基于 RuoYi(若依)框架 + SpringBoot + Netty + Redis + PostgreSQL 搭建,秉持 “輕部署、低成本、快速上線、全業務覆蓋” 的理念,為開發者與場站運營者提供一個可擴展、可學習、可實際落地的充電運營整體解決方案。
本文將從核心技術基礎、平臺架構設計、業務功能邏輯到關鍵代碼實現,完整拆解 100Charge 背后的設計與實現過程,助你輕松把握充電運營系統的核心要點。
核心技術棧:不是堆技術,而是貼合場景的最佳組合
100Charge 的技術組合并不是隨意羅列,而是圍繞三個核心需求優化所得:
- 設備高并發實時通信
- 業務數據一致性與可靠性
- 用戶端毫秒級體驗
以下從四個維度解讀其技術架構設計思路。
RuoYi(若依)——降低后臺系統開發與運維成本
若依框架在國內中小企業級項目中幾乎是“快開快用”的代名詞,它為 100Charge 帶來的價值體現在:
- 成熟權限體系 “角色—菜單—接口” 權限模型開箱即用,不必重復造輪子。 如:
場站管理員:僅能查看本場站設備與訂單
總部用戶:可管理所有場站與設備
- 完善的前端組件體系 借助若依自帶的 Vue 組件庫,可以迅速構建管理端頁面,如:
- 設備狀態表格
- 場站運營看板
- 訂單統計圖表
- 活躍的社區支持 中小場站無需重新組建技術團隊,日常維護門檻極低。
Netty —— 充電樁實時通信的核心引擎
100Charge 的通信層完全基于 Netty 構建,適配充電樁的實時數據上報與指令下發。
為何一定要用 Netty?
- 高性能的 異步非阻塞通信
- 可同時接入 上千臺設備
- 延遲控制在 100ms 內
- 可實現 自定義私有協議 (解決不同廠家充電樁協議格式不統一的問題)
這層通信能力決定了系統是否能做到“用戶掃碼立即啟動”、“設備故障秒級上報”。
PostgreSQL + Redis —— 數據一致性 + 高性能查詢的最佳組合
充電訂單涉及金額、時長、實時電量,要求極高的數據一致性,因此 100Charge 使用:
PostgreSQL(存核心數據)
- 存儲結構化業務數據(訂單、用戶余額、計費規則等)
- 支持 ACID 事務 → 避免 “扣費成功但訂單失敗” 的情況
Redis(緩存高頻數據)
- 場站空閑樁數量
- 當前電價與計費規則
- 用戶附近站點緩存
Redis 將用戶端訪問速度提升至 微秒級。
MinIO + Elasticsearch(增強版)——文件與海量日志存儲能力提升
- MinIO: 存儲場站實景圖、故障截圖、證件文件等
- ES(可選): 用于日志與運營數據分析,例如:
- 最近 7 天峰值充電時間段
- 某用戶月度充電行為分析
平臺架構:真正能夠落地的模塊化分層結構
100Charge 采用 分層架構 + 模塊化設計,從代碼層、數據層到前端層都清晰可控。
/com/icoderoad/charge
├── netty # 設備通信
├── station # 場站信息
├── device # 充電樁管理
├── order # 訂單業務
├── billing # 計費策略
├── user # 用戶賬戶
├── common # 公共組件
└── storage #MinIO 文件處理平臺總體結構如下:
層級 | 組件 | 職責 |
通信層 | Netty | 設備狀態上報、啟停指令下發 |
服務層 | SpringBoot | 場站、設備、訂單、計費、小程序用戶服務 |
緩存層 | Redis | 高頻業務查詢緩存 |
數據層 | PostgreSQL / ES | 核心數據 + 海量日志 |
文件層 | MinIO | 圖片、截圖、證件文件 |
前端層 | 小程序、若依后臺 | 用戶端 + 管理端 |
功能設計:覆蓋充電運營的全業務鏈路
場站與設備管理
- 多場站聚合管理
- 實時監控設備狀態(空閑、充電中、故障)
- 功率、電量、啟動限制參數配置
- 故障自動告警
靈活計費能力
支持:
- 時段電價
- 節假日電價
- 新用戶活動價
- 服務費可配置(全免 / 部分免)
- 停車費聯動優惠
非常貼合中小場站靈活運營的需求。
微信小程序用戶端
用戶無需下載 App,即可完成:
- 附近找樁
- 掃碼啟動
- 實時查看電量、電費
- 自動停止
- 微信支付 / 余額支付
- 訂單查詢與開票
整個鏈路不超過 3 步。
訂單與財務體系
- 訂單明細全記錄(電量、時長、費用、設備號)
- 按場站、時間、用戶篩選
- 導出 Excel 用于財務對賬
- 余額充值 / 贈送 / 扣費全流程記錄
關鍵代碼實現(已按 com.icoderoad 規范優化)
以下為關鍵模塊的完整代碼示例(已做語義優化)。
Maven 依賴(pom.xml)
<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">
<!-- 若依父工程 -->
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-parent</artifactId>
<version>3.8.5</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>100charge-server</artifactId>
<name>100Charge Server</name>
<properties>
<netty.version>4.1.90.Final</netty.version>
<postgresql.version>42.5.4</postgresql.version>
</properties>
<dependencies>
<!-- 若依基礎依賴 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<!-- Netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>application.yml(核心配置)
server:
port: 8088
servlet:
context-path: /100charge
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/100charge_db
username: postgres
password: 123456
redis:
host: localhost
port: 6379
database: 1
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 1
netty:
port: 8888
boss-thread-count: 1
worker-thread-count: 4Netty 服務端啟動類
package com.icoderoad.charge.netty;
@Slf4j
@Component
public class NettyServer {
@Value("${netty.port}")
private int port;
@PostConstruct
public void start() {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup(4);
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss, worker)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new ChargerDataDecoder());
ch.pipeline().addLast(new ChargerDataEncoder());
ch.pipeline().addLast(new ChargerBusinessHandler());
}
});
bootstrap.bind(port).sync();
log.info("Netty server started at {}", port);
} catch (Exception e) {
log.error("Netty start error", e);
}
}
}設備上報業務處理器
package com.icoderoad.charge.netty;
@Slf4j
public class ChargerBusinessHandler extends SimpleChannelInboundHandler<String> {
private final IChargerDeviceService deviceService =
SpringUtils.getBean(IChargerDeviceService.class);
private final RedisTemplate<String, Object> redis =
SpringUtils.getBean(RedisTemplate.class);
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
log.info("Device report: {}", msg);
String[] arr = msg.split("\\|");
if (arr.length != 3) {
ctx.writeAndFlush("ERROR\n");
return;
}
String deviceId = arr[0];
Integer status = Integer.valueOf(arr[1]);
Double power = Double.valueOf(arr[2]);
ChargerDevice dev = new ChargerDevice();
dev.setDeviceId(deviceId);
dev.setStatus(status);
dev.setRealTimePower(power);
deviceService.updateChargerDevice(dev);
String key = "CHARGER_STATUS:" + deviceId;
redis.opsForValue().set(key, dev, 1, TimeUnit.HOURS);
ctx.writeAndFlush("OK\n");
}
}結語:100Charge 不是 Demo,而是可真正運營的生產級方案
中小場站缺的不是“更復雜的系統”,而是:
- 易部署
- 又穩定
- 又能快速上線
- 又能低成本維護
而 100Charge 正是基于這個核心需求構建。 你既可以把它用作生產運營系統,也可以把它當成充電行業學習的最佳實踐架構。

























