星火大模型AI接口Spring中项目中使用【星火、AIGC】

news2024/11/20 16:28:51

星火大模型AI接口使用

讯飞的星火大模型是有免费版本赠送200万个Token,就个人学习来说完全够用了。

请添加图片描述

免费申请过后,到控制台,两个红色方框是最要紧的。

请添加图片描述

星火认知大模型Web文档 | 讯飞开放平台文档中心 (xfyun.cn)这是官方文档对于接口的详细使用,里面有对各种请求的详细描述。接下来我们将在Spring项目中使用星火的AIGC能力。

首先是星火给的APPID、APISecret、APIKey是连接到大模型的关键,通过这三个参数按照通用鉴权URL生成说明 | 讯飞开放平台文档中心 (xfyun.cn)生成通用鉴权URL就可以就行html请求,发送请求参数,接受返回信息。

https://xfyun-doc.cn-bj.ufileos.com/static%2F16933832521697972%2Fbig_model.zip 这是官方给出的Java例子。

通用鉴权URL的生成

官方给的,直接拿来用。

/ 获得鉴权地址
    public static String getAuthUrl(String hostUrl, String apiSecret, String apiKey) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

项目中实现

在项目中使用我们需要一个Config进行全局配置,一个WebListener发送接受请求,还有与星火交互的DTO。

请添加图片描述

1. XfunConfig
/**
 *   星火大模型AI接口配置
 */
@Configuration
@Data
@ConfigurationProperties(prefix = "xfun.open")
public class XfunConfig {
    private String appid;
    private String apiSecret;
    private String hostUrl;
    private String apiKey;
}

在application.yml中的配置

#星火
xfun:
  open:
    appid: XXXXXXXXXXXXXXXXXXXXXXX
    apiSecret: XXXXXXXXXXXXXXXXXXXXXXX
    hostUrl: https://spark-api.xf-yun.com/v2.1/chat
    apiKey: XXXXXXXXXXXXXXXXXXXXXXX
3. DTO – Xfun

看官方文档中对请求参数以及对各个字段的解释。

# 参数构造示例如下
{
        "header": {
            "app_id": "12345",
            "uid": "12345"
        },
        "parameter": {
            "chat": {
                "domain": "general",
                "temperature": 0.5,
                "max_tokens": 1024, 
            }
        },
        "payload": {
            "message": {
                # 如果想获取结合上下文的回答,需要开发者每次将历史问答信息一起传给服务端,如下示例
                # 注意:text里面的所有content内容加一起的tokens需要控制在8192以内,开发者如有较长对话需求,需要适当裁剪历史信息
                "text": [
                    {"role": "user", "content": "你是谁"} # 用户的历史问题
                    {"role": "assistant", "content": "....."}  # AI的历史回答结果
                    # ....... 省略的历史对话
                    {"role": "user", "content": "你会做什么"}  # 最新的一条问题,如无需上下文,可只传最新一条问题
                ]
        }
    }
}

请添加图片描述

其中Message单独为一个类

/**
 * 消息对象
 *
 */
@Data
public class MsgDTO {
    /**
     * 角色
     */
    private String role;
    /**
     * 消息内容
     */
    private String content;
    private Integer index;

    @Getter
    public static enum Role {
        SYSTEM("system"),
        USER("user"),
        ASSISTANT("assistant");

        private String name;

        private Role(String name) {
            this.name = name;
        }
    }

}

这样一个请求构成的数据对象类如下:

@Data
public class XfunSendRequest {

    @JsonProperty("header")
    private Header header;

    @JsonProperty("parameter")
    private ParameterDTO parameterDTO;

    @JsonProperty("payload")
    private PayloadDTO payload;
    @Data
    public static class Header{
        @JSONField(name = "app_id")
        private String appId;
        @JSONField(name = "uid")
        private String uid;
    }

    @ Data
    public static class ParameterDTO{

        @JsonProperty("chat")
        private ChatDTO chat;
        @Data
        public static class ChatDTO {
            @JsonProperty("domain")
            private String domain = "generalv2";
            @JsonProperty("temperature")
            private Double temperature = 0.5;
            @JSONField(name = "max_tokens")
            private Integer maxTokens = 2048;
        }
    }

    @Data
    public static class PayloadDTO {
        @JsonProperty("message")
        private MessageDTO message;


        @Data
        public static class MessageDTO {
            @JsonProperty("text")
            private List<MsgDTO> text;


        }
    }


}

接下来是构造接口响应对象:

# 接口为流式返回,此示例为最后一次返回结果,开发者需要将接口多次返回的结果进行拼接展示
{
    "header":{
        "code":0,
        "message":"Success",
        "sid":"cht000cb087@dx18793cd421fb894542",
        "status":2
    },
    "payload":{
        "choices":{
            "status":2,
            "seq":0,
            "text":[
                {
                    "content":"我可以帮助你的吗?",
                    "role":"assistant",
                    "index":0
                }
            ]
        },
        "usage":{
            "text":{
                "question_tokens":4,
                "prompt_tokens":5,
                "completion_tokens":9,
                "total_tokens":14
            }
        }
    }
}

请添加图片描述

由官方描述可见,其中 payload.choice.text中的内容就是构造的MsgDto, 根据官方文档给出的接口响应构造XfunReceieveRequest;

@Data
public class XfunReceieveRequest {

    @JsonProperty("header")
    private HeaderDTO header;
    @JsonProperty("payload")
    private PayloadDTO payload;

    @NoArgsConstructor
    @Data
    public static class HeaderDTO {
        @JsonProperty("code")
        private Integer code;
        @JsonProperty("message")
        private String message;
        @JsonProperty("sid")
        private String sid;
        @JsonProperty("status")
        private Integer status;
    }

    @NoArgsConstructor
    @Data
    public static class PayloadDTO {
        @JsonProperty("choices")
        private ChoicesDTO choices;
        @JsonProperty("usage")
        private UsageDTO usage;

        @NoArgsConstructor
        @Data
        public static class ChoicesDTO {
            @JsonProperty("status")
            private Integer status;
            @JsonProperty("seq")
            private Integer seq;
            @JsonProperty("text")
            private List<MsgDTO> text;

        }

        @NoArgsConstructor
        @Data
        public static class UsageDTO {
            @JsonProperty("text")
            private TextDTO text;

            @NoArgsConstructor
            @Data
            public static class TextDTO {
                @JsonProperty("question_tokens")
                private Integer questionTokens;
                @JsonProperty("prompt_tokens")
                private Integer promptTokens;
                @JsonProperty("completion_tokens")
                private Integer completionTokens;
                @JsonProperty("total_tokens")
                private Integer totalTokens;
            }
        }
    }

}

这样发送和接受请求都构造完成可以尝试与星火进行交互。

使用WebSocket将XfunSendRequest发出即可;以下是XfunListener中发送消息代码:

    public XfunListener sendMsg(String uid, List<MsgDTO> msgs, XfunListener webSocketListener) throws Exception {
        // 获取鉴权url
        String url = getAuthUrl(hostUrl,apiSecret,apiKey);
        //建立请求
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(url).build();

        WebSocket webSocket = okHttpClient.newWebSocket(request, webSocketListener);

        XfunSendRequest xfunSendRequest = this.getSendRequest(uid, msgs);
        System.out.println("params:" + JSONObject.toJSONString(xfunSendRequest));

        //发送消息
        webSocket.send(JSONObject.toJSONString(xfunSendRequest));

        return webSocketListener;
    }

可以看到整个发送消息的过程:

  1. 建立请求,根据请求创建WebSoeckt
  2. 利用WebSocket发出XfunSendRequest

接受消息写在XfunListener的OnMessage重载函数中,根据XfunReceiveRequest来处理数据;

3. XfunListener

具体代码如下:

最关键的就是两个函数:

  • OnMessage: 接受消息,处理消息
  • SendMsg: 发送消息
@Builder
public class XfunListener extends WebSocketListener {
    private String hostUrl;
    private String appid;
    private String apiSecret;
    private String apiKey;

    @Builder.Default
    public boolean is_finished = false;

    @Builder.Default
    private String answer = "";

    public String getAnswer() {
        return answer;
    }
    public boolean isFinished() {
        return is_finished;
    }

    public List<MsgDTO> getHistoryList() {
        return historyList;
    }

    @Builder.Default
    public List<MsgDTO> historyList = new ArrayList<>();
    @Override
    public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
        super.onOpen(webSocket, response);
    }

    public  void deleteHistory(){
        historyList = new ArrayList<>();
    }
    public void init_chat(){
        is_finished = false;
    }
    // 接收到消息如何处理
    @Override
    public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
        super.onMessage(webSocket, text);

        // System.out.println("接收到消息:" + text);

        // 消息格式处理
        XfunReceieveRequest xfunReceieveRequest = JSONObject.parseObject(text, XfunReceieveRequest.class);


        //状态判断
        if(xfunReceieveRequest.getHeader().getCode() == 0) {
            // 0的话 ,获取状态成功
            XfunReceieveRequest.PayloadDTO payload = xfunReceieveRequest.getPayload();
            XfunReceieveRequest.PayloadDTO.ChoicesDTO choices = payload.getChoices();
            //处理得到的答案
            List<MsgDTO> msgs = choices.getText();
            //打上index
            for(int i = 0; i < msgs.size(); i++){
                MsgDTO msg =msgs.get(i);
                msg.setIndex(historyList.size()+i);
                historyList.add(msg);
            }

            if(xfunReceieveRequest.getHeader().getStatus() == 2){
                //表示会话来到最后一个结果
                XfunReceieveRequest.PayloadDTO.UsageDTO.TextDTO text1 = payload.getUsage().getText();
                System.out.println("PromptTokecn:" + text1.getPromptTokens());
                System.out.println("QuestionToken:" + text1.getQuestionTokens());
                System.out.println("CompletionToken:" + text1.getCompletionTokens());
                System.out.println("TotalToken"+text1.getTotalTokens());

                is_finished = true;

                // 消息整合
                StringBuilder message = new StringBuilder();
                for(MsgDTO msg: historyList){
                    message.append(msg.getContent());
                }
                deleteHistory();
                answer = message.toString();
                //断开连接
               // webSocket.close(3,"客户端断开连接");


            }
        }
    }

    // 获得鉴权地址
    public static String getAuthUrl(String hostUrl, String apiSecret, String apiKey) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

    // msgs和uid 转成 XfunSendRequest
    public XfunSendRequest getSendRequest(String uid, List<MsgDTO> msgs) {
        XfunSendRequest xfunSendRequest = new XfunSendRequest();
        XfunSendRequest.Header header = new XfunSendRequest.Header();
        header.setAppId(appid);
        header.setUid(uid);
        xfunSendRequest.setHeader(header);
        XfunSendRequest.ParameterDTO parameterDTO = new XfunSendRequest.ParameterDTO();
        XfunSendRequest.ParameterDTO.ChatDTO chatDTO = new XfunSendRequest.ParameterDTO.ChatDTO();
        parameterDTO.setChat(chatDTO);
        xfunSendRequest.setParameterDTO(parameterDTO);
        XfunSendRequest.PayloadDTO payloadDTO = new XfunSendRequest.PayloadDTO();
        XfunSendRequest.PayloadDTO.MessageDTO messageDTO = new XfunSendRequest.PayloadDTO.MessageDTO();
        messageDTO.setText(msgs);
        payloadDTO.setMessage(messageDTO);
        xfunSendRequest.setPayload(payloadDTO);
        return xfunSendRequest;

    }

    /**
     *  发送信息
     */
    public XfunListener sendMsg(String uid, List<MsgDTO> msgs, XfunListener webSocketListener) throws Exception {
        // 获取鉴权url
        String url = getAuthUrl(hostUrl,apiSecret,apiKey);
        //建立请求
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(url).build();

        WebSocket webSocket = okHttpClient.newWebSocket(request, webSocketListener);

        XfunSendRequest xfunSendRequest = this.getSendRequest(uid, msgs);
        System.out.println("params:" + JSONObject.toJSONString(xfunSendRequest));

        //发送消息
        webSocket.send(JSONObject.toJSONString(xfunSendRequest));

        return webSocketListener;
    }
}

可以看到这个XfunListener不是一个Bean,所以在MainApplication中创建了这个Bean。

@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
@MapperScan("com.yupi.springbootinit.mapper")
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class MainApplication {

    @Autowired
    private XfunConfig xfunConfig;


    public static void main(String[] args) {

        SpringApplication.run(MainApplication.class, args);

    }

    @Bean
    public XfunListener getXfunListener() {
        return XfunListener.builder()
                .apiKey(xfunConfig.getApiKey())
                .apiSecret(xfunConfig.getApiSecret())
                .hostUrl(xfunConfig.getHostUrl())
                .appid(xfunConfig.getAppid()).build();
    }
}

这样整个星火的AIGC就设计完成,可以随意复用在任意的项目之中,利用XfunListener即可发送消息或获取消息。

详细的数据处理,发送消息,另外写一个AI的Service做具体的处理即可。例如以下一个简单的实例:

@Service
public class AiManager {

    
    @Resource
    private XfunListener xfunListener;  // 实现发送接受消息的websockect
    
        public String testChat(String question){
        
        //8位随机数
        String random = String.valueOf((int)((Math.random()*9+1)*10000000));
        List<MsgDTO> msgs = new ArrayList<>();
        MsgDTO msgDTO = new MsgDTO( );
        msgDTO.setRole("user");
        msgDTO.setContent(question);
        msgDTO.setIndex(0);
        msgs.add(msgDTO);
        
        xfunListener.init_chat();
        try {
            // 获取接受消息的webSoeckt
            XfunListener webSocket = xfunListener.sendMsg(random, msgs, xfunListener);
            //等待weSocked返回消息 , 这是一个笨笨的处理方法。
            int cnt = 30;
            //最长等待30S
            while (!webSocket.isFinished() && cnt > 0){
                Thread.sleep(1000);  //休息1S
                cnt--;
            }
            if(cnt == 0){
                return null;
            }

            String answer = webSocket.getAnswer();
            //返回答案
            return answer;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        AiManager ai = new AiManager();
        ai.xfunListener =  XfunListener.builder()
             .apiKey("xxxxxxx")
               .apiSecret("xxxxxxx")
               .appid("xxxxxxx")
                .hostUrl("https://spark-api.xf-yun.com/v2.1/chat")
               .build();

        System.out.println(ai.testChat("你好啊!"));
    }


}

AiManager运行结果

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1064377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI视野·今日NLP 自然语言处理论文速览 四十九期】Fri, 6 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Fri, 6 Oct 2023 Totally 44 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MathCoder: Seamless Code Integration in LLMs for Enhanced Mathematical Reasoning Authors Ke Wang, Houxi…

如何一键转发朋友圈,快速跟圈?

你是否曾为在微信上快速转发别人的朋友圈而烦恼&#xff1f;每天都要花费大量时间下载商品图片和复制粘贴商家的文案&#xff0c;让人疲惫不堪。我觉得这样太繁琐太麻烦了&#xff0c;每天都会上新货&#xff0c;上传朋友圈都要花将近一个小时的时间&#xff0c;花了大量时间在…

【C++设计模式之状态模式:行为型】分析及示例

简介 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为&#xff0c;看起来就像是改变了其类。状态模式将对象的状态封装成不同的类&#xff0c;并使得对象在不同状态下有不同的行为。 描述 状态模式通过…

C++ 类和对象篇(五) 析构函数

目录 一、概念 1. 析构函数是什么&#xff1f; 2. 为什么要有析构函数&#xff1f; 3. 怎么用析构函数&#xff1f; 3.1 创建析构函数 3.2 调用析构函数 二、特性 三、由编译器生成的默认析构函数 四、对象的析构顺序 1. 局部对象 2. new出来的堆对象 3. 全局对象 一、概念 1…

Linux指令示范(1)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇

小程序支付升级:实现微信支付V3接口接入

文章目录 用户付款流程业务流程讲解接入前准备快速接入1、引入开发库2、配置参数3、初始化商户配置4、微信支付对接5、支付回调-支付通知API 相较于 v2 版本&#xff0c;v3 版本的接口文档在阅读上可能显得相对凌乱。它的组织结构可能不太清晰&#xff0c;难以快速理解整个流程…

【Go语言实战】(25) 分布式算法 MapReduce

MapReduce 写在前面 身为大数据专业的学生&#xff0c;其实大学我也多多少少接触过mapreduce&#xff0c;但是当时觉得这玩意太老了&#xff0c;觉得这和php一样会被时代淘汰。只能说当时确实太年轻了&#xff0c;没有好好珍惜那时候的学习资源… 现在回过头来看mapreduce&a…

聊聊分布式架构——RPC通信原理

目录 RPC通信的基本原理 RPC结构 手撸简陋版RPC 知识点梳理 1.Socket套接字通信机制 2.通信过程的序列化与反序列化 3.动态代理 4.反射 思维流程梳理 码起来 服务端时序图 服务端—Api与Provider模块 客户端时序图 RPC通信的基本原理 RPC&#xff08;Remote Proc…

【算法练习Day13】二叉树的层序遍历翻转二叉树对称二叉树

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 二叉树的层序遍历翻转二叉树…

安装Ubuntu提示:系统找不到指定的文件。

今天我删除Ubuntu后重新下载&#xff0c;发现报错&#xff0c;错误信息如下&#xff1a; 这是因为系统没有卸载干净而导致的。 解决办法&#xff1a; 第一步&#xff1a; ##查询当前已安装的系统 wsl.exe --list --all 执行结果&#xff1a; 第二步&#xff1a; ##注销当前…

【GSEP202303 C++】1级 长方形面积

[GSEP202303 一级] 长方形面积 题目描述 小明刚刚学习了如何计算长方形面积。他发现&#xff0c;如果一个长方形的长和宽都是整数&#xff0c;它的面积一定也是整数。现在&#xff0c;小明想知道如果给定长方形的面积&#xff0c;有多少种可能的长方形&#xff0c;满足长和宽…

BF算法详解(JAVA语言实现)

目录 BF算法的介绍 图解 JAVA语言实现 BF算法的时间复杂度 BF算法的介绍 BF算法&#xff0c;即暴力(Brute Force)算法&#xff0c;是普通的模式匹配算法&#xff0c;BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配&#xff0c;若相等&#xff0c;则继…

C++设计模式-桥接(Bridge)

目录 C设计模式-桥接&#xff08;Bridge&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-桥接&#xff08;Bridge&#xff09; 一、意图 将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。 二、适用性 你不希望在抽象和它…

[笔记] Microsoft Windows网络编程《三》网际协议

文章目录 前言3.1 IPv43.1.1 寻址3.1.1.1 单播3.1.1.2 多播(组播)3.1.1.3 广播 3.1.2 IPv4 管理协议&#xff08;ARP&#xff0c;ICMP&#xff0c;IGMP&#xff09;ARPICMPIGMP 3.1.3 Winsock 中的IPv4 寻址 3.2 IPv63.2.1 寻址3.2.1.1 单播链接——本地地址站点——本地地址&a…

ipa文件怎么把应用上架到苹果ios系统下载的App Store商城

注册为苹果开发者&#xff1a;首先&#xff0c;您需要注册为苹果开发者。前往苹果开发者网站&#xff08;https://developer.apple.com/&#xff09;&#xff0c;点击"Enroll"按钮&#xff0c;并按照相关步骤注册和付费&#xff08;开发者账号需要年度费用&#xff0…

【Java 进阶篇】使用 JDBCTemplate 执行 DQL 语句详解

在前面的文章中&#xff0c;我们已经学习了如何使用 Spring 的 JDBCTemplate 执行 DML&#xff08;Data Manipulation Language&#xff09;操作&#xff0c;包括插入、更新和删除操作。现在&#xff0c;让我们来深入了解如何使用 JDBCTemplate 执行 DQL&#xff08;Data Query…

SpringCloud Alibaba - Seata 四种分布式事务解决方案(TCC、Saga)+ 实践部署(下)

目录 一、Seata 分布式解决方案 1.1、TCC 模式 1.1.1、TCC 模式理论 对比 TCC 和 AT 模式的一致性和隔离性 TC 的工作模型 1.2.2、TCC 模式优缺点 1.2.3、TCC 模式注意事项&#xff1a;空回滚 1.2.4、TCC 模式注意事项&#xff1a;业务悬挂 1.2.5、实现 TCC 模式 案例…

MySQL数据库基础回顾与复习一

MySQL数据库 一、原理定义概念 定义 数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库 数据库是长期储存在计算机内、有组织的、可共享的数据集合 分类&#xff1a; &#xff08;1&#xff09;非结构化数据&#xff1a; 数据相对来讲没…

Spring Cloud Gateway网关中各个过滤器的作用与介绍

文章目录 1. Route To Request URL Filter&#xff08;路由过滤器&#xff09;2. Gateway Filter&#xff08;全局过滤器&#xff09;3. Pre Filter&#xff08;前置过滤器&#xff09;4. Post Filter&#xff08;后置过滤器&#xff09;5. Error Filter&#xff08;错误过滤器…

【刷题笔记10.6】LeetCode:汉明距离

LeetCode&#xff1a;汉明距离 一、题目描述 两个整数之间的汉明距离是指这两个数字对应二进制位不同的位置的数目。 给你两个整数x 和 y&#xff0c;计算并返回他们之间的汉明距离。 二、分析及代码实现 对于汉明距离问题我们其实可以将其转换为&#xff1a;计算x 和 y按…