这个旅游网站系统采用当前Java Web开发中最主流的全栈技术组合,前后端分离架构设计让项目具备良好的可维护性和扩展性。作为一套完整的企业级解决方案,它涵盖了旅游行业常见的产品展示、订单管理、用户中心等核心业务模块。
技术栈选择上体现了明显的"新版本优先"原则:
提示:这套技术组合特别适合需要快速迭代的中大型旅游电商项目,MyBatis-Plus的ActiveRecord模式能显著提升开发效率,而Vue3的Composition API让前端组件逻辑更清晰。
系统采用经典的四层架构:
java复制// MyBatis-Plus配置示例
@Configuration
@MapperScan("com.travel.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
javascript复制// 路由守卫示例
router.beforeEach(async (to, from) => {
const userStore = useUserStore()
if (!userStore.token && to.meta.requiresAuth) {
return { path: '/login', query: { redirect: to.fullPath } }
}
})
MySQL8.0特有的优化策略:
sql复制-- 旅游产品表DDL示例
CREATE TABLE `tour_product` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`price` decimal(10,2) NOT NULL,
`cover_url` varchar(255) DEFAULT NULL,
`tags` json DEFAULT NULL,
`detail` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
PRIMARY KEY (`id`),
FULLTEXT KEY `ft_title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
bash复制mysql -uroot -p < docs/database/travel_system.sql
bash复制mvn clean spring-boot:run
bash复制cd travel-web
npm install
npm run dev
注意:首次启动前需修改application-dev.yml中的数据库连接配置,测试支付功能需要申请支付宝沙箱账号。
采用Elasticsearch构建的搜索服务支持:
java复制// 搜索服务实现片段
public PageResult<TourProductVO> search(SearchParam param) {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 构建多条件查询
if (StringUtils.hasText(param.getKeyword())) {
queryBuilder.withQuery(QueryBuilders.multiMatchQuery(param.getKeyword(),
"title", "description"));
}
// 添加分页参数
queryBuilder.withPageable(PageRequest.of(param.getPageNum()-1, param.getPageSize()));
SearchHits<TourProduct> search = elasticsearchRestTemplate.search(
queryBuilder.build(), TourProduct.class);
// 结果转换逻辑...
}
使用RabbitMQ延迟队列实现30分钟未支付订单自动取消:
java复制rabbitTemplate.convertAndSend(
"order.delay.exchange",
"order.delay.routingkey",
orderId,
message -> {
message.getMessageProperties().setDelay(30 * 60 * 1000);
return message;
});
三级缓存体系:
缓存击穿解决方案:
java复制public ProductDetail getProductDetail(Long id) {
// 1. 查询缓存
String cacheKey = "product:" + id;
ProductDetail detail = redisTemplate.opsForValue().get(cacheKey);
if (detail != null) {
return detail;
}
// 2. 获取分布式锁
RLock lock = redissonClient.getLock("lock:product:" + id);
try {
lock.lock(10, TimeUnit.SECONDS);
// 3. 二次检查缓存
detail = redisTemplate.opsForValue().get(cacheKey);
if (detail != null) {
return detail;
}
// 4. 查询数据库
detail = productMapper.selectDetailById(id);
if (detail != null) {
// 5. 写入缓存
redisTemplate.opsForValue().set(cacheKey, detail, 30, TimeUnit.MINUTES);
}
return detail;
} finally {
lock.unlock();
}
}
javascript复制const routes = [
{
path: '/detail/:id',
component: () => import('@/views/ProductDetail.vue')
}
]
java复制http.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'");
javascript复制axios.defaults.xsrfCookieName = 'XSRF-TOKEN'
axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN'
java复制@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
javascript复制import CryptoJS from 'crypto-js'
const encryptData = (data, key) => {
return CryptoJS.AES.encrypt(JSON.stringify(data), key).toString()
}
推荐使用Docker Compose编排:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.2-alpine
ports:
- "6379:6379"
backend:
build: ./travel-server
ports:
- "8080:8080"
depends_on:
- mysql
- redis
volumes:
mysql_data:
nginx复制server {
listen 80;
server_name travel.example.com;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
gzip on;
gzip_types text/plain application/xml application/javascript;
}
location /api {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
}
}
sql复制ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
javascript复制server: {
hmr: {
overlay: false
}
}
nginx复制client_max_body_size 20M;
这套系统在实际部署时,建议根据业务规模考虑引入Spring Cloud Alibaba组件实现服务治理。对于高并发场景,可对产品详情页进行静态化处理,通过Nginx直接返回预生成的HTML片段。我在多个旅游项目中的实践表明,这种架构组合能够支撑日均10万+的访问量,且保持毫秒级的API响应速度。