面向外卖接口开发:Spring Boot Starter封装霸王餐API通用对接组件
·
面向外卖接口开发:Spring Boot Starter封装霸王餐API通用对接组件
在外卖平台快速接入“霸王餐”营销能力的场景中,为避免各合作方重复实现鉴权、签名、重试、日志等通用逻辑,我们基于Spring Boot Starter机制封装了baodanbao-spring-boot-starter,实现一行依赖即可完成API对接。本文展示该Starter的设计思路与核心实现代码。
Starter模块结构设计
创建独立Maven模块baodanbao-spring-boot-starter,包结构如下:
src/main/java
└── baodanbao/com/cn/starter
├── autoconfigure/BaoDanBaoAutoConfiguration.java
├── properties/BaoDanBaoProperties.java
├── client/BaoDanBaoApiClient.java
└── model/QualifyRequest.java, QualifyResponse.java
定义配置属性类
通过@ConfigurationProperties绑定外部配置:
// baodanbao-spring-boot-starter/src/main/java/baodanbao/com/cn/starter/properties/BaoDanBaoProperties.java
package baodanbao.com.cn.starter.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "baodanbao.api")
public class BaoDanBaoProperties {
private String baseUrl = "https://api.baodanbao.com.cn";
private String appId;
private String appSecret;
private int connectTimeout = 5000;
private int readTimeout = 10000;
// getters and setters
}

实现API客户端
封装HTTP调用、签名生成与异常处理:
// baodanbao-spring-boot-starter/src/main/java/baodanbao/com/cn/starter/client/BaoDanBaoApiClient.java
package baodanbao.com.cn.starter.client;
import baodanbao.com.cn.starter.model.QualifyRequest;
import baodanbao.com.cn.starter.model.QualifyResponse;
import baodanbao.com.cn.starter.properties.BaoDanBaoProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class BaoDanBaoApiClient {
private final OkHttpClient client;
private final BaoDanBaoProperties properties;
private final ObjectMapper objectMapper = new ObjectMapper();
public BaoDanBaoApiClient(BaoDanBaoProperties props) {
this.properties = props;
this.client = new OkHttpClient.Builder()
.connectTimeout(props.getConnectTimeout(), java.util.concurrent.TimeUnit.MILLISECONDS)
.readTimeout(props.getReadTimeout(), java.util.concurrent.TimeUnit.MILLISECONDS)
.build();
}
public QualifyResponse checkQualify(QualifyRequest request) throws IOException {
Map<String, Object> payload = objectMapper.convertValue(request, Map.class);
String timestamp = String.valueOf(System.currentTimeMillis());
String sign = generateSign(payload, timestamp);
HttpUrl url = HttpUrl.parse(properties.getBaseUrl() + "/v1/qualify/check")
.newBuilder()
.addQueryParameter("appId", properties.getAppId())
.addQueryParameter("timestamp", timestamp)
.addQueryParameter("sign", sign)
.build();
RequestBody body = RequestBody.create(
objectMapper.writeValueAsString(payload),
MediaType.get("application/json")
);
Request httpRequest = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
return objectMapper.readValue(response.body().string(), QualifyResponse.class);
}
}
private String generateSign(Map<String, Object> params, String timestamp) {
// 简化签名逻辑:按key排序后拼接 + appSecret + timestamp,再取MD5
StringBuilder sb = new StringBuilder();
params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(e -> sb.append(e.getKey()).append("=").append(e.getValue()).append("&"));
sb.append("appSecret=").append(properties.getAppSecret()).append("×tamp=").append(timestamp);
return org.apache.commons.codec.digest.DigestUtils.md5Hex(sb.toString());
}
}
自动配置类
在autoconfigure包中注册Bean:
// baodanbao-spring-boot-starter/src/main/java/baodanbao/com/cn/starter/autoconfigure/BaoDanBaoAutoConfiguration.java
package baodanbao.com.cn.starter.autoconfigure;
import baodanbao.com.cn.starter.client.BaoDanBaoApiClient;
import baodanbao.com.cn.starter.properties.BaoDanBaoProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(BaoDanBaoProperties.class)
public class BaoDanBaoAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public BaoDanBaoApiClient baoDanBaoApiClient(BaoDanBaoProperties properties) {
return new BaoDanBaoApiClient(properties);
}
}
配置spring.factories
确保自动配置被Spring Boot加载:
# resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
baodanbao.com.cn.starter.autoconfigure.BaoDanBaoAutoConfiguration
注:Spring Boot 2.4+ 使用
AutoConfiguration.imports替代旧版spring.factories。
使用方集成示例
外卖系统只需三步即可调用霸王餐接口:
- 引入Starter依赖:
<dependency>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
- 配置
application.yml:
baodanbao:
api:
app-id: "waimai_1001"
app-secret: "xxxxxx"
base-url: "https://api.baodanbao.com.cn"
- 在Service中直接注入客户端:
@Service
public class WaimaiOrderService {
@Autowired
private BaoDanBaoApiClient baoDanBaoClient;
public void processOrder(String userId, String merchantId) {
try {
QualifyResponse resp = baoDanBaoClient.checkQualify(
new QualifyRequest(userId, merchantId)
);
if (resp.isQualified()) {
// 发放霸王餐权益
}
} catch (IOException e) {
log.error("调用霸王餐API失败", e);
}
}
}
该Starter已内置连接池、超时控制、签名安全及JSON序列化,极大降低接入成本。
本文著作权归 俱美开放平台 ,转载请注明出处!
更多推荐




所有评论(0)