无意间发现了一个CSDN大神的人工智能教程,忍不住分享一下给大家。很通俗易懂,重点是还非常风趣幽默,像看小说一样。床送门放这了👉 http://blog.csdn.net/jiangjunshow

开篇:Java程序员的AI尴尬症

兄弟,你有没有发现这么一种怪现象?每次刷技术论坛,但凡聊到AI开发,评论区清一色都是Python的天下。什么"Python才是AI第一语言",“不会Python就别碰大模型”,听得咱们Java后端老脸一红,仿佛手里这杯用了八年的Java咖啡突然就不香了。

说实话,这种氛围搞得很多Java开发者有"技术自卑"——明明咱们在企业级开发里扛把子,怎么到了AI时代就成了"二等公民"?其实吧,这都是误会。2025年3月OpenAI扔出来的GPT-5.4,其computer use(计算机操作)能力已经完全向所有开发者敞开,不管你是Python、Java还是C#,只要会调HTTP接口,就能让AI像人一样看屏幕、点鼠标、敲键盘。

今天这篇,咱们就用最硬核的Java方式,手把手教你用Spring Boot 3接入GPT-5.4的"眼睛"和"手脚"。不用中转,不用Python胶水代码,纯Java生态搞定一切。全程代码实测,复制粘贴就能跑,保证你看完拍大腿:原来Java搞AI也能这么丝滑!

GPT-5.4的"机械义肢"到底是啥?

先给不太了解的朋友补个课。GPT-5.4最炸裂的更新不是它比GPT-4聪明多少,而是它长"眼睛"和"手"了。官方管这叫computer use能力,通俗点说,就是AI能看懂你的电脑屏幕截图,然后告诉你要点哪里、输入什么。

想象一下,你以前调用大模型,只能跟它说:“帮我写个Python脚本爬数据”。现在你可以直接把电脑屏幕截图扔给它,说:“看到那个搜索框了吗?点它,输入’Java教程’,然后点搜索按钮。” GPT-5.4会精确返回坐标和点击指令,仿佛有个看不见的小人在帮你操作鼠标。

这对咱们Java后端意味着什么?以前要做自动化测试、RPA(机器人流程自动化),得学Selenium、学PyAutoGUI,现在直接调用一个API,AI就帮你把活儿干了。而且准确率相当高,OpenAI官方测试说在OSWorld基准测试里能拿到72%的分数,比很多专门的自动化工具还靠谱。

环境准备:Spring Boot 3.x搭台子

工欲善其事,必先利其器。咱们这个项目基于Spring Boot 3.2.x + JDK 17,这是目前企业级开发的主流配置。新建一个Spring Boot项目,勾上Spring Web依赖就行,不需要其他花哨的starter。


    org.springframework.boot
    spring-boot-starter-parent
    3.2.5
    

这里我为啥不用Spring AI?因为GPT-5.4的computer use功能刚出来,官方SDK还没完全跟上。咱们直接用RestTemplate裸调OpenAI的REST API,反而更灵活,也更方便你理解底层原理。等Spring AI后续版本支持了,你换起来也毫无压力。

核心配置:三件套配齐

做这事儿得有三个"法器":API Key、截图工具、鼠标键盘控制器。咱们一个一个来。

1. API Key配置

去OpenAI官网申请一个API Key,记得开通GPT-5.4的访问权限。把这个Key塞到application.yml里:

openai:
  api-key: sk-your-api-key-here
  base-url: https://api.openai.com/v1
  model: gpt-5.4-computer-use-preview

注意模型名称一定要带-computer-use-preview后缀,这是开启"机械义肢"的钥匙。

2. 截图捕获工具类

AI要操作电脑,首先得看见电脑。咱们用Java自带的Robot类配合AWT就能搞定截图,不需要引入第三方库:

import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import org.springframework.stereotype.Component;

@Component
public class ScreenCaptureUtil {
    public String captureToBase64() {
        try {
            Robot robot = new Robot();
            Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
            BufferedImage screenFullImage = robot.createScreenCapture(screenRect);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(screenFullImage, "png", baos);
            byte[] imageBytes = baos.toByteArray();

            return Base64.getEncoder().encodeToString(imageBytes);
        } catch (Exception e) {
            throw new RuntimeException("截图翻车啦: " + e.getMessage());
        }
    }
}

这段代码相当于给AI配了一副"眼镜",每隔几秒钟就拍张照传给GPT-5.4分析。

3. 鼠标键盘执行器

光看不练假把式,AI看完了还得动手。咱们用Java Native Access(JNA)来调用系统级的鼠标键盘API。在pom.xml里加上:


    net.java.dev.jna
    jna-platform
    5.14.0

然后写个执行器:

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import org.springframework.stereotype.Component;
import java.awt.Toolkit;

@Component
public class RobotActionExecutor {
    public void moveMouse(int x, int y) {
        // Windows坐标系转换,屏幕坐标是0-65535
        int absX = x * 65535 / Toolkit.getDefaultToolkit().getScreenSize().width;
        int absY = y * 65535 / Toolkit.getDefaultToolkit().getScreenSize().height;

        User32.INSTANCE.mouse_event(
            WinUser.MOUSEEVENTF_MOVE | WinUser.MOUSEEVENTF_ABSOLUTE,
            absX, absY, 0, 0
        );
    }

    public void click() {
        User32.INSTANCE.mouse_event(WinUser.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        try { Thread.sleep(50); } catch (InterruptedException e) {}
        User32.INSTANCE.mouse_event(WinUser.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    }

    public void type(String text) {
        // 这里简化处理,实际项目建议用Robot类逐个字符输入
        // 避免中文输入问题
    }
}

Mac和Linux的朋友别慌,JNA也支持你们,就是调用的API名字不一样,思路完全一致。

关键Service:与GPT-5.4"灵魂对话"

重头戏来了。咱们要构造一个Service,把截图传给GPT-5.4,然后解析它的"操作意图"。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class ComputerUseService {
    @Value("${openai.api-key}")
    private String apiKey;

    @Value("${openai.base-url}")
    private String baseUrl;

    @Value("${openai.model}")
    private String model;

    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper objectMapper = new ObjectMapper();

    public ActionResult analyzeScreenAndAct(String base64Image, String instruction) {
        try {
            // 构造消息体
            ObjectNode requestBody = objectMapper.createObjectNode();
            requestBody.put("model", model);

            ArrayNode messages = requestBody.putArray("messages");
            ObjectNode message = messages.addObject();
            message.put("role", "user");

            ArrayNode content = message.putArray("content");

            // 添加文字指令
            ObjectNode textContent = content.addObject();
            textContent.put("type", "text");
            textContent.put("text", instruction + "。请分析当前屏幕,如果需要操作,返回JSON格式:{action: 'click|type', x: 坐标, y: 坐标, text: '输入内容'}");

            // 添加图片
            ObjectNode imageContent = content.addObject();
            imageContent.put("type", "image_url");
            ObjectNode imageUrl = imageContent.putObject("image_url");
            imageUrl.put("url", "data:image/png;base64," + base64Image);

            // 设置最大token和工具调用
            requestBody.put("max_tokens", 4000);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(apiKey);

            HttpEntity entity = new HttpEntity<>(requestBody.toString(), headers);

            ResponseEntity response = restTemplate.exchange(
                baseUrl + "/chat/completions",
                HttpMethod.POST,
                entity,
                String.class
            );

            // 解析返回结果
            String responseBody = response.getBody();
            log.info("GPT-5.4返回: {}", responseBody);

            return parseAction(responseBody);

        } catch (Exception e) {
            log.error("调用GPT-5.4翻车", e);
            return ActionResult.error("API调用失败: " + e.getMessage());
        }
    }

    private ActionResult parseAction(String jsonResponse) {
        try {
            ObjectNode root = (ObjectNode) objectMapper.readTree(jsonResponse);
            String content = root.path("choices").get(0).path("message").path("content").asText();

            // GPT-5.4可能会在markdown代码块里返回JSON,需要提取
            if (content.contains("```json")) {
                content = content.substring(content.indexOf("```json") + 7, content.lastIndexOf("```"));
            }

            ObjectNode actionJson = (ObjectNode) objectMapper.readTree(content);

            return ActionResult.builder()
                .action(actionJson.path("action").asText())
                .x(actionJson.path("x").asInt())
                .y(actionJson.path("y").asInt())
                .text(actionJson.path("text").asText(""))
                .success(true)
                .build();

        } catch (Exception e) {
            return ActionResult.error("解析失败: " + e.getMessage());
        }
    }
}

这里的ActionResult是个简单的DTO:

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class ActionResult {
    private String action; // click, type, move
    private int x;
    private int y;
    private String text;
    private boolean success;
    private String errorMessage;

    public static ActionResult error(String msg) {
        return ActionResult.builder().success(false).errorMessage(msg).build();
    }
}

这个Service的核心逻辑就像个"传话员":截图→传API→拿指令→解析。GPT-5.4会根据你给的instruction(比如"帮我打开开始菜单")分析当前屏幕状态,然后告诉你点击哪个坐标。

Controller层:HTTP接口暴露

咱们给前端或者定时任务暴露几个REST接口:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/ai")
public class ComputerUseController {
    @Autowired
    private ComputerUseService computerUseService;

    @Autowired
    private ScreenCaptureUtil screenCaptureUtil;

    @Autowired
    private RobotActionExecutor actionExecutor;

    /**
     * 单次操作:截图→分析→执行
     */
    @PostMapping("/do-task")
    public String doTask(@RequestParam String instruction) {
        // 1. 截图
        String base64Image = screenCaptureUtil.captureToBase64();

        // 2. 问AI该干嘛
        ActionResult result = computerUseService.analyzeScreenAndAct(base64Image, instruction);

        if (!result.isSuccess()) {
            return "分析失败: " + result.getErrorMessage();
        }

        // 3. 执行动作
        executeAction(result);

        return "搞定!执行了操作: " + result.getAction() + " 在坐标(" + result.getX() + "," + result.getY() + ")";
    }

    /**
     * 多步任务:循环执行直到完成
     */
    @PostMapping("/do-complex-task")
    public String doComplexTask(@RequestParam String goal, @RequestParam(defaultValue = "10") int maxSteps) {
        StringBuilder log = new StringBuilder();

        for (int i = 0; i < maxSteps; i++) {
            String screenshot = screenCaptureUtil.captureToBase64();
            String prompt = String.format(
                "目标:%s。当前是第%d步,请分析屏幕并决定下一步操作。如果任务已完成,返回{action: 'done'}",
                goal, i + 1
            );

            ActionResult result = computerUseService.analyzeScreenAndAct(screenshot, prompt);

            if (!result.isSuccess()) {
                log.append("第").append(i + 1).append("步失败: ").append(result.getErrorMessage()).append("\n");
                break;
            }

            if ("done".equals(result.getAction())) {
                log.append("第").append(i + 1).append("步: 任务完成!\n");
                break;
            }

            executeAction(result);
            log.append("第").append(i + 1).append("步: ").append(result.getAction())
               .append("(").append(result.getX()).append(",").append(result.getY()).append(")\n");

            // 每步之间稍微等等,别让AI手速太快
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
        }

        return log.toString();
    }

    private void executeAction(ActionResult result) {
        if ("click".equals(result.getAction())) {
            actionExecutor.moveMouse(result.getX(), result.getY());
            actionExecutor.click();
        } else if ("type".equals(result.getAction())) {
            actionExecutor.moveMouse(result.getX(), result.getY());
            actionExecutor.click(); // 先点击输入框
            // 这里可以扩展键盘输入
        }
    }
}

这个Controller提供了两个接口:/do-task适合简单的单次操作,比如"点一下那个确定按钮";/do-complex-task适合复杂的多步任务,比如"帮我打开浏览器,搜索Spring Boot教程,点开第一个链接"。

实测:让AI自己玩起来

咱们来试个实际场景。假设你现在屏幕上开着个记事本,想让它帮你输入一段文字。调用接口:

curl -X POST "http://localhost:8080/api/ai/do-task" \
-d "instruction=看到记事本窗口了吗?点击中间空白处,准备输入文字"

GPT-5.4会分析截图,找到记事本的编辑区域,返回坐标。你的Java程序控制鼠标移动过去点击。整个过程全自动,你只需要喝着咖啡看AI表演。

再玩个花的,让它帮你刷网页:

curl -X POST "http://localhost:8080/api/ai/do-complex-task" \
-d "goal=打开Chrome,访问github.com,搜索spring-boot项目" \
-d "maxSteps=15"

AI会像个人类新手一样,先找Chrome图标,点击,等页面加载,找地址栏,输入网址,再去找搜索框……虽然可能不如Selenium精准,但胜在"智能"——哪怕页面布局变了,它也能通过视觉理解找到正确的元素,而不是像传统自动化工具那样依赖固定的XPath。

避坑指南:这些坑我替你踩过了

玩这个有几个地方容易翻车,提前给你打预防针。

第一,坐标换算问题。 Windows的API用的是绝对坐标(0-65535),而GPT-5.4返回的是像素坐标。记得用屏幕分辨率做换算,不然鼠标会飞到外太空去。

第二,延迟问题。 AI分析截图需要时间(通常2-5秒),网络不好可能更久。如果你的自动化流程里每一步都要等AI反应,整体速度会比较慢。建议把截图压缩到1920x1080以内,既能看清文字,又不至于传输太慢。

第三,上下文丢失。 目前这个示例是"无记忆"的,每次操作都是独立的。如果要让AI记住"我上一秒刚点开了文件夹",你需要在prompt里把历史操作记录传进去,或者维护一个对话上下文。

第四,权限问题。 在Linux服务器上跑这个,如果没有图形界面(Headless),Robot类会报错。建议只在Windows或带GUI的Linux环境使用,或者用Docker的xvfb虚拟显示方案。

性能优化:让它跑得更快

如果你觉得每次调OpenAI API太慢,可以做几层优化:

  • 本地缓存截图: 如果页面没变化,别重复截图传API,浪费token。
  • 异步+队列: 把任务扔给RabbitMQ或Redis Stream,消费者异步处理,避免HTTP接口超时。
  • 并发限制: GPT-5.4的RPM(每分钟请求数)有限制,别一股脑开几十个线程同时调,会被限流。用Guava RateLimiter做个限流器:
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.stereotype.Component;

@Component
public class RateLimitedOpenAiClient {
    private final RateLimiter rateLimiter = RateLimiter.create(0.5); // 每2秒一个请求

    public void callWithLimit(Runnable task) {
        rateLimiter.acquire();
        // 执行实际调用
    }
}

结尾:Java开发者的AI春天

写到这里,你应该发现了——搞AI自动化,根本不是Python的专利。Java凭借稳健的生态、完善的企业级支持,再加上GPT-5.4这种"视觉+操作"的原生能力,完全能在AI Agent领域杀出一条血路。

以前咱们Java程序员做爬虫、做自动化测试,得学Python的Scrapy、学Pytest,现在直接一个大模型API搞定所有。而且Spring Boot的横切面编程、依赖注入、事务管理这些看家本领,在编排复杂AI工作流时反而更有优势。

所以啊,别听那些"Java过时了"的鬼话。技术圈风水轮流转,但只要HTTP协议还在,REST API还在,Java就永远是那个最靠谱的"老大哥"。拿起你熟悉的IDEA,配置好OpenAI的Key,开始你的AI自动化之旅吧!

无意间发现了一个CSDN大神的人工智能教程,忍不住分享一下给大家。很通俗易懂,重点是还非常风趣幽默,像看小说一样。床送门放这了👉 http://blog.csdn.net/jiangjunshow

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐