Java中SSM 框架基本使用教程(小白版)
SSM 框架基本使用教程(小白版)
SSM = Spring + Spring MVC + MyBatis,是 Java Web 开发最经典的三大框架组合。
一、先搞懂三个框架各自干什么
用一个餐厅的比喻:
┌─────────────────────────────────────────────────────┐
│ SSM 餐厅 │
│ │
│ 🧑🍳 Spring → 餐厅经理(管理所有对象,协调一切) │
│ 🚪 Spring MVC → 前台服务员(接客人的点单,端菜上桌) │
│ 🗄️ MyBatis → 后厨(从仓库/数据库取出食材做菜) │
└─────────────────────────────────────────────────────┘
| 框架 | 一句话概括 | 干什么的 |
|---|---|---|
| Spring | 大管家 | 管理对象的创建和依赖关系(IoC/DI) |
| Spring MVC | 接待员 | 接收用户请求,返回页面或数据 |
| MyBatis | 数据库翻译 | 把 Java 代码翻译成 SQL,操作数据库 |
二、项目结构长什么样
ssm-demo/
├── src/main/java/com/example/
│ ├── controller/ ← Spring MVC:接收请求
│ │ └── UserController.java
│ ├── service/ ← Spring:业务逻辑
│ │ ├── UserService.java
│ │ └── UserServiceImpl.java
│ ├── mapper/ ← MyBatis:操作数据库
│ │ └── UserMapper.java
│ └── entity/ ← 实体类(对应数据库表)
│ └── User.java
├── src/main/resources/
│ ├── mapper/ ← MyBatis 的 SQL 映射文件
│ │ └── UserMapper.xml
│ ├── spring/ ← Spring 配置
│ │ ├── applicationContext.xml
│ │ └── spring-mvc.xml
│ └── db.properties ← 数据库连接信息
└── pom.xml ← Maven 依赖管理
三、一步一步搭建
第1步:Maven 依赖(pom.xml)
<dependencies>
<!-- ========== Spring 核心 ========== -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- ========== MyBatis ========== -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- Spring 和 MyBatis 的整合包(重要!) -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!-- ========== 数据库驱动 ========== -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.15</version>
</dependency>
<!-- ========== Servlet ========== -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
💡 提示:
pom.xml就是一个"购物清单",告诉 Maven 你需要哪些第三方库。
第2步:实体类(对应数据库表)
package com.example.entity;
/**
* 用户实体类 —— 与数据库的 user 表一一对应
*/
public class User {
private Integer id; // 对应数据库的 id 字段
private String username; // 用户名
private String password; // 密码
private String email; // 邮箱
// ---- getter 和 setter(必须有!框架靠它们读写数据)----
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{id=" + id + ", username='" + username + "', email='" + email + "'}";
}
}
对应的数据库表:
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(50),
email VARCHAR(100)
);
-- 插几条测试数据
INSERT INTO user VALUES (1, 'zhangsan', '123456', 'zhangsan@qq.com');
INSERT INTO user VALUES (2, 'lisi', '654321', 'lisi@qq.com');
第3步:MyBatis 层(操作数据库)
① Mapper 接口 —— 定义"能做哪些数据库操作":
package com.example.mapper;
import com.example.entity.User;
import java.util.List;
/**
* 用户 Mapper 接口
* 不用写实现类!MyBatis 会自动生成实现(通过 XML 中的 SQL)
*/
public interface UserMapper {
// 查询所有用户
List<User> findAll();
// 根据 id 查一个用户
User findById(Integer id);
// 添加用户
int insert(User user);
// 修改用户
int update(User user);
// 删除用户
int deleteById(Integer id);
}
② Mapper XML —— 写具体的 SQL:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace = 对应的 Mapper 接口的全类名
这样 MyBatis 就知道:这个 XML 里的 SQL 是给哪个接口用的
-->
<mapper namespace="com.example.mapper.UserMapper">
<!--
resultMap:告诉 MyBatis 数据库字段 和 Java 属性的对应关系
如果字段名和属性名完全一样,可以不写
-->
<resultMap id="userMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userMap">
SELECT id, username, password, email FROM user
</select>
<!-- 根据 id 查询 -->
<select id="findById" parameterType="int" resultMap="userMap">
SELECT id, username, password, email FROM user
WHERE id = #{id}
</select>
<!-- 添加用户 -->
<!-- useGeneratedKeys:插入后自动把数据库生成的 id 回填到对象里 -->
<insert id="insert" parameterType="com.example.entity.User"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (username, password, email)
VALUES (#{username}, #{password}, #{email})
</insert>
<!-- 修改用户 -->
<update id="update" parameterType="com.example.entity.User">
UPDATE user
SET username = #{username}, password = #{password}, email = #{email}
WHERE id = #{id}
</update>
<!-- 删除用户 -->
<delete id="deleteById" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
💡 提示
#{id}是占位符,相当于 JDBC 的?,会自动防 SQL 注入id="findAll"必须和接口方法名一样!这就是映射关系
第4步:Service 层(业务逻辑)
① 接口:
package com.example.service;
import com.example.entity.User;
import java.util.List;
public interface UserService {
List<User> findAll();
User findById(Integer id);
void add(User user);
void modify(User user);
void remove(Integer id);
}
② 实现类:
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service // 告诉 Spring:这个类由你来管理(自动创建对象)
public class UserServiceImpl implements UserService {
@Autowired // 告诉 Spring:自动帮我注入 UserMapper 对象
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public User findById(Integer id) {
return userMapper.findById(id);
}
@Override
public void add(User user) {
userMapper.insert(user);
}
@Override
public void modify(User user) {
userMapper.update(user);
}
@Override
public void remove(Integer id) {
userMapper.deleteById(id);
}
}
💡
@Autowired的神奇之处:你不用new UserServiceImpl(),Spring 自动帮你创建好并注入进来。
第5步:Controller 层(接收请求)
package com.example.controller;
import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller // 标记为控制器
@RequestMapping("/user") // 所有请求路径以 /user 开头
public class UserController {
@Autowired
private UserService userService;
/**
* 查询所有用户
* 请求:GET /user/list
* 返回:跳转到 user/list.jsp 页面
*/
@GetMapping("/list")
public String list(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users); // 把数据塞到页面上
return "user/list"; // 返回页面路径
}
/**
* 根据 id 查询用户
* 请求:GET /user/1
*/
@GetMapping("/{id}")
public String detail(@PathVariable Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user/detail";
}
/**
* 添加用户 —— 显示表单
* 请求:GET /user/add
*/
@GetMapping("/add")
public String addForm() {
return "user/add"; // 返回添加页面
}
/**
* 添加用户 —— 提交表单
* 请求:POST /user/add
*/
@PostMapping("/add")
public String add(User user) {
userService.add(user);
return "redirect:/user/list"; // 添加成功后跳转到列表页
}
/**
* 删除用户
* 请求:GET /user/delete/1
*/
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
userService.remove(id);
return "redirect:/user/list";
}
/**
* (前后端分离方式)返回 JSON 数据
* 请求:GET /user/api/list
*/
@GetMapping("/api/list")
@ResponseBody // 加了这个就不跳页面了,直接返回数据
public List<User> apiList() {
return userService.findAll();
}
}
💡 常用注解速记:
注解 意思 @Controller这是个控制器 @RequestMapping("/user")URL 映射 @GetMapping只处理 GET 请求 @PostMapping只处理 POST 请求 @PathVariable从 URL 里取参数,如 /user/{id}@RequestParam从 ?key=value 取参数 @ResponseBody返回 JSON 而不是页面 @RestController= @Controller+@ResponseBody
第6步:Spring 配置文件
数据库配置 (db.properties):
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_demo?useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456
Spring 核心配置 (applicationContext.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1. 加载数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2. 配置数据源(数据库连接池) -->
<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>
<!-- 3. 配置 MyBatis 的 SqlSessionFactory(核心!) -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="typeAliasesPackage" value="com.example.entity"/>
</bean>
<!-- 4. 扫描 Mapper 接口,自动创建实现类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
<!-- 5. 扫描 Service 层的注解(@Service, @Autowired 等) -->
<context:component-scan base-package="com.example.service"/>
</beans>
Spring MVC 配置 (spring-mvc.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1. 扫描 Controller 层的注解 -->
<context:component-scan base-package="com.example.controller"/>
<!-- 2. 开启注解驱动(让 @GetMapping 等注解生效) -->
<mvc:annotation-driven/>
<!-- 3. 配置视图解析器(决定返回的页面在哪里) -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/> <!-- 前缀 -->
<property name="suffix" value=".jsp"/> <!-- 后缀 -->
</bean>
<!-- 4. 放行静态资源(css/js/图片等) -->
<mvc:default-servlet-handler/>
</beans>
第7步:web.xml(启动入口)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 1. 加载 Spring 核心配置(启动 Spring 容器) -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 2. 配置 Spring MVC 的前端控制器(所有请求都先经过它) -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!-- 拦截所有请求 -->
</servlet-mapping>
<!-- 3. 字符编码过滤器(解决中文乱码) -->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
四、请求流转的完整过程
用户浏览器 你的代码
│
│ GET /user/list
▼
┌──────────────────┐
│ web.xml │ DispatcherServlet 拦截请求
│ (前端控制器) │
└────────┬─────────┘
▼
┌──────────────────┐
│ Spring MVC │ 根据 @RequestMapping 找到
│ (找Controller) │ UserController.list()
└────────┬─────────┘
▼
┌──────────────────┐
│ Controller │ 调用 userService.findAll()
│ (处理请求) │
└────────┬─────────┘
▼
┌──────────────────┐
│ Service │ 调用 userMapper.findAll()
│ (业务逻辑) │
└────────┬─────────┘
▼
┌──────────────────┐
│ Mapper + XML │ 执行 SQL: SELECT * FROM user
│ (操作数据库) │ MyBatis 把结果转成 User 对象
└────────┬─────────┘
▼
数据逐层返回
│
Controller 把数据塞到 Model 里
│
视图解析器拼接路径: /WEB-INF/views/user/list.jsp
│
渲染 JSP 页面返回给浏览器
▼
用户看到页面 ✅
五、常用注解速查表
Spring 注解
@Component // 通用组件,Spring 管理它
@Service // 等于 @Component,语义上表示"业务层"
@Repository // 等于 @Component,语义上表示"数据层"
@Autowired // 自动注入依赖对象
@Qualifier // 当有多个同类型对象时,指定注入哪个
Spring MVC 注解
@Controller // 控制器
@RestController // = @Controller + @ResponseBody(返回 JSON)
@RequestMapping // URL 映射(可以加在类和方法上)
@GetMapping // 等于 @RequestMapping(method=GET)
@PostMapping // 等于 @RequestMapping(method=POST)
@PathVariable // 从 URL 路径取值:/user/{id} → id
@RequestParam // 从查询参数取值:?name=xx → name
@ResponseBody // 返回数据(JSON),不走视图解析
@RequestBody // 接收 JSON 格式的请求体
MyBatis XML 中的标签
<select> 查询
<insert> 插入
<update> 修改
<delete> 删除
<if> 条件判断
<where> 智能 WHERE(自动去掉多余的 AND/OR)
<foreach> 循环(常用于 IN 查询和批量插入)
六、动态 SQL 示例(MyBatis 精华)
<!-- 条件查询:根据传入的参数动态拼 SQL -->
<select id="search" parameterType="com.example.entity.User" resultMap="userMap">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</where>
</select>
<!-- 批量删除 -->
<delete id="batchDelete" parameterType="list">
DELETE FROM user WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
💡
<where>的好处:如果里面所有<if>都不成立,就不会生成 WHERE 子句;如果第一个条件成立,会自动去掉多余的AND。
七、总结:三层架构对应关系
┌───────────────────────────────────────────────────────────────┐
│ 用户请求 │
│ ▼ │
│ ┌──────────┐ @Controller 处理请求、返回页面/JSON │
│ │Controller │────────────────────────────────────────── │
│ └────┬─────┘ │
│ ▼ │
│ ┌──────────┐ @Service 写业务逻辑(判断、计算等) │
│ │ Service │────────────────────────────────────────── │
│ └────┬─────┘ │
│ ▼ │
│ ┌──────────┐ Mapper + XML 操作数据库(增删改查) │
│ │ Mapper │────────────────────────────────────────── │
│ └────┬─────┘ │
│ ▼ │
│ ┌──────────┐ │
│ │ 数据库 │ MySQL │
│ └──────────┘ │
└───────────────────────────────────────────────────────────────┘
调用方向:Controller → Service → Mapper → 数据库
依赖注入:Spring 通过 @Autowired 自动把下层对象传给上层
Controller 接活,Service 干活,Mapper 拿货
Controller 接收请求,Service 处理业务逻辑,Mapper 操作数据库。
八、现在流行的替代方案
SSM 是经典配置式开发,现在更流行注解式 / 自动配置:
| 传统 SSM | 现代替代 |
|---|---|
| 手写 XML 配置 | Spring Boot 自动配置 |
| 手写 SQL | MyBatis-Plus 自动生成 CRUD |
| JSP 页面 | 前后端分离(Vue/React + JSON API) |
更多推荐


所有评论(0)