Java结合大模型文生图实战
导读:随着AIGC技术的快速发展,文生图已成为软件开发中的热门功能。本文将带你从零开始,使用Java结合OpenAI的DALL-E模型,构建一个完整的文生图系统。
一、技术背景与选型
2023年全球AIGC市场规模达到150亿美元,预计2025年将突破500亿美元。Java作为企业级开发的主力语言,与AI大模型的结合正成为开发者关注的焦点。
为什么选择OpenAI DALL-E?
✅ 技术成熟:API稳定,文档完善
✅ 效果优质:生成图片质量高
✅ 集成便捷:提供官方Java SDK
✅ 商业友好:清晰的定价模型
二、系统架构设计

六层架构体系:
1️⃣ 表现层:React/Vue前端
2️⃣ API网关层:认证授权、流量管理
3️⃣ 应用服务层:业务逻辑编排
4️⃣ 业务逻辑层:核心算法处理
5️⃣ 数据层:MySQL/Redis/MongoDB
6️⃣ AI服务层:OpenAI DALL-E调用
三、核心代码实现
核心依赖配置
xml
<dependencies>
<!-- Spring Boot Webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- OpenAI Client -->
<dependency>
<groupId>com.theokanning.openai-gpt3-java</groupId>
<artifactId>service</artifactId>
<version>0.17.0</version>
</dependency>
<!-- Caffeine缓存 -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
</dependencies>
核心类图

五个核心类:
🔹 ImageController:处理HTTP请求
🔹 OpenAiImageService:调用OpenAI API
🔹 ImageRequest:请求参数封装
🔹 ImageResponse:响应结果封装
🔹 CacheService:缓存管理
核心代码示例
ImageRequest - 请求模型
arduino
package com.example.textToImage.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.*;
/**
* 文生图请求参数
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ImageRequest {
/**
* 提示词
*/
@NotBlank(message = "提示词不能为空")
@Size(max = 1000, message = "提示词长度不能超过1000字符")
private String prompt;
/**
* 图片尺寸
*/
@NotNull(message = "图片尺寸不能为空")
private ImageSize size = ImageSize.S1024X1024;
/**
* 图片数量
*/
@Min(value = 1, message = "图片数量至少为1")
@Max(value = 10, message = "图片数量最多为10")
private Integer n = 1;
/**
* 图片风格
*/
private ImageStyle style = ImageStyle.VIVID;
/**
* 用户ID(用于缓存)
*/
private String userId;
/**
* 图片尺寸枚举
*/
public enum ImageSize {
S256X256("256x256"),
S512X512("512x512"),
S1024X1024("1024x1024");
private final String value;
ImageSize(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
/**
* 图片风格枚举
*/
public enum ImageStyle {
NATURAL("natural"),
VIVID("vivid");
private final String value;
ImageStyle(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
ImageController - REST接口
less
package com.example.textToImage.controller;
import com.example.textToImage.model.ImageRequest;
import com.example.textToImage.model.ImageResponse;
import com.example.textToImage.service.OpenAiImageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* 文生图控制器
*
* 提供RESTful API接口
*/
@Slf4j
@RestController
@RequestMapping("/api/images")
@CrossOrigin(origins = "*")
public class ImageController {
@Autowired
private OpenAiImageService imageService;
/**
* 生成图片 - 同步接口
*/
@PostMapping
public ResponseEntity<ImageResponse> generateImage(@Valid @RequestBody ImageRequest request) {
log.info("收到图片生成请求: prompt={}, size={}", request.getPrompt(), request.getSize());
try {
ImageResponse response = imageService.generateImage(request);
if (response.getSuccess()) {
return ResponseEntity.ok(response);
} else {
return ResponseEntity.internalServerError().body(response);
}
} catch (Exception e) {
log.error("图片生成请求处理失败", e);
return ResponseEntity.internalServerError()
.body(ImageResponse.builder()
.error(e.getMessage())
.success(false)
.build());
}
}
/**
* 生成图片 - 异步接口
*/
@PostMapping("/async")
public CompletableFuture<ResponseEntity<ImageResponse>> generateImageAsync(@Valid @RequestBody ImageRequest request) {
log.info("收到异步图片生成请求: prompt={}", request.getPrompt());
return CompletableFuture.supplyAsync(() -> {
try {
ImageResponse response = imageService.generateImage(request);
if (response.getSuccess()) {
return ResponseEntity.ok(response);
} else {
return ResponseEntity.internalServerError().body(response);
}
} catch (Exception e) {
log.error("异步图片生成请求处理失败", e);
return ResponseEntity.internalServerError()
.body(ImageResponse.builder()
.error(e.getMessage())
.success(false)
.build());
}
});
}
/**
* 批量生成图片
*/
@PostMapping("/batch")
public CompletableFuture<ResponseEntity<List<ImageResponse>>> generateImages(
@Valid @RequestBody List<ImageRequest> requests) {
return CompletableFuture.supplyAsync(() -> {
try {
List<ImageResponse> responses = requests.stream()
.map(imageService::generateImage)
.collect(Collectors.toList());
boolean allSuccess = responses.stream().allMatch(ImageResponse::getSuccess);
if (allSuccess) {
return ResponseEntity.ok(responses);
} else {
return ResponseEntity.internalServerError().body(responses);
}
} catch (Exception e) {
log.error("批量图片生成请求处理失败", e);
return ResponseEntity.internalServerError()
.body(Arrays.asList(ImageResponse.builder()
.error(e.getMessage())
.success(false)
.build()));
}
});
}
/**
* 生成示例图片
*/
@GetMapping("/examples")
public ResponseEntity<List<ImageRequest>> getExampleRequests() {
List<ImageRequest> examples = Arrays.asList(
createExampleRequest("一只可爱的卡通猫,坐在花园里,阳光明媚", ImageRequest.ImageSize.S1024X1024, 1, ImageRequest.ImageStyle.VIVID),
createExampleRequest("现代城市天际线,夜晚,霓虹灯", ImageRequest.ImageSize.S1024X1024, 1, ImageRequest.ImageStyle.NATURAL),
createExampleRequest("抽象艺术,彩色几何形状", ImageRequest.ImageSize.S512X512, 2, ImageRequest.ImageStyle.VIVID)
);
return ResponseEntity.ok(examples);
}
/**
* 检查服务状态
*/
@GetMapping("/health")
public ResponseEntity<String> healthCheck() {
return ResponseEntity.ok("Image Generation Service is running");
}
/**
* 创建请求
*/
private ImageRequest createExampleRequest(String prompt, ImageRequest.ImageSize size, int n, ImageRequest.ImageStyle style) {
ImageRequest request = new ImageRequest();
request.setPrompt(prompt);
request.setSize(size);
request.setN(n);
request.setStyle(style);
return request;
}
}
OpenAiImageService
scss
package com.example.textToImage.service;
import com.example.textToImage.model.ApiKeyConfig;
import com.example.textToImage.model.ImageRequest;
import com.example.textToImage.model.ImageResponse;
import com.theokanning.openai.image.CreateImageRequest;
import com.theokanning.openai.image.ImageResult;
import com.theokanning.openai.service.OpenAiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* OpenAI文生图服务实现
*
* 使用DALL-E 3/2模型生成图片
* 支持多种参数配置
*/
@Slf4j
@Service
public class OpenAiImageService {
@Autowired
private ApiKeyConfig apiKeyConfig;
/**
* 生成图片
*/
@Cacheable(value = "images", key = "#request.prompt + '_' + #request.size + '_' + #request.style")
public ImageResponse generateImage(ImageRequest request) {
long startTime = System.currentTimeMillis();
String requestId = UUID.randomUUID().toString();
try {
// 创建OpenAI服务
OpenAiService service = createOpenAiService();
// 构建请求参数
CreateImageRequest imageRequest = buildCreateImageRequest(request);
// 调用API生成图片
ImageResult result = service.createImage(imageRequest);
// 构建响应
ImageResponse response = buildResponse(request, requestId, result, startTime);
log.info("图片生成成功: requestId={}, prompt={}", requestId, request.getPrompt());
return response;
} catch (Exception e) {
log.error("图片生成失败: requestId={}, prompt={}", requestId, request.getPrompt(), e);
return buildErrorResponse(requestId, e.getMessage(), startTime);
}
}
/**
* 创建OpenAI服务
*/
private OpenAiService createOpenAiService() {
if (apiKeyConfig.getUseProxy() && apiKeyConfig.getProxy() != null) {
// 代理配置(示例)
return new OpenAiService(apiKeyConfig.getOpenaiKey(), Duration.ofSeconds(apiKeyConfig.getTimeout()));
} else {
// 直接连接
return new OpenAiService(apiKeyConfig.getOpenaiKey(), Duration.ofSeconds(apiKeyConfig.getTimeout()));
}
}
/**
* 构建图片请求
*/
private CreateImageRequest buildCreateImageRequest(ImageRequest request) {
return CreateImageRequest.builder()
.prompt(request.getPrompt())
.n(request.getN())
.size(request.getSize().getValue())
.responseFormat("url")
.user(request.getUserId() != null ? request.getUserId() : "anonymous")
.build();
}
/**
* 构建成功响应
*/
private ImageResponse buildResponse(ImageRequest request, String requestId,
ImageResult result, long startTime) {
List<String> urls = Arrays.asList(result.getData().stream()
.map(image -> image.getUrl())
.toArray(String[]::new));
List<String> imageIds = Collections.emptyList(); // 暂时使用空列表
return ImageResponse.builder()
.requestId(requestId)
.prompt(request.getPrompt())
.createdAt(java.time.LocalDateTime.now())
.urls(urls)
.imageIds(imageIds)
.duration(System.currentTimeMillis() - startTime)
.success(true)
.build();
}
/**
* 构建错误响应
*/
private ImageResponse buildErrorResponse(String requestId, String errorMessage, long startTime) {
return ImageResponse.builder()
.requestId(requestId)
.error(errorMessage)
.createdAt(java.time.LocalDateTime.now())
.duration(System.currentTimeMillis() - startTime)
.success(false)
.build();
}
}
四、业务流程详解

8步完整流程:
1️⃣ 用户输入文本:前端提交文本描述
2️⃣ 参数验证:校验参数格式和内容
3️⃣ 缓存查询:检查是否已生成过
4️⃣ 构建API请求:组装OpenAI请求
5️⃣ 调用OpenAI:发送图片生成请求
6️⃣ 接收响应:获取图片URL
7️⃣ 处理结果:保存到数据库
8️⃣ 返回图片:响应给用户
时序图

关键交互流程:
前端→控制器:POST请求
控制器→服务:参数验证
服务→缓存:查询缓存
服务→OpenAI:API调用
OpenAI→服务:返回图片URL
服务→缓存:更新缓存
服务→控制器:返回响应
五、缓存机制优化
多级缓存策略
L1 - Caffeine本地缓存
读写速度快,适合热点数据
减少网络调用
L2 - Redis分布式缓存
支持集群,容量大
集群环境数据共享
L3 - OpenAI API缓存
第三方服务自带缓存
降低API成本
Caffeine
csharp
package com.example.textToImage.demo;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Expiry;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Caffeine缓存演示类
*
* Caffeine缓存的基本用法和高级特性
*/
@Component
public class CaffeineDemo {
/**
* 创建基础缓存
*/
public Cache<String, String> createBasicCache() {
return Caffeine.newBuilder()
.maximumSize(1000) // 最大缓存数量
.expireAfterWrite(1, TimeUnit.HOURS) // 写入后1小时过期
.build();
}
/**
* 带有自定义过期策略的缓存
*/
public Cache<String, Object> createCustomExpiryCache() {
return Caffeine.newBuilder()
.expireAfter(new Expiry<String, Object>() {
@Override
public long expireAfterCreate(String key, Object value, long currentTime) {
return TimeUnit.MINUTES.toNanos(30); // 创建后30分钟过期
}
@Override
public long expireAfterUpdate(String key, Object value, long currentTime, long currentDuration) {
return currentDuration; // 更新时不重置过期时间
}
@Override
public long expireAfterRead(String key, Object value, long currentTime, long currentDuration) {
return currentDuration; // 读取时不重置过期时间
}
})
.maximumSize(500)
.build();
}
/**
* 带有统计信息的缓存
*/
public Cache<String, String> createStatsCache() {
return Caffeine.newBuilder()
.maximumSize(1000)
.recordStats() // 开启统计功能
.expireAfterWrite(1, TimeUnit.HOURS)
.build();
}
/**
* 缓存操作
*/
public void demonstrateCacheOperations() {
System.out.println("=== Caffeine缓存演示 ===");
// 创建缓存
Cache<String, String> cache = createBasicCache();
// 1. 基本操作
System.out.println("\n1. 基本缓存操作:");
// 存储
cache.put("user:1001", "张三");
cache.put("user:1002", "李四");
cache.put("user:1003", "王五");
// 获取
String user1 = cache.getIfPresent("user:1001");
System.out.println("获取用户1001: " + user1);
// 使用computeIfAbsent(原子操作)
String user4 = cache.get("user:1004", k -> "新用户" + k.substring(k.lastIndexOf(":") + 1));
System.out.println("获取用户1004: " + user4);
// 2. 统计信息
System.out.println("\n2. 缓存统计:");
Cache<String, String> statsCache = createStatsCache();
// 模拟一些操作
for (int i = 0; i < 100; i++) {
statsCache.put("key:" + i, "value:" + i);
}
for (int i = 0; i < 50; i++) {
statsCache.getIfPresent("key:" + i);
}
// 打印统计信息
com.github.benmanes.caffeine.cache.stats.CacheStats stats = statsCache.stats();
System.out.println("缓存命中次数: " + stats.hitCount());
System.out.println("缓存未命中次数: " + stats.missCount());
System.out.println("缓存命中率: " + stats.hitRate());
System.out.println("加载时间: " + stats.totalLoadTime() + " ns");
// 3. 手动失效
System.out.println("\n3. 缓存失效:");
cache.invalidate("user:1001"); // 单个key失效
cache.invalidateAll(); // 全部失效
System.out.println("缓存演示完成!");
}
/**
* 图片缓存场景
*/
public void demonstrateImageCache() {
System.out.println("\n=== 图片缓存演示 ===");
Cache<String, byte[]> imageCache = Caffeine.newBuilder()
.maximumSize(100) // 缓存100张图片
.maximumWeight(10 * 1024 * 1024) // 最大10MB
.expireAfterWrite(24, TimeUnit.HOURS) // 24小时过期
.build();
// 模拟图片数据
byte[] smallImage = new byte[50 * 1024]; // 50KB
byte[] largeImage = new byte[2 * 1024 * 1024]; // 2MB
// 存储图片
imageCache.put("image:small", smallImage);
imageCache.put("image:large", largeImage);
System.out.println("小图片缓存状态: " +
(imageCache.getIfPresent("image:small") != null ? "已缓存" : "未缓存"));
System.out.println("大图片缓存状态: " +
(imageCache.getIfPresent("image:large") != null ? "已缓存" : "未缓存"));
// 获取缓存统计
com.github.benmanes.caffeine.cache.stats.CacheStats stats = imageCache.stats();
System.out.println("图片缓存命中率: " + String.format("%.2f%%", stats.hitRate() * 100));
}
}
数据流转

智能缓存查询流程:
1、用户发起请求
2、验证并查询缓存
3、缓存未命中调用API
4、OpenAI生成图片
5、处理结果并缓存
6、返回结果给用户
六、性能优化与部署

JVM参数优化
diff
-Xms2g -Xmx4g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
异步处理配置
less
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor =
new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
return executor;
}
}
七、总结
多模态融合
文+图→图
图+图→视频
AR/VR内容生成
本地化部署
模型小型化
推理优化
成本可控