0
点赞
收藏
分享

微信扫一扫

蓝桥杯刷题_day8_动态规划_简单多状态

得一道人 04-02 08:31 阅读 3

文章目录

1.集成测试

1.集成测试正常下单
1.步骤

image-20240331195720151

2.浏览器访问 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100

image-20240331200211635

image-20240331200315814

image-20240331200345159

image-20240331200405815

image-20240331200414455

3.注意事项和细节

image-20240331201240727

2.集成测试模拟异常
1.步骤
1.com/sun/springcloud/controller/StorageController.java 休眠12s,模拟openfeign超时

image-20240331204813269

2.仍然按照正常步骤启动并测试

image-20240331195720151

3.预测结果
  • 保存订单,扣减账户余额,扣减库存成功!但是修改订单状态失败,也就是status是0!

image-20240331202326884

image-20240331202503115

2.执行前数据库状态
order表

image-20240331204912334

account表

image-20240331204932277

storage表

image-20240331205004551

3.浏览器输入 http://localhost:10008/order/save?userId=666&productId=1&nums=2&money=200,12s后查看数据库状态
order表

image-20240331205124780

account表(这里在写sql时并没有计算数量,所以确实应该减去200)

image-20240331205149516

storage表(库存减2)

image-20240331210545726

3.集成测试分布式事务控制
1.在com/sun/springcloud/service/Impl/OrderServiceImpl.java 的save方法加上@GlobalTransactional进行分布式事务控制

image-20240401085848112

2.测试步骤

image-20240331195720151

3.全部启动后查看nacos注册情况

image-20240401090152198

4.测试前数据库状态

image-20240401090227123

image-20240401090238720

image-20240401090249370

5.浏览器请求 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100

image-20240401090600011

image-20240401090536951

image-20240401090546928

image-20240401090555538

5.注意事项

image-20240401091116586

2.seata分布式事务总结

1.工作机制

image-20240401100528767

2.seata的使用流程
1.安装
2.修改 D:\seata\conf\file.conf文件
1.修改事务组(需要进行分布式事务控制的微服务在同一组)

image-20240331094307051

2.修改日志存储模式为db

image-20240331094402339

3.修改数据库(MySQL5.7)连接信息

在这里插入图片描述

3.修改registry.conf 配置注册中心nacos(seata需要注册到nacos)

image-20240331095851458

image-20240331095834040

4.创建seata数据库和表
1.创建seata数据库
# 创建数据库 seata
create database seata;
use seata;
2.复制db_store.sql的内容,创建需要的表

image-20240401101509841

image-20240331095307621

5.启动nacos和seata进行测试,seata会注册到nacos
6.为每个需要分布式事务控制的数据库执行 db_undo_log.sql,创建undo_log表,用于事务回滚

image-20240331103729957

7.pom.xml引入依赖
  • 注意这里引入的nacos是nacos-discovery starter,没有整合Seata之前引入的跟这个不一样!!!
    <dependencies>
        <!-- 提示 application.yml -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 引入 openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 在微服务模块引入 nacos-discovery starter -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--seata-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <exclusions>
                <!-- 排除自带的 seata-all -->
                <exclusion>
                    <artifactId>seata-all</artifactId>
                    <groupId>io.seata</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引入指定版本的 io.seata -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>0.9.0</version>
        </dependency>

        <!-- springboot web starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 如果在子工程/模块指定了 version,则以指定为准 -->
        </dependency>

        <!--
        1. starter-actuator 是 springboot 程序的监控系统,可以实现健康检查,info 信息
        等
        2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. -->
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <!-- 这里我们重新指定一下 version 因为父项目中没有对这个依赖进行版本仲裁-->
            <version>1.1.13</version>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 公共模块的jar包 -->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>e_commerce_center-common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
8.application.yml
server:
  port: 10010 # 配置服务端口
spring:
  application:
    name: seata-storage-micor-service # 配置服务的名称,名字任意这里与项目名保持一致
  cloud:
    alibaba:
      seata:  # 配置seata
        tx-service-group: sun_order_tx_group # 自定义事务组名称,与\conf\file.conf保持一致
    nacos: # 配置nacos
      discovery:
        server-addr: localhost:8848
  datasource: # 配置数据源
    driver-class-name: com.mysql.jdbc.Driver
    # 别忘记创建数据库之后修改数据库名称
    url: 
    username: 
    password: 
logging:  # 配置seata日志级别
  level:
    io:
      seata: info
mybatis:
  mapperLocations: classpath:mapper/*.xml # 扫描所有Mapper.xml
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰命名
9.D:\seata\conf下的两个配置文件复制到src/main/resources下并修改
1.将file.conf复制到src/main/resources下,然后修改这行,seata的服务ip+端口以及db根据实际情况修改(前面是修改过的)

image-20240331112838536

2.registry.conf复制到src/main/resources下,然后配置注册中心nacos(前面也配过,直接复制即可)

image-20240331113355613

3.最终的文件目录

image-20240331113408627

10.进行业务逻辑编写
1.创建实体类
  • 如果数据库中的数据是sun_name则在实体类中可以编写为sunName,不过这样需要在application.yml中开启自动驼峰命名(上面配置了)
  • 这个就相当于在每个Mapper.xml中加了一个resultMap映射,如果实体类属性和表的字段可以被自动驼峰命名所映射那么就不需要再写resultMap
2.dao层
  • Mapper接口注入容器
  • Mapper接口的@Param注解一旦指定,就不需要在xml实现的时候指定参数类型了,直接使用#{}来取出数据即可
  • Mapper.xml在application.yml中已经配置了自动扫描
3.service层
  • service接口编写
  • service实现类注入容器
4.controller层
  • 注入容器
  • 在微服务中如果使用GetMapping则参数需要添加@RequestParam
  • 如果使用PostMapping则参数需要添加@RequestBody
11.两个常规配置类
1.MyBatisConfig.java 配置类,依赖注入所有Mapper接口(不用加@Mapper注解了)
package com.sun.springcloud.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

/**
 * Description: MyBatis配置类,扫描所有Mapper接口,这样就不用在每个Mapper接口上添加@Mapper注解
 *
 * @Author sun
 * @Create 2024/3/31 13:16
 * @Version 1.0
 */
@MapperScan("com.sun.springcloud.dao")
@Configuration
public class MyBatisConfig {
}

2.DataSourceProxyConfig.java 配置数据源代理为 seata
  • 这里需要注意:配置文件中的mybatis.mapperLocations是以驼峰命名的
package com.sun.springcloud.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * Description: 配置数据源的代理是 seata
 *
 * @Author sun
 * @Create 2024/3/31 13:28
 * @Version 1.0
 */
@Configuration
public class DataSourceProxyConfig {
    // 配置文件中的mybatis.mapperLocations
    @Value("${mybatis.mapperLocations}")
    private String mapperLocations; // 1.mybatis的mapper文件位置

    // 配置数据源
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource") // 2.读取配置文件中的数据源配置
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    // 配置数据源代理为seata的DataSourceProxy
    @Bean // 配置数据源代理引入的包: io.seata.rm.datasource.DataSourceProxy
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }

    // 配置SqlSessionFactory为seata的SqlSessionFactoryBean
    @Bean // 配置SqlSessionFactory,常规配置
    public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy)
            throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean =
                new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        sqlSessionFactoryBean.setMapperLocations
                (new PathMatchingResourcePatternResolver().getResources(mapperLocations)); // 3.mybatis的mapper文件位置
        sqlSessionFactoryBean.setTransactionFactory
                (new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();
    }
}

12.创建主启动类(示例)
package com.sun.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/3/31 13:37
 * @Version 1.0
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 取消数据源的自动创建,使用代理数据源
@EnableDiscoveryClient // 开启服务发现
@EnableFeignClients // 开启Feign客户端
public class SeataStorageMicroServiceApplication10010 {
    public static void main(String[] args) {
        SpringApplication.run(SeataStorageMicroServiceApplication10010.class, args);
    }
}

13.OpenFeign远程调用细节
1.在前面的依赖中已经引入了OpenFeign,并且在主启动类中也开启了Feign客户端
2.service接口声明需要远程调用的controller
  • 这里的FeignClient可以进行服务发现,得到要调用的服务的ip+端口+上下文路径
  • 这里的RequestMapping可以找到远程调用的服务的资源路径,与服务发现的路径进行拼接即可找到指定资源
  • 具体声明的方式就是
    1. 添加@FeignClient注解,指定要远程调用服务的application-name(注意不能带_)
    2. 将需要调用的controller直接复制过来,然后去掉方法体即可
package com.sun.springcloud.service;

import com.sun.springcloud.util.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/3/31 16:19
 * @Version 1.0
 */
@FeignClient(value = "seata-storage-micor-service")
public interface StorageService {
    @RequestMapping("/storage/reduce")
    public Result reduce(Long productId, Integer nums);
}

3.远程调用的方式
  • 通过依赖注入针对service接口的代理对象进行远程调用
4.谁可以远程调用
  • service接口实现类
  • controller
举报

相关推荐

0 条评论