1. 项目背景与核心需求
电影评价系统作为典型的Web应用,在计算机专业毕业设计中一直保持着较高的热度。这类项目既能体现学生对Java Web全栈技术的掌握程度,又能展示实际业务场景的解决方案设计能力。基于SpringBoot框架的开发模式,已经成为当前企业级Java应用开发的事实标准。
这个毕业设计项目的核心诉求主要体现在三个层面:
- 技术验证层面:需要完整实现MVC架构、数据库交互、用户认证等基础功能
- 业务逻辑层面:要处理电影信息管理、用户评价、评分统计等核心业务流程
- 扩展性层面:需考虑接口设计规范、模块化程度等工程化要素
从技术选型来看,SpringBoot+MySQL+Tomcat的组合具有明显优势:
- SpringBoot的自动配置特性可以大幅减少XML配置
- 内嵌Tomcat简化了部署流程
- MySQL作为关系型数据库能很好支撑评价系统的数据持久化需求
2. 技术架构设计
2.1 整体架构方案
采用经典的三层架构设计:
code复制表现层:Thymeleaf模板引擎 + Bootstrap前端框架
业务层:SpringBoot 2.7.x + Spring MVC
数据层:MySQL 8.0 + MyBatis-Plus
这种架构组合具有以下特点:
- 开发效率高:MyBatis-Plus的代码生成器可自动生成基础CRUD代码
- 维护成本低:SpringBoot的starter机制统一管理依赖版本
- 性能有保障:连接池默认使用HikariCP,优于传统的DBCP
2.2 数据库设计要点
核心表结构设计建议:
sql复制CREATE TABLE `movie` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL COMMENT '电影名称',
`cover_url` varchar(255) DEFAULT NULL COMMENT '封面图URL',
`release_year` int DEFAULT NULL COMMENT '上映年份',
`director` varchar(50) DEFAULT NULL COMMENT '导演',
`description` text COMMENT '剧情简介',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT '加密密码',
`nickname` varchar(50) DEFAULT NULL COMMENT '显示昵称',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `review` (
`id` int NOT NULL AUTO_INCREMENT,
`movie_id` int NOT NULL COMMENT '关联电影ID',
`user_id` int NOT NULL COMMENT '评价用户ID',
`content` text COMMENT '评价内容',
`rating` decimal(3,1) DEFAULT NULL COMMENT '评分(0-10分)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_movie` (`movie_id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
设计注意事项:
- 密码字段需使用BCryptPasswordEncoder加密存储
- 评价表建立电影和用户的外键索引提升查询效率
- 使用utf8mb4字符集支持emoji等特殊符号
3. 核心功能实现
3.1 用户认证模块
Spring Security配置示例:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**","/js/**","/images/**").permitAll()
.antMatchers("/register","/login").anonymous()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
}
关键实现细节:
- 使用BCrypt加密算法存储密码,避免明文存储风险
- 静态资源放行配置要放在权限控制前面
- 登录成功后的跳转URL需要根据业务需求调整
3.2 电影评价功能
Controller层典型实现:
java复制@Controller
@RequestMapping("/movie")
public class MovieController {
@Autowired
private MovieService movieService;
@GetMapping("/{id}")
public String detail(@PathVariable Integer id, Model model) {
Movie movie = movieService.getById(id);
List<Review> reviews = movieService.getReviews(id);
// 计算平均分
Double avgRating = reviews.stream()
.mapToDouble(Review::getRating)
.average()
.orElse(0.0);
model.addAttribute("movie", movie);
model.addAttribute("reviews", reviews);
model.addAttribute("avgRating", String.format("%.1f", avgRating));
return "movie/detail";
}
@PostMapping("/{id}/review")
public String submitReview(@PathVariable Integer id,
@Valid ReviewForm form,
BindingResult result,
Principal principal) {
if (result.hasErrors()) {
return "redirect:/movie/" + id + "?error=1";
}
String username = principal.getName();
movieService.addReview(id, username, form);
return "redirect:/movie/" + id;
}
}
业务逻辑要点:
- 使用Java 8 Stream API计算平均分更简洁
- Principal对象自动注入获取当前用户信息
- 表单验证使用@Valid注解配合BindingResult处理
4. 项目优化与扩展
4.1 性能优化方案
- 缓存策略实现:
java复制@Service
@CacheConfig(cacheNames = "movieCache")
public class MovieServiceImpl implements MovieService {
@Cacheable(key = "'movie_' + #id")
public Movie getById(Integer id) {
return baseMapper.selectById(id);
}
@CacheEvict(key = "'movie_' + #id")
public void updateMovie(Movie movie) {
baseMapper.updateById(movie);
}
}
- 分页查询优化:
java复制@GetMapping("")
public String list(@RequestParam(defaultValue = "1") Integer page,
Model model) {
Page<Movie> pageInfo = new Page<>(page, 10);
IPage<Movie> moviePage = movieService.page(pageInfo);
model.addAttribute("pageInfo", moviePage);
return "movie/list";
}
4.2 扩展功能建议
- 电影推荐算法:
java复制public List<Movie> recommendMovies(Integer userId) {
// 基于用户历史评价的协同过滤
List<Review> userReviews = reviewMapper.selectByUser(userId);
// 获取相似用户的评价记录
List<Integer> similarUsers = findSimilarUsers(userId);
List<Review> similarReviews = reviewMapper.selectByUsers(similarUsers);
// 实现推荐逻辑
return recommendEngine.generate(userReviews, similarReviews);
}
- 接入第三方API:
java复制@RestController
@RequestMapping("/api/tmdb")
public class TMDBController {
@Value("${tmdb.api.key}")
private String apiKey;
@GetMapping("/search")
public ResponseEntity<String> searchMovie(@RequestParam String query) {
RestTemplate restTemplate = new RestTemplate();
String url = String.format(
"https://api.themoviedb.org/3/search/movie?api_key=%s&query=%s",
apiKey, query);
return restTemplate.getForEntity(url, String.class);
}
}
5. 常见问题解决方案
5.1 开发环境问题
- Lombok插件不生效:
确保IDEA安装Lombok插件并在设置中启用注解处理
在pom.xml中添加依赖:
xml复制<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- Tomcat启动端口冲突:
properties复制# application.properties
server.port=8081
server.tomcat.uri-encoding=UTF-8
5.2 生产环境部署
- 内存配置优化:
bash复制# 启动脚本增加JVM参数
java -Xms512m -Xmx1024m -jar movie-review.jar
- 数据库连接池配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
6. 毕业设计答辩要点
- 技术亮点阐述:
- 采用SpringBoot Starter机制简化配置
- 使用MyBatis-Plus提升开发效率
- 实现前后端适度的分离架构
- 业务逻辑演示重点:
- 用户注册登录流程
- 电影评价提交与显示
- 评分统计计算逻辑
- 项目改进方向:
- 引入Redis缓存热门电影数据
- 增加Elasticsearch实现全文检索
- 开发微信小程序端适配移动场景
