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

如何在Spring Boot REST API多模块中复用同一模型类

这是Spring Boot中复用REST请求模型非常典型的场景,我结合你的需求给出几个落地性强的方案,你可以根据实际场景选择:

方案1:泛型封装通用请求结构(最推荐)

核心思路是把固定的公共字段(query)和可变的参数部分(variables)拆分,用泛型来适配不同的参数结构,既保证类型安全,又能最大化复用。

步骤1:定义通用请求父类

创建一个泛型类来封装所有请求都有的query和泛型类型的variables:

import lombok.Data;

@Data
public class GenericGraphQLRequest<T> {
    private String query;
    private T variables;
}

这里用了Lombok的@Data来简化getter/setter/toString等方法,如果你没用到Lombok,手动生成这些方法即可。

步骤2:定义各接口专属的Variables类

针对你给出的3种请求场景,分别创建对应的Variables模型:

// 对应第一个请求:包含input(name/description/gitUrl/repoName)
@Data
public class CreateRepoVariables {
    private RepoInput input;

    @Data
    public static class RepoInput {
        private String name;
        private String description;
        private String gitUrl;
        private String repoName;
    }
}

// 对应第二个请求:包含input(仅name)
@Data
public class UpdateNameVariables {
    private NameInput input;

    @Data
    public static class NameInput {
        private String name;
    }
}

// 对应第三个请求:包含search字段
@Data
public class SearchVariables {
    private String search;
}

步骤3:在接口中使用泛型请求类

在你的Controller方法里,直接指定对应的泛型类型即可:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RepoController {

    @PostMapping("/create-repo")
    public String createRepo(@RequestBody GenericGraphQLRequest<CreateRepoVariables> request) {
        // 可以直接获取query和variables里的参数
        String query = request.getQuery();
        String repoName = request.getVariables().getInput().getRepoName();
        // 业务逻辑...
        return "Created repo: " + repoName;
    }

    @PostMapping("/update-name")
    public String updateName(@RequestBody GenericGraphQLRequest<UpdateNameVariables> request) {
        String name = request.getVariables().getInput().getName();
        // 业务逻辑...
        return "Updated name to: " + name;
    }

    @PostMapping("/search")
    public String search(@RequestBody GenericGraphQLRequest<SearchVariables> request) {
        String searchKeyword = request.getVariables().getSearch();
        // 业务逻辑...
        return "Searching for: " + searchKeyword;
    }
}

这样每个接口只需要关注自己需要的参数结构,公共的query字段完全复用,而且Spring Boot的Jackson会自动正确解析JSON请求体。

方案2:Jackson多态处理(适用于复杂多类型场景)

如果你的场景更复杂(比如同一个接口可能接收多种不同的variables结构),可以用Jackson的多态注解来实现动态类型解析。

步骤1:定义Variables父类并添加多态注解

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;

@Data
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type" // 通过type字段来区分不同的variables类型
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = CreateRepoVariables.class, name = "create"),
        @JsonSubTypes.Type(value = UpdateNameVariables.class, name = "update"),
        @JsonSubTypes.Type(value = SearchVariables.class, name = "search")
})
public abstract class BaseVariables {
    // 公共字段可以放在这里,如果有的话
}

步骤2:让各Variables类继承父类

比如修改CreateRepoVariables:

@Data
public class CreateRepoVariables extends BaseVariables {
    private RepoInput input;

    @Data
    public static class RepoInput {
        private String name;
        private String description;
        private String gitUrl;
        private String repoName;
    }
}

其他两个类同理继承BaseVariables。

步骤3:接口中使用父类接收请求

@PostMapping("/multi-operation")
public String multiOperation(@RequestBody GenericGraphQLRequest<BaseVariables> request) {
    BaseVariables variables = request.getVariables();
    if (variables instanceof CreateRepoVariables) {
        // 处理创建逻辑
    } else if (variables instanceof UpdateNameVariables) {
        // 处理更新逻辑
    } else if (variables instanceof SearchVariables) {
        // 处理搜索逻辑
    }
    return "Operation completed";
}

这种方式适合同一个接口需要处理多种请求类型的场景,但需要在请求JSON中额外添加type字段来标识类型,比如:

{
  "query": "",
  "variables": {
    "type": "create",
    "input": {
      "name": "",
      "description": "",
      "gitUrl": "",
      "repoName": ""
    }
  }
}
方案3:使用Map作为Variables类型(快速原型不推荐生产)

如果只是快速搭建原型,不想创建太多类,可以直接用Map<String, Object>作为variables的类型:

@Data
public class SimpleGraphQLRequest {
    private String query;
    private Map<String, Object> variables;
}

然后在接口中获取参数:

@PostMapping("/quick-test")
public String quickTest(@RequestBody SimpleGraphQLRequest request) {
    String search = (String) request.getVariables().get("search");
    // 注意:这里需要手动强转,类型不安全,容易出现ClassCastException
    return "Search keyword: " + search;
}

这种方式优点是快速,不需要创建多个模型类,但缺点很明显:类型不安全、没有参数校验、可读性差,不推荐在生产环境使用。

总结
  • 如果是不同接口对应不同参数结构,方案1的泛型封装是最优选择,兼顾类型安全和复用性;
  • 如果是同一个接口需要处理多种参数类型,方案2的多态处理更合适;
  • 方案3仅适合快速原型验证,生产环境不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:53:41