You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java过滤对象null空值 优化Spring Boot接口重复判空逻辑

重复判空代码优化方案

你当前遇到的大量重复null判断是动态搜索接口非常常见的问题,有几种成熟的简化方案,按需选择即可。

方案1:封装非空条件提取+逻辑映射,彻底消除重复if

这个方案完全匹配你提到的「提取非空字段为独立结构」的思路,把判空逻辑和字段处理逻辑解耦:

  1. 首先在SearchRequest类内部封装非空字段提取方法,把所有已赋值的搜索条件统一返回,不用在Controller层挨个判断:

    • 如果不想用反射,可以直接用Optional手动收集,逻辑完全可控:
    public class SearchRequest {
        // 原有字段、getter/setter省略
    
        /**
         * 提取所有非空的搜索条件
         * @return key为字段名,value为对应字段值
         */
        public Map<String, Object> getNonNullConditions() {
            Map<String, Object> conditions = new HashMap<>();
            Optional.ofNullable(type).ifPresent(v -> conditions.put("type", v));
            Optional.ofNullable(brand).ifPresent(v -> conditions.put("brand", v));
            Optional.ofNullable(date).ifPresent(v -> conditions.put("date", v));
            Optional.ofNullable(country).ifPresent(v -> conditions.put("country", v));
            Optional.ofNullable(client).ifPresent(v -> conditions.put("client", v));
            Optional.ofNullable(airco).ifPresent(v -> conditions.put("airco", v));
            Optional.ofNullable(transmission).ifPresent(v -> conditions.put("transmission", v));
            Optional.ofNullable(seats).ifPresent(v -> conditions.put("seats", v));
            return conditions;
        }
    }
    
    • 如果后续字段加的多,嫌手动写put麻烦,也可以用反射遍历类字段自动收集,几个字段的场景下反射性能损耗完全可以忽略。
  2. 把每个字段对应的处理逻辑提前注册到映射表中,不用在接口方法里堆if:

    @RestController
    public class CarSearchController {
        // 字段名 -> 对应处理逻辑的映射
        private final Map<String, Consumer<Object>> fieldHandlerMap = new HashMap<>();
    
        @PostConstruct
        public void initHandlers() {
            fieldHandlerMap.put("type", val -> {
                // 原代码中type非空时的dosomething逻辑,val就是searchRequest.getType()的值
            });
            fieldHandlerMap.put("brand", val -> {
                // 原代码中brand非空时的dosomething逻辑
            });
            fieldHandlerMap.put("country", val -> {
                // 原代码中country非空时的dosomething逻辑
            });
            // 其余字段照着注册即可
        }
    
        // 原有依赖注入省略
        @PostMapping("/searchCarOptions")
        public ResponseEntity<Cars> search(
                @Parameter(description = "some searchRequest") @RequestBody SearchRequest searchRequest) {
            // 遍历所有非空条件,执行对应处理逻辑
            searchRequest.getNonNullConditions().forEach((fieldName, val) -> {
                Optional.ofNullable(fieldHandlerMap.get(fieldName))
                        .ifPresent(handler -> handler.accept(val));
            });
            return ResponseEntity.ok(someService.search(searchRequest));
        }
    }
    

    后续新增搜索字段时,只需要在SearchRequest加对应字段、在getNonNullConditions加收集逻辑、在handlerMap注册对应处理逻辑即可,不用再改接口主流程代码,整洁度提升非常明显。

方案2:持久层框架自带动态查询,无需手写判空

如果你写这堆if判断本质是为了拼接数据库查询条件,完全没必要自己在Controller层做判空,主流持久层框架都自带动态条件拼接能力,自动忽略null值字段:

  • 用MyBatis-Plus的话,直接在Service层用条件构造器,第一个参数传判空表达式,为true才会拼接对应SQL条件:
    public Page<Car> search(SearchRequest req) {
        LambdaQueryWrapper<Car> wrapper = Wrappers.lambdaQuery(Car.class)
                .eq(req.getType() != null, Car::getType, req.getType())
                .eq(req.getBrand() != null, Car::getBrand, req.getBrand())
                .eq(req.getCountry() != null, Car::getCountry, req.getCountry())
                .eq(req.getClient() != null, Car::getClient, req.getClient())
                .eq(req.getAirco() != null, Car::getAirco, req.getAirco())
                .eq(req.getTransmission() != null, Car::getTransmission, req.getTransmission())
                .eq(req.getSeats() != null, Car::getSeats, req.getSeats())
                .eq(req.getDate() != null, Car::getProduceDate, req.getDate());
        return carMapper.selectPage(req.getPage(), wrapper);
    }
    
  • 用Spring Data JPA的话可以搭配Querydsl或者Specification实现动态查询,同样自动处理null条件,不用手写判空。

方案3:最小改动写法,不调整原有结构

如果你不想大改现有代码结构,只是想简化判空写法,可以直接用Optional的ifPresent方法替换原生的if (xx != null)写法,视觉上会整洁很多:

@PostMapping("/searchCarOptions")
public ResponseEntity<Cars> search(
        @Parameter(description = "some searchRequest") @RequestBody SearchRequest searchRequest) {
    Optional.ofNullable(searchRequest.getType()).ifPresent(val -> {
        // dosomething
    });
    Optional.ofNullable(searchRequest.getBrand()).ifPresent(val -> {
        // dosomething
    });
    Optional.ofNullable(searchRequest.getCountry()).ifPresent(val -> {
        // dosomething
    });
    // 其余字段同理
    return ResponseEntity.ok(someService.search(searchRequest));
}

注意:如果字段除了非空判断,还要做空字符串、空集合的校验,可以把判断逻辑抽成通用工具方法,不用每个地方重复写判断规则。

内容的提问来源于stack exchange,提问作者mesut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 08:45:32