Spring分布式事务在service中动态切换数据源

简介:

Spring分布式事务在service中动态切换数据源

项目采用的是struts2的+弹簧+ ibatis的架构,下面是关键部分代码:

applicationContext.xml中:

[html] 查看纯文本

  1. <?xml version = “1.0” encoding = “UTF-8” ?>
  2. < beans xmlns = “http://www.springframework.org/schema/beans”
  3.        xmlns:xsi = “http://www.w3.org/2001/XMLSchema-instance”
  4.        xmlns:context = “http://www.springframework.org/schema/context”
  5.        xmlns:aop = “http://www.springframework.org/schema/aop”
  6.        xmlns:tx = “http://www.springframework.org/schema/tx”
  7.        xsi:schemaLocation =“http://www.springframework.org/schema/beans
  8.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  9.            http://www.springframework.org/schema/context
  10.            http://www.springframework.org/schema/context/spring-context-2.5.xsd
  11.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  12.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd“
  13.            default-autowire = “byName” default-lazy-init = “false” >
  14.     < context:component-scan base-package = “com.ssi。*” />
  15.     <! - 属性文件读入 - >
  16.     < bean id = “propertyConfigurer” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >>
  17.         < property name = “locations” >
  18.             < list >
  19.                 < value > classpath *:jdbc.properties </ value >
  20.             </ list >
  21.         </ property >
  22.     </ bean >
  23.     <! - 配置sqlMapclient - >
  24.     < bean id = “sqlMapClient” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
  25.         < property name = “configLocation” value = “classpath:ibatis-sqlmap-config.xml” />
  26.         < property name = “dataSource” ref = “dataSource” />
  27.     </ bean >
  28.     < bean id = “sqlMapClient1” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
  29.         < property name = “configLocation” value = “classpath:ibatis-sqlmap-config.xml” />
  30.         < property name = “dataSource” ref = “db1” />
  31.     </ bean >
  32.     < bean id = “sqlMapClient2” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
  33.         < property name = “configLocation” value = “classpath:ibatis-sqlmap-config.xml” />
  34.         < property name = “dataSource” ref = “db2” />
  35.     </ bean >
  36.     < bean id = “sqlMapClientCenter” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
  37.         < property name = “configLocation” value = “classpath:ibatis-sqlmap-config.xml” />
  38.         < property name = “dataSource” ref = “center” />
  39.     </ bean >
  40.     < bean id = “dynamicSqlMapClientDaoSupport” class = “com.ssi.dao.DynamicSqlClientDaoSupport” >>
  41.         < property name = “targetSqlMapClients” >
  42.             < map >
  43.                 < entry key = “db1” value-ref = “sqlMapClient1” />
  44.                 < entry key = “db2” value-ref = “sqlMapClient2” />
  45.                 < entry key = “center” value-ref = “sqlMapClientCenter” />
  46.             </ map >
  47.         </ property >
  48.         < property name = “defaultSqlMapClient” ref = “sqlMapClientCenter” />
  49.     </ bean >
  50.     < bean id = “ibatisDaoSupport” class = “com.ssi.dao.IbatisDaoSupport” parent = “dynamicSqlMapClientDaoSupport” > </bean >
  51.     < bean id = “userDao” class = “com.ssi.dao.impl.UserDaoImpl” parent = “ibatisDaoSupport” > </ bean >
  52.     <! - 支持@AspectJ标记 - >
  53.     < aop:aspectj-autoproxy proxy-target-class = “true” />
  54.     <! - 配置JTA的事务管理器 - >
  55.     < bean id = “atomikosTransactionManager” class = “com.atomikos.icatch.jta.UserTransactionManager” init-method = “init” destroy-method = “close” >
  56.         < property name = “forceShutdown” value = “true” />
  57.     </ bean >
  58.     < bean id = “atomikosUserTransaction” class = “com.atomikos.icatch.jta.UserTransactionImp” >
  59.         < property name = “transactionTimeout” value = “300” />
  60.     </ bean >
  61.     < bean id = “springTransactionManager” class = “org.springframework.transaction.jta.JtaTransactionManager”>
  62.         < property name = “transactionManager” ref = “atomikosTransactionManager” />
  63.         < property name = “userTransaction” ref = “atomikosUserTransaction” />
  64.     </ bean >
  65.     <! - 配置通知 - >
  66.     < tx:advice id = “txAdvice” transaction-manager = “springTransactionManager” >
  67.         < tx:attributes >
  68.              < tx:method name = “*” rollback-for = “Exception,RuntimeException,com.ssi.exception.SystemException” propagation = “REQUIRED” />
  69.         </ tx:attributes >
  70.     </ tx:advice >
  71.     <! - 以AspectJ方式定义AOP - >
  72.     < aop:config >
  73.         < aop:advisor pointcut = “execution(* com.ssi.service .. * Service *。*(..))” advice-ref = “txAdvice”/>
  74.     </ aop:config >
  75.     <! - spring定时器任务开始 - >
  76.     < bean name = “job” class = “org.springframework.scheduling.quartz.JobDetailBean” >
  77.          < property name = “jobClass” >
  78.              < value > com.ssi.action.TimerAction </ value >
  79.          </ property >
  80.          < property name = “jobDataAsMap” >
  81.              < map >
  82.                   <! - timeout属性设定了当服务器启动后过10秒钟首次调用你的JobAction - >
  83.                   < entry key = “timeout” >
  84.                      < value > 10 </ value >
  85.                   </ entry >
  86.              </ map >
  87.          </ property >
  88.     </ bean >
  89.     < bean id = “cronTrigger” class = “org.springframework.scheduling.quartz.CronTriggerBean” >
  90.          < property name = “jobDetail” >
  91.              < ref bean = “job” />
  92.          </ property >
  93.          < property name = “cronExpression” >
  94.              < > 0 53 15?* MON-FRI </ value >
  95.          </ property >
  96.     </ bean >
  97.     < bean class = “org.springframework.scheduling.quartz.SchedulerFactoryBean” autowire = “no” >
  98.          < property name = “triggers” >
  99.              < list >
  100.                  < ref local = “cronTrigger” />
  101.              </ list >
  102.          </ property >
  103.     </ bean >
  104.     <! - spring定时器任务结束 - >
  105. </ beans >

 

[html] 查看纯文本

的applicationContext-datasource.xml

[html] 查看纯文本

  1. <?xml version = “1.0” encoding = “UTF-8” ?>
  2. < beans xmlns = “http://www.springframework.org/schema/beans”
  3.     xmlns:xsi = “http://www.w3.org/2001/XMLSchema-instance”
  4.     xmlns:aop = “http://www.springframework.org/schema/aop”
  5.     xmlns:tx = “http://www.springframework.org/schema/tx”
  6.     xsi:schemaLocation =“
  7.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  9.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd“ >
  10.     <! - 指定春天配置中用到的属性文件 - >
  11.     < bean id = “propertyConfig” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>>
  12.         < property name = “locations” >
  13.             < list >
  14.                 < value > classpath:jdbc.properties </ value >
  15.             </ list >
  16.         </ property >
  17.     </ bean >
  18.     <! - JTA数据源配置 - >
  19.     < bean id = “center” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close” >
  20.         < property name = “uniqueResourceName” >
  21.             < > mysql / center </ value >
  22.         </ property >
  23.         < property name = “xaDataSourceClassName” >
  24.             < value > $ {jta.driver.className} </ value >
  25.         </ property >
  26.         < property name = “xaProperties” >
  27.             < 道具>
  28.                 < prop key = “url” > $ {center.jdbc.driver.url} </ prop >
  29.                 < prop key = “user” > $ {center.sql.user.name} </ prop >
  30.                 < prop key = “password” > $ {center.sql.user.password} </ prop >
  31.             </ 道具>
  32.         </ property >
  33.         < property name = “testQuery” value = “select 1” />
  34.         < property name = “poolSize” >
  35.             < value > $ {poolsize} </ value >
  36.         </ property >
  37.         < property name = “maxPoolSize” >
  38.             < value > $ {maxPoolSize} </ value >
  39.         </ property >
  40.         < property name = “borrowConnectionTimeout” > < value > $ {borrowConnectionTimeout} </ value > </ property >
  41.     </ bean >
  42.     < bean id = “db1” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close”>
  43.         < property name = “uniqueResourceName” >
  44.             < value > mysql / db1 </ value >
  45.         </ property >
  46.         < property name = “xaDataSourceClassName” >
  47.             < value > $ {jta.driver.className} </ value >
  48.         </ property >
  49.         < property name = “xaProperties” >
  50.             < 道具>
  51.                 < prop key = “url” > $ {db1.jdbc.driver.url} </ prop >
  52.                 < prop key = “user” > $ {company.sql.user.name} </ prop >
  53.                 < prop key = “password” > $ {company.sql.user.password} </ prop >
  54.             </ 道具>
  55.         </ property >
  56.         < property name = “testQuery” value = “select 1” />
  57.         < property name = “poolSize” >
  58.             < value > $ {poolsize} </ value >
  59.         </ property >
  60.         < property name = “maxPoolSize” >
  61.             < value > $ {maxPoolSize} </ value >
  62.         </ property >
  63.         < property name = “borrowConnectionTimeout” > < value > $ {borrowConnectionTimeout} </ value > </ property >
  64.     </ bean >
  65.     < bean id = “db2” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close”>
  66.         < property name = “uniqueResourceName” >
  67.             < value > mysql / db2 </ value >
  68.         </ property >
  69.         < property name = “xaDataSourceClassName” >
  70.             < value > $ {jta.driver.className} </ value >
  71.         </ property >
  72.         < property name = “xaProperties” >
  73.             < 道具>
  74.                 < prop key = “url” > $ {db2.jdbc.driver.url} </ prop >
  75.                 < prop key = “user” > $ {company.sql.user.name} </ prop >
  76.                 < prop key = “password” > $ {company.sql.user.password} </ prop >
  77.             </ 道具>
  78.         </ property >
  79.         < property name = “testQuery” value = “select 1” />
  80.         < property name = “poolSize” >
  81.             < value > $ {poolsize} </ value >
  82.         </ property >
  83.         < property name = “maxPoolSize” >
  84.             < value > $ {maxPoolSize} </ value >
  85.         </ property >
  86.         < property name = “borrowConnectionTimeout” > < value > $ {borrowConnectionTimeout} </ value > </ property >
  87.     </ bean >
  88.     < bean id = “dataSource” class = “com.ssi.datasource.DynamicDataSource” >
  89.         < property name = “targetDataSources” >
  90.             < map key-type = “java.lang.String” >
  91.                 < entry key = “db1” value-ref = “db1” />
  92.                 < entry key = “db2” value-ref = “db2” />
  93.                 < entry key = “center” value-ref = “center” />
  94.             </ map >
  95.         </ property >
  96.         < property name = “defaultTargetDataSource” ref = “center” />
  97.     </ bean >
  98. </ beans >

 

DynamicSqlClientDaoSupport.java

[java] 查看纯文本

  1.  com.ssi.dao;
  2. import  java.util.Map;
  3. import  javax.sql.DataSource;
  4. import  org.springframework.beans.factory.InitializingBean;
  5. import  org.springframework.dao.support.DaoSupport;
  6. import  org.springframework.orm.ibatis.SqlMapClientTemplate;
  7. import  org.springframework.util.Assert;
  8. import  com.ibatis.sqlmap.client.SqlMapClient;
  9. import  com.ssi.datasource.DbContextHolder;
  10. 公共 DynamicSqlClientDaoSupport  扩展 DaoSupport  实现 InitializingBean {
  11.     私人 SqlMapClientTemplate sqlMapClientTemplate =  新的 SqlMapClientTemplate();
  12.     私人 地图<String,SqlMapClient> targetSqlMapClients;
  13.     私人 SqlMapClient的defaultSqlMapClient;
  14.     private boolean  externalTemplate =  false ;
  15.     / **
  16.      *设置此DAO使用的JDBC数据源。
  17.      *不需要:SqlMapClient可能携带共享数据源。
  18.      * @see #setSqlMapClient
  19.      * /
  20.     public final void  setDataSource(DataSource dataSource){
  21.         如果 (!this .externalTemplate){
  22.         这个.sqlMapClientTemplate.setDataSource(dataSource);
  23.         }
  24.     }
  25.     / **
  26.      *返回此DAO使用的JDBC数据源。
  27.      * /
  28.     public final  DataSource getDataSource(){
  29.         返回这个.sqlMapClientTemplate.getDataSource();
  30.     }
  31.     / **
  32.      *设置iBATIS数据库层SqlMapClient使用。
  33.      *这个或者“sqlMapClientTemplate”是必需的。
  34.      * @see #setSqlMapClientTemplate
  35.      * /
  36.     public final void  setSqlMapClient(SqlMapClient sqlMapClient){
  37.         如果 (!this .externalTemplate){
  38.             这个.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
  39.         }
  40.     }
  41.     / **
  42.      *返回该模板使用的iBATIS数据库层SqlMapClient。
  43.      * /
  44.     public final  SqlMapClient getSqlMapClient(){
  45.         返回这个.sqlMapClientTemplate.getSqlMapClient();
  46.     }
  47.     / **
  48.      *明确地为此DAO设置SqlMapClientTemplate,
  49.      *作为指定SqlMapClient的替代方法。
  50.      * @see #setSqlMapClient
  51.      * /
  52.     public final void  setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate){
  53.         Assert.notNull(sqlMapClientTemplate,  “SqlMapClientTemplate不能为空” );
  54.         这个.sqlMapClientTemplate = sqlMapClientTemplate;
  55.         这个.externalTemplate =  true ;
  56.     }
  57.     / **
  58.      *返回此DAO的SqlMapClientTemplate,
  59.      *用SqlMapClient预先初始化或明确设置。
  60.      * /
  61.     public final  SqlMapClientTemplate getSqlMapClientTemplate(){
  62.       字符串dbtype = DbContextHolder.getDbType();
  63.       if (targetSqlMapClients!= null && targetSqlMapClients.containsKey(dbtype)){
  64.           SqlMapClient sqlMapClient = targetSqlMapClients.get(dbtype);
  65.           sqlMapClientTemplate =  新的 SqlMapClientTemplate(sqlMapClient);
  66.       }
  67.       返回这个.sqlMapClientTemplate;
  68.     }
  69.     @覆盖
  70.     protected final void  checkDaoConfig(){
  71.         如果 (!this .externalTemplate){
  72.             这个.sqlMapClientTemplate.afterPropertiesSet();
  73.         }
  74.     }
  75.     public  Map <String,SqlMapClient> getTargetSqlMapClients(){
  76.         返回 targetSqlMapClients;
  77.     }
  78.     public void  setTargetSqlMapClients(Map <String,SqlMapClient> targetSqlMapClients){
  79.         这个.targetSqlMapClients = targetSqlMapClients;
  80.     }
  81.     public  SqlMapClient getDefaultSqlMapClient(){
  82.         返回 defaultSqlMapClient;
  83.     }
  84.     public void  setDefaultSqlMapClient(SqlMapClient defaultSqlMapClient){
  85.         这个.defaultSqlMapClient = defaultSqlMapClient;
  86.     }
  87. }

IbatisDaoSupport.java

[java] 查看纯文本

  1.  com.ssi.dao;
  2. import  java.io.Serializable;
  3. import  java.sql.SQLException;
  4. import  java.util.List;
  5. import  java.util.Map;
  6. import  org.apache.commons.logging.Log;
  7. import  org.apache.commons.logging.LogFactory;
  8. import  org.springframework.orm.ibatis.SqlMapClientCallback;
  9. import  com.ibatis.sqlmap.client.SqlMapExecutor;
  10. @SuppressWarnings “未选中”
  11. 公共 IbatisDaoSupport <实体>  扩展 DynamicSqlClientDaoSupport  实现 IEntityDao <实体> {
  12.     受保护的最终 日志日志= LogFactory.getLog(getClass());
  13.     公共 实体get(String sqlId,Serializable id){
  14.         return  (Entity)getSqlMapClientTemplate()。queryForObject(sqlId,id);
  15.     }
  16.     公共 实体getByParamMap(字符串sqlId,对象参数){
  17.         return  (Entity)getSqlMapClientTemplate()。queryForObject(sqlId,param);
  18.     }
  19.     public  Object save(String sqlId,Object o){
  20.         返回 getSqlMapClientTemplate()。insert(sqlId,o);
  21.     }
  22.     public  Object batchSave(final  String sqlId,final  List <Entity> entityList)  throws  Exception {
  23.         //执行回调   
  24.         返回 getSqlMapClientTemplate()。execute(新的 SqlMapClientCallback(){
  25.             //实现回调接口   
  26.             公共 对象doInSqlMapClient(SqlMapExecutor执行器)  throws  SQLException {
  27.                 //开始批处理   
  28.                 executor.startBatch();
  29.                 for  (Entity entity:entityList){
  30.                     executor.insert(sqlId,entity);
  31.                 }
  32.                 return  executor.executeBatch();
  33.             }
  34.         });
  35.     }
  36.     public  Integer remove(String sqlId,Object o){
  37.         返回 getSqlMapClientTemplate()。delete(sqlId,o);
  38.     }
  39.     public  Integer removeById(String sqlId,Serializable id){
  40.         返回 getSqlMapClientTemplate()。delete(sqlId,id);
  41.     }
  42.     public  Integer update(String sqlId,Object o){
  43.         返回 getSqlMapClientTemplate()。update(sqlId,o);
  44.     }
  45.     public  long totalCount(String sqlId,Object o){
  46.         return  (Long)getSqlMapClientTemplate()。queryForObject(sqlId,o);
  47.     }
  48.     public  List <Entity> pagedList(String sqlId,Map <String,Object> map,int  pageSize,  int  pageNum){
  49.         int  start =(pageNum -  1 )* pageSize;
  50.         map.put(“开始” ,开始);
  51.         map.put(“pageSize” ,pageSize);
  52.         List <Entity> list = getSqlMapClientTemplate()。queryForList(sqlId,map);
  53.         退货 清单;
  54.     }
  55.     public  List <Entity> list(String sqlId,Object o){
  56.         返回 getSqlMapClientTemplate()。queryForList(sqlId,o);
  57.     }
  58.     public  List <Entity> list(String sqlId){
  59.         返回 getSqlMapClientTemplate()。queryForList(sqlId);
  60.     }
  61. }

 

UserDaoImpl.java:

[java] 查看纯文本

  1.  com.ssi.dao.impl;
  2. import  org.springframework.stereotype.Repository;
  3. import  com.ssi.dao.IUserDao;
  4. import  com.ssi.dao.IbatisDaoSupport;
  5. import  com.ssi.model.User;
  6. @Repository “userDAO的”
  7. 公共 UserDaoImpl  扩展 IbatisDaoSupport <用户>  实现 IUserDao {
  8.     公共 整数addUser(用户用户)  抛出 异常{
  9.         返回 (整数)  这个.save(“User.insert” ,用户);
  10.     }
  11. }

 

UserServiceImpl.java

[java] 查看纯文本

  1.  com.ssi.service.impl;
  2. import  javax.annotation.Resource;
  3. import  org.springframework.stereotype.Service;
  4. import  com.ssi.dao.IUserDao;
  5. import  com.ssi.datasource.DbContextHolder;
  6. import  com.ssi.model.User;
  7. import  com.ssi.service.IUserService;
  8. @Service “userService”
  9. 公共 UserServiceImpl  实现 IUserService {
  10.     @Resource private  IUserDao userDao;
  11.     / **
  12.      *测试在服务中切换数据源异常是否回滚
  13.      * /
  14.     公共无效 addUser(用户用户)  抛出 异常{
  15.         DbContextHolder.setDbType(“db1” );
  16.         userDao.addUser(用户);
  17.         DbContextHolder.setDbType(“db2” );
  18.         user.setUserName(“user2” );
  19.         userDao.addUser(用户);
  20.         DbContextHolder.setDbType(“center” );
  21.         user.setUserName(“user3” );
  22.         userDao.addUser(用户);
  23.         //System.out.println(1/0);
  24.     }
  25. }

 

DynamicDataSource.java:

[java] 查看纯文本

  1. public class  DynamicDataSource  extends  AbstractRoutingDataSource {
  2.     静态 记录仪日志= Logger.getLogger(DynamicDataSource。);
  3.     protected  Object determineCurrentLookupKey(){
  4.         返回 DbContextHolder.getDbType();
  5.     }
  6. }

DbContextHolder.java:

[java] 查看纯文本

  1. 公共 DbContextHolder {
  2.     private static final  ThreadLocal contextHolder =  new  ThreadLocal();
  3.     public static void  setDbType(String dbType){
  4.         contextHolder.set(DBTYPE);
  5.     }
  6.     public static  String getDbType(){
  7.         return  (String)contextHolder.get();
  8.     }
  9.     public static void  clearDbType(){
  10.         contextHolder.remove();
  11.     }
  12. }

三个数据库:dbcenter,db1,db2表结构均相同

脚本:

[sql] 查看纯文本

  1. DROP TABLE  IF EXISTS`tb_user`;
  2. CREATE TABLE  `tb_user`(
  3.   `id`  int (11)  NOT NULL  AUTO_INCREMENT,
  4.   `userName`  varchar (20)  DEFAULT NULL
  5.   ` 密码VARCHAR (60)  DEFAULT NULL
  6.   PRIMARY KEY  (`id`)
  7. )ENGINE = InnoDB  DEFAULT  CHARSET = utf8;

单元测试:

[java] 查看纯文本

  1. 公共 JunitTest {
  2.     public  ApplicationContext cxt;
  3.     @测试
  4.     公共无效的 init()  抛出 异常{
  5.         cxt =  new  ClassPathXmlApplicationContext(new  String [] { “applicationContext.xml” “applicationContext-datasource.xml” });
  6.         testInsertUser();
  7.     }
  8.     私人无效 testInsertUser()  抛出 异常{
  9.         IUserService userService =(IUserService)cxt.getBean(“userService” );
  10.         用户用户=   用户();
  11.         user.setUserName(“user1” );
  12.         user.setPassword(“0” );
  13.         userService.addUser(用户);
  14.     }
  15.     私人无效 testInsertUser2()  抛出 异常{
  16. }
相关文章
|
5月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
4296 84
|
6月前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
140 0
|
7月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1161 3
|
5月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
10月前
|
人工智能 负载均衡 Java
Spring AI Alibaba 发布企业级 MCP 分布式部署方案
本文介绍了Spring AI Alibaba MCP的开发与应用,旨在解决企业级AI Agent在分布式环境下的部署和动态更新问题。通过集成Nacos,Spring AI Alibaba实现了流量负载均衡及节点变更动态感知等功能。开发者可方便地将企业内部业务系统发布为MCP服务或开发自己的AI Agent。文章详细描述了如何通过代理应用接入存量业务系统,以及全新MCP服务的开发流程,并提供了完整的配置示例和源码链接。未来,Spring AI Alibaba计划结合Nacos3的mcp-registry与mcp-router能力,进一步优化Agent开发体验。
3368 14
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
1372 160
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
487 1
|
存储 Java 文件存储
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储
本文介绍了如何基于Spring Boot 3和MinIO实现分布式文件存储。随着应用规模扩大,传统的单机文件存储方案难以应对大规模数据和高并发访问,分布式文件存储系统成为更好的选择。文章详细讲解了MinIO的安装、配置及与Spring Boot的整合步骤,包括Docker部署、MinIO控制台操作、Spring Boot项目中的依赖引入、配置类编写及工具类封装等内容。最后通过一个上传头像的接口示例展示了具体的开发和测试过程,强调了将API操作封装成通用工具类以提高代码复用性和可维护性的重要性。
2492 7
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
959 5
|
缓存 NoSQL Java
Spring Boot中的分布式缓存方案
Spring Boot提供了简便的方式来集成和使用分布式缓存。通过Redis和Memcached等缓存方案,可以显著提升应用的性能和扩展性。合理配置和优化缓存策略,可以有效避免常见的缓存问题,保证系统的稳定性和高效运行。
451 3