Springboot + Mybatis-Plus代码生成指南

使用 Spring Boot 和 MyBatis-Plus 生成代码,可以大大简化开发流程,可以保持编码的规范性,生成单元测试等。以下是详细步骤:

配置pom.xml

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

<!-- velocity-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency>

<!-- swagger-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.8.0</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.8.0</version>
</dependency>

<!-- 单元测试相关-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

配置数据库连接

在 src/main/resources/application.properties 或 application.yml 中配置数据库连接信息:

server:
    port: 8000
spring:
    application:
        name: ocean-code-generation
    jackson:
        date-format: yyyy-MM-dd HH:mm:ss
        time-zone: GMT+8
        deserialization.accept_empty_string_as_null_object: true
    datasource:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db-ocean?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        username: root
        password: 123456

    mvc:
        pathmatch:
            matching-strategy: ANT_PATH_MATCHER

mybatis-plus:
    mapper-locations: classpath*:mapper/*Mapper.xml
    configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

定义代码生成模版

模版代码目录截图:

在这里插入图片描述

核心代码

  1. controller.java.vm
package ${package.Controller};

import ${package.base_packages}.common.BaseController;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.RequestMapping;
import ${package.base_packages}.common.ApiResult;
import ${package.base_packages}.common.PageResult;
import ${package.base_packages}.domain.dto.${entity}DTO;
import ${package.base_packages}.domain.entity.${entity};
import ${package.base_packages}.domain.qo.${entity}QO;
import ${package.base_packages}.domain.vo.${entity}VO;
import ${package.base_packages}.service.${entity}Service;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;

/**
 1. $!{table.comment} 前端控制器
 2.  3. @author ${author}
 4. @time ${date}
 */
@Api(value = "$!{table.comment}接口", tags = {"$!{table.comment}相关接口"})
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")
public class ${table.controllerName} extends BaseController {

    @Resource
    private ${entity}Service service;

    @ApiOperation(value = "$!{table.comment}列表", notes = "$!{table.comment}列表", consumes = "application/json", produces = "application/json", httpMethod = "GET")
    @ApiResponses({@ApiResponse(code = 200, message = "OK"),
            @ApiResponse(code = 50000, message = "service exception")
    })
    @GetMapping("/list")
    public PageResult<${entity}VO> page(${entity}QO qo) {
        return service.page(qo);
    }

    @ApiOperation(value = "获取$!{table.comment}信息", notes = "获取$!{table.comment}信息", consumes = "application/json", produces = "application/json", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "$!{table.comment}ID", required = true)
    })
    @ApiResponses({@ApiResponse(code = 200, message = "OK", response = ${entity}.class),
            @ApiResponse(code = 50000, message = "service exception")
    })
    @GetMapping("/get/{id}")
    public ApiResult<${entity}> get(@PathVariable Long id) {
        ${entity} entity = service.getById(id);
        if(null == entity) {
            return ApiResult.error();
        }
        return ApiResult.success(entity);
    }

    @ApiOperation(value = "保存$!{table.comment}", notes = "保存$!{table.comment}", consumes = "application/json", produces = "application/json", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "OK"),
            @ApiResponse(code = 50000, message = "service exception")
    })
    @PostMapping("/save")
    public ApiResult<Long> save(@RequestBody ${entity}DTO dto) {
        return service.save(dto);
    }

    @ApiOperation(value = "更新$!{table.comment}", notes = "更新$!{table.comment}", consumes = "application/json", produces = "application/json", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "OK"),
            @ApiResponse(code = 50000, message = "service exception")
    })
    @PostMapping("/update")
    public ApiResult<Long> update(@RequestBody ${entity}DTO dto) {
        return service.update(dto);
    }

    @ApiOperation(value = "删除$!{table.comment}", notes = "删除$!{table.comment}", consumes = "application/json", produces = "application/json", httpMethod = "DELETE")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "$!{table.comment}ID", required = true)
    })
    @ApiResponses({@ApiResponse(code = 200, message = "OK"),
            @ApiResponse(code = 50000, message = "service exception")
    })
    @DeleteMapping("/delete/{id}")
    public ApiResult<Void> delete(@PathVariable Long id) {
        service.removeById(id);
        return ApiResult.success();
    }
}
  1. service.java.vm
package ${package.Service};

import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import ${package.qo_packages}.${entity}QO;
import ${package.vo_packages}.${entity}VO;
import ${package.dto_packages}.${entity}DTO;
import ${package.base_packages}.common.ApiResult;
import ${package.base_packages}.common.PageResult;

/**
 * $!{table.comment} 服务类
 *
 * @author ${author}
 * @time ${date}
 */
#if(${kotlin})
interface ${table.serviceName} : ${superServiceClass}<${entity}>
#else
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {

    /**
     * @desc 分页查询
     *
     * @param qo
     * @return ${package.base_packages}.common.PageResult<${package.vo_packages}.${entity}VO>
     */
    PageResult<${entity}VO> page(${entity}QO qo);

    /**
     * @desc 保存
     *
     * @param dto
     * @return ${package.base_packages}.common.ApiResult
     */
    ApiResult<Long> save(${entity}DTO dto);

    /**
     * @desc 更新
     *
     * @param dto
     * @return ${package.base_packages}.common.ApiResult
     */
    ApiResult<Long> update(${entity}DTO dto);

}
#end
  1. serviceImpl.java.vm
package ${package.ServiceImpl};

import cn.hutool.core.bean.BeanUtil;
import ${package.base_packages}.common.ApiResult;
import ${package.base_packages}.common.PageResult;
import ${package.base_packages}.constant.ResultCode;
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import ${package.qo_packages}.${entity}QO;
import ${package.vo_packages}.${entity}VO;
import ${package.dto_packages}.${entity}DTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;


/**
 1. $!{table.comment} 服务实现类
 2.  3. @author ${author}
 4. @time ${date}
 */
@Service
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {

    @Resource
    private ${entity}Mapper mapper;

    @Override
    public PageResult<${entity}VO> page(${entity}QO qo) {
        List<${entity}VO> data = mapper.list${entity}(qo);
        int total = mapper.count${entity}(qo);
        PageResult<${entity}VO> pageResult = PageResult.success(data, total);
        pageResult.setPageSize(qo.getPageSize());
        pageResult.setPageNum(qo.getPageNum());
        int pages = total % qo.getPageSize() == 0 ? total / qo.getPageSize() : total / qo.getPageSize() + 1;
        pageResult.setPages(pages);
        return pageResult;
    }

    @Override
    @Transactional
    public ApiResult<Long> save(${entity}DTO dto) {
        ${entity} entity = new ${entity}();
        BeanUtil.copyProperties(dto, entity);
        mapper.insert(entity);
        return ApiResult.success(entity.getId());
    }

    @Override
    @Transactional
    public ApiResult<Long> update(${entity}DTO dto) {
        if(null == dto.getId()) {
            return ApiResult.error(ResultCode.PARAM_ERROR);
        }
        ${entity} entity = new ${entity}();
        BeanUtil.copyProperties(dto, entity);
        mapper.updateById(entity);
        return ApiResult.success(entity.getId());
    }
}
  1. mapper.java.vm
package ${package.Mapper};

import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import ${package.qo_packages}.${entity}QO;
import ${package.vo_packages}.${entity}VO;
import java.util.List;
import org.apache.ibatis.annotations.Param;

/**
 1. $!{table.comment} Mapper
 2.  3. @author ${author}
 4. @time ${date}
 */
#if(${kotlin})
interface ${table.mapperName} : ${superMapperClass}<${entity}>
#else
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {

    /**
     * @desc $!{table.comment}列表
     *
     * @param qo
     * @return java.util.List<${package.vo_packages}.${entity}VO>
     */
    List<${entity}VO> list${entity}(@Param("qo") ${entity}QO qo);

    /**
     * @desc $!{table.comment}条数
     *
     * @param qo
     * @return int
     */
    int count${entity}(@Param("qo") ${entity}QO qo);
}
#end
  1. mapper.xml.vm
<?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="${package.Mapper}.${table.mapperName}">

#if(${enableCache})
    <!-- 开启二级缓存 -->
    <cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>

#end
#if(${baseResultMap})
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
#foreach($field in ${table.fields})
#if(${field.keyFlag})##生成主键排在第一位
        <id column="${field.name}" property="${field.propertyName}" />
#end
#end
#foreach($field in ${table.commonFields})##生成公共字段
        <result column="${field.name}" property="${field.propertyName}" />
#end
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
        <result column="${field.name}" property="${field.propertyName}" />
#end
#end
    </resultMap>

#end
#if(${baseColumnList})
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
#foreach($field in ${table.commonFields})
        ${field.columnName},
#end
        ${table.fieldNames}
    </sql>

    <select id="list${entity}" resultType="${package.vo_packages}.${entity}VO">
        SELECT
#foreach($field in ${table.commonFields})
        ${field.columnName},
#end
        ${table.fieldNames}
        FROM ${table.name}
        ORDER BY id DESC
        LIMIT #{qo.limit},#{qo.offset}
    </select>

    <select id="count${entity}" resultType="java.lang.Integer">
        SELECT count(*) FROM ${table.name}
    </select>

#end
</mapper>
  1. entity.java.vm
package ${package.Entity};

#if(${swagger2})
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#end
#if(${entityLombokModel})
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.io.Serializable;
#if(${chainModel})
import lombok.experimental.Accessors;
#end
#end

/**
 * $!{table.comment}
 *
 * @author ${author}
 * @time ${date}
 */
#if(${entityLombokModel})
@Data
  #if(${superEntityClass})
@EqualsAndHashCode(callSuper = true)
  #else
@EqualsAndHashCode(callSuper = false)
  #end
  #if(${chainModel})
@Accessors(chain = true)
  #end
#end
#if(${swagger2})
@ApiModel(value="${entity}", description="$!{table.comment}")
#end
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
#elseif(${activeRecord})
public class ${entity} extends Model<${entity}> {
#else
public class ${entity} implements Serializable {
#end

#if(${entitySerialVersionUID})
    private static final long serialVersionUID = 1L;
#end
## ----------  BEGIN 字段循环遍历  ----------
#foreach($field in ${table.fields})

#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
  #if(${swagger2})
    @ApiModelProperty(value = "${field.comment}")
  #else
    /**
     * ${field.comment}
     */
  #end
#end
#if(${field.keyFlag})
## 普通字段
#elseif(${field.fill})
## -----   存在字段填充设置   -----
  #if(${field.convert})
    @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
  #else
    @TableField(fill = FieldFill.${field.fill})
  #end
#elseif(${field.convert})
    @TableField("${field.annotationColumnName}")
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
    @Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
    @TableLogic
#end
    private ${field.propertyType} ${field.propertyName};
#end
## ----------  END 字段循环遍历  ----------

#if(!${entityLombokModel})
#foreach($field in ${table.fields})
  #if(${field.propertyType.equals("boolean")})
    #set($getprefix="is")
  #else
    #set($getprefix="get")
  #end

    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

  #if(${chainModel})
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
  #else
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
  #end
        this.${field.propertyName} = ${field.propertyName};
  #if(${chainModel})
        return this;
  #end
    }
#end
## --foreach end---
#end
## --end of #if(!${entityLombokModel})--

#if(${entityColumnConstant})
  #foreach($field in ${table.fields})
    public static final String ${field.name.toUpperCase()} = "${field.name}";

  #end
#end
#if(${activeRecord})
    @Override
    protected Serializable pkVal() {
  #if(${keyPropertyName})
        return this.${keyPropertyName};
  #else
        return null;
  #end
    }

#end
#if(!${entityLombokModel})
    @Override
    public String toString() {
        return "${entity}{" +
  #foreach($field in ${table.fields})
    #if($!{foreach.index}==0)
        "${field.propertyName}=" + ${field.propertyName} +
    #else
        ", ${field.propertyName}=" + ${field.propertyName} +
    #end
  #end
        "}";
    }
#end
}
  1. dto.java.vm
package ${package.dto_packages};

import java.util.Date;
#if(${swagger2})
import io.swagger.annotations.ApiModelProperty;
#end
import lombok.Data;
import java.io.Serializable;

/**
 * $!{table.comment}
 *
 * @author ${author}
 * @time ${date}
 */
@Data
public class ${entity}DTO implements Serializable {

    private static final long serialVersionUID = 1L;

## ----------  BEGIN 字段循环遍历  ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
    #set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
    #if(${swagger2})
    @ApiModelProperty(value = "${field.comment}")
    #else
    /**
     * ${field.comment}
     */
    #end
#end
#if(${field.fill})
    ## -----   存在字段填充设置   -----

#elseif(${field.convert})
@TableField("${field.annotationColumnName}")
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
@Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
    private ${field.propertyType} ${field.propertyName};

#end
## ----------  END 字段循环遍历  ----------

}
  1. qo.java.vm
package ${package.qo_packages};

import java.util.Date;
import ${package.base_packages}.common.PageDomain;
#if(${swagger2})
import io.swagger.annotations.ApiModelProperty;
#end
import lombok.Data;
import java.io.Serializable;

/**
 * $!{table.comment}
 *
 * @author ${author}
 * @time ${date}
 */
@Data
public class ${entity}QO extends PageDomain implements Serializable {

    private static final long serialVersionUID = 1L;

## ----------  BEGIN 字段循环遍历  ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
    #set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
    #if(${swagger2})
    @ApiModelProperty(value = "${field.comment}")
    #else
    /**
     * ${field.comment}
     */
    #end
#end
#if(${field.fill})
    ## -----   存在字段填充设置   -----

#elseif(${field.convert})
@TableField("${field.annotationColumnName}")
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
@Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
    private ${field.propertyType} ${field.propertyName};

#end
## ----------  END 字段循环遍历  ----------

}
  1. vo.java.vm
package ${package.vo_packages};

import java.util.Date;
#if(${swagger2})
import io.swagger.annotations.ApiModelProperty;
#end
import lombok.Data;
import java.io.Serializable;

/**
 * $!{table.comment}
 *
 * @author ${author}
 * @time ${date}
 */
@Data
public class ${entity}VO implements Serializable {

    private static final long serialVersionUID = 1L;

## ----------  BEGIN 字段循环遍历  ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
    #set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
    #if(${swagger2})
    @ApiModelProperty(value = "${field.comment}")
    #else
    /**
     * ${field.comment}
     */
    #end
#end
#if(${field.fill})
    ## -----   存在字段填充设置   -----

#elseif(${field.convert})
@TableField("${field.annotationColumnName}")
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
@Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
    private ${field.propertyType} ${field.propertyName};

#end
## ----------  END 字段循环遍历  ----------

}

单元测试代码

  1. controller.java.vm
package ${package.Controller};

import ${package.base_packages}.common.ApiResult;
import ${package.base_packages}.common.PageResult;
import ${package.base_packages}.domain.dto.${entity}DTO;
import ${package.base_packages}.domain.entity.${entity};
import ${package.base_packages}.domain.qo.${entity}QO;
import ${package.base_packages}.domain.vo.${entity}VO;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.alibaba.fastjson2.JSON;

@Slf4j
@SpringBootTest
class ${entity}ControllerTest {

    @Resource
    private ${entity}Controller controller;

    @Test
    void page() {
        ${entity}QO qo = new ${entity}QO();
        PageResult<${entity}VO> result = controller.page(qo);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void get() {
        Long id = 0L;
        ApiResult<${entity}> result = controller.get(id);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void save() {
        ${entity}DTO dto = new ${entity}DTO();
        ApiResult<?> result = controller.save(dto);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void update() {
        ${entity}DTO dto = new ${entity}DTO();
        ApiResult<?> result = controller.update(dto);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void delete() {
        Long id = 0L;
        ApiResult<?> result = controller.delete(id);
        log.info("{}", JSON.toJSONString(result));
    }
}
  1. service.java.vm
package ${package.Service};

import ${package.qo_packages}.${entity}QO;
import ${package.vo_packages}.${entity}VO;
import ${package.dto_packages}.${entity}DTO;
import ${package.base_packages}.common.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.alibaba.fastjson2.JSON;
import javax.annotation.Resource;

@Slf4j
@SpringBootTest
class ${entity}ServiceTest {

    @Resource
    private ${entity}Service service;

    @Test
    void page() {
        ${entity}QO qo = new ${entity}QO();
        PageResult<${entity}VO> result = service.page(qo);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void save() {
        ${entity}DTO dto = new ${entity}DTO();
        service.save(dto);
    }

    @Test
    void update() {
        ${entity}DTO dto = new ${entity}DTO();
        service.update(dto);
    }
}
  1. mapper.java.vm
package ${package.Mapper};

import ${package.qo_packages}.${entity}QO;
import ${package.vo_packages}.${entity}VO;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.alibaba.fastjson2.JSON;
import javax.annotation.Resource;

@Slf4j
@SpringBootTest
class ${entity}MapperTest {

    @Resource
    private ${entity}Mapper mapper;

    @Test
    void list${entity}() {
        ${entity}QO qo = new ${entity}QO();
        List<${entity}VO> result = mapper.list${entity}(qo);
        log.info("{}", JSON.toJSONString(result));
    }

    @Test
    void count${entity}() {
        ${entity}QO qo = new ${entity}QO();
        int result = mapper.count${entity}(qo);
        log.info("{}", result);
    }
}

其他使用到的类

package com.angel.ocean.common;

public class BaseController {

}
package com.angel.ocean.common;

import com.angel.ocean.constant.ResultCode;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class ApiResult<T> {

    @ApiModelProperty(value = "响应码")
    private Integer code;

    @ApiModelProperty(value = "提示信息")
    private String msg;

    @ApiModelProperty(value = "数据集合")
    private T data;

    public ApiResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static <T> ApiResult<T> success(T data) {
        return new ApiResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data);
    }

    public static <T> ApiResult<T> success() {
        return new ApiResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), null);
    }

    public static <T> ApiResult<T> error(int code, String msg) {
        return new ApiResult(code, msg, null);
    }

    public static <T> ApiResult<T> error() {
        return new ApiResult(ResultCode.SERVICE_INTERNAL_ERROR.getCode(), ResultCode.SERVICE_INTERNAL_ERROR.getMsg(), null);
    }

    public static <T> ApiResult<T> error(ResultCode messageCode) {
        return new ApiResult(messageCode.getCode(), messageCode.getMsg(), null);
    }
}
package com.angel.ocean.common;

import com.angel.ocean.constant.ResultCode;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;

@Data
public class PageResult<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "总条数")
    private Integer total;

    @ApiModelProperty(value = "数据集合")
    private List<T> rows;

    @ApiModelProperty(value = "响应码")
    private Integer code;

    @ApiModelProperty(value = "提示信息")
    private String msg;

    @ApiModelProperty(value = "页码,1-首页")
    private Integer pageNum;

    @ApiModelProperty(value = "每页数据大小")
    private Integer pageSize;

    @ApiModelProperty(value = "总页数")
    private Integer pages;

    public PageResult() {
    }

    public PageResult(List<T> list, int total) {
        this.rows = list;
        this.total = total;
    }

    public PageResult(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public PageResult(Integer total, List<T> rows, int code, String msg) {
        this.total = total;
        this.rows = rows;
        this.code = code;
        this.msg = msg;
    }

    public PageResult(Integer total, List<T> rows, int code, String msg, int pageNum, int pageSize) {
        this.total = total;
        this.rows = rows;
        this.code = code;
        this.msg = msg;
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.pages = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
    }


    public static <T> PageResult<T> success(List<T> list, Integer total) {
        return new PageResult(total, list, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
    }

    public static <T> PageResult<T> success(List<T> list, Integer total, Integer pageNum, Integer pageSize) {
        return new PageResult(total, list, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), pageNum, pageSize);
    }

    public static <T> PageResult<T> error(ResultCode resultCode) {
        return new PageResult(resultCode.getCode(), resultCode.getMsg());
    }

    public static <T> PageResult<T> error() {
        return new PageResult(ResultCode.SERVICE_INTERNAL_ERROR.getCode(), ResultCode.SERVICE_INTERNAL_ERROR.getMsg());
    }
}
package com.angel.ocean.common;

import io.swagger.annotations.ApiModelProperty;

public class PageDomain {

    /***
     * 页码
     */
    @ApiModelProperty(value = "页码,1-首页")
    private Integer pageNum;

    /***
     * 页面条数
     */
    @ApiModelProperty(value = "每页数据大小")
    private Integer pageSize;

    @ApiModelProperty(hidden = true)
    private Integer limit;

    @ApiModelProperty(hidden = true)
    private Integer offset;

    public int getLimit() {
        limit = (getPageNum() - 1) * getPageSize();
        return limit;
    }

    public int getOffset() {
        offset = getPageSize();
        return offset;
    }

    public Integer getPageNum() {
        if(null == pageNum || pageNum < 1) {
            return 1;
        }
        return pageNum;
    }

    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }

    public Integer getPageSize() {
        if(null == pageSize || pageSize < 1) {
            pageSize = 10;
        }
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }
}

定义代码生成执行方法

package com.angel.ocean;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;

@SpringBootTest
class ApplicationTests {

    @Test
    void generate() {

        // 1、创建代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 表名
        String tableName = "sys_role";

        // 表前缀
        String tablePrefix = "";

        // 包名
        String packages = "com.angel.ocean";

        // 2、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("Jaime.yu");
        gc.setOpen(false);  //生成后是否打开资源管理器
        gc.setFileOverride(false);  //重新生成时文件是否覆盖
        gc.setServiceName("%sService"); //去掉Service接口的首字母I
        gc.setIdType(IdType.AUTO);  //主键策略
        gc.setDateType(DateType.ONLY_DATE); //定义生成的实体类中日期类型
        gc.setSwagger2(true);   //开启Swagger2模式
        gc.setBaseResultMap(true);  //启用通用查询映射结果
        gc.setBaseColumnList(true);  //启用通用查询结果列

        mpg.setGlobalConfig(gc);

        // 3、数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/db-ocean?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 4、包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null); //模块名
        pc.setParent(packages);
        pc.setController("controller");
        pc.setEntity("domain.entity");
        pc.setService("service");
        pc.setMapper("mapper");
        mpg.setPackageInfo(pc);

        // 配置模板引擎
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 注入自定义配置,可以在 VM 中使用 cfg.injectionConfig 设置的值
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                this.getConfig().getPackageInfo().put("base_packages", packages);
                this.getConfig().getPackageInfo().put("entity_packages", packages + StringPool.DOT + "domain" + StringPool.DOT + "entity");
                this.getConfig().getPackageInfo().put("dto_packages", packages + StringPool.DOT + "domain" + StringPool.DOT + "dto");
                this.getConfig().getPackageInfo().put("vo_packages", packages + StringPool.DOT + "domain" + StringPool.DOT + "vo");
                this.getConfig().getPackageInfo().put("qo_packages", packages + StringPool.DOT + "domain" + StringPool.DOT + "qo");
            }
        };
        //自定义文件输出位置(非必须)
        List<FileOutConfig> fileOutList = new ArrayList<FileOutConfig>();

        fileOutList.add(new FileOutConfig("/templates/qo.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getPath(packages) + "/domain/qo"
                        + "/" + tableInfo.getEntityName() + "QO" + StringPool.DOT_JAVA;
            }
        });

        fileOutList.add(new FileOutConfig("/templates/dto.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getPath(packages) + "/domain/dto"
                        + "/" + tableInfo.getEntityName() + "DTO" + StringPool.DOT_JAVA;
            }
        });

        fileOutList.add(new FileOutConfig("/templates/vo.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getPath(packages) + "/domain/vo"
                        + "/" + tableInfo.getEntityName() + "VO" +StringPool.DOT_JAVA;
            }
        });

        fileOutList.add(
            new FileOutConfig("/templates/mapper.xml.vm") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return "src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                }
            }
        );

        fileOutList.add(new FileOutConfig("/templates/test/mapper.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getTestPath(packages) + "/mapper"
                        + "/" + tableInfo.getEntityName() + "MapperTest" + StringPool.DOT_JAVA;
            }
        });

        fileOutList.add(new FileOutConfig("/templates/test/service.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getTestPath(packages) + "/service"
                        + "/" + tableInfo.getEntityName() + "ServiceTest" + StringPool.DOT_JAVA;
            }
        });

        fileOutList.add(new FileOutConfig("/templates/test/controller.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + getTestPath(packages) + "/controller"
                        + "/" + tableInfo.getEntityName() + "ControllerTest" + StringPool.DOT_JAVA;
            }
        });

        injectionConfig.setFileOutConfigList(fileOutList);
        mpg.setCfg(injectionConfig);

        // 5、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude(tableName);//对那一张表生成代码
        strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
        strategy.setTablePrefix(tablePrefix); //生成实体时去掉表前缀
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
        strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
        strategy.setRestControllerStyle(true); //restful api风格控制器
        strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
        mpg.setStrategy(strategy);

        // 6、执行
        mpg.execute();
    }

    private String getPath(String packages) {
        String path = "";
        if(StrUtil.isNotEmpty(packages)) {
            path = "/src/main/java/" + packages.replace(".", "/") + "/";
        }

        return path;
    }

    private String getTestPath(String packages) {
        String path = "";
        if(StrUtil.isNotEmpty(packages)) {
            path = "/src/test/java/" + packages.replace(".", "/") + "/";
        }

        return path;
    }

}

代码生成截图

红色框中为生成的代码,包含controller/service/mapper/entity/dto/qo/vo,以及单元测试代码
在这里插入图片描述

启动服务

在这里插入图片描述
Swagger配置:

package com.angel.ocean.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * swagger配置文件
 */
@Slf4j
@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket createRestApi() {
        log.info("进入到swagger的配置中,swagger地址:http://<host>:<port>/swagger-ui.html");
        return new Docket(DocumentationType.SWAGGER_2)
                // 指定构建api文档的详细信息的方法:apiInfo()
                .apiInfo(apiInfo())
                .select()
                // 指定要生成api接口的包路径,这里把controller作为包路径,生成controller中的所有接口
                .apis(RequestHandlerSelectors.basePackage("com.angel.ocean.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 构建api文档的详细信息
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // 设置页面标题
                .title("Spring Boot集成Swagger2接口总览")
                // 设置接口描述
                .description("Swagger接口学习")
                // 设置联系方式
                .contact(new Contact("测试swagger","http://localhost:8000/","861565437@qq.com"))
                // 设置版本
                .version("1.0")
                // 构建
                .build();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/749019.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Arcgis 计算经纬度坐标并补齐6位小数

工作中我们经常需要在Arcgis中计算点的经纬度或者线的起点、终点坐标&#xff0c;为确保数据的准确性&#xff0c;我们必须保留6位小数&#xff0c;但我们在默认计算的时候偶尔会遇到算出来的经纬度坐标小数位不足6位&#xff0c;那我们应该如何补齐呢&#xff0c;这里我将方法…

如何不改变 PostgreSQL 列类型#PG培训

开发应用程序并在其背后操作数据库集群时&#xff0c;会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。 #PG考试#postgresql培训#postgresql考试#postgresql认证 关于如何在 PostgreSQL&#xff08;以及其他符合 SQ…

Hugo Barra对Apple Vision Pro 硬件和软件的详细评述

原文&#xff1a;hugo.blog/2024/03/11/vision-pro 这篇文章的作者是Hugo Barra。Hugo Barra曾是Meta公司&#xff08;前身为Facebook&#xff09;旗下Oculus VR/AR团队的负责人。他在2017年至2020年期间领导了Oculus的团队&#xff0c;参与了多个VR头显的开发和发布。Hugo Bar…

MySQL详细介绍:开源关系数据库管理系统的魅力

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

未来20年人工智能将如何塑造社会

照片由Brian McGowan在Unsplash上拍摄 更多资讯&#xff0c;请访问 2img.ai “人工智能会成为我们的救星还是我们的末日&#xff1f;” 几十年来&#xff0c;这个问题一直困扰着哲学家、科学家和科幻爱好者。 当我们踏上技术革命的边缘时&#xff0c;是时候透过水晶球&#x…

从0开始编写VS1053音频解码芯片的底层驱动代码(适用于任何单片机)

VS1053是一个高性能的音频解码器芯片,它是干什么的? 他有两个功能:()用来解码音频文件播放音乐的。(2)将麦克风听到的声音编码成音频文件数据,配合单片机可以保存到SD卡。 单片机加上一个VS1053就可以轻松做一个音乐播放器、一个录音机 等项目。 VS1053支持两种协议:…

Visio文件编辑查看工具:Visio Viewer for Mac 激活版

Visio Viewer 软件通过该软件&#xff0c;用户可以在没有Visio软件的情况下查看使用Visio创建的绘图和图表&#xff0c;方便用户对复杂信息的可视化、分析和交流。Visio Viewer 2007是一个功能强大的软件&#xff0c;它可以帮助IT和商务专业人员轻松地可视化、分析和交流复杂信…

AI论文降重:一键操作,让你的论文查重率瞬间下降

高查重率是许多毕业生的困扰。通常&#xff0c;高查重率源于过度引用未经修改的参考资料和格式错误。传统的降重方法&#xff0c;如修改文本和增添原创内容&#xff0c;虽必要但耗时且成效不一。 鉴于此&#xff0c;应用AI工具进行AIGC降重成为了一个高效的解决方案。这些工具…

PyCharm 2024.1最新变化

PyCharm 2024.1 版本带来了一系列激动人心的新功能和改进&#xff0c;以下是一些主要的更新亮点: Hugging Face 模型和数据集文档预览&#xff1a;在 PyCharm 内部快速获取 Hugging Face 模型或数据集的详细信息&#xff0c;通过鼠标悬停或使用 F1 键打开文档工具窗口来预览。 …

基于springboot、logback的日志脱敏组件

Logback⽇志数据脱敏⼯具&#xff1a;隐私和安全的守护者 概述 在涉及敏感数据的⽇志记录环境中&#xff0c;数据保护和个⼈隐私⽆疑是⾄关重要的领域。确保敏感数据不被泄露&#xff0c;脱敏处理成为必不可少的⼀步。数据脱敏是⼀种技术⼿段&#xff0c;其将敏感信息转换为不…

注意!流量卡的禁区并不一样,请看清楚后再下单!

大家好&#xff0c;我是搜卡之家&#xff0c;今天我又来给大家科普了&#xff01; 今天科普的内容是关于流量卡禁区&#xff01; 首先要说一下&#xff0c;流量卡为什么会有禁区&#xff1f;运营商设立禁区主要是为了应对电信诈骗和违法使用电话卡的行为&#xff0c;确保网络…

Studying-代码随想录训练营day21| 669.修建二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树、二叉树总结

第21天&#xff0c;二叉树最后一篇&#xff0c;冲&#x1f4aa; 目录 669.修建二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 二叉树总结 669.修建二叉搜索树 文档讲解&#xff1a;代码随想录修建二叉搜索树 视频讲解&#xff1a;手撕修建二叉…

NAT和内网穿透

NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是一种广泛应用于计算机网络的技术&#xff0c;其主要目的是为了解决IPv4地址空间的短缺问题&#xff0c;并且增强网络安全。NAT技术允许一个私有网络内的多个设备共享一个或几个全局唯一的公共…

【Python实战因果推断】2_因果效应异质性2

目录 CATE with Regression Evaluating CATE Predictions CATE with Regression 我想你可能已经预料到了&#xff1a;与应用因果推理中的大多数情况一样&#xff0c;答案往往从线性回归开始。但在走这条路之前&#xff0c;让我们把事情变得更具体一些。假设你在一家遍布全国的…

nuxt3项目打包后获取.env设置的环境变量无效的解决办法

问题描述 在nuxt3项目开发过程中&#xff0c;设置了开发环境变量和生产环境变量&#xff0c;在本地开发时都能正常获取&#xff0c;但打包部署时获取不到&#xff0c;设置如下&#xff1a; //.env.development文件示例 SERVER_API_PATHhttp://192.168.25.100//.env.productio…

Shell (一)Ubuntu的网络配置及软件安装

Ubuntu的配置及软件安装 网络配置 虚拟机提供的网络类型 桥接模式 主机和虚拟机分别拥有不同的ip地址&#xff0c;可以实现和外界设备通信 NAT模式 也可以联网&#xff0c;但是和主机共用同一个ip地址&#xff0c;外界无法识别虚拟机和主机发送的信息 仅主机模式 虚拟机不可…

【Chapter9】设备与IO管理,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]零、设备管理的功能和目标0.1 设备管理的功能0.2 设备管理的目标 一、设备的分类1.1 输入输出型设备和存储型设备&#xff08;用途&#xff09;1.2 独占型设备和共享型设备 二、设备的物理特性2.1 IO设备的物理特性2.2 存储型设备的物理特性2.2.1 磁带的物理特性…

nest.js关键笔记

Nest.js 介绍核心功能设计模式&#xff1a;IOC 控制反转 DI 依赖注入前置知识&#xff1a;装饰器前置知识装饰器-实现一个GET请求 Nestjs脚手架Nestjs cli 常用命令 RESTful 风格设计Nestjs 控制器控制器中常见的参数装饰器 Session 实例Nestjs 提供者工厂模式异步模式 Nestjs …

高中数学:不等式-常用不等式知识点汇总

一、基本性质 比较大小的常用两种方法&#xff1a;作差法&#xff0c;作商法 等式性质 不等式性质 二、基本(均值)不等式 扩展 三、二次函数与一元二次方程不等式 定义 解的对应关系 一元二次不等式的求解过程 四、二元一次不等式(组)与线性规划 关键在于求多个不等…

vite-ts-cesium项目集成mars3d修改相关的包和配置参考

如果vite技术栈下使用原生cesium&#xff0c;请参考下面文件的包和配置修改&#xff0c;想用原生创建的viewer结合我们mars3d的功能的话。 1. package.json文件 "dependencies": {"cesium": "^1.103.0","mars3d": "^3.7.18&quo…