1. 项目背景与技术选型
去年帮学弟做毕业设计时,我们选择了旅游网站这个方向。当时市面上大多数教学项目都是简单的CMS系统或电商平台,而旅游网站既有业务复杂度又能体现前后端分离架构的优势。Spring Boot和Vue的组合完美契合这个需求——Spring Boot的约定优于配置特性让后端开发效率极高,Vue的组件化开发则让前端交互变得优雅。
这个项目最核心的价值在于:
- 完整实现了旅游产品展示、订单管理、用户中心等业务模块
- 采用RESTful API规范进行前后端通信
- 使用JWT实现无状态认证
- 数据库设计考虑了旅游业务特有的多表关联关系
技术选型时特别注意:Spring Boot 2.7.x与Vue 2.6.x的版本兼容性,这是经过多个项目验证的稳定组合。最新版反而可能存在隐性问题。
2. 系统架构设计
2.1 后端架构
采用经典的三层架构:
code复制controller → service → dao
↑
Spring Security
↑
JPA + QueryDSL
关键配置示例(application.yml):
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/tourism?useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: update
2.2 前端架构
Vue项目结构设计:
code复制src/
├── api/ # 接口封装
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── utils/ # 工具类
└── views/ # 页面组件
3. 核心功能实现
3.1 旅游产品模块
采用JPA实现的多表关联查询:
java复制@Entity
public class TourProduct {
@Id
@GeneratedValue
private Long id;
private String title;
private BigDecimal price;
@OneToMany(mappedBy = "product")
private List<TourImage> images;
@ManyToOne
private Category category;
}
前端使用Element UI实现卡片式展示:
vue复制<el-row :gutter="20">
<el-col
v-for="item in products"
:key="item.id"
:span="6">
<product-card :data="item"/>
</el-col>
</el-row>
3.2 订单支付流程
典型的分布式事务场景:
- 创建订单(订单服务)
- 扣减库存(库存服务)
- 支付处理(支付服务)
使用Spring的@Transactional注解保证原子性:
java复制@Transactional
public Order createOrder(OrderDTO dto) {
// 1. 校验库存
stockService.reduce(dto.getProductId(), dto.getQuantity());
// 2. 生成订单
Order order = convertToOrder(dto);
orderRepository.save(order);
// 3. 调用支付
paymentService.createPayment(order);
return order;
}
4. 关键技术难点解决方案
4.1 图片上传与存储
采用阿里云OSS的方案:
java复制public String upload(MultipartFile file) {
String fileName = UUID.randomUUID() + getExtension(file);
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
ossClient.putObject(bucketName, fileName, file.getInputStream());
return "https://" + bucketName + "." + endpoint + "/" + fileName;
} finally {
ossClient.shutdown();
}
}
前端配合使用vue-upload-component:
vue复制<file-upload
v-model="files"
post-action="/api/upload"
@input-file="onInputFile">
</file-upload>
4.2 高并发场景优化
使用Redis缓存热门旅游产品:
java复制@Cacheable(value = "products", key = "#id")
public Product getById(Long id) {
return productRepository.findById(id).orElseThrow();
}
配合Spring Cache抽象层:
java复制@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// ...其他配置
return template;
}
}
5. 数据库设计要点
5.1 主要表结构
sql复制CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `tour_product` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`price` decimal(10,2) NOT NULL,
`stock` int NOT NULL,
`category_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL,
`user_id` bigint NOT NULL,
`total_amount` decimal(10,2) NOT NULL,
`status` tinyint NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
5.2 索引优化建议
- 订单表的user_id和order_no需要建立索引
- 旅游产品的category_id需要外键索引
- 联合索引遵循最左前缀原则
6. 部署与上线
6.1 后端部署
使用Docker容器化:
dockerfile复制FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/tourism-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
启动命令:
bash复制docker build -t tourism-backend .
docker run -d -p 8080:8080 --name tourism tourism-backend
6.2 前端部署
Nginx配置示例:
nginx复制server {
listen 80;
server_name www.yourdomain.com;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
}
}
7. 常见问题排查
7.1 跨域问题
解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
7.2 Vue路由刷新404
修改Nginx配置:
nginx复制location / {
try_files $uri $uri/ /index.html;
}
7.3 数据库连接池耗尽
调整Spring Boot配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
8. 项目扩展建议
- 增加ELK日志分析系统
- 集成第三方登录(微信、支付宝)
- 实现分布式架构(Spring Cloud)
- 添加智能推荐算法
- 开发微信小程序端
实际开发中发现,旅游产品的搜索功能最容易成为性能瓶颈。后来我们采用Elasticsearch重构搜索模块,查询性能提升了10倍以上。具体实现是在Spring Boot中集成ElasticsearchRepository:
java复制public interface ProductSearchRepository extends
ElasticsearchRepository<EsProduct, Long> {
List<EsProduct> findByTitleOrDescription(String title, String description);
}
这个毕业设计项目最值得骄傲的是,学弟在答辩时现场演示了系统的全流程操作,从用户注册、产品浏览到下单支付一气呵成,最终获得了优秀毕业设计的评价。整个项目从技术选型到最终上线,踩过的坑和积累的经验,都是教科书上学不到的实战财富。
