在现代航空旅行日益普及的背景下,高效的票务管理系统成为连接旅客与航空公司的关键枢纽。传统线下购票模式存在信息更新滞后、操作流程繁琐、数据一致性难以保障等固有痛点,尤其在高并发预订场景下容易引发超售风险。针对这些行业挑战,基于SSM(Spring+SpringMVC+MyBatis)框架构建的航班机票销售预订平台应运而生,通过模块化架构设计和严谨的事务控制,实现了航班管理、动态定价、在线支付与库存实时更新的全流程数字化管控。
技术架构设计
系统采用经典的三层架构模式,通过依赖注入(DI)和面向切面编程(AOP)实现业务组件的解耦与复用。Spring Framework作为控制反转(IoC)容器,统一管理Service层业务对象与DAO层数据访问实例的依赖关系。例如,通过注解方式声明事务边界,确保机票预订过程中航班库存扣减与订单生成的原子性操作:
@Service
@Transactional
public class FlightOrderServiceImpl implements FlightOrderService {
@Autowired
private FlightInventoryMapper flightInventoryMapper;
@Override
public boolean createOrder(OrderDTO orderDTO) {
// 1. 校验航班余票
FlightInventory inventory = flightInventoryMapper.selectForUpdate(orderDTO.getFlightId());
if (inventory.getRemainingSeats() < orderDTO.getPassengerCount()) {
throw new BusinessException("剩余座位不足");
}
// 2. 扣减库存(悲观锁保证数据一致性)
inventory.setRemainingSeats(inventory.getRemainingSeats() - orderDTO.getPassengerCount());
flightInventoryMapper.updateInventory(inventory);
// 3. 生成订单记录
return orderMapper.insertOrder(orderDTO) > 0;
}
}
表现层采用SpringMVC框架处理HTTP请求路由,通过@Controller注解定义 RESTful 接口,并结合拦截器实现用户身份验证。以下代码展示了航班查询接口的参数绑定与动态响应机制:
@Controller
@RequestMapping("/flight")
public class FlightController {
@Autowired
private FlightService flightService;
@RequestMapping(value = "/search", method = RequestMethod.GET)
@ResponseBody
public ResultModel searchFlights(
@RequestParam String departureCity,
@RequestParam String arrivalCity,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date departureDate) {
List<FlightVO> flights = flightService.searchByCriteria(departureCity, arrivalCity, departureDate);
return ResultModel.success(flights);
}
}
数据持久层依托MyBatis框架,通过XML映射文件将Java对象与数据库表字段动态关联。以下示例展示了动态SQL构建多条件航班查询的灵活实现:
<!-- FlightMapper.xml -->
<select id="selectByDynamicConditions" parameterType="map" resultMap="FlightResultMap">
SELECT flight_id, flight_number, departure_airport, arrival_airport,
departure_time, arrival_time, ticket_price, remaining_seats
FROM flight_inventory
<where>
<if test="departureCity != null and departureCity != ''">
AND departure_airport LIKE CONCAT('%', #{departureCity}, '%')
</if>
<if test="arrivalCity != null and arrivalCity != ''">
AND arrival_airport LIKE CONCAT('%', #{arrivalCity}, '%')
</if>
<if test="departureDate != null">
AND DATE(departure_time) = DATE(#{departureDate})
</if>
<if test="minPrice != null">
AND ticket_price >= #{minPrice}
</if>
<if test="maxPrice != null">
AND ticket_price <= #{maxPrice}
</if>
</where>
ORDER BY departure_time ASC
</select>
前端页面采用JSP模板引擎渲染,结合jQuery库实现异步数据交互。航班选择页面通过Ajax调用后端接口动态加载筛选结果,并通过DOM操作实时更新座位余量提示:
function loadFlightList() {
$.ajax({
url: '/flight/search',
type: 'GET',
data: {
departureCity: $('#departureCity').val(),
arrivalCity: $('#arrivalCity').val(),
departureDate: $('#departureDate').val()
},
success: function(response) {
if (response.success) {
renderFlightTable(response.data);
} else {
alert('查询失败:' + response.message);
}
}
});
}
数据库架构精析
系统数据库包含5张核心表,通过外键关联实现数据完整性约束。其中航班库存表(flight_inventory)采用乐观锁机制控制并发修改,用户表(user)通过角色字段区分终端旅客与管理员权限,订单表(flight_order)则记录完整的交易流水。
航班库存表设计 采用业务主键与自然主键结合的方式,既保证查询效率又符合业务逻辑:
CREATE TABLE flight_inventory (
flight_id VARCHAR(20) PRIMARY KEY COMMENT '航班业务ID',
flight_number VARCHAR(10) NOT NULL COMMENT '航班号',
aircraft_model VARCHAR(20) COMMENT '机型',
departure_airport VARCHAR(50) NOT NULL COMMENT '出发机场',
arrival_airport VARCHAR(50) NOT NULL COMMENT '到达机场',
departure_time DATETIME NOT NULL COMMENT '计划起飞时间',
arrival_time DATETIME NOT NULL COMMENT '计划到达时间',
total_seats INT DEFAULT 0 COMMENT '总座位数',
remaining_seats INT DEFAULT 0 COMMENT '剩余座位数',
ticket_price DECIMAL(10,2) COMMENT '基准票价',
version INT DEFAULT 0 COMMENT '乐观锁版本号',
INDEX idx_departure_arrival (departure_airport, arrival_airport),
INDEX idx_departure_time (departure_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='航班库存表';
该表通过version字段实现乐观锁控制,在并发订票场景下避免超售问题。索引设计覆盖了常见的查询组合(出发地-目的地、起飞时间),显著提升搜索性能。
订单表结构 采用星型 schema 设计,通过冗余存储关键业务字段降低多表关联查询开销:
CREATE TABLE flight_order (
order_id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '订单ID',
order_number VARCHAR(32) UNIQUE NOT NULL COMMENT '订单编号',
user_id BIGINT NOT NULL COMMENT '用户ID',
flight_id VARCHAR(20) NOT NULL COMMENT '航班ID',
passenger_name VARCHAR(50) NOT NULL COMMENT '乘机人姓名',
passenger_idcard VARCHAR(18) NOT NULL COMMENT '乘机人证件号',
order_amount DECIMAL(10,2) NOT NULL COMMENT '订单金额',
order_status TINYINT DEFAULT 0 COMMENT '订单状态(0-待支付 1-已支付 2-已取消)',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
pay_time DATETIME COMMENT '支付时间',
flight_number VARCHAR(10) COMMENT '航班号(冗余存储)',
departure_time DATETIME COMMENT '起飞时间(冗余存储)',
FOREIGN KEY (user_id) REFERENCES user(user_id),
FOREIGN KEY (flight_id) REFERENCES flight_inventory(flight_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='机票订单表';
冗余字段设计虽然增加了存储空间,但避免了订单列表查询时频繁联接航班表的需求,尤其在高并发读取场景下可降低数据库负载。
核心功能实现解析
1. 智能航班搜索与动态筛选
旅客通过出发地、目的地和日期条件查询可售航班,系统后端通过MyBatis动态SQL构建多维度查询语句。前端界面采用渐进式加载策略,在用户输入过程中实时触发搜索建议:

搜索功能的核心服务层代码通过构建查询条件对象,实现灵活的条件组合:
@Service
public class FlightSearchServiceImpl implements FlightSearchService {
public List<FlightVO> searchFlights(FlightQueryDTO queryDTO) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("departureCity", queryDTO.getDepartureCity());
paramMap.put("arrivalCity", queryDTO.getArrivalCity());
paramMap.put("departureDate", queryDTO.getDepartureDate());
paramMap.put("minPrice", queryDTO.getPriceRange().getMin());
paramMap.put("maxPrice", queryDTO.getPriceRange().getMax());
return flightMapper.selectByDynamicConditions(paramMap);
}
}
2. 机票预订与库存一致性保障
预订流程包含座位可用性校验、价格计算、订单生成等关键步骤。系统通过@Transactional注解声明事务边界,确保库存扣减与订单创建的原子性:

库存扣减操作采用悲观锁机制,在查询阶段即通过SELECT ... FOR UPDATE锁定记录,防止并发修改:
@Mapper
public interface FlightInventoryMapper {
@Select("SELECT * FROM flight_inventory WHERE flight_id = #{flightId} FOR UPDATE")
FlightInventory selectForUpdate(String flightId);
@Update("UPDATE flight_inventory SET remaining_seats = #{remainingSeats}, version = version + 1 WHERE flight_id = #{flightId} AND version = #{version}")
int updateWithOptimisticLock(FlightInventory inventory);
}
3. 多角色权限管理体系
系统通过用户表(user)中的role字段区分普通用户与管理员权限。SpringMVC拦截器在请求预处理阶段验证会话状态与操作权限:
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
UserVO user = (UserVO) session.getAttribute("currentUser");
if (user == null) {
response.sendRedirect("/login");
return false;
}
// 管理员接口权限校验
if (handler instanceof HandlerMethod) {
RequireAdmin requireAdmin = ((HandlerMethod) handler).getMethodAnnotation(RequireAdmin.class);
if (requireAdmin != null && !user.getRole().equals("admin")) {
throw new PermissionDeniedException("需要管理员权限");
}
}
return true;
}
}
管理员登录后可通过专属界面管理航班信息、调整票价策略、监控销售数据:

4. 订单状态机与业务流程闭环
订单生命周期包含"待支付→已支付→已出票→已完成"等状态流转。系统通过状态模式(State Pattern)封装不同状态下的业务规则:
public abstract class OrderState {
protected FlightOrder order;
public abstract void pay();
public abstract void cancel();
public abstract void complete();
}
@Component
public class PendingPaymentState extends OrderState {
@Override
public void pay() {
// 执行支付逻辑
order.setStatus(OrderStatus.PAID);
order.setState(new PaidState(order));
// 记录支付时间
order.setPayTime(new Date());
orderMapper.updateStatus(order);
}
@Override
public void cancel() {
// 释放库存
flightInventoryMapper.increaseSeats(order.getFlightId(), order.getPassengerCount());
order.setStatus(OrderStatus.CANCELLED);
order.setState(new CancelledState(order));
orderMapper.updateStatus(order);
}
}
用户可在个人中心查看历史订单并进行状态操作:

实体模型与业务对象映射
系统通过MyBatis的resultMap配置实现Java对象与数据库表的精细映射,尤其在处理复杂关联关系时展现框架优势:
<resultMap id="OrderDetailResultMap" type="com.airline.model.FlightOrder">
<id property="orderId" column="order_id"/>
<result property="orderNumber" column="order_number"/>
<result property="orderAmount" column="order_amount"/>
<result property="orderStatus" column="order_status"/>
<!-- 关联用户信息 -->
<association property="user" javaType="com.airline.model.User">
<id property="userId" column="user_id"/>
<result property="username" column="username"/>
<result property="phone" column="phone"/>
</association>
<!-- 关联航班信息 -->
<association property="flight" javaType="com.airline.model.FlightInventory">
<id property="flightId" column="flight_id"/>
<result property="flightNumber" column="flight_number"/>
<result property="departureTime" column="departure_time"/>
<result property="arrivalTime" column="arrival_time"/>
</association>
<!-- 集合映射:乘机人列表 -->
<collection property="passengers" ofType="com.airline.model.Passenger">
<result property="name" column="passenger_name"/>
<result property="idCard" column="passenger_idcard"/>
</collection>
</resultMap>
性能优化与扩展方向
当前系统在应对中小规模并发场景下表现稳定,未来可从以下几个方向进一步提升系统能力:
- 缓存策略升级:引入Redis集群实现热点航班数据的分布式缓存,将航班搜索结果的QPS提升3-5倍。可通过Spring Cache抽象层统一管理缓存注解:
@Cacheable(value = "flights", key = "#queryDTO.hashCode()", unless = "#result == null")
public List<FlightVO> searchFlights(FlightQueryDTO queryDTO) {
return flightMapper.selectByDynamicConditions(queryDTO);
}
- 异步任务处理:使用Spring的
@Async注解将订单超时取消、出票通知等非实时操作异步化,通过消息队列削峰填谷:
@Async("taskExecutor")
@EventListener
public void handleOrderTimeout(OrderTimeoutEvent event) {
FlightOrder order = orderMapper.selectById(event.getOrderId());
if (order.getStatus() == OrderStatus.PENDING_PAYMENT) {
order.cancel();
}
}
分库分表架构:当订单数据量超过千万级时,可按时间维度进行分表存储,通过Sharding-JDBC中间件实现透明路由。
价格动态引擎:构建基于历史数据和实时需求的智能定价模型,通过独立的价格服务动态调整航班票价,提升收益管理水平。
多租户支持:通过数据库 schema 隔离或数据行级权限控制,支持第三方票务代理机构接入,扩展平台商业模式。
该系统通过严谨的架构设计和细致的技术实现,为航空票务领域提供了稳定可靠的数字基座。其模块化设计理念与可扩展的技术栈选型,为后续功能迭代与性能优化奠定了坚实基础。