https://blog.csdn.net/huangwenyi1010/article/details/71249258

版权声明:我已委托“维权骑士”(rightknights.com)为我的文章进行维权行动 https://blog.csdn.net/huangwenyi1010/article/details/71249258

开心一笑

【1.你以为我会眼睁睁的看着你去送死?我会闭着眼睛。2.给你讲个故事,从前有个笨蛋,他非常笨,别人问他问题他只会回答“没有”,这个故事你听过吗?】

视频教程

大家好,我录制的视频《Java之优雅编程之道》已经在CSDN学院发布了,有兴趣的同学可以购买观看,相信大家一定会收获到很多知识的。谢谢大家的支持……

视频地址:http://edu.csdn.net/lecturer/994

提出问题

如何利用 Java + Freemarker 实现代码生成器???

解决问题

* 前言 *

做业务开发的时候,经常要根据建立好的数据库表,生成相关的 Model , DTO , Service, Controller , DAO 等等。包括基本的增删改查。而这些细活往往比较简单且没有挑战性,纯粹苦力活。因此,根据公司的框架,开发一个代码生成器是很有必要的。

这里: 
假如你有一定的java基础; 
假如你熟悉freemarker模板引擎; 
假如你熟悉MVC框架; 
假如你熟悉Spring Data 框架

* 技术选型 *

由于代码生成器是要生成很多文件的,包 Test.java , TestDTO.java ,TestController.java , TestServiceImpl.java , ITestService.java , TestDAO.java 等等这些文件。所有考虑用 freemarker 强大的模板引擎,制作相关的模板。

* 实现思路 *

首先,假如在数据库中有一张表 ay_test.

CREATE TABLE "public"."ay_test" (
"id" varchar(32) COLLATE "default" NOT NULL,
"name" varchar(10) COLLATE "default",
"birth_date" timestamp(6),
"remark" text COLLATE "default",
CONSTRAINT "ay_test_pkey" PRIMARY KEY ("id")
)
我们首先要获取数据库的连接,这里我只贴出相关的代码。
private final String URL = "jdbc:postgresql://192.168.3.160:10655/cibpm";
private final String USER = "postgres";
private final String PASSWORD = "888888";
private final String DRIVER = "org.postgresql.Driver"; public Connection getConnection() throws Exception{
Class.forName(DRIVER);
Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
return connection;
}

获取数据库表的元数据

private final String changeTableName = replaceUnderLineAndUpperCase(tableName);

Connection connection = getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");

最后根据元数据获取表字段,注释等等,生成相关的文件

代码实现

Java代码实现

package com.evada.inno.pm.code.generate.util;
import com.evada.inno.pm.code.generate.model.ColumnClass; import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils; import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 描述:代码生成器
* Created by Ay on 2017/5/1.
*/
public class CodeGenerateUtils { private final String AUTHOR = "Ay";
private final String CURRENT_DATE = "2017/05/03";
private final String tableName = "tm_project_quality_problem";
private final String packageName = "com.evada.pm.process.manage";
private final String tableAnnotation = "质量问题";
private final String URL = "jdbc:postgresql://192.168.3.160:10655/cibpm";
private final String USER = "postgres";
private final String PASSWORD = "888888";
private final String DRIVER = "org.postgresql.Driver";
private final String diskPath = "D://";
private final String changeTableName = replaceUnderLineAndUpperCase(tableName); public Connection getConnection() throws Exception{
Class.forName(DRIVER);
Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
return connection;
} public static void main(String[] args) throws Exception{
CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
codeGenerateUtils.generate();
} public void generate() throws Exception{
try {
Connection connection = getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");
//生成Mapper文件
generateMapperFile(resultSet);
//生成Dao文件
generateDaoFile(resultSet);
//生成Repository文件
generateRepositoryFile(resultSet);
//生成服务层接口文件
generateServiceInterfaceFile(resultSet);
//生成服务实现层文件
generateServiceImplFile(resultSet);
//生成Controller层文件
generateControllerFile(resultSet);
//生成DTO文件
generateDTOFile(resultSet);
//生成Model文件
generateModelFile(resultSet);
} catch (Exception e) {
throw new RuntimeException(e);
}finally{ }
} private void generateModelFile(ResultSet resultSet) throws Exception{ final String suffix = ".java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Model.ftl";
File mapperFile = new File(path);
List<ColumnClass> columnClassList = new ArrayList<>();
ColumnClass columnClass = null;
while(resultSet.next()){
//id字段略过
if(resultSet.getString("COLUMN_NAME").equals("id")) continue;
columnClass = new ColumnClass();
//获取字段名称
columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
//获取字段类型
columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
//转换字段名称,如 sys_name 变成 SysName
columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
//字段在数据库的注释
columnClass.setColumnComment(resultSet.getString("REMARKS"));
columnClassList.add(columnClass);
}
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("model_column",columnClassList);
generateFileByTemplate(templateName,mapperFile,dataMap); } private void generateDTOFile(ResultSet resultSet) throws Exception{
final String suffix = "DTO.java";
final String path = "D://" + changeTableName + suffix;
final String templateName = "DTO.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap);
} private void generateControllerFile(ResultSet resultSet) throws Exception{
final String suffix = "Controller.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Controller.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap);
} private void generateServiceImplFile(ResultSet resultSet) throws Exception{
final String suffix = "ServiceImpl.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "ServiceImpl.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap);
} private void generateServiceInterfaceFile(ResultSet resultSet) throws Exception{
final String prefix = "I";
final String suffix = "Service.java";
final String path = diskPath + prefix + changeTableName + suffix;
final String templateName = "ServiceInterface.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap);
} private void generateRepositoryFile(ResultSet resultSet) throws Exception{
final String suffix = "Repository.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Repository.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap);
} private void generateDaoFile(ResultSet resultSet) throws Exception{
final String suffix = "DAO.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "DAO.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap); } private void generateMapperFile(ResultSet resultSet) throws Exception{
final String suffix = "Mapper.xml";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Mapper.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,dataMap); } private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
FileOutputStream fos = new FileOutputStream(file);
dataMap.put("table_name_small",tableName);
dataMap.put("table_name",changeTableName);
dataMap.put("author",AUTHOR);
dataMap.put("date",CURRENT_DATE);
dataMap.put("package_name",packageName);
dataMap.put("table_annotation",tableAnnotation);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
template.process(dataMap,out);
} public String replaceUnderLineAndUpperCase(String str){
StringBuffer sb = new StringBuffer();
sb.append(str);
int count = sb.indexOf("_");
while(count!=0){
int num = sb.indexOf("_",count);
count = num + 1;
if(num != -1){
char ss = sb.charAt(count);
char ia = (char) (ss - 32);
sb.replace(count , count + 1,ia + "");
}
}
String result = sb.toString().replaceAll("_","");
return StringUtils.capitalize(result);
} }
FreeMarkerTemplateUtils工具类

FreeMarkerTemplateUtils工具类用来配置模板所在的路径

package com.evada.inno.pm.code.generate.util;

import com.evada.inno.core.exception.BusinessException;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler; import java.io.IOException; /**
* Created by Ay on 2016/7/27.
*/
public class FreeMarkerTemplateUtils { private FreeMarkerTemplateUtils(){}
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22); static{
//这里比较重要,用来指定加载模板所在的路径
CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/templates"));
CONFIGURATION.setDefaultEncoding("UTF-8");
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
} public static Template getTemplate(String templateName) throws IOException {
try {
return CONFIGURATION.getTemplate(templateName);
} catch (IOException e) {
throw e;
}
} public static void clearCache() {
CONFIGURATION.clearTemplateCache();
}
}
实体类 ColumnClass

ColumnClass 用来封装 数据库表元数据的信息,如字段名称,字段类型,字段注释等等。

package com.evada.inno.pm.code.generate.model;

/**
* 数据库字段封装类
* Created by Ay on 2017/5/3.
*/
public class ColumnClass { /** 数据库字段名称 **/
private String columnName;
/** 数据库字段类型 **/
private String columnType;
/** 数据库字段首字母小写且去掉下划线字符串 **/
private String changeColumnName;
/** 数据库字段注释 **/
private String columnComment; public String getColumnComment() {
return columnComment;
} public void setColumnComment(String columnComment) {
this.columnComment = columnComment;
} public String getColumnName() {
return columnName;
} public void setColumnName(String columnName) {
this.columnName = columnName;
} public String getColumnType() {
return columnType;
} public void setColumnType(String columnType) {
this.columnType = columnType;
} public String getChangeColumnName() {
return changeColumnName;
} public void setChangeColumnName(String changeColumnName) {
this.changeColumnName = changeColumnName;
}
}

freemarker 模板文件

Freemarker的模板文件,后缀都是以ftl结尾的。

Model.ftl模型模板

Model.ftl可以生成字段的属性,并且可以生成字段属性对应的 set 和 get 方法,包括字段在数据库中对应的注释,以及一些该引入的包和类注释。

package ${package_name}.model;
import com.evada.inno.common.domain.BaseModel;
import com.evada.inno.common.listener.ICreateListenable;
import com.evada.inno.common.listener.IDeleteListenable;
import com.evada.inno.common.listener.IModifyListenable;
import org.hibernate.annotations.Where;
import javax.persistence.*;
import java.util.Date; /**
* 描述:${table_annotation}模型
* @author ${author}
* @date ${date}
*/
@Entity
@Table(name="${table_name_small}")
@Where(clause = "status > '0'")
@Inheritance(strategy= InheritanceType.SINGLE_TABLE)
public class ${table_name} extends BaseModel implements ICreateListenable,IModifyListenable,IDeleteListenable { <#if model_column?exists>
<#list model_column as model>
/**
*${model.columnComment!}
*/
<#if (model.columnType = 'varchar' || model.columnType = 'text')>
@Column(name = "${model.columnName}",columnDefinition = "VARCHAR")
private String ${model.changeColumnName?uncap_first}; </#if>
<#if model.columnType = 'timestamp' >
@Column(name = "${model.columnName}",columnDefinition = "TIMESTAMP")
private Date ${model.changeColumnName?uncap_first}; </#if>
</#list>
</#if> <#if model_column?exists>
<#list model_column as model>
<#if (model.columnType = 'varchar' || model.columnType = 'text')>
public String get${model.changeColumnName}() {
return this.${model.changeColumnName?uncap_first};
} public void set${model.changeColumnName}(String ${model.changeColumnName?uncap_first}) {
this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};
} </#if>
<#if model.columnType = 'timestamp' >
public Date get${model.changeColumnName}() {
return this.${model.changeColumnName?uncap_first};
} public void set${model.changeColumnName}(Date ${model.changeColumnName?uncap_first}) {
this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};
} </#if>
</#list>
</#if> }
DTO.ftl模板

DTO.ftl 文件用来生产 DTO 值对象,该对象继承 Model.ftl 文件中的对象。

package ${package_name}.dto;

import ${package_name}.model.${table_name};

/**
* 描述:${table_annotation}DTO
* @author ${author}
* @date ${date}
*/
public class ${table_name}DTO extends ${table_name}{ }
Service.ftl模板

Service.ftl 模板用来生成服务层实现类,在模板中已经添加了增 ,删,改,查等方法,同时可以注入DAO和repository 到service中,一旦文件生成,就不需要我们去写了,很方便,提高开发的效率。

package ${package_name}.service.impl;
import com.evada.inno.core.service.impl.BaseServiceImpl;
import ${package_name}.model.${table_name};
import ${package_name}.repository.${table_name}Repository;
import ${package_name}.service.I${table_name}Service;
import ${package_name}.repository.mybatis.${table_name}DAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ${package_name}.dto.${table_name}DTO;
import org.apache.commons.beanutils.BeanUtils;
import com.evada.inno.core.enums.StatusEnum; /**
* 描述:${table_annotation} 服务实现层
* @author ${author}
* @date ${date}
*/
@Service
public class ${table_name}ServiceImpl extends BaseServiceImpl<${table_name}, String> implements I${table_name}Service { @Autowired
private ${table_name}DAO ${table_name?uncap_first}DAO; @Autowired
private ${table_name}Repository ${table_name?uncap_first}Repository; @Override
public ${table_name}DTO findDTOById(String id) throws Exception {
${table_name}DTO ${table_name?uncap_first}DTO = ${table_name?uncap_first}DAO.findDTOById(id);
return ${table_name?uncap_first}DTO;
} @Override
public ${table_name}DTO create${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {
${table_name} ${table_name?uncap_first} = new ${table_name}();
BeanUtils.copyProperties(${table_name?uncap_first},${table_name?uncap_first}DTO);
${table_name?uncap_first}.setStatus(StatusEnum.ENABLE.toString());
${table_name?uncap_first} = ${table_name?uncap_first}Repository.saveAndFlush(${table_name?uncap_first});
return this.findDTOById(${table_name?uncap_first}.getId());
} @Override
public ${table_name}DTO update${table_name}(${table_name}DTO ${table_name?uncap_first}DTO)throws Exception {
${table_name} ${table_name?uncap_first} = new ${table_name}();
BeanUtils.copyProperties(${table_name?uncap_first},${table_name?uncap_first}DTO);
${table_name?uncap_first} = ${table_name?uncap_first}Repository.saveAndFlush(${table_name?uncap_first});
return this.findDTOById(${table_name?uncap_first}.getId());
}
Interface.ftl 模板

Interface.ftl 用来生成服务层接口,接口中定义了增,删,改,查等接口。

package ${package_name}.service;
import com.evada.inno.core.service.IBaseService;
import ${package_name}.model.${table_name};
import ${package_name}.dto.${table_name}DTO;
/**
* 描述:${table_annotation} 服务实现层接口
* @author ${author}
* @date ${date}
*/
public interface I${table_name}Service extends IBaseService<${table_name},String> { /**
* 描述:根据Id获取DTO
* @param id
*/
${table_name}DTO findDTOById(String id)throws Exception; ${table_name}DTO create${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception; void delete${table_name}(String id) throws Exception; ${table_name}DTO update${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception; }
Respontory.ftl 模板

Respontory.ftl 用来生成 Repository 文件,这一块是 Spring Data的内容,可能不同的公司,使用的框架不一样。

package ${package_name}.repository;
import com.evada.inno.core.repository.BaseJpaRepository;
import ${package_name}.model.${table_name}; /**
* 描述:${table_annotation} Repository接口
* @author ${author}
* @date ${date}
*/
public interface ${table_name}Repository extends BaseJpaRepository<${table_name}, String> { }
Mappter.ftl 模板

Mappter.ftl 用来生成 MyBatis 使用到的 mappter 文件,在文件中,定义了查询的sql语句。

<?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_name}.repository.mybatis.${table_name}DAO"> <resultMap id="${table_name}DTOResultMap" type="${package_name}.dto.${table_name}DTO"></resultMap> <sql id="findDtoSql">
select * from (
select * from ${table_name_small} temp
) t
</sql> <select id="findDTOById" parameterType="String" resultMap="${table_name}DTOResultMap">
<include refid="findDtoSql"></include>
<where>
and t.id = ${r'#{id}'}
</where>
</select> <select id="find${table_name}Page" parameterType="${package_name}.dto.${table_name}DTO" resultMap="${table_name}DTOResultMap">
<include refid="findDtoSql" />
<where> </where>
</select> </mapper>
Controller.ftl 模板

Controller.ftl 文件用来生成控制层类,类中已经帮我们生成了,增,删,改,查等路由。同时可以注入接口道控制层中。

package ${package_name}.controller;
import com.evada.inno.core.annotation.Rest;
import ${package_name}.service.I${table_name}Service;
import ${package_name}.model.${table_name};
import ${package_name}.dto.${table_name}DTO;
import org.springframework.beans.factory.annotation.Autowired;
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.http.MediaType;
import com.evada.inno.common.domain.ResultData;
import com.evada.inno.core.util.AssertUtils; /**
* 描述:${table_annotation}控制层
* @author ${author}
* @date ${date}
*/
@Rest(${table_name}.class)
public class ${table_name}Controller { @Autowired
private I${table_name}Service ${table_name?uncap_first}Service; /**
* 描述:根据Id 查询
* @param id ${table_annotation}id
*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResultData findById(@PathVariable("id") String id)throws Exception {
${table_name}DTO ${table_name?uncap_first}DTO = ${table_name?uncap_first}Service.findDTOById(id);
AssertUtils.checkResourceFound(${table_name?uncap_first}DTO);
return new ResultData(${table_name}DTO.class, ${table_name?uncap_first}DTO);
} /**
* 描述:创建${table_annotation}
* @param ${table_name?uncap_first}DTO ${table_annotation}DTO
*/
@RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResultData create(@RequestBody ${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {
return new ResultData(${table_name}.class,${table_name?uncap_first}Service.create${table_name}(${table_name?uncap_first}DTO));
} /**
* 描述:删除${table_annotation}
* @param id ${table_annotation}id
*/
@RequestMapping(value = "/{id}/bulk", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public void deleteById(@PathVariable("id") String id) throws Exception {
${table_name?uncap_first}Service.deleteById(id);
} /**
* 描述:更新${table_annotation}
* @param id ${table_annotation}id
*/
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResultData update${table_name}(@PathVariable("id") String id,@RequestBody ${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {
${table_name?uncap_first}DTO.setId(id);
return new ResultData(${table_name}.class,${table_name?uncap_first}Service.update${table_name}(${table_name?uncap_first}DTO));
} }

通过上面的代码生成,我们就可以把生成的文件复制到相关的目录,重新启动系统,这样,基本的增,删,改,查就实现了。

读书感悟

来自东野圭吾《信》

  • “大多数人都想置身于远离罪犯的地方。和犯罪者,特别是犯下抢劫杀人这样恶心犯罪的人,哪怕是间接的关系也不想有。因为稍微有点什么关系,没准也会被卷入莫名其妙的事情中去。排斥犯罪者或是与其近似的人,是非常正当的行为,也可以说是正当防卫的本能。”
  • 犯罪者必须要有这样的思想准备,就是自己犯罪的同时也抹杀了自己亲属在社会上的存在。
  • 所谓偏见,就是不平等看待,其产生的根源就在于人的自私本性。这里的不平等看待,其实可以视为一种处理各种社会关系时的态度平衡缺失,而总是向有利于自己的一方倾斜,除非不同的立场之间不存在厉害冲突。一般情况下,人都是首先从自己的角度来看问题,而不会力图站在他人的立场来考量,完全意义上的中立是不可能的,由己及人是必然的思维定势,偏见遂自然而生。

经典故事

  
【一只小青蛙厌倦了常年生活的小水沟——水沟的水越来越少,它已经没有什么食物了。小青蛙每天都不停地蹦,想要逃离这个地方。而它的同伴整日懒洋洋地蹲在浑浊的水洼里,说:“现在不是还饿不死 
吗?你着什么急?”终于有一天,小青蛙纵身一跃,跳进了旁边的一个大河塘,那里面有很多好吃的,它可以自由游弋。小青蛙呱呱地呼唤自己的伙伴:“你快过来吧,这边简直是天堂!”但是它的同伴说:“我在这里已经习惯了,我从小就生活在这里,懒得动了!” 不久,水沟里的水干了,小青蛙的同伴活活饿死了。】

大神文章

【1】Freemarker官网 
【2】可用于企业级开发的JAVA代码生成器 
【3】 一个java代码生成器的简单实现

其他

如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎点赞、顶、欢迎留下宝贵的意见、多谢支持!

Java之利用Freemarker模板引擎实现代码生成器,提高效率的更多相关文章

  1. Spring Boot 2.0 整合 FreeMarker 模板引擎

    本篇博文将和大家一起使用Spring Boot 2.0 和FreeMarker 模板引擎整合实战. 1. 创建新的项目 2. 填写项目配置信息 3. 勾选web 模块 4. 勾选freemarker模 ...

  2. freemarker模板引擎的使用

    freemarker是一套前端模板引擎,在使用时,要先在web项目中添加freemarker.jar的依赖. 我在这里主要演示spring-mvc整合freemarker模板引擎.项目案例的文件包结构 ...

  3. Spring Boot☞ 使用freemarker模板引擎渲染web视图

    效果图 代码 package com.wls.integrateplugs.hello.controller; /** * Created by wls on 2017/8/24. */ import ...

  4. springboot中Thymeleaf和Freemarker模板引擎的区别

    前言这两个都是属于模板引擎,但是各有各的好处,enn,在市面上比较多的也就是jsp.freemarker.velocity.thymeleaf等页面方案.Thymeleaf和Freemarker的区别 ...

  5. SpringBoot获取Freemarker模板引擎,生成HTML代码

    今天用Ajax异步添加评论,加载Freemarker模板引擎,生成模板模块 1.新建Freemarker模板 <li id="${comment.oId}"> < ...

  6. FreeMarker模板引擎

    现在开发的项目,也是基于SOA架构,每个功能接口都是用WebService实现,Web服务的通信协议就是用XML来传输. 以前写WebService都是自动生成XML,没想到这项目竟然要自己定义XML ...

  7. Spring Boot 系列(五)web开发-Thymeleaf、FreeMarker模板引擎

    前面几篇介绍了返回json数据提供良好的RESTful api,下面我们介绍如何把处理完的数据渲染到页面上. Spring Boot 使用模板引擎 Spring Boot 推荐使用Thymeleaf. ...

  8. Spring Boot 揭秘与实战(七) 实用技术篇 - FreeMarker 模板引擎

    文章目录 1. FreeMaker 代替 JSP 作为页面渲染 2. 生成静态文件 3. 扩展阅读 4. 源代码 Spring Boot 提供了很多模板引擎的支持,例如 FreeMarker.Thym ...

  9. Spring MVC 学习总结(七)——FreeMarker模板引擎与动态页面静态化

    模板引擎可以让程序实现界面与数据分离,业务代码与逻辑代码的分离,这就提升了开发效率,良好的设计也使得代码复用变得更加容易.一般的模板引擎都包含一个模板解析器和一套标记语言,好的模板引擎有简洁的语法规则 ...

随机推荐

  1. LCD编程_画点线圆

    上篇博客中进行了lcd的简单测试,这篇博客将进行更加复杂的测试——画点.画线.画圆.画线和画圆是在画点的基础上实现的,因此本篇博客重点实现画点操作. 先抛出这样的一个问题,已知: (x,y)的坐标: ...

  2. Win7下安装openssl

    安装环境: 操作系统:window7(64位) C++编译器:VS2012 -------------------------------------------------------------- ...

  3. npm执行gulp提示编译错误

    script如下 "test":"gulp --gulpfile test.js" 运行 npm run test ,提示编译错误 解决办法如下: 增加scri ...

  4. JSPDF支持中文(思源黑体)采坑之旅,JSPDF中文字体乱码解决方案

    我拍个砖,通常标称自己文章完美解决何种问题的,往往就是解决不了任何问题! 众所周知,JSPDF是一个开源的,易用的,但是对中文支持非常差的PDF库. 下面,我教大家,如何在pdf中使用思源黑体.思源黑 ...

  5. Codeforces Round #606 (Div. 2) E - Two Fairs(DFS,反向思维)

  6. ElementUI_NodeJS环境搭建

    ElementUI简介 我们学习VUE,知道它的核心思想式组件和数据驱动,但是每一个组件都需要自己编写模板,样式,添加事件,数据等是非常麻烦的, 所以饿了吗推出了基于VUE2.0的组件库,它的名称叫做 ...

  7. BootstrapTable的简单使用教程

    1.引入必须的几个包 <link th:href="bootstrap/css/bootstrap.css}"/> <link th:href="boo ...

  8. barbor部署

    harbor 部署介绍: 1.版本信息 系统 :Centos 7.5 版本: harbor-offline-installer-v1.8.1 docker :docker-ce-18.06.2.ce- ...

  9. express框架,使用 static 访问 public 内静态文件

    使用 express 生成 node 服务器后,我们需要访问放在public文件夹内的静态文件,如上传的图片 我们需要在app.js中添加配置项: app.use('/public',express. ...

  10. phpstrom 配置getter和setter

    先看一段代码 protected $mddid; /** * @return mixed */ public function getMddid() { return $this->mddid; ...