一、读写分离介绍 当使用Spring Boot开发数据库应用时,读写分离是一种常见的优化策略。读写分离将读操作和写操作分别分配给不同的数据库实例,以提高系统的吞吐量和性能。
读写分离实现主要是通过动态数据源功能实现的,动态数据源是一种通过在运行时动态切换数据库连接的机制。它允许应用程序根据不同的条件或配置选择不同的数据源,以实现更灵活和可扩展的数据库访问。
二、实现读写分离 - 基础 1、配置主数据库和从数据库的连接信息 # 主库配置 spring.datasource.master.jdbc-url=jdbc:mysql://ip:port/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource.master.username=master spring.datasource.master.password=123456 spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver # 从库配置 spring.datasource.slave.jdbc-url=jdbc:mysql://ip:port/slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource.slave.username=slave spring.datasource.slave.password=123456 spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver 2、创建主数据库和从数据库的数据源配置类 通过不同的条件限制和配置文件前缀可以完成不同数据源的创建工作,不止是主从也可以是多个不同的数据库。
主库数据源配置:
@Configuration @ConditionalOnProperty("spring.datasource.master.jdbc-url") public class MasterDataSourceConfiguration { @Bean("masterDataSource") @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } } 从库数据源配置:
@Configuration @ConditionalOnProperty("spring.datasource.slave.jdbc-url") public class SlaveDataSourceConfiguration { @Bean("slaveDataSource") @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } } 3、创建主从数据源枚举 public enum DataSourceTypeEnum { /** * 主库 */ MASTER, /** * 从库 */ SLAVE, ; } 4、创建动态路由数据源 这儿做了一个开关,可以控制读写分离的开启和关闭工作,可以将操作全部切换到主库进行。然后根据上下文中的数据源类型来返回不同的数据源类型枚举。
本文将带你了解如何使用 Spring Boot 和 Open Telemetry 为 Kafka 生产者和消费者配置追踪功能。我们会使用 Micrometer 库发送追踪信息,并使用Jaeger来存储和可视化这些数据。Spring Kafka内置了与 Micrometer 的集成,用于 KafkaTemplate 和监听容器。本文还会介绍何配置 Spring Kafka observability (可观察性),以在追踪中添加自定义标签(Tag)。
源码 你可以在 GitHub 上找到完整的源码。Clone 项目后,进入 kafka 目录,按照说明进行操作即可。
依赖 添加如下依赖,其中 Spring Boot Starter 和 Spring Kafka 用于发送或接收消息,Spring Boot Actuator 和 Micrometer Tracing Open Telemetry 桥接器用于自动生成与每条消息相关的追踪,最后是 opentelemetry-exporter-otlp,用于将追踪导出到应用外。
对于本文中的两个示例 Spring Boot 应用,依赖都是相同的。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-otel</artifactId> </dependency> <dependency> <groupId>io.
响应压缩是 Web 应用一种常见的优化手段,通过压缩算法减小传输数据的体积,提高传输效率、节约带宽。客户端接收到数据后,使用相同的算法对数据进行解压从而获取到原始数据。
客户端和服务器需要通过 Header 来协商双方支持的压缩算法。
Accept-Encoding:请求头,告诉服务器客户端支持的压缩算法(多个使用逗号分割)。例如:Accept-Encoding: gzip, deflate。 Content-Encoding:响应头,告诉客户端当前 Payload 使用的编码方式(压缩算法)。例如:Content-Encoding: gzip。 常用的压缩算法如下:
gzip deflate br JDK 提供了对 GZIP 压缩算法的实现:GZIPOutputStream 和 GZIPInputStream,我们可以用它们来实现 Gzip 压缩和解压缩。
使用 Gzip 压缩响应 在 Spring Boot 应用中创建一个 Controller,使用 GZIPOutputStream 把一张图片文件(20 KB)压缩后响应给客户端。
package cn.springdoc.demo.web.controller; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import java.util.zip.GZIPOutputStream; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @RestController @RequestMapping("/demo") public class DemoController { @GetMapping public void file (HttpServletRequest request, HttpServletResponse response) throws IOException { // 20.
1、简介 本文将会带你学习如何使用 Spring Boot 以及 React JavaScript 框架开发一个简单的 RESTful CRUD 应用。
2、Spring Boot 2.1、Maven 依赖 在 pom.xml 中添加如下依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.4.4</version> <scope>test</scope> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.200</version> <scope>runtime</scope> </dependency> </dependencies> 如上,添加了 Web、Test、Spring Data JPA 以及 H2 依赖。
2.2、创建 Model 创建 Client 实体类,有 id、name 和 email 属性:
@Entity @Table(name = "client") public class Client { @Id @GeneratedValue private Long id; private String name; private String email; // 省略构造函数和 get/set 方法 } 2.
SQLite 是一种嵌入式关系型数据库管理系统(RDBMS),使用 C 语言开发,以其简单性、轻量级和零配置而闻名。不需要独立的服务器,可以直接嵌入到应用中。支持事务,支持各种编程语言。是移动应用和嵌入式系统的首选数据库解决方案。
本文将会带你了解如何在 Spring Boot 中配置和使用 SQLite。
创建 Spring Boot 应用 创建一个示例 Spring Boot 应用。在 pom.xml 添加 spring-boot-starter-jdbc 和 SQLite 驱动 sqlite-jdbc 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> </dependency> sqlite-jdbc 已经被 Spring Boot 纳入了版本控制,所以在项目继承了 spring-boot-starter-parent 的情况下,添加此依赖不用声明版本号。
配置属性 在 application.yaml 中配置如下属性:
spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: org.sqlite.JDBC url: "jdbc:sqlite:D:\\app.db" 使用默认的数据源实现 HikariDataSource。通过 driver-class-name属性指定 SQLite 的驱动类。url 配置指定了 SQLite 数据库文件的位置,可以是相对路径或者绝对路径。如果文件不存在,会被创建。
测试 得益于 Spring Boot 对数据源开箱即用的支持,完成上述配置后,SQLite 数据库已经就绪可以使用了。
创建测试类:
import java.time.LocalDateTime; import java.
1、概览 在设计 RESTful API 的时候,往往会纠结于到底是用 PUT 还是 POST 请求?
本文将会带你了解在 RESTful API 中 PUT 和 POST 请求之间的区别以及它们的应用场景。
2、PUT 与 POST 在典型的 REST 架构中,客户端以 HTTP 方法的形式向服务器发送请求,以创建、检索、修改或删除资源。虽然可以使用 PUT 和 POST 来创建资源,但它们在预期应用方面有很大的不同。
根据 RFC 2616 标准,POST 方法应该用于请求服务器将所附实体作为现有资源(由请求 URI 标识)的子级接受。这意味着使用 POST 方法调用将在资源集合下创建一个子资源。
相反,PUT 方法应该用于请求服务器将所附实体存储在请求的 URI 下。如果请求 URI 指向服务器上的现有资源,则提供的实体将被视为现有资源的修改版本。因此,PUT 方法调用要么创建一个新资源,要么更新现有资源。
这两种方法的另一个重要区别是,PUT 是一种幂等方法,而 POST 不是。例如,多次调用 PUT 方法将创建或更新同一资源。相比之下,多次 POST 请求将导致多次创建同一资源。
3、示例应用 使用 Spring Boot 创建一个简单的 RESTful Web 应用来演示 PUT 和 POST 请求的区别。
3.1、Maven 依赖 需要在 pom.xml 中添加 Spring Web、Spring Data JPA 和 H2 内存数据库依赖:
1、简介 本文将带你了解如何在 Spring Boot 项目中处理 Multipart 文件上传请求。
Multipart 请求可以包含多个独立的请求体部分,通常用于文件上传。除了文件以外,还可以同时上传表单、JSON、XML 等等数据。
2、使用 @ModelAttribute 一个简单的示例,使用表单发送包含了员工姓名和文件的数据。
创建 Employee 类:
public class Employee { private String name; private MultipartFile document; } 然后,使用 Thymeleaf 渲染表单:
<form action="#" th:action="@{/employee}" th:object="${employee}" method="post" enctype="multipart/form-data"> <p>name: <input type="text" th:field="*{name}" /></p> <p>document:<input type="file" th:field="*{document}" multiple="multiple"/> <input type="submit" value="upload" /> <input type="reset" value="Reset" /></p> </form> 注意,需要将表单的 enctype 属性声明为 multipart/form-data。
最后,创建一个接受表单数据(包括 Multipart 文件)的方法:
@RequestMapping(path = "/employee", method = POST, consumes = { MediaType.
Minio 是一个用 Golang 开发的开源的对象存储服务器,它基于 Amazon S3 协议,提供了简单而强大的存储解决方案。可以在本地部署或云环境中使用。也支持分布式部署,并具有高可用性和容错性。
本文将会带你了解如何在 Linux 中通过 Docker 的方式来安装、配置 Minio,以及如何在 Spring Boot 应用中通过 Minio 官方 SDK 上传文件资源到 Minio 服务器。
安装 Minio 在 Linux 下,使用 Docker 的方式安装 Minio 最简单。首先确保你在服务器上安装了 Docker,并且需要 root 用户来执行下面的安装过程。
首先,创建存放文件资源的目录:
mkdir -p ~/minio/data 上述命令在 $HOME 目录下创建了 /minio/data 文件夹,用于存放资源。
接着,使用 Docker 运行 Minio 容器:
docker run \ -d \ -p 9000:9000 \ -p 9090:9090 \ --name minio-server \ -v ~/minio/data:/data \ -e "MINIO_ROOT_USER=admin" \ -e "MINIO_ROOT_PASSWORD=minio858896" \ quay.
1、概览 本文将会带你了解在 Spring Boot 启动时出现 ApplicationContextException 异常的原因,以及解决办法:
ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean 2、可能的原因 异常信息,“由于缺少 ServletWebServerFactory Bean,无法启动 ServletWebServerApplicationContext” 说明了一切。ApplicationContext 中没有配置 ServletWebServerFactory Bean。
该异常主要出现在 Spring Boot 无法启动 ServletWebServerApplicationContext 时。为什么会这样?因为 ServletWebServerApplicationContext 使用包含的 ServletWebServerFactory Bean 来启动自身。
一般来说,Spring Boot 通过 SpringApplication.run 方法来启动 Spring 应用。
SpringApplication 类会根据应用类型(如,Web 应用),尝试创建正确的 ApplicationContext。
用于确定是否是 Web 应用的算法来自于一些依赖,如 spring-boot-starter-web。缺少这些依赖,可能是导致异常的原因之一。
另一个原因是 Spring Boot 启动类中缺少 @SpringBootApplication 注解。
3、重现异常 创建一个示例应用,故意在 main 类上不添加 @SpringBootApplication 注解。
public class MainEntryPoint { public static void main(String[] args) { SpringApplication.
i18n(Internationalization),即国际化。目的是为了使软件、应用或网站能够适应不同的语言、地区,用户可以选择他们熟悉的语言进行交互,为所有用户提供一致的体验。
本文将会带你了解如何使用 Spring Boot + Freemarker 实现国际化。
假设我们有一个登录页面,其中有 2 个输入框,分别用于输入 用户名 和 密码。对于使用不同语言的用户,需要显示不同的输入框名称。
创建项目 在 pom.xml 中添加 web 和 freemarker stater 依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> 配置 定义国际化资源文件 通常我们会把项目中需要国际化的内容定义在不同的 properties 文件中,通过 properties 文件名的后缀来表示资源的 语言 和 国别。
在 resources 目录下创建 i18n 目录,用于存放国际化资源文件。接着,在 i18n 目录中创建如下 3 个 properties 文件,如下:
message.properties
# message.properties 的内容 # 空着就行 message_en_US.properties
# message_en_US.properties 的内容 # 英文 login.username=USERNAME login.password=PASSWORD message_zh_CN.properties
# message_zh_CN.properties 的内容 # 中文 login.