本文目录导读:

我来为你提供几个完整的Java无服务器计算案例,涵盖不同云平台和使用场景。
AWS Lambda + Java 案例
基础Lambda函数示例
package com.example.lambda;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.HashMap;
import java.util.Map;
public class UserServiceHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private final UserRepository userRepository = new UserRepository();
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
context.getLogger().log("收到请求: " + input.getHttpMethod() + " " + input.getPath());
try {
// 根据HTTP方法路由请求
switch (input.getHttpMethod()) {
case "GET":
return handleGetRequest(input);
case "POST":
return handlePostRequest(input);
case "PUT":
return handlePutRequest(input);
case "DELETE":
return handleDeleteRequest(input);
default:
return createResponse(405, "方法不允许");
}
} catch (Exception e) {
context.getLogger().log("处理异常: " + e.getMessage());
return createResponse(500, "服务器内部错误");
}
}
private APIGatewayProxyResponseEvent handleGetRequest(APIGatewayProxyRequestEvent input) {
// GET /users/{id}
String userId = input.getPathParameters().get("id");
if (userId != null) {
User user = userRepository.findById(userId);
if (user != null) {
return createResponse(200, gson.toJson(user));
}
return createResponse(404, "用户不存在");
}
// GET /users - 获取所有用户
List<User> users = userRepository.findAll();
return createResponse(200, gson.toJson(users));
}
private APIGatewayProxyResponseEvent handlePostRequest(APIGatewayProxyRequestEvent input) {
// POST /users - 创建用户
User newUser = gson.fromJson(input.getBody(), User.class);
User createdUser = userRepository.save(newUser);
return createResponse(201, gson.toJson(createdUser));
}
private APIGatewayProxyResponseEvent handlePutRequest(APIGatewayProxyRequestEvent input) {
// PUT /users/{id} - 更新用户
String userId = input.getPathParameters().get("id");
User updatedUser = gson.fromJson(input.getBody(), User.class);
updatedUser.setId(userId);
User result = userRepository.update(updatedUser);
if (result != null) {
return createResponse(200, gson.toJson(result));
}
return createResponse(404, "用户不存在");
}
private APIGatewayProxyResponseEvent handleDeleteRequest(APIGatewayProxyRequestEvent input) {
// DELETE /users/{id} - 删除用户
String userId = input.getPathParameters().get("id");
userRepository.delete(userId);
return createResponse(200, "删除成功");
}
private APIGatewayProxyResponseEvent createResponse(int statusCode, String body) {
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setStatusCode(statusCode);
// 添加CORS头
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Access-Control-Allow-Origin", "*");
headers.put("Access-Control-Allow-Headers", "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token");
headers.put("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
response.setHeaders(headers);
response.setBody(body);
return response;
}
}
用户实体类
package com.example.lambda;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
@DynamoDBTable(tableName = "Users")
public class User {
private String id;
private String name;
private String email;
private int age;
private long createdAt;
public User() {}
public User(String id, String name, String email, int age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
this.createdAt = System.currentTimeMillis();
}
@DynamoDBHashKey(attributeName = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@DynamoDBAttribute(attributeName = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@DynamoDBAttribute(attributeName = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@DynamoDBAttribute(attributeName = "age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@DynamoDBAttribute(attributeName = "createdAt")
public long getCreatedAt() {
return createdAt;
}
public void setCreatedAt(long createdAt) {
this.createdAt = createdAt;
}
}
使用DynamoDB的数据访问层
package com.example.lambda;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import java.util.List;
import java.util.UUID;
public class UserRepository {
private final AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
private final DynamoDBMapper mapper = new DynamoDBMapper(client);
public User save(User user) {
if (user.getId() == null || user.getId().isEmpty()) {
user.setId(UUID.randomUUID().toString());
}
mapper.save(user);
return user;
}
public User findById(String id) {
return mapper.load(User.class, id);
}
public List<User> findAll() {
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
return mapper.scan(User.class, scanExpression);
}
public User update(User user) {
User existing = findById(user.getId());
if (existing != null) {
mapper.save(user);
return user;
}
return null;
}
public void delete(String id) {
User user = new User();
user.setId(id);
mapper.delete(user);
}
}
Azure Functions + Java 案例
定时触发器函数(定时清理任务)
package com.example.azure;
import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.time.Instant;
import java.util.Optional;
public class CleanupScheduler {
private static final Logger logger = LoggerFactory.getLogger(CleanupScheduler.class);
@FunctionName("cleanupExpiredData")
public void cleanupExpiredData(
@TimerTrigger(name = "timerInfo", schedule = "0 0 2 * * *") String timerInfo,
ExecutionContext context) {
context.getLogger().info("定时清理任务开始执行: " + Instant.now());
// 清理过期的临时文件
cleanupTempFiles(context);
// 清理过期的会话
cleanupExpiredSessions(context);
// 清理日志文件
cleanupOldLogs(context);
context.getLogger().info("定时清理任务执行完成");
}
private void cleanupTempFiles(ExecutionContext context) {
try {
// 使用Azure Blob Storage清理文件
String connectionString = System.getenv("AzureWebJobsStorage");
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.connectionString(connectionString)
.buildClient();
String containerName = "temp-files";
BlobContainerClient containerClient = blobServiceClient.getBlobContainerClient(containerName);
long cutoffTime = System.currentTimeMillis() - (24 * 60 * 60 * 1000); // 24小时前
int deletedCount = 0;
for (BlobItem blob : containerClient.listBlobs()) {
BlobClient blobClient = containerClient.getBlobClient(blob.getName());
BlobProperties properties = blobClient.getProperties();
if (properties.getLastModified().getTime() < cutoffTime) {
blobClient.delete();
deletedCount++;
}
}
context.getLogger().info("清理了 " + deletedCount + " 个临时文件");
} catch (Exception e) {
context.getLogger().severe("清理临时文件失败: " + e.getMessage());
}
}
private void cleanupExpiredSessions(ExecutionContext context) {
String connectionString = System.getenv("AZURE_SQL_CONNECTION");
if (connectionString == null) {
context.getLogger().warning("未配置数据库连接字符串");
return;
}
try (Connection conn = DriverManager.getConnection(connectionString);
PreparedStatement stmt = conn.prepareStatement(
"DELETE FROM user_sessions WHERE expires_at < GETDATE()")) {
int deletedCount = stmt.executeUpdate();
context.getLogger().info("清理了 " + deletedCount + " 个过期会话");
} catch (Exception e) {
context.getLogger().severe("清理会话失败: " + e.getMessage());
}
}
private void cleanupOldLogs(ExecutionContext context) {
// 清理超过30天的应用日志
String connectionString = System.getenv("AzureWebJobsStorage");
try {
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
.connectionString(connectionString)
.buildClient();
String tableName = "applogs";
String cutoffDate = Instant.now()
.minus(30, ChronoUnit.DAYS)
.toString()
.substring(0, 10);
int deletedCount = 0;
// 查询并删除旧日志
PagedIterable<TableEntity> entities = tableServiceClient.queryTable(
tableName,
String.format("PartitionKey lt '%s'", cutoffDate),
null);
for (TableEntity entity : entities) {
tableServiceClient.deleteTableEntity(tableName, entity);
deletedCount++;
}
context.getLogger().info("清理了 " + deletedCount + " 条旧日志");
} catch (Exception e) {
context.getLogger().severe("清理日志失败: " + e.getMessage());
}
}
}
事件网格触发器(处理订单事件)
package com.example.azure;
import com.example.models.Order;
import com.google.gson.Gson;
import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.*;
import com.azure.storage.queue.QueueClient;
import com.azure.storage.queue.QueueClientBuilder;
public class OrderProcessor {
private static final Gson gson = new Gson();
@FunctionName("processOrder")
public void processOrder(
@EventGridTrigger(name = "event") String event,
ExecutionContext context) {
context.getLogger().info("订单事件到达: " + event);
try {
// 解析事件
EventGridEvent eventGridEvent = EventGridEvent.fromString(event);
Order order = gson.fromJson(eventGridEvent.getData().toString(), Order.class);
context.getLogger().info("处理订单: " + order.getOrderId());
// 1. 验证订单
boolean isValid = validateOrder(order);
if (!isValid) {
context.getLogger().warning("订单无效: " + order.getOrderId());
return;
}
// 2. 更新库存
updateInventory(order);
// 3. 如果订单金额大于1000,需要人工审核
if (order.getTotalAmount() > 1000) {
sendForApproval(order);
}
// 4. 设置订单状态
order.setStatus("PROCESSING");
// 5. 发送通知
sendNotification(order);
context.getLogger().info("订单处理完成: " + order.getOrderId());
} catch (Exception e) {
context.getLogger().severe("处理订单失败: " + e.getMessage());
throw new RuntimeException("处理订单失败", e);
}
}
private boolean validateOrder(Order order) {
// 验证订单基本信息
return order.getOrderId() != null
&& order.getCustomerId() != null
&& order.getItems() != null
&& !order.getItems().isEmpty();
}
private void updateInventory(Order order) {
// 使用Azure SQL更新库存
String connectionString = System.getenv("AZURE_SQL_CONNECTION");
try (Connection conn = DriverManager.getConnection(connectionString)) {
for (OrderItem item : order.getItems()) {
String sql = "UPDATE inventory SET quantity = quantity - ? WHERE product_id = ? AND quantity >= ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, item.getQuantity());
stmt.setString(2, item.getProductId());
stmt.setInt(3, item.getQuantity());
int updatedRows = stmt.executeUpdate();
if (updatedRows == 0) {
throw new RuntimeException("库存不足: " + item.getProductId());
}
}
}
} catch (Exception e) {
throw new RuntimeException("更新库存失败", e);
}
}
private void sendForApproval(Order order) {
// 发送到队列等待人工审核
String connectionString = System.getenv("AzureWebJobsStorage");
QueueClient queueClient = new QueueClientBuilder()
.connectionString(connectionString)
.queueName("order-approval")
.buildClient();
order.setStatus("PENDING_APPROVAL");
queueClient.sendMessage(gson.toJson(order));
}
private void sendNotification(Order order) {
// 使用Azure Notification Hubs发送通知
String connectionString = System.getenv("AZURE_NOTIFICATION_HUB_CONNECTION");
String hubName = System.getenv("AZURE_NOTIFICATION_HUB_NAME");
NotificationHubClient client = new NotificationHubClientBuilder()
.connectionString(connectionString)
.notificationHubName(hubName)
.buildClient();
Map<String, String> payload = new HashMap<>();
payload.put("message", "订单 " + order.getOrderId() + " 正在处理中");
try {
client.sendNotification(Notification.createWindowsNotification(
gson.toJson(payload)), new NotificationHubClient.SendNotificationOptions());
} catch (Exception e) {
context.getLogger().warning("发送通知失败: " + e.getMessage());
}
}
}
Google Cloud Functions + Java 案例
图片处理函数
package com.example.gcp;
import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.vision.v1.*;
import com.google.protobuf.ByteString;
import net.coobird.thumbnailator.Thumbnails;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
public class ImageProcessor implements BackgroundFunction<StorageEvent> {
private final Storage storage = StorageOptions.getDefaultInstance().getService();
private final ImageAnnotatorClient visionClient;
public ImageProcessor() {
try {
visionClient = ImageAnnotatorClient.create();
} catch (Exception e) {
throw new RuntimeException("初始化Vision客户端失败", e);
}
}
@Override
public void accept(StorageEvent event, Context context) throws Exception {
context.logger().log("处理图片: " + event.getName());
// 1. 读取原图
Blob sourceBlob = storage.get(event.getBucket(), event.getName());
byte[] imageData = sourceBlob.getContent();
// 2. 生成缩略图
String thumbnailPath = "thumbnails/" + event.getName();
generateThumbnail(imageData, event.getBucket(), thumbnailPath);
// 3. 检测图片内容(检查是否为违规内容)
boolean isSafe = detectUnsafeContent(imageData);
if (!isSafe) {
context.logger().log("图片可能包含违规内容: " + event.getName());
moveToQuarantine(event.getBucket(), event.getName());
return;
}
// 4. 提取图片标签
List<String> labels = extractLabels(imageData);
// 5. 存储图片元数据
storeImageMetadata(event, labels);
context.logger().log("图片处理完成");
}
private void generateThumbnail(byte[] imageData, String bucketName, String thumbnailPath) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 使用Thumbnailator生成缩略图
Thumbnails.of(new ByteArrayInputStream(imageData))
.size(300, 300)
.outputFormat("JPEG")
.toOutputStream(outputStream);
BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, thumbnailPath)
.setContentType("image/jpeg")
.build();
storage.create(blobInfo, outputStream.toByteArray());
}
private boolean detectUnsafeContent(byte[] imageData) {
try {
ByteString imgBytes = ByteString.copyFrom(imageData);
Image image = Image.newBuilder().setContent(imgBytes).build();
Feature feature = Feature.newBuilder()
.setType(Feature.Type.SAFE_SEARCH_DETECTION)
.build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(feature)
.setImage(image)
.build();
BatchAnnotateImagesResponse response = visionClient.batchAnnotateImages(
Collections.singletonList(request));
SafeSearchAnnotation annotation = response.getResponses(0).getSafeSearchAnnotation();
// 检查是否有高几率的不安全内容
boolean isUnsafe =
annotation.getAdultValue() >= Likelihood.LIKELY_VALUE ||
annotation.getViolenceValue() >= Likelihood.LIKELY_VALUE ||
annotation.getRacyValue() >= Likelihood.VERY_LIKELY_VALUE;
return !isUnsafe;
} catch (Exception e) {
// 无法检测时默认通过
return true;
}
}
private List<String> extractLabels(byte[] imageData) {
try {
ByteString imgBytes = ByteString.copyFrom(imageData);
Image image = Image.newBuilder().setContent(imgBytes).build();
Feature feature = Feature.newBuilder()
.setType(Feature.Type.LABEL_DETECTION)
.build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(feature)
.setImage(image)
.build();
BatchAnnotateImagesResponse response = visionClient.batchAnnotateImages(
Collections.singletonList(request));
List<String> labels = new ArrayList<>();
response.getResponses(0).getLabelAnnotationsList()
.forEach(label -> labels.add(label.getDescription()));
return labels;
} catch (Exception e) {
return Collections.emptyList();
}
}
private void moveToQuarantine(String bucketName, String fileName) {
String quarantinePath = "quarantine/" + fileName;
Blob blob = storage.get(bucketName, fileName);
storage.copy(
Storage.CopyRequest.newBuilder()
.setSource(blob.getBlobId())
.setTarget(BlobId.of(bucketName, quarantinePath))
.build());
blob.delete();
}
private void storeImageMetadata(StorageEvent event, List<String> labels) {
// 存储元数据到Datastore
Datastore datastore = DatastoreOptions.getDefaultInstance().getService();
Key key = datastore.newKeyFactory()
.setKind("ImageMetadata")
.newKey(UUID.randomUUID().toString());
Entity entity = Entity.newBuilder(key)
.set("fileName", event.getName())
.set("bucket", event.getBucket())
.set("contentType", event.getContentType())
.set("size", event.getSize())
.set("processedAt", Timestamp.now())
.set("labels", labels)
.build();
datastore.put(entity);
}
}
存储事件类
package com.example.gcp;
import java.util.Map;
public class StorageEvent {
private String bucket;
private String name;
private String contentType;
private long size;
private String timeCreated;
public String getBucket() {
return bucket;
}
public void setBucket(String bucket) {
this.bucket = bucket;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getTimeCreated() {
return timeCreated;
}
public void setTimeCreated(String timeCreated) {
this.timeCreated = timeCreated;
}
}
部署配置示例
AWS Lambda - serverless.yml
service: java-serverless-crud
provider:
name: aws
runtime: java11
region: us-east-1
environment:
DYNAMODB_TABLE: Users
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:Scan
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
functions:
userApi:
handler: com.example.lambda.UserServiceHandler
events:
- http:
path: users
method: get
cors: true
- http:
path: users
method: post
cors: true
- http:
path: users/{id}
method: get
cors: true
- http:
path: users/{id}
method: put
cors: true
- http:
path: users/{id}
method: delete
cors: true
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:provider.environment.DYNAMODB_TABLE}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
Azure Functions - host.json
{
"version": "2.0",
"functionTimeout": "00:10:00",
"extensions": {
"timer": {
"maxExecutionTime": "00:30:00"
}
},
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}
最佳实践案例
无服务器API网关 + 认证
package com.example.secure;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JwtTokenValidator {
private static final String SECRET_KEY = System.getenv("JWT_SECRET_KEY");
public static JwtUser validateToken(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("your-issuer")
.build();
DecodedJWT jwt = verifier.verify(token);
// 提取用户信息
JwtUser user = new JwtUser();
user.setUserId(jwt.getSubject());
user.setUsername(jwt.getClaim("username").asString());
user.setRoles(jwt.getClaim("roles").asList(String.class));
return user;
} catch (JWTVerificationException e) {
throw new AuthenticationException("无效的JWT令牌");
}
}
}
// 安全的Lambda处理器
public class SecureApiHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
// 1. 获取Authorization头
String authorizationHeader = input.getHeaders().get("Authorization");
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
return unauthorizedResponse();
}
// 2. 验证JWT令牌
String token = authorizationHeader.substring(7);
try {
JwtUser user = JwtTokenValidator.validateToken(token);
// 3. 检查用户权限
if (!user.hasRole("ADMIN")) {
return forbiddenResponse();
}
// 4. 处理业务逻辑
return processRequest(input, user);
} catch (AuthenticationException e) {
return unauthorizedResponse();
}
}
}
这些案例涵盖了Java无服务器计算的核心场景:
- AWS Lambda:API网关集成、DynamoDB操作、CRUD应用
- Azure Functions:定时任务、事件处理、队列操作
- Google Cloud Functions:图片处理、内容检测、存储事件
- 安全和最佳实践:JWT认证、权限控制
每个案例都展示了无服务器应用的关键特性:
- 事件驱动架构
- 自动扩缩容
- 按需计费
- 与其他云服务集成
- 无服务器特性(连接管理、状态管理等)