在传统家具电器维修行业,电话预约模式长期存在信息记录易错、派单效率低下、服务过程不透明等痛点。数字化转型升级成为必然趋势,通过构建在线预约平台,将维修需求、服务匹配、进度跟踪等环节整合于一体,能够显著提升服务响应速度与用户体验,同时帮助服务商优化内部管理、降低运营成本。
本系统采用经典的SSM(Spring+Spring MVC+MyBatis)三层架构进行开发。Spring框架作为核心容器,通过依赖注入(DI)和面向切面编程(AOP)机制管理业务对象,实现了服务层组件的低耦合与事务控制。Spring MVC负责Web请求的调度与处理,其清晰的控制器(Controller)、模型(Model)和视图(View)分离结构,使得处理用户交互逻辑条理分明。数据持久层由MyBatis担当,通过灵活的XML映射文件将Java对象与数据库表记录进行高效转换。前端页面使用JSP结合JSTL标签库进行数据渲染,与后端控制器紧密协作,形成完整的请求-响应闭环。
数据库设计亮点分析
系统共设计11张核心数据表,其中维修订单表(repair_order)和维修服务类型表(repair_service_type)的设计尤为关键,直接关系到业务逻辑的完整性和系统性能。
维修订单表采用复合主键设计,通过订单编号(order_id)与用户ID(user_id)共同确保数据唯一性:
CREATE TABLE repair_order (
order_id VARCHAR(32) NOT NULL,
user_id INT NOT NULL,
service_type_id INT NOT NULL,
repair_point_id INT NOT NULL,
appointment_time DATETIME NOT NULL,
device_type VARCHAR(50) NOT NULL,
fault_description TEXT,
order_status ENUM('pending','accepted','in_progress','completed','cancelled') DEFAULT 'pending',
total_amount DECIMAL(10,2),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (order_id, user_id),
FOREIGN KEY (service_type_id) REFERENCES repair_service_type(type_id),
FOREIGN KEY (repair_point_id) REFERENCES repair_point(point_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
该表设计具有以下技术亮点:
- 状态机设计:
order_status字段使用ENUM类型明确限定订单生命周期状态,确保业务逻辑的严谨性 - 金额精度控制:
total_amount采用DECIMAL(10,2)类型,精确到分位,避免浮点数计算误差 - 时间戳管理:
create_time和update_time自动记录数据变更时间,便于审计和追踪 - 外键约束:通过外键确保数据一致性,防止无效的服务类型或维修点数据
维修服务类型表采用树形结构设计,支持服务类目的多级分类:
CREATE TABLE repair_service_type (
type_id INT AUTO_INCREMENT PRIMARY KEY,
type_name VARCHAR(50) NOT NULL UNIQUE,
parent_id INT DEFAULT NULL,
description TEXT,
base_price DECIMAL(8,2) NOT NULL,
is_available TINYINT(1) DEFAULT 1,
sort_order INT DEFAULT 0,
FOREIGN KEY (parent_id) REFERENCES repair_service_type(type_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
该设计的先进性体现在:
- 自关联设计:通过
parent_id字段实现无限级分类,支持"家电维修>空调维修>中央空调"这类层级关系 - 软删除机制:
is_available字段实现逻辑删除,保留历史数据关联性 - 排序优化:
sort_order字段控制前端展示顺序,提升用户体验
核心业务功能实现
1. 智能预约调度系统
预约功能的核心控制器采用RESTful风格设计,支持多种查询条件组合:
@Controller
@RequestMapping("/api/order")
public class RepairOrderController {
@Autowired
private RepairOrderService orderService;
@PostMapping("/create")
@ResponseBody
public ResponseEntity<Map<String, Object>> createOrder(
@RequestBody RepairOrderDTO orderDTO,
HttpSession session) {
User user = (User) session.getAttribute("currentUser");
if (user == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Collections.singletonMap("error", "用户未登录"));
}
orderDTO.setUserId(user.getUserId());
try {
String orderId = orderService.createOrder(orderDTO);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("orderId", orderId);
return ResponseEntity.ok(result);
} catch (BusinessException e) {
return ResponseEntity.badRequest()
.body(Collections.singletonMap("error", e.getMessage()));
}
}
@GetMapping("/list")
public String listOrders(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) String status,
@RequestParam(required = false) String keyword,
Model model) {
PageHelper.startPage(page, size);
List<RepairOrder> orders = orderService.findOrdersByCriteria(status, keyword);
PageInfo<RepairOrder> pageInfo = new PageInfo<>(orders);
model.addAttribute("orders", orders);
model.addAttribute("pageInfo", pageInfo);
return "order/order-list";
}
}
服务层实现复杂的业务逻辑校验和事务管理:
@Service
@Transactional
public class RepairOrderServiceImpl implements RepairOrderService {
@Autowired
private RepairOrderMapper orderMapper;
@Autowired
private RepairPointService pointService;
@Override
public String createOrder(RepairOrderDTO orderDTO) throws BusinessException {
// 校验预约时间合理性
validateAppointmentTime(orderDTO.getAppointmentTime());
// 检查维修点服务能力
if (!pointService.canProvideService(
orderDTO.getRepairPointId(),
orderDTO.getServiceTypeId())) {
throw new BusinessException("该维修点不支持所选服务类型");
}
// 生成唯一订单号
String orderId = generateOrderId();
RepairOrder order = new RepairOrder();
BeanUtils.copyProperties(orderDTO, order);
order.setOrderId(orderId);
order.setOrderStatus("pending");
order.setCreateTime(new Date());
orderMapper.insert(order);
return orderId;
}
private String generateOrderId() {
return "RO" + System.currentTimeMillis() +
ThreadLocalRandom.current().nextInt(1000, 9999);
}
}

2. 动态维修点匹配算法
系统根据用户位置、服务类型、技师忙闲状态等多维度因素智能推荐最优维修点:
@Service
public class RepairPointMatchService {
public List<RepairPoint> findSuitablePoints(String city, Integer serviceTypeId,
Date appointmentTime) {
// 基于地理位置的初步筛选
List<RepairPoint> candidates = repairPointMapper
.findByCityAndServiceType(city, serviceTypeId);
// 负载均衡算法:选择当前时段任务最少的维修点
return candidates.stream()
.filter(point -> isAvailableAtTime(point, appointmentTime))
.sorted(Comparator.comparingInt(this::calculateWorkloadScore))
.collect(Collectors.toList());
}
private int calculateWorkloadScore(RepairPoint point) {
// 综合考虑技师数量、当前订单数、平均完成时间等因素
int technicianCount = point.getTechnicians().size();
int currentOrders = orderMapper.countCurrentOrders(point.getPointId());
double avgCompletionTime = point.getAvgCompletionTime();
return (int) (currentOrders * 0.6 +
(technicianCount > 0 ? 100.0 / technicianCount : 100) * 0.4);
}
}

3. 订单状态实时追踪
采用WebSocket技术实现订单状态的实时推送,让用户随时了解维修进度:
@ServerEndpoint("/websocket/order/{orderId}")
@Component
public class OrderTrackingWebSocket {
private static ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam("orderId") String orderId) {
sessions.put(orderId, session);
// 推送当前订单状态
pushOrderStatus(orderId);
}
public static void pushStatusUpdate(String orderId, String status) {
Session session = sessions.get(orderId);
if (session != null && session.isOpen()) {
try {
session.getBasicRemote().sendText(
String.format("{\"orderId\":\"%s\",\"status\":\"%s\",\"timestamp\":%d}",
orderId, status, System.currentTimeMillis()));
} catch (IOException e) {
// 处理异常
}
}
}
}
前端通过JavaScript监听状态变化并更新界面:
function connectOrderWebSocket(orderId) {
const socket = new WebSocket(`ws://localhost:8080/websocket/order/${orderId}`);
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
updateOrderStatusUI(data.status);
// 更新进度条
const progress = calculateProgress(data.status);
$('#progress-bar').css('width', progress + '%');
};
socket.onclose = function() {
setTimeout(() => connectOrderWebSocket(orderId), 5000);
};
}

数据持久层优化实践
MyBatis的动态SQL功能在复杂查询场景下发挥重要作用:
<!-- 维修订单动态查询 -->
<select id="selectOrdersByCondition" parameterType="map" resultMap="BaseResultMap">
SELECT * FROM repair_order
<where>
<if test="userId != null">
AND user_id = #{userId}
</if>
<if test="status != null and status != ''">
AND order_status = #{status}
</if>
<if test="startTime != null">
AND appointment_time >= #{startTime}
</if>
<if test="endTime != null">
AND appointment_time <= #{endTime}
</if>
<if test="keyword != null and keyword != ''">
AND (device_type LIKE CONCAT('%',#{keyword},'%')
OR fault_description LIKE CONCAT('%',#{keyword},'%'))
</if>
</where>
ORDER BY create_time DESC
<if test="offset != null and limit != null">
LIMIT #{offset}, #{limit}
</if>
</select>
二级缓存配置提升系统性能:
<!-- 启用Redis作为二级缓存 -->
<cache type="org.mybatis.caches.redis.RedisCache"
eviction="LRU"
flushInterval="60000"
size="1024"
readOnly="true"/>
实体模型设计精要
核心实体关系采用面向对象的设计原则,体现业务领域的完整性:
@Entity
@Table(name = "repair_order")
public class RepairOrder {
private String orderId;
private Integer userId;
private Integer serviceTypeId;
private Integer repairPointId;
private Date appointmentTime;
private String deviceType;
private String faultDescription;
private String orderStatus;
private BigDecimal totalAmount;
private Date createTime;
private Date updateTime;
// 关联实体
private User user;
private RepairServiceType serviceType;
private RepairPoint repairPoint;
private List<OrderTracking> trackings;
// 业务方法
public boolean canBeCancelled() {
return "pending".equals(orderStatus) || "accepted".equals(orderStatus);
}
public void updateStatus(String newStatus, String operator) {
this.orderStatus = newStatus;
this.trackings.add(new OrderTracking(this.orderId, newStatus, operator));
}
}

安全性与事务管理
系统通过Spring Security实现细粒度的权限控制:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/api/order/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.and()
.csrf().disable();
}
}
分布式事务处理确保数据一致性:
@Service
public class OrderProcessingService {
@Transactional(rollbackFor = Exception.class)
public void processOrderCompletion(String orderId, BigDecimal actualAmount) {
// 更新订单状态
orderMapper.updateStatus(orderId, "completed");
// 记录支付信息
PaymentRecord payment = new PaymentRecord(orderId, actualAmount);
paymentMapper.insert(payment);
// 更新技师工作量统计
technicianService.updateWorkload(orderId);
// 发送通知
notificationService.sendCompletionNotice(orderId);
}
}
性能优化策略
- 数据库连接池优化:
# Druid连接池配置
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
- SQL性能监控:
<bean id="statFilter" class="com.alibaba.druid.filter.stat.StatFilter">
<property name="slowSqlMillis" value="1000"/>
<property name="logSlowSql" value="true"/>
</bean>
- 页面静态化处理:对服务介绍等不常变的内容进行静态化缓存
未来优化方向
智能派单算法升级:引入机器学习算法,基于历史数据预测最优派单策略,考虑技师技能匹配度、交通状况、用户评价等多维度因素。
移动端原生应用开发:基于React Native或Flutter开发跨平台移动应用,提供更佳的用户体验,支持扫码报修、照片上传等便捷功能。
物联网设备集成:通过与智能家电厂商合作,实现设备自动故障检测和预警,在用户发现问题前主动推送维修建议。
大数据分析平台:构建数据分析看板,为维修服务商提供业务洞察,包括高峰期预测、配件需求预测、服务质量分析等。
微服务架构重构:将单体应用拆分为用户服务、订单服务、派单服务、支付服务等微服务,提升系统可扩展性和维护性。
该系统通过SSM框架的深度应用,构建了一个功能完善、性能稳定的在线维修服务平台。其模块化设计和扩展性架构为后续功能迭代奠定了坚实基础,体现了现代Java Web开发的最佳实践。随着技术的不断演进,该平台有望发展成为智能家居服务生态的核心枢纽。