28 KiB
28 KiB
后端代码生成参考
本文档包含 SpringBlade 开源版后端各层的完整代码模板。所有模板均来源于 SpringBlade 开源工程真实业务代码(参考 modules/system、modules/desk 及 Cloud 的 blade-service/blade-system 等)。
目录
- 一、Entity 实体类
- 二、DTO 数据传输对象
- 三、VO 视图对象
- 四、Excel 导出类
- 五、Mapper 接口
- 六、Mapper XML
- 七、Service 接口
- 八、ServiceImpl 实现
- 九、Controller 控制器
- 十、Wrapper 数据转换器
- 十一、Feign Client 接口(Cloud)
- 十二、Feign Client 实现(Cloud)
一、Entity 实体类
开源版 Entity 命名不带
Entity后缀(如User.java、Post.java、Notice.java)。
模式A:TenantEntity(多租户业务表,默认)
package org.springblade.modules.{module}.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.TenantEntity;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* {中文名}实体类
*
* @author {author}
*/
@Data
@TableName("blade_{table_name}")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "{中文名}")
public class {Name} extends TenantEntity {
/**
* {字段注释}
*/
@Schema(description = "{字段注释}")
private {Type} {fieldName};
// --- 字段类型注解模式 ---
// Long 类型字段(防止前端精度丢失)
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "关联ID")
private Long refId;
// Date 类型字段
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "发布时间")
private Date releaseTime;
// Integer 字典字段(配合 Wrapper 翻译)
@Schema(description = "分类")
private Integer category;
// String 普通文本
@Schema(description = "标题")
private String title;
// String 大文本
@Schema(description = "内容")
private String content;
}
TenantEntity 自动继承的字段(不需要在子类中声明):
id(Long) - 主键,@TableId(type = IdType.ASSIGN_ID),雪花 IDtenantId(String) - 租户 IDcreateUser(Long) - 创建人createDept(Long) - 创建部门createTime(Date) - 创建时间updateUser(Long) - 更新人updateTime(Date) - 更新时间status(Integer) - 业务状态,默认 1isDeleted(Integer) - 逻辑删除标记,@TableLogic,默认 0
模式B:BaseEntity(跨租户业务表)
package org.springblade.modules.{module}.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
/**
* {中文名}实体类
*
* @author {author}
*/
@Data
@TableName("blade_{table_name}")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "{中文名}")
public class {Name} extends BaseEntity {
@Schema(description = "{字段注释}")
private {Type} {fieldName};
}
BaseEntity 继承字段:与 TenantEntity 相同但不含 tenantId。
模式C:Raw Serializable(原生模式)
package org.springblade.modules.{module}.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* {中文名}实体类
*
* @author {author}
*/
@Data
@TableName("blade_{table_name}")
@Schema(description = "{中文名}")
public class {Name} implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "主键id")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
// --- 业务字段 ---
@Schema(description = "{字段注释}")
private {Type} {fieldName};
// --- 审计字段(手动定义) ---
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "创建人", hidden = true)
private Long createUser;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "创建部门", hidden = true)
private Long createDept;
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "创建时间", hidden = true)
private Date createTime;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "更新人", hidden = true)
private Long updateUser;
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "更新时间", hidden = true)
private Date updateTime;
@Schema(description = "业务状态", hidden = true)
private Integer status;
@TableLogic
@Schema(description = "是否已删除", hidden = true)
private Integer isDeleted;
}
Cloud 版本 Entity 差异
Cloud 中 Entity 放在 API 模块,包名不同:
// Boot
package org.springblade.modules.{module}.entity;
// Cloud
package org.springblade.{module}.entity;
其余代码完全相同。
二、DTO 数据传输对象
标准 DTO(继承 Entity)
package org.springblade.modules.{module}.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.modules.{module}.entity.{Name};
/**
* {中文名}数据传输对象
*
* @author {author}
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class {Name}DTO extends {Name} {
}
大多数情况下 DTO 为空类,仅作为扩展点。如有特定传输需求可添加字段。
精简 DTO(仅特定字段)
package org.springblade.modules.{module}.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* {中文名}数据传输对象
*
* @author {author}
*/
@Data
public class {Name}DTO implements Serializable {
@Schema(description = "特定字段")
private String specificField;
}
三、VO 视图对象
标准 VO(简单扩展)
package org.springblade.modules.{module}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.modules.{module}.entity.{Name};
/**
* {中文名}视图对象
*
* @author {author}
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class {Name}VO extends {Name} {
/**
* 分类名称(由 Wrapper 通过字典翻译填充)
*/
@Schema(description = "分类名称")
private String categoryName;
}
对于每个需要字典翻译的字段,在 VO 中添加对应的 {字段名}Name 字段。
树形 VO(实现 INode 接口)
用于 Menu、Dict、Dept 等树形结构:
package org.springblade.modules.{module}.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.tool.node.INode;
import org.springblade.modules.{module}.entity.{Name};
import java.util.ArrayList;
import java.util.List;
/**
* {中文名}视图对象(树形)
*
* @author {author}
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class {Name}VO extends {Name} implements INode<{Name}VO> {
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "主键ID")
private Long id;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "父节点ID")
private Long parentId;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Schema(description = "子节点")
private List<{Name}VO> children;
@Schema(description = "是否有子节点")
private Boolean hasChildren;
@Schema(description = "上级名称")
private String parentName;
@Override
public List<{Name}VO> getChildren() {
if (this.children == null) {
this.children = new ArrayList<>();
}
return this.children;
}
}
四、Excel 导出类
package org.springblade.modules.{module}.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serializable;
/**
* {中文名}导出对象
*
* @author {author}
*/
@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class {Name}Excel implements Serializable {
@ExcelProperty("{字段中文名}")
private {Type} {fieldName};
// 不导出审计字段(createUser、createTime 等)
}
开源版使用 FastExcel(
cn.idev.excel.*,由blade-starter-excel引入)。
五、Mapper 接口
package org.springblade.modules.{module}.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.excel.{Name}Excel;
import org.springblade.modules.{module}.vo.{Name}VO;
import java.util.List;
/**
* {中文名} Mapper 接口
*
* @author {author}
*/
public interface {Name}Mapper extends BaseMapper<{Name}> {
/**
* 自定义分页查询
*/
List<{Name}VO> select{Name}Page(IPage page, {Name}VO {modelCode});
/**
* 导出数据查询
*/
List<{Name}Excel> export{Name}(@Param("ew") Wrapper<{Name}> queryWrapper);
}
树形模板追加方法:
/**
* 树形结构查询
*/
List<{Name}VO> tree(String tenantId);
六、Mapper XML
标准 CRUD
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.modules.{module}.mapper.{Name}Mapper">
<!-- 通用查询映射结果 -->
<resultMap id="{modelCode}ResultMap" type="org.springblade.modules.{module}.entity.{Name}">
<result column="id" property="id"/>
<!-- 每个业务字段一行映射 -->
<result column="{column_name}" property="{fieldName}"/>
<!-- 审计字段映射(TenantEntity 模式需要) -->
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<!-- 自定义分页查询 -->
<select id="select{Name}Page" resultMap="{modelCode}ResultMap">
SELECT
t.*,
d.dict_value AS categoryName
FROM blade_{table_name} t
LEFT JOIN (SELECT * FROM blade_dict WHERE code = '{dictCode}') d
ON t.category = d.dict_key
WHERE t.is_deleted = 0
<if test="{modelCode}.tenantId != null and {modelCode}.tenantId != ''">
AND t.tenant_id = #{{{modelCode}.tenantId}}
</if>
<!-- 动态查询条件 -->
<if test="{modelCode}.{queryField} != null and {modelCode}.{queryField} != ''">
AND t.{query_column} LIKE CONCAT('%', #{{{modelCode}.{queryField}}}, '%')
</if>
<if test="{modelCode}.{eqField} != null">
AND t.{eq_column} = #{{{modelCode}.{eqField}}}
</if>
</select>
<!-- 导出查询 -->
<select id="export{Name}" resultType="org.springblade.modules.{module}.excel.{Name}Excel">
SELECT * FROM blade_{table_name}
${ew.customSqlSegment}
</select>
</mapper>
注意事项:
- 如果有字典关联查询,在 select 中 LEFT JOIN blade_dict 表
- 动态条件中
LIKE用于模糊查询字段,=用于精确查询字段 - TenantEntity 模式需要
tenant_id过滤条件 - resultMap 中每个数据库列名(snake_case)映射到 Java 属性(camelCase)
七、Service 接口
TenantEntity / BaseEntity 模式
package org.springblade.modules.{module}.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.vo.{Name}VO;
/**
* {中文名} 服务接口
*
* @author {author}
*/
public interface I{Name}Service extends BaseService<{Name}> {
/**
* 自定义分页
*/
IPage<{Name}VO> select{Name}Page(IPage<{Name}VO> page, {Name}VO {modelCode});
}
Raw Serializable 模式
package org.springblade.modules.{module}.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.modules.{module}.entity.{Name};
/**
* {中文名} 服务接口
*
* @author {author}
*/
public interface I{Name}Service extends IService<{Name}> {
}
八、ServiceImpl 实现
TenantEntity / BaseEntity 模式
package org.springblade.modules.{module}.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.mapper.{Name}Mapper;
import org.springblade.modules.{module}.service.I{Name}Service;
import org.springblade.modules.{module}.vo.{Name}VO;
import org.springframework.stereotype.Service;
/**
* {中文名} 服务实现
*
* @author {author}
*/
@Service
public class {Name}ServiceImpl extends BaseServiceImpl<{Name}Mapper, {Name}> implements I{Name}Service {
@Override
public IPage<{Name}VO> select{Name}Page(IPage<{Name}VO> page, {Name}VO {modelCode}) {
{modelCode}.setTenantId(AuthUtil.getTenantId());
return page.setRecords(baseMapper.select{Name}Page(page, {modelCode}));
}
}
注意:BaseEntity 模式下不需要 setTenantId() 那行。
Raw Serializable 模式
package org.springblade.modules.{module}.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.mapper.{Name}Mapper;
import org.springblade.modules.{module}.service.I{Name}Service;
import org.springframework.stereotype.Service;
/**
* {中文名} 服务实现
*
* @author {author}
*/
@Service
public class {Name}ServiceImpl extends ServiceImpl<{Name}Mapper, {Name}> implements I{Name}Service {
}
九、Controller 控制器
Boot 版本
package org.springblade.modules.{module}.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.RoleConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.service.I{Name}Service;
import org.springblade.modules.{module}.vo.{Name}VO;
import org.springblade.modules.{module}.wrapper.{Name}Wrapper;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* {中文名} 控制器
*
* @author {author}
*/
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_{MODULE}_NAME + "/{modelCode}")
@Tag(name = "{中文名}", description = "{中文名}接口")
public class {Name}Controller extends BladeController {
private final I{Name}Service {modelCode}Service;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入{modelCode}")
public R<{Name}VO> detail({Name} {modelCode}) {
{Name} detail = {modelCode}Service.getOne(Condition.getQueryWrapper({modelCode}));
return R.data({Name}Wrapper.build().entityVO(detail));
}
/**
* 分页列表
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入{modelCode}")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
public R<IPage<{Name}VO>> list(@RequestParam Map<String, Object> {modelCode}, Query query) {
IPage<{Name}> pages = {modelCode}Service.page(
Condition.getPage(query),
Condition.getQueryWrapper({modelCode}, {Name}.class)
);
return R.data({Name}Wrapper.build().pageVO(pages));
}
/**
* 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "自定义分页", description = "传入{modelCode}")
public R<IPage<{Name}VO>> page({Name}VO {modelCode}, Query query) {
IPage<{Name}VO> pages = {modelCode}Service.select{Name}Page(Condition.getPage(query), {modelCode});
return R.data(pages);
}
/**
* 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入{modelCode}")
public R save(@Valid @RequestBody {Name} {modelCode}) {
return R.status({modelCode}Service.save({modelCode}));
}
/**
* 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入{modelCode}")
public R update(@Valid @RequestBody {Name} {modelCode}) {
return R.status({modelCode}Service.updateById({modelCode}));
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入{modelCode}")
public R submit(@Valid @RequestBody {Name} {modelCode}) {
return R.status({modelCode}Service.saveOrUpdate({modelCode}));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status({modelCode}Service.deleteLogic(Func.toLongList(ids)));
}
}
Cloud 版本差异
Cloud 版本仅以下几处不同:
// 1. 包名不同
package org.springblade.{module}.controller;
// 2. import 路径不同(Entity/VO/Service 都在 org.springblade.{module} 下)
import org.springblade.{module}.entity.{Name};
import org.springblade.{module}.vo.{Name}VO;
import org.springblade.{module}.service.I{Name}Service;
// 3. RequestMapping 不需要服务名前缀
@RequestMapping("/{modelCode}")
无 Wrapper 版本
如不使用 Wrapper,detail 和 list 方法简化为:
@GetMapping("/detail")
public R<{Name}> detail({Name} {modelCode}) {
{Name} detail = {modelCode}Service.getOne(Condition.getQueryWrapper({modelCode}));
return R.data(detail);
}
@GetMapping("/list")
public R<IPage<{Name}>> list(@RequestParam Map<String, Object> {modelCode}, Query query) {
IPage<{Name}> pages = {modelCode}Service.page(
Condition.getPage(query),
Condition.getQueryWrapper({modelCode}, {Name}.class)
);
return R.data(pages);
}
Raw Serializable 模式的 remove 方法
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status({modelCode}Service.removeBatchByIds(Func.toLongList(ids)));
}
权限注解使用规则
SpringBlade 开源版仅支持角色级权限:
| 场景 | 写法 |
|---|---|
| 仅管理员可访问(类级) | @PreAuth(RoleConstant.HAS_ROLE_ADMIN) 加在类上 |
| 仅管理员可访问(方法级) | @PreAuth(RoleConstant.HAS_ROLE_ADMIN) 加在方法上 |
| 隐藏 Swagger 文档 | @Hidden(来自 OpenAPI 3) |
| 全公开 | 不加任何权限注解 |
导出接口
@GetMapping("/export-{modelCode}")
@ApiOperationSupport(order = 8)
@Operation(summary = "导出数据", description = "传入{modelCode}")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
public void export{Name}(@RequestParam Map<String, Object> {modelCode}, HttpServletResponse response) {
QueryWrapper<{Name}> queryWrapper = Condition.getQueryWrapper({modelCode}, {Name}.class);
List<{Name}Excel> list = {modelCode}Service.export{Name}(queryWrapper);
ExcelUtil.export(response, "{中文名}数据", "{中文名}数据表", list, {Name}Excel.class);
}
十、Wrapper 数据转换器
package org.springblade.modules.{module}.wrapper;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.modules.system.cache.DictCache;
import org.springblade.modules.{module}.entity.{Name};
import org.springblade.modules.{module}.vo.{Name}VO;
/**
* {中文名}包装类,返回视图层所需的字段
*
* @author {author}
*/
public class {Name}Wrapper extends BaseEntityWrapper<{Name}, {Name}VO> {
public static {Name}Wrapper build() {
return new {Name}Wrapper();
}
@Override
public {Name}VO entityVO({Name} {modelCode}) {
{Name}VO {modelCode}VO = BeanUtil.copyProperties({modelCode}, {Name}VO.class);
// 字典翻译:将字典键值转换为可读名称
String categoryName = DictCache.getValue("{dictCode}", {modelCode}.getCategory());
{modelCode}VO.setCategoryName(categoryName);
return {modelCode}VO;
}
}
常见翻译模式:
// 1. 字典翻译
String categoryName = DictCache.getValue("{dictCode}", entity.getCategory());
// 2. 关联实体名称(通过缓存)
User user = UserCache.getUser(entity.getUserId());
if (Func.isNotEmpty(user)) {
vo.setUserName(user.getAccount());
}
// 3. 父节点名称(树形结构)
if (Func.equals(entity.getParentId(), BladeConstant.TOP_PARENT_ID)) {
vo.setParentName(BladeConstant.TOP_PARENT_NAME);
} else {
{Name} parent = {modelCode}Service.getById(entity.getParentId());
vo.setParentName(parent.getName());
}
树形 Wrapper 追加方法:
public List<{Name}VO> listNodeVO(List<{Name}> list) {
List<{Name}VO> collect = list.stream()
.map(entity -> BeanUtil.copyProperties(entity, {Name}VO.class))
.collect(Collectors.toList());
return ForestNodeMerger.merge(collect);
}
十一、Feign Client 接口(Cloud)
放在 API 模块中(blade-service-api/blade-{module}-api):
package org.springblade.{module}.feign;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.mp.support.BladePage;
import org.springblade.core.tool.api.R;
import org.springblade.{module}.entity.{Name};
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* {中文名} Feign 接口
*
* @author {author}
*/
@FeignClient(value = AppConstant.APPLICATION_{MODULE}_NAME)
public interface I{Name}Client {
String API_PREFIX = "/feign/client/{modelCode}";
String TOP = API_PREFIX + "/top";
/**
* 获取分页数据
*/
@GetMapping(TOP)
BladePage<{Name}> top(@RequestParam("current") Integer current, @RequestParam("size") Integer size);
}
十二、Feign Client 实现(Cloud)
放在 Service 模块中(blade-service/blade-{module}):
package org.springblade.{module}.feign;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.BladePage;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.{module}.entity.{Name};
import org.springblade.{module}.service.I{Name}Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* {中文名} Feign 实现
*
* @author {author}
*/
@Hidden
@RestController
@AllArgsConstructor
public class {Name}Client implements I{Name}Client {
private final I{Name}Service service;
@Override
@GetMapping(TOP)
public BladePage<{Name}> top(Integer current, Integer size) {
Query query = new Query();
query.setCurrent(current);
query.setSize(size);
IPage<{Name}> page = service.page(Condition.getPage(query));
return BladePage.of(page);
}
}
Feign 实现要点:
@Hidden:对 Swagger 文档隐藏(内部接口)@RestController:作为 HTTP 端点暴露- 路径常量复用接口中定义的常量
附:完整 import 参考
Entity 常用 import
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity; // BaseEntity
import org.springblade.core.mp.base.TenantEntity; // TenantEntity
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
Controller 常用 import
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.launch.constant.AppConstant; // Boot 路由前缀使用
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.RoleConstant;
import org.springblade.core.tool.utils.Func;
import org.springframework.web.bind.annotation.*;
Service 常用 import
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.stereotype.Service;
Wrapper 常用 import
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.node.ForestNodeMerger;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.cache.DictCache; // 字典缓存(Boot 路径)