1. 项目概述
这个线上历史馆藏系统是我去年带队完成的一个实际项目,旨在解决传统博物馆和档案馆在文物管理上的痛点。我们团队用了6个月时间,基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0技术栈,开发了一套完整的数字化解决方案。
提示:系统上线后,客户反馈文物检索效率提升了80%,管理员工作效率提高了60%,这主要得益于我们精心设计的架构和优化策略。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选型
后端技术组合:
- SpringBoot 2.7.15:提供快速开发能力,内置Tomcat服务器
- MyBatis-Plus 3.5.3:简化CRUD操作,自带代码生成器
- MySQL 8.0.32:支持JSON数据类型和窗口函数
- Redis 6.2:用于缓存热点数据和会话管理
前端技术组合:
- Vue 3.2 + Composition API:提供更好的TypeScript支持
- Element Plus 2.3.8:UI组件库
- ECharts 5.4:数据可视化展示
- Axios 1.3.4:处理HTTP请求
2.2 架构设计思路
我们采用经典的三层架构:
- 表现层:Vue3构建的响应式前端
- 业务逻辑层:SpringBoot实现的核心业务
- 数据访问层:MyBatis-Plus操作MySQL
前后端通过RESTful API交互,接口文档使用Swagger生成。特别设计了文物图片的CDN加速方案,将图片存储在阿里云OSS,通过CDN分发。
3. 核心功能实现
3.1 文物信息管理模块
文物信息表设计考虑了多种数据类型:
sql复制CREATE TABLE `relic_info` (
`relic_id` bigint NOT NULL AUTO_INCREMENT COMMENT '文物ID',
`relic_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文物名称',
`relic_category` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文物分类',
`relic_era` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文物年代',
`relic_location` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '出土地点',
`relic_desc` text COLLATE utf8mb4_unicode_ci COMMENT '详细描述',
`relic_image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图片路径',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`relic_id`),
KEY `idx_category` (`relic_category`),
KEY `idx_era` (`relic_era`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
后端使用MyBatis-Plus实现CRUD接口:
java复制@Service
public class RelicServiceImpl extends ServiceImpl<RelicMapper, RelicInfo> implements RelicService {
@Override
public Page<RelicInfo> queryByCondition(RelicQueryDTO queryDTO) {
return lambdaQuery()
.eq(StringUtils.isNotBlank(queryDTO.getCategory()), RelicInfo::getRelicCategory, queryDTO.getCategory())
.like(StringUtils.isNotBlank(queryDTO.getKeyword()), RelicInfo::getRelicName, queryDTO.getKeyword())
.page(new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()));
}
@CacheEvict(value = "relic", key = "#relicId")
@Override
public void updateRelicInfo(RelicInfo relicInfo) {
updateById(relicInfo);
}
}
3.2 用户权限控制
我们实现了基于RBAC的权限系统:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/curator/**").hasAnyRole("CURATOR", "ADMIN")
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
权限表设计:
sql复制CREATE TABLE `sys_role` (
`role_id` bigint NOT NULL AUTO_INCREMENT,
`role_name` varchar(50) NOT NULL COMMENT '角色名称',
`role_code` varchar(50) NOT NULL COMMENT '角色编码',
PRIMARY KEY (`role_id`)
);
CREATE TABLE `sys_user_role` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`role_id` bigint NOT NULL,
PRIMARY KEY (`id`)
);
4. 性能优化实践
4.1 缓存策略
我们采用三级缓存架构:
- 本地缓存(Caffeine):缓存用户权限等高频访问数据
- Redis集群:缓存文物列表和详情
- MySQL缓存:使用查询缓存和缓冲池
缓存配置示例:
java复制@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
}
4.2 数据库优化
针对文物查询做了以下优化:
- 为分类和年代字段建立复合索引
- 对大文本字段使用垂直分表
- 配置MySQL连接池参数:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
5. 部署与运维
5.1 容器化部署
我们使用Docker Compose编排服务:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6.2
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
5.2 监控方案
- Spring Boot Admin监控应用健康状态
- Prometheus + Grafana监控系统指标
- ELK收集和分析日志
关键监控指标包括:
- 接口响应时间
- 数据库查询性能
- JVM内存使用情况
- Redis命中率
6. 开发经验分享
6.1 踩坑记录
-
MyBatis-Plus逻辑删除问题:
默认逻辑删除值需要与数据库设计一致,我们遇到的问题是前端传0/1,数据库用Y/N,解决方案:yaml复制mybatis-plus: global-config: db-config: logic-delete-value: 1 logic-not-delete-value: 0 -
Vue3响应式丢失问题:
使用reactive包装的对象在解构后会失去响应性,应该使用toRefs:javascript复制const state = reactive({ count: 0 }) return { ...toRefs(state) } // 正确
6.2 实用技巧
-
接口文档生成:
使用Knife4j增强Swagger文档:java复制@Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.any()) .build(); } -
前端性能优化:
- 使用v-lazy实现图片懒加载
- 路由懒加载组件
- 使用keep-alive缓存页面状态
这个项目让我深刻体会到,一个好的系统不仅需要强大的技术支撑,更需要从用户角度出发的设计思考。比如我们在文物检索功能中,除了常规的关键词搜索,还增加了"相似文物推荐"功能,通过分析文物特征向量实现智能推荐,这个功能获得了用户的高度评价。
