汉服租赁管理系统是一个基于Spring Boot框架开发的传统服饰订制与租赁平台。作为一名长期从事Java全栈开发的工程师,我设计这套系统的初衷是为了解决当前汉服租赁行业普遍存在的管理混乱、效率低下等问题。系统采用前后端分离架构,整合了用户管理、服饰库存、租赁订单、支付结算等核心功能模块,为汉服租赁商家提供了一套完整的数字化解决方案。
在实际开发过程中,我特别注重系统的实用性和易用性。前端采用Vue.js构建响应式界面,后端基于Spring Boot实现RESTful API,数据库选用MySQL保证数据安全。系统还集成了Shiro安全框架,确保不同角色的用户只能访问其权限范围内的功能。这套系统不仅适合作为计算机专业毕业设计项目,更可以直接应用于实际的汉服租赁业务场景。
系统采用经典的MVC(Model-View-Controller)设计模式,将业务逻辑、数据展示和用户交互清晰分离:
模型层(Model):由实体类(Entity)和数据访问层(DAO)组成。每个实体类对应数据库中的一张表,通过MyBatis Plus实现ORM映射。例如汉服饰品类:
java复制@Entity
@Table(name = "costume")
public class Costume {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name; // 服饰名称
private String style; // 朝代风格
private String size; // 尺码
private BigDecimal rentalPrice; // 租赁价格
private Integer stock; // 库存数量
// 省略getter/setter
}
视图层(View):基于Vue.js构建,使用Element UI组件库实现美观的界面。前后端完全分离,通过axios发送HTTP请求与后端交互。
控制层(Controller):接收前端请求,调用服务层处理业务逻辑,返回JSON格式数据。典型的控制器代码如下:
java复制@RestController
@RequestMapping("/api/costume")
public class CostumeController {
@Autowired
private CostumeService costumeService;
@GetMapping
public Result list(@RequestParam Map<String,Object> params) {
PageUtils page = costumeService.queryPage(params);
return Result.ok().put("page", page);
}
}
后端技术栈:
前端技术栈:
技术选型心得:Spring Boot极大简化了SSM框架的配置工作,MyBatis Plus的代码生成器可以快速创建基础CRUD代码,Vue 3的组合式API让前端开发更加灵活。这套技术组合在开发效率和运行性能之间取得了良好平衡。
系统采用RBAC(基于角色的访问控制)模型,用户-角色-权限三级结构。Shiro框架负责认证和授权逻辑:
java复制public class UserRealm extends AuthorizingRealm {
// 授权逻辑
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
User user = (User)principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 添加用户角色
info.addRoles(user.getRoles());
// 添加用户权限
info.addStringPermissions(user.getPermissions());
return info;
}
// 认证逻辑
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
String username = (String)token.getPrincipal();
User user = userService.findByUsername(username);
if(user == null) {
throw new UnknownAccountException("账号不存在");
}
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
关键实现细节:
完整的租赁流程包括以下几个关键步骤:
sql复制SELECT * FROM costume
WHERE style = '唐制'
AND rental_price BETWEEN 100 AND 300
AND status = 1
ORDER BY create_time DESC
java复制public void addToCart(Long userId, Long costumeId, Integer days) {
String key = "cart:" + userId;
CartItem item = new CartItem(costumeId, days);
redisTemplate.opsForHash().put(key, costumeId.toString(), item);
}
java复制@Transactional
public Result createOrder(Long userId, OrderDTO dto) {
// 1. 校验库存
checkStock(dto.getItems());
// 2. 扣减库存
reduceStock(dto.getItems());
// 3. 生成订单
Order order = buildOrder(userId, dto);
orderMapper.insert(order);
// 4. 清空租赁车
clearCart(userId);
return Result.ok().put("orderId", order.getId());
}
库存管理是系统的核心难点之一,主要解决以下问题:
java复制@Transactional
public boolean reduceStock(Long costumeId, Integer num) {
// 使用乐观锁防止超卖
int rows = costumeMapper.reduceStock(costumeId, num);
return rows > 0;
}
<!-- MyBatis映射文件 -->
<update id="reduceStock">
UPDATE costume
SET stock = stock - #{num}
WHERE id = #{id} AND stock >= #{num}
</update>
java复制@Scheduled(cron = "0 0 9 * * ?") // 每天9点执行
public void checkStockWarning() {
List<Costume> list = costumeMapper.selectList(
new QueryWrapper<Costume>().lt("stock", 5));
if(!list.isEmpty()) {
String message = "以下服饰库存不足:\n";
for(Costume c : list) {
message += c.getName() + "(" + c.getStyle() + ") 剩余" + c.getStock() + "件\n";
}
mailService.sendStockWarning(message);
}
}
基于用户历史租赁数据,实现简单的协同过滤推荐:
java复制public List<Costume> recommend(Long userId) {
// 1. 获取用户历史租赁记录
List<OrderItem> history = orderItemMapper.selectByUser(userId);
// 2. 提取偏好标签(朝代、价格区间等)
Map<String, Integer> tags = extractTags(history);
// 3. 根据标签匹配相似服饰
QueryWrapper<Costume> query = new QueryWrapper<>();
for(String tag : tags.keySet()) {
query.or().like("style", tag)
.or().between("rental_price", tags.get(tag)-50, tags.get(tag)+50);
}
return costumeMapper.selectList(query.orderByDesc("rent_count"));
}
使用FullCalendar组件实现租赁时间可视化,避免时间冲突:
javascript复制// Vue组件中初始化日历
initCalendar() {
this.calendar = new Calendar(this.$refs.calendar, {
plugins: [dayGridPlugin, interactionPlugin],
initialView: 'dayGridMonth',
selectable: true,
dateClick: this.handleDateClick,
events: this.fetchRentalEvents
});
this.calendar.render();
}
基于ECharts实现租赁数据可视化分析:
java复制public Map<String, Object> getRentalStats(Date start, Date end) {
Map<String, Object> result = new HashMap<>();
// 租赁趋势分析
List<Map<String, Object>> trend = orderMapper.selectTrend(start, end);
result.put("trend", trend);
// 服饰品类占比
List<Map<String, Object>> styleRatio = orderMapper.selectStyleRatio(start, end);
result.put("styleRatio", styleRatio);
// 客户租赁频次分布
List<Map<String, Object>> frequency = orderMapper.selectFrequency(start, end);
result.put("frequency", frequency);
return result;
}
服务器配置建议:
部署步骤:
bash复制# 打包Spring Boot应用
mvn clean package -DskipTests
# 运行jar包
nohup java -jar hanfu-rental.jar --spring.profiles.active=prod > app.log 2>&1 &
bash复制# 构建生产环境代码
npm run build
# 配置Nginx
server {
listen 80;
server_name yourdomain.com;
location / {
root /path/to/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
}
}
数据库优化:
缓存策略:
java复制@Cacheable(value = "costume", key = "#id")
public Costume getById(Long id) {
return costumeMapper.selectById(id);
}
异步处理:
前端优化:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
}
代码规范:
调试技巧:
java复制@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.hanfu.rental.controller"))
.paths(PathSelectors.any())
.build();
}
版本控制:
在实际开发过程中,我深刻体会到良好的系统设计文档和注释的重要性。特别是在团队协作中,清晰的接口文档和代码注释可以大幅提高开发效率。此外,自动化测试(如JUnit单元测试、MockMVC接口测试)也应该在项目早期就纳入开发流程,而不是等到项目后期才补充。