SpringBoot+Vue3旅游管理系统开发实战

📅 2026/8/6 12:44:16
SpringBoot+Vue3旅游管理系统开发实战
1. 项目概述这个旅游管理系统采用当前主流的前后端分离架构后端基于SpringBoot框架构建前端使用Vue3实现数据持久层采用MyBatis框架数据库选用MySQL。这种技术组合在2023年的企业级应用开发中已经成为标配方案特别适合需要快速迭代的中小型项目。我在实际开发中发现这种架构最大的优势在于各层职责清晰SpringBoot负责业务逻辑和API接口Vue3处理用户交互MyBatis作为ORM框架简化数据库操作MySQL提供稳定可靠的数据存储。前后端通过RESTful API进行通信完全解耦使得团队可以并行开发。2. 技术栈深度解析2.1 SpringBoot后端设计SpringBoot 2.7.x版本是这个项目的最佳选择它内置了Tomcat服务器通过starter依赖可以快速集成各种组件。我在项目中主要使用了以下关键配置SpringBootApplication MapperScan(com.travel.mapper) public class TravelApplication { public static void main(String[] args) { SpringApplication.run(TravelApplication.class, args); } }注意MapperScan注解必须正确配置MyBatis的mapper接口路径否则会出现注入失败的问题认证模块采用JWT实现核心配置类需要继承WebSecurityConfigurerAdapterConfiguration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers(/api/auth/**).permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())); } }2.2 Vue3前端架构前端采用Vue3的组合式API写法比Options API更加灵活。项目结构建议如下/src /api - 接口请求封装 /assets - 静态资源 /components - 公共组件 /router - 路由配置 /store - Pinia状态管理 /views - 页面组件路由配置示例使用vue-router 4.xconst routes [ { path: /, component: () import(/views/Home.vue), meta: { requiresAuth: true } }, { path: /login, component: () import(/views/Login.vue) } ]2.3 MyBatis数据层实现MyBatis的mapper接口需要与XML映射文件对应这里有个容易踩的坑如果使用注解和XML混合开发需要注意优先级问题。我建议统一使用XML方式便于复杂SQL的维护。!-- UserMapper.xml -- mapper namespacecom.travel.mapper.UserMapper select idselectByUsername resultTypeUser SELECT * FROM user WHERE username #{username} /select /mapper分页查询推荐使用PageHelper插件PageHelper.startPage(pageNum, pageSize); ListUser users userMapper.selectAll(); PageInfoUser pageInfo new PageInfo(users);3. 核心功能实现3.1 旅游产品管理模块产品表设计需要考虑多种旅游类型CREATE TABLE product ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL, description text, price decimal(10,2) NOT NULL, stock int NOT NULL DEFAULT 0, type enum(GROUP,FREE,CUSTOM) NOT NULL, start_date date DEFAULT NULL, end_date date DEFAULT NULL, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;后端接口设计遵循RESTful规范GET /api/products - 获取产品列表 POST /api/products - 创建新产品 GET /api/products/{id} - 获取产品详情 PUT /api/products/{id} - 更新产品 DELETE /api/products/{id} - 删除产品3.2 订单支付系统支付流程是系统的核心难点需要考虑事务处理Transactional public Order createOrder(OrderDTO orderDTO) { // 1. 检查库存 Product product productMapper.selectById(orderDTO.getProductId()); if(product.getStock() orderDTO.getQuantity()) { throw new BusinessException(库存不足); } // 2. 扣减库存 productMapper.reduceStock(orderDTO.getProductId(), orderDTO.getQuantity()); // 3. 创建订单 Order order new Order(); BeanUtils.copyProperties(orderDTO, order); order.setStatus(OrderStatus.UNPAID); orderMapper.insert(order); // 4. 记录支付流水 Payment payment new Payment(); payment.setOrderId(order.getId()); payment.setAmount(order.getTotalAmount()); paymentMapper.insert(payment); return order; }3.3 用户评价功能评价系统采用多级评论设计CREATE TABLE comment ( id bigint NOT NULL AUTO_INCREMENT, content text NOT NULL, user_id bigint NOT NULL, product_id bigint NOT NULL, parent_id bigint DEFAULT NULL, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_product (product_id), KEY idx_parent (parent_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;前端实现递归组件展示评论树template div classcomment div classcomment-content{{ comment.content }}/div div v-ifcomment.children classreplies CommentItem v-forreply in comment.children :keyreply.id :commentreply / /div /div /template4. 项目部署方案4.1 开发环境配置推荐使用Docker Compose快速搭建开发环境version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: travel ports: - 3306:3306 volumes: - ./mysql-data:/var/lib/mysql redis: image: redis:alpine ports: - 6379:6379后端配置数据库连接spring.datasource.urljdbc:mysql://localhost:3306/travel?useSSLfalse spring.datasource.usernameroot spring.datasource.passwordroot spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver4.2 生产环境部署前端使用Nginx部署编译后的静态文件server { listen 80; server_name travel.example.com; location / { root /var/www/travel-frontend; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; } }后端推荐使用Jenkins自动化部署pipeline脚本示例pipeline { agent any stages { stage(Build) { steps { sh mvn clean package -DskipTests } } stage(Deploy) { steps { sh scp target/travel.jar userserver:/opt/travel sh ssh userserver systemctl restart travel } } } }5. 常见问题排查5.1 跨域问题解决方案开发环境常见跨域问题后端需要配置CORSConfiguration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowedHeaders(*); } }生产环境建议通过Nginx反向代理解决跨域。5.2 MyBatis缓存问题开启事务后一级缓存可能导致查询不到最新数据解决方案在方法上添加Transactional(propagation Propagation.REQUIRES_NEW)手动清除缓存sqlSession.clearCache()在查询语句中添加flushCachetrue5.3 Vue3响应式失效使用reactive()创建的对象直接赋值会导致响应式失效// 错误写法 state.list newList // 响应式丢失 // 正确写法 state.list [...newList] // 保持响应式或者使用ref()const list ref([]) list.value newList // 保持响应式6. 性能优化建议6.1 数据库优化为常用查询字段添加索引大表考虑分库分表复杂查询使用explain分析执行计划6.2 前端性能优化路由懒加载组件按需引入使用keep-alive缓存组件图片懒加载6.3 缓存策略热点数据使用Redis缓存合理设置缓存过期时间考虑多级缓存架构我在实际项目中发现将旅游产品的详情信息缓存到Redis中可以将查询性能提升10倍以上public Product getProductById(Long id) { String key product: id; String productJson redisTemplate.opsForValue().get(key); if(productJson ! null) { return JSON.parseObject(productJson, Product.class); } Product product productMapper.selectById(id); if(product ! null) { redisTemplate.opsForValue().set(key, JSON.toJSONString(product), 1, TimeUnit.HOURS); } return product; }7. 安全防护措施7.1 SQL注入防护MyBatis使用#{}参数绑定可防止SQL注入!-- 安全 -- select idselectByUsername resultTypeUser SELECT * FROM user WHERE username #{username} /select !-- 不安全 -- select idselectByUsername resultTypeUser SELECT * FROM user WHERE username ${username} /select7.2 XSS防护前端使用vue-dompurify-html过滤HTML内容import DOMPurify from dompurify const clean DOMPurify.sanitize(dirtyHtml)7.3 CSRF防护Spring Security默认启用CSRF防护对于前后端分离项目可以禁用Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); }但需要在JWT实现中加入防重放攻击机制。8. 项目扩展方向增加多语言支持i18n集成第三方登录微信、支付宝实现推荐算法基于用户行为的旅游推荐接入地图API实现景点定位开发移动端APP使用Uniapp或Flutter以地图集成示例使用高德地图APIimport AMapLoader from amap/amap-jsapi-loader AMapLoader.load({ key: your-key, version: 2.0 }).then((AMap) { const map new AMap.Map(map-container, { viewMode: 2D, zoom: 11, center: [116.397428, 39.90923] }) })这个旅游管理系统采用的技术栈组合成熟稳定社区资源丰富特别适合作为全栈开发的学习项目。我在实际开发中最大的体会是前后端分离架构虽然增加了初期的配置复杂度但带来的开发效率和可维护性提升是非常值得的。