SpringBoot與Druid整合,實現主從數據庫同步

通過引入主從數據庫同步系統,可以顯著提升平臺的性能和穩定性,同時保證數據的一致性和安全性。Druid連接池也提供了強大的監控和安全防護功能,使得整個系統更加健壯和可靠。

我們為什么選擇Druid?

  • 高效的連接管理:Druid 提供了高效的物理連接復用機制,能夠快速獲取和釋放數據庫連接,減少連接建立和關閉的開銷。

  • 異步初始化:支持異步初始化連接池,提高應用啟動速度。

  • 詳細的統計信息:Druid 內置了豐富的統計功能,可以收集 SQL 執行情況、慢查詢記錄等詳細數據,幫助我們更好地進行性能調優。

  • 防火墻規則:支持配置防火墻規則,限制哪些 IP 地址可以訪問數據庫,增強安全性。

  • SQL 防注入:提供 WallFilter 插件,防止 SQL 注入攻擊,保護數據庫不受惡意 SQL 的影響。

  • 多數據源支持:Druid 支持配置多個數據源,非常適合實現讀寫分離等高級場景。在我們的項目中,主從數據庫的配置正是利用了這一特性。

代碼實操

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><!-- Druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
</dependencies>

application.yml

server:port:8080spring:
datasource:type:com.alibaba.druid.pool.DruidDataSourcedruid:master:url:jdbc:mysql://localhost:3306/master_db?useSSL=false&serverTimezone=UTCusername:rootpassword:rootslave:url:jdbc:mysql://localhost:3307/slave_db?useSSL=false&serverTimezone=UTCusername:rootpassword:rootmybatis-plus:
configuration:log-impl:org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations:classpath*:mybatis-mapper.xml

動態數據源上下文持有者

package?com.example.demo.config;publicclass?DynamicDataSourceContextHolder?{privatestaticfinal?ThreadLocal<String> contextHolder =?new?ThreadLocal<>();public?static?void?setDataSourceType(String dataSourceType)?{contextHolder.set(dataSourceType);}public?static?String?getDataSourceType()?{return?contextHolder.get();}public?static?void?clearDataSourceType()?{contextHolder.remove();}
}

數據源配置

package?com.example.demo.config;import?com.alibaba.druid.pool.DruidDataSource;
import?org.springframework.beans.factory.annotation.Value;
import?org.springframework.context.annotation.Bean;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import?javax.sql.DataSource;
import?java.util.HashMap;
import?java.util.Map;@Configuration
publicclass?DataSourceConfig?{@Value("${spring.datasource.druid.master.url}")private?String masterUrl;@Value("${spring.datasource.druid.master.username}")private?String masterUsername;@Value("${spring.datasource.druid.master.password}")private?String masterPassword;@Value("${spring.datasource.druid.slave.url}")private?String slaveUrl;@Value("${spring.datasource.druid.slave.username}")private?String slaveUsername;@Value("${spring.datasource.druid.slave.password}")private?String slavePassword;@Beanpublic?DataSource?dynamicDataSource()?{Map<Object, Object> targetDataSources =?new?HashMap<>();targetDataSources.put("master", masterDataSource());targetDataSources.put("slave", slaveDataSource());AbstractRoutingDataSource abstractRoutingDataSource =?new?AbstractRoutingDataSource() {@Overrideprotected?Object?determineCurrentLookupKey()?{return?DynamicDataSourceContextHolder.getDataSourceType();}};abstractRoutingDataSource.setDefaultTargetDataSource(masterDataSource());abstractRoutingDataSource.setTargetDataSources(targetDataSources);return?abstractRoutingDataSource;}@Beanpublic?DataSource?masterDataSource()?{DruidDataSource dataSource =?new?DruidDataSource();dataSource.setUrl(masterUrl);dataSource.setUsername(masterUsername);dataSource.setPassword(masterPassword);return?dataSource;}@Beanpublic?DataSource?slaveDataSource()?{DruidDataSource dataSource =?new?DruidDataSource();dataSource.setUrl(slaveUrl);dataSource.setUsername(slaveUsername);dataSource.setPassword(slavePassword);return?dataSource;}
}

實體類

package?com.example.demo.entity;import?com.baomidou.mybatisplus.annotation.IdType;
import?com.baomidou.mybatisplus.annotation.TableId;
import?com.baomidou.mybatisplus.annotation.TableName;@TableName("product")
publicclass?Product?{@TableId(type = IdType.AUTO)private?Long id;private?String name;private?Double price;// getters and setters
}

Mapper接口

package?com.example.demo.mapper;import?com.baomidou.mybatisplus.core.mapper.BaseMapper;
import?com.example.demo.entity.Product;public?interface?ProductMapper?extends?BaseMapper<Product>?{
}

mybatis-mapper.xml

<?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">
<mapper?namespace="com.example.demo.mapper.ProductMapper"><select?id="selectById"?resultType="com.example.demo.entity.Product">SELECT * FROM product WHERE id = #{id}</select><insert?id="insert"?parameterType="com.example.demo.entity.Product">INSERT INTO product (name, price) VALUES (#{name}, #{price})</insert></mapper>

Service接口

package?com.example.demo.service;import?com.example.demo.entity.Product;public?interface?ProductService?{Product?getProductById(Long id);boolean?saveProduct(Product product);
}

Service

package?com.example.demo.service.impl;import?com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import?com.example.demo.config.DynamicDataSourceContextHolder;
import?com.example.demo.entity.Product;
import?com.example.demo.mapper.ProductMapper;
import?com.example.demo.service.ProductService;
import?org.springframework.stereotype.Service;@Service
publicclass?ProductServiceImpl?extends?ServiceImpl<ProductMapper,?Product>?implements?ProductService?{@Overridepublic?Product?getProductById(Long id)?{DynamicDataSourceContextHolder.setDataSourceType("slave");try?{return?getById(id);}?finally?{DynamicDataSourceContextHolder.clearDataSourceType();}}@Overridepublic?boolean?saveProduct(Product product)?{DynamicDataSourceContextHolder.setDataSourceType("master");try?{return?save(product);}?finally?{DynamicDataSourceContextHolder.clearDataSourceType();}}
}

Controller

package?com.example.demo.controller;import?com.example.demo.entity.Product;
import?com.example.demo.service.ProductService;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/products")
publicclass?ProductController?{@Autowiredprivate?ProductService productService;@GetMapping("/{id}")public?Product?getProduct(@PathVariable Long id)?{return?productService.getProductById(id);}@PostMapping("/")public?boolean?addProduct(@RequestBody Product product)?{return?productService.saveProduct(product);}
}

Application

package?com.example.demo;import?org.mybatis.spring.annotation.MapperScan;
import?org.springframework.boot.SpringApplication;
import?org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public?class?DemoApplication?{public?static?void?main(String[] args)?{SpringApplication.run(DemoApplication.class,?args);}
}

測試

添加產品

curl -X POST http://localhost:8080/products/ \-H?"Content-Type: application/json"?\-d?'{"name": "Sample Product", "price": 99.99}'

Respons

true

獲取產品

curl -X GET http://localhost:8080/products/1

Respons

{"id":1,"name":"Sample Product","price":99.99}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77792.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77792.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77792.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在Linux系統中安裝MySQL,二進制包版

1、檢查是否已安裝數據庫&#xff08;rpm軟件包管理器&#xff09; rpm -qa | grep mysql rpm -qa | grep mariadb #centOS7自帶mariadb與mysql數據庫沖突2、刪除已有數據庫 rpm -e –nodeps 軟件名稱 3、官網下載MySQL包 4、上傳 # 使用FinalShell或Xshell工具上傳&#…

【含文檔+PPT+源碼】基于SpringBoot電腦DIY裝機教程網站的設計與實現

項目介紹 本課程演示的是一款 基于SpringBoot電腦DIY裝機教程網站的設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本套…

Spring Boot 緩存機制:從原理到實踐

文章目錄 一、引言二、Spring Boot 緩存機制原理2.1 緩存抽象層2.2 緩存注解2.3 緩存管理器 三、入門使用3.1 引入依賴3.2 配置緩存3.3 啟用緩存3.4 使用緩存注解3.5 實體類 四、踩坑記錄4.1 緩存鍵生成問題4.2 緩存過期與更新問題4.3 事務與緩存的一致性問題 五、心得體會5.1 …

Spark讀取Apollo配置

--conf spark.driver.extraJavaOptions-Dapp.idapollo的app.id -Denvfat -Dapollo.clusterfat -Dfat_metaapollo的meta地址 --conf spark.executor.extraJavaOptions-Dapp.idapollo的app.id -Denvfat -Dapollo.clusterfat -Dfat_metaapollo的meta地址 在spark的提交命令中&…

[逆向工程]如何理解小端序?逆向工程中的字節序陷阱與實戰解析

[逆向工程]如何理解小端序&#xff1f;逆向工程中的字節序陷阱與實戰解析 關鍵詞&#xff1a;逆向工程、小端序、字節序、二進制分析、數據解析 引言&#xff1a;為什么字節序是逆向工程師的必修課&#xff1f; 在逆向工程中&#xff0c;分析二進制數據是最基礎的任務之一。…

項目三 - 任務2:創建筆記本電腦類(一爹多叔)

在本次實戰中&#xff0c;我們通過Java的單根繼承和多接口實現特性&#xff0c;設計了一個筆記本電腦類。首先創建了Computer抽象類&#xff0c;提供計算的抽象方法&#xff0c;模擬電腦的基本功能。接著定義了NetCard和USB兩個接口&#xff0c;分別包含連接網絡和USB設備的抽象…

ElasticSearch深入解析(六):集群核心配置

1.開發模式和生產模式 Elasticsearch默認運行在開發模式下&#xff0c;此模式允許節點在配置存在錯誤時照常啟動&#xff0c;僅將警告信息寫入日志文件。而生產模式則更為嚴格&#xff0c;一旦檢測到配置錯誤&#xff0c;節點將無法啟動&#xff0c;這是一種保障系統穩定性的安…

【Prometheus-MySQL Exporter安裝配置指南,開機自啟】

目錄 1. 創建 MySQL 監控用戶2. 配置 MySQL 認證文件3. 安裝 mysqld_exporter4. 配置 Systemd 服務5. 啟動并驗證服務6. 修改Prometheus配置常見錯誤排查錯誤現象排查步驟 6. 驗證監控數據關鍵注意事項 7. Grafana看板 1. 創建 MySQL 監控用戶 mysql -uroot -p123456 # 登錄M…

redis未授權訪問漏洞學習

一、Redis常見用途 1. Redis介紹 全稱與起源: Redis全稱Remote Dictionary Service(遠程字典服務)&#xff0c;最初由antirez在2009年開發&#xff0c;用于解決網站訪問記錄統計的性能問題。發展歷程: 從最初僅支持列表功能的內存數據庫&#xff0c;經過十余年發展已支持多種…

4.27搭建用戶界面

更新 router下面的index.js添加新的children 先區分一下views文件夾下的不同vue文件&#xff1a; Home.vue是繪制home頁面的所有的表格。 Main.vue是架構頭部和左側目錄的框架的。 研究一下這個routes對象&#xff0c;就可以發現重定向redirect的奧妙所在&#xff0c;我們先把…

【MySQL】(8) 聯合查詢

一、聯合查詢的作用 由于范式的規則&#xff0c;數據分到多個表中&#xff0c;想要查詢完整的信息&#xff0c;就需要聯合查詢多張表。比如查詢學生的學生信息和所在班級的信息&#xff0c;就需要聯合查詢學生表和班級表。 二、聯合查詢過程 案例&#xff1a;查詢學生姓名為孫…

圖漾官網Sample_V1版本C++語言完整參考例子---單相機版本

文章目錄 1.參考例子 主要梳理了圖漾官網Sample_V1版本的例子 1.參考例子 主要增加了從storage區域讀取相機參數的設置&#xff0c;使用圖漾PercipioViewer軟件&#xff0c;如何將相機參數保存到srorage區&#xff0c;可參考鏈接&#xff1a;保存相機參數操作 保存參數設置 注…

關于本地端口啟動問題

如何啟動一個本地端口 1. Node.js (使用Express框架) 使用node.js的方法 注意&#xff1a;下列bash命令最好在管理員權限運行的cmd窗口中進行&#xff0c;否則可能會有權限錯誤 首先&#xff0c;確保您已經安裝了Node.js和npm。然后&#xff0c;創建一個新的Node.js項目并安…

產銷協同的作用是什么?又如何對各部門發揮作用?

目錄 一、產銷協同的對象有哪些&#xff1f; 1. 客戶需求 2. 市場趨勢 3. 供應鏈伙伴 4. 企業戰略目標 二、產銷協同的作用是什么&#xff1f; 1. 提高客戶滿意度 2. 降低企業成本 3. 增強市場競爭力 4. 優化資源配置 三、產銷協同對各部門怎么發揮作用&#xff1f;…

React Router v7 從入門到精通指南

一、設計思想與核心原理 1. 設計哲學 組件即路由&#xff1a;路由以 <Route> 組件形式聲明&#xff0c;與 React 組件樹深度集成聲明式導航&#xff1a;通過 <Link> 和 useNavigate 實現無刷新路由跳轉動態匹配機制&#xff1a;路徑參數、通配符、優先級匹配規則…

Python爬蟲實戰:獲取網yi新聞網財經信息并做數據分析,以供選股做參考

一、引言 在財經領域,股市信息對投資者意義重大。網yi新聞作為知名新聞資訊平臺,其股市板塊蘊含豐富的最新股市熱點信息。然而,依靠傳統人工方式從海量網頁數據中獲取并分析這些信息,效率低下且難以全面覆蓋。因此,利用爬蟲技術自動化抓取相關信息,并結合數據分析和機器…

Spring Boot Actuator - 應用監控與管理

一、 Spring Boot Actuator 概述 Spring Boot Actuator是Spring Boot 提供的生產級監控與管理工具集&#xff0c;用于實時監控和運維管理應用。Actuator 通過HTTP 端點&#xff08;或 JMX 端點&#xff09;暴露應用的健康狀態、性能指標、日志信息、環境配置等關鍵數據&#x…

不同類型插槽的聲明方法和對應的調用方式

在 Vue 3 中&#xff0c;slot 用于讓組件的使用者可以向組件內部插入自定義內容。Vue 3 提供了多種聲明和使用插槽的方式&#xff0c;下面為你詳細介紹不同類型插槽的聲明方法和對應的調用方式。 1. 匿名插槽 聲明方法 在組件模板中直接使用 標簽來定義匿名插槽&#xff0c;它可…

DeepSeek 聯手 Word,開啟辦公開掛模式

目錄 一、DeepSeek 與 Word 結合的神奇之處二、前期準備&#xff0c;萬事俱備2.1 了解 DeepSeek2.2 確認軟件版本2.3 賬號與密鑰獲取 三、接入方法全解析3.1 OfficeAI 插件接入3.1.1 下載與安裝插件3.1.2 配置 API 密鑰 3.2 VBA 宏接入3.2.1 啟用開發者工具3.2.2 調整信任設置3…

云鑰科技紅外短波工業相機

云鑰科技的紅外短波相機是一款基于短波紅外&#xff08;SWIR&#xff0c;波長范圍約1-3微米&#xff09;技術的成像設備&#xff0c;專為高精度檢測、全天候成像及特殊場景應用設計。以下從核心技術、性能參數、應用場景及產品優勢等方面進行詳細介紹&#xff1a; ??一、核心…