1. 项目概述
这个电影评论网站系统采用当前主流的前后端分离架构,后端基于SpringBoot框架构建,前端使用Vue3实现,数据持久层采用MyBatis框架操作MySQL数据库。作为一个完整的全栈项目,它实现了用户注册登录、电影信息展示、评论发布、评分管理等核心功能模块。
我在实际开发中发现,这种技术组合特别适合中小型Web应用的快速开发。SpringBoot提供了完善的依赖管理和自动配置,Vue3的Composition API让前端逻辑组织更清晰,而MyBatis则兼顾了SQL灵活性和开发效率。三者配合使用,可以在保证性能的同时大幅提升开发速度。
2. 技术架构解析
2.1 后端技术栈
SpringBoot 2.7.x作为后端框架,主要处理业务逻辑和API接口。我选择这个版本是因为它在稳定性和新特性之间取得了很好的平衡。项目采用了经典的MVC分层架构:
- Controller层:处理HTTP请求,参数校验
- Service层:业务逻辑实现
- DAO层:数据访问接口
- Entity层:数据模型定义
特别值得一提的是,我在项目中使用了Spring Security来实现权限控制,通过JWT进行身份认证。这种无状态认证方式特别适合前后端分离架构。
2.2 前端技术栈
前端采用Vue3 + TypeScript的组合,使用Vite作为构建工具。相比Webpack,Vite的冷启动速度和热更新效率都有显著提升。主要技术特点包括:
- Composition API:逻辑复用更灵活
- Pinia状态管理:替代Vuex的轻量级方案
- Element Plus组件库:提供丰富的UI组件
- Axios:处理HTTP请求
在实际开发中,我发现Vue3的setup语法糖可以大幅减少模板代码量,配合TypeScript的类型检查,能有效减少运行时错误。
2.3 数据持久层
MyBatis作为ORM框架,提供了灵活的SQL编写方式。项目中采用了MyBatis-Plus扩展,它提供的通用Mapper和条件构造器可以显著减少重复代码。数据库使用MySQL 8.0,主要优化包括:
- 使用utf8mb4字符集支持完整Unicode
- 合理设计索引提高查询效率
- 事务隔离级别设置为READ COMMITTED
3. 核心功能实现
3.1 用户认证模块
用户系统采用经典的邮箱/密码注册登录方式,后端使用Spring Security的过滤器链实现安全控制。关键实现细节:
java复制// JWT认证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) {
// 解析JWT token
String token = parseJwt(request);
if (token != null && jwtUtils.validateJwtToken(token)) {
String username = jwtUtils.getUserNameFromJwtToken(token);
// 构建认证对象
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
username, null, null);
authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
}
前端使用axios的拦截器自动携带token:
javascript复制// 请求拦截器
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
3.2 电影信息管理
电影数据采用分页查询,后端使用MyBatis-Plus的分页插件:
java复制@GetMapping("/movies")
public Result listMovies(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
Page<Movie> page = new Page<>(pageNum, pageSize);
QueryWrapper<Movie> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("release_date");
return Result.success(movieService.page(page, queryWrapper));
}
前端使用Vue3的reactive实现分页状态管理:
javascript复制const pagination = reactive({
currentPage: 1,
pageSize: 10,
total: 0
})
const loadMovies = async () => {
const res = await getMovies({
pageNum: pagination.currentPage,
pageSize: pagination.pageSize
})
movieList.value = res.data.records
pagination.total = res.data.total
}
3.3 评论与评分系统
评论功能实现了多级回复,数据库设计采用邻接表模式:
sql复制CREATE TABLE `comment` (
`id` bigint NOT NULL AUTO_INCREMENT,
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`user_id` bigint NOT NULL,
`movie_id` bigint NOT NULL,
`parent_id` bigint DEFAULT NULL COMMENT '父评论ID',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_movie` (`movie_id`),
KEY `idx_parent` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
后端使用递归查询构建评论树:
java复制public List<CommentVO> buildCommentTree(List<Comment> comments) {
// 找出所有顶级评论
List<Comment> topComments = comments.stream()
.filter(c -> c.getParentId() == null)
.collect(Collectors.toList());
// 递归构建子树
return topComments.stream()
.map(c -> {
CommentVO vo = convertToVO(c);
vo.setChildren(findChildren(c.getId(), comments));
return vo;
})
.collect(Collectors.toList());
}
private List<CommentVO> findChildren(Long parentId, List<Comment> comments) {
return comments.stream()
.filter(c -> parentId.equals(c.getParentId()))
.map(c -> {
CommentVO vo = convertToVO(c);
vo.setChildren(findChildren(c.getId(), comments));
return vo;
})
.collect(Collectors.toList());
}
4. 项目部署与优化
4.1 后端部署配置
SpringBoot应用采用内嵌Tomcat服务器,生产环境建议添加以下配置:
yaml复制server:
port: 8080
tomcat:
max-threads: 200
min-spare-threads: 10
spring:
datasource:
url: jdbc:mysql://localhost:3306/movie_db?useSSL=false&serverTimezone=UTC
username: root
password: yourpassword
hikari:
maximum-pool-size: 20
connection-timeout: 30000
4.2 前端部署优化
使用Vite构建生产版本时,可以配置如下优化:
javascript复制// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
}
}
},
chunkSizeWarningLimit: 1000
}
})
4.3 性能优化实践
-
数据库查询优化:
- 为常用查询字段添加索引
- 避免SELECT *,只查询必要字段
- 使用JOIN替代多次单表查询
-
缓存策略:
java复制@Cacheable(value = "movies", key = "#id") public Movie getMovieById(Long id) { return movieMapper.selectById(id); } -
前端性能优化:
- 路由懒加载
- 图片懒加载
- 组件按需引入
5. 常见问题与解决方案
5.1 跨域问题处理
前后端分离项目常见的跨域问题,可以通过配置解决:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
5.2 接口版本管理
随着项目迭代,接口版本管理变得重要。我采用URL路径版本控制:
java复制@RestController
@RequestMapping("/api/v1/movies")
public class MovieControllerV1 {
// v1接口实现
}
@RestController
@RequestMapping("/api/v2/movies")
public class MovieControllerV2 {
// v2接口实现
}
5.3 数据一致性保障
对于评论和评分这类需要保证数据一致性的操作,使用Spring事务管理:
java复制@Transactional
public void addComment(CommentDTO commentDTO) {
// 保存评论
commentMapper.insert(comment);
// 更新电影评论数
movieMapper.updateCommentCount(comment.getMovieId(), 1);
// 其他业务操作...
}
6. 项目扩展方向
基于现有系统,可以考虑以下扩展:
-
推荐系统集成:
- 基于用户行为的协同过滤
- 基于内容的推荐算法
-
社交功能增强:
- 用户关注系统
- 私信功能
-
数据分析模块:
- 电影评分趋势分析
- 用户行为分析
-
微服务化改造:
- 将用户服务、电影服务、评论服务拆分
- 引入Spring Cloud组件
在实际开发过程中,我特别建议做好单元测试和接口文档。使用Swagger可以自动生成API文档:
java复制@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.movie"))
.paths(PathSelectors.any())
.build();
}
}
对于前端项目,可以考虑使用Mock.js在开发阶段模拟接口数据,这样前后端可以并行开发。我在项目中配置了这样的开发环境,大大提高了团队协作效率。