支持私有化部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


java对接Dify的工作流API(实战篇)

发布日期:2025-04-26 23:39:51 浏览次数: 1633 作者:小研说技术
推荐语

深入探索Java与Dify工作流API的集成实践,掌握企业级AI应用的关键技术。

核心内容:
1. 基于Dify工作流的Java对接流程与实战案例
2. 接口测试与工作流发布的关键步骤
3. Java代码对接Dify工作流的详细指南

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家
前面的博客有讲到dify工作流调接口查询数据以及调用Dify的聊天助手API,此博客需具备以上基础。
背景:本人就职于某IT企业,当前公司正推进企业级AI应用的建设。基于微服务架构的业务复杂度较高,在技术选型中我们采用Dify工作流来实现核心需求。该方案的实现流程与此博客大体一致,可满足企业级应用的技术要求。
步骤一:启动Dify
目前版本:1.2.0
步骤二:搭建工作流
搭建步骤已省略,核心内容在下方。Dify的工作流具备很多组件,大家可以根据需求灵活使用,此次演示为Demo,真实场景比这个要复杂哈。
步骤三:接口测试
由于在工作流中使用http请求保存数据,需要使用postman验证该接口是否可用。
还需要去数据库查看一下
数据保存成功,进入下一环节
步骤四:发布工作流
在发布前,需要运行或调试工作流是否正常。遇到问题不要慌,解决问题就是,大家可以加入技术群或个人微信交流~
步骤五:对接工作流
有些人就会问,Dify不是都实现了吗,为啥还要编写java代码去对接了,前端不是能对接python接口吗?
回答:基于业务需求,没错,就这么简单!
自己也不确定,特意借助DeepSeek查了下,支持国产!
真是良心,回答的非常详细。
WorkFlowController
@RestController@RequestMapping("/workflow")public class WorkFlowController {    @Autowired    private WorkFlowService workFlowService;
    /**     * 上传文件     *     * @param file     * @return     * @throws IOException     */    @PostMapping("/upload")    public WorkFlowFileVo upload(@RequestParam("file") MultipartFile file) throws IOException {        return workFlowService.upload(file);    }
    /**     * 执行工作流     *     * @param workFlowRunDto     * @return     */    @PostMapping("/runWorkFlow")    public SseEmitter runWorkFlow(@RequestBody WorkFlowRunDto workFlowRunDto) {        return workFlowService.runWorkFlow(workFlowRunDto);    }
    /**     * 获取工作流执行情况     *     * @param workflowRunId     * @return     */    @GetMapping("/workFlowInfo")    public WorkFlowExeVo workFlowRunInfo(String workflowRunId) {        return workFlowService.workFlowRunInfo(workflowRunId);    }
}
WorkFlowService
public interface WorkFlowService {    /**     * 上传文件     *     * @param file     * @return     */    public WorkFlowFileVo upload(@RequestParam("file") MultipartFile file) throws IOException;
    /**     * 执行工作流     *     * @param workFlowRunDto     * @return     */    public SseEmitter runWorkFlow(@RequestBody WorkFlowRunDto workFlowRunDto);
    /**     * 获取工作流执行情况     *     * @param workflowRunId     * @return     */    public WorkFlowExeVo workFlowRunInfo(String workflowRunId);
}
WorkFlowServiceImpl
     /**     * 上传文件     *     * @param file     * @return     * @throws IOException     */    @Override    public WorkFlowFileVo upload(MultipartFile file) throws IOException {        // 设置请求头        HttpHeaders headers = new HttpHeaders();        headers.setContentType(MediaType.MULTIPART_FORM_DATA);        headers.set("Authorization", difyConfig.getSaveDataAuthorization());        // 创建请求实体        MultiValueMap<StringObject> body = new LinkedMultiValueMap<>();        // 处理文件内容        body.add("file"new ByteArrayResource(file.getBytes()) {            @Override            public String getFilename() {                // 返回原始文件名                return file.getOriginalFilename();            }        });
        HttpEntity<MultiValueMap<StringObject>> requestEntity = new HttpEntity<>(body, headers);        String uploadUrl = difyConfig.getSaveDataUrl() + "/files/upload";
        // 发送请求        ResponseEntity<String> response = restTemplate.exchange(uploadUrl, HttpMethod.POST, requestEntity, String.class);        log.info("上传文件的response: {}", response);
        WorkFlowFileVo workFlowFileVo = JSON.parseObject(response.getBody(), WorkFlowFileVo.class);        // 构建工作流请求体        WorkFlowRunDto workFlowRunDto = buildWorkFlowRunDto(workFlowFileVo.getId());        // 执行工作流        this.runWorkFlow(workFlowRunDto);    }
     /**     * 执行工作流     *     * @param workFlowRunDto     * @return     */    @Override    public SseEmitter runWorkFlow(WorkFlowRunDto workFlowRunDto) {        // 设置超时时间 300s        SseEmitter emitter = new SseEmitter(300_000L);
        // 使用异步线程处理流式响应        ExecutorService executor = Executors.newSingleThreadExecutor();        executor.execute(() -> {            try {                String runUrl = difyConfig.getSaveDataUrl() + "/workflows/run";                log.info("runUrl: {}", runUrl);
                // 创建请求头                HttpHeaders headers = new HttpHeaders();                headers.set("Authorization", difyConfig.getSaveDataAuthorization());                headers.setContentType(MediaType.APPLICATION_JSON);                // 设置接收流                headers.set(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE);                HttpEntity<WorkFlowRunDto> requestEntity = new HttpEntity<>(workFlowRunDto, headers);
                // 使用restTemplate的execute方法处理流式响应                restTemplate.execute(                        runUrl,                        HttpMethod.POST,                        request -> {                            // 关键修复:手动设置Content-Type和请求头                            request.getHeaders().setContentType(MediaType.APPLICATION_JSON);                            request.getHeaders().addAll(requestEntity.getHeaders());
                            // 写入请求体                            if (requestEntity.getBody() != null) {                                new ObjectMapper().writeValue(request.getBody(), requestEntity.getBody());                            }                        },                        response -> {                            try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.getBody()))) {                                // 标记是否已处理workflow_run_id                                boolean workflowRunIdProcessed = false;                                String line;                                while ((line = reader.readLine()) != null) {                                    if (line.startsWith("event: ping")) {                                        // 跳过心跳事件                                        continue;                                    }                                    emitter.send(line);                                    log.info("line: {}", line);                                    if (!workflowRunIdProcessed) {                                        try {                                            workflowRunIdProcessed = processLine(line);                                        } catch (Exception e) {                                            log.error("记录id出现异常: {}", e.getMessage());                                            emitter.completeWithError(e);                                        }                                    }                                }                            }                            emitter.complete();                            return null;                        }                );
            } catch (Exception e) {                log.error("处理过程中发生错误: {}", e.getMessage());                emitter.completeWithError(e);            } finally {                log.info("流式输出结束...");            }        });        // 关闭线程池        executor.shutdown();        log.info("流式输出完成...");        return emitter;    }
    @Override    public WorkFlowExeVo workFlowRunInfo(String workflowRunId) {        log.info("获取到的工作流id: {}", workflowRunId);
        // 设置请求头        HttpHeaders headers = new HttpHeaders();        headers.set("Authorization", difyConfig.getWorkFlowAuthorization());
        String workFlowInfoUrl = difyConfig.getWorkFlowUrl() + "/workflows/run/" + workflowRunId;
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        // 发送请求        ResponseEntity<String> response = restTemplate.exchange(workFlowInfoUrl, HttpMethod.GET, requestEntity, String.class);        log.info("response: {}", response);
        return JSON.parseObject(response.getBody(), WorkFlowExeVo.class);    }
步骤六:测试
有小伙伴就纳闷了,公司不是有测试吗,怎么还要自己测啊?
回答:招你进来不是闲着玩的
个人:都是牛马
测试文件上传,由于Demo版代码执行文件与工作流执行在一块,如果基于业务需求,中间会进行其他操作。
控制台信息:
建议大家在开发过程中规范记录日志,以便在系统出现异常时能快速定位问题根源。日志的详细程度可根据实际需求和开发经验灵活调整。
基于上述流程方案,我们已顺利完成了企业级应用需求的开发。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询