☰
IDEA搭建SSM框架源码:从零跑通登录到二次开发避坑指南
2026/10/21 12:09:16 网站建设 项目流程

简介:这份源码资源面向Java Web初学者与需要巩固SSM整合流程的开发者,解决从零搭建Spring+SpringMVC+MyBatis项目时环境配置繁琐、依赖版本易冲突的问题。资源基于IDEA2021、Tomcat9.0与MySQL8.0.25环境整理,可直接导入运行,适合课程设计、毕业设计或企业入门项目参考。压缩包共105个文件,约22.34MB,其中52个jar包提供框架与数据库驱动依赖,28个xml文件承载Spring、SpringMVC及MyBatis核心配置,另有java源码、jsp页面、properties配置与class编译文件,完整覆盖控制层、业务层与持久层结构。目前已有3136人学习下载,说明其整合思路具备一定参考价值。读者可借此理清SSM各层职责划分、依赖注入与映射配置的对应关系,对照Book相关模块理解增删改查实现路径,并掌握IDEA下Tomcat部署与MySQL连接的排错方法,为后续框架进阶打下基础。

1. 从一堆报错到跑通登录:这套 IDEA 搭建 SSM 源码到底能帮你省下多少时间

如果你正在搜「ssm框架搭建 idea ssm javaweb java」,大概率不是想听 Spring 和 MyBatis 的概念,而是手里有个 JavaWeb 课设或者老项目要维护,打开 IDEA 新建工程后,对着 web.xml、applicationContext.xml、spring-mvc.xml 三个配置文件发呆。这套源码解决的就是这个场景:它把 SSM(Spring + SpringMVC + MyBatis)从零搭建的完整过程固化成了一个可运行的工程,包含 Maven 依赖、分层包结构、XML 配置和一套基础的增删改查示例。适合两类人:一是刚接触 JavaWeb、需要照着跑通第一个整合项目的学生或转行者;二是接手了传统 SSM 老系统、需要快速回忆配置套路的开发者。它不炫技,就是把「能跑起来」这件事做扎实。

2. 工程骨架拆解:Maven 依赖、包结构和三份 XML 怎么配合

拿到源码先别急着点运行,把工程结构看一遍,后面出问题才知道去哪找。这套 SSM 工程用的是标准 Maven 布局,核心目录就下面这些。

2.1 目录结构与各层职责

ssm-demo ├── pom.xml ├── src/main/java │ ├── com.demo.controller // SpringMVC 控制层 │ ├── com.demo.service // 业务接口 │ ├── com.demo.service.impl // 业务实现 │ ├── com.demo.mapper // MyBatis 映射接口 │ └── com.demo.entity // 实体类 ├── src/main/resources │ ├── applicationContext.xml // Spring 核心配置 │ ├── spring-mvc.xml // SpringMVC 配置 │ ├── mybatis-config.xml // MyBatis 全局配置 │ ├── jdbc.properties // 数据库连接参数 │ └── mapper/ // SQL 映射文件 └── src/main/webapp ├── WEB-INF/web.xml // 三大配置的加载入口 └── WEB-INF/views/ // JSP 视图

分层逻辑很直白:controller 接请求,service 写业务,mapper 管数据库,entity 做数据载体。新手最容易犯的错是把业务逻辑写进 controller,或者让 controller 直接调 mapper,跑是能跑,但后面改需求就痛苦了。

2.2 pom.xml 里的关键依赖

SSM 整合的依赖版本必须对齐,否则启动就报NoSuchMethodError。源码里锁定的核心依赖如下:

<!-- Spring 核心,版本统一管理 --> <properties> <spring.version>5.3.20</spring.version> </properties> <dependencies> <!-- spring-context 提供 IoC 容器 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- spring-webmvc 提供 DispatcherServlet 等 MVC 组件 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- spring-jdbc 负责事务与数据源管理 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- MyBatis 与 Spring 的粘合包,缺它整合不起来 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <!-- 数据库驱动与连接池 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.11</version> </dependency> </dependencies>

参数说明:spring.version用属性统一管理,改版本只改一处;mybatis-spring是整合的关键,它把 MyBatis 的 SqlSession 交给 Spring 管理;Druid 做连接池,比默认的 DriverManager 稳定得多。常见做法是把版本号都提到 properties 里,避免依赖冲突时到处翻。

2.3 web.xml:三大配置的加载顺序

web.xml 是整个应用的入口,加载顺序错了就会报No WebApplicationContext found。

<!-- 1. Spring 容器:加载 service、mapper、数据源 --> <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> <!-- 2. SpringMVC 前端控制器:加载 controller --> <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> <!-- 3. 字符编码过滤器,解决中文乱码 --> <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> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

逻辑说明:ContextLoaderListener先启动父容器,负责 service 和 mapper;DispatcherServlet再启动子容器,负责 controller。子容器能拿到父容器的 Bean,反过来不行,所以 controller 里能注入 service,service 里不能注入 controller。url-pattern写/而不是/*,是为了不拦截 JSP 请求,这个坑后面还会提。

3. 核心配置落地:数据源、MyBatis 扫描和事务怎么串起来

配置是 SSM 最容易翻车的地方,一个标签写错就是启动失败。这一章把三份 XML 拆开讲,每份都给出可抄的代码和参数含义。

3.1 applicationContext.xml:数据源与 MyBatis 整合

这份配置管的是「非 Web 层」的东西:数据源、SqlSessionFactory、mapper 扫描、事务。

<!-- 读取 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}"/> <property name="initialSize" value="5"/> <property name="maxActive" value="20"/> </bean> <!-- SqlSessionFactory:把数据源和 mapper 位置交给 MyBatis --> <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> <!-- 注解式事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>

参数说明:initialSize是连接池初始连接数,本地开发 5 够用;maxActive是最大连接数,压测时按并发调。mapperLocations用通配符批量加载映射文件,新增 mapper 不用改配置。MapperScannerConfigurer会自动为接口生成实现类,所以 mapper 接口不需要写实现。事务用@Transactional注解开启,比 XML 切面配置省事。

3.2 spring-mvc.xml:视图解析与静态资源放行

这份配置只管 Web 层,重点是视图解析器和静态资源处理。

<!-- 开启注解驱动,让 @RequestMapping 生效 --> <mvc:annotation-driven/> <!-- 扫描 controller 包 --> <context:component-scan base-package="com.demo.controller"/> <!-- 视图解析器:controller 返回 "login" 会拼成 /WEB-INF/views/login.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 放行静态资源,否则 css/js 会被 DispatcherServlet 拦截 --> <mvc:default-servlet-handler/>

逻辑说明:InternalResourceViewResolver的 prefix 和 suffix 决定了 controller 返回字符串怎么变成真实路径。mvc:default-servlet-handler是新手最容易漏的一行,不加的话页面样式全丢,控制台还看不到明显报错,属于典型的玄学问题。

3.3 jdbc.properties 与 mybatis-config.xml

数据库参数单独抽出来,方便切换环境:

jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssm_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123456

注意serverTimezone参数,MySQL 8 不加会报时区错误。mybatis-config.xml里主要配别名和驼峰映射:

<configuration> <settings> <!-- 数据库下划线字段自动映射到 Java 驼峰属性 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 打印 SQL,调试用,上线关掉 --> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <typeAliases> <package name="com.demo.entity"/> </typeAliases> </configuration>

mapUnderscoreToCamelCase打开后,user_name字段能自动映射到userName属性,省掉大量 resultMap 配置。logImpl用标准输出打印 SQL,本地调试看得到执行的语句和参数,上线记得换成日志框架或关掉。

4. 一个请求的完整链路:从 Controller 到 Mapper 的代码逐段拆

配置通了之后,看代码怎么串。以一个用户查询为例,走一遍 controller → service → mapper → 数据库的完整链路。

4.1 Controller 层:接收请求与参数绑定

@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; // 查询用户列表,返回 JSP 视图 @RequestMapping("/list") public String list(Model model) { List<User> users = userService.findAll(); model.addAttribute("users", users); return "userList"; // 对应 /WEB-INF/views/userList.jsp } // 根据 id 查询单个用户,返回 JSON @RequestMapping("/get/{id}") @ResponseBody public User getById(@PathVariable("id") Integer id) { return userService.findById(id); } }

逻辑说明:@Controller声明这是控制器,@RequestMapping定义访问路径。@Autowired注入 service,注意这里注入的是接口不是实现类。Model用来往视图传数据,@ResponseBody表示返回 JSON 而不是跳转页面。@PathVariable从 URL 路径取值,适合 RESTful 风格。

4.2 Service 层:业务逻辑与事务边界

@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> findAll() { return userMapper.selectAll(); } @Override public User findById(Integer id) { return userMapper.selectById(id); } // 涉及多表写入时加事务,保证原子性 @Override @Transactional public void register(User user) { userMapper.insert(user); // 其他关联表操作... } }

参数说明:@Service把实现类交给 Spring 管理。@Transactional加在方法上,方法内任何异常都会回滚。注意事务默认只对RuntimeException回滚,受检异常需要显式配置rollbackFor。业务逻辑写在这一层,controller 只做参数校验和结果组装。

4.3 Mapper 接口与 XML:SQL 写在哪

public interface UserMapper { List<User> selectAll(); User selectById(Integer id); int insert(User user); }

接口只声明方法,SQL 写在对应的 XML 里:

<mapper namespace="com.demo.mapper.UserMapper"> <select id="selectAll" resultType="User"> SELECT id, user_name, age FROM t_user </select> <select id="selectById" parameterType="int" resultType="User"> SELECT id, user_name, age FROM t_user WHERE id = #{id} </select> <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_user(user_name, age) VALUES(#{userName}, #{age}) </insert> </mapper>

逻辑说明:namespace必须和 mapper 接口全限定名一致,否则绑定失败。resultType用了别名User,靠 mybatis-config 里的 typeAliases 配置。#{}是预编译占位符,能防 SQL 注入;${}是字符串拼接,除非动态表名否则别用。useGeneratedKeys让插入后自增主键回填到实体对象。

5. 避坑与排查:启动报错、404、乱码的定位思路

SSM 搭建过程中报错信息往往不直观,这一章列几个高频问题,按「现象 → 原因 → 解决」给排查路径。

5.1 启动报 NoClassDefFoundError 或 NoSuchMethodError

现象:Tomcat 启动直接失败,控制台一堆类找不到或方法不存在。 原因:依赖版本冲突,通常是 Spring 各模块版本不一致,或者 mybatis-spring 与 mybatis 版本不匹配。 解决:在 IDEA 右侧 Maven 面板执行dependency:tree,看有没有同一 artifact 出现多个版本。把 Spring 全家桶统一到同一个spring.version,mybatis-spring 2.x 配 mybatis 3.5.x。

5.2 页面 404,但控制台没报错

现象:访问/user/list返回 404,日志里看不到异常。 原因:多半是spring-mvc.xml没被加载,或者 controller 没被扫描到。也可能是url-pattern写成了/*导致 JSP 也被拦截。 解决:先确认 web.xml 里 DispatcherServlet 的contextConfigLocation指向正确;再检查component-scan的包路径是否覆盖 controller;最后把url-pattern改成/。

5.3 中文乱码

现象:表单提交的中文在数据库里变成问号,或者页面显示乱码。 原因:请求编码、数据库连接编码、表字段编码三者不一致。 解决:web.xml 加CharacterEncodingFilter并设 UTF-8;jdbc.url 加useUnicode=true&characterEncoding=utf8;建表时字段用utf8mb4。三处都对齐才彻底。

5.4 静态资源 404,CSS/JS 加载不出来

现象:页面能打开但没样式,F12 看到 css/js 请求 404。 原因:DispatcherServlet 拦截了所有请求,静态资源没放行。 解决:spring-mvc.xml 加<mvc:default-servlet-handler/>,或者用<mvc:resources>显式映射静态资源路径。

5.5 事务不生效

现象:方法里抛异常了,但数据没回滚。 原因:@Transactional加在了 private 方法上,或者同类内部方法直接调用(没走代理),或者异常类型不在回滚范围。 解决:注解加在 public 方法上;同类调用通过注入自身或 AopContext 走代理;受检异常加rollbackFor = Exception.class。

6. 二次开发改造:换数据库、加拦截器、拆模块的实操思路

跑通之后,多数人是要在这套骨架上改东西。这一章给几个改造方向,都是实际项目里用得上的。

6.1 换数据库:从 MySQL 迁到其他库

改三处:pom.xml 换驱动依赖,jdbc.properties 换 driver 和 url,mapper XML 里的 SQL 方言按目标库调整。分页写法差异最大,MySQL 用LIMIT,其他库可能是ROWNUM或OFFSET FETCH。常见做法是引入 PageHelper 插件,把分页逻辑从 SQL 里抽出来,换库时只改配置。

6.2 加登录拦截器

在 spring-mvc.xml 里注册拦截器:

<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/login"/> <mvc:exclude-mapping path="/static/**"/> <bean class="com.demo.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors>

拦截器实现HandlerInterceptor,在preHandle里判断 session 是否有用户信息,没有就重定向到登录页。exclude-mapping放行登录接口和静态资源,否则会死循环。

6.3 拆模块与接口规范

单工程跑通后,如果要做大,按业务拆成多模块 Maven 工程:common 放工具类和实体,dao 放 mapper,service 放业务,web 放 controller。拆的时候注意依赖方向,web 依赖 service,service 依赖 dao,不能反向。接口返回值统一封装成Result<T>,包含 code、msg、data 三个字段,前端处理起来省心。

改造验证有个笨办法但很管用:每改一处配置,先只启动不访问,看容器能不能起来;起来了再访问一个最简单的接口;接口通了再测业务。别一次改五六个地方然后一起调,出了问题根本定位不到是哪处。从那以后我每次动 SSM 配置都强制走一遍「启动 → 空接口 → 业务接口」的验证链,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询