Java框架快速入门: SSM整合与表现层数据封装

SSM框架讲解(史上最详细的文章) SSM框架是spring、springMVC、和mybatis框架的整合,是标准的MVC模式。标准的SSM框架有四层,分别是dao层(mapper),service层,controller层和View层。使用spring实现业务对象管理,使用springMVC负责请求的转发和视图管理,mybatis作为数据对象的持久化引擎。1)持久层dao层(mapper)层作用主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。2)业务层Service层作用3)表现层作用作用。... 阅读详情

本文纲要

一、SSM整合概述

二、项目结构与依赖管理
2.1 项目目录结构
2.2 Maven依赖清单

三、SSM核心配置类详解
3.1 Spring主配置类 SpringConfig
3.2 数据源与事务配置 JdbcConfig
3.3 MyBatis整合配置 MyBatisConfig
3.4 SpringMVC主配置 SpringMvcConfig
3.5 Web容器初始化 ServletConfig
3.6 父子容器关系图解

四、业务层开发
4.1 实体类 Book
4.2 数据访问层 BookDao
4.3 业务接口与实现
4.4 事务管理配置

五、控制器层开发(原始返回)

六、接口测试
6.1 Service层测试
6.2 Controller接口测试

七、表现层数据封装协议
7.1 前后端数据交互的痛点
7.2 协议演进过程
7.3 统一返回格式设计

八、统一返回格式落地实现
8.1 状态码类 Code
8.2 返回结果类 Result
8.3 改造后的 BookController
8.4 Postman测试验证

九、总结

一、SSM整合概述

SSM 是 Spring + SpringMVC + MyBatis 三个经典框架的组合,广泛应用于 Java Web 开发。本章我们将从零搭建一个 SSM 整合工程,完成配置、功能模块开发、接口测试,并引入表现层数据封装协议,使后端返回的数据格式统一、清晰,便于前后端协作。

整个整合过程分为以下几个阶段:

  1. 基础环境搭建:创建 Maven Web 项目,导入依赖。
  2. 配置类编写:用纯 Java 类替代 XML,完成 Spring、MyBatis、SpringMVC 的整合配置。
  3. 业务模块开发:从数据库表 → 实体类 → DAO → Service → Controller,实现 CRUD 功能。
  4. 事务管理:在 Spring 配置中开启注解事务,为 Service 层添加事务控制。
  5. 接口测试:使用 JUnit 测试 Service,使用 Postman 测试 Controller。
  6. 表现层数据封装:设计统一的返回格式 Result,定义状态码 Code,解决前端解析混乱的问题。

下面我们按照上述步骤,逐一展开。

二、项目结构与依赖管理

1 ) 项目目录结构

最终项目的完整目录结构如下(以 springmvc_09_result 为准):

springmvc_09_result 
├── pom.xml 
└── src 
    ├── main 
    │   ├── java 
    │   │   └── com 
    │   │       └── wb 
    │   │           ├── config 
    │   │           │   ├── JdbcConfig.java 
    │   │           │   ├── MyBatisConfig.java 
    │   │           │   ├── ServletConfig.java 
    │   │           │   ├── SpringConfig.java 
    │   │           │   └── SpringMvcConfig.java 
    │   │           ├── controller 
    │   │           │   ├── BookController.java 
    │   │           │   ├── Code.java 
    │   │           │   └── Result.java 
    │   │           ├── dao 
    │   │           │   └── BookDao.java 
    │   │           ├── domain 
    │   │           │   └── Book.java 
    │   │           └── service 
    │   │               ├── BookService.java 
    │   │               └── impl 
    │   │                   └── BookServiceImpl.java 
    │   ├── resources 
    │   │   └── jdbc.properties 
    │   └── webapp 
    │       ├── index.jsp 
    │       └── WEB-INF 
    │           └── web.xml 
    └── test 
        └── java 
            └── com 
                └── wb 
                    └── service 
                        └── BookServiceTest.java 

2 ) Maven依赖清单

pom.xml 中引入的依赖及作用如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.wb</groupId>
    <artifactId>springmvc09result</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
 
    <dependencies>
        <!-- Spring WebMVC (包含spring-context等核心模块) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
 
        <!-- Spring JDBC (事务管理依赖) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
 
        <!-- Spring Test (整合JUnit) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
 
        <!-- MyBatis核心 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
 
        <!-- MyBatis与Spring整合桥接包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
 
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
 
        <!-- Druid连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
 
        <!-- JUnit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
 
        <!-- Servlet API (provided,由容器提供) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- Jackson: Java对象与JSON互转 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <!-- Tomcat7 Maven插件,方便运行 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>80</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

要点:spring-webmvc 会自动传递 spring-context、spring-web 等,因此无需重复声明。

三、SSM核心配置类详解

SSM 整合的核心在于使用配置类替代传统的 XML 配置文件。下面逐一解析每个配置类的作用和编写方式。

1 ) Spring主配置类 SpringConfig

SpringConfig 是 Spring 的根配置类,负责管理 Service 层、事务、属性文件加载以及导入其他配置类。

package com.wb.config;
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
 
@Configuration 
@ComponentScan({"com.wb.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement 
public class SpringConfig {
}

配置说明:

  • @Configuration:标识为配置类。
  • @ComponentScan("com.wb.service"):只扫描 Service 包,避免与 SpringMVC 扫描冲突。
  • @PropertySource("classpath:jdbc.properties"):加载数据库连接属性文件。
  • @Import({JdbcConfig.class, MyBatisConfig.class}):导入数据源和 MyBatis 的配置类。
  • @EnableTransactionManagement:开启注解式事务驱动(配合 @Transactional 使用)。

2 ) 数据源与事务配置 JdbcConfig

JdbcConfig 负责创建 Druid 数据源,并配置事务管理器。

package com.wb.config;
 
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
 
import javax.sql.DataSource;
 
public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
 
    @Bean 
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
 
    @Bean 
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager ds = new DataSourceTransactionManager();
        ds.setDataSource(dataSource);
        return ds;
    }
}
  • @Value("${...}") 从 jdbc.properties 中注入属性值。
  • dataSource() 方法返回一个 Druid 数据源,并注册为 Bean。
  • transactionManager 方法创建事务管理器,注入数据源。Spring 在调用时会自动从容器中按类型注入 DataSource。

jdbc.properties 内容:

jdbc.driver=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/ssm_db 
jdbc.username=root 
jdbc.password=root 

3 ) MyBatis整合配置 MyBatisConfig

MyBatisConfig 负责创建 SqlSessionFactory 和映射扫描器。

package com.wb.config;
 
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
 
import javax.sql.DataSource;
 
public class MyBatisConfig {
 
    @Bean 
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setTypeAliasesPackage("com.wb.domain");
        return factoryBean;
    }
 
    @Bean 
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.wb.dao");
        return msc;
    }
}
  • SqlSessionFactoryBean:整合包提供的工厂 Bean,需要注入数据源,并设置实体类别名包(自动扫描 com.wb.domain 下的类,首字母小写作为别名)。
  • MapperScannerConfigurer:自动扫描 com.wb.dao 包下的接口,为它们创建代理实现并注册为 Bean,无需再写 @Mapper 注解(当然也可以加)。

4 ) SpringMVC主配置 SpringMvcConfig

package com.wb.config;
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 
@Configuration 
@ComponentScan("com.wb.controller")
@EnableWebMvc 
public class SpringMvcConfig {
}
  • @ComponentScan("com.wb.controller"):只扫描 Controller 层。
  • @EnableWebMvc:开启 SpringMVC 的默认配置,包括 JSON 转换、路径映射等。

5 ) Web容器初始化 ServletConfig

在 Servlet 3.0+ 环境中,可以通过实现 AbstractAnnotationConfigDispatcherServletInitializer 来替代 web.xml。

package com.wb.config;
 
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
 
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
 
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
  • getRootConfigClasses():返回 Spring 根容器配置类(父容器)。
  • getServletConfigClasses():返回 SpringMVC 子容器配置类。
  • getServletMappings():指定 DispatcherServlet 的拦截路径,/ 表示拦截所有请求(不包含 .jsp)。

6 ) 父子容器关系图解

Web容器启动

ServletConfig初始化

创建父容器: SpringConfig

创建子容器: SpringMvcConfig

管理Service/DAO/事务等

管理Controller/视图解析等

可以访问父容器Bean

不能访问子容器Bean

  • 父容器(Root ApplicationContext):由 SpringConfig 加载,管理 Service、DAO、事务等基础组件。
  • 子容器(Servlet ApplicationContext):由 SpringMvcConfig 加载,管理 Controller、视图解析器等 Web 组件。

子容器可以访问父容器中的 Bean,反之则不行。为了避免混乱,通常将两个配置分离,扫描不同的包。

四、业务层开发

1 ) 实体类 Book

对应数据库表 tbl_book(字段:id, type, name, description)。

package com.wb.domain;
 
public class Book {
    private Integer id;
    private String type;
    private String name;
    private String description;
 
    @Override 
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", type='" + type + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
}

2 ) 数据访问层 BookDao

使用 MyBatis 注解直接绑定 SQL。注意注释掉的 @Insert 是一种省略字段列表的写法,两种均可。

package com.wb.dao;
 
import com.wb.domain.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
 
import java.util.List;
 
public interface BookDao {
 
    // 省略字段列表的写法:insert into tbl_book values(null,#{type},#{name},#{description})
    @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})")
    public void save(Book book);
 
    @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
    public void update(Book book);
 
    @Delete("delete from tbl_book where id = #{id}")
    public void delete(Integer id);
 
    @Select("select * from tbl_book where id = #{id}")
    public Book getById(Integer id);
 
    @Select("select * from tbl_book")
    public List<Book> getAll();
}

3 ) 业务接口与实现

BookService 接口:定义业务方法,添加 @Transactional 实现声明式事务。

package com.wb.service;
 
import com.wb.domain.Book;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.List;
 
@Transactional 
public interface BookService {
    /*
	保存 
	@param book 
	@return 
     */
    public boolean save(Book book);
 
    /*
	修改 
	@param book 
	@return 
     */
    public boolean update(Book book);
 
    /*
	按id删除 
	@param id 
	@return 
     */
    public boolean delete(Integer id);
 
    /*
	按id查询 
	@param id 
	@return 
     */
    public Book getById(Integer id);
 
    /*
	查询全部 
	@return 
     */
    public List<Book> getAll();
}

BookServiceImpl:注入 BookDao,实现具体逻辑。

package com.wb.service.impl;
 
import com.wb.dao.BookDao;
import com.wb.domain.Book;
import com.wb.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.List;
 
@Service 
public class BookServiceImpl implements BookService {
    @Autowired 
    private BookDao bookDao;
 
    public boolean save(Book book) {
        bookDao.save(book);
        return true;
    }
 
    public boolean update(Book book) {
        bookDao.update(book);
        return true;
    }
 
    public boolean delete(Integer id) {
        bookDao.delete(id);
        return true;
    }
 
    public Book getById(Integer id) {
        return bookDao.getById(id);
    }
 
    public List<Book> getAll() {
        return bookDao.getAll();
    }
}

注:目前增删改操作直接返回 true,真实项目中可通过异常捕获返回 false,或在后续结合 AOP 统一处理。

4 ) 事务管理配置

事务管理已通过以下三步完成:

  1. SpringConfig 上添加 @EnableTransactionManagement。
  2. JdbcConfig 中配置 PlatformTransactionManager Bean。
  3. BookService 接口上添加 @Transactional。

这样,Service 中的所有方法都将运行在事务中。当方法正常结束时事务提交,抛出 RuntimeException 时事务回滚。

五、控制器层开发(原始返回)

在没有统一返回格式之前,BookController 直接返回实体类、布尔值或 List。这是最初版本(对应 springmvc_08_ssm)。

package com.wb.controller;
 
import com.wb.domain.Book;
import com.wb.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.List;
 
@RestController 
@RequestMapping("/books")
public class BookController {
 
    @Autowired 
    private BookService bookService;
 
    @PostMapping 
    public boolean save(@RequestBody Book book) {
        return bookService.save(book);
    }
 
    @PutMapping 
    public boolean update(@RequestBody Book book) {
        return bookService.update(book);
    }
 
    @DeleteMapping("/{id}")
    public boolean delete(@PathVariable Integer id) {
        return bookService.delete(id);
    }
 
    @GetMapping("/{id}")
    public Book getById(@PathVariable Integer id) {
        return bookService.getById(id);
    }
 
    @GetMapping 
    public List<Book> getAll() {
        return bookService.getAll();
    }
}

这种写法会导致前端收到格式不统一的数据:增删改返回 true/false,查单个返回 JSON 对象,查全部返回 JSON 数组。前端解析时需要判断类型,非常不便。于是我们需要引入表现层数据封装。

六、接口测试

1 ) Service层测试

使用 Spring 整合 JUnit,测试 Service 方法。

package com.wb.service;
 
import com.wb.config.SpringConfig;
import com.wb.domain.Book;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import java.util.List;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {
 
    @Autowired 
    private BookService bookService;
 
    @Test 
    public void testGetById() {
        Book book = bookService.getById(1);
        System.out.println(book);
    }
 
    @Test 
    public void testGetAll() {
        List<Book> all = bookService.getAll();
        System.out.println(all);
    }
}

2 ) Controller接口测试

启动 Tomcat 后,使用 Postman 发送请求:

操作方法URL请求体/参数
新增POST/books{"type":"...","name":"...","description":"..."}
修改PUT/books{"id":1,"type":"...","name":"...","description":"..."}
删除DELETE/books/1无
查单个GET/books/1无
查全部GET/books无

此时返回的数据格式各异,为后续统一返回格式埋下伏笔。

七、表现层数据封装协议

1 ) 前后端数据交互的痛点

在没有统一格式的情况下,前端收到的响应五花八门:

  • 增删改:true 或 false(布尔值)
  • 查单个:{"id":1,"type":"...","name":"...","description":"..."}(对象)
  • 查全部:[{"id":1,...},{"id":2,...}](数组)

前端需要针对不同接口编写不同的解析逻辑,维护成本高。而且当操作失败时,前端无法仅通过数据本身判断操作是否成功,也不知道失败的原因。

2 ) 协议演进过程

我们通过逐步分析,设计出一个通用的返回模型:

演进阶段问题解决方案
1. 原始返回格式不统一,解析困难将所有数据放入一个统一模型
2. 增加数据字段数据都在 data 中,但无法区分操作类型增加状态码 code
3. 增加状态码能区分操作,但无法区分成功/失败规定状态码末位:1 成功,0 失败
4. 增加消息字段失败时需要给用户提示信息增加 msg 字段

最终确定的数据模型包含三个字段:

  • data:实际返回的数据(可为任意类型)。
  • code:状态码,用于标识操作类型和成败。
  • msg:消息,主要用于失败时携带错误提示。

3 ) 统一返回格式设计

Result

-Object data

-Integer code

-String msg

+Result()

+Result(Integer code, Object data)

+Result(Integer code, Object data, String msg)

«constant»

Code

+Integer SAVE_OK = 20011

+Integer DELETE_OK = 20021

+Integer UPDATE_OK = 20031

+Integer GET_OK = 20041

+Integer SAVE_ERR = 20010

+Integer DELETE_ERR = 20020

+Integer UPDATE_ERR = 20030

+Integer GET_ERR = 20040

状态码设计规则:

  • 前三位表示操作类型(200=成功类,也可自定义),第四位表示具体操作(1新增、2删除、3修改、4查询),末位 1 表示成功,0 表示失败。

示例:

  • 新增成功:{ "code": 20011, "data": true }
  • 查询失败:{ "code": 20040, "data": null, "msg": "数据查询失败,请重试!" }

八、统一返回格式落地实现

1 ) 状态码类 Code

package com.wb.controller;
 
//状态码 
public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;
 
    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;
}

2 ) 返回结果类 Result

package com.wb.controller;
 
public class Result {
    private Object data;
    private Integer code;
    private String msg;
 
    public Result() {
    }
 
    public Result(Integer code, Object data) {
        this.data = data;
        this.code = code;
    }
 
    public Result(Integer code, Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }
 
    public Object getData() {
        return data;
    }
 
    public void setData(Object data) {
        this.data = data;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public void setCode(Integer code) {
        this.code = code;
    }
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

3 ) 改造后的 BookController

将所有方法返回值改为 Result,内部根据操作结果构造相应的返回对象。

package com.wb.controller;
 
import com.wb.domain.Book;
import com.wb.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.List;
 
@RestController 
@RequestMapping("/books")
public class BookController {
 
    @Autowired 
    private BookService bookService;
 
    @PostMapping 
    public Result save(@RequestBody Book book) {
        boolean flag = bookService.save(book);
        return new Result(flag ? Code.SAVEOK : Code.SAVEERR, flag);
    }
 
    @PutMapping 
    public Result update(@RequestBody Book book) {
        boolean flag = bookService.update(book);
        return new Result(flag ? Code.UPDATEOK : Code.UPDATEERR, flag);
    }
 
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = bookService.delete(id);
        return new Result(flag ? Code.DELETEOK : Code.DELETEERR, flag);
    }
 
    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        Book book = bookService.getById(id);
        Integer code = book != null ? Code.GETOK : Code.GETERR;
        String msg = book != null ? "" : "数据查询失败,请重试!";
        return new Result(code, book, msg);
    }
 
    @GetMapping 
    public Result getAll() {
        List<Book> bookList = bookService.getAll();
        Integer code = bookList != null ? Code.GETOK : Code.GETERR;
        String msg = bookList != null ? "" : "数据查询失败,请重试!";
        return new Result(code, bookList, msg);
    }
}

改造过程详解:

原方法原返回类型新返回类型核心变化
savebooleanResult根据 flag 选择 SAVEOK 或 SAVEERR
updatebooleanResult根据 flag 选择 UPDATEOK 或 UPDATEERR
deletebooleanResult根据 flag 选择 DELETEOK 或 DELETEERR
getByIdBookResult判断 book 是否为 null,设置 code 和 msg
getAllList<Book>Result判断 bookList 是否为 null,设置 code 和 msg

注意:查询全部时,返回空集合([])仍视为成功,只有返回 null 才视为失败。

4 ) Postman测试验证

启动项目后,使用 Postman 测试各接口:

新增成功:

{
    "code": 20011,
    "data": true,
    "msg": null 
}

查询单个成功:

{
    "code": 20041,
    "data": {
        "id": 1,
        "type": "技术",
        "name": "Spring实战",
        "description": "一本好书"
    },
    "msg": ""
}

查询不存在的数据:

{
    "code": 20040,
    "data": null,
    "msg": "数据查询失败,请重试!"
}

查询全部成功:

{
    "code": 20041,
    "data": [
        { "id": 1, "type": "...", "name": "...", "description": "..." },
        { "id": 2, "type": "...", "name": "...", "description": "..." }
    ],
    "msg": ""
}

至此,所有接口返回格式完全统一,前端只需判断 code 即可知道操作结果,并从 data 中获取数据,必要时展示 msg 信息。

总结

本文从零开始,完整演示了 SSM 整合的全过程,并在此基础上引入了表现层数据封装,使后端接口返回的数据格式统一、语义清晰。核心要点回顾:

  1. 配置类整合:通过 SpringConfig、JdbcConfig、MyBatisConfig、SpringMvcConfig、ServletConfig 五个 Java 配置类完成 Spring + SpringMVC + MyBatis 的整合,完全摒弃 XML。
  2. 分层开发:Domain → DAO(注解 SQL) → Service(事务) → Controller(RESTful API),结构清晰。
  3. 事务管理:通过 @EnableTransactionManagement、事务管理器 Bean 和 @Transactional 实现声明式事务。
  4. 统一返回格式:设计 Result 和 Code 类,将增删改查的返回值统一封装,包含状态码、数据和消息,极大方便了前后端协作。
  5. 测试驱动:分别使用 JUnit 测试 Service 层,Postman 测试 Controller 层,确保功能正确。

掌握这些内容后,你将能够快速搭建一个标准化的 SSM 后端服务,并为后续的微服务或前后端分离项目打下坚实基础。

Java SSM 框架(详解) SSM 框架(Spring + SpringMVC + MyBatis)是 Java Web 开发中的主流技术组合,凭借其轻量级、高效性和灵活性,成为开发者的首选。Spring 通过控制反转(IoC)和面向切面编程(AOP)简化企业级应用开发;SpringMVC 基于 MVC 模式,简化 Web 层开发;MyBatis 则通过灵活的 SQL 映射简化数据库操作。SSM 框架的核心优势包括轻量高效、灵活可定制以及强大的社区支持。在实际应用中,SSM 框架通过合理的项目结构、依赖配置和配置文件 阅读详情

相关推荐

SSM项目的基本目录结构

一个完整的SSM(Spring+SpringMVC+MyBatis)项目理应包含以下几个目录结构:上面是一个普通的maven项目。

m0_74977981的博客 1253

SSM框架详解

SSM框架是指将Spring、SpringMVC和MyBatis三个技术框架结合起来使用的一种开发模式。它的目标是通过整合这三个框架的优势,实现高效、灵活、可扩展的Web应用程序开发。Spring:提供了IoC(Inverse of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)等功能,简化了企业级应用的开发流程。

m0_72410588的博客 3万+

教小白学ssm框架:初识ssm框架

**备注**:在使用Java EE语言进行后端项目开发的过程中,使用最普遍的框架便是SSM框架,要想利用SSM框架来进行后端项目的开发,首先便是对SSM框架有一个基本的了解与掌握,了解SSM框架中各层次的关系,以及SSM框架各层次的整合步骤。

小白_xm 7066

SSM整合,手把手教程,详解思路讲解

SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容),常作为数据源较简单的web项目的框架。虽然现在后端主流开发API的框架是springboot,但ssm的学习依然重要,也是springboot的基石。 很多人说ssm配置起来太麻烦了,不如springboot,看完我这篇,让你在ssm阶段像SpringBoot一样快速搭建,大大提高开发效率 项目搭建 一,工程创建 1.新建Ma

liyingjie2001的博客 1万+

SSM框架快速入门:MyBatis与JavaWeb整合教程

SSM框架是Spring、SpringMVC和MyBatis三大框架的组合简称,是目前主流的Java EE企业级应用开发框架。它以Spring为核心,整合了SpringMVC和MyBatis两个子框架,实现了表现层、业务层和持久层的解耦,使得系统各层的职责更加清晰,便于维护和扩展。ORM(Object-Relational Mapping)对象关系映射是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

weixin_34640289的博客 1019

Java Maven SSM整合框架实战教程

SSM框架是Spring、SpringMVC和MyBatis三个框架整合而成,分别对应Java Web应用的三个主要层次:数据持久层、业务逻辑层和展示层。Maven是一个项目管理和构建自动化工具,它基于项目对象模型(POM)的概念,能够管理项目的依赖关系、生命周期、构建等。Maven不仅仅是一个构建工具,它还提供了一个统一的方式来构建和管理项目,无论是Java、C#还是其他语言。它能够处理编译、测试、打包、部署等构建周期内的各个环节,使开发者从繁琐的构建工作中解放出来,专注于代码编写。

weixin_35987118的博客 1146

SSM框架整合(2020基础版)

文章目录一、SSM框架简介1.1、基本概念1.2、环境准备1.3、SSM整合思路 一、SSM框架简介 1.1、基本概念 三层架构:   开发架构一般都是基于两种形式:一种是C/S架构,也就是客户端/服务器,另一种是B/S架构,也就是浏览器服务器。   在JavaEE开发中,几乎全都是基于B/S架构的开发。那么在B/S架构中,系统标准的三层架构包括:表现层、业务层、持久层。其中每一层都分工明确: ...

qq_25083447的博客 2万+

快速掌握SSM框架整合实战小项目

SSM(Spring + Spring MVC + MyBatis)框架整合是当前Java Web开发中主流的轻量级解决方案。Spring负责业务逻辑层的Bean管理和依赖注入,Spring MVC处理HTTP请求与响应,MyBatis则专注于持久层的数据交互。三者结合,既解耦清晰又开发高效,尤其适合中小型项目。相比传统的Java EE开发方式,SSM框架通过配置化和注解简化了开发流程,提升了可维护性。

weixin_36235398的博客 819

最通俗易懂的ssm框架整合讲解

文章目录环境Mybatis1、数据库配置文件2、配置 MybatisSpring 整合 Mybatis1、context:property-placeholder标签作用?2、数据库连接池3、配置 SqlSessionFactory 对象4、配置扫描dao接口包整合 SpringMVCweb.xml 文件是如何执行的?1、执行顺序2、init-param标签3、load-on-startup标签springmvc 配置文件是如何执行的?1、mvc:annotation-driven作用?2、mvc:defa

沸羊羊_ 5459

SSM基础框架项目快速整合实战

本文还有配套的精品资源,点击获取 简介:SSM基础框架是Java Web开发常用的三大组件集成,包括Spring、SpringMVC和MyBatis。本文旨在通过详细的步骤介绍如何快速整合SSM框架,并通过配置jar包和核心文件,为开发者提供一个快速搭建项目环境的方法。SSM框架提供了依赖注入、面向切面编程、MVC架构、数据访问和持久层操作等功能,通过这些组件的整合,能够实...

weixin_32661831的博客 1071

SSM框架整合包:快速搭建Java Web项目

是Spring MVC用来查找处理器映射的核心接口。默认情况下,Spring提供了多种的实现。然而,在某些情况下,开发者可能需要根据特定需求来定义自己的。自定义实现的步骤创建一个类实现接口。实现getHandler方法来定义如何根据请求找到对应的处理器。在Spring配置文件中注册该实现。代码块示例@Override// 自定义逻辑来确定handler// 假设我们根据请求路径确定handler。

weixin_35949153的博客 761

【愚公系列】2023年10月 Java教学课程 162-Spring MVC框架的SSM整合

SSM整合指的是将Spring、Spring MVC、MyBatis三个框架集成在一起,以便更好地开发Java Web应用程序。它们之间的整合可以提高开发效率,简化配置,减少重复代码,提高代码重用性。Spring作为IoC容器和AOP框架,可以管理Bean的生命周期,简化代码结构;Spring MVC作为Web框架,可以方便地处理请求和响应;MyBatis作为持久层框架,可以简化数据库操作。SSM整合后,可以通过注解来简化配置,使开发更加高效快速。/*** 封装结果信息*/@Data。

愚公智库 5万+

SSM框架快速入门与实践模板

SSM框架是Java EE开发中的重要技术栈,它整合了Spring、Spring MVC和MyBatis三个框架,各自承担着不同的开发层面职责,为现代Web应用的构建提供了强大的支持。本章节将对SSM框架做一个全面的基础性介绍,为之后深入探讨各个框架的核心功能和高级特性打下坚实的基础。SSM框架是一种整合模式,它将Spring的轻量级控制反转(IoC)和面向切面编程(AOP)特性,Spring MVC的Web开发框架以及MyBatis的半自动ORM功能结合起来。

weixin_27645199的博客 978

SSM框架整合实战:从入门到精通

SSM框架(Spring+SpringMVC+MyBatis)是Java企业级开发的经典组合,通过分层架构实现高效开发。Spring负责IoC容器和事务管理,SpringMVC处理Web请求,MyBatis简化数据库操作。文章详细解析了SSM的整合原理、核心配置和开发流程,包括环境搭建、分层实现(Controller/Service/Mapper)、事务管理和性能优化技巧,并提供了用户管理模块的完整CRUD示例。同时介绍了全局异常处理、拦截器等扩展功能,以及常见问题的解决方案。SSM框架的分层思想和整

2401_83675559的博客 1224

DPABI安装教程

DPABI是是中科院心理研究所严超赣老师团队开发的一款磁共振脑影像数据分析工具包。基于SPM,在安装DPABI之前需要安装好SPM,才能正常使用。SPM的安装方法见文matlab2021a版本条件下安装spm_kidllll的博客-优快云博客 1、下载安装包 下载地址:DPABI: a toolbox for Data Processing & Analysis for Brain Imaging | The R-fMRI Network 2、将下载好的dpabi文件夹移动到matl..

qq_42356925的博客 1万+

UR10e+D435+ag95夹爪 gazebo 仿真记录(一)

学习仿真环境gazebo下利用UR10e机械臂搭建模拟平台,此博客用于记录搭建过程!!主要参考光头明明、总有一天全城的人都要高看我们和bug404_三位博主。最终自己功能包的主要参考了bug404_的ur_platform,感觉这个结构比较合理。运行环境:Ubuntu18.04+Ros-melodic+Gazebo9。

Forbiven的博客 6330

【Java开发】Java热门框架深入开发第9篇:今日内容,一、SSM整合【重点】【附代码文档】

学习目标 一、Spring简介 2 初识Spring 3 Spring体系结构 二、IOC和DI入门案例【重点】 五、Bean的生命周期【了解】 问题导入 1 生命周期相关概念介绍 2 代码演示 3 Bean销毁时机 六、依赖注入(DI配置) 1 依赖注入方式【重点】 2 依赖自动装配【理解】 3 集合注入 今日目标 一、第三方资源配置管理 1 管理DataSource连接池对象 2 加载properties属性文件【重点】 四、Spring整合其他技术【重点】 二、AOP案例 1 案例-测量业务层接口万次

小帅说java 860

带有验证码的爆破(包含Burp suite工具爆破)

关于含有验证码爆破的一些总结!

weixin_43960066的博客 8699

Springboot快速入门及SSM整合

Springboot快速入门及SSM整合!!!

LLM | Agent | RAG | Java 2942

解决OpenCASCADE性能瓶颈:显示加速与三角剖分优化全攻略

本文深入探讨OpenCASCADE在工业设计和CAD建模中的性能优化策略,重点解决显示加速与三角剖分等核心瓶颈问题。通过智能刷新控制、显示数据结构优化和动态LOD技术,显著提升渲染效率和交互体验,适用于复杂场景下的三维可视化应用。

weixin_30752699的博客 344

LightRAG实战:5分钟快速搭建一个轻量级法律问答系统(附完整代码)

本文通过实战指南,详细介绍了如何使用LightRAG技术快速搭建一个轻量级法律问答系统。该方案通过构建扁平化实体关系网络和混合检索策略,在5分钟内即可完成从环境准备到智能问答的完整流程,并附有完整代码,为中小团队和个人开发者提供了高效、低成本的AI应用解决方案。

time3的博客 280

Java框架——SSM整合

AJAX初体验异步可理解为局部刷新,同步指需要按部就班地完成一整套流程AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。

qq_51936245的博客 2537

手把手拆解固态电池成本:2030年真能比液态电池便宜30%吗?

本文深度解析固态电池成本结构,探讨2030年实现比液态电池便宜30%的可行性路径。通过拆解正极材料、负极材料和固态电解质的成本演变,分析关键技术对降本的影响,并预测产业链协同效应下的成本优化趋势。文章指出,在材料创新、设备国产化和政策支持等多重因素推动下,固态电池有望在2030年实现显著降本目标。

kite3的博客 406

SSM框架整合详细过程

整合思路 由于SpringMVC是Spring框架中的一个模块,SSM框架的整合只涉及Spring与MyBatis的整合及Spring MVC与MyBatis的整合。如下图所示 整合环境 SSM框架整合需要使用Spring、SpringMVC、Mybaits依赖的jar包。项目创建后,需要将这些jar导入。如果是maven工程,只需在pom文件中添加以下依赖包,具体内容如下: <!--spring核心依赖包--> <dependency> <gro

guoyp2126的博客 3173

详解k-means++

一、概述 定义:k-means++是一种为k-means聚类算法选择初始值(或“种子”)的算法。它是NP-hard k-means问题的一种近似算法,它是一种避免标准k-means算法有时发现的较弱聚类的方法。 K-means与K-means++:原始K-means算法最开始随机选取数据集中K个点作为聚类中心,而K-means++按照如下的思想选取K个聚类中心:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时:距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚

qq_42364307的博客 3万+

遗传算法解整数规划IntCon

x = ga(fun,nvars,A,b,[],[],lb,ub,nonlcon,IntCon) IntCon就是代表整数的参量,描述的是哪几个自变量是0-1整数变量。比如navrs设置有4个变量,设置IntCon为[2 3],代表第2和第3个变量是整数。 再比如设置IntCon=2:2:nvars,代表偶数项的变量是整数。 值得注意的是一旦设置了非空的IntCon,则Aeqandbeqmust be an empty entry ([]), andnonlconmust re...

jianti9962的博客 9220
上一篇: Java框架快速入门: SpringMVC RESTful风格开发实战
下一篇: Java框架快速入门: SSM整合进阶——统一异常处理与前后端联调实战
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值