# 是什么 SSM

SSM 是三个框架的简写,本别是 Spring,SpringMVC,Mybatis,这三个框架作为 JavaWeb 强有力的支撑件,极大地提高了开发效率,降低了维护成本,是 Java 程序员学习 Web 技术的必经之路(至少现在是这样)

在此之前,我希望你能熟练掌握,额,哪怕不熟练也要了解 Web 部分的老祖:请求,响应以及 Servlet 技术,这些技术能帮助你更好、更快、更流畅的掌握 SSM 技术。

其次本文主要讲解 SSM 整合的相关细节,并不会深入讲解 Spring,SpringMVC,Mybatis 每个框架的知识,希望大家在看本文之前能了解 Spring,SpringMVC,Mybatis 单个框架的使用方法。

# 整合开始

首先我先放出最终的整合状态,其实也不一定非要按照我这样来做。

1.png bean 包:大多数的实体类

config 包:整合的核心配置类

controller 包:外部控制器暴露点

mapper 包:Mybiats SQL 标准化

service 包:业务逻辑,包含接口以及实现

resource 包:资源文件、配置文件

webapp:前端资源

那么接下来我将带着大家一步一步的来做,从创建项目到最终完成整合。

# 创建项目(Maven 构建方式)

选择新建一个项目(或模块),选择 Maven Archetype 形式创建,我给他命名叫做 SSM_demo。

JDK:1.8(Java 8)

Archetype:选择最后以 webapp 结尾的,这是一个创建模板

组 ID:公司域名反写

2.png

# 创建包结构

在 main 目录下创建 java 目录和必要的包结构

3.png

# 依赖导入、必要启动配置

我们需要在 pom.xml 文件下导入我们 SSM 所需要的依赖,并配置必要的启动项。

# 导入详解

第一步:导包

需要思考我们需要什么依赖:

junit:单元测试。

spring-webmvc:整个依赖就比较强大了她不仅包含了 SpringMVC 的部分也包含了 Spring-Context 部分,其实也不难理解,因为 SpringMVC 是基于 Spring 开发的,那也就必然包含了 Spring 框架的部分。

至此我们还剩下数据库的部分,我们继续将其填充完整。

Mybatis:这个是 Mybatis 的核心依赖。

mybatis-spring:整个是将 Mybatis 与 Spring 进行整合。

spring-jdbc:简化 Java 应用程序与数据库之间的交互,Spring JDBC 是 MyBatis-Spring 的底层依赖,提供了连接管理、事务管理等基础功能。

mysql-connector-java:这个是 MySQL 的驱动依赖。

druid:数据库连接池。

servlet-api:Spring MVC 架构是基于 Servlet 规范的。它使用 Servlet API 来处理和分发 Web 请求,以及与 Web 容器进行交互。

jackson-databind:用于在 Java 对象和 JSON 数据之间进行序列化(对象到 JSON)和反序列化(JSON 到对象)的核心部分。

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.10.RELEASE</version>
  </dependency>
  <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>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.0.6</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.31</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4</version>
  </dependency>
</dependencies>

一定要为我们的 servlet-api 配置作用域为 provided,这是非常大的一个坑点!!!

如果您不将 servlet-api 的作用域设置为 provided ,而是将其作用域设置为默认的 compile ,则可能会导致以下问题和影响:

  1. 冲突问题: 如果您的应用程序包含了自己的 Servlet API 实现(例如 jar 包),而 Web 容器也提供了自己的实现,可能会导致冲突和不稳定性。
  2. 版本不一致: 不同的 Web 容器可能使用不同版本的 Servlet API,如果您将 API 包含在应用程序中,可能会导致版本不一致的问题。
  3. 应用程序大小增加: 将 Servlet API 包含在应用程序中会增加应用程序的大小,尽管这在绝大多数情况下可能不会对性能产生明显影响,但仍然会浪费一些资源。
  4. 维护困难: 如果您在多个项目中重复地包含 Servlet API,可能会导致维护上的困难,特别是在更新版本或切换到不同的 Web 容器时。
<scope>provided</scope>

第二步:启动配置

在这里你可以选择外挂 Tomcat 和 Maven 插件的两种启动方式,在这里我选择插件法,因为外挂启动真的是太慢了 QWQ

pom.xml 文件中的 build 标签下配置 tomcat 插件:

<build>
  <finalName>SSM_demo</finalName>
  <plugins>
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
      <configuration>
        <port>80</port>
        <path>/</path>
      </configuration>
    </plugin>
  </plugins>
</build>

80 端口为启动端口,你也可以进行修改,例如修改到 8090

<port>8090</port>

第三步:Java 版本配置

其实这是一个坑点我们需要在 pom 文件加上这两行:

<properties>
  <maven.compiler.source>8</maven.compiler.source>
  <maven.compiler.target>8</maven.compiler.target>
</properties>

这是在声明我们的 Java 版本为 java8,这个一定要根据我们项目的 java 版本来填写

# 最终展示

pom.xml
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.KarryCode</groupId>
  <artifactId>SSM_demo</artifactId>
  <packaging>war</packaging>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <version>1.0-SNAPSHOT</version>
  <name>SSM_demo Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
    <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>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.31</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.16</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.4</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>SSM_demo</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>80</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

# 创建 JDBC.properties 文件

resource 目录下创建 jdbc.properties

JdbcProperties
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = 
jdbc.username = 
jdbc.password =

等号后面的根据自己的需要进行填写

为了测试,我还创建的一张表:

4.png

这是我的生成脚本:

生成脚本
create table tb_book
(
    id          int auto_increment
        primary key,
    type        varchar(20)  null,
    name        varchar(50)  null,
    description varchar(255) null
);

# 创建 mapper 代理包

首先在 resource 目录下创建与 java 源代码目录一样的包,切记一定要以 “/” 的分割形式去创建,

例如:com/KarryCode/mapper

创建好后,后置在这个目录下创建对应的 xml,我们稍后再说!

# 创建配置文件(配置类)

这部分将以配置类的形式进行配置。

# Spring_Mybatis 整合配置

首先在 config 包下创建 Spring_Mybatis 配置类

package com.KarryCode.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @ClassName SpringConfig
 * @Description TODO Spring 核心配置类
 * @Version 1.0
 */
@Configuration                                  //TODO 核心配置唯一标识
@ComponentScan({"com.KarryCode.service","com.KarryCode.bean"})     //TODO 注解扫描指定包
@PropertySource("classpath:jdbc.properties")    //TODO 加载 JDBC 配置类
@MapperScan("com.KarryCode.mapper")             //TODO MyBatis 基于包扫描方式识别 Mapper
@EnableTransactionManagement                    //TODO 事务的自动代理,注解驱动
public class Spring_MybatisConfig {
    @Bean
    //TODO DruidDataSource 数据源的产生
    public DataSource dataSource(
            @Value("${jdbc.driver}") String driver,
            @Value("${jdbc.url}") String url,
            @Value("${jdbc.username}") String username,
            @Value("${jdbc.password}") String password
    ) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        // 里面还可以配置更多关于数据库连接池的选项.......
        return dataSource;
    }
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        //TODO sqlSessionFactoryBean MybatisBeans 加载
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        //TODO 平台事务管理
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

具体内容不展开讲解,主要概述一下注解以及方法的作用:

@MapperScan:指定包扫描的路径。

DataSource dataSource:数据源的产生。

PlatformTransactionManager transactionManager:事务交由 Spring 管理。

# SpringMVC 整合配置

同样地,在 config 包下创建 SpringMvcConfig

package com.KarryCode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @PackageName com.KarryCode.config
 * @ClassName SpringMvcConfig
 * @Description TODO
 * @Version 1.0
 */
@Configuration
@EnableWebMvc
@ComponentScan("com.KarryCode.controller")
public class SpringMvcConfig {
}

# Servlet-api 整合配置

同样地,在 config 包下创建 ServletConfig

package com.KarryCode.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{Spring_MybatisConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

此时的目录结构是这样的:

5.png

至此,整合已经基本完成!

# Bean 实体类创建

根据数据库里的以及逻辑关系创建 Bean 实体,在这里我先创建一个 Book 实体

package com.KarryCode.bean;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @PackageName com.KarryCode.bean
 * @ClassName Book
 * @Description TODO
 * @Version 1.0
 */
public class Book {
    private Integer id;
    private String type;
    private String name;
    private String description;
    // 省略 getter/setter/ 构造器(有参 / 无参)/toString
}

# mapper 接口创建

在 mapper 包下创建一个 mapper 接口 BookMapper

package com.KarryCode.mapper;
import com.KarryCode.bean.Book;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @PackageName com.KarryCode.mapper
 * @ClassName BookMapper
 * @Description TODO
 * @Version 1.0
 */
public interface BookMapper {
    @Insert("insert into ssm_db.tb_book values (null,#{type},#{name},#{description})")
    int save(Book book);
    @Update("update ssm_db.tb_book set type=#{type},name=#{name},description=#{description} where id=#{id}")
    int update(Book book);
    @Delete("delete from ssm_db.tb_book where tb_book.id=#{id}")
    int delete(Integer id);
    @Select("select * from ssm_db.tb_book where id=#{id}")
    @ResultType(Book.class)
    Book getBookById(Integer id);
    @Select("select * from ssm_db.tb_book")
    List<Book> getBookList();
}

通过注解方式配置了增删改查四种方法

# mapper 代理 xml 创建

虽然没啥用,但是创建了也没什么坏处,在 resource 的对应目录下创建 BookMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.KarryCode.mapper.BookMapper">
</mapper>

# Service 逻辑创建

BookService 接口

package com.KarryCode.service;
import com.KarryCode.bean.Book;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @ClassName BookService
 * @Description TODO
 * @Version 1.0
 */
@Transactional
public interface BookService {
    /**
     * @param book
     * @return boolean
     * @Author KarryLiu_刘珂瑞
     * @Date 2023/8/14 下午 10:58
     * @Description TODO 保存
     */
    boolean save(Book book);
    /**
     * @param book
     * @return boolean
     * @Author KarryLiu_刘珂瑞
     * @Date 2023/8/14 下午 10:58
     * @Description TODO 修改
     */
    boolean update(Book book);
    /**
     * @param id
     * @return boolean
     * @Author KarryLiu_刘珂瑞
     * @Date 2023/8/14 下午 10:58
     * @Description TODO 根据 id 删除
     */
    boolean delete(Integer id);
    /**
     * @param id
     * @return edu.beihua.bean.Book
     * @Author KarryLiu_刘珂瑞
     * @Date 2023/8/14 下午 10:59
     * @Description TODO 根据 id 查询
     */
    Book getBookById(Integer id);
    /**
     * @param
     * @return java.util.List<edu.beihua.bean.Book>
     * @Author KarryLiu_刘珂瑞
     * @Date 2023/8/14 下午 10:59
     * @Description TODO 查询全部
     */
    List<Book> getBookList();
}

BookService 接口实现

package com.KarryCode.service.impl;
import com.KarryCode.bean.Book;
import com.KarryCode.mapper.BookMapper;
import com.KarryCode.service.BookService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @Date 2023/8/14 下午 10:43
 * @ClassName BookServiceImpl
 * @Description TODO
 * @Version 1.0
 */
@Service
public class BookServiceImpl implements BookService {
    @Resource
    private BookMapper bookMapper;
    @Override
    public boolean save(Book book) {
        System.out.println("save=====>Service");
        int save = bookMapper.save(book);
        if (save>0){
            return true;
        }else {
            return false;
        }
    }
    @Override
    public boolean update(Book book) {
        System.out.println("update=====>Service");
        bookMapper.update(book);
        return true;
    }
    @Override
    public boolean delete(Integer id) {
        System.out.println("delete=====>Service");
        bookMapper.delete(id);
        return true;
    }
    @Override
    public Book getBookById(Integer id) {
        System.out.println("getBookById=====>Service");
        Book book = bookMapper.getBookById(id);
        return book;
    }
    @Override
    public List<Book> getBookList() {
        System.out.println("getBookList=====>Service");
        return bookMapper.getBookList();
    }
}

# Spring—Mybatis 通路检测

编写测试类,观察输出

import com.KarryCode.bean.Book;
import com.KarryCode.config.Spring_MybatisConfig;
import com.KarryCode.service.BookService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.List;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @PackageName PACKAGE_NAME
 * @ClassName mybatisTest
 * @Description TODO
 * @Version 1.0
 */
public class mybatisSpringTest {
    @Test
    public void testMybatisSpring(){
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Spring_MybatisConfig.class);
        BookService bookService = annotationConfigApplicationContext.getBean(BookService.class);
        List<Book> bookList = bookService.getBookList();
        System.out.println(bookList);
    }
}
输出

信息: {dataSource-1} inited
getBookList=====>Service
[Book {id=1, type=‘计算机’, name=‘软件工程’, description=‘吼吼吼吼’}, Book {id=2, type=‘文学’, name=‘儒家经典’, description=‘儒家好书啊!!!!!’}, Book {id=3, type=‘科技’, name=‘百科全书’, description=‘真不错!!!!’}, Book {id=4, type=‘美术’, name=‘当代顶流美术’, description=‘好书啊好书!!!!’}, Book {id=6, type=‘科技’, name=‘百科全书’, description=‘真不错!!!!’}, Book {id=7, type=‘科技’, name=‘百科全书’, description=‘真不错!!!!’}]

进程已结束,退出代码 0

至此,Spring—Mbatis 整合完成

# 构建 Controller

在 controller 包下创建 BookController

package com.KarryCode.controller;
import com.KarryCode.bean.Book;
import com.KarryCode.service.BookService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
 * @Author KarryLiu
 * @Creed may all the beauty be blessed
 * @PackageName com.KarryCode.controller
 * @ClassName BookController
 * @Description TODO
 * @Version 1.0
 */
@RestController
@Transactional
@RequestMapping("/books")
public class BookController {
    @Resource
    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 getBookById(@PathVariable Integer id) {
        return bookService.getBookById(id);
    }
    @GetMapping
    public List<Book> getBookList() {
        return bookService.getBookList();
    }
}

符合 Restful 设计建议。

# 启动 Tomcat

6.png

# Postman 接口测试

# 存书测试

7.png

8.png

success

9.png

# 查书测试

# 查询全部

10.png

# 指定 id 查书

11.png

# 更新书

12.png

13.png

# 删除测试

14.png

15.png

所有接口测试调通,至此 SSM 整合完毕

# 总结

其实 SSM 整合还是比较简单的,通过三个框架的配置就可以完成了,后面的工作都是在进行业务创建。

好了!本篇文章到这里就结束了,有什么不理解的地方或者有疑问的地方请在评论区留言,或者添加我的联系方式,欢迎各位大佬积极批评讨论!谢谢!

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

KarryLiu 微信支付

微信支付

KarryLiu 支付宝

支付宝