随着城市机动车保有量的持续增长,传统停车场管理面临效率低下、人工计费误差大、数据统计困难等挑战。智慧停车管理平台应运而生,通过数字化手段实现车位资源的高效配置和费用自动核算,为停车场运营方提供全面的管理解决方案。
系统架构与技术栈
平台采用经典的三层架构设计,基于SSH(Struts2+Spring+Hibernate)集成框架构建。表现层使用Struts2框架处理用户请求与页面跳转,通过Action类接收前端表单数据并调用业务逻辑;业务层依托Spring框架的IoC容器统一管理Service组件,利用声明式事务确保收费、车位状态变更等操作的数据一致性;数据持久层基于Hibernate实现对象关系映射,通过实体类映射数据库表,并借助HQL完成复杂查询。
技术栈配置如下:
<dependencies>
<!-- Struts2核心 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.30</version>
</dependency>
<!-- Spring框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
<!-- Hibernate ORM -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.7.Final</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
数据库设计亮点分析
停车记录表(t_carstop)的设计优化
t_carstop表作为系统的核心业务表,其设计体现了多重优化考虑:
CREATE TABLE `t_carstop` (
`stopId` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录编号',
`carNumber` varchar(20) DEFAULT NULL COMMENT '车牌号',
`carType` int(11) DEFAULT NULL COMMENT '车辆类型',
`owner` varchar(20) DEFAULT NULL COMMENT '车主',
`cardNumber` varchar(30) DEFAULT NULL COMMENT '卡号',
`startTime` varchar(20) DEFAULT NULL COMMENT '开始时间',
`endTime` varchar(20) DEFAULT NULL COMMENT '结束时间',
`stopDuration` float DEFAULT NULL COMMENT '停车时长',
`carPositionObj` int(11) DEFAULT NULL COMMENT '所在车位',
`stopCost` float DEFAULT NULL COMMENT '停车费用',
PRIMARY KEY (`stopId`),
KEY `FK3FC77D0B9F1D10B5` (`carPositionObj`),
KEY `FK3FC77D0B96E09FA` (`carType`),
CONSTRAINT `FK3FC77D0B96E09FA` FOREIGN KEY (`carType`) REFERENCES `t_cartype` (`carTypeId`),
CONSTRAINT `FK3FC77D0B9F1D10B5` FOREIGN KEY (`carPositionObj`) REFERENCES `t_carposition` (`positionId`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='停车记录表'
设计亮点分析:
- 索引策略优化:为
carPositionObj和carType字段建立了外键索引,显著提升了车位查询和车辆类型统计的性能 - 数据类型精准选择:
stopDuration使用float类型精确存储停车时长,stopCost同样使用float确保费用计算的精度 - 外键约束完整性:通过FOREIGN KEY约束确保数据的一致性,防止无效的车位或车辆类型记录
区域信息表(t_areainfo)的定价策略设计
CREATE TABLE `t_areainfo` (
`areaId` int(11) NOT NULL AUTO_INCREMENT COMMENT '区域编号',
`areaName` varchar(40) DEFAULT NULL COMMENT '区域名称',
`price` float DEFAULT NULL COMMENT '价格',
PRIMARY KEY (`areaId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='区域信息表'
该表采用简洁高效的设计,支持不同区域差异化定价策略。price字段的float类型设计为后续实现动态调价功能预留了扩展空间。
用户权限分离设计
系统通过t_userinfo和admin表的分离设计,实现了操作员与管理员角色的权限隔离:
CREATE TABLE `t_userinfo` (
`user_name` varchar(20) NOT NULL COMMENT '用户名',
`password` varchar(20) DEFAULT NULL COMMENT '密码',
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`sex` varchar(4) DEFAULT NULL COMMENT '性别',
`birthday` varchar(20) DEFAULT NULL COMMENT '生日',
`userPhoto` varchar(50) DEFAULT NULL COMMENT '用户照片',
`telephone` varchar(20) DEFAULT NULL COMMENT '电话',
`memo` longtext DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表'
CREATE TABLE `admin` (
`username` varchar(20) NOT NULL COMMENT '用户名',
`password` varchar(20) DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员表'
这种设计确保了系统安全性和数据隔离性,管理员表仅保留核心认证信息,而操作员表包含完整的个人信息管理功能。
核心功能实现
1. 智能计费引擎实现
系统的核心计费功能通过Service层实现复杂的费用计算逻辑:
@Service
@Transactional
public class BillingService {
@Autowired
private ParkingRecordDAO parkingRecordDAO;
@Autowired
private AreaInfoDAO areaInfoDAO;
public float calculateParkingFee(String carNumber, Date exitTime) {
ParkingRecord record = parkingRecordDAO.findByCarNumberAndExitTimeIsNull(carNumber);
if (record == null) {
throw new BusinessException("未找到该车辆的停车记录");
}
AreaInfo area = areaInfoDAO.findById(record.getAreaId());
long duration = calculateDuration(record.getStartTime(), exitTime);
// 分段计费逻辑
float fee = 0;
if (duration <= 60) { // 首小时
fee = area.getFirstHourPrice();
} else {
fee = area.getFirstHourPrice() +
(float) Math.ceil((duration - 60) / 60.0) * area.getAdditionalHourPrice();
}
record.setStopCost(fee);
record.setEndTime(exitTime);
record.setStopDuration(duration / 60.0f); // 转换为小时
parkingRecordDAO.update(record);
return fee;
}
private long calculateDuration(Date startTime, Date endTime) {
return (endTime.getTime() - startTime.getTime()) / (1000 * 60); // 返回分钟数
}
}

2. 车位状态实时监控
通过Hibernate实现车位状态的实时查询和更新:
@Entity
@Table(name = "t_carposition")
public class CarPosition {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer positionId;
@Column(name = "positionName")
private String positionName;
@Column(name = "areaObj")
private Integer areaObj;
@Column(name = "positionState")
private String positionState; // 空闲、占用、维修中
@OneToMany(mappedBy = "carPositionObj")
private Set<CarStop> carStops;
// getter和setter方法
}
@Repository
public class CarPositionDAOImpl implements CarPositionDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<CarPosition> findAvailablePositions(Integer areaId) {
String hql = "FROM CarPosition WHERE areaObj = :areaId AND positionState = '空闲'";
Query<CarPosition> query = sessionFactory.getCurrentSession().createQuery(hql, CarPosition.class);
query.setParameter("areaId", areaId);
return query.list();
}
@Override
@Transactional
public void updatePositionState(Integer positionId, String state) {
String hql = "UPDATE CarPosition SET positionState = :state WHERE positionId = :positionId";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
query.setParameter("state", state);
query.setParameter("positionId", positionId);
query.executeUpdate();
}
}

3. 统计分析功能实现
系统提供多维度数据统计,支持决策分析:
@Controller
public class StatisticsAction extends ActionSupport {
private StatisticsService statisticsService;
private List<DailyStats> dailyStatsList;
private Date startDate;
private Date endDate;
public String dailyParkingStats() {
dailyStatsList = statisticsService.getDailyParkingStats(startDate, endDate);
return SUCCESS;
}
public String monthlyFeeStats() {
// 月费用统计逻辑
return SUCCESS;
}
// getter和setter方法
}
@Service
public class StatisticsServiceImpl implements StatisticsService {
@Autowired
private ParkingRecordDAO parkingRecordDAO;
@Override
public List<DailyStats> getDailyParkingStats(Date startDate, Date endDate) {
String hql = "SELECT new com.edu.dto.DailyStats(CAST(p.startTime AS date), " +
"COUNT(p.stopId), SUM(p.stopCost)) " +
"FROM ParkingRecord p " +
"WHERE p.startTime BETWEEN :startDate AND :endDate " +
"GROUP BY CAST(p.startTime AS date) " +
"ORDER BY CAST(p.startTime AS date)";
Query<DailyStats> query = sessionFactory.getCurrentSession().createQuery(hql, DailyStats.class);
query.setParameter("startDate", startDate);
query.setParameter("endDate", endDate);
return query.list();
}
}

4. 用户权限管理
基于Struts2拦截器实现细粒度的权限控制:
<!-- struts.xml配置 -->
<package name="secure" extends="struts-default" namespace="/secure">
<interceptors>
<interceptor name="authInterceptor" class="com.edu.interceptor.AuthInterceptor"/>
<interceptor-stack name="secureStack">
<interceptor-ref name="authInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="secureStack"/>
<action name="parkingManagement" class="parkingAction" method="manage">
<result name="success">/secure/parking_management.jsp</result>
<result name="error">/login.jsp</result>
</action>
</package>
public class AuthInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Map<String, Object> session = invocation.getInvocationContext().getSession();
String username = (String) session.get("username");
String userType = (String) session.get("userType");
if (username == null) {
return "login";
}
// 检查权限
String actionName = invocation.getProxy().getActionName();
if (!hasPermission(userType, actionName)) {
return "noPermission";
}
return invocation.invoke();
}
private boolean hasPermission(String userType, String actionName) {
// 权限验证逻辑
return true;
}
}

实体模型设计
系统采用标准的JPA注解进行实体映射,确保对象关系的一致性:
@Entity
@Table(name = "t_carstop")
public class CarStop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "stopId")
private Integer stopId;
@Column(name = "carNumber")
private String carNumber;
@ManyToOne
@JoinColumn(name = "carType")
private CarType carType;
@Column(name = "owner")
private String owner;
@Column(name = "startTime")
private String startTime;
@Column(name = "endTime")
private String endTime;
@Column(name = "stopDuration")
private Float stopDuration;
@ManyToOne
@JoinColumn(name = "carPositionObj")
private CarPosition carPosition;
@Column(name = "stopCost")
private Float stopCost;
// 构造函数、getter和setter方法
public CarStop() {}
public CarStop(String carNumber, CarType carType, String startTime) {
this.carNumber = carNumber;
this.carType = carType;
this.startTime = startTime;
}
// 其他getter和setter方法...
}
功能展望与优化方向
1. 引入Redis缓存提升性能
@Service
public class CachedParkingService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ParkingRecordDAO parkingRecordDAO;
@Cacheable(value = "parkingStats", key = "#areaId + '_' + #date")
public ParkingStats getDailyStats(Integer areaId, Date date) {
// 数据库查询逻辑
return parkingRecordDAO.getStatsByAreaAndDate(areaId, date);
}
@CacheEvict(value = "parkingStats", key = "#areaId + '_' + #date")
public void refreshStatsCache(Integer areaId, Date date) {
// 缓存清除逻辑
}
}
2. 微服务架构改造
将单体应用拆分为车位管理、计费服务、用户服务等微服务,通过Spring Cloud实现服务治理和分布式部署。
3. 移动端适配与无感支付
开发微信小程序和APP,集成车牌识别和无感支付功能,提升用户体验。
4. 大数据分析平台
集成Apache Spark进行停车行为分析,预测高峰时段和车位需求,为运营决策提供数据支持。
5. IoT设备集成
通过物联网技术连接车位传感器、道闸设备,实现真正的智能化管理。
总结
该智慧停车管理平台通过SSH框架的有机整合,构建了一个稳定、高效、可扩展的停车场管理系统。系统在数据库设计上体现了良好的规范化程度和性能优化考虑,在功能实现上覆盖了从车辆入场到费用结算的全业务流程。基于当前架构,通过引入缓存、微服务改造、移动端适配等优化措施,可以进一步提升系统的性能和用户体验,为停车场运营管理提供更加智能化的解决方案。