zoukankan      html  css  js  c++  java
  • seata 分布式事务 -- seata-one 工程完整代码

     

    eureka,沿用  TX-LCN分布式事务-- LCN事务模式(eureka模块)

    seata-one  工程结构:

    配置文件在最下面:

    启动类:

    package com.;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class SeataOneApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SeataOneApplication.class, args);
        }
    
        @Bean
        @LoadBalanced//开启负载均衡
        public RestTemplate restTemplate(){
    
            return new RestTemplate();
        }
    }

    入口  controller:

    (一个 AT 模式,一个 TCC 模式)

    
    
    package com..controller;

    import com..service.Rm_One_Interface;
    import com..service.Rm_One_Service;
    import io.seata.spring.annotation.GlobalTransactional;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class Rm_One_Controller {

    @Autowired
    private Rm_One_Service rm_one_service;

    @Autowired
    private Rm_One_Interface rm_one_interface;


    /**
    * AT 模式
    * @return
    */
    @RequestMapping("/one_at")
    @GlobalTransactional(rollbackFor = Exception.class)
    public String at_one(){

    String result = rm_one_service.rm1();
    if(result.equals("err")){
    return "err";
    }
    return "success_"+result;
    }


    /**
    * TCC模式
    * @return
    * @throws InterruptedException
    */
    @RequestMapping("/one_tcc")
    @GlobalTransactional(rollbackFor = Exception.class)
    public String oneTcc() throws InterruptedException {
    rm_one_interface.rm1(null);
    return "success";
    }


    }
     

    数据库实体类:

    package com..entity;
    
    
    public class TbloneInfo {
        
        private String id;
    
        
        private String name;
    
        
        public String getId() {
            return id;
        }
    
        
        public void setId(String id) {
            this.id = id;
        }
    
        
        public String getName() {
            return name;
        }
    
       
        public void setName(String name) {
            this.name = name == null ? null : name.trim();
        }
    }

    mapper:

    package com..mapper;
    
    import com..entity.TbloneInfo;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    @Mapper
    @Component(value = "TbloneInfoMapper")
    public interface TbloneInfoMapper {
        
        int deleteByPrimaryKey(String id);
    
        
        int insert(TbloneInfo record);
    
       
        TbloneInfo selectByPrimaryKey(String id);
    
       
        List<TbloneInfo> selectAll();
    
       
        int updateByPrimaryKey(TbloneInfo record);
    }

    AT 模式 实现类:

    package com..service;
    
    
    import com..entity.TbloneInfo;
    import com..mapper.TbloneInfoMapper;
    import com..sqlToJava.SnowFlake;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * AT 模式 
     */
    @Service
    public class Rm_One_Service {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Autowired
        TbloneInfoMapper tbloneInfoMapper;
    
    
        public String rm1(){
    
            long id = SnowFlake.nextId();
            TbloneInfo tbloneInfo = new TbloneInfo();
            tbloneInfo.setId(id+"");
            tbloneInfo.setName("Rm_One_"+id);
            int insert = tbloneInfoMapper.insert(tbloneInfo);
    
            rm2();
    
            rm3();
    
            if (insert==1){
                return id+"";
            }
            return "err";
        }
    
    
        public String rm2(){
    
            restTemplate.getForObject("http://seata-two/two_at", String.class);
            return "";
        }
    
    
        public String rm3(){
    
            restTemplate.getForObject("http://seata-three/three_at", String.class);
    
            return "";
        }
    }

    TCC模式 接口 / 实现类:

    接口:

    package com..service; import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.LocalTCC; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; @LocalTCC public interface Rm_One_Interface { @TwoPhaseBusinessAction(name = "rm1TccAction",commitMethod = "rm1Commit",rollbackMethod = "rm1Rollback") public String rm1(BusinessActionContext businessActionContext); public boolean rm1Commit(BusinessActionContext businessActionContext); public boolean rm1Rollback(BusinessActionContext businessActionContext); }


    实现类:
    package com..service;

    import com..entity.TbloneInfo;
    import com..mapper.TbloneInfoMapper;
    import com..sqlToJava.SnowFlake;
    import io.seata.rm.tcc.api.BusinessActionContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.client.RestTemplate;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;

    @Component
    public class Rm_One_InterfaceImpl implements Rm_One_Interface {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    TbloneInfoMapper tbloneInfoMapper;

    private static ConcurrentMap<String,String> maps = new ConcurrentHashMap<>();

    @Override
    @Transactional
    public String rm1(BusinessActionContext businessActionContext) {

    long id = SnowFlake.nextId();
    TbloneInfo tbloneInfo = new TbloneInfo();
    tbloneInfo.setId(id+"");
    tbloneInfo.setName("Rm_One_"+id);
    maps.put("id",id+"");
    int insert = tbloneInfoMapper.insert(tbloneInfo);
    System.out.println("rm1 try....."+insert);
    rm2();
    rm3();

    return null;
    }

    @Override
    @Transactional
    public boolean rm1Commit(BusinessActionContext businessActionContext) {
    System.out.println("rm1 rm1Commit...");
    return true;
    }

    @Override
    @Transactional
    public boolean rm1Rollback(BusinessActionContext businessActionContext) {

    String id = maps.get("id");
    int i = tbloneInfoMapper.deleteByPrimaryKey(id);
    System.out.println("rm1 rm1Rollback..."+i);
    return true;
    }



    public String rm2(){

    restTemplate.getForObject("http://seata-two/two_tcc", String.class);
    return "";
    }


    public String rm3(){

    restTemplate.getForObject("http://seata-three/three_tcc", String.class);

    return "";
    }

    }
     

    一个数据库主键生成工具类(雪花算法):

    package com..sqlToJava;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.RuntimeMXBean;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.Enumeration;
    
    /**
     * id自增器(雪花算法)
     *
     * @author renjie
     * @version 1.0.0
     */
    public class SnowFlake {
    
        private final static long twepoch = 12888349746579L;
        // 机器标识位数
        private final static long workerIdBits = 5L;
        // 数据中心标识位数
        private final static long datacenterIdBits = 5L;
    
        // 毫秒内自增位数
        private final static long sequenceBits = 12L;
        // 机器ID偏左移12位
        private final static long workerIdShift = sequenceBits;
        // 数据中心ID左移17位
        private final static long datacenterIdShift = sequenceBits + workerIdBits;
        // 时间毫秒左移22位
        private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
        //sequence掩码,确保sequnce不会超出上限
        private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
        //上次时间戳
        private static long lastTimestamp = -1L;
        //序列
        private long sequence = 0L;
        //服务器ID
        private long workerId = 1L;
        private static long workerMask = -1L ^ (-1L << workerIdBits);
        //进程编码
        private long processId = 1L;
        private static long processMask = -1L ^ (-1L << datacenterIdBits);
    
        private static SnowFlake snowFlake = null;
    
        static{
            snowFlake = new SnowFlake();
        }
        public static synchronized long nextId(){
            return snowFlake.getNextId();
        }
    
        private SnowFlake() {
    
            //获取机器编码
            this.workerId=this.getMachineNum();
            //获取进程编码
            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            this.processId=Long.valueOf(runtimeMXBean.getName().split("@")[0]).longValue();
    
            //避免编码超出最大值
            this.workerId=workerId & workerMask;
            this.processId=processId & processMask;
        }
    
        public synchronized long getNextId() {
            //获取时间戳
            long timestamp = timeGen();
            //如果时间戳小于上次时间戳则报错
            if (timestamp < lastTimestamp) {
                try {
                    throw new Exception("Clock moved backwards.  Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //如果时间戳与上次时间戳相同
            if (lastTimestamp == timestamp) {
                // 当前毫秒内,则+1,与sequenceMask确保sequence不会超出上限
                sequence = (sequence + 1) & sequenceMask;
                if (sequence == 0) {
                    // 当前毫秒内计数满了,则等待下一秒
                    timestamp = tilNextMillis(lastTimestamp);
                }
            } else {
                sequence = 0;
            }
            lastTimestamp = timestamp;
            // ID偏移组合生成最终的ID,并返回ID
            long nextId = ((timestamp - twepoch) << timestampLeftShift) | (processId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
            return nextId;
        }
    
        /**
         * 再次获取时间戳直到获取的时间戳与现有的不同
         * @param lastTimestamp
         * @return 下一个时间戳
         */
        private long tilNextMillis(final long lastTimestamp) {
            long timestamp = this.timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = this.timeGen();
            }
            return timestamp;
        }
    
        private long timeGen() {
            return System.currentTimeMillis();
        }
    
        /**
         * 获取机器编码
         * @return
         */
        private long getMachineNum(){
            long machinePiece;
            StringBuilder sb = new StringBuilder();
            Enumeration<NetworkInterface> e = null;
            try {
                e = NetworkInterface.getNetworkInterfaces();
            } catch (SocketException e1) {
                e1.printStackTrace();
            }
            while (e.hasMoreElements()) {
                NetworkInterface ni = e.nextElement();
                sb.append(ni.toString());
            }
            machinePiece = sb.toString().hashCode();
            return machinePiece;
        }
    }

    application.yml  :

    server:
      port: 8080
    
    #应用名称及验证账号
    spring:
      application:
        name: seata-one
    
    
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/seata-rm-one?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
        username: root
        password: root
        dbcp2:
          initial-size: 5
          min-idle: 5
          max-total: 5
          max-wait-millis: 200
          validation-query: SELECT 1
          test-while-idle: true
          test-on-borrow: false
          test-on-return: false
    
    mybatis:
      mapper-locations:
        - classpath:mapper/*.xml
    
    eureka:
      client:
        prefer-ip-address: true
        service-url:
          defaultZone: http://localhost:7900/eureka/

    数据库链接 TbloneInfoMapper.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..mapper.TbloneInfoMapper">
      <resultMap id="BaseResultMap" type="com..entity.TbloneInfo">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        <id column="id" jdbcType="VARCHAR" property="id" />
        <result column="name" jdbcType="VARCHAR" property="name" />
      </resultMap>
      <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        delete from tbl_one
        where id = #{id,jdbcType=VARCHAR}
      </delete>
      <insert id="insert" parameterType="com..entity.TbloneInfo">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        insert into tbl_one (id, name)
        values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR})
      </insert>
      <update id="updateByPrimaryKey" parameterType="com..entity.TbloneInfo">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        update tbl_one
        set name = #{name,jdbcType=VARCHAR}
        where id = #{id,jdbcType=VARCHAR}
      </update>
      <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        select id, name
        from tbl_one
        where id = #{id,jdbcType=VARCHAR}
      </select>
      <select id="selectAll" resultMap="BaseResultMap">
        <!--
          WARNING - @mbg.generated
          This element is automatically generated by MyBatis Generator, do not modify.
          This element was generated on Mon May 17 11:02:49 CST 2021.
        -->
        select id, name
        from tbl_one
      </select>
    </mapper>

    pom:

    (<groupId>com.</groupId> 需要根据情况补充 )

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.5</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.</groupId>
        <artifactId>seata-one</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>seata-one</name>
        <description>seata-oneBoot</description>
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>2020.0.2</spring-cloud.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <!-- euekea 依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
            <!-- mysql:MyBatis相关依赖-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.0.0</version>
            </dependency>
    
            <!-- 整合MyBatis java类依赖 -->
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.4.0</version>
                <type>maven-plugin</type>
            </dependency>
    
            <!-- mysql:mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!-- mysql:阿里巴巴数据库连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
            <!--  JSONObject  -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.60</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-seata</artifactId>
                <version>2.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-commons</artifactId>
                <version>3.0.2</version>
            </dependency>
    
        </dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
  • 相关阅读:
    python + selenium 环境搭建及问题
    SQL数据库各种查询建表插入集合-待续持续更新
    使chrome支持跨域访问
    PayPal 开发详解(七):运行REST API SAMPLE
    PayPal 开发详解(六):下载paypal立即付款SDK 并编译打包
    PayPal 开发详解(五):创建第一个应用,获取clientId和clientSecret
    PayPal 开发详解(四):买家付款
    PayPal 开发详解(三):在网站上创建【立即付款】按钮
    PayPal 开发详解(二):开启【自动返回】和【数据传输】
    PayPal 开发详解(一):注册PayPal帐号
  • 原文地址:https://www.cnblogs.com/lifan12589/p/14781543.html
Copyright © 2011-2022 走看看