1. 项目背景与核心需求
加油站作为现代交通能源供给的重要节点,其运营管理涉及油品进销存、设备维护、会员营销、财务核算等多个业务模块。传统的手工记录或单机版管理系统已难以满足以下行业痛点:
- 实时数据同步困难:油罐库存与前台销售数据脱节,容易产生"卖空"风险
- 人工核算效率低下:每日交班时需要手动汇总各油枪的销售数据
- 营销手段单一:缺乏会员积分、电子券等数字化营销工具
- 安全监管薄弱:卸油作业、设备检修等关键环节缺乏电子化流程管控
基于SpringBoot的加油站运营管理系统正是为解决这些问题而设计。系统采用B/S架构,主要实现以下核心功能:
- 油品库存管理:实时监控地下油罐液位,自动计算库存余量
- 前台收银系统:支持加油枪号绑定、支付方式记录、小票打印
- 会员营销体系:积分累积/兑换规则配置,电子优惠券发放
- 设备运维管理:加油机、油罐等设备的定期检修提醒
- 经营数据分析:油品销量排行、时段分布等可视化报表
提示:系统设计时需要特别注意加油站行业的特殊需求,如必须支持脱机运行(网络中断时仍可记录交易数据)、具备双重计量校验(加油机脉冲数与系统记录比对)等安全机制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 技术栈组成
本系统采用主流Java技术栈实现:
后端核心:
- SpringBoot 2.7.x(平衡稳定性和新特性)
- Spring Security(RBAC权限控制)
- MyBatis-Plus(简化CRUD操作)
- Redis(缓存促销活动数据)
- Quartz(定时生成日报表)
前端方案:
- Thymeleaf + Bootstrap(管理后台模板)
- ECharts(数据可视化展示)
- jQuery(基础交互逻辑)
数据库:
- MySQL 8.0(主库存储业务数据)
- SQLite(本地应急数据库)
2.2 微服务架构设计
针对加油站可能存在的连锁经营需求,系统采用模块化设计:
code复制com.gasstation
├── gas-common // 公共组件
├── gas-auth // 认证中心
├── gas-gateway // API网关
├── gas-inventory // 库存服务
├── gas-transaction // 交易服务
├── gas-member // 会员服务
└── gas-monitor // 设备监控
关键设计考量:
- 服务注册发现:通过Nacos实现动态服务发现,便于后续扩展新油站节点
- 分布式事务:使用Seata处理"加油扣库存+记录交易"的原子性操作
- 数据同步机制:采用RabbitMQ实现各油站与总部数据的最终一致性
2.3 特殊场景处理
脱机模式实现方案:
java复制// 交易服务降级处理
@Fallback(fallbackMethod = "localTransaction")
@PostMapping("/payment")
public Result processPayment(@RequestBody PaymentDTO dto) {
// 正常业务流程...
}
private Result localTransaction(PaymentDTO dto) {
// 1. 将交易数据写入SQLite
// 2. 记录待同步标记
// 3. 返回离线交易凭证
}
双重计量校验逻辑:
sql复制-- 每日对账SQL示例
SELECT
t.gun_no,
t.liter AS system_liter,
m.pulse_count/100 AS device_liter -- 假设每100脉冲=1升
FROM
transaction t
JOIN
meter_record m ON t.gun_no = m.gun_no
WHERE
ABS(t.liter - (m.pulse_count/100)) > 0.5 -- 误差超过0.5升触发警报
3. 核心功能实现细节
3.1 油罐液位监控
采用Modbus RTU协议与液位仪通信,关键实现步骤:
- 设备连接配置:
yaml复制# application-device.yml
modbus:
serial:
port: /dev/ttyUSB0
baud-rate: 9600
data-bits: 8
stop-bits: 1
parity: none
- 数据采集任务:
java复制@Scheduled(fixedRate = 30000)
public void readTankLevels() {
ModbusMaster master = new ModbusFactory()
.createRtuMaster(serialParameters);
// 读取4号油罐的液位(寄存器地址0x0000)
int[] data = master.readHoldingRegisters(1, 0, 1);
double level = data[0] * 0.1; // 转换为厘米
// 计算库存量(需预置油罐容积表)
double volume = calculateVolume(level);
inventoryService.updateStock(4, volume);
}
- 异常处理机制:
- 连续3次读取失败触发设备报警
- 液位突变超过阈值(如10cm/分钟)触发安全警报
3.2 交易流水处理
典型加油交易处理流程:
- 交易初始化:
java复制public Transaction startTransaction(GunInfo gun) {
Transaction tx = new Transaction();
tx.setGunNo(gun.getNo());
tx.setStartTime(LocalDateTime.now());
tx.setStartTotalizer(gun.getCurrentTotalizer());
tx.setStatus(TransactionStatus.STARTED);
return transactionMapper.insert(tx);
}
- 交易结算:
java复制@Transactional
public PaymentResult completeTransaction(Long txId, PaymentMethod method) {
// 1. 获取交易详情
Transaction tx = getById(txId);
// 2. 计算油量及金额
GunInfo gun = gunService.getByNo(tx.getGunNo());
double liters = (gun.getCurrentTotalizer() - tx.getStartTotalizer()) / 1000.0;
double amount = calculateAmount(liters, gun.getOilType());
// 3. 扣减库存
inventoryService.deduct(gun.getOilType(), liters);
// 4. 记录支付
Payment payment = createPayment(txId, method, amount);
// 5. 更新交易状态
tx.setStatus(TransactionStatus.COMPLETED);
updateById(tx);
return generateReceipt(tx, payment);
}
3.3 会员积分计算
采用策略模式实现不同油品的差异化积分规则:
java复制public interface PointStrategy {
int calculatePoints(double amount, MemberLevel level);
}
@Service
@Qualifier("gasolinePoint")
public class GasolinePointStrategy implements PointStrategy {
@Override
public int calculatePoints(double amount, MemberLevel level) {
return (int) (amount * level.getGasolineRate());
}
}
@Service
public class PointService {
private final Map<OilType, PointStrategy> strategies;
public PointService(List<PointStrategy> strategyList) {
this.strategies = strategyList.stream()
.collect(Collectors.toMap(
s -> s.getClass().getAnnotation(Qualifier.class).value(),
Function.identity()
));
}
public int awardPoints(OilType oilType, double amount, MemberLevel level) {
return strategies.get(oilType.name() + "Point")
.calculatePoints(amount, level);
}
}
4. 系统部署与性能优化
4.1 生产环境部署方案
硬件配置建议:
- 前端收银机:Intel i5/8GB RAM/256GB SSD(Windows 10)
- 服务器:Dell R750/双Xeon Silver/64GB RAM/RAID 10(CentOS 8)
容器化部署:
dockerfile复制# Dockerfile示例
FROM openjdk:11-jre
WORKDIR /app
COPY target/gas-station.jar .
EXPOSE 8080
ENTRYPOINT ["java","-jar",
"-Dspring.profiles.active=prod",
"-Djava.security.egd=file:/dev/./urandom",
"gas-station.jar"]
高可用配置:
- 使用Keepalived实现VIP漂移
- Nginx负载均衡配置:
nginx复制upstream gascluster {
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080 weight=2;
server 192.168.1.103:8080 weight=1;
check interval=3000 rise=2 fall=3 timeout=2000;
}
4.2 性能优化实践
数据库优化:
- 交易表按月份分表(使用ShardingSphere实现)
- 建立复合索引:
sql复制CREATE INDEX idx_transaction_query ON transaction
(gun_no, status, create_time);
缓存策略:
java复制@Cacheable(value = "oilPrice", key = "#type")
public BigDecimal getCurrentPrice(OilType type) {
return priceMapper.getLatestPrice(type);
}
@CacheEvict(value = "oilPrice", key = "#type")
public void updatePrice(OilType type, BigDecimal price) {
priceMapper.insert(new PriceAdjustment(type, price));
}
JVM参数调优:
code复制-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-Xms4g -Xmx4g
-XX:+HeapDumpOnOutOfMemoryError
5. 安全防护措施
5.1 支付安全
- PCI DSS合规实现:
- 使用Tokenization技术处理银行卡信息
- 支付密码采用HSM加密存储
- 交易日志去除敏感字段(如完整卡号)
- 防套现机制:
java复制public void checkAbnormalTransaction(Long memberId, BigDecimal amount) {
// 规则1:单日累计不超过5000元
BigDecimal dailyTotal = transactionMapper.sumTodayAmount(memberId);
if (dailyTotal.add(amount).compareTo(new BigDecimal("5000")) > 0) {
throw new BusinessException("单日交易限额已达上限");
}
// 规则2:相同金额短时重复交易检查
int sameAmountCount = transactionMapper.countRecentSameAmount(
memberId, amount, LocalDateTime.now().minusMinutes(30));
if (sameAmountCount >= 3) {
alertService.triggerAntiFraudAlert(memberId);
}
}
5.2 数据安全
- 通信安全:
- 全站HTTPS(使用Let's Encrypt证书)
- 敏感API增加时间戳+签名验证
- 数据库加密:
java复制@ColumnTransformer(
read = "AES_DECRYPT(credit_card, '${encryption.key}')",
write = "AES_ENCRYPT(?, '${encryption.key}')")
@Column(name = "credit_card")
private String creditCard;
- 审计日志:
java复制@Aspect
@Component
public class AuditLogAspect {
@AfterReturning(
pointcut = "@annotation(com.gasstation.common.annotation.AuditLog)",
returning = "result")
public void logAudit(JoinPoint jp, Object result) {
AuditLogEntry entry = new AuditLogEntry();
entry.setOperation(getOperationName(jp));
entry.setParams(JsonUtils.toJson(jp.getArgs()));
entry.setResult(JsonUtils.toJson(result));
auditLogMapper.insert(entry);
}
}
6. 项目开发经验总结
在实际开发过程中,以下几个关键点值得特别注意:
- 硬件兼容性问题:
- 不同型号的加油机通信协议存在差异,建议在协议层增加适配器模式
- USB转RS485转换器的驱动稳定性需要充分测试
- 交易对账机制:
- 设计"三次自动对账+人工复核"的容错流程
- 对账差异超过0.3%时应触发系统锁止
- 压力测试指标:
- 单台服务器应支持≥200TPS的并发交易
- 日结报表生成时间控制在3分钟以内
- 网络延迟300ms时不影响正常交易
- 扩展性考量:
- 油枪编号建议采用"油站ID+枪号"的复合编码
- 预留API对接第三方支付平台(如微信、支付宝)
对于毕业设计实现,可以适当简化以下方面:
- 使用H2内存数据库替代MySQL简化部署
- 用Mock数据模拟硬件设备通信
- 重点实现核心交易流程和基础报表功能
项目完整开发周期建议分配:
- 需求分析:2周
- 技术预研:1周(重点测试硬件通信)
- 核心功能开发:4周
- 测试调试:2周
- 文档编写:1周
