当前位置: 首页 > news >正文

第3章——SSM整合

一、整合持久层框架MyBatis

1.准备数据库表及数据

创建数据库:springboot

使用IDEA工具自带的mysql插件来完成表的创建和数据的准备:



创建表

表创建成功后,为表准备数据,如下:

2.创建SpringBoot项目

使用脚手架创建Spring Boot项目

引入mysql驱动以及mybatis的启动器

依赖如下:

<!--mybatis的启动器-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency>
<!--mysql的驱动依赖-->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>

注意,之前也提到过:

Spring Boot官方提供的启动器的名字规则:spring-boot-starter-xxx

第三方(非Spring Boot官方)提供的启动器的名字规则:xxx-spring-boot-starter

3.编写数据源配置

前面提到过,Spring Boot配置统一可以编写到application.properties中,配置如下:

以上的配置属于连接池的配置,连接池使用的是Spring Boot默认的连接池:HikariCP

4.编写实体类Vip

package org.example1.bean;public class Vip {private Long id;private String name;private String cardNumber; // 数据库字段 card_numberprivate String birth;public Vip(Long id, String name, String cardNumber, String birth) {this.id = id;this.name = name;this.cardNumber = cardNumber;this.birth = birth;}public Vip() {}public Vip(String name, String cardNumber, String birth) {this.name = name;this.cardNumber = cardNumber;this.birth = birth;}@Overridepublic String toString() {return "Vip{" +"id=" + id +", name='" + name + '\'' +", cardNumber='" + cardNumber + '\'' +", birth='" + birth + '\'' +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCardNumber() {return cardNumber;}public void setCardNumber(String cardNumber) {this.cardNumber = cardNumber;}public String getBirth() {return birth;}public void setBirth(String birth) {this.birth = birth;}
}

以上代码可以使用第三方库Lombok进行改造,后面再说。

5.编写Mapper接口

创建repository包,在该包下新建VipMapper接口,代码如下:

package org.example1.repository;import org.example1.bean.Vip;import java.util.List;public interface VipMapper {/*** 保存会员信息* @param vip 会员信息* @return 1表示保存成功。*/int insert(Vip vip);/*** 获取所有会员信息* @return 会员列表*/List<Vip> selectAll();
}

6.编写Mapper接口的XML配置文件

在`resources`目录下新建`mapper`目录,将来的`mapper.xml`配置文件放在这个目录下。

安装`MyBatisX`插件,该插件可以根据我们编写的`VipMapper`接口自动生成mapper的XML配置文件。

然后在`VipMapper`接口上:alt+enter

接下来,你会看到Mapper接口中方法报错了,可以在错误的位置上使用`alt+enter`,选择`Generate statement`:

接下来就是编写SQL语句了,最终VipMapper.xml文件的配置如下:

7.添加Mapper的扫描

在Spring Boot的入口程序上添加如下的注解,来完成`VipMapper`接口的扫描:

8.编写service

接口

package org.example1.service;
import org.example1.bean.Vip;
import java.util.List;
public interface VipService {/*** 保存会员信息* @param vip  会员信息* @return true表示成功,false表示失败*/boolean save(Vip vip);/*** 查看会员列表* @return 会员列表*/List<Vip> findAll();}

package org.example1.service.impl;import org.example1.bean.Vip;
import org.example1.repository.VipMapper;
import org.example1.service.VipService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class VipServiceImpl implements VipService {@Autowiredprivate VipMapper vipMapper;@Overridepublic boolean save(Vip vip) {return vipMapper.insert(vip) == 1;}@Overridepublic List<Vip> findAll() {return vipMapper.selectAll();}
}

9.告诉MyBatis框架MapperXML文件的位置

在`application.properties`配置文件中进行如下配置:

10.测试整合MyBatis是否成功

在Spring Boot主入口程序中获取Spring上下文对象ApplicationContext,从Spring容器中获取VipService对象,然后调用相关方法进行测试:


测试结果中可以看到cardNumber属性没有赋值成功,原因是:表中的字段名叫做card_number,和实体类Vip的属性名cardNumber对应不上。解决办法两个:

  • 第一种方式:查询语句使用as关键字起别名,让查询结果列名和实体类的属性名对应上。

再次测试:

  • 第二种方式:通过配置自动映射

application.properties配置文件中进行如下配置:

mybatis.configuration.map-underscore-to-camel-case=true

map-underscore-to-camel-case 是一个配置项,主要用于处理数据库字段名与Java对象属性名之间的命名差异。在许多数据库中,字段名通常使用下划线(_)分隔单词,例如 first_name 或 last_name。而在Java代码中,变量名通常使用驼峰式命名法(camel case),如 firstName 和 lastName。

当使用MyBatis作为ORM框架时,默认情况下它会将SQL查询结果映射到Java对象的属性上。如果数据库中的字段名与Java对象的属性名不一致,那么就需要手动为每个字段指定相应的属性名,或者使用某种方式来自动转换这些名称。

map-underscore-to-camel-case 这个配置项的作用就是在查询结果映射到Java对象时,自动将下划线分隔的字段名转换成驼峰式命名法。这样可以减少手动映射的工作量,并提高代码的可读性和可维护性。

mapper的xml文件中的sql语句仍然使用*的方式:

测试结果如下:

二、 Lombok库

Lombok 是一个 Java 库,它可以通过注解的方式减少 Java 代码中的样板代码。Lombok 自动为你生成构造函数、getter、setter、equals、hashCode、toString 方法等,从而避免了手动编写这些重复性的代码。这不仅减少了出错的机会,还让代码看起来更加简洁。

Lombok只是一个编译阶段的库,能够帮我们自动补充代码,在Java程序运行阶段并不起作用。(因此Lombok库并不会影响Java程序的执行效率)

例如我们有这样一个java源文件`User.java`,代码如下:

@Data
public class User{private String name;
}

以上代码在程序的编译阶段,Lombok库会将User.java文件编译生成这样的User.class字节码文件:

public class com.powernode.lomboktest.model.User {public com.powernode.lomboktest.model.User();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic java.lang.String getName();Code:0: aload_01: getfield      #7                  // Field name:Ljava/lang/String;4: areturnpublic void setName(java.lang.String);Code:0: aload_01: aload_12: putfield      #7                  // Field name:Ljava/lang/String;5: returnpublic boolean equals(java.lang.Object);Code:0: aload_11: aload_02: if_acmpne     75: iconst_16: ireturn7: aload_18: instanceof    #8                  // class com/powernode/lomboktest/model/User11: ifne          1614: iconst_015: ireturn16: aload_117: checkcast     #8                  // class com/powernode/lomboktest/model/User20: astore_221: aload_222: aload_023: invokevirtual #13                 // Method canEqual:(Ljava/lang/Object;)Z26: ifne          3129: iconst_030: ireturn31: aload_032: invokevirtual #17                 // Method getName:()Ljava/lang/String;35: astore_336: aload_237: invokevirtual #17                 // Method getName:()Ljava/lang/String;40: astore        442: aload_343: ifnonnull     5446: aload         448: ifnull        6551: goto          6354: aload_355: aload         457: invokevirtual #21                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z60: ifne          6563: iconst_064: ireturn65: iconst_166: ireturnprotected boolean canEqual(java.lang.Object);Code:0: aload_11: instanceof    #8                  // class com/powernode/lomboktest/model/User4: ireturnpublic int hashCode();Code:0: bipush        592: istore_13: iconst_14: istore_25: aload_06: invokevirtual #17                 // Method getName:()Ljava/lang/String;9: astore_310: iload_211: bipush        5913: imul14: aload_315: ifnonnull     2318: bipush        4320: goto          2723: aload_324: invokevirtual #24                 // Method java/lang/Object.hashCode:()I27: iadd28: istore_229: iload_230: ireturnpublic java.lang.String toString();Code:0: aload_01: invokevirtual #17                 // Method getName:()Ljava/lang/String;4: invokedynamic #28,  0             // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;9: areturn
}

通过字节码可以看到Lombok库的@Data注解可以帮助我们生成无参构造器settergettertoStringhashCodeequals

1.Lombok 的主要注解

@Data

  • 等价于 @ToString, @EqualsAndHashCode, @Getter@Setter, @RequiredArgsConstructor.

  • 用于生成:必要参数的构造方法、getter、setter、toString、equals 和 hashcode 方法。

@Getter / @Setter

  • 分别用于生成所有的 getter 和 setter 方法。

  • 可以作用于整个类,也可以作用于特定的字段。

@NoArgsConstructor

  • 生成一个无参构造方法。

@AllArgsConstructor

  • 生成一个包含所有实例变量的构造器。

@RequiredArgsConstructor

  • 生成包含所有被 final 修饰符修饰的实例变量的构造方法。

  • 如果没有的实例变量,则自动生成无参数构造方法。

@ToString / @EqualsAndHashCode:

  • 用于生成 toString 和 equals/hashCode 方法。
  • 这两个注解都有exclude属性,通过这个属性可以定制toString、hashCode、equals方法。


Lombok 主要注解详解及代码示例


添加依赖

在 Maven 的 pom.xml 文件中添加 Lombok 依赖:

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope>
</dependency>

IDEA中安装Lombok插件

高版本的IntelliJ IDEA工具默认都是绑定Lombok插件的,不需要再额外安装:

Lombok插件不是必须要安装的,为了提高开发效率以及开发者的体验,安装Lombok插件是有必要的。

也就是说安装了Lombok插件之后,编写代码的时候,才会有方法的提示功能。

2.Lombok的其他常用注解

@Value

@Builder

@Singular

@Slf4j

......

@Value

该注解会给所有属性添加final,给所有属性提供getter方法,自动生成toStringhashCodeequals

通过这个注解可以创建不可变对象。

测试程序:

可以查看一下字节码,你会发现,@Value注解的作用只会生成:全参数构造方法、getter方法、hashCode、equals、toString方法。(没有setter方法。)

@Builder

GoF23种设计模式之一:建造模式

建造模式(Builder Pattern)属于创建型设计模式。GoF23种设计模式之一。

用于解决对象创建时参数过多的问题。它通过将对象的构造过程与其表示分离,使得构造过程可以逐步完成,而不是一次性提供所有参数。建造模式的主要目的是让对象的创建过程更加清晰、灵活和可控。

简而言之,建造模式用于:

  1. 简化构造过程:通过逐步构造对象,避免构造函数参数过多。

  2. 提高可读性和可维护性:让构造过程更加清晰和有序。

  3. 增强灵活性:允许按需配置对象的不同部分。

这样可以更方便地创建复杂对象,并且使得代码更加易于理解和维护。


建造模式的代码

建造模式代码如下:

package org.example1;// 定义一个 Person 类,用于表示一个人的信息
public class Person {// 一般建造模式的 bean 属性使用 final 进行修饰,确保对象的不可变性private final String name;private final int age;// 私有构造函数,只能通过建造器来创建 Person 对象private Person(String name, int age) {// 将传入的 name 参数赋值给当前对象的 name 属性this.name = name;// 将传入的 age 参数赋值给当前对象的 age 属性this.age = age;}// 获取姓名的方法public String getName() {return name;}// 获取年龄的方法public int getAge() {return age;}// 重写 toString 方法,方便打印 Person 对象的信息@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}// 通过这个公开的静态方法获取建造器对象public static PersonBuilder builder() {return new PersonBuilder();}// 静态内部类,用于构建 Person 对象public static class PersonBuilder {// 用于存储要构建的 Person 对象的姓名private String name;// 用于存储要构建的 Person 对象的年龄private int age;// 设置姓名的方法,返回当前建造器对象,以便进行链式调用public PersonBuilder name(String name) {this.name = name;return this;}// 设置年龄的方法,返回当前建造器对象,以便进行链式调用public PersonBuilder age(int age) {this.age = age;return this;}// 构建 Person 对象的方法public Person build() {return new Person(name, age);}}
}


建造模式就是可以把参数拆出来,一个一个建造?

没错,建造模式的确能够把参数拆分,逐个进行构建。下面为你详细介绍建造模式及其参数拆分构建的原理:

定义

建造模式(Builder Pattern)属于创建型设计模式,其作用是将一个复杂对象的构建和表示分离,如此一来,相同的构建过程就能创建出不同的表示。

把参数拆出来逐个构建的原理

  • 链式调用:建造模式一般会在建造器类里为每个参数提供对应的设置方法,这些方法会返回建造器自身,这样就能实现链式调用。你可以逐个调用这些方法来设置参数。
  • 封装构建逻辑:构建复杂对象时,不同参数的设置可能涉及复杂的逻辑,建造模式把这些逻辑封装在建造器类的各个方法中,用户仅需调用这些方法就能完成参数设置,而不用关心内部的具体实现。
  • 最终构建:当所有参数都设置好之后,调用建造器的 build() 方法,该方法会依据设置好的参数创建出最终的对象。

使用@Builder注解自动生成建造模式的代码

该注解可以直接帮助我们生成以上的代码。使用@Builder注解改造以上代码。

@Singular

@Singular注解是辅助@Builder注解的。

被建造的对象的属性是一个集合,这个集合属性使用@Singular注解进行标注的话,可以连续调用集合属性对应的方法完成多个元素的添加。如果没有这个注解,则无法连续调用方法完成多个元素的添加。代码如下:

先说不使用Singular的方法

运行结果:

使用@Singular注解

运行结果:

@Slf4j

Lombok 支持多种日志框架的注解,可以根据你使用的日志框架选择合适的注解。以下是 Lombok 提供的部分日志注解及其对应的日志框架:

@Log4j:

自动生成一个 org.apache.log4j.Logger 对象。

适用于 Apache Log4j 1.x 版本。

@Slf4j:

自动生成一个 org.slf4j.Logger 对象。

适用于 SLF4J(Simple Logging Facade for Java),这是一种日志门面,可以与多种实际的日志框架(如 Logback、Log4j 等)集成。

@Log4j2:

自动生成一个 org.apache.logging.log4j.Logger 对象。

适用于 Apache Log4j 2.x 版本。

使用示例

假设我们有一个类 `ExampleClass`,并且我们想要使用 SLF4J 作为日志框架,我们可以这样使用 `@Slf4j` 注解:

import lombok.extern.slf4j.Slf4j;@Slf4j
public class UserService {public void login(){log.info("登录验证...");}// 测试public static void main(String[] args) {UserService userService = new UserService();userService.login();}
}

在这个例子中,`log` 是一个静态成员变量,表示一个 `org.slf4j.Logger` 对象。Lombok 自动生成了这个日志对象,并且你可以直接使用它来进行日志记录。

选择合适的注解

选择哪个注解取决于你使用的日志框架。例如:

  • 如果你使用的是 SLF4J,可以选择 `@Slf4j`。
  • 如果你使用的是 Log4j 1.x,可以选择 `@Log4j`。
  •  如果你使用的是 Log4j 2.x,可以选择 `@Log4j2`。

注意事项

确保在使用这些注解之前,已经在项目中引入了相应的日志框架依赖。例如,如果你使用 SLF4J,你需要在项目中添加 SLF4J 的依赖,以及一个具体的日志实现(如 Logback)。对于其他日志框架,也需要相应地添加依赖。

示例依赖

如果你使用 Maven 项目,并且选择了 SLF4J + Logback 的组合,可以添加以下依赖:

<!--Slf4j日志规范-->
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.16</version>
</dependency>
<!--Slf4j日志实现:logback-->
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.5.11</version>
</dependency>

通过这些日志注解,你可以方便地在类中使用日志记录功能,而无需手动创建日志对象。

执行结果:

三、MyBatis逆向生成

MyBatis逆向工程:使用IDEA插件可以根据数据库表的设计逆向生成MyBatis的Mapper接口 与 MapperXML文件。

1.安装插件free mybatis tools

2.在IDEA中配置数据源

3.生成MyBatis代码放到SpringBoot项目中

在表上右键:Mybatis-Generator

代码生成后,如果在IDEA中看不到,这样做(重新从硬盘加载):

注意:生成的VipMapper接口上自动添加了@Repository注解,这个注解没用,删除即可。

4.编写mybatis相关配置

application.properties属性文件的配置:

spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456mybatis.mapper-locations=classpath:com/powernode/springboot/repository/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

5.编写测试程序

对初始的Vip进行修改

测试

到此,Spring Boot整合MyBatis结束!

四、 整合SpringMVC(SSM整合)

SSM整合:Spring + SpringMVC + MyBatis

Spring Boot项目本身就是基于Spring框架实现的。因此SSM整合时,只需要在整合MyBatis框架之后,引入`web启动器`即可完成SSM整合。

1.使用脚手架创建SpringBoot项目

添加依赖:web启动器、mybatis启动器、mysql驱动依赖、lombok依赖

项目结构:

2.使用free mybatis tool插件逆向生成MyBatis代码

springboot数据库中的t_vip表逆向生成mybatis代码。这里不再赘述。

3.整合MyBatis

编写数据源的配置

在主入口类上添加@MapperScan注解

4.编写service

编写`VipService`接口:

public interface VipService {/*** 根据id获取会员信息* @param id 会员标识* @return 会员信息*/Vip getById(Long id);
}

编写`VipServiceImpl`实现类:

5.编写controller

编写`VipController`,代码如下:

@RestController
public class VipController {@Autowiredprivate VipService vipService;@GetMapping("/vip/{id}")public Vip detailById(@PathVariable("id") Long id){Vip vip = vipService.getById(id);return vip;}
}

6.启动服务器测试

执行SpringBoot项目主入口的main方法,启动Tomcat服务器:

打开浏览器访问:

到此为止,SSM框架就集成完毕了,通过这个集成也可以感觉到SpringBoot简化了SSM三大框架的集成。

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误-CSDN博客

相关文章:

  • 学习设计模式《十二》——命令模式
  • LeetCode 热题 100 34. 在排序数组中查找元素的第一个和最后一个位置
  • ComfyUI 工作流
  • Ref vs. Reactive:Vue 3 响应式变量的最佳选择指南
  • 安卓基础(生成APK)
  • SpringBoot 自动化部署实战:CI/CD 整合方案与避坑指南
  • Prompt Engineering Notes
  • 深入解析Java中的装箱与拆箱机制
  • Python——day46通道注意力(SE注意力)
  • 23套橙色系精选各行业PPT模版分享
  • Java常用的判空方法
  • 在MyBatis中设计SQL返回布尔值(Boolean)有几种常见方法
  • 计算机视觉与深度学习 | 基于MATLAB的图像特征提取与匹配算法总结
  • Transformer-BiGRU多变量时序预测(Matlab完整源码和数据)
  • 【Linux】Linux基础指令3
  • scikit-learn机器学习
  • 计算机视觉顶刊《International Journal of Computer Vision》2025年5月前沿热点可视化分析
  • LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
  • Java + Spring Boot + Mybatis 实现批量插入
  • 逻辑回归与Softmax
  • 王也天的个人资料/网络seo
  • 做房地产网站广告销售/关键词搜索技巧
  • 黔西南北京网站建设/百度秒收录软件工具
  • 如何对网站做镜像/360推广联盟
  • 泰州泛亚信息做网站怎么样/深圳关键词推广优化
  • 做企业网站专用词/怎么样做推广最有效