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

郑州汉狮做网站的大公司怎么在平台上做推广

郑州汉狮做网站的大公司,怎么在平台上做推广,合肥公司建站模板,做网站建设分哪些类型集成组件包括MySQL分库分表及读写分离、seata以及Sentinel 若依项目文档连接 代码下载地址 需要结合ruoyi代码配合看&#xff0c;前提是熟悉基本代码结构&#xff0c;熟悉feign调用和基础网关配置等。 采用的版本信息 <java.version>1.8</java.version> <spr…

集成组件包括MySQL分库分表及读写分离、seata以及Sentinel

若依项目文档连接
代码下载地址

需要结合ruoyi代码配合看,前提是熟悉基本代码结构,熟悉feign调用和基础网关配置等。

采用的版本信息

<java.version>1.8</java.version>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.0.9</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version>

项目目录结构

MYSQL分库分表及读写分离,版本基于MySQL8.0+版本

  1. 在ruoyi-file和ruoyi-system中引入ShardingSphere依赖,采用的是5.1.2版本
 <!-- ShardingSphere 读写分离/分库分表 -->
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.1.2</version>
</dependency>
  1. 在bootstrap.yaml中配置
    ruoyi-system,中有分表操作,对应
spring:main:allow-bean-definition-overriding: trueshardingsphere:props:sql-show: truedatasource:names: master,slavemaster:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.177:3306/ry-user?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: xxxxpassword: xxxxslave:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.179:3306/ry-user?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: xxxxpassword: xxxxxrules:readwrite-splitting:data-sources:rw_ds:type: Staticprops:write-data-source-name: masterread-data-source-names: slaveload-balancer-name: round_robinload-balancers:round_robin:type: ROUND_ROBINsharding:tables:lake_company_info:actual-data-nodes: rw_ds.xx_sd,rw_ds.xxx_ah,rw_ds.xxx_js,rw_ds.xxx_othertable-strategy:standard:sharding-column: init_province_idsharding-algorithm-name: province-algorithmsharding-algorithms:province-algorithm:type: CLASS_BASEDprops:strategy: standardalgorithmClassName: com.ruoyi.system.shardingconfig.ProvinceIdShardingAlgorithm

涉及到的类

package com.ruoyi.system.shardingconfig;import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;import java.util.Collection;
import java.util.Properties;//sharding分表规则
@Slf4j
public class ProvinceIdShardingAlgorithm implements StandardShardingAlgorithm<String> {@Overridepublic String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {StringBuilder resultTableName = new StringBuilder();String logicTableName = preciseShardingValue.getLogicTableName();String value = preciseShardingValue.getValue();String postTable = "other" ;if("370000".equals(value)) {postTable = "sd" ;}if("340000".equals(value)) {postTable = "ah" ;}if("320000".equals(value)) {postTable = "js" ;}resultTableName.append(logicTableName).append("_").append(postTable);log.error("操作的表名{}",resultTableName);return ShardingAlgorithmTool.shardingTablesCheckAndCreatAndReturn(logicTableName, resultTableName.toString());}@Overridepublic Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {return null;}@Overridepublic Properties getProps() {return null;}@Overridepublic void init(Properties properties) {System.out.println();}
}
package com.ruoyi.system.shardingconfig;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;@Slf4j
public class ShardingAlgorithmTool {private static final HashSet<String> tableNameCache = new HashSet<>();//    private static HssHistoryMapper hssHistoryMapper=SpringUtil.getBean(HssHistoryMapper.class);/*** 判断 分表获取的表名是否存在 不存在则自动建表** @param logicTableName  逻辑表名(表头)* @param resultTableName 真实表名* @return 确认存在于数据库中的真实表名*/public static String shardingTablesCheckAndCreatAndReturn(String logicTableName, String resultTableName) {synchronized (logicTableName.intern()) {// 缓存中有此表 返回if (tableNameCache.contains(resultTableName)) {return resultTableName;}// 缓存中无此表 建表 并添加缓存// 调用mapper 创建表// @Update("CREATE TABLE IF NOT EXISTS ${name} LIKE hss_history")
//            hssHistoryMapper.createTable(resultTableName);tableNameCache.add(resultTableName);}return resultTableName;}/*** 缓存重载方法*/public static void tableNameCacheReload() {// 读取数据库中所有表名List<String> tableNameList = getAllTableNameBySchema();// 删除旧的缓存(如果存在)ShardingAlgorithmTool.tableNameCache.clear();// 写入新的缓存9ShardingAlgorithmTool.tableNameCache.addAll(tableNameList);}/*** 获取数据库中的表名*/public static List<String> getAllTableNameBySchema() {List<String> res = new ArrayList<>();// 获取数据中的表名,需要自己构建数据源 SHOW TABLES like 'hss_history%'
//         List<String> res = hssHistoryMapper.showTables();
//        Environment env = SpringUtil.getApplicationContext().getEnvironment();
//        try (Connection connection = DriverManager.getConnection(env.getProperty("spring.datasource.druid.url"), env.getProperty("spring.datasource.druid.username"), env.getProperty("spring.datasource.druid.password"));
//             Statement st = connection.createStatement()) {
//            try (ResultSet provinceRs = st.executeQuery("SHOW TABLES like 'lake_company_info%'")) {
//                while (provinceRs.next()) {
//                    res.add(provinceRs.getString(1));
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }res.add("lake_company_info");res.add("lake_company_info_sd");res.add("lake_company_info_ah");res.add("lake_company_info_js");res.add("lake_company_info_other");return res;}/*** 获取缓存中的表名* @return*/public static HashSet<String> cacheTableNames() {return tableNameCache;}
}package com.ruoyi.system.shardingconfig;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** 项目启动后 读取已有分表 进行缓存*/
@Slf4j
@Order(value = 1) // 数字越小 越先执行
@Component
public class ShardingTablesLoadRunner implements CommandLineRunner {@Overridepublic void run(String... args) {ShardingAlgorithmTool.tableNameCacheReload();}
}

ruoyi-file中引入

spring:main:allow-bean-definition-overriding: trueapplication:# 应用名称name: ruoyi-fileprofiles:# 环境配置active: devcloud:nacos:discovery:# 服务注册地址server-addr: 192.168.0.227:8848config:# 配置中心地址server-addr: 192.168.0.227:8848# 配置文件格式file-extension: yml# 共享配置shared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}shardingsphere:props:sql-show: truedatasource:names: master,slavemaster:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.177:3306/seata_file?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: xxxxpassword: xxxxslave:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.179:3306/seata_file?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: xxxxxpassword: xxxxxxrules:readwrite-splitting:data-sources:rw_ds:type: Staticprops:write-data-source-name: masterread-data-source-names: slaveload-balancer-name: round_robinload-balancers:round_robin:type: ROUND_ROBIN
  1. 测试
    可以自行测试,可以正确看到写入走master,读取操作走slave
    在这里插入图片描述

sentinel集成 ,版本采用的是1.7.2

sentinel搭建参考连接

项目集成
先配置网关请求路由限流策略,在ruoyi-gateway中引入依赖

<!-- SpringCloud Alibaba Sentinel -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency><!-- SpringCloud Alibaba Sentinel Gateway -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency><!-- Sentinel Datasource Nacos -->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

在bootstrap中引入

spring: application:# 应用名称name: ruoyi-gatewayprofiles:# 环境配置active: devcloud:nacos:discovery:# 服务注册地址server-addr: 192.168.0.227:8848config:# 配置中心地址server-addr: 192.168.0.227:8848# 配置文件格式file-extension: yml# 共享配置shared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}sentinel:# 取消控制台懒加载eager: truetransport:# 控制台地址dashboard: 192.168.0.172:8080# nacos配置持久化datasource:ds1:nacos:server-addr: 192.168.0.227:8848dataId: sentinel-ruoyi-gatewaygroupId: DEFAULT_GROUPdata-type: jsonrule-type: gw-flow

nacos上的配置

具体内容如下:

[{"resource": "ruoyi-auth","count": 500,"grade": 1,"limitApp": "default","strategy": 0,"controlBehavior": 0},{"resource": "ruoyi-system","count": 1000,"grade": 1,"limitApp": "default","strategy": 0,"controlBehavior": 0},{"resource": "ruoyi-gen","count": 200,"grade": 1,"limitApp": "default","strategy": 0,"controlBehavior": 0},{"resource": "ruoyi-job","count": 300,"grade": 1,"limitApp": "default","strategy": 0,"controlBehavior": 0}
]

在网关项目中建立对应的类

package com.ruoyi.gateway.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import com.ruoyi.gateway.handler.SentinelFallbackHandler;/*** 网关限流配置* * @author ruoyi*/
@Configuration
public class GatewayConfig
{@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelFallbackHandler sentinelGatewayExceptionHandler(){return new SentinelFallbackHandler();}
}

自定义限流异常处理类

package com.ruoyi.gateway.handler;import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.ruoyi.common.core.utils.ServletUtils;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;/*** 自定义限流异常处理** @author ruoyi*/
public class SentinelFallbackHandler implements WebExceptionHandler
{private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange){return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试");}@Overridepublic Mono<Void> handle(ServerWebExchange exchange, Throwable ex){if (exchange.getResponse().isCommitted()){return Mono.error(ex);}if (!BlockException.isBlockException(ex)){return Mono.error(ex);}return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));}private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable){return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);}
}

运行前后端项目,访问对应接口。
在这里插入图片描述
之后对具体项目进行限流,在ruoyi-system中实操。同样的在ruoyi-system中引入依赖

<!-- SpringCloud Alibaba Sentinel -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<!-- Sentinel Datasource Nacos -->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

在bootstrap文件中创建对应的限流和降级策略

spring:application:# 应用名称name: ruoyi-systemprofiles:# 环境配置active: devcloud:nacos:discovery:# 服务注册地址server-addr: 192.168.0.227:8848config:# 配置中心地址server-addr: 192.168.0.227:8848# 配置文件格式file-extension: yml# 共享配置shared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}sentinel:eager: truetransport:dashboard: 192.168.0.172:8080datasource:flow:nacos:server-addr: 192.168.0.227:8848dataId: ruoyi-system-flow-rulesgroupId: DEFAULT_GROUPdata-type: jsonrule-type: flowdegrade:nacos:server-addr: 192.168.0.227:8848dataId: ruoyi-system-degrade-rulesgroupId: DEFAULT_GROUPdata-type: jsonrule-type: degradeenabled: true

在nacos上分别建立对应的文件
在这里插入图片描述
在这里插入图片描述

对应文件内容如下
ruoyi-system-flow-rules

[{"app": "ruoyi-system",  //对应应用"clusterMode": false,  // 是否集群模式"controlBehavior": 0,  // 流控效果(0:快速失败、1:warm up 2:排队等待)"count": 10,  // 阈值(QPS=2)"gmtModified": 1747376424368, "grade": 1,  // 限流类型 (1:QPS,2:线程数)"id": 40, "limitApp": "default", // 限流应用(default表示不区分来源)"resource": "dictList",  // 资源名称 (@SentinelResuorce的value)"strategy": 0 // 流控模式(0:直接 1:关联 2:链路)}
]

ruoyi-system-degrade-rules

[{"resource": "dictList",  // 资源名称"grade": 0,  // 0慢调用比例,1异常比例,2异常数"count": 23, // 阈值(RT=23ms)"timeWindow": 1, // 熔断恢复时间(秒)"minRequestAmount": 5, //最小请求数(触发熔断的最小请求)"statIntervalMs": 1000, // 统计窗口(毫秒)"slowRatioThreshold": 0.5 // 慢调用比例阈值(仅 grade=0 时生效)}
]

在代码中进行集成

RequiresPermissions("system:dict:list")@GetMapping("/list")@SentinelResource(value = "dictList", blockHandler = "selectUserByNameBlockHandler", fallback = "selectUserByNameFallback")public TableDataInfo list(SysDictType dictType){startPage();R<Boolean> booleanR = this.remoteLogService.saveLogA("1", SecurityConstants.INNER);System.out.println(JSONObject.toJSONString(booleanR));
//        int x=1/0 ;List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);return getDataTable(list);}// 服务流量控制处理,触发走这个public TableDataInfo selectUserByNameBlockHandler(SysDictType dictType, BlockException ex){System.out.println("selectUserByNameBlockHandler异常信息:" + ex.getMessage());return getDataTable(new ArrayList<>());}// 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数  抛出异常走这个public TableDataInfo selectUserByNameFallback(SysDictType dictType, Throwable throwable){System.out.println("selectUserByNameFallback异常信息:" + throwable.getMessage());return getDataTable(new ArrayList<>());}

以上代码会触发对应的规则,需要注意必须为public ,返回值必须一致,请求参数必须一致,熔断和流量控制的参数为额外传递一个Throwable throwable和 BlockException ex。如果想定义在某个类中,可以blockHandlerclass和fallbackclass并在类中定义不同的方法。

feign的集成

package com.ruoyi.system.api;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog;
import com.ruoyi.system.api.factory.RemoteLogFallbackFactory;
import org.springframework.web.bind.annotation.RequestParam;import javax.validation.Valid;/*** 日志服务* * @author ruoyi*/
@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class)
public interface RemoteLogService
{/*** 保存系统日志** @param sysOperLog 日志实体* @param source 请求来源* @return 结果*/@PostMapping("/operlog")public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) throws Exception;/*** 保存访问记录** @param sysLogininfor 访问实体* @param source 请求来源* @return 结果*/@PostMapping("/logininfor")public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);/*** 测试使用* @param aa* @param source* @return*/@PostMapping("/operlog/a")public R<Boolean> saveLogA(@RequestParam(value = "aa")String aa, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

服务不可用时会走这个类,RemoteLogFallbackFactory

package com.ruoyi.system.api.factory;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog;/*** 日志服务降级处理* * @author ruoyi*/
@Component
public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogService>
{private static final Logger log = LoggerFactory.getLogger(RemoteLogFallbackFactory.class);@Overridepublic RemoteLogService create(Throwable throwable){log.error("日志服务调用失败:{}", throwable.getMessage());return new RemoteLogService(){@Overridepublic R<Boolean> saveLog(SysOperLog sysOperLog, String source){return R.fail("保存操作日志失败:" + throwable.getMessage());}@Overridepublic R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source){return R.fail("保存登录日志失败:" + throwable.getMessage());}@Overridepublic R<Boolean> saveLogA(String aa, String source) {return R.fail("保存操作日志失败:" + throwable.getMessage());}};}
}

以上代码结合ruoyi框架,可以自行模拟,在下游服务不可用时,会走降级方法。

sentinel集成 ,版本采用的是1.4.x

搭建参考连接

在项目中集成,使用ruoyi-system和ruoyi-file

先引入依赖
ruoyi-system

<!-- SpringBoot Seata -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

ruoyi-file

<!-- SpringBoot Seata -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

在ruoyi-system的bootstrap中引入

# seata配置
seata:enabled: true# Seata 应用编号,默认为 ${spring.application.name}application-id: ${spring.application.name}# Seata 事务组编号,用于 TC 集群名tx-service-group: my_test_tx_group # 要和nacos配置文件中一致# 关闭自动代理enable-auto-data-source-proxy: false# 服务配置项service:# 虚拟组和分组的映射vgroup-mapping:my_test_tx_group: default # 要和nacos配置文件中一致grouplist:default: 192.168.0.172:8091 #seata启动地址config:type: nacosnacos:serverAddr: 192.168.0.227:8848group: SEATA_GROUPnamespace: seataregistry:type: nacosnacos:application: seata-serverserver-addr: 192.168.0.227:8848namespace: seata

在ruoyi-file的bootstrap中引入

seata:enabled: true# Seata 应用编号,默认为 ${spring.application.name}application-id: ${spring.application.name}# Seata 事务组编号,用于 TC 集群名tx-service-group: my_test_tx_group# 关闭自动代理enable-auto-data-source-proxy: false# 服务配置项service:# 虚拟组和分组的映射vgroup-mapping:my_test_tx_group: defaultgrouplist:default: 192.168.0.172:8091config:type: nacosnacos:serverAddr: 192.168.0.227:8848group: SEATA_GROUPnamespace: seataregistry:type: nacosnacos:application: seata-serverserver-addr: 192.168.0.227:8848namespace: seata

因为集成了ShardingSphere,所以需要额外配置代理数据源,该配置在两个项目中都要引入

package com.ruoyi.file.config;import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceProxyConfig {
//    @Bean
//    @ConfigurationProperties(prefix = "spring.datasource")
//    public DataSource druidDataSource() {
//        return new DruidDataSource();
//    }@Primary@Beanpublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}
}

以上就配置完成,接下来进行测试。
点击新增菜单按钮,调用后端接口

 @RequiresPermissions("system:menu:add")@Log(title = "菜单管理", businessType = BusinessType.INSERT)@PostMapping
//    @Transactional@GlobalTransactional(rollbackFor = Exception.class)public AjaxResult add(@Validated @RequestBody SysMenu menu){if (!menuService.checkMenuNameUnique(menu)){return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");}else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())){return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");}menu.setCreateBy(SecurityUtils.getUsername());log.info("当前 XID: {}", RootContext.getXID());SysFileInfo fileInfo = new SysFileInfo();fileInfo.setFileName("11111111111");fileInfo.setFilePath("222222");AjaxResult ajaxResult = toAjax(menuService.insertMenu(menu));// 调用远程服务R<Boolean> booleanR = this.remoteFileService.saveFile(fileInfo);// 要根据上面的爆出对应的异常信息log.error(JSONObject.toJSONString(booleanR));if(booleanR.getCode() == 500) {throw new RuntimeException("巴伯错");}
//        int x=1/0;return ajaxResult ;}

ruoyi-file中的内容

package com.ruoyi.file.service;import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.file.mapper.SysFileInfoMapper;
import com.ruoyi.system.api.domain.SysFileInfo;
import io.seata.core.context.RootContext;@Service
public class SysFileInfoServiceImpl implements ISysFileInfoService
{private static final Logger log = LoggerFactory.getLogger(SysFileInfoServiceImpl.class);@Resourceprivate SysFileInfoMapper sysFileInfoMapper;/*** 事务传播特性设置为 REQUIRES_NEW 开启新的事务 重要!!!!一定要使用REQUIRES_NEW*/@Override@Transactional(propagation = Propagation.REQUIRES_NEW)public void insertFile(SysFileInfo fileInfo){fileInfo.setFileId(System.currentTimeMillis()+"");log.info("=============FILE START=================");log.info("当前 XID: {}", RootContext.getXID());sysFileInfoMapper.insert(fileInfo);int x=1/0;log.info("=============FILE END=================");}}

在调用远程服务 在新增菜单成功后,远程调用 this.remoteFileService.saveFile(fileInfo) 保存时出错。代码回滚成功,此时有一个注意事项,在下游服务报错,回传了降级方法内容或者全局异常时,需要在上游服务中抛出,要不然不能够正常处理。

还有一种情况,远程服务调用成功,在上游服务中报错,此时也会正常回滚。

 @RequiresPermissions("system:menu:add")@Log(title = "菜单管理", businessType = BusinessType.INSERT)@PostMapping
//    @Transactional@GlobalTransactional(rollbackFor = Exception.class)public AjaxResult add(@Validated @RequestBody SysMenu menu){if (!menuService.checkMenuNameUnique(menu)){return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");}else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())){return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");}menu.setCreateBy(SecurityUtils.getUsername());log.info("当前 XID: {}", RootContext.getXID());SysFileInfo fileInfo = new SysFileInfo();fileInfo.setFileName("11111111111");fileInfo.setFilePath("222222");// 调用远程服务R<Boolean> booleanR = this.remoteFileService.saveFile(fileInfo);// 要根据上面的爆出对应的异常信息log.error(JSONObject.toJSONString(booleanR));if(booleanR.getCode() == 500) {throw new RuntimeException("巴伯错");}int x=1/0;return  toAjax(menuService.insertMenu(menu));}

ruoyi-file中的内容

package com.ruoyi.file.service;import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.file.mapper.SysFileInfoMapper;
import com.ruoyi.system.api.domain.SysFileInfo;
import io.seata.core.context.RootContext;@Service
public class SysFileInfoServiceImpl implements ISysFileInfoService
{private static final Logger log = LoggerFactory.getLogger(SysFileInfoServiceImpl.class);@Resourceprivate SysFileInfoMapper sysFileInfoMapper;/*** 事务传播特性设置为 REQUIRES_NEW 开启新的事务 重要!!!!一定要使用REQUIRES_NEW*/@Override@Transactional(propagation = Propagation.REQUIRES_NEW)public void insertFile(SysFileInfo fileInfo){fileInfo.setFileId(System.currentTimeMillis()+"");log.info("=============FILE START=================");log.info("当前 XID: {}", RootContext.getXID());sysFileInfoMapper.insert(fileInfo);log.info("=============FILE END=================");}}

代码基本完成了,可能还有其他类型的,也基本差不多,遵循对应的规则就可以。

http://www.dtcms.com/wzjs/254000.html

相关文章:

  • 网站建设问题及解决办法seo顾问咨询
  • 如何形容一个网站做的好惠州seo网站推广
  • 开通网站流程网络营销工具和方法
  • 做房地产一级市场的看什么网站农产品网络营销方案
  • 张云网站建设如何让百度收录网址
  • 免费商业网站模板seo诊断服务
  • iis 建立默认网站万网域名注册流程
  • 网站建设熊掌号上海百度推广排名优化
  • 黄南北京网站建设2022年度关键词
  • 网站公司动态做不了怎么办为什么外包会是简历污点
  • 做网站编程的电脑配置杭州网站建设方案优化
  • wordpress免费下载windows优化大师的特点
  • 帮人做网站收多少钱北京网站建设公司优势
  • 郑州外贸网站建设公司价格百度竞价推广有哪些优势
  • 重庆网站建开发郑州专业seo推荐
  • 中国做网站找谁万网域名注册教程
  • 专业网站设计公司爱站网长尾词挖掘
  • 福田商城网站制作网络营销做的比较好的企业
  • 乐清微网站建设写软文能赚钱吗
  • 全屏响应式网站网站推广软件哪个最好
  • 云服务器怎么搭建网站汕头网站设计公司
  • 免费网站开发网站优化方案怎么写
  • 网站策划与建设阶段上海网站建设费用
  • 南京专业做网站惠州企业网站建设
  • 网上找工程项目怎么找抖音seo查询工具
  • 佛山网站关键词优化公司seo网站优化服务合同
  • 百度网站制作公司百度知道官网手机版
  • 手把手做网站页面北京seo排名服务
  • 成都网站建设排名今日特大军事新闻
  • 沈阳网站建设黑酷科技十堰seo优化