MyBatis-Flex+ShardingSphere-JDBC多數(shù)據(jù)源分庫分表實現(xiàn)
1、目的
用于動態(tài)配置ShardingSphere-JDBC實現(xiàn)配置化分庫分表
2、實現(xiàn)
2-1、導入MyBatis-Flex和ShardingSphere-JDBC的相關依賴
<dependency> <groupId>com.mybatis-flex</groupId> <artifactId>mybatis-flex-spring-boot-starter</artifactId> <version>1.9.3</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.1.1</version> </dependency>
2-2、配置初始化的數(shù)據(jù)庫連接用來加載配置,當然用配置中心來保存初始化數(shù)據(jù)的配置
spring.datasource.ds1.jdbc-url=jdbc:mysql://localhost/test?allowPublicKeyRetrieval=true spring.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.ds1.username=root spring.datasource.ds1.password=123456 spring.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
2-3、初始化數(shù)據(jù)源進行配置查詢
初始化數(shù)據(jù)源配置類:
package com.mochenli.shardingshere.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @author: MoChenLi * @description: * @createTime: 2024-06-27 21:23 */ @Configuration public class DataSourceConfig { /** * 根據(jù)配置文件構建數(shù)據(jù)源 * @return */ @Bean @ConfigurationProperties(prefix = "spring.datasource.ds1") public DataSource dataSourceOne(){ return DataSourceBuilder.create().build(); } }
數(shù)據(jù)配置表以及數(shù)據(jù)
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80034 (8.0.34) Source Host : localhost:3306 Source Schema : test Target Server Type : MySQL Target Server Version : 80034 (8.0.34) File Encoding : 65001 Date: 29/06/2024 17:52:36 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for databaseconfig -- ---------------------------- DROP TABLE IF EXISTS `databaseconfig`; CREATE TABLE `databaseconfig` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵唯一標識', `jdbc_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '數(shù)據(jù)庫連接', `driver_class_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '數(shù)據(jù)庫連接驅動', `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '數(shù)據(jù)庫連接用戶名', `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '數(shù)據(jù)庫連接密碼', `Connection_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '數(shù)據(jù)庫連接名稱', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of databaseconfig -- ---------------------------- INSERT INTO `databaseconfig` VALUES (1, 'jdbc:mysql://192.168.157.129:3310/db_order?allowPublicKeyRetrieval=true', 'com.mysql.cj.jdbc.Driver', 'root', '123456', 'server-order0'); INSERT INTO `databaseconfig` VALUES (2, 'jdbc:mysql://192.168.157.129:3311/db_order?allowPublicKeyRetrieval=true', 'com.mysql.cj.jdbc.Driver', 'root', '123456', 'server-order1'); SET FOREIGN_KEY_CHECKS = 1;
數(shù)據(jù)庫配置對象類
package com.mochenli.shardingshere.entity; import com.mybatisflex.annotation.Id; import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.Table; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 17:28 */ @Data @NoArgsConstructor @AllArgsConstructor @Table("DataBaseConfig") public class DataBaseConfig { @Id(keyType = KeyType.Auto) private Integer id; private String jdbcUrl; private String username; private String password; private String driverClassName; private String connectionName; }
mapper類
package com.mochenli.shardingshere.mapper; import com.mochenli.shardingshere.entity.DataBaseConfig; import com.mybatisflex.core.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 17:31 */ @Mapper public interface DataBaseConfigMapper extends BaseMapper<DataBaseConfig> { }
2-4、初始化ShardingDataSource數(shù)據(jù)源實現(xiàn)分庫分表
分片算法可查看鏈接
package com.mochenli.shardingshere.config; import com.mochenli.shardingshere.entity.DataBaseConfig; import com.mochenli.shardingshere.mapper.DataBaseConfigMapper; import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.datasource.FlexDataSource; import com.zaxxer.hikari.HikariDataSource; import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory; import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration; import org.apache.shardingsphere.infra.config.mode.ModeConfiguration; import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration; import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration; import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration; import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration; import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.sql.SQLException; import java.util.*; /** * @author: MoChenLi * @description: * @createTime: 2024-06-19 13:53 */ @Configuration public class ShardingConfig { private DataBaseConfigMapper dataBaseConfigMapper; public ShardingConfig(DataBaseConfigMapper dataBaseConfigMapper) throws SQLException { this.dataBaseConfigMapper = dataBaseConfigMapper; FlexDataSource flexDataSource = FlexGlobalConfig.getDefaultConfig() .getDataSource(); flexDataSource.addDataSource("getShardingDataSource",getShardingDataSource()); } /** * 配置shardingsphere的內(nèi)存模式 * @return */ @Bean public ModeConfiguration getModeConfiguration() { ModeConfiguration modeConfiguration = new ModeConfiguration("Memory", null, false); return modeConfiguration; } /** * 構建ShardingDataSource數(shù)據(jù)源 * @return * @throws SQLException */ public DataSource getShardingDataSource() throws SQLException { //查詢數(shù)據(jù)庫的數(shù)據(jù)連接配置設置到dataSourceMap當中 Map<String, DataSource> dataSourceMap = new HashMap<>(); List<DataBaseConfig> dataBaseConfigs = dataBaseConfigMapper.selectAll(); for (DataBaseConfig dataBaseConfig : dataBaseConfigs) { DataSource dataSource = createDataSource(dataBaseConfig); dataSourceMap.put(dataBaseConfig.getConnectionName(), dataSource); } //以下分片配置的規(guī)則也可持久化從數(shù)據(jù)庫查詢出來進行配置 此處用于演示所需即靜態(tài)配置 // 配置分片規(guī)則 ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); //算法相關配置 Map<String, ShardingSphereAlgorithmConfiguration> shardingSphereAlgorithmConfigurations = new HashMap<>(); Properties properties = new Properties(); properties.put("algorithm-expression","server-order$->{user_id % 2}"); ShardingSphereAlgorithmConfiguration shardingSphereAlgorithmConfiguration = new ShardingSphereAlgorithmConfiguration("INLINE",properties); Properties properties1 = new Properties(); properties1.put("sharding-count","2"); ShardingSphereAlgorithmConfiguration shardingSphereAlgorithmConfiguration1 = new ShardingSphereAlgorithmConfiguration("MOD",properties1); Properties properties2 = new Properties(); properties2.put("sharding-count","2"); ShardingSphereAlgorithmConfiguration shardingSphereAlgorithmConfiguration2 = new ShardingSphereAlgorithmConfiguration("HASH_MOD",properties2); shardingSphereAlgorithmConfigurations.put("alg_inline_userid",shardingSphereAlgorithmConfiguration); shardingSphereAlgorithmConfigurations.put("alg_mod",shardingSphereAlgorithmConfiguration1); shardingSphereAlgorithmConfigurations.put("alg_hash_mod",shardingSphereAlgorithmConfiguration2); shardingRuleConfig.setShardingAlgorithms(shardingSphereAlgorithmConfigurations); //分庫分表策略配置 Collection<ShardingTableRuleConfiguration> shardingTableRuleConfigurations = new ArrayList<>(); //分庫策略 ShardingTableRuleConfiguration shardingTableRuleConfiguration = new ShardingTableRuleConfiguration("t_order","server-order$->{0..1}.t_order$->{0..1}"); ShardingStrategyConfiguration shardingStrategyConfiguration = new StandardShardingStrategyConfiguration("user_id","alg_mod"); shardingTableRuleConfiguration.setDatabaseShardingStrategy(shardingStrategyConfiguration); //分表策略 ShardingStrategyConfiguration shardingStrategyConfigurationtable = new StandardShardingStrategyConfiguration("order_no","alg_hash_mod"); shardingTableRuleConfiguration.setTableShardingStrategy(shardingStrategyConfigurationtable); shardingTableRuleConfigurations.add(shardingTableRuleConfiguration); shardingRuleConfig.setTables(shardingTableRuleConfigurations); //配置主鍵算法生成策略 Map<String, ShardingSphereAlgorithmConfiguration> keyGenerators = new HashMap<>(); ShardingSphereAlgorithmConfiguration shardingSphereAlgorithmConfigurationsk = new ShardingSphereAlgorithmConfiguration("SNOWFLAKE",null); keyGenerators.put("alg_snowflake",shardingSphereAlgorithmConfigurationsk); shardingRuleConfig.setKeyGenerators(keyGenerators); //分布式id KeyGenerateStrategyConfiguration keyGenerateStrategyConfiguration =new KeyGenerateStrategyConfiguration("id","alg_snowflake"); shardingTableRuleConfiguration.setKeyGenerateStrategy(keyGenerateStrategyConfiguration); //屬性設置運行sql打印顯示 Properties properties3 = new Properties(); properties3.put("sql-show",true); // 創(chuàng)建ShardingDataSource DataSource dataSources = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig),properties3 ); return dataSources; } /** * 創(chuàng)建數(shù)據(jù)源連接 * @param dataBaseConfig * @return */ public static DataSource createDataSource(DataBaseConfig dataBaseConfig) { // 創(chuàng)建數(shù)據(jù)源,這里需要根據(jù)實際情況創(chuàng)建,例如使用HikariCP、Druid等連接池 HikariDataSource dataSource = new HikariDataSource(); dataSource.setDriverClassName(dataBaseConfig.getDriverClassName()); dataSource.setJdbcUrl(dataBaseConfig.getJdbcUrl()); dataSource.setUsername(dataBaseConfig.getUsername()); dataSource.setPassword(dataBaseConfig.getPassword()); //不使用連接池 //DriverManagerDataSource dataSource1 = new DriverManagerDataSource(); //dataSource1.setDriverClassName(dataBaseConfig.getDriverClassName()); //dataSource1.setUrl(dataBaseConfig.getJdbcUrl()); //dataSource1.setUsername(dataBaseConfig.getUsername()); //dataSource1.setPassword(dataBaseConfig.getPassword()); return dataSource; } }
2-5、兩個數(shù)據(jù)庫連接server-order0和server-order1的表結構如下:分別在兩個庫當中運行
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_order0 -- ---------------------------- DROP TABLE IF EXISTS `t_order0`; CREATE TABLE `t_order0` ( `id` bigint NOT NULL, `order_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `user_id` bigint NULL DEFAULT NULL, `amount` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for t_order1 -- ---------------------------- DROP TABLE IF EXISTS `t_order1`; CREATE TABLE `t_order1` ( `id` bigint NOT NULL, `order_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `user_id` bigint NULL DEFAULT NULL, `amount` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
2-6、實體這個@Table(“t_order”)是邏輯表名ShardingConfig分庫策略時設置的
package com.mochenli.shardingshere.entity; import com.mybatisflex.annotation.Id; import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.Table; import lombok.Data; import java.math.BigDecimal; /** * @author: MoChenLi * @description: * @createTime: 2024-06-18 17:15 */ @Table("t_order") @Data public class Order { @Id(keyType = KeyType.Auto) private Long id; private String orderNo; private Long userId; private BigDecimal amount; }
2-7、mapper
package com.mochenli.shardingshere.mapper; import com.mochenli.shardingshere.entity.Order; import com.mybatisflex.core.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * @author: MoChenLi * @description: * @createTime: 2024-06-18 17:18 */ @Mapper public interface OrderMapper extends BaseMapper<Order> { }
3、測試
3-1、測試分庫分表的新增
package com.mochenli.shardingshere.controller; import com.mochenli.shardingshere.entity.Order; import com.mochenli.shardingshere.mapper.OrderMapper; import com.mybatisflex.core.datasource.DataSourceKey; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 18:11 */ @RestController @AllArgsConstructor public class TestController { private final OrderMapper orderMapper; /** * id是用分布式id雪花算法 所以不填 * 測試新增 因為前面配置是根據(jù)user_id進行分庫 分庫算法是:取模分片,算法類型:MOD 分片數(shù)量是 2 * 分表算法是根據(jù) order_no 進行分表 分表算法是 哈希取模分片算法,類型:HASH_MOD 分片數(shù)量是 2 */ @GetMapping("/testAddOrder") public String addTOrder(){ //切換數(shù)據(jù)源 使用ShardingDataSource數(shù)據(jù)源 DataSourceKey.use("getShardingDataSource"); //進行分庫分表插入 for (int i = 1; i <=60; i++) { Order order = new Order(); order.setUserId(Long.valueOf(i)); order.setOrderNo("分表算法"+i); orderMapper.insert(order); } return "success"; } }
結果如下所示:
server_order0.t_order0
server_order0.t_order1
server_order1.t_order0
server_order1.t_order1
3-2、測試分頁查詢:
package com.mochenli.shardingshere.controller; import com.mochenli.shardingshere.entity.Order; import com.mochenli.shardingshere.mapper.OrderMapper; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 18:11 */ @RestController @AllArgsConstructor public class TestController { private final OrderMapper orderMapper; /** * 測試分頁查詢 * @return */ @GetMapping("/testPageOrder") public Page<Order> getPage(){ //切換數(shù)據(jù)源 使用ShardingDataSource數(shù)據(jù)源 DataSourceKey.use("getShardingDataSource"); //進行分頁查詢 Page<Order> page = new Page<>(); page.setPageNumber(1); page.setPageSize(27); Page<Order> paginate = orderMapper.paginate(page, new QueryWrapper()); return paginate; }
結果如下:
3-3、測試事務問題
1、正常情況
package com.mochenli.shardingshere.controller; import com.mochenli.shardingshere.entity.DataBaseConfig; import com.mochenli.shardingshere.entity.Order; import com.mochenli.shardingshere.mapper.DataBaseConfigMapper; import com.mochenli.shardingshere.mapper.OrderMapper; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 18:11 */ @RestController @AllArgsConstructor public class TestController { private final OrderMapper orderMapper; private final DataBaseConfigMapper dataBaseConfigMapper; /** * 測試事務問題 * 正常情況 */ @GetMapping("/testTransaction") public Map<String,Object> testTransaction(){ Map<String,Object> map = new HashMap<>(); List<DataBaseConfig> dataBaseConfigs = dataBaseConfigMapper.selectAll(); map.put("dataBaseConfigs",dataBaseConfigs); DataSourceKey.clear();//清除數(shù)據(jù)源 //切換數(shù)據(jù)源 使用ShardingDataSource數(shù)據(jù)源 DataSourceKey.use("getShardingDataSource"); List<Order> orders = orderMapper.selectAll(); map.put("orders",orders); return map; } }
結果:
2、出錯進行事務回滾情況一
package com.mochenli.shardingshere.controller; import com.mochenli.shardingshere.entity.DataBaseConfig; import com.mochenli.shardingshere.entity.Order; import com.mochenli.shardingshere.mapper.DataBaseConfigMapper; import com.mochenli.shardingshere.mapper.OrderMapper; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 18:11 */ @RestController @AllArgsConstructor public class TestController { private final OrderMapper orderMapper; private final DataBaseConfigMapper dataBaseConfigMapper; /** * 測試事務問題 * 報錯情況一 不分庫的數(shù)據(jù)源報錯 回滾 */ @GetMapping("/testTransactionError") @Transactional public void testTransactionError() { DataBaseConfig dataBaseConfig = new DataBaseConfig(); dataBaseConfig.setConnectionName("連接名稱"); dataBaseConfig.setJdbcUrl("連接字符串"); dataBaseConfig.setUsername("用戶名"); dataBaseConfig.setPassword("密碼"); dataBaseConfig.setDriverClassName("驅動"); //進行新增 dataBaseConfigMapper.insert(dataBaseConfig); //模擬報錯 int i = 10 / 0; DataSourceKey.clear();//清除數(shù)據(jù)源 //切換數(shù)據(jù)源 使用ShardingDataSource數(shù)據(jù)源 DataSourceKey.use("getShardingDataSource"); List<Order> orders = orderMapper.selectAll(); } }
3、出錯進行事務回滾情況二
package com.mochenli.shardingshere.controller; import com.mochenli.shardingshere.entity.DataBaseConfig; import com.mochenli.shardingshere.entity.Order; import com.mochenli.shardingshere.mapper.DataBaseConfigMapper; import com.mochenli.shardingshere.mapper.OrderMapper; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: MoChenLi * @description: * @createTime: 2024-06-29 18:11 */ @RestController @AllArgsConstructor public class TestController { private final OrderMapper orderMapper; private final DataBaseConfigMapper dataBaseConfigMapper; /** * 測試事務問題 * 報錯情況二 分庫分表的數(shù)據(jù)源報錯 回滾 */ @GetMapping("/testTransactionError1") @Transactional public void testTransactionError1() { //切換數(shù)據(jù)源 使用ShardingDataSource數(shù)據(jù)源 DataSourceKey.use("getShardingDataSource"); for (int i = 1; i <= 5; i++) { Order order = new Order(); //不出錯 1%2=1應該在server_order1庫當中 order.setUserId(1L); //不出錯 "事務回滾測試".hashCode() % 2 = 0 應該在 t_order0表當中; order.setOrderNo("事務回滾測試"); orderMapper.insert(order); } //模擬報錯 int k = 10 / 0; DataSourceKey.clear();//清除數(shù)據(jù)源 List<DataBaseConfig> dataBaseConfigs = dataBaseConfigMapper.selectAll(); } }
結果回滾了
補充:mybatis-plus不支持多數(shù)據(jù)源切換,得自己實現(xiàn),且還得自己進行自定義事務增強
到此這篇關于MyBatis-Flex+ShardingSphere-JDBC多數(shù)據(jù)源分庫分表實現(xiàn)的文章就介紹到這了,更多相關MyBatis-Flex+ShardingSphere-JDBC 分庫分表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中的FileInputStream 和 FileOutputStream 介紹_動力節(jié)點Java學院整理
FileInputStream 是文件輸入流,它繼承于InputStream。FileOutputStream 是文件輸出流,它繼承于OutputStream。接下來通過本文給大家介紹Java中的FileInputStream 和 FileOutputStream,需要的朋友可以參考下2017-05-05Java中由substring方法引發(fā)的內(nèi)存泄漏詳解
這篇文章主要介紹了Java中由substring方法引發(fā)的內(nèi)存泄漏詳解,涉及substring方法引發(fā)的內(nèi)存泄漏簡介,substring的作用和實現(xiàn)原理等相關內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下2017-12-12springboot中redis的緩存穿透問題實現(xiàn)
這篇文章主要介紹了springboot中redis的緩存穿透問題實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-02-02詳解SpringMVC重定向傳參數(shù)的實現(xiàn)
本篇文章主要介紹了詳解SpringMVC重定向傳參數(shù)的實現(xiàn),我們可以使用重定向的方式,改變?yōu)g覽器的地址欄,防止表單因為刷新重復提交。有興趣的可以了解一下。2017-01-01如何從Java環(huán)境中調(diào)用GoLang函數(shù)
Go,常被稱為GoLang,Go語言憑借其豐富的標準庫,以及 goroutines和 channels等獨特特性,在開發(fā)可擴展且高效的程序方面展現(xiàn)了顯著優(yōu)勢,許多開發(fā)者傾向于將Go與其他編程語言結合使用,在本文中,我們將深入探討如何從Java環(huán)境中調(diào)用GoLang函數(shù),以實現(xiàn)兩種語言的無縫集成2025-01-01