简介:这份源码资源面向Java Web初学者与需要从零搭建SSM框架的开发者,基于IDEA2021、Tomcat9.0与MySQL8.0.25环境,完整演示Spring+SpringMVC+MyBatis整合过程,帮助读者理解分层架构、依赖注入与数据库映射的落地方式。压缩包共105个文件,约22.34MB,其中52个jar为框架与数据库驱动依赖,28个xml承担Spring、MyBatis及Web配置,另有java源码、jsp页面、properties配置、class编译文件等,覆盖从配置到运行的完整链路。目前已有3136人学习下载,说明该搭建流程具备一定参考价值。读者可据此获得一套可直接导入IDEA的工程结构,对照Controller、Service、Dao与实体类的组织方式,掌握SSM各层职责划分、配置文件写法及常见启动报错的排查思路,适合作为课程设计或入门练手的起步模板。
1. 从一次“找不到依赖”的翻车说起:IDEA 2021 搭 SSM 到底要装什么
很多人第一次在 IDEA 2021 里搭 SSM,卡住的地方根本不是 Spring、SpringMVC、MyBatis 三者怎么串起来,而是打开项目第一眼就飘红:Cannot resolve symbol 'springframework'。我见过一个模拟项目X,代码逻辑写得挺完整,结果换台机器重新拉下来,Maven 本地仓库是空的,IDEA 又默认走它自带的 Maven,版本和pom.xml里写的对不上,光“让依赖下载下来”就耗掉一整个下午。SSM 框架搭建在 JavaWeb 里属于最经典、也最容易被低估的一类环境活:它不挑高深算法,但特别挑版本对齐和目录结构。这篇笔记面向的是正准备用 IDEA 2021 从零搭一套 SSM 源码的开发者,尤其是那种“照着视频敲完却跑不起来”的情况。下面按装什么、怎么装、坏了怎么救的顺序走一遍,版本和参数我都会写清楚,能直接抄。
2. 环境清单与版本选择:IDEA 2021 下 SSM 的依赖怎么定
2.1 先把 JDK、Maven、Tomcat 三件套定死
SSM 本身是代码层面的框架,但它跑起来要靠一整套外部环境托着。IDEA 2021 这个版本对 JDK 8 的支持最稳,再往上到 JDK 11 也能跑,但 Spring 5.x 配 JDK 8 是社区里踩坑最少的组合。我一般会这样定:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8(8u 系列) | Spring 5.x 官方基线,IDEA 2021 识别无压力 |
| Maven | 3.6.3 | 比 3.8 少一些镜像和 HTTP 仓库的拦截问题 |
| Tomcat | 8.5 或 9.0 | 别用 Tomcat 10,javax.*包名变了会直接崩 |
| MySQL | 5.7 或 8.0 | 8.0 要换驱动类和时区参数 |
| IDEA | 2021.1 ~ 2021.3 | 社区版够用,旗舰版对 Web 支持更全 |
这里最容易被忽略的是 Tomcat 版本。Tomcat 10 把javax.servlet改成了jakarta.servlet,而 Spring 5.x 还在用javax,一旦用 Tomcat 10 部署,启动就报ClassNotFoundException。所以搭 SSM 源码,Tomcat 停在 9.0 就行,别追新。
Maven 版本也不是越新越好。3.8 之后默认拦截 HTTP 仓库,如果你settings.xml里配的是公司内网或老镜像,会直接报blocked mirror。3.6.3 相对省心,这也是我反复用它的原因。
2.2 pom.xml 里 SSM 依赖的版本对齐
环境定完,真正决定能不能跑通的是pom.xml。SSM 三件套的版本必须互相兼容,Spring 和 MyBatis 之间还要靠mybatis-spring这个桥接包粘起来。下面是我常用的一套组合,直接抄:
<!-- Spring 核心:context 负责 IoC 容器,webmvc 负责 MVC 调度 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.20</version> </dependency> <!-- Spring 事务管理,Service 层 @Transactional 靠它 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.20</version> </dependency> <!-- MyBatis 本体与 Spring 桥接包,版本要成对看 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency> <!-- 数据库驱动,MySQL 8 用 com.mysql.cj.jdbc.Driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <!-- 连接池,Druid 或 HikariCP 二选一 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency>逻辑说明:spring-context和spring-webmvc版本必须一致,混用会出现NoSuchMethodError;mybatis-spring2.0.x 对应 MyBatis 3.5.x,如果mybatis-spring用 1.x 配 MyBatis 3.5,运行时会报SqlSessionFactoryBean找不到方法。参数上,mysql-connector-java8.0 的驱动类名是com.mysql.cj.jdbc.Driver,URL 还要带serverTimezone=Asia/Shanghai,否则连接直接抛时区异常。
提示:依赖下载不下来时,先看 IDEA 右侧 Maven 面板用的是不是 Bundled Maven。我一般改成自己装的 3.6.3,并在
settings.xml里指定本地仓库路径,避免和系统默认仓库打架。
3. 从零建工程:IDEA 2021 里 SSM 目录结构与配置落地
3.1 用 Maven 骨架建 Web 工程并补全目录
IDEA 2021 新建工程时选 Maven,勾上Create from archetype,选maven-archetype-webapp。建完你会发现目录是残缺的:只有src/main/webapp,没有java和resources。这两个目录得手动补,而且要在 Project Structure 里标记类型,否则编译时 Java 文件根本不被识别。
# 在 src/main 下手动创建两个目录 src/main/java # 标记为 Sources Root src/main/resources # 标记为 Resources Root操作路径是 File → Project Structure → Modules → Sources,把java标成 Sources,resources标成 Resources。这一步不做,后面applicationContext.xml放在 resources 里也加载不到,报FileNotFoundException。目录补完后,标准结构应该是:java下按controller / service / mapper / entity分包,resources下放applicationContext.xml、spring-mvc.xml、mybatis-config.xml、jdbc.properties。
3.2 web.xml 与三个 Spring 配置文件的挂载关系
SSM 的配置核心是“三个 XML 各管一摊,web.xml 负责把它们串起来”。applicationContext.xml管 Service 和 Dao,spring-mvc.xml管 Controller,web.xml里用监听器和 Servlet 分别加载。
<!-- web.xml:加载 Spring 根容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- DispatcherServlet:加载 SpringMVC 子容器 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>逻辑说明:ContextLoaderListener启动时创建父容器,DispatcherServlet创建子容器,子容器能拿到父容器的 Bean,反过来不行。所以 Controller 里能注入 Service,但 Service 里注入 Controller 会失败。url-pattern写/而不是/*,/*会拦截 jsp 导致页面 404,这是很经典的一个坑。
3.3 applicationContext.xml 里数据源与 MyBatis 的整合
根容器里最关键的是数据源和SqlSessionFactory的装配。用 Druid 做连接池,把jdbc.properties抽出来单独放,改数据库时不用动 XML。
<!-- 读取 jdbc.properties --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- Druid 数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- SqlSessionFactory 交给 Spring 管理 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <!-- 扫描 Mapper 接口,生成代理实现 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.demo.mapper"/> </bean>逻辑说明:MapperScannerConfigurer会为com.demo.mapper下的接口生成动态代理,所以 Mapper 接口不需要写实现类。mapperLocations指向 XML 映射文件,如果接口和 XML 同名同包,也可以不配这一项,但分开放更清晰。jdbc.properties里 MySQL 8 的 URL 要写成jdbc:mysql://localhost:3306/ssm_demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8,少一个参数都可能连不上。
注意:
context:property-placeholder只能配一次,如果 spring-mvc.xml 里也配了,后加载的会覆盖前面的,导致数据源读不到值。我一般只在根容器里配。
4. 避坑与排查:SSM 搭建中最容易翻车的 5 个点
4.1 现象:启动报 NoClassDefFoundError: javax/servlet/ServletContext
原因基本锁定在 Tomcat 版本。Tomcat 10 用的是jakarta.servlet,而 Spring 5.x 编译时依赖javax.servlet,两者包名对不上。解决方式是换回 Tomcat 9.0 或 8.5,在 IDEA 的 Run/Debug Configurations 里重新指定 Tomcat 安装目录,别用默认下载的最新版。
4.2 现象:Mapper 接口注入失败,报 NoSuchBeanDefinitionException
原因是MapperScannerConfigurer的basePackage写错,或者 Mapper 接口没放在指定包下。还有一种情况是applicationContext.xml没被加载,检查 web.xml 里contextConfigLocation的路径是不是classpath:开头。我一般会在启动日志里搜MapperScannerConfigurer,看它扫描了哪些包。
4.3 现象:中文乱码,页面提交后数据库存的是问号
三个地方要同时设:web.xml里加CharacterEncodingFilter,jdbc.url带characterEncoding=utf8,数据库建表时字符集用utf8mb4。少一处都可能乱码。过滤器要放在所有 filter 最前面,否则顺序不对不生效。
<filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>4.4 现象:IDEA 里 Tomcat 启动后访问 404,但控制台没报错
先看 Artifact 有没有配。File → Project Structure → Artifacts,确认war exploded存在,并且 Output Layout 里WEB-INF/classes下有编译后的 class 和 resources。如果 classes 是空的,说明模块没编译,Build → Rebuild Project 走一遍。另一个常见原因是url-pattern写成了/*,改成/。
4.5 现象:Maven 依赖全部飘红,reimport 也没用
先确认 IDEA 用的 Maven 是不是 Bundled。Settings → Build Tools → Maven,把 Maven home path 改成自己装的 3.6.3,User settings file 指向改好的settings.xml。然后在本地仓库目录执行一次清理,把*.lastUpdated文件删掉,再 reimport。如果公司网络有限制,就在settings.xml里配好镜像地址,别用默认中央仓库硬拉。
5. 装完怎么验证:一套能跑通的 SSM 最小闭环
配置写完不代表跑通,得用一个最小的增删改查闭环验证。我一般会建一张user表,写一个查询接口,从 Controller 一路打到数据库,能返回数据才算环境真的立住了。
先建表:
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(32) NOT NULL, `age` INT DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `user` (`name`, `age`) VALUES ('测试用户', 20);然后写 Mapper 接口和 XML:
// UserMapper.java public interface UserMapper { List<User> selectAll(); }<!-- UserMapper.xml --> <mapper namespace="com.demo.mapper.UserMapper"> <select id="selectAll" resultType="com.demo.entity.User"> SELECT id, name, age FROM user </select> </mapper>Controller 里注入 Service,Service 注入 Mapper,最后用浏览器或 Postman 访问/user/list。如果返回 JSON 里能看到测试用户,说明 Spring 容器、MyBatis 映射、数据源、MVC 调度四条链路全通了。
验证时重点看三处日志:启动阶段有没有Root WebApplicationContext initialized,说明根容器起来了;请求进来有没有DispatcherServlet的映射日志;SQL 有没有打印,可以在mybatis-config.xml里配logImpl为STDOUT_LOGGING临时打开。
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>这个配置只在排查时开,上线要关掉,否则日志量很大。我自己的习惯是:每次搭完 SSM,先不写业务,就用这张user表跑一遍查询,确认四条链路都活着,再往里加功能。从那以后我每次新建 SSM 工程,都会强制走一遍这个最小闭环,省得写到一半才发现是环境问题而不是代码问题。希望帮到你。
本文还有配套的精品资源,点击获取