Lombok‘s `@Builder` && 配置类使用
文章目录
前言
@Builder 是什么?
它是 Lombok 提供的注解,编译时自动生成一个 Builder 内部类,让你用链式调用构建对象。
原理对比
没有 @Builder 时,你需要:
TemplateMessage msg = new TemplateMessage();
msg.setToUser("oXXXX");
msg.setTemplateId("abc123");
msg.setUrl("https://...");
// 字段多了很繁琐,而且构造函数参数顺序容易搞混
用了 @Builder 后,Lombok 在编译时自动生成等价代码:
TemplateMessage msg = TemplateMessage.builder()
.toUser("oXXXX")
.templateId("abc123")
.url("https://...")
.data(dataMap)
.build(); // 最后调用 build() 才真正创建对象
为什么推荐用?
| 优势 | 说明 |
|---|---|
| 可读性好 | 链式调用,一眼看出每个字段赋了什么值 |
| 不怕顺序错 | 不依赖构造函数参数顺序 |
| 可选字段灵活 | 只设你需要的字段,其他保持 null |
| 不可变对象 | 配合 @Builder + @AllArgsConstructor + 私有构造,可以做出不可变对象 |
本项目中的实际使用
在 WxPushService.java 里就是这样用的:
TemplateMessage message = TemplateMessage.builder()
.toUser(openId) // 接收者
.templateId(templateId) // 模板ID
.url(url) // H5跳转
.miniProgram(miniProgram) // 小程序跳转
.data(data) // 模板数据
.build(); // 构建对象
简单说:@Builder = Lombok 帮你自动写了一个链式构建器,你只管 .字段名(值) 链式调用,最后 .build() 拿到对象。
对比
| Java (本项目) | JavaScript | |
|---|---|---|
| 代码 | JSON.toJSONString(message) |
JSON.stringify(message) |
| 库 | fastjson2 | 内置 |
| 作用 | Java 对象 → JSON 字符串 | JS 对象 → JSON 字符串 |
具体例子
Java 端(本项目):
TemplateMessage message = TemplateMessage.builder()
.toUser("oXXXX")
.templateId("abc123")
.build();
String jsonBody = JSON.toJSONString(message);
// 结果: {"touser":"oXXXX","template_id":"abc123","data":null,...}
等价于 JavaScript 端:
const message = {
touser: "oXXXX",
template_id: "abc123",
data: null
};
const jsonBody = JSON.stringify(message);
// 结果: {"touser":"oXXXX","template_id":"abc123","data":null}
为什么需要这一步?
微信 API 要求请求体是 JSON 字符串,而不是 Java 对象。所以必须把 Java 对象"序列化"成 JSON 字符串,才能通过 HTTP POST 发给微信服务器。
Java 对象 → JSON.toJSONString() → JSON 字符串 → POST 发给微信
一句话总结:JSON.toJSONString() 就是 Java 版的 JSON.stringify(),都是把对象转成 JSON 字符串。
区别
TemplateMessage.builder() |
new Request.Builder() |
|
|---|---|---|
| 来源 | Lombok @Builder 注解自动生成 |
OkHttp 库手写的 Builder 类 |
| 调用方式 | 类名.builder() |
new 类名.Builder() |
| 原理 | 编译时 Lombok 自动生成代码 | OkHttp 作者手动写的 Java 代码 |
为什么 OkHttp 的 Request 要用 Builder?
因为 Request 对象字段很多,而且有些是必填(URL),有些是可选(header、body、tag等)。用 Builder 模式可以灵活组合:
// GET 请求 — 简单
Request req1 = new Request.Builder()
.url("https://api.weixin.qq.com/...")
.get()
.build();
// POST 请求 — 加 body
Request req2 = new Request.Builder()
.url("https://api.weixin.qq.com/...")
.post(requestBody)
.addHeader("Authorization", "Bearer xxx") // 可选加 header
.build();
怎么区分?
看调用方式就行:
// Lombok 的 @Builder(没有 new)
TemplateMessage.builder().toUser("xxx").build();
// 库自己写的 Builder(有 new)
new Request.Builder().url("xxx").build();
有 new = 库/框架自己实现的 Builder 类
没有 new = Lombok @Builder 自动生成的静态方法
一句话总结:Builder 是一种通用的设计模式,Lombok 只是帮你自动生成,OkHttp 是作者手写的,效果一样,写法略有不同。
配置类–核心思路
package com.example.wxpush.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 微信公众号配置属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpConfig {
/** 公众号 AppID */
private String appId;
/** 公众号 AppSecret */
private String appSecret;
/** 模板消息模板ID */
private String templateId;
// ==================== 微信 API 地址常量 ====================
/** 获取 access_token 接口 */
public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
/** 发送模板消息接口 */
public static final String TEMPLATE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
}
把所有可变的、跟环境相关的值从代码中抽出来,集中管理。
硬编码(❌ 差) 配置类(✅ 好)
代码里写死 appid 配置文件里填,代码里读取
换个环境要改代码 换个环境只改配置文件
通用三步套路
第一步:application.yml 写配置值
wx:
mp:
app-id: wx123456
app-secret: abcdef
template-id: xyz789
第二步:Java 类用 @ConfigurationProperties 绑定
@Data
@Component
@ConfigurationProperties(prefix = "wx.mp") // 对应 yml 中的 wx.mp
public class WxMpConfig {
private String appId; // 自动绑定 app-id(驼峰自动转换)
private String appSecret;
private String templateId;
}
第三步:哪里需要,就注入哪里
@Service
public class WxPushService {
private final WxMpConfig wxMpConfig; // 注入配置类
public WxPushService(WxMpConfig wxMpConfig) {
this.wxMpConfig = wxMpConfig;
}
public void doSomething() {
String appId = wxMpConfig.getAppId(); // 直接用
}
}
为什么这样做?
| 好处 | 说明 |
|---|---|
| 不改代码换配置 | 开发/测试/生产环境只需换 yml 文件 |
| 集中管理 | 所有配置值在一个类里,一目了然 |
| 类型安全 | String、Integer、Boolean 自动转换,不会拼错 |
| IDE 提示 | 配合插件,yml 里写错字段名会报错 |
| 方便复用 | 多个 Service 都注入同一个配置类 |
常见场景
几乎任何需要配置的东西都这么做:
# 数据库配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
# 阿里云 OSS 配置
aliyun:
oss:
endpoint: oss-cn-hangzhou.aliyuncs.com
access-key-id: LTAI...
bucket-name: my-bucket
# 支付配置
pay:
alipay:
app-id: 2021...
private-key: MIIEv...
每个都对应一个 @ConfigurationProperties 配置类。
一句话总结
配置类的本质 = yml 文件和 Java 代码之间的桥梁,让代码不硬编码、配置集中管、环境切换零改动。
更多推荐


所有评论(0)