一.实验背景

当前文心一言和deepseek都开源了,二者都可以作为大模型应用开发的模型基础了,我们都可以编写springboot项目来集成deepseek和文心一言了

二.实验目标

本文基于实际操作,通过实际操作来对比文心一言和deepseek在集成到springboot项目中的异同,并通过其各自的能力来对比分析二者的异同点,为便新手开发者集成大模型开发具体应用并提供实际的开发建议.

注:鉴于模型部署非同一台硬件资源能力,故本文不对模型自身性能进行对比,只对比其集成到开发能力方便的便捷程度等

三.实验环境

3.1 开发环境规划

  基于springboot 2.6.13,jdk11,maven 3.3.3

3.2 文心一言规划

  A.版本:4.5系列。本文使用的具体版本是文心一言4.5 Turbo VL即ERNIE 4.5 Turbo VL

  B.调用方式:本文不做本地环境搭建,使用文心一言开发者账号下官方部署的模型,通过账号+sdk完成功能调用

  C.开发者平台:文心一言开发者平台

      https://console.bce.baidu.com/qianfan/modelcenter/model/buildIn/list

3.3 deepseek规划

  A.版本:同样

  B.调用方式:不做本地环境搭建,使用DeepSeek的官方网站(https://www.deepseek.com)提供的API密钥或访问令牌来调用其能力,使用okhttp调api方式

  C.开发者平台 deepseek开发者平台

3.4 实验功能规划

主要从开发流程,文档完整度,开发sdk获取便利度,开发方式,开发过程踩坑度,开发支持的功能,功能实现的表现等几方面进行评估

四.环境准备

4.1.文心一言

版本:ERNIE 4.5 Turbo VL

  创建文心一言开发者账号,并注册访问令牌,并下载sdk(sdk可以使用maven,本文以maven为例)

先注册登录

  

进入页面之后,选择文心一言大模型4.5系列,本文按照ERNIE4.5 Turbo VL为例 

选中后,进入api文档,连接:文心一言4.5 api 

 

可以看到调用api的接口文档都在这里了。

我们调用api前需要进行安全认证,或者accesskey等。

创建apikey(子用户底下进行创建)

参考:https://cloud.baidu.com/doc/qianfan-api/s/ym9chdsy5

这个访问也是sdk方式访问的凭证,所以先生成,sdk直接使用maven进行下载后配置使用即可

 选择中间下面的蓝色按钮:创建子账户,通过子账户访问文心一言4.5官方模型

按步骤操作后获取访问的key,并下载到本地。供后续项目中配置使用 。

有了访问key,还需要域名:

https://qianfan.baidubce.com

 就可以到springboot中配置sdk了

创建应用appid

操作连接:https://console.bce.baidu.com/ai-engine/speech/overview/index

文心一言的环境准备到此告一段落,下面开始准备deepseek的。 

具体文档参考地址:https://cloud.baidu.com/doc/qianfan-api/s/ym9chdsy5

4.2. deepseek

版本:DeepSeek-R1 

创建deepseek账号,并注册访问令牌,并下载sdk(sdk可以使用maven,本文以maven为例)

登录注册,地址:deepseek开发平台

需要进行验证邮箱,提供邮箱,点击验证码之后,在邮箱获取验证码后再进行校验

获取访问accesskey

 将此key拷贝,备用,这个就是项目中配置的访问key。对应的访问域名使用

获取对应的域名:https://platform.deepseek.com/ 

到此步骤,deepseek的环境准备基本结束,可以在项目里配置api域名,访问key了。

五.实验步骤

5.1.创建springboot项目

   项目使用maven进行包管理。为了方便,本文简述步骤。通过简单的页面访问

选择模块

初始项目  

对项目jdk,maven环境进行配置,本文略过

保证可正常打包

项目正常启动

 

5.2 集成文心一言 ERNIE 4.5 Turbo VL

版本:ERNIE 4.5 Turbo VL

5.2.1  pom文件增加依赖

 <!-- 文心一言 SDK --><dependency><groupId>com.baidu.aip</groupId><artifactId>java-sdk</artifactId><version>4.16.1</version> <!-- 使用最新版本 --></dependency>

5.2.2 创建类,配置文件,controller,service类,并编写代码;创建html文件用来演示操作

config文件

package globalfairy.top.wenxinyiyandeepseekdemo.demos.web.config;import com.baidu.aip.imageclassify.AipImageClassify;
import com.baidu.aip.imagesearch.AipImageSearch;
import com.baidu.aip.nlp.AipNlp;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ErnieConfig {@Value("${ernie.app-id}")private String APP_ID;@Value("${ernie.api-key}")private String API_KEY;@Value("${ernie.secret-key}")private String SECRET_KEY;@Beanpublic AipImageClassify ernieClient() {return new AipImageClassify(APP_ID,API_KEY, SECRET_KEY);}@Beanpublic AipNlp ernieNlpClient() {return new AipNlp(APP_ID,API_KEY, SECRET_KEY);}@Beanpublic AipImageSearch AipImageSearchClient() {AipImageSearch client = new AipImageSearch(APP_ID,API_KEY, SECRET_KEY);return client;}}

处理文本的核心客户端类:

@Bean
    public AipNlp ernieNlpClient() {
        return new AipNlp(APP_ID,API_KEY, SECRET_KEY);
    }

 处理图片的核心客户端类

@Bean
    public AipImageSearch AipImageSearchClient() {
        AipImageSearch client = new AipImageSearch(APP_ID,API_KEY, SECRET_KEY);
        return client;
    }

 controller

package globalfairy.top.wenxinyiyandeepseekdemo.demos.web.controller;import globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service.ErnieService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.Collections;
import java.util.Map;@RestController
@RequestMapping("/api/ernie")
public class ErnieController {@Resourceprivate ErnieService ernieServiceImpl;@PostMapping("/generate")public Map<String, String> generateText(@RequestBody Map<String, String> request) {String prompt = request.get("prompt");String result = ernieServiceImpl.generateText(prompt);return Collections.singletonMap("result", result);}
}

 serviceimpl

package globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service.impl;import com.baidu.aip.imageclassify.AipImageClassify;
import com.baidu.aip.nlp.AipNlp;
import globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service.ErnieService;
import org.json.JSONObject;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.HashMap;@Service
public class ErnieServiceImpl implements ErnieService {@Resourceprivate AipNlp client;@Overridepublic String generateText(String prompt) {try {// 文心一言文本生成调用JSONObject response = client.dnnlmCn(prompt, new HashMap<>());return response.toString(2); // 返回格式化JSON} catch (Exception e) {throw new RuntimeException("文心一言调用失败", e);}}
}

service接口: 

package globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service;public interface ErnieService {String generateText(String prompt);
}

页面: 

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>DeepSeek 聊天</title><style>body {font-family: Arial, sans-serif;margin: 20px;background-color: #f9f9f9;}h1 {text-align: center;color: #333;}.chat-container {display: flex;flex-direction: column;align-items: center;border: 1px solid #ccc;border-radius: 8px;padding: 20px;background-color: #ffffff;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);}#messages {margin-top: 20px;border: 1px solid #ccc;border-radius: 5px;padding: 10px;max-height: 400px;overflow-y: auto;width: 100%;background-color: #f1f1f1;box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);display: flex;flex-direction: column;gap: 10px; /* 使用 gap 来增加消息之间的间距 */}.message {padding: 10px;border-radius: 5px;max-width: 80%;white-space: normal; /* 允许正常换行 */word-wrap: break-word; /* 长单词换行 */overflow-wrap: break-word; /* 长单词换行 */background: #c8e6c9; /* 默认背景色 */display: inline-block; /* 使用 inline-block 以保持其流动性 */}.user-message {background-color: #e1f5fe;align-self: flex-end;text-align: right;border: 1px solid #b3e5fc;}.response-message {align-self: flex-start;text-align: left;border: 1px solid #a5d6a7;}input[type="text"] {padding: 10px;width: 70%;border-radius: 5px;border: 1px solid #ccc;margin-right: 10px;}button {padding: 10px 15px;border-radius: 5px;border: none;background-color: #007bff;color: white;cursor: pointer;transition: background-color 0.3s;}button:hover {background-color: #0056b3;}.loading {color: #ff9800;font-weight: bold;text-align: center;}</style>
</head>
<body>
<div class="chat-container"><h1>聊天流</h1><div><input type="text" id="prompt" placeholder="输入您的消息" /><button id="start">开始聊天</button></div><div id="messages"></div>
</div><script>let eventSource;document.getElementById('start').addEventListener('click', function() {const prompt = document.getElementById('prompt').value;if (!prompt) {alert("请输入消息。");return;}if (eventSource) {eventSource.close(); // 关闭之前的连接}// 清空输入框document.getElementById('prompt').value = '';// 添加加载状态const messageDiv = document.getElementById('messages');messageDiv.innerHTML += '<span class="loading">加载中...</span>';eventSource = new EventSource(`/api/events?prompt=${encodeURIComponent(prompt)}`);eventSource.onmessage = function(event) {const data = JSON.parse(event.data); // 假设返回的是 JSON 格式const messageDiv = document.getElementById('messages');const responseMessage = document.createElement('span'); // 使用 span 而非 divresponseMessage.classList.add('message', 'response-message');responseMessage.textContent = data.response;messageDiv.appendChild(responseMessage);messageDiv.scrollTop = messageDiv.scrollHeight; // 滚动到最新消息};eventSource.onerror = function(err) {// 仅在连接意外关闭时显示错误if (eventSource.readyState === EventSource.OPEN) {console.error("EventSource 连接失败:", err);const messageDiv = document.getElementById('messages');const errorMessage = document.createElement('span'); // 使用 span 而非 diverrorMessage.classList.add('message', 'error-message');errorMessage.textContent = '连接时出现错误。';messageDiv.appendChild(errorMessage);}eventSource.close(); // 关闭连接};// 监听连接关闭事件eventSource.onclose = function() {console.log("EventSource 连接已关闭");};});
</script>
</body>
</html>

 访问并测试:

https://localhost:8443/

经调试 改为文本调用之后:

package globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service.impl;import com.baidu.aip.imageclassify.AipImageClassify;
import com.baidu.aip.nlp.AipNlp;
import globalfairy.top.wenxinyiyandeepseekdemo.demos.web.service.ErnieService;
import org.json.JSONObject;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.HashMap;@Service
public class ErnieServiceImpl implements ErnieService {@Resourceprivate AipNlp client;@Overridepublic String generateText(String prompt) {try {// 文心一言文本生成调用JSONObject response = client.dnnlmCn(prompt, new HashMap<>());return response.toString(2); // 返回格式化JSON} catch (Exception e) {throw new RuntimeException("文心一言调用失败", e);}}
}

仍然报错:

可以看到提示非常清楚,针对性进行优化。

5.3 集成 deepseek 

5.3.1pom

<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.14.9</version></dependency>
5.3.2
package com.globalfairy.dsweb.demos.web.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;import java.time.Duration;@Configuration
public class AIClientConfig {// 读取配置参数@Value("${deepseek.api.url:http://localhost:11434/api/generate}")private String apiUrl;@Value("${deepseek.api.key:}")private String apiKey;@Beanpublic WebClient deepseekWebClient() {return WebClient.builder().baseUrl(apiUrl).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).defaultHeader("Authorization", "Bearer " + apiKey) // 认证头.clientConnector(new ReactorClientHttpConnector(HttpClient.create().responseTimeout(Duration.ofSeconds(60)) // 模型响应需要较长时间)).build();}
}

5.3.3

package com.globalfairy.dsweb.demos.web.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(5000);   // 5秒连接超时factory.setReadTimeout(60000);      // 60秒读取超时return new RestTemplate(factory);}
}

5.3.3

package com.globalfairy.dsweb.demos.web.service;import com.globalfairy.dsweb.demos.web.bean.CompletionRequest;
import com.globalfairy.dsweb.demos.web.bean.CompletionResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;import java.time.Duration;@Service
@Slf4j
public class DeepSeekService {private final WebClient webClient;public DeepSeekService(WebClient deepseekWebClient) {this.webClient = deepseekWebClient;}// 普通请求public CompletionResponse generateSync(String prompt) {return webClient.post().bodyValue(CompletionRequest.builder().model("deepseek").prompt(prompt).temperature(0.7).max_tokens(2000).build()).retrieve().bodyToMono(CompletionResponse.class).block();}// 流式响应处理public Flux<String> generateStream(String prompt) {return webClient.post().bodyValue(CompletionRequest.builder().model("deepseek-r1:1.5B").prompt(prompt).stream(true).max_tokens(50).build()).retrieve().bodyToFlux(String.class).timeout(Duration.ofMinutes(5)) // 长时对话场景.onErrorResume(e -> {log.error("API调用异常", e);return Flux.just("服务暂时不可用");});}
}

 5.3.5页面

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>DeepSeek 聊天</title><style>body {font-family: Arial, sans-serif;margin: 20px;background-color: #f9f9f9;}h1 {text-align: center;color: #333;}.chat-container {display: flex;flex-direction: column;align-items: center;border: 1px solid #ccc;border-radius: 8px;padding: 20px;background-color: #ffffff;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);}#messages {margin-top: 20px;border: 1px solid #ccc;border-radius: 5px;padding: 10px;max-height: 400px;overflow-y: auto;width: 100%;background-color: #f1f1f1;box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);display: flex;flex-direction: column;gap: 10px; /* 使用 gap 来增加消息之间的间距 */}.message {padding: 10px;border-radius: 5px;max-width: 80%;white-space: normal; /* 允许正常换行 */word-wrap: break-word; /* 长单词换行 */overflow-wrap: break-word; /* 长单词换行 */background: #c8e6c9; /* 默认背景色 */display: inline-block; /* 使用 inline-block 以保持其流动性 */}.user-message {background-color: #e1f5fe;align-self: flex-end;text-align: right;border: 1px solid #b3e5fc;}.response-message {align-self: flex-start;text-align: left;border: 1px solid #a5d6a7;}input[type="text"] {padding: 10px;width: 70%;border-radius: 5px;border: 1px solid #ccc;margin-right: 10px;}button {padding: 10px 15px;border-radius: 5px;border: none;background-color: #007bff;color: white;cursor: pointer;transition: background-color 0.3s;}button:hover {background-color: #0056b3;}.loading {color: #ff9800;font-weight: bold;text-align: center;}</style>
</head>
<body>
<div class="chat-container"><h1>聊天流</h1><div><input type="text" id="prompt" placeholder="输入您的消息" /><button id="start">开始聊天</button></div><div id="messages"></div>
</div><script>let eventSource;document.getElementById('start').addEventListener('click', function() {const prompt = document.getElementById('prompt').value;if (!prompt) {alert("请输入消息。");return;}if (eventSource) {eventSource.close(); // 关闭之前的连接}// 清空输入框document.getElementById('prompt').value = '';// 添加加载状态const messageDiv = document.getElementById('messages');messageDiv.innerHTML += '<span class="loading">加载中...</span>';eventSource = new EventSource(`/api/events?prompt=${encodeURIComponent(prompt)}`);eventSource.onmessage = function(event) {const data = JSON.parse(event.data); // 假设返回的是 JSON 格式const messageDiv = document.getElementById('messages');const responseMessage = document.createElement('span'); // 使用 span 而非 divresponseMessage.classList.add('message', 'response-message');responseMessage.textContent = data.response;messageDiv.appendChild(responseMessage);messageDiv.scrollTop = messageDiv.scrollHeight; // 滚动到最新消息};eventSource.onerror = function(err) {// 仅在连接意外关闭时显示错误if (eventSource.readyState === EventSource.OPEN) {console.error("EventSource 连接失败:", err);const messageDiv = document.getElementById('messages');const errorMessage = document.createElement('span'); // 使用 span 而非 diverrorMessage.classList.add('message', 'error-message');errorMessage.textContent = '连接时出现错误。';messageDiv.appendChild(errorMessage);}eventSource.close(); // 关闭连接};// 监听连接关闭事件eventSource.onclose = function() {console.log("EventSource 连接已关闭");};});
</script>
</body>
</html>

六.结论

两者在开发流程,文档完整度,开发sdk获取便利度,开发方式上基本上区别不大。

不过文心一言开发过程在验权上要复杂不少,如果能更简洁就更好了 

起来轻松玩转文心大模型吧一文心大模型免费下载地址:https://ai.gitcode.com/theme/1939325484087291906

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

核磁共振数据T2几何均值计算

1、T₂ 几何均值公式如下&#xff1a;2、核磁T2几何均值计算代码 CSV 文件文件格式&#xff1a; 每一行是一个样点&#xff08;样品深度&#xff09;&#xff0c;列为&#xff1a;第一列是“深度”或其他&#xff1b;第二列及以后&#xff08;如 TASPEC0 ~ TASPEC199&#xff0…

微服务架构技巧篇——接口类设计技巧

目录 一、微服务架构的特点 二、微服务接口类设计技巧 2.1、BFF(Backend For Frontend) 2.1.1、 服务分布式带来的第一个挑战导致的几个典型问题 2.1.2、什么是 BFF 2.1.3、BFF 应用场景 2.1.4、BFF 落地经验 2.1.4.1、前端负责 BFF 开发优缺点 2.1.4.2、后端负责 BFF 开发优…

C++游戏开发(2)

直接上代码 1.首先是头文件编写 #include <iostream> #include <graphics.h> #include <string> 2,添加画布 长1280&#xff0c;宽720 initgraph(1280, 720); 3.添加主循环 bool running true; while(runing) { } 4.定义结构体变量msg ExMessge msg; 5.开…

Unity开发2D类银河恶魔城游戏学习笔记目录

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 玩家状态机 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现…

智慧社区项目开发(三)——基于 Spring Boot 实现动态路由加载:从数据库到前端菜单的完整方案

在后台管理系统中&#xff0c;不同用户角色往往拥有不同的操作权限&#xff0c;对应的菜单展示也需动态调整。动态路由加载正是解决这一问题的核心方案 —— 根据登录用户的权限&#xff0c;从数据库查询其可访问的菜单&#xff0c;封装成前端所需的路由结构并返回。本文将详细…

Python在自动化与运维领域的核心角色:工具化、平台化与智能化

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在 IT 系统日益复杂、运维任务持续增长的今天&#xff0c;自动化已成为企业基础设施管理的关键方向。Python 以其简洁的语法、强大…

RAG实战指南 Day 28:RAG系统缓存与性能优化

【RAG实战指南 Day 28】RAG系统缓存与性能优化 开篇 欢迎来到"RAG实战指南"系列的第28天&#xff01;今天我们将深入探讨RAG系统的缓存机制与性能优化策略。在实际生产环境中&#xff0c;RAG系统往往面临高并发、低延迟的需求&#xff0c;而合理的缓存设计和性能优…

swanlab实验优雅起名

init中的参数的作用project&#xff1a;整个实验的名字&#xff1b;experiment_name&#xff1a;在这个实验中&#xff0c;你的名字是什么&#xff1b; 比如说现在我们要进行对比实验&#xff0c;PEAN和Triflownet分别是对比方法的名字&#xff0c;这样的好处是&#xff0c;她们…

Nestjs框架: NestJS 核心机制解析 —— DI(依赖注入)容器与模块化工作原理

理解 NestJS 的 DI 管理机制 我们想要了解依赖注入&#xff08;Dependency Injection, DI&#xff09;最核心的工作逻辑NestJS 拥有自己的一套 DI 管理系统&#xff0c;它通过一个称为 DI 容器 的机制&#xff0c;来统一管理应用中所有类&#xff08;class&#xff09;的依赖关…

日语学习-日语知识点小记-构建基础-JLPT-N3阶段(12):文法+单词

日语学习-日语知识点小记-构建基础-JLPT-N3阶段&#xff08;12&#xff09;&#xff1a;文法单词 1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰2、知识点&#xff11;ーたぶん 多分&#xff12;ーV&#xff08;て&#xff09;いく ・ V&…

【赵渝强老师】OceanBase租户的资源管理

OceanBase数据库是多租户的数据库系统&#xff0c;一个集群内可包含多个相互独立的租户&#xff0c;每个租户提供独立的数据库服务。在OceanBase数据库中&#xff0c;使用资源配置&#xff08;Unit Config&#xff09;、资源单元&#xff08;Unit&#xff09;和资源池&#xff…

8K、AI、低空智联,H.266能否撑起下一代视频通路?

一、&#x1f4c8; 爆发式增长的 AI 与视频数据&#xff1a;智能时代的“数据燃料革命” 随着生成式 AI、大模型推理、多模态理解等技术的迅猛发展&#xff0c;视频数据从“记录工具”转变为“感知基础设施”&#xff0c;其在现代智能系统中的战略地位日益凸显。 1️⃣ 视频数…

保姆级别IDEA关联数据库方式、在IDEA中进行数据库的可视化操作(包含图解过程)

本文以mysql为例&#xff0c;学会了Mysql&#xff0c;其它的数据库也是类似的模版~如果您觉得这边文章对你有帮助&#xff0c;可以收藏防止找不到~如果您觉得这篇文章不错&#xff0c;也感谢您的点赞对我创作的支持1.1 打开侧边栏的Database2.2 选择要连接的数据库&#xff08;…

33.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--财务服务--记账

这篇文章我们一起把记账模块从单体应用迁移到微服务架构中。记账模块的功能想必大家都已经了解了&#xff0c;主要是记录用户的收入和支出&#xff0c;以及对这些记录的删除修改和查询等操作。具体的功能可以参考单体应用专栏&#xff0c;在这里就不多讲了。我们现在一起开始迁…

Cursor结合Playwright MCP Server支持自动化

Cursor结合Playwright MCP Server支持自动化 今天分享一下 playwright MCP Server&#xff0c;其提供了浏览器自动化能力&#xff0c;使大型语言模型能够在真实的浏览器环境中与网页交互&#xff0c; 也可以执行任务&#xff0c;例如运行JavaScript、截屏和导航网页元素&…

Python 求梯形面积的程序(Program to find area of a Trapezoid)

梯形的定义&#xff1a; 梯形是凸四边形&#xff0c;至少有一对边平行。平行边称为梯形的底边&#xff0c;另外两条不平行的边称为梯形的腿。梯形也可以有两对底边。在上图中&#xff0c;CD || AB&#xff0c;它们构成底边&#xff0c;而另外两条边&#xff0c;即AD和BC&#…

C语言 —— 指针(4)

动态内存分配动态内存需要手动申请&#xff0c;手动归还&#xff0c;其内存是开辟在堆区。申请的函数为&#xff1a;void *malloc(size_t size) &#xff08;需包含头文件#include<stdlib.h>&#xff09;size&#xff1a;要分配的内存大小&#xff0c;以字节为单位。申请…

常用算法思想及模板

今天继续整理一些关于算法竞赛中C适用的一些模板以及思想。 保留x位小数 保留x位小数在C语言中可以使用printf中的"%.xf"来实现&#xff0c;但是很多C选手由于关闭了同步流&#xff0c;害怕cin、cout与scanf、printf混用容易出错&#xff0c;所以就给大家介绍一个强…

GitLab 仓库 — 常用的 git 命令

在公司的 gitlab 公共仓库中写代码做项目时&#xff0c;主要涉及以下常用 git 命令&#xff1a;一、单个命令讲解1. 拉取代码&#xff08;1&#xff09;git clone [仓库 URL]‌克隆远程仓库到本地&#xff08;需确保 URL 正确&#xff09; ‌&#xff08;‌2&#xff09;git pu…

【28】C# WinForm入门到精通 ——多文档窗体MDI【属性、方法、实例、源码】【多窗口重叠、水平平铺、垂直平铺、窗体传值】

文章目录1多文档窗体MDI2 基本设置3 实例&#xff1a;多窗口重叠、水平平铺、垂直平铺3.1 主窗口属性设置3.2 主窗口3.3 主窗口窗口添加MenuStrip菜单3.4 添加处理函数3.5 测试效果4 利用窗体参数定义进行传值4.1 在Form2、Form3添加相关控件4.2 Form3 定义函数public Form3(st…