ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

电影在线观看系统Java毕设:SSM+JSP+Layui全流程开发实战

电影在线观看系统Java毕设:SSM+JSP+Layui全流程开发实战 简介资源为基于 Java SSM 体系开发的电影在线观看系统完整项目适合正在学习 SSM 整合、JSP 前端交互及 Maven 项目构建的 Java 初学者也便于课程设计或毕业设计参考。项目采用 JSP Spring SpringMVC MyBatis Layui 技术栈涵盖用户与视频管理、播放历史记录等常见业务模块代码分层清晰可直接导入 Eclipse、IntelliJ IDEA 等开发工具运行。资源包共 322 个文件以 Java 源码、JSP 页面、Mapper 映射 XML、JS 与 CSS 样式文件为主同时包含数据库 SQL 脚本和项目配置文件压缩包整体约 4.32MB轻量易下载。已有 551 人学习使用。通过学习这份项目源码和目录结构可以直观理解 SSM 框架的后台接口、前端页面与数据库表之间的调用关系掌握视频信息展示、在线播放、历史记录等功能的实现思路适合结合源码逐段调试提升 Java Web 项目实战能力。1. 拿到“电影在线观看系统”这个 Java 毕设题第一步不是写代码每年这个时候都会有一批人被“电影在线观看系统”这类标题卡住。它不是前后端分离项目不搞微服务也不是 Spring Boot 全家桶而是一套非常典型的传统 Java Web 项目SSM 框架做后端、JSP 做页面渲染、Layui 解决管理后台的界面问题、Maven 管理依赖、MySQL 存数据。这套组合在高校毕业设计里占了很大比例能覆盖 Spring IOC、SpringMVC 请求流转、MyBatis 持久层操作、JSP 标签库和 jQuery 生态这些必考知识点数据库设计也有足够的扩展空间让你写“创新点”。很多人拿到这个标题后第一反应是到处找源码包然后发现要么依赖跑不起来要么 MySQL 版本不匹配要么 Layui 表格一直是“加载中”。我的建议是反着来先别急着找现成代码拿一张纸把这个系统涉及的实体、页面、请求路径拆出来你会发现它本质上就是一个“用户浏览电影 管理员维护数据”的 CURD 系统难点全在 SSM 整合、参数传递和 Layui 表格对接 JSON 格式这些细节上。这篇文章就是按这个思路写的从搭建环境、设计表结构到打通一条完整的“列表查询”链路最后把最容易翻车的坑一次说清楚。2. 拆解技术栈SSM、JSP、Layui、Maven、MySQL 在这个项目里各管哪一段2.1 SSM 不是框架而是“三段式”谁管请求、谁管业务、谁管数据库SSM 是 SSM 框架的缩写具体指 Spring、SpringMVC、MyBatis。在电影在线观看系统里它们的分工非常明确Spring 负责管理对象也就是 Service 和 Mapper 这些 Bean 的创建与注入SpringMVC 负责接收浏览器过来的 HTTP 请求把 URL 映射到 Controller 方法上再返回 JSP 页面或 JSON 数据MyBatis 负责把 Java 方法和 SQL 语句绑定起来处理数据库的增删改查。新手最容易搞混的是 MyBatis 和 MySQL 的关系。MySQL 是数据库本身存电影信息、用户账号这些数据MyBatis 是 Java 程序访问 MySQL 的一座桥。没有 MyBatis 你也可以用 JDBC 写 SQL但代码量会翻好几倍。在这个项目里MyBatis 的主要工作量集中在写 Mapper 接口、Mapper XML 和 resultMap 映射这三块。这套组合的业务流转顺序是浏览器发起请求 → SpringMVC 的 DispatcherServlet 根据注解找到 Controller 方法 → Controller 调用 Service 层接口 → Service 实现类通过 Mapper 接口访问数据库 → 结果逐层返回。如果你之前只学过 Servlet理解 SSM 的关键是接受“约定优于配置”这件事接口名、XML 路径、注解扫描包名有一处对不上启动时直接报错。2.2 JSP 在这个项目里不是“过时技术”而是渲染层的主力JSP 在电影在线观看系统的角色是“视图层”。用户浏览电影列表、点进详情、登录注册、管理员管理电影这些页面全由 JSP 输出。它的特点是服务端渲染Java 代码和 HTML 可以混写配合 JSTL 标签库实现循环和条件判断不用像前后端分离项目那样必须依赖 Ajax 拼 HTML。使用 JSP 的核心注意点是路径问题。项目里的 JSP 文件一般放在两个地方webapp 根目录下或者 WEB-INF 目录下。WEB-INF 下的页面不能通过 URL 直接访问必须经过 Controller 转发才能打开。这个机制很适合做管理员后台防止用户猜路径直接打开一个没有鉴权的修改页面。前台展示页面则可以放在 webapp 根目录下方便直接访问和跳转。视图解析器配置通常是前缀/WEB-INF/views/、后缀.jspController 返回字符串movie/list就会自动去渲染/WEB-INF/views/movie/list.jsp。另外JSP 页面顶部必须写pageEncoding和contentType的编码声明否则中文片名在页面上会变成问号。% page contentTypetext/html;charsetUTF-8 languagejava %这行代码在传统 JSP 项目里是保命符。我见过太多“数据库中文正常但页面乱码”的情况最后查出来是 JSP 页面缺了这个声明或者 Tomcat 的 URIEncoding 没设置成 UTF-8。2.3 Layui 解决的是“后台界面怎么做才像样”的问题Layui 是一套基于 jQuery 的前端 UI 框架它的定位是“面向后端开发者”。不需要懂 npm、webpack、Vue下载解压后把 layui.css 和 layui.js 引入页面就能用。在电影在线观看系统里Layui 最常用的模块是 table、form、layer 和 pagination。table 模块负责以表格形式展示电影数据支持分页、排序、行内操作按钮。它和后端交互的方式是 Ajax 请求要求后端返回固定的 JSON 格式{code:0,msg:,count:100,data:[...]}。这个格式是整个项目里最容易出问题的地方——Layui 对 code 字段的值要求是 0而很多同学在 Controller 里返回了业务状态码 200 或成功字符串结果表格一直转圈。form 模块负责登录、添加电影、编辑电影这些表单的渲染和提交。Layui 会对form标签内的lay-submit按钮做拦截自动收集表单数据后发起 Ajax 请求。layer 模块则用来做弹窗提示和确认框比如删除电影前弹一个“确定删除吗”。这三个模块熟悉后整个管理后台开发速度会快很多。2.4 Maven依赖管理和打包的“后悔药”Maven 在项目里的价值有两个管理依赖和完成构建。依赖管理让你不用手动下载 jar 包只需要在 pom.xml 里写dependencyMaven 会自动从仓库下载。构建功能则负责编译、打包最终生成一个可部署到 Tomcat 的 war 包。Maven 配置的重点是仓库地址。默认中央仓库下载速度在国内经常卡住需要修改settings.xml配置阿里云镜像。另一个重点是依赖版本。Spring、MyBatis、MySQL 驱动这三个组件的版本必须兼容比如 MyBatis 3.5.x 对应 mybatis-spring 2.0.xSpring 5.x 对应 JDK 8 及以上。如果你拿到一个老项目用的是 Spring 4 加 MyBatis 3.2却配了 MySQL 8 的驱动连接池初始化时就会因为驱动类加载问题直接报错。2.5 MySQL表结构设计决定了项目能写多厚电影在线观看系统的核心表至少有五张用户表、电影表、电影类型表、评论表、收藏表。用户表和管理员表可以共用一张用 role 字段区分也可以单独建电影表是核心字段要包含标题、封面图地址、播放地址、简介、上映年份、评分、点击量、所属类型评论表关联用户和电影收藏表关联用户和电影记录收藏时间。表结构设计有一个建议电影类型不要直接存字符串而是建一张独立的类型表电影表通过type_id关联。这样后面前台做分类筛选时只需要一个where type_id ?查询管理端维护类型也方便。等你写到“XX 系统设计与实现”论文的数据表设计章节时这种规范的表结构也能直接截图用。3. 把环境先跑通MySQL、Maven、Tomcat 的配置与验证3.1 数据库连接是第一个坑URL 参数必须一次写对创建数据库和表之后第一步是配置数据源。常见做法是使用db.properties统一管理数据库配置Spring 的配置文件通过占位符读取。连接 URL 是这个项目最早的“拦路虎”不同 MySQL 版本对参数要求不同。jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/movie_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456这段配置里有三个参数决定了你能不能连上serverTimezoneAsia/Shanghai是给新版驱动用的老版本不写会报时区异常useSSLfalse是关掉 SSL 加密连接MySQL 8 默认开启 SSL但本地开发没必要不关会报 SSL 连接错误allowPublicKeyRetrievaltrue是为了解决 MySQL 8 使用 caching_sha2_password 认证插件时的公钥检索报错。如果你用的是 MySQL 5.7驱动用com.mysql.jdbc.DriverURL 里只保留characterEncodingutf8就够了。另一个容易忽略的点是characterEncodingutf8和数据库实际编码要一致。建库时执行CREATE DATABASE movie_db DEFAULT CHARACTER SET utf8mb4;保证库、表、连接三层编码统一中文才不会乱码。3.2 Maven 的 settings.xml改两处就能避免大半依赖下载问题Maven 装好后不要急着在 IDEA 里建项目先检查conf/settings.xml。需要改两处本地仓库路径和镜像地址。本地仓库默认在用户目录.m2/repository下如果你 C 盘空间紧张可以改到其他盘。镜像直接换成阿里云能避免下载依赖时卡死。localRepositoryD:/develop/maven-repository/localRepository mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror配置完成后在 IDEA 的 Maven 设置里把Maven home path、User settings file、Local repository三项都指到你的实际路径。很多依赖报“无法解析”的问题不是依赖本身不存在而是 IDEA 使用的 settings.xml 和你手动改的不是同一个。判断标准是看 IDEA 里 Maven 面板的配置路径是否显示为红色红色表示文件不存在。验证 Maven 是否可用在命令行执行mvn -v。能看到版本号、Java 版本和 Maven 仓库路径就说明配置成功。如果你想确认阿里云镜像生效执行mvn help:effective-settings查看最终生效的镜像配置。3.3 pom.xml 的核心依赖清单版本搭配不能乱SSM 项目的 pom.xml 依赖看起来多但真正核心的就那几组。以下是一份经过验证的依赖组合注意所有版本都写version不要省略否则 Maven 可能会拉取到不兼容的快照版本。properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties !-- Spring -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.20/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.20/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-jdbc/artifactId version5.3.20/version /dependency !-- MyBatis -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.10/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.29/version /dependency !-- 数据库连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.11/version /dependency !-- Servlet APITomcat 自带scope 用 provided -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency !-- JSTL 标签库 -- dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency !-- Jackson处理 JSON -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.13.3/version /dependency这套组合的版本逻辑Spring 5.3.x 配合 mybatis-spring 2.0.xMyBatis 3.5.x 支持 JDK 8MySQL 驱动 8.0.x 对应 MySQL 8 服务器Druid 连接池替代 Spring 默认的 DriverManagerDataSource生产环境下更可靠。如果你的项目是 JDK 8 且 Tomcat 是 8.5/9.x这套组合可以直接跑通。Servlet API 的 scope 设置为provided很关键因为 Tomcat 自己带了 servlet-api.jar如果这里不写 provided打包时会把 servlet-api 打进去部署到 Tomcat 后可能因为 jar 包冲突导致 JSP 里的c:if标签报错。3.4 Spring 配置文件扫描、数据源、事务、MyBatis 四个要点SSM 的 Spring 配置一般拆成两个文件applicationContext.xml和spring-mvc.xml。前者管数据源、事务、Service、Mapper后者只管 Controller 和视图解析。下面是applicationContext.xml里 MyBatis 和事务的核心配置。!-- 数据源Druid 连接池 -- bean iddataSource classcom.alibaba.druid.pool.DruidDataSource property namedriverClassName value${jdbc.driver}/ property nameurl value${jdbc.url}/ property nameusername value${jdbc.username}/ property namepassword value${jdbc.password}/ /bean !-- SqlSessionFactory把 Mapper XML 的位置告诉 MyBatis -- bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath:mapper/*.xml/ property nametypeAliasesPackage valuecom.movie.entity/ /bean !-- Mapper 接口扫描把每个 Mapper 接口注册成 Bean -- bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.movie.mapper/ /bean !-- 事务管理器 -- bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertransactionManager/这里最需要注意的是mapperLocations的路径。它指向resources目录下的mapper/文件夹里面放的是每个 Mapper 接口对应的 XML 文件。如果你把 Mapper XML 和 Mapper 接口放在同一个包目录下而不是放在 resources 里那么classpath:mapper/*.xml会扫不到。这是“Invalid bound statement (not found)”错误最常见的原因。typeAliasesPackage可以让你在 Mapper XML 里用com.movie.entity.Movie的简单类名Movie不用每次写全限定名。basePackage则是告诉容器扫描哪个包下的接口自动生成实现代理类。Spring MVC 的配置则更简单重点是设置扫描范围和视图解析器。context:component-scan base-packagecom.movie.controller/ mvc:annotation-driven/ bean classorg.springframework.web.servlet.view.InternalResourceViewResolver property nameprefix value/WEB-INF/views// property namesuffix value.jsp/ /beanmvc:annotation-driven负责注册 JSON 消息转换器这样 Controller 方法上加了ResponseBody才能返回 JSON 给 Layui。缺少这行配置时接口返回的不是 JSON 而是字符串Layui 表格会解析失败。视图解析器的 prefix 和 suffix 决定了 Controller 返回的字符串如何定位到具体的 JSP 文件。4. 从建表到跑通“电影列表”数据库、Mapper、Service、Controller、Layui 一条链路4.1 数据库脚本电影表的字段设计兼顾展示和检索电影表是整个系统的核心。字段设计时要同时考虑前台展示需要哪些数据、后台管理需要哪些字段、论文里能画出什么样的 E-R 图三个维度。以下 SQL 可以在 MySQL 8 下直接执行。DROP TABLE IF EXISTS movie; CREATE TABLE movie ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL COMMENT 电影名称, cover varchar(255) DEFAULT NULL COMMENT 封面图URL, video_url varchar(255) DEFAULT NULL COMMENT 播放地址, type_id int(11) DEFAULT NULL COMMENT 所属类型ID, description text COMMENT 剧情简介, rating decimal(3,1) DEFAULT 0.0 COMMENT 评分如8.7, release_year varchar(20) DEFAULT NULL COMMENT 上映年份, play_count int(11) DEFAULT 0 COMMENT 播放次数, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 录入时间, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT电影信息表;type_id用 int 而不是 varchar是因为它要关联到类型表的主键。rating用 decimal(3,1) 而不是 float是为了避免浮点数比较的精度问题前端展示“8.7 分”也够用。play_count是点击量字段后面做“热门电影排行”直接按它排序。description用 text 类型因为电影简介可能很长。如果你要展示“最新上映”create_time就是排序字段。如果你想做搜索功能可以给title加一个普通索引。对于毕设项目不需要考虑复杂的索引优化保持表结构清晰即可。4.2 Mapper 接口与 XMLMyBatis 的 SQL 写成注解还是 XMLMyBatis 的 SQL 可以写在 Mapper 接口的注解里也可以写在独立的 XML 文件里。电影在线观看系统建议用 XML因为后期 SQL 变长后XML 的清晰度远高于注解而且resultMap做字段映射更灵活。接口定义如下。public interface MovieMapper { ListMovie selectList(MovieQuery query); Movie selectById(Integer id); int insert(Movie movie); int update(Movie movie); int deleteById(Integer id); int count(MovieQuery query); }对应的 XML 文件放在resources/mapper/MovieMapper.xml中。?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.movie.mapper.MovieMapper resultMap idmovieMap typeMovie id propertyid columnid/ result propertytitle columntitle/ result propertycover columncover/ result propertyvideoUrl columnvideo_url/ result propertytypeId columntype_id/ result propertydescription columndescription/ result propertyrating columnrating/ result propertyreleaseYear columnrelease_year/ result propertyplayCount columnplay_count/ result propertycreateTime columncreate_time/ /resultMap select idselectList resultMapmovieMap SELECT * FROM movie where if testkeyword ! null and keyword ! AND title LIKE CONCAT(%, #{keyword}, %) /if if testtypeId ! null AND type_id #{typeId} /if /where ORDER BY create_time DESC LIMIT #{offset}, #{pageSize} /select select idcount resultTypeint SELECT COUNT(*) FROM movie where if testkeyword ! null and keyword ! AND title LIKE CONCAT(%, #{keyword}, %) /if if testtypeId ! null AND type_id #{typeId} /if /where /select insert idinsert parameterTypeMovie useGeneratedKeystrue keyPropertyid INSERT INTO movie (title, cover, video_url, type_id, description, rating, release_year) VALUES (#{title}, #{cover}, #{videoUrl}, #{typeId}, #{description}, #{rating}, #{releaseYear}) /insert delete iddeleteById parameterTypeint DELETE FROM movie WHERE id #{id} /delete /mapper这段 XML 里有三个细节值得注意。第一where标签解决了动态 SQL 的问题keyword 为空时不会生成多余的AND连接。第二LIKE CONCAT(%, #{keyword}, %)使用 CONCAT 拼接而不是写成%${keyword}%。${}是字符串拼接存在 SQL 注入风险#{}是预编译参数更安全。很多同学的搜索功能报错或产生注入漏洞就是在这里用了${}。第三LIMIT #{offset}, #{pageSize}是分页的基础offset 由前端页号和 pageSize 计算得来。4.3 Service 层与分页为什么需要 PageResult 这种“半成品”Service 层在 Controller 和 Mapper 之间加了一层。它的价值在于事务控制和业务逻辑复用。比如添加电影时需要同时往 movie 表插入记录、更新类型表的数量这两个操作必须在同一个事务里Service 层的Transactional注解就能保证要么全成功要么全失败。分页查询是列表页的核心需求。Layui 表格每次请求会带page和limit两个参数后端需要返回总数和当前页数据。我一般会定义一个PageResult类统一封装分页结果。public class PageResultT { private Integer code; // 状态码0 表示成功 private String msg; // 提示信息 private Long count; // 总记录数 private ListT data; // 当前页数据 public static T PageResultT success(Long count, ListT data) { PageResultT result new PageResult(); result.code 0; result.msg ; result.count count; result.data data; return result; } }这个类的code、msg、count、data四个字段严格按照 Layui table 的接口规范设计。Service 层查询时需要先调用count方法获取总数再调用selectList获取当前页数据两条 SQL 合在一起返回PageResult。查询条件对象MovieQuery也需要一个对应设计。它包含 keyword、typeId、page、limit 四个字段其中 offset 字段可以不暴露给前端在 Service 里计算。public class MovieQuery { private String keyword; private Integer typeId; private Integer page 1; private Integer limit 10; public Integer getOffset() { return (page null || page 1 ? 1 : page - 1) * (limit null ? 10 : limit); } }getOffset()的写法规避了空指针和负数页号问题。前端传page1时 offset 为 0传page2时 offset 为 10正好对应 MySQL 的LIMIT 0, 10和LIMIT 10, 10。这里不需要 PageHelper 插件因为只有一张表的主表查询手写分页更直观也方便在论文里讲清楚原理。4.4 Controller返回视图还是返回 JSON由方法决定Controller 层有两种返回方式。浏览电影页面用“返回视图”用户点开/movie/list时服务端渲染 JSP 并返回 HTML管理员后台的表格数据用“返回 JSON”前端 Layui 表格通过 Ajax 请求拿到数据后用 JS 渲染。这两种模式在 SSM 项目里经常同时存在。Controller RequestMapping(/movie) public class MovieController { Autowired private MovieService movieService; GetMapping(/list) public String listPage() { return movie/list; } ResponseBody GetMapping(/data) public PageResultMovie data(MovieQuery query) { Long count movieService.count(query); ListMovie list movieService.selectList(query); return PageResult.success(count, list); } ResponseBody GetMapping(/detail) public Movie detail(Integer id) { return movieService.selectById(id); } }listPage方法没有ResponseBody注解返回的字符串会被视图解析器拼成/WEB-INF/views/movie/list.jsp路径渲染成完整的 HTML 页面。data方法加了ResponseBody返回的PageResult对象会被 Jackson 序列化成 JSON交给 Layui 的 table 模块处理。这里有个需要提前设定的细节如果项目使用的是 Spring 4.2 以下版本GetMapping注解不可用需要换成RequestMapping(value/data, methodRequestMethod.GET)。当前这套写法以 Spring 5 为准如果你手头的项目是更老的版本注意调整。4.5 前端页面Layui 表格如何对接后端 JSON 接口电影列表页先由 JSP 输出一个div容器然后 Layui 的 table 模块负责渲染。页面只需引入 Layui 的 CSS 和 JS 文件不用手写table标签因为 Layui 表格是动态生成的。% page contentTypetext/html;charsetUTF-8 languagejava % html head title电影管理/title link relstylesheet href${pageContext.request.contextPath}/static/layui/css/layui.css /head body div classlayui-container table idmovieTable lay-filtermovieTable/table /div script src${pageContext.request.contextPath}/static/layui/layui.js/script script layui.use([table, form], function () { var table layui.table; table.render({ elem: #movieTable, url: ${pageContext.request.contextPath}/movie/data, page: true, limit: 10, cols: [[ {field: id, title: ID, width: 60}, {field: title, title: 电影名称, width: 200}, {field: rating, title: 评分, width: 90}, {field: releaseYear, title: 上映年份, width: 100}, {field: playCount, title: 播放次数, width: 100} ]] }); }); /script /body /htmlLayui 表格渲染的核心是table.render里指定了elem、url和cols。elem是表格挂载点的选择器url是数据接口地址cols定义了每一列的字段名和表头。字段名必须和 JSON 中data数组里每个对象的 key 一致。比如后端Movie实体里有releaseYear属性JSON 里的 key 就是releaseYearcols里的field就必须写releaseYear。这里有一个非常典型的坑如果你后端的实体属性命名不规范比如把release_year映射成了releaseyear而不是releaseYearLayui 表格里这一列就会显示为空。所以 MyBatis 的 resultMap 里的 property 必须和实体类字段严格同名。5. SSM 项目避坑指南5 个高频翻车场景与解决办法5.1 Maven 依赖下载慢、导入项目后 pom.xml 一直报错现象新建项目后 IDEA 右下角一直提示下载依赖半小时后依然卡住或者 pom.xml 里部分依赖下面出现红色波浪线提示无法解析。原因Maven 默认使用中央仓库国内访问速度极不稳定。另一个常见原因是本地仓库里曾经下载过损坏的lastUpdated文件Maven 检查到存在这个文件后不会再重新下载。还有可能是 IDEA 里配置的 settings.xml 路径不对你修改的文件根本没生效。解决按本文 3.2 节配置阿里云镜像。如果修改后还是报错打开本地仓库目录删除所有*.lastUpdated结尾的文件再在 IDEA 里执行 Maven 面板的“Reimport”。最彻底的验证方式是在命令行先跑一次mvn clean compile如果命令行能过而 IDEA 不能过问题一定出在 IDEA 的 Maven 配置路径指向了不同的 settings.xml。在 Maven 阿里云镜像这里多花几分钟能省去整周的烦躁。5.2 Invalid bound statement (not found)Mapper 接口和 XML 对不上现象Tomcat 启动成功后访问接口控制台抛出org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.movie.mapper.MovieMapper.selectList。原因MyBatis 的 SqlSessionFactoryBean 没有扫描到 Mapper XML 文件或者扫描到了但 namespace 与接口全限定名不一致。最常见的原因是 XML 文件没有放在mapperLocations配置的路径下比如你的 XML 在com.movie.mapper包下但配置写的是classpath:mapper/*.xml。解决先检查target/classes/mapper/目录下有没有编译后的 XML 文件。如果没有说明 XML 没有被 Maven 打包进去需要在 pom.xml 里配置 resource 目录或者直接把 XML 移到src/main/resources/mapper/下。如果文件存在则打开 XML 检查namespace是否与接口全限定名完全一致包括大小写。这个问题排查时速度快慢的差别在于是否先看编译输出目录而不是在代码里反复翻找。5.3 MySQL 连接报 SSL 错误或时区异常现象Tomcat 启动时日志出现Cannot create PoolableConnectionFactoryCaused by 指向CLIENT_PLUGIN_AUTH或Server returns invalid timezone。或者数据库连接能成功但执行查询时报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。原因MySQL 8 驱动com.mysql.cj.jdbc.Driver对连接参数有额外要求。时区参数缺失会导致驱动无法识别数据库服务器的默认时区useSSL 参数缺失时驱动会尝试建立 SSL 连接本地未配置 SSL 证书时直接失败。解决按 3.1 节的 URL 格式把serverTimezoneAsia/ShanghaiuseSSLfalse补上。如果你的 MySQL 服务器时区配置特殊可以把serverTimezone改为GMT%2B8或UTC。还有一点顺便提醒MySQL 8 默认认证插件是caching_sha2_password如果连接报Public Key Retrieval is not allowed在 URL 末尾加allowPublicKeyRetrievaltrue即可。5.4 Layui 表格一直转圈但接口返回正常现象页面能打开表格区域显示“加载中”永远不结束用浏览器直接访问/movie/data接口能看到 JSON 数据但页面就是不渲染。原因Layui table 的url请求返回的 JSON 格式不符合规范。它要求外层必须有code字段且值为 0data字段必须是数组。你有三种写法会导致失败只返回了ListMovie而不是PageResultcode值写成了 200data不是数组而是对象。解决统一使用PageResult.success(count, list)作为接口返回值。检查 JSON 里的 key 是否是code、count、data三个英文单词不要换成中文或别名。如果你用的是 Spring MVC 并且已经配置了mvc:annotation-driven序列化会自动完成如果没有配置控制器返回对象时会报 406 错误页面上表现为数据格式解析失败。遇到这个情况时可以先用浏览器直接访问接口地址确认返回 JSON 的真实结构再反向调整代码比在页面里反复刷新有效得多。5.5 JSP 页面部署到 Tomcat 后中文乱码或找不到标签现象本地 IDEA 里运行页面正常打成 war 包部署到独立的 Tomcat 后页面中文变成问号或者提示找不到 JSTL 标签的taglib声明。原因IDEA 内置 Tomcat 和独立 Tomcat 的 URI 编码配置不一致。Apache Tomcat 默认的 URI 编码是 ISO-8859-1如果 URL 中携带中文参数接收方解析出的就是乱码。JSTL 标签报错则是jstl.jar未被打入 war 包因为依赖 scope 配置错误或者打包时被排除了。解决修改 Tomcat 的conf/server.xml在 Connector 节点添加URIEncodingUTF-8。JSTL 问题检查 pom.xml 中jstl依赖的 scope去掉provided让它打进 war 包。更稳妥的做法是确保所有 JSP 页面第一行都写了pageEncodingUTF-8。如果你在代码里用了request.setCharacterEncoding(UTF-8)也要加上因为 Servlet 默认的请求编码不是 UTF-8。乱码问题的本质是编码链路长每一环都要统一这条路没有任何捷径可走。6. 部署验证与进阶用日志和压测确认项目“真的能上线”项目跑通后的第一件事不是继续加功能而是做一次完整的验证。验证分三个层次接口功能、SQL 执行效率、部署后的稳定性。接口功能验证我用的是最笨但也最有效的方式先启动 Tomcat再用浏览器开发者工具逐个看接口的请求和响应。重点看三个地方/movie/data接口的响应体是否符合 Layui 格式/movie/detail接口在传入不存在 id 时是否返回空对象或报错登录接口在密码错误时是否返回友好提示。响应时间超过 300ms 的接口逐个检查 SQL 是不是漏了条件或忘了加索引。SQL 效率验证需要打开 MyBatis 的日志输出。在applicationContext.xml里加一个 log4j 配置把 Mapper 接口的日志级别设为 DEBUG。log4j.rootLoggerINFO, stdout log4j.logger.com.movie.mapperDEBUG log4j.appender.stdoutorg.apache.log4j.ConsoleAppender log4j.appender.stdout.TargetSystem.out log4j.appender.stdout.layoutorg.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern%d{HH:mm:ss} [%p] %m%n配置生效后访问/movie/data时控制台会打印完整 SQL 和查询参数。这时你能直观看到 MyBatis 执行的是SELECT * FROM movie LIMIT 0, 10而不是一条带无关条件的错误 SQL。对于点击量字段play_count在用户每次打开播放页时更新一次。更新时用UPDATE movie SET play_count play_count 1 WHERE id ?不要先查再改这样就不会出现并发下的数据不一致。部署验证的核心是打 war 包而不是直接拷文件夹。在 IDEA Maven 面板执行clean package然后到target/目录找到movie.war。把 war 包丢进 Tomcat 的webapps/后启动Tomcat 会自动解压。此时你遇到的 JSP 编译、jar 冲突等问题都要在标准 Tomcat 环境下解决。这也顺带回答了很多人的疑问传统 JSP 项目部署时不需要 Nginx 参与Tomcat 本身就是 Web 服务器兼 JSP 容器Nginx 的 HTTP 转发优势在这个项目里没有用武之地。进阶方面我一般还会给项目加一个小功能来体现思考深度而不是把基础 CRUD 写到头。比如“播放次数排行榜”接口SELECT id, title, play_count FROM movie ORDER BY play_count DESC LIMIT 10前台首页展示一个 Top10 列表。功能不大但涉及排序、限量查询、前端列表渲染三个知识点论文里能写的接口设计和实现部分也多了一块。如果你还想继续打磨另一个比较实用的方向是用户收藏功能在详情页加一个“收藏”按钮数据存在收藏表里用户中心展示收藏列表。这个功能考验的是多表关联查询和事务控制恰好是 SSM 框架最擅长的部分。最后分享一个我的习惯项目提交或部署前花半小时把所有 JSP 页面检查一遍看有没有硬编码的中文路径、有没有引用了不存在的静态资源。很多问题不是代码写错了而是资源路径写错导致页面样式全丢、功能按钮失效。把 Tomcat 日志和浏览器控制台的报错对照着看比在代码里盲猜快得多。希望这些经验能帮你在做电影在线观看系统这条路上少绕几个弯。本文还有配套的精品资源点击获取
返回列表