在当今数字化浪潮下,传统汽车租赁行业面临着转型升级的迫切需求。客户找车难、门店管理效率低下、预订流程繁琐等痛点长期制约着行业发展。为此,我们设计并实现了一套企业级汽车租赁管理平台,通过JSP+Servlet技术栈构建了一个完整的在线租赁解决方案。
系统架构与技术栈选型
该平台采用经典的MVC架构模式,实现了业务逻辑、数据展示和用户交互的清晰分离。技术栈选择基于稳定性和成熟度考虑:后端使用Java Servlet处理业务逻辑,JSP负责视图渲染,MySQL作为数据存储层,前端采用HTML+CSS+JavaScript组合。
// Servlet控制器示例
@WebServlet("/car/rent")
public class CarRentServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String carId = request.getParameter("carId");
String startDate = request.getParameter("startDate");
String endDate = request.getParameter("endDate");
String userId = (String) request.getSession().getAttribute("userId");
// 参数校验
if (Validator.isEmpty(carId) || Validator.isEmpty(startDate)) {
request.setAttribute("error", "参数不完整");
request.getRequestDispatcher("/error.jsp").forward(request, response);
return;
}
// 业务逻辑处理
CarRentService rentService = new CarRentService();
boolean success = rentService.processRental(userId, carId, startDate, endDate);
if (success) {
response.sendRedirect("/order/success.jsp");
} else {
request.setAttribute("error", "租赁失败,车辆可能已被预订");
request.getRequestDispatcher("/car/list.jsp").forward(request, response);
}
}
}
数据库连接采用JDBC连接池技术,确保高并发场景下的性能稳定:
// 数据库连接池配置
public class DatabaseConnection {
private static DataSource dataSource;
static {
MysqlDataSource mysqlDS = new MysqlDataSource();
mysqlDS.setURL("jdbc:mysql://localhost:3306/car_rental");
mysqlDS.setUser("username");
mysqlDS.setPassword("password");
mysqlDS.setCachePrepStmts(true);
mysqlDS.setPrepStmtCacheSize(250);
mysqlDS.setPrepStmtCacheSqlLimit(2048);
dataSource = mysqlDS;
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
数据库设计深度解析
商品表(goods)设计优化
商品表作为系统的核心数据表,设计考虑了扩展性和查询效率:
CREATE TABLE `goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`goodno` varchar(255) DEFAULT NULL COMMENT '商品编号',
`goodname` varchar(255) DEFAULT NULL COMMENT '商品名称',
`fid` varchar(255) DEFAULT NULL COMMENT '父分类ID',
`sid` varchar(255) DEFAULT NULL COMMENT '子分类ID',
`price` varchar(255) DEFAULT NULL COMMENT '商品价格',
`note` text DEFAULT NULL COMMENT '商品描述',
`saver` varchar(255) DEFAULT NULL COMMENT '保存人',
`savetime` varchar(255) DEFAULT NULL COMMENT '保存时间',
`shstatus` varchar(255) DEFAULT NULL COMMENT '审核状态',
`istj` varchar(255) DEFAULT NULL COMMENT '是否推荐',
`tprice` varchar(255) DEFAULT NULL COMMENT '特价',
`filename` varchar(255) DEFAULT NULL COMMENT '图片文件名',
`delstatus` varchar(255) DEFAULT NULL COMMENT '删除状态',
`salestatus` varchar(255) DEFAULT NULL COMMENT '销售状态',
`goodpp` varchar(255) DEFAULT NULL COMMENT '商品品牌',
PRIMARY KEY (`id`),
KEY `idx_goodno` (`goodno`),
KEY `idx_fid_sid` (`fid`,`sid`),
KEY `idx_shstatus` (`shstatus`),
KEY `idx_salestatus` (`salestatus`)
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品表'
设计亮点分析:
- 索引策略优化:针对商品编号、分类ID组合、审核状态和销售状态建立了复合索引,显著提升查询性能
- 字段类型选择:价格字段采用varchar类型,支持灵活的价格格式(如区间价格、折扣价格)
- 状态管理:通过多个状态字段实现商品的精细化管理,支持软删除机制
- 扩展性考虑:预留了品牌字段和推荐标识,为后续营销功能扩展奠定基础
库存记录表(kcrecord)设计
库存记录表实现了车辆库存的精确追踪:
CREATE TABLE `kcrecord` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`gid` varchar(255) DEFAULT NULL COMMENT '商品ID',
`happennum` varchar(255) DEFAULT NULL COMMENT '发生数量',
`type` varchar(255) DEFAULT NULL COMMENT '操作类型',
`savetime` varchar(255) DEFAULT NULL COMMENT '保存时间',
PRIMARY KEY (`id`),
KEY `idx_gid` (`gid`),
KEY `idx_savetime` (`savetime`)
) ENGINE=InnoDB AUTO_INCREMENT=92 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='库存记录表'
该表通过操作类型字段区分库存变动原因(租赁、归还、维修等),配合时间索引可实现库存历史追溯和统计分析。
核心功能实现详解
车辆租赁业务流程
租赁业务是系统的核心功能,涉及复杂的状态管理和库存控制:
// 租赁服务实现
public class CarRentService {
private GoodsDAO goodsDAO = new GoodsDAO();
private OrderDAO orderDAO = new OrderDAO();
private KcrecordDAO kcrecordDAO = new KcrecordDAO();
public boolean processRental(String userId, String carId,
String startDate, String endDate) {
Connection conn = null;
try {
conn = DatabaseConnection.getConnection();
conn.setAutoCommit(false);
// 检查车辆可用性
Goods car = goodsDAO.findById(conn, carId);
if (!"上架".equals(car.getSalestatus()) ||
!"已审核".equals(car.getShstatus())) {
return false;
}
// 创建订单
Order order = new Order();
order.setUserId(userId);
order.setGoodsId(carId);
order.setStartDate(startDate);
order.setEndDate(endDate);
order.setStatus("待支付");
order.setCreateTime(new Date());
boolean orderSuccess = orderDAO.save(conn, order);
if (!orderSuccess) {
conn.rollback();
return false;
}
// 更新库存记录
Kcrecord record = new Kcrecord();
record.setGid(carId);
record.setHappennum("-1"); // 减少库存
record.setType("租赁出库");
record.setSavetime(new Date().toString());
boolean kcSuccess = kcrecordDAO.save(conn, record);
if (!kcSuccess) {
conn.rollback();
return false;
}
conn.commit();
return true;
} catch (Exception e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException ex) {}
}
return false;
} finally {
if (conn != null) {
try { conn.close(); } catch (SQLException e) {}
}
}
}
}

订单管理模块
订单管理实现了完整的生命周期控制,从创建到完成的全流程跟踪:
<%-- 订单列表JSP页面 --%>
<%@ page import="java.util.List,com.carrental.model.Order" %>
<%
List<Order> orders = (List<Order>) request.getAttribute("orders");
%>
<table class="table table-striped">
<thead>
<tr>
<th>订单编号</th>
<th>车辆信息</th>
<th>租赁时间</th>
<th>订单状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<% for(Order order : orders) { %>
<tr>
<td><%= order.getOrderNo() %></td>
<td>
<img src="<%= order.getGoods().getFilename() %>" width="50">
<%= order.getGoods().getGoodname() %>
</td>
<td><%= order.getStartDate() %> 至 <%= order.getEndDate() %></td>
<td>
<span class="status-<%= order.getStatus() %>">
<%= order.getStatus() %>
</span>
</td>
<td>
<a href="/order/detail?id=<%= order.getId() %>" class="btn btn-info">详情</a>
<% if("待支付".equals(order.getStatus())) { %>
<a href="/payment/create?orderId=<%= order.getId() %>" class="btn btn-warning">支付</a>
<% } %>
</td>
</tr>
<% } %>
</tbody>
</table>

车辆库存管理
库存管理采用实时追踪机制,确保数据准确性:
// 库存查询服务
public class InventoryService {
public int getCurrentStock(String goodsId) {
String sql = "SELECT SUM(CAST(happennum AS SIGNED)) as total " +
"FROM kcrecord WHERE gid = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, goodsId);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getInt("total");
}
return 0;
} catch (SQLException e) {
e.printStackTrace();
return -1;
}
}
public List<Kcrecord> getStockHistory(String goodsId, Date startDate, Date endDate) {
List<Kcrecord> records = new ArrayList<>();
String sql = "SELECT * FROM kcrecord WHERE gid = ? AND savetime BETWEEN ? AND ? " +
"ORDER BY savetime DESC";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, goodsId);
pstmt.setTimestamp(2, new Timestamp(startDate.getTime()));
pstmt.setTimestamp(3, new Timestamp(endDate.getTime()));
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
Kcrecord record = new Kcrecord();
record.setId(rs.getLong("id"));
record.setGid(rs.getString("gid"));
record.setHappennum(rs.getString("happennum"));
record.setType(rs.getString("type"));
record.setSavetime(rs.getString("savetime"));
records.add(record);
}
} catch (SQLException e) {
e.printStackTrace();
}
return records;
}
}

用户会话管理
系统采用Session机制管理用户状态,确保安全性:
// 登录验证Servlet
@WebServlet("/user/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String userType = request.getParameter("userType");
UserService userService = new UserService();
User user = userService.authenticate(username, password, userType);
if (user != null) {
HttpSession session = request.getSession();
session.setAttribute("userId", user.getId());
session.setAttribute("username", user.getUsername());
session.setAttribute("userType", userType);
session.setMaxInactiveInterval(30 * 60); // 30分钟超时
// 记录登录日志
LogService.logLogin(user.getId(), request.getRemoteAddr());
if ("admin".equals(userType)) {
response.sendRedirect("/admin/dashboard.jsp");
} else {
response.sendRedirect("/user/dashboard.jsp");
}
} else {
request.setAttribute("error", "用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}

实体模型设计
系统采用面向对象的设计思想,构建了完整的实体模型体系:
// 商品实体类
public class Goods {
private Long id;
private String goodno;
private String goodname;
private String fid;
private String sid;
private String price;
private String note;
private String saver;
private String savetime;
private String shstatus;
private String istj;
private String tprice;
private String filename;
private String delstatus;
private String salestatus;
private String goodpp;
// getter和setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getGoodno() { return goodno; }
public void setGoodno(String goodno) { this.goodno = goodno; }
// 其他getter/setter方法...
// 业务方法
public boolean isAvailable() {
return "上架".equals(salestatus) && "已审核".equals(shstatus) && !"是".equals(delstatus);
}
public BigDecimal getCurrentPrice() {
if (tprice != null && !tprice.trim().isEmpty()) {
return new BigDecimal(tprice);
}
return new BigDecimal(price);
}
}
功能展望与优化方向
基于当前系统架构,未来可从以下几个方向进行优化和功能扩展:
1. 引入Redis缓存层
实现思路:将热点数据如车辆信息、用户会话、配置信息等存入Redis,减轻数据库压力。
// 缓存服务示例
@Service
public class RedisCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public Goods getGoodsFromCache(String goodsId) {
String key = "goods:" + goodsId;
Goods goods = (Goods) redisTemplate.opsForValue().get(key);
if (goods == null) {
goods = goodsDAO.findById(goodsId);
if (goods != null) {
redisTemplate.opsForValue().set(key, goods, Duration.ofHours(1));
}
}
return goods;
}
}
2. 微服务架构改造
实现思路:将单体应用拆分为用户服务、订单服务、库存服务、支付服务等微服务,提升系统可扩展性和维护性。
3. 移动端适配开发
实现思路:开发React Native或Flutter移动应用,提供更好的移动端用户体验,支持扫码租车等移动特色功能。
4. 智能推荐系统
实现思路:基于用户历史租赁数据和协同过滤算法,实现个性化车辆推荐:
public class RecommendationService {
public List<Goods> recommendCars(String userId) {
// 基于用户历史行为分析
List<RentalHistory> history = rentalDAO.findUserHistory(userId);
// 协同过滤算法实现
Map<String, Double> userPreferences = analyzePreferences(history);
// 返回匹配度最高的车辆
return goodsDAO.findByPreferences(userPreferences);
}
}
5. 大数据分析平台
实现思路:集成ELK栈或ClickHouse,构建租赁业务数据分析平台,为运营决策提供数据支持。
系统安全与性能优化
系统在安全性方面采用了多重防护措施:
// SQL注入防护
public class SQLInjectionProtection {
public static boolean isValidParameter(String input) {
if (input == null) return false;
// 检测SQL注入关键词
String[] sqlKeywords = {"select", "insert", "delete", "update", "drop",
"union", "exec", "truncate"};
String lowerInput = input.toLowerCase();
for (String keyword : sqlKeywords) {
if (lowerInput.contains(keyword) &&
lowerInput.matches(".*\\b" + keyword + "\\b.*")) {
return false;
}
}
return true;
}
}
// XSS防护
public class XSSProtection {
public static String filterXSS(String input) {
if (input == null) return null;
return input.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\"", """)
.replaceAll("'", "'")
.replaceAll("/", "/");
}
}
性能优化方面,系统采用了数据库连接池、静态资源缓存、页面静态化等技术:
<!-- web.xml中的缓存配置 -->
<filter>
<filter-name>ExpiresFilter</filter-name>
<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
<init-param>
<param-name>ExpiresByType image</param-name>
<param-value>access plus 1 month</param-value>
</init-param>
</filter>
该汽车租赁管理平台通过严谨的架构设计、完善的业务功能实现和多重安全防护措施,为传统汽车租赁行业提供了完整的数字化解决方案。系统具有良好的扩展性和维护性,为后续的功能升级和技术演进奠定了坚实基础。