都说了布尔类型的变量不要加 is 前缀,非要加,这不是坑人了嘛
开心一刻
今天心情不好,给哥们发语音
我:哥们,晚上出来喝酒聊天吧
哥们:咋啦,心情不好?
我:嗯,刚刚在公交车上看见前女友了
哥们:然后呢?
我:给她让座时,发现她怀孕了...
哥们:所以难受了?
我:不是她怀孕让我难受,是她怀孕还坐公交车让我难受
哥们:不是,她跟着你就不用坐公交车了?不还是也要坐,有区别吗?
我默默的挂断了语音,心情更难受了

Java开发手册
作为一个 javaer
,我们肯定看过 Alibaba
的 Java开发手册,作为国内Java开发领域的标杆性编码规范,我们或多或少借鉴了其中的一些规范,其中有一点

我印象特别深,也一直在奉行,自己还从未试过用 is
作为布尔类型变量的前缀,不知道会有什么坑;正好前段时间同事这么用了,很不幸,他挖坑,我踩坑,阿西吧!

is前缀的布尔变量有坑
为了复现问题,我先简单搞个 demo
;调用很简单,服务 workflow
通过 openfeign
调用 offline-sync
,代码结构如下

qsl-data-govern-common:整个项目的公共模块
qsl-offline-sync:离线同步
- qsl-offline-sync-api:向外提供
openfeign
接口- qsl-offline-sync-common:离线同步公共模块
- qsl-offline-sync-server:离线同步服务
qsl-workflow:工作流
- qsl-workflow-api:向外提供
openfeign
接口,暂时空实现- qsl-workflow-common:工作流公共模块
- qsl-workflow-server:工作流服务
完整代码:qsl-data-govern
qsl-offline-sync-server
提供删除接口
/**
* @author 青石路
*/
@RestController
@RequestMapping("/task")
public class SyncTaskController {
private static final Logger LOG = LoggerFactory.getLogger(SyncTaskController.class);
@PostMapping("/delete")
public ResultEntity<String> delete(@RequestBody SyncTaskDTO syncTask) {
// TODO 删除处理
LOG.info("删除任务[taskId={}]", syncTask.getTaskId());
return ResultEntity.success("删除成功");
}
}
qsl-offline-sync-api
对外提供 openfeign
接口
/**
* @author 青石路
*/
@FeignClient(name = "data-govern-offline-sync", contextId = "dataGovernOfflineSync", url = "${offline.sync.server.url}")
public interface OfflineSyncApi {
@PostMapping(value = "/task/delete")
ResultEntity<String> deleteTask(@RequestBody SyncTaskDTO syncTaskDTO);
}
qsl-workflow-server
调用 openfeign
接口
/**
* @author 青石路
*/
@RestController
@RequestMapping("/definition")
public class WorkflowController {
private static final Logger LOG = LoggerFactory.getLogger(WorkflowController.class);
@Resource
private OfflineSyncApi offlineSyncApi;
@PostMapping("/delete")
public ResultEntity<String> delete(@RequestBody WorkflowDTO workflow) {
LOG.info("删除工作流[workflowId={}]", workflow.getWorkflowId());
// 1.查询工作流节点,查到离线同步节点(taskId = 1)
// 2.删除工作流节点,删除离线同步节点
ResultEntity<String> syncDeleteResult = offlineSyncApi.deleteTask(new SyncTaskDTO(1L));
if (syncDeleteResult.getCode() != 200) {
LOG.error("删除离线同步任务[taskId={}]失败:{}", 1, syncDeleteResult.getMessage());
ResultEntity.fail(syncDeleteResult.getMessage());
}
return ResultEntity.success("删除成功");
}
}
逻辑是不是很简单?我们启动两个服务,然后发起 http
请求
POST http://localhost:8081/data-govern/workflow/definition/delete
Content-Type: application/json{
"workflowId": 99
}
此时 qsl-offline-sync-server
日志输出如下
2025-06-30 14:53:06.165|INFO|http-nio-8080-exec-4|25|c.q.s.s.controller.SyncTaskController :删除任务[taskId=1]
至此,一切都很正常,第一版也是这么对接的;后面 offline-sync
进行调整,删除接口增加了一个参数:isClearData
public class SyncTaskDTO {
public SyncTaskDTO(){}
public SyncTaskDTO(Long taskId, Boolean isClearData) {
this.taskId = taskId;
this.isClearData = isClearData;
}
private Long taskId;
private Boolean isClearData = false;
public Long getTaskId() {
return taskId;
}
public void setTaskId(Long taskId) {
this.taskId = taskId;
}
public Boolean getClearData() {
return isClearData;
}
public void setClearData(Boolean clearData) {
isClearData = clearData;
}
}
然后实现对应的逻辑
/**
* @author 青石路
*/
@RestController
@RequestMapping("/task")
public class SyncTaskController {
private static final Logger LOG = LoggerFactory.getLogger(SyncTaskController.class);
@PostMapping("/delete")
public ResultEntity<String> delete(@RequestBody SyncTaskDTO syncTask) {
// TODO 删除处理
LOG.info("删除任务[taskId={}]", syncTask.getTaskId());
if (syncTask.getClearData()) {
LOG.info("清空任务[taskId={}]历史数据", syncTask.getTaskId());
// TODO 清空历史数据
}
return ResultEntity.success("删除成功");
}
}
调整完之后,同事通知我,让我做对 qsl-workflow
做对应的调整。调整很简单,qsl-workflow
删除时直接传 true
即可
/**
* @author 青石路
*/
@RestController
@RequestMapping("/definition")
public class WorkflowController {
private static final Logger LOG = LoggerFactory.getLogger(WorkflowController.class);
@Resource
private OfflineSyncApi offlineSyncApi;
@PostMapping("/delete")
public ResultEntity<String> delete(@RequestBody WorkflowDTO workflow) {
LOG.info("删除工作流[workflowId={}]", workflow.getWorkflowId());
// 1.查询工作流节点,查到离线同步节点(taskId = 1)
// 2.删除工作流节点,删除离线同步节点
// 删除离线同步任务,isClearData直接传true
ResultEntity<String> syncDeleteResult = offlineSyncApi.deleteTask(new SyncTaskDTO(1L, true));
if (syncDeleteResult.getCode() != 200) {
LOG.error("删除离线同步任务[taskId={}]失败:{}", 1, syncDeleteResult.getMessage());
ResultEntity.fail(syncDeleteResult.getMessage());
}
return ResultEntity.success("删除成功");
}
}
调整完成之后,发起 http
请求,发现历史数据没有被清除,看日志发现
LOG.info("清空任务[taskId={}]历史数据", syncTask.getTaskId());
没有打印,参数明明传的是 true
吖!!!
offlineSyncApi.deleteTask(new SyncTaskDTO(1L, true));
这是哪里出了问题?

问题排查
因为 qsl-offline-sync-api
是直接引入的,并非我实现的,所以我第一时间找到了其实现者,反馈了问题后让其自测下;一开始他还很自信,说这么简单怎么会有问题

当他启动 qsl-offline-sync-server
后,发起 http
请求
POST http://localhost:8080/data-govern/sync/task/delete
Content-Type: application/json{
"taskId": 123,
"isClearData": true
}
发现 isClearData
的值是 false

此刻,疑问从我的额头转移到了他的额头上,他懵逼了,我轻松了。为了功能能够正常交付,我还是决定看下这个问题,没有了心理压力,也许更容易发现问题所在。第一眼看到 isClearData
,我就隐约觉得有问题,所以我决定仔细看下 SyncTaskDTO
这个类,发现 isClearData
的 setter
和 getter
方法有点不一样
private Boolean isClearData = false;
public Boolean getClearData() {
return isClearData;
}
public void setClearData(Boolean clearData) {
isClearData = clearData;
}
方法名是不是少了 Is
?带着这个疑问我找到了同事,问他 setter
、getter
为什么要这么命名?他说是 idea
工具自动生成的(也就是我们平时用到的idea自动生成setter、getter方法的功能)

我让他把 Is
补上试试
private Boolean isClearData = false;
public Boolean getIsClearData() {
return isClearData;
}
public void setIsClearData(Boolean isClearData) {
this.isClearData = isClearData;
}
发现传值正常了,他回过头看着我,我看着他,两人同时提问
他:为什么加了
Is
就可以了?我:布尔类型的变量,你为什么要加
is
前缀?
问题延申
作为一个严谨的开发,不只是要知其然,更要知其所以然;关于
为什么加了
Is
就可以了
这个问题,我们肯定是要会上一会的;会这个问题之前,我们先来捋一下参数的流转,因为是基于 Spring MVC
实现的 Web 应用,所以我们可以这么问 deepseek
Spring MVC 是如何将前端参数转换成POJO的
能够查到如下重点信息

RequestResponseBodyMethodProcessor
的 resolveArgument
/**
* Throws MethodArgumentNotValidException if validation fails.
* @throws HttpMessageNotReadableException if {@link RequestBody#required()}
* is {@code true} and there is no body content or if there is no suitable
* converter to read the content with.
*/
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
parameter = parameter.nestedIfOptional();
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter);
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
if (mavContainer != null) {
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
}
return adaptArgumentIfNecessary(arg, parameter);
}
正是解析参数的地方,我们打个断点,再发起一次 http
请求

很明显,readWithMessageConverters
是处理并转换参数的地方,继续跟进去会来到 MappingJackson2HttpMessageConverter
的 readJavaType
方法

此刻我们可以得到,是通过 jackson
完成数据绑定与数据转换的。继续跟进,会看到 isClearData
的赋值过程

通过前端传过来的参数 isClearData
找对应的 setter
方法是 setIsClearData,而非 setClearData
,所以问题
为什么加了
Is
就可以了
是不是就清楚了?
问题解决
- 按上述方式调整
isClearData
的setter
、getter
方法带上
is
public Boolean getIsClearData() {
return isClearData;
}
public void setIsClearData(Boolean isClearData) {
this.isClearData = isClearData;
} - 布尔类型的变量,不用
is
前缀可以用
if
前缀private Boolean ifClearData = false;
public Boolean getIfClearData() {
return ifClearData;
}
public void setIfClearData(Boolean ifClearData) {
this.ifClearData = ifClearData;
} - 可以结合
@JsonProperty
来处理@JsonProperty("isClearData")
private Boolean isClearData = false;
总结
Spring MVC
对参数的绑定与转换,内容不同,采用的处理器也不同- form表单数据(application/x-www-form-urlencoded)
处理器:
ServletModelAttributeMethodProcessor
- JSON 数据 (application/json)
处理器:
RequestResponseBodyMethodProcessor
转换器:MappingJackson2HttpMessageConverter
- 多部分文件 (multipart/form-data)
处理器:
MultipartResolver
POJO
的布尔类型变量,不要加is
前缀命名不符合规范,集成第三方框架的时候就很容易出不好排查的问题
成不了规范的制定者,那就老老实实遵循规范!
来源:juejin.cn/post/7521642915278422070