【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)

汝之观览,吾之幸也! 从本文开始讲下项目中用到的一些框架和技术,最基本的框架使用的是SpringBoot(2.5.10)+Mybatis-plus(3.5.3.2)+lombok(1.18.28)+knife4j(3.0.3)+hutool(5.8.21),可以做到代码自动生成,满足最基本的增删查改。

一、新建SpringBoot项目

使用Idea工具直接创建项目
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第1张图片

输入项目名称等
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第2张图片

生成web项目
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第3张图片

二、配置pom

<?xml version="1.0" encoding="UTF-8"?>
://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    >4.0.0>
    >
        >org.springframework.boot>
        >spring-boot-starter-parent>
        >2.5.10>
        > <!-- lookup parent from repository -->
    
    com.mitool
    springboot
    0.0.1-SNAPSHOT
    springboot
    Demo project for Spring Boot
    
        1.8
        3.5.3.2
        2.3.29
        1.18.28
        3.0.3
        5.8.21
        1.4.7
        4.3.2
        1.4.2.Final
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            mysql
            mysql-connector-java
            runtime
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
            ${mybatis-plus.version}
        
        
        
            com.baomidou
            mybatis-plus-generator
            ${mybatis-plus.version}
            
                
                    com.baomidou
                    mybatis-plus-extension
                
            
        
        
        
            org.freemarker
            freemarker
            ${freemarker.version}
        
        
        
            org.projectlombok
            lombok
            ${lombok.version}
            provided
        
        
        
            com.github.xiaoymin
            knife4j-spring-boot-starter
            ${knife4j.version}
        
        
        
            cn.hutool
            hutool-all
            ${hutool.version}
        
        
        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            ${pagehelper.version}
        
        
        
            com.alibaba.cola
            cola-component-dto
            ${ali.cola.version}
        
        
            org.mapstruct
            mapstruct
            ${org.mapstruct.version}
        
    

    >
        >
            >
                >org.springframework.boot>
                >spring-boot-maven-plugin>
            >
            >
                >org.apache.maven.plugins>
                >maven-compiler-plugin>
                >3.8.1>
                >
                    >1.8>
                    >1.8>
                    >
                        >
                            >org.projectlombok>
                            >lombok>
                            >${lombok.version}>
                        >
                        >
                            >org.mapstruct>
                            >mapstruct-processor>
                            >${org.mapstruct.version}>
                        >
                    >
                >
            >
        >
    >

>

三、配置application.properties

1、配置application.properties

配置application.properties文件,文件中包含数据库配置、knife4j配置

# 应用名称
spring.application.name=spring-demo
# 开发环境设置
spring.profiles.active=dev
# 应用路径
server.servlet.context-path=/springboot
# 编码字符集
server.servlet.encoding.charset=utf-8
# swagger
knife4j.enable=true
knife4j.production=false
knife4j.basic.enable=false

2、配置application-dev.properties

配置数据库,
localhost:数据库IP
db_source:数据库名称
username:用户名
password:密码

# 端口
server.port=9900
spring.datasource.url=jdbc:mysql://localhost:3306/db_source?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# SSO
zsc.open.token.check=false

四、新建代码生成工具类 CodeGeneratorUtil

package com.mitool.springboot.utils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.InjectionConfig;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 

Title: CodeGeneratorUtil

*

Description: * 描述:mybatis-plus 自动生成代码工具类 *

* * @author Jimmy.Shen * @version v1.0.0 * @since 2022-10-19 9:58 */
@Slf4j public class CodeGeneratorUtil { /** * 表前缀 */ private static final String[] PREFIX = new String[]{"illp_", "t_"}; /** * 是否生成controller、service、serviceImpl、converter */ private static final boolean ONLY_UPDATE_COLUMNS = true; /** * 数据源配置 */ private static final DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig .Builder("jdbc:mysql://10.10.177.151:3309/smart_park?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true", "root", "ztesoft"); /** * 读取控制台内容 */ public static String scanner(String tip) { Scanner scanner = new Scanner(System.in); log.info("### 请输入" + tip); if (scanner.hasNext()) { String ipt = scanner.next(); if (StrUtil.isNotEmpty(ipt)) { return ipt; } } throw new MybatisPlusException("请输入正确的" + tip + "!"); } public static void main(String[] args) { String projectPath = System.getProperty("user.dir"); String outputDir = projectPath + "/springboot/src/main/java/"; String[] scannerArr = scanner("作者名,包名,表名").split(","); String authorName = scannerArr[0]; String packageName = scannerArr[1]; String tableName = scannerArr[2]; // 规定代码路径,如果代码在不同项目中可进行调整 String controllerName = projectPath + "/springboot/src/main/java/com/mitool/springboot/controller/" + packageName; String serviceName = projectPath + "/springboot/src/main/java/com/mitool/springboot/service/" + packageName; String serviceImplName = projectPath + "/springboot/src/main/java/com/mitool/springboot/service/" + packageName + "/impl/"; String entityName = projectPath + "/springboot/src/main/java/com/mitool/springboot/entity/dataobject/" + packageName; String mapperName = projectPath + "/springboot/src/main/java/com/mitool/springboot/mapper/" + packageName; String mapperXmlName = projectPath + "/springboot/src/main/resources/mybatis-mapper/" + packageName; String voName = projectPath + "/springboot/src/main/java/com/mitool/springboot/entity/vo/" + packageName; String converterName = projectPath + "/springboot/src/main/java/com/mitool/springboot/converter/" + packageName; FastAutoGenerator.create(DATA_SOURCE_CONFIG) // 全局配置 .globalConfig(builder -> //作者名 builder.author(authorName) // 开启 swagger 模式 默认值:false .enableSwagger() // 禁止打开输出目录 默认值:true .disableOpenDir() // 指定输出目录 .outputDir(outputDir)) .packageConfig(builder -> builder.moduleName(packageName)) .injectionConfig(builder -> { updateColumn(entityName, mapperName, mapperXmlName, voName, builder); if (ONLY_UPDATE_COLUMNS) { updateTemplate(controllerName, serviceName, serviceImplName, converterName, builder); } }) //具体的生成文件的策略配置 .strategyConfig(builder -> { builder.addInclude(tableName.split("#")) // .enableSkipView() .addTablePrefix(Arrays.asList(PREFIX)) .entityBuilder() .enableFileOverride() .enableLombok() // // controller .controllerBuilder() .enableRestStyle() .formatFileName("%sController") .enableFileOverride() // service .serviceBuilder() .superServiceClass(IService.class) .formatServiceFileName("%sService") .formatServiceImplFileName("%sServiceImpl") .enableFileOverride() //开启生成mapper .mapperBuilder() .enableBaseResultMap() .enableBaseColumnList() .superClass(BaseMapper.class) .formatMapperFileName("%sMapper") .formatXmlFileName("%sXml") .enableFileOverride(); }) //模板配置,如果你没有自定义的一些模板配置,这里直接使用默认即可。 .templateConfig(config -> config.entity("/templates/entity.java")) //模板引擎配置 .templateEngine(new FreemarkerTemplateEngine()) .execute(); // 删除生成的自带的 baomidou代码 FileUtil.del(projectPath + "/springboot/src/main/java/com/baomidou"); } private static void updateColumn(String entityName, String mapperName, String mapperXmlName, String voName, InjectionConfig.Builder builder) { builder.customFile(consumer -> consumer .fileName("DO.java") .filePath(entityName) .enableFileOverride() .templatePath("/templates/entity.java.ftl")); builder.customFile(consumer -> consumer .fileName("Mapper.java") .filePath(mapperName) .enableFileOverride() .templatePath("/templates/mapper.java.ftl")); builder.customFile(consumer -> consumer .fileName("Mapper.xml") .filePath(mapperXmlName) .enableFileOverride() .templatePath("/templates/mapper.xml.ftl")); builder.customFile(consumer -> consumer .fileName("VO.java") .filePath(voName) .enableFileOverride() .templatePath("/templates/vo.java.ftl")); } private static void updateTemplate(String controllerName, String serviceName, String serviceImplName, String converterName, InjectionConfig.Builder builder) { builder.customFile(consumer -> consumer .fileName("Controller.java") .filePath(controllerName) .enableFileOverride() .templatePath("/templates/controller.java.ftl")); builder.customFile(consumer -> consumer .fileName("Service.java") .filePath(serviceName) .enableFileOverride() .templatePath("/templates/service.java.ftl")); builder.customFile(consumer -> consumer .fileName("ServiceImpl.java") .filePath(serviceImplName) .enableFileOverride() .templatePath("/templates/serviceImpl.java.ftl")); builder.customFile(consumer -> consumer .fileName("AppConverter.java") .filePath(converterName) .enableFileOverride() .templatePath("/templates/converter.java.ftl")); } }

五、模板(FreemarkerTemplate)

模板文件放在resource/templates下

1、controller.java.ftl

package com.mitool.springboot.controller.${package.ModuleName};

import com.mitool.springboot.utils.PageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import com.mitool.springboot.service.${package.ModuleName}.${table.serviceName};
import com.mitool.springboot.entity.dataobject.${package.ModuleName}.${entity}DO;
import com.mitool.springboot.entity.vo.${package.ModuleName}.${entity}VO;
import com.mitool.springboot.converter.${package.ModuleName}.${entity}AppConverter;
import com.alibaba.cola.dto.SingleResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
<#if superControllerClassPackage??>
    import ${superControllerClassPackage};

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
/**
* 

* ${table.comment!} 前端控制器 *

* * @author ${author} * @since ${date} */ @Slf4j @RestController @RequestMapping("/api/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}") @Api(value = "${table.comment!}", tags = "${table.comment!} 管理模块") <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass} { <#else> public class ${table.controllerName} { @Resource private ${table.serviceName} service; @Resource private ${entity}AppConverter converter; @ApiOperation(value = "${table.comment!}分页查询", notes = "${table.comment!}分页查询") @GetMapping("/page") public SingleResponse page(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) { PageHelper.startPage(pageIndex, pageSize); List<${entity}DO> list = service.list(); return SingleResponse.of(PageUtil.pageInfoCopy(new PageInfo<>(list), ${entity}VO.class, converter::toValueObject)); } @ApiOperation(value = "${table.comment!}列表查询", notes = "${table.comment!}列表查询") @GetMapping("/list") public SingleResponse list() { List<${entity}DO> list = service.list(); return SingleResponse.of(converter.toValueObject(list)); } @ApiOperation(value = "${table.comment!}详情", notes = "${table.comment!}详情") @GetMapping("/detail") public SingleResponse detail(@RequestParam Integer id) { return SingleResponse.of(converter.toValueObject(service.getById(id))); } @ApiOperation("新增") @PostMapping("/save") public SingleResponse save(@RequestBody ${entity}VO param) { ${entity}DO dataObject = converter.toDataObject(param); service.save(dataObject); return SingleResponse.buildSuccess(); } @ApiOperation("更新") @PostMapping("/update") public SingleResponse update(@RequestBody ${entity}VO param) { ${entity}DO dataObject = converter.toDataObject(param); service.updateById(dataObject); return SingleResponse.buildSuccess(); } @ApiOperation("删除") @PostMapping("/remove") public SingleResponse remove(@RequestBody ${entity}VO param) { service.removeById(param.getId()); return SingleResponse.buildSuccess(); } }

2、converter.java.ftl

package com.mitool.springboot.converter.${package.ModuleName};

import com.mitool.springboot.entity.dataobject.${package.ModuleName}.${entity}DO;
import com.mitool.springboot.entity.vo.${package.ModuleName}.${entity}VO;

import org.mapstruct.Mapper;

import java.util.List;

/**
 * 

* ${table.comment!} app 模型转换服务 *

* * @author ${author} * @since ${date} */ @Mapper(componentModel = "spring") public interface ${entity}AppConverter { ${entity}DO toDataObject(${entity}VO ${entity?uncap_first}VO); List<${entity}DO> toDataObject(List<${entity}VO> ${entity?uncap_first}VOList); ${entity}VO toValueObject(${entity}DO ${entity?uncap_first}DO); List<${entity}VO> toValueObject(List<${entity}DO> ${entity?uncap_first}DOList); }

3、entity.java.ftl

package com.mitool.springboot.entity.dataobject.${package.ModuleName};

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
* 

* Title:${entity} *

*

* Description:描述:${table.comment} 对象 *

* * @author ${author} * @version 1.0.0 * @since ${date} **/ @Data @TableName("${table.name}") public class ${entity}DO implements Serializable { private static final long serialVersionUID = 1L; <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> /** * ${field.comment} */ <#if field.keyFlag> <#assign keyPropertyName="${field.propertyName}"/> @TableId(value = "${field.name}", type = IdType.AUTO) private ${field.propertyType} ${field.propertyName}; <#------------ END 字段循环遍历 ----------> }

4、mapper.java.ftl

package com.mitool.springboot.mapper.${package.ModuleName};

import com.mitool.springboot.entity.dataobject.${package.ModuleName}.${entity}DO;
import ${superMapperClassPackage};
<#if mapperAnnotationClass??>
 import ${mapperAnnotationClass.name};

import org.apache.ibatis.annotations.Mapper;

/**
* 

* ${table.comment!} Mapper 接口 *

* * @author ${author} * @since ${date} */ <#if mapperAnnotationClass??> @${mapperAnnotationClass.simpleName} <#if kotlin> interface ${table.mapperName} : ${superMapperClass}<${entity}DO> <#else> @Mapper public interface ${table.mapperName} extends ${superMapperClass}<${entity}DO> { }

5、mapper.xml.ftl





    <#if enableCache>
        
        

    

    
    
        <#list table.fields as field>
            <#if field.keyFlag><#--生成主键排在第一位-->
            
            
        
        <#list table.commonFields as field><#--生成公共字段 -->
            
        
        <#list table.fields as field>
            <#if !field.keyFlag><#--生成普通字段 -->
        


    


<#if baseColumnList>
    
    
<#list table.commonFields as field>
        ${field.columnName},

        ${table.fieldNames}
    




6、service.java.ftl

package com.mitool.springboot.service.${package.ModuleName};

import ${superServiceClassPackage};
import com.mitool.springboot.entity.dataobject.${package.ModuleName}.${entity}DO;

/**
* 

* ${table.comment!} 服务类 *

* * @author ${author} * @since ${date} */ <#if kotlin> interface ${table.serviceName} : ${superServiceClass}<${entity}DO> <#else> public interface ${table.serviceName} extends ${superServiceClass}<${entity}DO> { }

7、serviceImpl.java.ftl

package com.mitool.springboot.service.${package.ModuleName}.impl;

import com.mitool.springboot.mapper.${package.ModuleName}.${table.mapperName};
import com.mitool.springboot.service.${package.ModuleName}.${table.serviceName};
import com.mitool.springboot.entity.dataobject.${package.ModuleName}.${entity}DO;
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;

/**
* 

* ${table.comment!} 服务实现类 *

* * @author ${author} * @since ${date} */ @Service <#if kotlin> open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}DO>(), ${table.serviceName} { } <#else> public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}DO> implements ${table.serviceName} { }

8、vo.java.ftl

package com.mitool.springboot.entity.vo.${package.ModuleName};

<#list table.importPackages as pkg>
    <#if pkg?contains("baomidou")>
    <#elseif pkg?contains("Serializable")>
    <#else>
import ${pkg};
    

import lombok.Data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * 

* ${table.comment!} 请求模型 *

* * @author ${author} * @since ${date} */ @ApiModel(value="${entity}对象", description="${table.comment!}") @Data public class ${entity}VO { <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> <#if field.name != "is_delete"> <#if field.keyFlag> <#assign keyPropertyName="${field.propertyName}"/> <#if field.comment!?length gt 0> /** * ${field.comment} */ @ApiModelProperty(value = "${field.comment}") private ${field.propertyType} ${field.propertyName}; <#------------ END 字段循环遍历 ----------> }

六、用到的其他类 PageUtil

使用到了分页的工具类,放在utils目录下

package com.mitool.springboot.utils;

import com.github.pagehelper.PageInfo;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页工具类
 *
 * @author Jimmy.Shen
 * @since 2021/11/26
 */
public class PageUtil {

    /**
     * 通用pageInfo转换
     *
     * @param sourcePageInfo 源数据
     * @param targetClass    目标类型
     * @param mapper         list转换方法
     * @param             目标类型
     * @param             源类型
     */
    public static <T, S> PageInfo<T> pageInfoCopy(PageInfo<S> sourcePageInfo, Class<T> targetClass, Function<S, T> mapper) {
        PageInfo<T> respPageInfo = new PageInfo<>();
        respPageInfo.setPageNum(sourcePageInfo.getPageNum());
        respPageInfo.setPageSize(sourcePageInfo.getPageSize());
        respPageInfo.setSize(sourcePageInfo.getSize());
        respPageInfo.setStartRow(sourcePageInfo.getStartRow());
        respPageInfo.setEndRow(sourcePageInfo.getEndRow());
        respPageInfo.setPages(sourcePageInfo.getPages());
        respPageInfo.setPrePage(sourcePageInfo.getPrePage());
        respPageInfo.setNextPage(sourcePageInfo.getNextPage());
        respPageInfo.setIsFirstPage(sourcePageInfo.isIsFirstPage());
        respPageInfo.setIsLastPage(sourcePageInfo.isIsLastPage());
        respPageInfo.setHasPreviousPage(sourcePageInfo.isHasPreviousPage());
        respPageInfo.setHasNextPage(sourcePageInfo.isHasNextPage());
        respPageInfo.setNavigatePages(sourcePageInfo.getNavigatePages());
        respPageInfo.setNavigatepageNums(sourcePageInfo.getNavigatepageNums());
        respPageInfo.setNavigateFirstPage(sourcePageInfo.getNavigateFirstPage());
        respPageInfo.setNavigateLastPage(sourcePageInfo.getNavigateLastPage());
        respPageInfo.setTotal(sourcePageInfo.getTotal());

        List<T> pageList = sourcePageInfo.getList().stream().map(mapper).collect(Collectors.toList());
        respPageInfo.setList(pageList);
        return respPageInfo;
    }
}

七、运行 CodeGeneratorUtil main方法

输入作者、包、表名生成文件,启动项目后可生成代码
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第4张图片
生成的项目架构
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第5张图片
使用swagger查看
【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)_第6张图片

你可能感兴趣的:(SpringBoot,Java,spring,boot,架构,mybatis)