本文将以 SpringBoot + MyBatis 为例,展示如何实现一个完整的 Controller → Service → Mapper 三层架构接口,并给出优化建议。

1. 功能背景

在表外贷款场景中,诉讼详情通常包括以下三类信息:

  1. 诉讼信息:案件基本情况

  2. 诉讼文件:相关文书、证据材料

  3. 诉讼流程记录:案件处理进展

因此,我们需要设计一个 详情接口,通过 loanId 关联查询,返回完整的诉讼信息。

2. Controller 层

@GetMapping("/lawsuit-detail")
@Operation(summary = "获得表外诉讼详细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('bank:loan-out-lawsuit:export')")
public CommonResult<?> getLoanoutlawsuit(@RequestParam("id") Long id) {
    return success(loanOutLawsuitService.loadInfo(id));
}
  • 路径:/lawsuit-detail

  • 请求参数:id(Long 类型)

  • 权限控制:bank:loan-out-lawsuit:export

  • 调用 Service 查询详情并返回

3. Service 层

    /**
     * 详情
     *
     * @return 详情
     */
    Map<String, Object> loadInfo(Long id);
@Override
public Map<String, Object> loadInfo(Long id) {
    Map<String, Object> map = new HashMap<>();
    map.put("lawsuit", loanOutLawsuitMapper.getByLoanId(id));         // 诉讼信息
    map.put("lawsuitFile", loanOutLawsuitFileMapper.getByLoanId(id)); // 文件信息
    map.put("lawsuitRecord", loanOutLawsuitRecordMapper.getByLoanId(id)); // 流程记录
    return map;
}
  • loadInfo 方法整合三类数据

  • 返回 Map<String, Object>,前端可以直接展示

返回结果示例:

{
  "lawsuit": [ {...} ],
  "lawsuitFile": [ {...} ],
  "lawsuitRecord": [ {...} ]
}

4. Mapper 层

LoanOutLawsuitMapper 为例:

@Mapper
public interface LoanOutLawsuitMapper extends BaseMapperX<LoanOutLawsuitDO> {

    @Select("<script>" +
            "SELECT m.* " +
            "FROM ux_loan_out_lawsuit m " +
            "WHERE m.deleted = 0 " +
            "AND m.loan_id = #{loanId} " +
            "ORDER BY m.id " +
            "</script>")
    List<LoanOutLawsuitRespVO> getByLoanId(@Param("loanId") Long loanId);

}
  • 关联表:ux_loan_out_lawsuit

  • 条件:loan_id = #{loanId} 且未删除

  • 返回结果:LoanOutLawsuitRespVO 列表


5. VO 代码

以 LoanOutLawsuitRespVO为例:

@Schema(description = "管理后台 - 表外贷款-诉讼信息 Response VO")
@Data
@ExcelIgnoreUnannotated
public class LoanOutLawsuitRespVO {

    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "7238")
    @ExcelProperty("ID")
    private Long id;

    @Schema(description = "客户ID", example = "22593")
    @ExcelProperty("客户ID")
    private Long custId;

    @Schema(description = "客户编号")
    @ExcelProperty("客户编号")
    private String custCode;

    @Schema(description = "客户名称", example = "张三")
    @ExcelProperty("客户名称")
    private String custName;

    @Schema(description = "贷款ID", example = "4169")
    @ExcelProperty("贷款ID")
    private Long loanId;

    @Schema(description = "贷款账号")
    @ExcelProperty("贷款账号")
    private String loanCode;

    @Schema(description = "立案法院")
    @ExcelProperty("立案法院")
    private String court;

    @Schema(description = "立案号")
    @ExcelProperty("立案号")
    private String lawsuitCode;

    @Schema(description = "涉案金额")
    @ExcelProperty("涉案金额")
    private BigDecimal amount;

    @Schema(description = "担保人", example = "李四")
    @ExcelProperty("担保人")
    private String guarantName;

    @Schema(description = "担保金额")
    @ExcelProperty("担保金额")
    private BigDecimal guarantAmount;

    @Schema(description = "代理人")
    @ExcelProperty("代理人")
    private String agentor;

    @Schema(description = "代理日期")
    @ExcelProperty("代理日期")
    private String agentDate;

    @Schema(description = "代理期限")
    @ExcelProperty("代理期限")
    private LocalDateTime agentClosingDate;

    @Schema(description = "审理状态(0起诉中,1已开庭,2已判决,3已执行,4已和解)")
    @ExcelProperty(value = "审理状态", converter = DictConvert.class)
    @DictFormat("ux_trial_status")
    private Integer hearStatus;

    @Schema(description = "备注说明", example = "你说的对")
    @ExcelProperty("备注说明")
    private String remark;

    @Schema(description = "图片信息")
    @ExcelProperty("图片信息")
    private String imgs;

    @Schema(description = "主办客户经理", example = "王五")
    @ExcelProperty("主办客户经理")
    private String userName;

    @Schema(description = "客户经理ID(用户ID)", example = "32458")
    @ExcelProperty("客户经理ID(用户ID)")
    private Long userId;

    @Schema(description = "机构名称", example = "李四")
    @ExcelProperty("机构名称")
    private String deptName;

    @Schema(description = "机构id(部门ID)", example = "23013")
    @ExcelProperty("机构id(部门ID)")
    private Long deptId;

    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;

    @Schema(description = "担保方式(1保证,2抵押,3信用,4质押)", example = "2")
    @ExcelProperty(value = "担保方式", converter = DictConvert.class)
    @DictFormat("ux_guarant_type")
    private Integer guarantType;
}

关键点解析

1 Swagger 注解

  • @Schema
    用于接口文档生成,前端能直接看到字段说明、示例。

2 EasyExcel 注解

  • @ExcelProperty("字段名")
    用于导出 Excel 时的列标题。

  • @ExcelIgnoreUnannotated
    忽略未标注的字段,避免导出多余字段。

3 字典转换

  • @DictFormat("ux_trial_status")
    指定字典类型,例如审理状态(起诉中、已开庭…)。

  • @DictConvert
    用于导出 Excel 时自动把字典值转成文字。

4 Lombok 简化

  • @Data 自动生成 Getter/Setter/ToString/Equals/HashCode。


 设计思路

  1. Controller 调用 Service 返回 VO 对象

  2. Service 调用 Mapper 查询数据库结果,并封装成 VO

  3. VO 层 统一管理返回字段,便于维护

  4. 支持 Swagger 接口文档、EasyExcel 导出、字典转换,一次性解决多种需求

通过一个 LoanOutLawsuitRespVO,我们实现了:

✅ 接口文档自动生成(Swagger)
✅ Excel 导出支持(EasyExcel)
✅ 字典值自动转换(DictFormat + DictConvert)
✅ 返回对象规范化(VO 层解耦)

这种设计方式,既满足了业务需求,也大幅度提高了代码可维护性和前后端协作效率。

7. 总结

本文展示了一个 表外贷款诉讼详情接口 的完整实现流程,涉及:

  • Controller 接口设计

  • Service 聚合查询

  • Mapper SQL 编写

         给出了 VO 重构 方案。

这样的设计更符合 DDD 分层思想,同时也方便前后端联调与接口文档生成。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐