1. 项目概述
这个基于SpringBoot+Vue的旅游网系统是一个典型的前后端分离架构毕业设计项目,我去年指导过3个类似案例。这类系统本质上是通过技术栈组合解决旅游行业的信息展示与交易需求,特别适合计算机专业学生展示全栈开发能力。
从技术实现角度看,系统包含三个关键模块:后端服务(SpringBoot+MyBatis)、前端界面(Vue+ElementUI)和数据库(MySQL)。这种架构选择既符合当前企业主流技术栈,又能覆盖毕业设计要求的核心技术点。我见过不少同学在这个项目上踩坑,主要集中在跨域配置、JWT鉴权和前后端数据联调这几个环节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7.x是当前最稳定的选择(避免直接用3.0+版本可能出现的兼容性问题)。实际开发中需要特别注意:
- 用spring-boot-starter-web处理HTTP请求
- 通过spring-boot-starter-aop做日志切面
- 使用MyBatis-Plus 3.5.x简化DAO层开发
数据库设计建议采用MySQL 8.0,主要表包括:
sql复制CREATE TABLE `scenic_spot` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT '景点名称',
`location` varchar(255) NOT NULL COMMENT '地理位置',
`description` text COMMENT '景点描述',
`price` decimal(10,2) DEFAULT '0.00' COMMENT '门票价格',
`image_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 前端技术方案
Vue 3.x + Element Plus是目前最成熟的组合。需要注意:
- 使用vue-router处理路由跳转
- 通过axios封装HTTP请求
- 采用Vuex/Pinia做状态管理
典型景点列表组件实现:
vue复制<template>
<el-table :data="spots" style="width: 100%">
<el-table-column prop="name" label="景点名称" width="180" />
<el-table-column prop="location" label="地理位置" />
<el-table-column prop="price" label="价格" />
<el-table-column label="操作">
<template #default="scope">
<el-button @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script setup>
import { ref } from 'vue'
const spots = ref([])
const handleDetail = (row) => {
// 跳转详情页逻辑
}
</script>
3. 核心功能实现
3.1 用户认证模块
采用JWT+Redis方案最稳妥:
- 用户登录后生成token
- 将token存入Redis并设置过期时间
- 通过拦截器验证token有效性
SpringSecurity配置示例:
java复制@Configuration
@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()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
3.2 景点搜索功能
Elasticsearch是最佳选择,但考虑到毕业设计复杂度,可以先用MySQL全文检索:
java复制@Mapper
public interface ScenicSpotMapper {
@Select("SELECT * FROM scenic_spot WHERE MATCH(name,description) AGAINST(#{keyword})")
List<ScenicSpot> searchByKeyword(String keyword);
}
前端实现搜索建议:
javascript复制const search = debounce(async (query) => {
if (!query) return
const res = await axios.get('/api/spots/search', { params: { keyword: query } })
suggestions.value = res.data
}, 300)
4. 项目部署方案
4.1 开发环境配置
- JDK 17 + IntelliJ IDEA
- Node.js 16.x + VS Code
- MySQL 8.0 + Redis 6.x
4.2 生产环境部署
推荐Docker Compose方案:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./mysql-data:/var/lib/mysql
redis:
image: redis:6-alpine
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
5. 常见问题解决方案
5.1 跨域问题
后端配置CORS:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
5.2 文件上传
使用阿里云OSS示例:
java复制public String uploadToOSS(MultipartFile file) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
String fileName = UUID.randomUUID() + file.getOriginalFilename();
ossClient.putObject(bucketName, fileName, file.getInputStream());
return "https://" + bucketName + "." + endpoint + "/" + fileName;
} finally {
ossClient.shutdown();
}
}
5.3 支付接口集成
支付宝沙箱接入:
java复制public String createOrder(Order order) {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipaydev.com/gateway.do",
APP_ID,
APP_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2");
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl("http://yourdomain.com/return");
request.setNotifyUrl("http://yourdomain.com/notify");
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", order.getOrderNo());
bizContent.put("total_amount", order.getAmount());
bizContent.put("subject", "景点门票购买");
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
request.setBizContent(bizContent.toString());
return alipayClient.pageExecute(request).getBody();
}
6. 项目优化建议
- 接口性能监控:集成Spring Boot Actuator
properties复制management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
- 前端性能优化:
- 使用vue-lazyload实现图片懒加载
- 配置Webpack分包策略
- 启用Gzip压缩
- 安全加固:
- 定期更换JWT密钥
- SQL注入防护:MyBatis使用#{}占位符
- XSS防护:前端使用DOMPurify过滤
- 扩展功能:
- 微信小程序端(Uniapp方案)
- 推荐算法(基于用户行为的协同过滤)
- 数据可视化(ECharts集成)
这个项目最难的部分其实是前后端协作开发,建议先用Postman测试所有接口,再对接前端。数据库设计要预留扩展字段,我见过太多因为字段不足导致后期大改的情况。如果时间允许,可以尝试加入Redis缓存热门景点数据,这会是答辩时的亮点。
