这个主要是黑马的ihrm课程中讲的代码生成器的部分内容。


文章目录

  • 应用场景
  • 第一个FreeMarker程序(数据+模板 = 文件输出)
  • 概述
  • 数据模型
  • 模板的常用标签
  • 模板的常用指令
  • 元数据
  • 数据库元数据
  • 参数元数据
  • 结果集元数据
  • 代码生成器
  • 思路分析
  • 搭建环境
  • 导入坐标
  • 配置实体类
  • 导入工具类
  • 代码生成器实现
  • 构造数据模型
  • 数据分析
  • 自定义数据
  • 元数据处理
  • 路径处理
  • 制作模板
  • 模板的约定
  • 需求分析
  • SpringBoot通用模板
  • 实体类
  • 持久化层
  • Service层
  • Controller
  • 配置文件



页面=模板+数据模型


freemarke 生成目录_元数据


FreeMarker 不是 Web 应用框架。它是 Web 应用框架中的一个适用的组件,但是FreeMarker 引擎本身并不知道


HTTP 协议或 Servlet。它仅仅来生成文本。即便这样,它也非常适用于非 Web 应用环境的开发

应用场景

动态页面
基于模板配置和表达式生成页面文件,可以像jsp一样被客户端访问
页面静态化
对于系统中频繁使用数据库进行查询但是内容更新很小的应用,都可以用FreeMarker将网页静态化,这样就避免
了大量的数据库访问请求,从而提高网站的性能

代码生成器
可以自动根据后台配置生成页面或者代码

第一个FreeMarker程序(数据+模板 = 文件输出)

先导入依赖

<!--        freemarker核心包-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>

创建模板:

欢迎您:${username}
public class testFreemarker01 {
    
    @Test
    public void test01() throws Exception {
        // 1.创建FreeMarker配置类
        Configuration cfg = new Configuration();

        //2. 指定模板加速器: 将模板存入缓存
        // 文件路径加载器
        FileTemplateLoader ftl = new FileTemplateLoader(new File("templates"));
        cfg.setTemplateLoader(ftl);

        // 3. 获取模板
        Template template = cfg.getTemplate("template01.ftl");

        // 4. 构造数据模型
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("username","ZHNSHknlnd");
        dataModel.put("flag",1);

        List<String> list = new ArrayList<>();
        list.add("星期一");
        list.add("星期二");
        list.add("星期三");
        list.add("星期四");
        list.add("星期五");

        dataModel.put("weeks",list);


        // 5.文件输出
        /**
        * 参数一:数据模型
        * 参数二:writer(FileWriter(文件输出),printWriter(控制台输出))
        */
//        template.process(dataModel, new FileWriter("E:\\tmp\\a.txt"));
        template.process(dataModel,new PrintWriter(System.out));
    }
}

其实Java代码是其次的,最重要的还是模板最重要的。

概述

FreeMarker模板文件主要有5个部分组成:

  1. 数据模型:模板能用的所有数据
  2. 文本,直接输出的部分
  3. 注释,即<#–…–>格式不会输出
  4. 插值(Interpolation):即${…}或者#{…}格式的部分,将使用数据模型中的部分替代输出
  5. FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出。

数据模型

FreeMarker(还有模板开发者)并不关心数据是如何计算的,FreeMarker 只是知道真实的数据是什么。模板能用的所有数据被包装成 data-model 数据模型

freemarke 生成目录_freemarke 生成目录_02

模板的常用标签

在FreeMarker模板中可以包括下面几个特定部分:

  1. ${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代。
  • ${name}可以取得root中key为name的value。
  • ${}可以取得成员变量为person的name属性
  1. <#…>:FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分
  2. <@>:宏,自定义标签
  3. 注释:包含在<#–和–>(而不是)之间

模板的常用指令

  • if指令
    分支控制语句
<#if condition>
     ....
      <#elseif condition2>
     ...
      <#elseif condition3>      
     ...
      <#else>
     ...
      </#if>
  • list、break指令
    list指令时一个典型的迭代输出指令,用于迭代输出数据模型中的集合
<#list sequence as item>
         ...
       </#list>
   除此之外,迭代集合对象时,还包括两个特殊的循环变量:
       a、item_index:当前变量的索引值。
       b、item_has_next:是否存在下一个对象
       也可以使用<#break>指令跳出迭代
        <#list ["星期一","星期二","星期三","星期四","星期五"] as x>
           ${x_index +1}.${x} <#if x_has_next>,</#if>
            <#if x = "星期四"><#break></#if>
        </#list>
  • include 指令
    include指令的作用类似于JSP的包含指令,用于包含指定页,include指令的语法格式如下
<#include filename [options]></#include>
           在上面的语法格式中,两个参数的解释如下
           a、filename:该参数指定被包含的模板文件
           b、options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding 
  指定包含页面时所使用的解码集,而parse指定被
           包含是否作为FTL文件来解析。如果省略了parse选项值,则该选项值默认是true
  • assign指令
    它用于为该模板页面创建或替换一个顶层变量
<#assign name = zhangsan />
  • 内置函数
    FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可通过内建函
    数来转换输出变量。下面是常用的内建的字符串函数:
?html:html字符转义
  
         ?cap_first: 字符串的第一个字母变为大写形式
  
         ?lower_case :字符串的小写形式
  
         ?upper_case :字符串的大写形式
  
         ?trim:去掉字符串首尾的空格
  
         ?substring:截字符串
  
         ?lenth: 取长度
  
         ?size: 序列中元素的个数
  
         ?int : 数字的整数部分(比如- 1.9?int 就是- 1)
         
		 ?replace:字符串替换

元数据

数据库元数据

(1)元数据(MetaData),是指定义数据结构的数据。那么数据库元数据就是指定义数据库各类对象结构的数据。 例如数据库中的数据库名,表明, 列名、用户名、版本名以及从SQL语句得到的结果中的大部分字符串是元数据
(2)数据库元数据的作用
在应用设计时能够充分地利用数据库元数据深入理解了数据库组织结构,再去理解数据访问相关框架的实现原理会更加容易。
(3)如何获取元数据
在我们前面使用JDBC来处理数据库的接口主要有三个,即Connection,PreparedStatement和ResultSet这三个,而对于这三个接口,还可以获取不同类型的元数据,通过这些元数据类获得一些数据库的信息。下面将对这三种类
型的元数据对象进行各自的介绍并通过使用MYSQL数据库进行案例说明(部分代码再不同数据库中略有不同,学员如有其他需求请查阅API)
数据库元数据(DatabaseMetaData):是由Connection对象通过getMetaData方法获取而来,主要封装了是对
数据库本身的一些整体综合信息,例如数据库的产品名称,数据库的版本号,数据库的URL,是否支持事务等等。
以下有一些关于DatabaseMetaData的常用方法:

  • getDatabaseProductName:获取数据库的产品名称
  • getDatabaseProductName:获取数据库的版本号
  • getUserName:获取数据库的用户名
  • getURL:获取数据库连接的URL
  • getDriverName:获取数据库的驱动名称
  • driverVersion:获取数据库的驱动版本号
  • isReadOnly:查看数据库是否只允许读操作
  • supportsTransactions:查看数据库是否支持事务

获取数据库综合信息

public class DataBaseMetaDataTest {
    private Connection conn;
    @Before
    public void init() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Properties props =new Properties();
        //设置连接属性,使得可获取到表的REMARK(备注)
        props.put("remarksReporting","true");
        props.put("user", "root");
        props.put("password", "111111");
        conn = java.sql.DriverManager.
                getConnection("jdbc:mysql://127.0.0.1:3306/?
useUnicode=true&characterEncoding=UTF8", props);
   }
    @Test
    public void testDatabaseMetaData() throws SQLException {
        //获取数据库元数据
        DatabaseMetaData dbMetaData =  conn.getMetaData();
        //获取数据库产品名称
        String productName = dbMetaData.getDatabaseProductName();
        System.out.println(productName);
        //获取数据库版本号
        String productVersion = dbMetaData.getDatabaseProductVersion();
        System.out.println(productVersion);
        //获取数据库用户名
        String userName = dbMetaData.getUserName();
        System.out.println(userName);
        //获取数据库连接URL
        String userUrl = dbMetaData.getURL();
        System.out.println(userUrl);
        //获取数据库驱动
        String driverName = dbMetaData.getDriverName();
        System.out.println(driverName);
        //获取数据库驱动版本号
        String driverVersion = dbMetaData.getDriverVersion();
        System.out.println(driverVersion);
        //查看数据库是否允许读操作
        boolean isReadOnly = dbMetaData.isReadOnly();
        System.out.println(isReadOnly);
        //查看数据库是否支持事务操作
        boolean supportsTransactions = dbMetaData.supportsTransactions();
        System.out.println(supportsTransactions);
   }
}

获取数据库列表

@Test
    public void testFindAllCatalogs() throws Exception {
        //获取元数据
        DatabaseMetaData metaData = conn.getMetaData();
        //获取数据库列表
        ResultSet rs = metaData.getCatalogs();
        //遍历获取所有数据库表
        while(rs.next()){
            //打印数据库名称
            System.out.println(rs.getString(1));
       }
        //释放资源
        rs.close();
        conn.close();
   }

获取数据库中的所有表信息

@Test
    public void testFindAllTable() throws Exception{
        //获取元数据
        DatabaseMetaData metaData = conn.getMetaData();
        //获取所有的数据库表信息
        ResultSet tablers = metaData.getTables("ihrm", "", "bs_user", new String[]
{"TABLE"});
        //拼装table
        while(tablers.next()) {
            //所属数据库
            System.out.println(tablers.getString(1));
            //所属schema
            System.out.println(tablers.getString(2));
            //表名
            System.out.println(tablers.getString(3));
            //数据库表类型
            System.out.println(tablers.getString(4));
            //数据库表备注
            System.out.println(tablers.getString(5));
       }
   }

参数元数据

参数元数据(ParameterMetaData):是由PreparedStatement对象通过getParameterMetaData方法获取而来,主要是针对PreparedStatement对象和其预编译的SQL命令语句提供一些信息,ParameterMetaData能提供占位符参数的个数,获取指定位置占位符的SQL类型等等。
以下有一些关于ParameterMetaData的常用方法:

  • getParameterCount:获取预编译SQL语句中占位符参数的个数
/**
 * 测试参数元数据ParameterMetaData
 *      通过PreparedStatement获取
 *      获取sql参数中的属性信息
 */
public class ParameterMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=utf8&useSSL=false";
        String username = "root";
        String password = "root";

        Properties properties = new Properties();
        properties.put("user",username);
        properties.put("password",password);
        properties.put("remarkReporting","true");   // 获取数据库的备注信息

        // 1. 获取连接
        Class.forName(driver); // 注册驱动
        connection = DriverManager.getConnection(url,properties);

    }
    @Test
    public void test() throws Exception {
        String sql = "select * from bs_user where id=?";
        PreparedStatement pstmt = connection.prepareStatement(sql);
        pstmt.setString(1, "1063705482939731968");
        //获取ParameterMetaData对象
        ParameterMetaData paramMetaData = pstmt.getParameterMetaData();
        //获取参数个数
        int paramCount = paramMetaData.getParameterCount();
        System.out.println(paramCount);
    }
}

结果集元数据

结果集元数据(ResultSetMetaData):是由ResultSet对象通过getMetaData方法获取而来,主要是针对由数据
库执行的SQL脚本命令获取的结果集对象ResultSet中提供的一些信息,比如结果集中的列数、指定列的名称、指定
列的SQL类型等等,可以说这个是对于框架来说非常重要的一个对象。
以下有一些关于ResultSetMetaData的常用方法:

  • getColumnCount:获取结果集中列项目的个数
  • getColumnType:获取指定列的SQL类型对应于Java中Types类的字段
  • getColumnTypeName:获取指定列的SQL类型
  • getClassName:获取指定列SQL类型对应于Java中的类型(包名加类名)

代码生成器

思路分析

freemarke 生成目录_元数据_03


如上分析,得知完成代码生成器需要以下几个操作:

  1. 用户填写的数据库信息,工程搭建信息需要构造到实体类对象中方便操作
  2. 数据库表信息,数据库字段信息需要构造到实体类中
  3. 构造Freemarker数据模型,将数据库表对象和基本配置存入到Map集合中
  4. 借助Freemarker完成代码生成
  5. 自定义公共代码模板

搭建环境

导入坐标

<dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
</dependencies>

配置实体类

(1) UI页面获取的数据库配置,封装到数据库实体类中

//数据库实体类
public class DataBase {
    private static String mysqlUrl = "jdbc:mysql://[ip]:[port]/[db]?
useUnicode=true&characterEncoding=UTF8";
    private static String oracleUrl = "jdbc:oracle:thin:@[ip]:[port]:[db]";
    private String dbType;//数据库类型
    private String driver;
    private String userName;
    private String passWord;
    private String url;
    public DataBase() {}
    public DataBase(String dbType) {
        this(dbType,"127.0.0.1","3306","");
   }
    public DataBase(String dbType,String db) {
        this(dbType,"127.0.0.1","3306",db);
   }
    public DataBase(String dbType,String ip,String port,String db) {
        this.dbType = dbType;
        if("MYSQL".endsWith(dbType.toUpperCase())) {
            this.driver="com.mysql.jdbc.Driver";
            this.url=mysqlUrl.replace("[ip]",ip).replace("[port]",port).replace("
[db]",db);
       }else{
            this.driver="oracle.jdbc.driver.OracleDriver";
            this.url=oracleUrl.replace("[ip]",ip).replace("[port]",port).replace("
[db]",db);
       }
   }
    public String getDbType() {
        return dbType;
   }
    public void setDbType(String dbType) {
        this.dbType = dbType;
   }
    public String getDriver() {
        return driver;
         }
    public void setDriver(String driver) {
        this.driver = driver;
   }
    public String getUserName() {
        return userName;
   }
    public void setUserName(String userName) {
        this.userName = userName;
   }
    public String getPassWord() {
        return passWord;
   }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
   }
    public String getUrl() {
        return url;
   }
    public void setUrl(String url) {
        this.url = url;
   }
}

(2) UI页面获取的自动生成工程配置,封装到设置实体类中

public class Settings {
    private String project="example";
    private String pPackage="com.example.demo";
    private String projectComment;
    private String author;
    private String path1="com";
    private String path2="example";
    private String path3="demo";
    private String pathAll;
    public Settings(String project, String pPackage, String projectComment, String
author) {
        if(StringHelper.isNotBlank(project)) {
            this.project = project;
       }
        if(StringHelper.isNotBlank(pPackage)) {
            this.pPackage = pPackage;
       }
        this.projectComment = projectComment;
           this.author = author;
        String[] paths = pPackage.split("\\.");
        path1 = paths[0];
        path2 = paths.length>1?paths[1]:path2;
        path3 = paths.length>2?paths[2]:path3;
        pathAll = pPackage.replaceAll(".","/");
   }
    public Map<String, Object> getSettingMap(){
        Map<String, Object> map = new HashMap<>();
        Field[] declaredFields = Settings.class.getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            try{
                map.put(field.getName(), field.get(this));
           }catch (Exception e){}
       }
        return map;
   }
    public String getProject() {
        return project;
   }
    public void setProject(String project) {
        this.project = project;
   }
    public String getpPackage() {
        return pPackage;
   }
    public void setpPackage(String pPackage) {
        this.pPackage = pPackage;
   }
    public String getProjectComment() {
        return projectComment;
   }
    public void setProjectComment(String projectComment) {
        this.projectComment = projectComment;
   }
    public String getAuthor() {
        return author;
   }
    public void setAuthor(String author) {
        this.author = author;
   }
    public String getPath1() {
     return path1;
   }
    public void setPath1(String path1) {
        this.path1 = path1;
   }
    public String getPath2() {
        return path2;
   }
    public void setPath2(String path2) {
        this.path2 = path2;
   }
    public String getPath3() {
        return path3;
   }
    public void setPath3(String path3) {
        this.path3 = path3;
   }
    public String getPathAll() {
        return pathAll;
   }
    public void setPathAll(String pathAll) {
        this.pathAll = pathAll;
   }
}

(3) 将查询数据表的元数据封装到Table实体类

public class Table {
 
 private String name;//表名称
 private String name2;//处理后的表名称
 private String comment;//介绍
 private String key;// 主键列
 private List<Column> columns;//列集合
 public String getName() {
 return name;
 }
 public void setName(String name) {
  = name;
 }
 public String getName2() {
 return name2;
 }
 public void setName2(String name2) {
 2 = name2;
 }
 public String getComment() {
 return comment;
 }
 public void setComment(String comment) {
 this.comment = comment;
 }
 public String getKey() {
 return key;
 }
 public void setKey(String key) {
 this.key = key;
 }
 public List<Column> getColumns() {
 return columns;
 }
 public void setColumns(List<Column> columns) {
 this.columns = columns;
 }
}

(4)将查询数据字段的元数据封装到Column实体类

/**
 * 列对象
*/
public class Column {
 
 private String columnName;//列名称
 private String columnName2;//列名称(处理后的列名称)
 private String columnType;//列类型
 private String columnDbType;//列数据库类型
 private String columnComment;//列备注D
 private String columnKey;//是否是主键
 public String getColumnName() {
 return columnName;
 }
 public void setColumnName(String columnName) {
 this.columnName = columnName;
 }
 public String getColumnName2() {
 return columnName2;
 }
 public void setColumnName2(String columnName2) {
 this.columnName2 = columnName2;
 }
 public String getColumnType() {
 return columnType;
 }
 public void setColumnType(String columnType) {
 this.columnType = columnType;
 }
 public String getColumnDbType() {
 return columnDbType;
 }
 public void setColumnDbType(String columnDbType) {
 this.columnDbType = columnDbType;
 }
 public String getColumnComment() {
 return columnComment;
 }
 public void setColumnComment(String columnComment) {
 this.columnComment = columnComment;
 }
 public String getColumnKey() {
 return columnKey;
 }
 public void setColumnKey(String columnKey) {
 this.columnKey = columnKey;
 }
}

导入工具类

freemarke 生成目录_元数据_04


freemarke 生成目录_数据库_05

代码生成器实现

  • 实现封装元数据的工具类
  • 实现代码生成器的代码编写
  • 掌握模板创建的

构造数据模型

数据分析

借助Freemarker机制可以方便的根据模板生成文件,同时也是组成代码生成器的核心部分。对于Freemarker而
言,其强调 数据模型 + 模板 = 文件 的思想,所以代码生成器最重要的一个部分之一就是数据模型。在这里数据
模型共有两种形式组成:

  • 数据库中表、字段等信息
    针对这部分内容,可以使用元数据读取并封装到java实体类中
  • 用户自定义的数据
    为了代码生成器匹配多样的使用环境,可以让用户自定义的数据,并且以key-value的形式配置到properties文件中

自定义数据

通过PropertiesUtils工具类,统一对properties文件夹下的所有 .properties 文件进行加载,并存入内存中

/**
* 需要将自定义的配置信息写入到properties文件中
* 配置到相对于工程的properties文件夹下
*/
public class PropertiesUtils {
    public static Map<String,String> customMap = new HashMap<>();
    static {
			File dir = new File("properties");
			try {
			List<File> files = FileUtils.searchAllFile(new
			File(dir.getAbsolutePath()));
			for (File file : files) {
			if(file.getName().endsWith(".properties")) {
			Properties prop = new Properties();
			prop.load(new FileInputStream(file));
			customMap.putAll((Map) prop);
			}
		}
			} catch (IOException e) {
			            e.printStackTrace();
			       }
			   }
	}

元数据处理

加载指定数据库表,将表信息转化为实体类对象(Table)

/**
     * 获取表及字段信息
     */
    public static List<Table> getDbInfo(DataBase db,String tableNamePattern) throws
Exception {
        //创建连接
        Connection connection = getConnection(db.getDriver(),db.getUserName(), 
db.getPassWord(), db.getUrl());
        //获取元数据
        DatabaseMetaData metaData = connection.getMetaData();
        //获取所有的数据库表信息
        ResultSet tablers = metaData.getTables(null, null, tableNamePattern, new
String[]{"TABLE"});
        List<Table> list=new ArrayList<Table>();
        //拼装table
        while(tablers.next()) {
            Table table = new Table();
            String tableName=tablers.getString("TABLE_NAME");
            //如果为垃圾表
            if(tableName.indexOf("=")>=0 || tableName.indexOf("$")>=0){
                continue;
           }
            table.setName(tableName);
            table.setComment(tablers.getString("REMARKS"));
            //获得主键
            ResultSet primaryKeys = metaData.getPrimaryKeys(null, null, tableName);
            List<String> keys=new ArrayList<String>();
            while(primaryKeys.next()){
                String keyname=primaryKeys.getString("COLUMN_NAME");
                //判断 表名为全大写 ,则转换为小写
                if(keyname.toUpperCase().equals(keyname)){
                    keyname=keyname.toLowerCase();//转换为小写
               }
                keys.add(keyname);
           }
            //获得所有列
            ResultSet columnrs = metaData.getColumns(null, null, tableName, null);
            List<Column> columnList=new ArrayList<Column>();
            while(columnrs.next()){
                Column column=new Column();
                //处理字段
                String columnName=  columnrs.getString("COLUMN_NAME");
                //字段名称
                column.setColumnName(columnName);
                column.setColumnName2(StringUtils.toJavaVariableName(columnName));
                //字段类型
                String columnDbType = columnrs.getString("TYPE_NAME");
                column.setColumnDbType(columnDbType);//数据库原始类型
                //java类型
                Map<String, String> convertMap = PropertiesUtils.customMap;
                String typeName = convertMap.get(columnDbType);//获取转换后的类型
                if(typeName==null) {
                    typeName=columnrs.getString("TYPE_NAME");
               }
                column.setColumnType(typeName);
                String remarks = columnrs.getString("REMARKS");//备注
                column.setColumnComment(StringUtils.isBlank(remarks)?
columnName:remarks);
                //如果该列是主键
                if(keys.contains(columnName)){
                    column.setColumnKey("PRI");
                    table.setKey(column.getColumnName());
               }else {
                    column.setColumnKey("");
               }
                columnList.add(column);
           }
            columnrs.close();
            table.setColumns(columnList);
            list.add(table );
       }
        tablers.close();
        connection.close();
            return list;
   }

路径处理

使用字符串模板对文件生成路径进行统一处理

//处理字符串模板
    private String processTemplateString(String templateString,Map dataMap) throws
Exception {
        StringWriter out = new StringWriter();
        Template template = new Template("ts",new StringReader(templateString),conf);
        template.process(dataMap, out);
        return out.toString();
   }

制作模板

不同的工程需要的模板不一样。

模板的约定

(1)模板位置

模板统一放置到相对于当前路径的 模板 文件夹下

freemarke 生成目录_数据库_06


(2)自定义数据

自定义的数据以 .propeties 文件(key-value)的形式存放入相对于当前路径的 properties 文件夹下

(3)数据格式

freemarke 生成目录_spring boot_07


table中数据内容:

freemarke 生成目录_元数据_08

需求分析

制作通用的SpringBoot程序的通用模板

  • 实体类
    类路径,类名,属性列表(getter,setter方法)
  • 持久化层
    类路径,类名,引用实体类
  • 业务逻辑层
    类路径,类名,引用实体类,引用持久化层代码
  • 视图层
    类路径,类名,引用实体类,引用业务逻辑层代码,请求路径
  • 配置文件
    pom文件,springboot配置文件

SpringBoot通用模板

实体类

package ${pPackage}.pojo;
import javax.persistence.Entity;
import ;
import javax.persistence.Table;
/**
* ${comment!}服务层
* @author ${author!"itcast"}
*/
@Entity
@Table(name="${table.name}")
public class ${ClassName} implements Serializable {
 //定义私有属性
 <#list table.columns as column>
 <#if column.columnKey??>
 @Id
 </#if>
 private ${column.columnType} ${column.columnName2};
 </#list>
 
 //处理getter,setter方法
 <#list table.columns as column>
 public void set${column.columnName2?cap_first}(${column.columnType} value) {
 this.${column.columnName2} = value;
 }
 
 public ${column.columnType} get${column.columnName2?cap_first}() {
 return this.${column.columnName2};
 }
 </#list>
}

持久化层

package ${pPackage}.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import ${pPackage}.pojo.${ClassName};
/**
* ${comment!}数据访问接口
* @author ${author!"itcast"}
*/
public interface ${ClassName}Dao extends
JpaRepository<${ClassName},String>,JpaSpecificationExecutor<${ClassName}>{
 
}

Service层

<#assign classNameLower = ClassName ? uncap_first>
package ${pPackage}.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import util.IdWorker;
import ${pPackage}.dao.${ClassName}Dao;
import ${pPackage}.pojo.${ClassName};
/**
* ${comment!}服务层
* @author ${author!"itcast"}
*/
@Service
public class ${ClassName}Service {
 @Autowired
 private ${ClassName}Dao ${classNameLower}Dao;
 
 @Autowired
 private IdWorker idWorker;
 /**
 * 查询全部列表
 * @return
 */
 public List<${ClassName}> findAll() {
 return ${classNameLower}Dao.findAll();
 }
 /**
 * 分页查询
 *
 * @param page
 * @param size
 * @return
 */
 public Page<${ClassName}> findPage(int page, int size) {
 PageRequest pageRequest = PageRequest.of(page-1, size);
 return ${classNameLower}Dao.findAll(pageRequest);
 }
 /**
 * 根据ID查询实体
 * @param id
 * @return
 */
 public ${ClassName} findById(String id) {
 return ${classNameLower}Dao.findById(id).get();
 }
 /**
 * 增加
 * @param ${ClassName}
 */
 public void add(${ClassName} ${ClassName}) {
 ${ClassName}.setId( idWorker.nextId()+"" );
 ${classNameLower}Dao.save(${ClassName});
 }
 /**
 * 修改
 * @param ${ClassName}
 */
 public void update(${ClassName} ${ClassName}) {
 ${classNameLower}Dao.save(${ClassName});
 }
 /**
 * 删除
 * @param id
 */
 public void deleteById(String id) {
 ${classNameLower}Dao.deleteById(id);
 }
}

Controller

<#assign classNameLower = ClassName ? uncap_first>
package ${pPackage}.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ${pPackage}.pojo.${ClassName};
import ${pPackage}.service.${ClassName}Service;
import entity.PageResult;
import entity.Result;
/**
* [comment]控制器层
* @author Administrator
*
*/
@RestController
@CrossOrigin
@RequestMapping("/${classNameLower}")
public class ${ClassName}Controller {
 @Autowired
 private ${ClassName}Service ${classNameLower}Service;
 
 
 /**
 * 查询全部数据
 * @return
 */
 @RequestMapping(method= RequestMethod.GET)
 public Result findAll(){
 return new Result(ResultCode.SUCCESS,${classNameLower}Service.findAll());
 }
 
 /**
 * 根据ID查询
 * @param id ID
 * * @return
 */
 @RequestMapping(value="/{id}",method= RequestMethod.GET)
 public Result findById(@PathVariable String id){
 return new Result(ResultCode.SUCCESS,${classNameLower}Service.findById(id));
 }
 /**
 * 分页查询全部数据
 * @param page
 * @param size
 * @return
 */
 @RequestMapping(value="/{page}/{size}",method=RequestMethod.GET)
 public Result findPage(@PathVariable int page,@PathVariable int size){
 Page<${ClassName}> searchPage = ${classNameLower}Service.findPage(page, size);
 PageResult<Role> pr = new
PageResult(searchPage.getTotalElements(),searchPage.getContent());
 return new Result(ResultCode.SUCCESS,pr);
 }
 /**
 * 增加
 * @param ${classNameLower}
 */
 @RequestMapping(method=RequestMethod.POST)
 public Result add(@RequestBody ${ClassName} ${classNameLower} ){
 ${classNameLower}Service.add(${classNameLower});
 return new Result(ResultCode.SUCCESS);
 }
 
 /**
 * 修改
 * @param ${classNameLower}
 */
 @RequestMapping(value="/{id}",method= RequestMethod.PUT)
 public Result update(@RequestBody ${ClassName} ${classNameLower}, @PathVariable
String id ){
 ${classNameLower}.setId(id);
 ${classNameLower}Service.update(${classNameLower}); 
 return new Result(ResultCode.SUCCESS);
 }
 
 /**
 * 删除
 * @param id
 */
 @RequestMapping(value="/{id}",method= RequestMethod.DELETE)
 public Result delete(@PathVariable String id ){
 ${classNameLower}Service.deleteById(id);
 return new Result(ResultCode.SUCCESS);
 }
}

配置文件

(1)application.yml

server: 
 port: 9001
spring: 
 application:  
   name: ${project}-${path3} #指定服务名
 datasource:  
   driverClassName: ${driverName}
   url: ${url}
   username: ${dbuser}
   password: ${dbpassword}
 jpa: 
   database: MySQL
   show-sql: true

(2)pom.xml

<project xmlns="http:///POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 
http:///xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>${path_1}.${path2}</groupId>
    <artifactId>${project}_parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>${project}_${path3}</artifactId>
  <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <dependency>
 <groupId>${path1}.${path2}</groupId>
 <artifactId>${project}_common</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 </dependency>
  </dependencies>  
</project>

目前的代码生成器其实只是一个简单的示例,还有很多的问题,重点是了解freemarker的模板作用。