基于 Doubao-Seedream-4.5 的单张图片生成后端接口实战

在文章:上一篇文章中,我已经写过关于 豆包大模型 Doubao-Seedream-4.5 的介绍,接下来就写一下如何接入 Doubao-Seedream-4.5 的 API 进行使用,本篇文章主要是 单图生成。

解锁视觉创作新范式:基于 Doubao-Seedream-4.5 的单张图片生成后端接口实战

随着 AIGC 技术的爆发式发展,AI 图片生成已从实验室走向商业化落地,成为内容创作、电商、游戏等领域的核心生产力工具。在众多 AI 图片生成模型中,火山引擎推出的 Doubao-Seedream-4.5 凭借极致的画质表现、丰富的风格适配、高效的生成速度,成为开发者落地单张图片生成场景的优选模型。

本文将从实战角度出发,完整讲解基于 Doubao-Seedream-4.5 的单张图片生成后端接口开发流程,包括环境准备、核心代码实现、参数优化、异常处理及生产环境适配,帮助开发者快速落地这一能力。

一、初识 Doubao-Seedream-4.5:单张图片生成的优选模型

Doubao-Seedream-4.5 是火山引擎针对单张高清图片生成场景深度优化的模型,其核心优势体现在三方面:

  1. 高清画质:原生支持 2K/4K 分辨率输出,可精准还原光线追踪、动态模糊、景深等电影级视觉细节;
  2. 风格适配:兼容超现实主义、暗黑风、国风、赛博朋克等多元创作风格,能精准解析复杂提示词;
  3. 生成效率:针对单张图片生成做了性能优化,平均生成耗时比同类型模型缩短 30% 以上。

该模型的官方调用入口为 Ark 开放平台,开发者可通过标准化的 Java SDK 快速集成,无需关注底层模型训练和部署细节。

二、开发前准备:环境与权限配置

在开始接口开发前,需完成基础环境搭建和权限配置,这是保证接口正常调用的前提。

1. 开发环境要求

  • JDK 版本:推荐 JDK 8 及以上(兼容 Ark SDK 运行环境);
  • 构建工具:Maven 3.6+ 或 Gradle 7.0+;
  • 网络环境:确保服务器能访问火山引擎 Ark 开放平台的 API 地址。

2. 依赖引入

Doubao-Seedream-4.5 的调用依赖火山引擎 Ark Runtime SDK,需在项目的pom.xml(Maven)中引入以下依赖:

java 复制代码
<?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>3.5.9-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>gzj.spring</groupId>
    <artifactId>ai</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ai</name>
    <description>ai</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <java.json>2.0.32</java.json>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <!-- 新增Redis依赖(Spring Boot整合版) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- 可选:Redis连接池(提升性能) -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>



        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${java.json}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-model</artifactId>
            <version>1.1.0-M4</version>
        </dependency>

        <!-- RxJava(流式调用) -->
        <dependency>
            <groupId>io.reactivex.rxjava3</groupId>
            <artifactId>rxjava</artifactId>
            <version>3.1.8</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/net.jthink/jaudiotagger -->
        <dependency>
            <groupId>net.jthink</groupId>
            <artifactId>jaudiotagger</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java-bundle</artifactId>
            <version>3.25.10</version>
        </dependency>

        <dependency>
            <groupId>com.volcengine</groupId>
            <artifactId>volcengine-java-sdk-ark-runtime</artifactId>
            <version>LATEST</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>

</project>

3. API Key 获取

调用 Doubao-Seedream-4.5 接口需先获取 API Key,步骤如下:

  1. 登录火山引擎控制台,进入 "方舟大模型" 模块;
  2. 选择 "应用管理",创建新应用并绑定 Doubao-Seedream-4.5 模型;
  3. 在应用详情页获取 API Key(核心凭证,需严格保密)。

具体操作可以观看这篇文章:从零到一:豆包大模型API获取与调用全指南(含多模型深度对比)-CSDN博客

三、核心接口开发:从示例到生产级实现

火山引擎提供了基础调用示例,但直接用于生产环境存在参数硬编码、无异常处理、不可复用等问题。本节先解析官方示例核心逻辑,再封装成生产级工具类。

1. 官方示例代码解析

官方示例代码如下,我们逐行拆解核心逻辑:

java 复制代码
package com.volcengine.ark.runtime;

import com.volcengine.ark.runtime.model.images.generation.GenerateImagesRequest;
import com.volcengine.ark.runtime.model.images.generation.ImagesResponse;
import com.volcengine.ark.runtime.model.images.generation.ResponseFormat;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;

import java.util.concurrent.TimeUnit;

public class ImageGenerationsExample { 
    public static void main(String[] args) {
        // 1. 从环境变量获取API Key(避免硬编码)
        String apiKey = System.getenv("ARK_API_KEY");
        // 2. 配置OkHttp连接池(控制连接数和空闲时间)
        ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
        Dispatcher dispatcher = new Dispatcher();
        // 3. 构建ArkService实例(核心服务类)
        ArkService service = ArkService.builder()
                .dispatcher(dispatcher)
                .connectionPool(connectionPool)
                .apiKey(apiKey)
                .build();

        // 4. 构建图片生成请求参数
        GenerateImagesRequest generateRequest = GenerateImagesRequest.builder()
                // 指定模型名称(Doubao-Seedream-4.5的官方标识)
                .model("doubao-seedream-4-5-251128")
                // 提示词:描述图片内容、风格、画质等
                .prompt("星际穿越,黑洞,黑洞里冲出一辆快支离破碎的复古列车,抢视觉冲击力,电影大片,末日既视感,动感,对比色,oc渲染,光线追踪,动态模糊,景深,超现实主义,深蓝,画面通过细腻的丰富的色彩层次塑造主体与场景,质感真实,暗黑风背景的光影效果营造出氛围,整体兼具艺术幻想感,夸张的广角透视效果,耀光,反射,极致的光影,强引力,吞噬")
                // 图片尺寸:支持2K/4K等(需符合模型要求)
                .size("2K")
                // 顺序生成开关:disabled表示非顺序生成(单张图片无需顺序)
                .sequentialImageGeneration("disabled")
                // 响应格式:Url表示返回图片URL,Base64表示返回Base64编码
                .responseFormat(ResponseFormat.Url)
                // 流式响应:false表示同步返回结果
                .stream(false)
                // 水印开关:true表示生成的图片带官方水印
                .watermark(true)
                .build();
        
        // 5. 发送请求并获取响应
        ImagesResponse imagesResponse = service.generateImages(generateRequest);
        // 6. 输出图片URL
        System.out.println(imagesResponse.getData().get(0).getUrl());

        // 7. 关闭线程池(释放资源)
        service.shutdownExecutor();
    }
}

核心逻辑拆解

  • ArkService 构建:作为调用模型的核心服务类,通过 Builder 模式配置请求分发器、连接池、API Key 等核心参数;
  • GenerateImagesRequest:图片生成请求的参数封装类,包含模型名称、提示词、尺寸等关键参数;
  • 请求发送与响应 :调用generateImages()发送同步请求,返回ImagesResponse,其中data字段包含图片 URL/Base64 编码;
  • 资源释放 :调用shutdownExecutor()关闭线程池,避免资源泄漏。

2. 实际后端接口

1. res和req

响应和传递类

1.1 ChatImageReq
java 复制代码
package gzj.spring.ai.req;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author DELL
 */
@Data
public class ChatImageReq {

    @ApiModelProperty(value = "图片像素大小")
    private String size;

    @ApiModelProperty(value = "是否连续生成图片")
    private String sequentialImageGeneration;

    @ApiModelProperty(value = "指定生成图像的返回格式")
    private String responseFormat;

    @ApiModelProperty(value = "图片描述")
    private String question;

}
1.1 ChatImageRes
java 复制代码
package gzj.spring.ai.res;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author DELL
 */
@Data
public class ChatImageRes {

    @ApiModelProperty(value = "图片URL")
    private String imageUrl;

}
2. 工具类 ArkServiceUtil
java 复制代码
package gzj.spring.ai.util;

import com.volcengine.ark.runtime.service.ArkService;
import nonapi.io.github.classgraph.json.JSONUtils;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * 方舟服务客户端工具类(Spring Bean,非静态注入)
 * @author DELL
 */
@Component // 标记为Spring组件,让Spring管理
public class ArkServiceUtil {
    // 1. 去掉static,Spring只能注入非静态字段
    private static String apiKey = System.getenv("ARK_API_KEY");

    private static final String baseUrl = "https://ark.cn-beijing.volces.com/api/v3";
    private static final ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
    private static final Dispatcher dispatcher = new Dispatcher();

    // 2. 非静态的ArkService实例(通过@PostConstruct初始化)
    private static ArkService arkService;

    // 3. Spring Bean初始化完成后执行(此时apiKey已注入)
    @PostConstruct
    public void initArkService() {
        if (apiKey == null || apiKey.trim().isEmpty()) {
            throw new IllegalArgumentException("doubao.api-key 未配置,请检查application.yml");
        }
        this.arkService = ArkService.builder()
                .dispatcher(dispatcher)
                .connectionPool(connectionPool)
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .build();
    }


    // 4. 提供获取实例的方法(非静态)
    public static ArkService getArkService() {
        if (arkService == null) {
            throw new RuntimeException("ArkService未初始化,请检查配置");
        }
        return arkService;
    }
}
3. 实现类Service 和 impl
3.1 ChatImageService
java 复制代码
package gzj.spring.ai.service;

import gzj.spring.ai.R.AjaxJsonResult;
import gzj.spring.ai.req.ChatImageReq;
import gzj.spring.ai.res.ChatImageRes;

/**
 * @author DELL
 */
public interface ChatImageService {

    AjaxJsonResult<ChatImageRes> getImageAnswer(ChatImageReq req);

}
3.1 ChatImageServiceImpl
java 复制代码
package gzj.spring.ai.service.impl;

import com.volcengine.ark.runtime.model.images.generation.GenerateImagesRequest;
import com.volcengine.ark.runtime.model.images.generation.ImagesResponse;
import com.volcengine.ark.runtime.service.ArkService;
import gzj.spring.ai.R.AjaxJsonResult;
import gzj.spring.ai.req.ChatImageReq;
import gzj.spring.ai.res.ChatImageRes;
import gzj.spring.ai.service.ChatImageService;
import gzj.spring.ai.util.ArkServiceUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * 图片生成服务实现类
 * 优化点:参数校验、异常处理、日志完善、容错机制、常量抽离、空指针防护
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatImageServiceImpl implements ChatImageService {

    // ========== 常量抽离:避免硬编码,便于统一维护 ==========
    /**
     * 图片生成模型标识
     */
    private static final String DOBAO_MODEL = "doubao-seedream-4-5-251128";
    /**
     * 支持的图片尺寸
     */
    private static final String[] SUPPORTED_SIZES = {"2K", "4K", "1080P"};
    /**
     * 支持的响应格式
     */
    private static final String[] SUPPORTED_RESPONSE_FORMATS = {"url", "base64"};
    /**
     * 顺序生成开关有效值
     */
    private static final String[] SUPPORTED_SEQUENTIAL_FLAGS = {"enabled", "disabled"};

    // ========== 核心业务方法 ==========

    /**
     * 生成图片(添加重试机制:网络抖动/接口临时不可用时自动重试)
     *
     * @param req 图片生成请求参数
     * @return 图片URL/Base64编码
     */
    @Override
    @Retryable(
            // 重试触发条件:接口调用异常、响应为空等
            retryFor = {Exception.class},
            // 重试次数:最多3次
            maxAttempts = 3,
            // 退避策略:每次重试间隔1秒,避免高频重试触发限流
            backoff = @Backoff(delay = 1000)
    )
    public AjaxJsonResult<ChatImageRes> getImageAnswer(ChatImageReq req) {
        long startTime = System.currentTimeMillis();
        // 生成追踪ID,便于日志排查
        String traceId = String.valueOf(System.nanoTime());

        try {
            // 1. 参数校验:前置拦截非法请求,减少无效调用
            validateRequest(req, traceId);

            // 2. 获取ArkService实例(确保单例且初始化完成)
            ArkService arkService = ArkServiceUtil.getArkService();
            if (Objects.isNull(arkService)) {
                log.error("[图片生成][{}] ArkService实例未初始化", traceId);
                return new AjaxJsonResult<>(null, "500", "图片生成失败,请稍后重试");
            }

            // 3. 构建生成请求参数(优雅空值处理)
            GenerateImagesRequest genReq = buildGenerateRequest(req);

            // 4. 调用图片生成接口,记录调用信息
            log.info("[图片生成][{}] 开始调用Doubao-Seedream-4.5接口,请求参数:{}", traceId, genReq);
            ImagesResponse response = arkService.generateImages(genReq);

            // 5. 响应结果校验与解析(空指针防护)
            String result = parseResponse(response, req, traceId);

            ChatImageRes results = new ChatImageRes();
            results.setImageUrl(result);

            // 6. 记录成功日志,返回结果
            long costTime = System.currentTimeMillis() - startTime;
            log.info("[图片生成][{}] 接口调用成功,耗时{}ms,生成图片地址:{}", traceId, costTime, result);
            return new AjaxJsonResult<>(results, "200", "图片生成成功");

        } catch (IllegalArgumentException e) {
            // 业务异常:参数非法,直接返回
            long costTime = System.currentTimeMillis() - startTime;
            log.warn("[图片生成][{}] 参数校验失败,耗时{}ms,错误信息:{}", traceId, costTime, e.getMessage());
            return new AjaxJsonResult<>(null,"400", e.getMessage());

        } catch (Exception e) {
            // 系统异常:接口调用失败,记录详细异常栈
            long costTime = System.currentTimeMillis() - startTime;
            log.error("[图片生成][{}] 接口调用异常,耗时{}ms", traceId, costTime, e);
            return new  AjaxJsonResult<>(null,"500", "图片生成失败,请稍后重试");

        }
    }

    // ========== 私有辅助方法:分层解耦 ==========

    /**
     * 请求参数校验(非空+合法性)
     */
    private void validateRequest(ChatImageReq req, String traceId) {
        // 1. 请求对象非空校验
        if (Objects.isNull(req)) {
            log.error("[图片生成][{}] 请求参数为空", traceId);
            throw new IllegalArgumentException("请求参数不能为空");
        }

        // 2. 提示词非空且长度校验(避免空提示词/超长提示词)
        String prompt = req.getQuestion();
        if (!StringUtils.hasText(prompt)) {
            throw new IllegalArgumentException("图片生成提示词不能为空");
        }
        if (prompt.length() > 2000) {
            throw new IllegalArgumentException("提示词长度不能超过2000字符");
        }

        // 3. 图片尺寸合法性校验
        String size = req.getSize();
        if (!StringUtils.hasText(size) || !isValidValue(size, SUPPORTED_SIZES)) {
            throw new IllegalArgumentException(
                    String.format("图片尺寸不合法,仅支持:%s", String.join(",", SUPPORTED_SIZES)));
        }

        // 4. 响应格式合法性校验
        String responseFormat = req.getResponseFormat();
        if (!StringUtils.hasText(responseFormat) || !isValidValue(responseFormat, SUPPORTED_RESPONSE_FORMATS)) {
            throw new IllegalArgumentException(
                    String.format("响应格式不合法,仅支持:%s", String.join(",", SUPPORTED_RESPONSE_FORMATS)));
        }

        // 5. 顺序生成开关合法性校验
        String sequentialFlag = req.getSequentialImageGeneration();
        if (!StringUtils.hasText(sequentialFlag) || !isValidValue(sequentialFlag, SUPPORTED_SEQUENTIAL_FLAGS)) {
            throw new IllegalArgumentException(
                    String.format("顺序生成开关不合法,仅支持:%s", String.join(",", SUPPORTED_SEQUENTIAL_FLAGS)));
        }
    }

    /**
     * 构建图片生成请求对象(封装参数,便于维护)
     */
    private GenerateImagesRequest buildGenerateRequest(ChatImageReq req) {
        // 根据请求格式转换为对应的枚举值
        String formatValue = req.getResponseFormat().toLowerCase();
        String enumValue = "url".equals(formatValue) ? "url" : "b64_json";

        return GenerateImagesRequest.builder()
                .model(DOBAO_MODEL)
                .prompt(req.getQuestion().trim()) // 去除提示词首尾空格
                .size(req.getSize())
                .sequentialImageGeneration(req.getSequentialImageGeneration())
                .responseFormat(enumValue) // 使用字符串格式,避免枚举问题
                .stream(false) // 单张图片生成无需流式响应,固定配置
                .watermark(true) // 生产环境建议加水印,可配置化
                .build();
    }

    /**
     * 解析响应结果(空指针防护,避免NPE)
     */
    private String parseResponse(ImagesResponse response, ChatImageReq req, String traceId) {
        // 1. 响应对象非空校验
        if (Objects.isNull(response)) {
            log.error("[图片生成][{}] 接口返回响应为空", traceId);
            throw new RuntimeException("图片生成接口返回结果为空");
        }

        // 2. 响应数据列表非空且有数据
        if (Objects.isNull(response.getData()) || response.getData().isEmpty()) {
            log.error("[图片生成][{}] 接口返回数据列表为空", traceId);
            throw new RuntimeException("图片生成失败,未返回有效图片信息");
        }

        // 3. 提取结果(URL/Base64)
        String result;
        if ("base64".equalsIgnoreCase(req.getResponseFormat())) {
            result = response.getData().get(0).getB64Json();
        } else {
            result = response.getData().get(0).getUrl();
        }

        // 4. 结果非空校验
        if (!StringUtils.hasText(result)) {
            log.error("[图片生成][{}] 接口返回图片地址为空", traceId);
            throw new RuntimeException("图片生成成功,但未返回有效地址");
        }

        return result;
    }

    /**
     * 校验值是否在支持的列表中(通用方法)
     */
    private boolean isValidValue(String value, String[] supportedValues) {
        for (String supported : supportedValues) {
            if (supported.equalsIgnoreCase(value)) {
                return true;
            }
        }
        return false;
    }
}
4.接口 Controller
java 复制代码
package gzj.spring.ai.controller;

import gzj.spring.ai.req.ChatImageReq;
import gzj.spring.ai.service.ChatImageService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author DELL
 */
@RestController
@RequestMapping("/doubaoimage")
@Api(tags = "图文生成接口 Doubao-Seedream-4.5")
public class ChatImageController {


    private final ChatImageService chatImageService;

    public ChatImageController(ChatImageService chatImageService) {
        this.chatImageService = chatImageService;
    }

    @RequestMapping("/getImageAnswer")
    public Object getImageAnswer(@RequestBody ChatImageReq req) {
        return chatImageService.getImageAnswer(req);
    }


}

3.效果演示

虽然不像吴彦祖就是了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

END

如果觉得这份修改实用、总结清晰,别忘了动动小手点个赞👍,再关注一下呀~ 后续还会分享更多 AI 接口封装、代码优化的干货技巧,一起解锁更多好用的功能,少踩坑多提效!🥰 你的支持就是我更新的最大动力,咱们下次分享再见呀~🌟

相关推荐
几颗流星几秒前
Rust 像素级绘图入门:Pixels 库核心机制解析
后端·rust
乌日尼乐7 分钟前
【Java基础整理】封装、继承、抽象、接口和多态
java·后端
heartbeat..8 分钟前
JavaWeb 入门 - HttpServletResponse 响应对象 详解
java·网络·http·web·response
zs宝来了9 分钟前
Spring Boot启动流程源码深度解析:电商订单系统面试实战
java·spring boot·面试·源码分析·电商
智航GIS10 分钟前
9.1 多线程入门
java·开发语言·python
我是谁的程序员10 分钟前
不用 Instruments 而在 Windows 环境下测试 iOS App
后端
ServBay11 分钟前
PHP 8.6 新特性预览,更简洁的语法与更严谨的类型控制
后端·php
nvd1112 分钟前
FastMCP 开发指南: 5分钟入门
人工智能·python
文心快码BaiduComate14 分钟前
用Comate开发我的第一个MCP——让Vibe Coding长长脑子
前端·后端·程序员
神奇小汤圆17 分钟前
Spring Boot + 执行管道:让业务流程清晰可控
后端