【JavaWeb】——原理拔高-若依代码生成器

代码生成器

1. 代码解读

  • 代码生成器表结构说明

    • gen_table用于存储业务表的基本信息

    • gen_table_column用于存储业务表的字段信息

      • gen_table与gen_table_column+的 关系为一对多

      在这里插入图片描述

  • 代码生成器目录结构

    在这里插入图片描述

  • 查询数据库

    • 前端

      • @/views/tool/index.vue

        <!-- 导入数据表弹框组件 -->
        <import-table ref="importRef" @ok="handleQuery" />
        
        /** 打开导入表弹窗 */
        function openImportTable() {
          proxy.$refs["importRef"].show();
        }
        

        @/views/tool/importTable.vue,查询数据并打开弹窗

        /** 查询参数列表 */
        function show() {
          getList();
          visible.value = true;
        }
        
        /** 查询表数据 */
        function getList() {
          listDbTable(queryParams).then(res => {
            dbTableList.value = res.rows;
            total.value = res.total;
          });
        }
        

        src\api\tool\gen.js,发送api请求

        export function listDbTable(query) {
          return request({
            url: '/tool/gen/db/list',
            method: 'get',
            params: query
          })
        }
        
    • 后端

      在这里插入图片描述

      • generator模块的GenController.java

        /**
        * 查询数据库列表
        */
        @PreAuthorize("@ss.hasPermi('tool:gen:list')")
        @GetMapping("/db/list")
        public TableDataInfo dataList(GenTable genTable)
        {
            startPage();
            List<GenTable> list = genTableService.selectDbTableList(genTable);
            return getDataTable(list);
        }
        

        底层的xml如下

        <select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
            select table_name, table_comment, create_time, update_time from information_schema.tables
            where table_schema = (select database())
            AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
            AND table_name NOT IN (select table_name from gen_table)
            <if test="tableName != null and tableName != ''">
                AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
            </if>
            <if test="tableComment != null and tableComment != ''">
            	AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
            </if>
            <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
                AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
            </if>
            <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
                AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
            </if>
            order by create_time desc
        </select>
        

        information_schema.tables表是mysql自带的表,用于查询该数据库中所有表的信息。

        在这里插入图片描述

        在上面的查询语句中,使用了通配符qrtz_%gen_%'排除了和定时任务以及代码生成器相关的表。

        AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
        

        并且排除了在gen_table中已经存在的表名(排除已经导入的表名)

        AND table_name NOT IN (select table_name from gen_table)
        
  • 导入表结构

    • 前端

      • importTable.vue

        <el-button type="primary" @click="handleImportTable">确 定</el-button>
        

        要将选中的表的表明用,连接成字符串并传递给后端

        /** 导入按钮操作 */
        function handleImportTable() {
          const tableNames = tables.value.join(",");
          if (tableNames == "") {
            proxy.$modal.msgError("请选择要导入的表");
            return;
          }
          importTable({ tables: tableNames }).then(res => {
            proxy.$modal.msgSuccess(res.msg);
            if (res.code === 200) {
              visible.value = false;
              emit("ok");
            }
          });
        }
        

        gen.js

        // 导入表
        export function importTable(data) {
          return request({
            url: '/tool/gen/importTable',
            method: 'post',
            params: data
          })
        }
        
    • 后端

      在这里插入图片描述

      • Controller

        将字符串拆分成数组并查询响应的数据库字段

        /**
        * 导入表结构(保存)
        */
        @PreAuthorize("@ss.hasPermi('tool:gen:import')")
        @Log(title = "代码生成", businessType = BusinessType.IMPORT)
        @PostMapping("/importTable")
        public AjaxResult importTableSave(String tables)
        {
            String[] tableNames = Convert.toStrArray(tables);
            // 查询表信息
            List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
            genTableService.importGenTable(tableList, SecurityUtils.getUsername());
            return success();
        }
        

        importGenTable方法用于导入代码生成表配置,注意table变量的作用域包含该次的for循环,也就是说在GenUtils.initTable方法可以直接改变table变量,而不用返回,genTableMapper.insertGenTable(table)中的table,就是已经是被修改后的table。

        tableList 为表格列表,包含需要导入的表结构信息

        username 为当前操作用户的用户名,用于记录操作日志和权限验证

        @Override
        @Transactional
        public void importGenTable(List<GenTable> tableList, String operName)
        {
            try
            {
                for (GenTable table : tableList)
                {
                    String tableName = table.getTableName();
                    GenUtils.initTable(table, operName);
                    int row = genTableMapper.insertGenTable(table);
                    if (row > 0)
                    {
                        // 保存列信息
                        List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
                        for (GenTableColumn column : genTableColumns)
                        {
                            GenUtils.initColumnField(column, table);
                            genTableColumnMapper.insertGenTableColumn(column);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new ServiceException("导入失败:" + e.getMessage());
            }
        }
        

        通过项目配置,初始化代码生成表的基本信息

        /**
             * 初始化代码生成表的基本信息
             * 设置类名、包名、模块名、业务名、功能名、作者、创建者等基础属性
             *
             * @param genTable 代码生成表对象,用于存储表的配置信息
             * @param operName 操作人员名称,用于记录创建者信息
             */
        public static void initTable(GenTable genTable, String operName)
        {
            // 根据表明上传类名,用于代码上传时的类名识别
            genTable.setClassName(convertClassName(genTable.getTableName()));
            // 设置包名,根据项目配置的包名进行设置
            genTable.setPackageName(GenConfig.getPackageName());
            // 设置模块名,通过解析包得到
            genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
            // 根据表名设置业务名,用于生成代码时的功能描述
            genTable.setBusinessName(getBusinessName(genTable.getTableName()));
            // 设置功能名,通过解析表名得到
            genTable.setFunctionName(replaceText(genTable.getTableComment()));
            // 设置生成代码的作战,根据配置文件中的作者信息进行设置
            genTable.setFunctionAuthor(GenConfig.getAuthor());
            // 将操作人设置为当前操作的用户
            genTable.setCreateBy(operName);
        }
        

        GenConfig,生成代码的配置类,配置类的变量取决于配置文件generator.yml

        /**
         * 读取代码生成相关配置
         * 
         * @author ruoyi
         */
        @Component
        @ConfigurationProperties(prefix = "gen")
        @PropertySource(value = { "classpath:generator.yml" })
        public class GenConfig
        {
            /** 作者 */
            public static String author;
        
            /** 生成包路径 */
            public static String packageName;
        
            /** 自动去除表前缀,默认是false */
            public static boolean autoRemovePre;
        
            /** 表前缀(类名不会包含表前缀) */
            public static String tablePrefix;
        
            public static String getAuthor()
            {
                return author;
            }
        
            @Value("${author}")
            public void setAuthor(String author)
            {
                GenConfig.author = author;
            }
        
            public static String getPackageName()
            {
                return packageName;
            }
        
            @Value("${packageName}")
            public void setPackageName(String packageName)
            {
                GenConfig.packageName = packageName;
            }
        
            public static boolean getAutoRemovePre()
            {
                return autoRemovePre;
            }
        
            @Value("${autoRemovePre}")
            public void setAutoRemovePre(boolean autoRemovePre)
            {
                GenConfig.autoRemovePre = autoRemovePre;
            }
        
            public static String getTablePrefix()
            {
                return tablePrefix;
            }
        
            @Value("${tablePrefix}")
            public void setTablePrefix(String tablePrefix)
            {
                GenConfig.tablePrefix = tablePrefix;
            }
        }
        

        配置文件generator.yml,我们可以修改这个文件,来减少代码生成的修改项(注意,这个配置文件在导入时生效,已经导入的表格,数据已经被记录,配置文件不会影响)

        # 代码生成
        gen:
          # 作者
          author: ruoyi
          # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
          packageName: com.dkd.system
          # 自动去除表前缀,默认是false
          autoRemovePre: false
          # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
          tablePrefix: sys_
        
      • xml

        根据表名查询数据库信息

        <select id="selectDbTableListByNames" resultMap="GenTableResult">
            select table_name, table_comment, create_time, update_time from information_schema.tables
            where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
            and table_name in
            <foreach collection="array" item="name" open="(" separator="," close=")">
            	#{name}
        	</foreach> 
        </select>
        

        根据表名查询数据库表列信息,包括列名、是否必填、是否主键、排序位置、列注释、是否自增、列类型等信息

        <!--
            根据表名查询数据库表列信息
            查询指定表的所有列信息,
        
            参数说明:
            - tableName: 表名,用于查询指定表的列信息
        
            返回值说明:
            - 返回GenTableColumnResult映射的结果集,包含列的详细信息
            -->
        <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
            select column_name, 
            (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required, 
            (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, 
            (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
            from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
            order by ordinal_position
        </select>
        

        我们这里执行一下sql

        select column_name,
               (case when (is_nullable = 'no' && column_key != 'PRI') then '1' else '0' end) as is_required,
               (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment,
               (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
        from information_schema.columns where table_schema = (select database()) and table_name = ('sku')
            order by ordinal_position
        

        可以看到sku(商品表)的列配置信息被查询出来了,并且和字段信息的表格相对应

        在这里插入图片描述

      • 初始化并保存列信息

        GenUtils.initColumnField(column, table);
        

        这个方法就是初始化、添加上面查询没有对应到的字段或数据

        /**
             * 初始化列属性字段
             */
        public static void initColumnField(GenTableColumn column, GenTable table)
        {
            String dataType = getDbType(column.getColumnType());
            String columnName = column.getColumnName();
            column.setTableId(table.getTableId());
            column.setCreateBy(table.getCreateBy());
            // 设置java字段名
            column.setJavaField(StringUtils.toCamelCase(columnName));
            // 设置默认类型
            column.setJavaType(GenConstants.TYPE_STRING);
            column.setQueryType(GenConstants.QUERY_EQ);
        
            if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
            {
                // 字符串长度超过500设置为文本域
                Integer columnLength = getColumnLength(column.getColumnType());
                String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
                column.setHtmlType(htmlType);
            }
            else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
            {
                column.setJavaType(GenConstants.TYPE_DATE);
                column.setHtmlType(GenConstants.HTML_DATETIME);
            }
            else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
            {
                column.setHtmlType(GenConstants.HTML_INPUT);
        
                // 如果是浮点型 统一用BigDecimal
                String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
                if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
                {
                    column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
                }
                // 如果是整形
                else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
                {
                    column.setJavaType(GenConstants.TYPE_INTEGER);
                }
                // 长整形
                else
                {
                    column.setJavaType(GenConstants.TYPE_LONG);
                }
            }
        
            // 插入字段(默认所有字段都需要插入)
            column.setIsInsert(GenConstants.REQUIRE);
        
            // 编辑字段
            if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
            {
                column.setIsEdit(GenConstants.REQUIRE);
            }
            // 列表字段
            if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
            {
                column.setIsList(GenConstants.REQUIRE);
            }
            // 查询字段
            if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
            {
                column.setIsQuery(GenConstants.REQUIRE);
            }
        
            // 查询字段类型
            if (StringUtils.endsWithIgnoreCase(columnName, "name"))
            {
                column.setQueryType(GenConstants.QUERY_LIKE);
            }
            // 状态字段设置单选框
            if (StringUtils.endsWithIgnoreCase(columnName, "status"))
            {
                column.setHtmlType(GenConstants.HTML_RADIO);
            }
            // 类型&性别字段设置下拉框
            else if (StringUtils.endsWithIgnoreCase(columnName, "type")
                     || StringUtils.endsWithIgnoreCase(columnName, "sex"))
            {
                column.setHtmlType(GenConstants.HTML_SELECT);
            }
            // 图片字段设置图片上传控件
            else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
            {
                column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
            }
            // 文件字段设置文件上传控件
            else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
            {
                column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
            }
            // 内容字段设置富文本控件
            else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
            {
                column.setHtmlType(GenConstants.HTML_EDITOR);
            }
        }
        

        根据数据库的列表转换为字段的名称(转换为小驼峰)

        // 设置java字段名
        column.setJavaField(StringUtils.toCamelCase(columnName));
        

        设置默认类型,默认类型为字符串,查询方式为相等

        // 设置默认类型
        column.setJavaType(GenConstants.TYPE_STRING);
        column.setQueryType(GenConstants.QUERY_EQ);
        

        其他的太多了,就不一一列举了,建议从上到下看一遍。

  • 上传代码

    在这里插入图片描述

    • Controller

      /**
           * 生成代码(下载方式)
           */
      @PreAuthorize("@ss.hasPermi('tool:gen:code')")
      @Log(title = "代码生成", businessType = BusinessType.GENCODE)
      @GetMapping("/download/{tableName}")
      public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
      {
          byte[] data = genTableService.downloadCode(tableName);
          genCode(response, data);
      }
      
      
    • Service

      /**
       * 生成代码(下载方式)
       * 
       * @param tableName 表名称
       * @return 包含生成代码的字节数组,用于下载
       */
      @Override
      public byte[] downloadCode(String tableName)
      {
          // 创建字节数组输出流,用于存储生成的代码内容
          ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
          
          // 创建ZIP压缩输出流,将生成的代码文件压缩成ZIP格式
          ZipOutputStream zip = new ZipOutputStream(outputStream);
          
          // 生成代码,并将代码内容写入ZIP流中
          generatorCode(tableName, zip);
          
          // 安静地关闭ZIP流,释放资源
          IOUtils.closeQuietly(zip);
          
          // 将输出流中的字节转换为字节数组并返回,用于下载
          return outputStream.toByteArray();
      }
      
      /**
           * 查询表信息并生成代码
           */
      private void generatorCode(String tableName, ZipOutputStream zip)
      {
          // 查询表信息
          GenTable table = genTableMapper.selectGenTableByName(tableName);
          // 设置主子表信息
          setSubTable(table);
          // 设置主键列信息
          setPkColumn(table);
      
          VelocityInitializer.initVelocity();
      
          VelocityContext context = VelocityUtils.prepareContext(table);
      
          // 获取模板列表
          List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
          for (String template : templates)
          {
              // 渲染模板
              StringWriter sw = new StringWriter();
              Template tpl = Velocity.getTemplate(template, Constants.UTF8);
              tpl.merge(context, sw);
              try
              {
                  // 添加到zip
                  zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
                  IOUtils.write(sw.toString(), zip, Constants.UTF8);
                  IOUtils.closeQuietly(sw);
                  zip.flush();
                  zip.closeEntry();
              }
              catch (IOException e)
              {
                  log.error("渲染模板失败,表名:" + table.getTableName(), e);
              }
          }
      }
      
    • 查询表信息

      GenTable table = genTableMapper.selectGenTableByName(tableName);
      
      <select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
          SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
      c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
          FROM gen_table t
          LEFT JOIN gen_table_column c ON t.table_id = c.table_id
          where t.table_name = #{tableName} order by c.sort
      </select>                                                        
      

2. velocity模板

Velocity是一个Java模板引擎,它使用特定语法在模板中嵌入Java对象数据,实现界面与代码的分离。

  • Velocity官网:https://velocity.apache.org/

    在这里插入图片描述

  • 入门案例

    代码目录结构

    在这里插入图片描述

    模板文件(test.html.vm)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
    <h1>Hello ${name}</h1>
    </body>
    </html>
    

    写入测试(VelocityDemo.java)

    public static void main(String[] args) throws IOException {
        // 1. 初始化模板引擎
        VelocityInitializer.initVelocity();
        // 2. 创建Velocity上下文对象
        VelocityContext context = new VelocityContext();
        // 3. 添加数据到上下文对象中
        context.put("name", "Velocity");
        // 4. 读取模板
        Template template = Velocity.getTemplate("vm/test.html.vm", "UTF-8");
        // 5. 输出结果(渲染模板)
        FileWriter fileWriter = new FileWriter("D:\\velocity-test.html");
        template.merge(context, fileWriter);
        fileWriter.close();
    }
    

    效果

    在这里插入图片描述

  • 变量声明

    • 在模板中定义变量:#set开头,比如#set($name = “velocity”)

    • 获取变量的值: $name 或者 ${name}

      但是$name不能进行字符串的拼接,推荐使用${name}

      ## 定义变量
      #set($name = "Veolicty")
      
      ## 输出变量
      第一种情况:${name} <br/>
      第二种情况:$name <br/>
      
    • 对象变量

      Region.java

      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @ApiModel("区域管理对象")
      public class Region extends BaseEntity
      {
          private static final long serialVersionUID = 1L;
      
          /** 区域主键ID(自增) */
          private Long id;
      
          /** 区域名称(如:朝阳区、海淀区) */
          private String regionName;
      }
      

      模板文件(test.html.vm)

      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>Document</title>
          </head>
          <body>
          ## 获取对象中的数据
          $region <br/>
          区域ID:$region.id <br/>
          区域名称:$region.regionName <br/>
      
          </body>
      </html>
      

      写入测试(VelocityDemo.java)

      public class VelocityDemo {
          public static void main(String[] args) throws IOException {
              // 1. 初始化模板引擎
              VelocityInitializer.initVelocity();
              // 2. 创建Velocity上下文对象
              VelocityContext context = new VelocityContext();
              // 3. 添加数据到上下文对象中
              Region region = new Region(1L, "大兴");
              context.put("region", region);
              // 4. 读取模板
              Template template = Velocity.getTemplate("vm/test.html.vm", "UTF-8");
              // 5. 输出结果(渲染模板)
              FileWriter fileWriter = new FileWriter("D:\\velocity-test.html");
              template.merge(context, fileWriter);
              fileWriter.close();
          }
      }
      

      运行效果:

      在这里插入图片描述

  • 循环判断

    • 循环

      模板文件(test.html.vm)

      ## 定义一个集合
      #set($list=["春", "夏", "秋", "冬"])
      ## 遍历循环
      #foreach($item in $list)
          [$foreach.index]$item <br/>
      #end
      

      $foreach.index是从0开始的,$foreach.count是从1开始的

      输出效果:

      在这里插入图片描述

    • 判断

      判断的语法:#if(condition) … #elseif(condition) … #else … #end

      在这里插入图片描述

  • 模板阅读

    • domain

      在这里插入图片描述

    • 其他controller、service、mapper类似

  • lombok集成

    首先,确认在common模块中导入了坐标

    <!--  lombok工具-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    

    domain.java.vm中,导包

    import lombok.Builder;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    

    写注解

    ## lombook集成
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    

    删除手写get和set(包括子表)

    #foreach ($column in $columns)
    #if(!$table.isSuperColumn($column.javaField))
    #if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
    #set($AttrName=$column.javaField)
    #else
    #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
    #end
        public void set${AttrName}($column.javaType $column.javaField) 
        {
            this.$column.javaField = $column.javaField;
        }
    
        public $column.javaType get${AttrName}() 
        {
            return $column.javaField;
        }
    #end
    #end
    
    #if($table.sub)
        public List<${subClassName}> get${subClassName}List()
        {
            return ${subclassName}List;
        }
    
        public void set${subClassName}List(List<${subClassName}> ${subclassName}List)
        {
            this.${subclassName}List = ${subclassName}List;
        }
    
    #end
    

    重写toString的方法,以及相关的导包也要删除

    import org.apache.commons.lang3.builder.ToStringBuilder;
    import org.apache.commons.lang3.builder.ToStringStyle;
    
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            #foreach ($column in $columns)
            #if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
            #set($AttrName=$column.javaField)
            #else
            #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
            #end
            .append("${column.javaField}", get${AttrName}())
            #end
            #if($table.sub)
            .append("${subclassName}List", get${subClassName}List())
            #end
            .toString();
    }
    

    从代码预览可以看出,lombok集成成功

    在这里插入图片描述

  • swagger集成

    首先,确认在common模块中导入了坐标

    <!-- knife4j -->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>3.0.3</version>
    </dependency>
    

    在controller中集成,

    @Api(tags = "${functionName}")
    @RestController
    @RequestMapping("/${moduleName}/${businessName}")
    public class ${ClassName}Controller extends BaseController
    {
        // ...
    }       
    
    /**
         * 查询${functionName}列表
         */
    @ApiOperation("查询${functionName}列表")
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
    @GetMapping("/list")
    #if($table.crud || $table.sub)
    public TableDataInfo list(${ClassName} ${className})
    {
        // ...
    }
    

    同样,其他方法也添加相应的swagger注解,用于描述该方法的功能

    但是,返回对象AjaxResult默认继承了HashMap,与swagger不兼容,我们需要将返回类型改为R类型返回

    public R add(@RequestBody ${ClassName} ${className})
    {
        // 核心修改:toAjax()改为R.ok()
        return R.ok(${className}Service.insert${ClassName}(${className}));
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值