抽象出一个通用的 CRUD 方法类,传入实体泛型即可使用,适用于单表操作,多表需要自行扩展。

在实训项目里面学到的,自己改进了一下代码。

@Slf4j
public abstract class AbstractCoreController<T> {

    private final IService<T> coreService;

    public AbstractCoreController(IService<T> coreService) {
        this.coreService = coreService;
    }

    /**
     * 删除记录
     */
    @ApiOperation(value = "删除")
    @DeleteMapping("/{id}")
    public Result<T> deleteById(@PathVariable(name = "id") Serializable id) {
        boolean flag = coreService.removeById(id);
        if (!flag) {
            return Result.error();
        }
        return Result.ok();
    }

    /**
     * 添加记录
     */
    @ApiOperation(value = "添加")
    @PostMapping
    public Result<T> insert(@RequestBody T record) {
        boolean flag = coreService.save(record);
        if (!flag) {
            return Result.error();
        }
        return Result.ok(record);
    }

    /**
     * 更新数据
     */
    @ApiOperation(value = "更新")
    @PutMapping
    public Result<T> updateByPrimaryKey(@RequestBody T record) {
        boolean flag = coreService.updateById(record);
        if (!flag) {
            return Result.error();
        }
        return Result.ok();
    }

    /**
     * 查询数据
     */
    @ApiOperation(value = "查询")
    @GetMapping("/{id}")
    public Result<T> findById(@PathVariable(name = "id") Serializable id) {
        T t = coreService.getById(id);
        return Result.ok(t);
    }

    /**
     * 查询所有数据
     */
    @ApiOperation(value = "查询所有")
    @GetMapping
    public Result<List<T>> findAll() {
        List<T> list = coreService.list();
        return Result.ok(list);
    }

    /**
     * 通用条件分页查询
     * @param pageRequestDto 通用条件
     */
    @ApiOperation(value = "分页条件")
    @PostMapping(value = "/search")
    public Result<PageInfo<T>> findByPage(@RequestBody PageRequestDto<T> pageRequestDto) {

        //构造分页条件
        IPage<T> page = new Page<>(pageRequestDto.getPage(), pageRequestDto.getSize());

        //条件查询 非 lamda表达式查询条件
        QueryWrapper<T> queryWrapper = getWrapper(pageRequestDto.getBody());

        //分页查询
        IPage<T> iPage = coreService.page(page, queryWrapper);

        //封装返回数据
        PageInfo<T> pageInfo = new PageInfo<>(iPage.getCurrent(), iPage.getSize(), iPage.getTotal(), iPage.getPages(), iPage.getRecords());
        return Result.ok(pageInfo);
    }

    /**
     * 根据body参数构建查询条件
     * @param body 查询参数
     */
    private QueryWrapper<T> getWrapper(T body) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<T>();

        if (body == null) {
            return queryWrapper;
        }

        Field[] declaredFields = body.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            try {
                //遇到 id注解 则直接跳过 不允许实现根据主键查询
                //https://www.coder.work/article/2808807
                if (declaredField.isAnnotationPresent(TableId.class) || "serialVersionUID".equals(declaredField.getName())) {
                    // 遇到 id
                    continue;
                }
                //属性描述器  record.getClass()
                PropertyDescriptor propDesc = new PropertyDescriptor(declaredField.getName(), body.getClass());
                //获取这个值  先获取读方法的方法对象,并调用获取里面的值
                Object value = propDesc.getReadMethod().invoke(body);
                //查询变量的 @TableField 注解)
                TableField annotation = declaredField.getAnnotation(TableField.class);
                //如果传递的值为空则不做处理
                if (value != null && annotation != null) {
                    //如是字符串 则用like
                    if ("java.lang.String".equals(value.getClass().getName())) {
                        queryWrapper.like(annotation.value(), value);
                    } else {
                        //否则使用=号
                        queryWrapper.eq(annotation.value(), value);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getCause().getLocalizedMessage());
            }
        }
        return queryWrapper;
    }
}

让你的 controller 继承这个抽象类,传入 service 即可。

@RestController
@RequestMapping(value = "/user")
@Api(value = "UserController", tags = "用户管理")
public class UserController extends AbstractCoreController<User> {

    private final UserService userService;

    //@Autowired
    public UserController(UserService userService) {
        super(userService);
        this.userService = userService;
    }

    @ApiOperation(value = "获得前三个用户")
    @GetMapping("/three")
    public Result<List<User>> getThree() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>();
        userQueryWrapper.last("limit 3");
        List<User> userList = userService.list(userQueryWrapper);
        return Result.ok(userList);
    }
}

老师给的资料有一些通用的封装类,看起来还不错,修修改改复制过来备用。

PageInfo,通用返回分页结果对象

@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "通用返回分页结果对象", value = "result")
public class PageInfo<T> implements Serializable {
    //当前页码
    @ApiModelProperty(notes = "当前页", required = true)
    private Long page;
    //每页显示行
    @ApiModelProperty(notes = "每页显示的条数", required = true)
    private Long size;
    //总记录数
    @ApiModelProperty(notes = "总记录数", required = true)
    private Long total;
    //总页数
    @ApiModelProperty(notes = "总页数", required = true)
    private Long totalPages;
    //当前页记录
    @ApiModelProperty(notes = "响应的数据结果集", required = false)
    private List<T> list;
}

PageRequestDto,分页查询对象

@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(description = "分页查询对象", value = "PageRequestDto")
public class PageRequestDto<T> implements Serializable {
    //当前页码
    @ApiModelProperty(notes = "当前页码", required = false)
    private Long page = 1L;
    //每页显示的行
    @ApiModelProperty(notes = "每页显示的行", required = false)
    private Long size = 10L;
    //请求体实体对象
    @ApiModelProperty(notes = "请求体实体对象", required = false)
    private T body;
}

StatusCode,枚举类状态码

public enum StatusCode {
    //区分与http状态码
    SUCCESS(20000, "操作成功"),
    PARAM_ERROR(40000, "参数异常"),
    NOT_FOUND(40004, "资源不存在"),
    FAILURE(50000, "系统异常"),
    CUSTOM_FAILURE(50001, "自定义异常错误");

    private final Integer code;
    private final String message;

    StatusCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    //获取状态码
    public Integer code() {
        return code;
    }

    //获取信息
    public String message() {
        return message;
    }

    @Override
    public String toString() {
        return String.valueOf(this.code);
    }
}

Result,通用返回响应结果对象

@Data
@ApiModel(description = "通用返回响应结果对象", value = "result")
public class Result<T> implements Serializable {

    @ApiModelProperty(notes = "响应结果的错误信息", required = true)
    private String message;
    @ApiModelProperty(notes = "响应结果的错误信息状态码,2000X表示成功,4000X表示错误,5000X表示服务端异常", required = true)
    private Integer code;
    @ApiModelProperty(notes = "响应结果逻辑数据", required = true)
    private T data;

    //成功 并不返回数据
    public static <T> Result<T> ok() {
        return new Result<T>(StatusCode.SUCCESS.message(), StatusCode.SUCCESS.code(), null);
    }

    //成功 并返回数据
    public static <T> Result<T> ok(T data) {
        return new Result<T>(StatusCode.SUCCESS.message(), StatusCode.SUCCESS.code(), data);
    }

    //系统错误 不返回数据
    public static <T> Result<T> error() {
        return new Result<T>(StatusCode.FAILURE.message(), StatusCode.FAILURE.code(), null);
    }

    //系统错误 并返回逻辑数据
    public static <T> Result<T> error(T data) {
        return new Result<T>(StatusCode.FAILURE.message(), StatusCode.FAILURE.code(), data);
    }

    //错误并返回指定错误信息和状态码以及逻辑数据
    public static <T> Result<T> error(StatusCode statusCode, T data) {
        return new Result<T>(statusCode.message(), statusCode.code(), data);
    }

    // 错误并返回指定错误信息和状态码 不返回数据
    public static <T> Result<T> error(StatusCode statusCode) {
        return new Result<T>(statusCode.message(), statusCode.code(), null);
    }

    //自定义错误和状态返回
    public static <T> Result<T> errorMessage(String message, Integer code, T data) {
        return new Result<T>(message, code, data);
    }

    //自定义错误信息 状态码固定
    public static <T> Result<T> errorMessage(String message) {
        return new Result<T>(message, StatusCode.CUSTOM_FAILURE.code(), null);
    }
    
    public Result(String message, Integer code, T data) {
        this.message = message;
        this.code = code;
        this.data = data;
    }
}

Last modification:June 23, 2021
如果觉得我的文章对你有用,请随意赞赏