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

如何用Callable设计模式优化Spring Controller重复代码?

使用Callable(函数式编程)消除Spring Controller重复代码的可行方案

当然可行!你已经找对了方向——用函数式编程的思路把重复的「获取integId/orgId」逻辑抽离出来,让Controller方法只专注于请求本身的参数和业务调用。

先看看你原来的代码里的重复点:每个方法都要写一遍helper.getIntegId(request)和helper.getOrgId(request),这部分完全可以统一封装到一个通用执行方法里。下面是具体的实现方案:

首先,我们需要定义几个自定义的函数式接口(Java标准库没有现成的三元/四元函数接口),用来适配不同业务方法的参数需求:

// 三元函数接口:接收三个参数,返回一个结果
@FunctionalInterface
private interface TriFunction<T, U, V, R> {
    R apply(T t, U u, V v);
}

// 四元消费接口:接收四个参数,无返回值
@FunctionalInterface
private interface QuadConsumer<T, U, V, W> {
    void accept(T t, U u, V v, W w);
}

接下来,在你的Controller里实现几个重载的通用execute方法,负责统一获取integId和orgId,然后执行传入的业务逻辑:

// 适配无额外参数的业务方法(比如getUserRules)
private <T> ResponseEntity<?> execute(HttpServletRequest request, BiFunction<String, String, T> businessLogic) {
    String integId = helper.getIntegId(request);
    String orgId = helper.getOrgId(request);
    T result = businessLogic.apply(integId, orgId);
    return ResponseEntity.ok(result);
}

// 适配需要ruleId的查询方法(比如getRule)
private <T> ResponseEntity<?> execute(HttpServletRequest request, Long ruleId, TriFunction<String, String, Long, T> businessLogic) {
    String integId = helper.getIntegId(request);
    String orgId = helper.getOrgId(request);
    T result = businessLogic.apply(integId, orgId, ruleId);
    return ResponseEntity.ok(result);
}

// 适配需要ruleId和请求体的更新方法(比如updateRule)
private ResponseEntity<?> execute(HttpServletRequest request, Long ruleId, Object object, QuadConsumer<String, String, Long, Object> businessLogic) {
    String integId = helper.getIntegId(request);
    String orgId = helper.getOrgId(request);
    businessLogic.accept(integId, orgId, ruleId, object);
    return ApiResponse.ok();
}

现在,你原来的Controller方法就可以简化成这样,完全消除重复代码:

@GetMapping("")
public ResponseEntity<?> getUserRules(HttpServletRequest request) {
    return execute(request, service::getUserRules);
}

@GetMapping("/{ruleId}")
public ResponseEntity<?> getRule(HttpServletRequest request, @PathVariable Long ruleId) {
    return execute(request, ruleId, service::getRule);
}

@PutMapping("/{ruleId}")
public ResponseEntity<?> updateRule(HttpServletRequest request, @PathVariable Long ruleId, @RequestBody @Valid Object object) {
    return execute(request, ruleId, object, service::updateRule);
}

补充说明

  • 这里用了方法引用(service::getUserRules)让代码更简洁,如果你需要做额外的参数处理,也可以用lambda表达式代替,比如:(integId, orgId) -> service.someMethod(integId, orgId, otherParam)
  • 如果后续有更多参数的业务方法,可以继续扩展对应的函数式接口和execute重载方法,保持Controller的清爽
  • 这种方式本质是利用了函数式编程的「行为参数化」思想,和你提到的Callable设计模式思路一致——把可变的业务逻辑作为参数传入,固定的通用逻辑放在execute里统一处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:58:47