Compare commits
No commits in common. "feature/v0.0.4" and "master" have entirely different histories.
feature/v0
...
master
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,5 @@
|
|||||||
.*
|
.*
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
*.iml
|
*.iml
|
||||||
target/
|
target/
|
||||||
bin/
|
|
||||||
|
13
ISSUE_TEMPLATE.zh-CN.md
Normal file
13
ISSUE_TEMPLATE.zh-CN.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
## 该问题是怎么引起的?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 重现步骤
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 报错信息
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
15
PULL_REQUEST_TEMPLATE.zh-CN.md
Normal file
15
PULL_REQUEST_TEMPLATE.zh-CN.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
## 该Pull Request关联的Issue
|
||||||
|
|
||||||
|
|
||||||
|
## 修改描述
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 测试用例
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 修复效果的截屏
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.context.annotation.ImportResource;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Shaun Chyxion <br>
|
|
||||||
* chyxion@163.com <br>
|
|
||||||
* Jun 24, 2018 20:43:36
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@SpringBootApplication
|
|
||||||
@ImportResource("classpath*:spring/spring-*.xml")
|
|
||||||
public class TigonCodeGen implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args start args
|
|
||||||
*/
|
|
||||||
public static void main(final String[] args) {
|
|
||||||
log.info("Startup args [{}].", StringUtils.join(args, "\n"));
|
|
||||||
SpringApplication.run(TigonCodeGen.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
|
||||||
registry.addResourceHandler("/assets/**")
|
|
||||||
.addResourceLocations("/assets/", "classpath:assets/");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 10:56:39
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class BaseClass {
|
|
||||||
private String name;
|
|
||||||
private String fullName;
|
|
||||||
private boolean importRequired;
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import java.util.Set;
|
|
||||||
import lombok.ToString;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 27, 2020 17:10:18
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class BaseClassWithFields extends BaseClass {
|
|
||||||
private Set<String> fields = new HashSet<>();
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 27, 2020 17:11:11
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class BasicItem {
|
|
||||||
private String projectDir;
|
|
||||||
private String basePackage;
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 10:42:03
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Component
|
|
||||||
@ToString
|
|
||||||
@ConfigurationProperties("tigon.codegen")
|
|
||||||
public class ConfigProperties implements InitializingBean {
|
|
||||||
private String workDir;
|
|
||||||
private FileDoc fileDoc = new FileDoc();
|
|
||||||
private String[] defaultGenItems = {
|
|
||||||
"model",
|
|
||||||
"mapper",
|
|
||||||
"form",
|
|
||||||
"service",
|
|
||||||
"controller"
|
|
||||||
};
|
|
||||||
private String basePackage;
|
|
||||||
private String tablePrefix;
|
|
||||||
private ItemModel model = new ItemModel();
|
|
||||||
private ItemModel formCreate = new ItemModel();
|
|
||||||
private ItemModel formUpdate = new ItemModel();
|
|
||||||
private ItemMapper mapper = new ItemMapper();
|
|
||||||
private Item service = new Item();
|
|
||||||
private Item serviceImpl = new Item();
|
|
||||||
private ItemController controller = new ItemController();
|
|
||||||
private Item view = new Item();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
log.info("After config [{}] init.", this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 26, 2020 17:58:54
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class FileDoc {
|
|
||||||
private boolean gen = true;
|
|
||||||
private String author = "Donghuang";
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 10:57:47
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class Item extends BasicItem {
|
|
||||||
private BaseClass baseClass = new BaseClass();
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Mar 16, 2021 00:02:00
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class ItemController extends Item {
|
|
||||||
private String urlPrefix;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 10:57:47
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class ItemMapper extends Item {
|
|
||||||
private boolean cacheEnabled;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.configprop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 10:57:47
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class ItemModel extends BasicItem {
|
|
||||||
private BaseClassWithFields baseClass = new BaseClassWithFields();
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.controller;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import me.chyxion.tigon.kit.json.JsonService;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
|
||||||
import me.chyxion.tigon.codegen.service.CodeGenService;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import me.chyxion.tigon.codegen.configprop.ConfigProperties;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @version 0.0.1
|
|
||||||
* @since 0.0.1
|
|
||||||
* @author Shaun Chyxion <br>
|
|
||||||
* chyxion@163.com <br>
|
|
||||||
* Oct 5, 2014 9:34:54 PM
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
public class SiteController {
|
|
||||||
@Autowired
|
|
||||||
private CodeGenService service;
|
|
||||||
@Autowired
|
|
||||||
private ConfigProperties configProperties;
|
|
||||||
@Autowired
|
|
||||||
private JsonService json;
|
|
||||||
|
|
||||||
@RequestMapping("/")
|
|
||||||
public ModelAndView index() {
|
|
||||||
return new ModelAndView("views/index")
|
|
||||||
.addObject("components",
|
|
||||||
json.toJSONString(configProperties.getDefaultGenItems()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/codegen/tables")
|
|
||||||
public List<Map<String, Object>> tables() {
|
|
||||||
return service.tables();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/codegen")
|
|
||||||
public void gen(@Valid GenForm form) {
|
|
||||||
service.process(form.getModel(),
|
|
||||||
json.parseArray(form.getColumns()), form);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/codegen/list")
|
|
||||||
public List<Map<String, Object>> list() {
|
|
||||||
return service.list();
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/codegen")
|
|
||||||
public void delete(
|
|
||||||
@RequestParam("items")
|
|
||||||
String items,
|
|
||||||
@RequestParam(value = "dropTable", defaultValue = "true")
|
|
||||||
boolean dropTable) {
|
|
||||||
service.delete(json.parseArray(items), dropTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class GenForm {
|
|
||||||
@NotNull
|
|
||||||
private String columns;
|
|
||||||
@NotBlank
|
|
||||||
private String model;
|
|
||||||
@NotBlank
|
|
||||||
private String table;
|
|
||||||
@NotBlank
|
|
||||||
private String tableComment;
|
|
||||||
private boolean genView;
|
|
||||||
private boolean genController;
|
|
||||||
private boolean genService;
|
|
||||||
private boolean genMapper;
|
|
||||||
private boolean genModel;
|
|
||||||
private boolean genForm;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 23, 2020 09:54:27
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class GenConfig {
|
|
||||||
private GenItem[] items;
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 22, 2020 17:44:22
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class GenItem {
|
|
||||||
private String item;
|
|
||||||
private String projectDir;
|
|
||||||
private String template;
|
|
||||||
private String result;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* copy this
|
|
||||||
* @return copy
|
|
||||||
*/
|
|
||||||
public GenItem copy() {
|
|
||||||
final GenItem it = new GenItem();
|
|
||||||
it.item = item;
|
|
||||||
it.projectDir = projectDir;
|
|
||||||
it.template = template;
|
|
||||||
it.result = result;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,231 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.service;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.util.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import java.sql.DatabaseMetaData;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import freemarker.template.Template;
|
|
||||||
import me.chyxion.tigon.util.WordUtils;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
import org.springframework.jdbc.support.JdbcUtils;
|
|
||||||
import org.springframework.jdbc.core.ConnectionCallback;
|
|
||||||
import me.chyxion.tigon.codegen.configprop.ConfigProperties;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
|
||||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @version 0.0.1
|
|
||||||
* @since 0.0.1
|
|
||||||
* @author chyxion <br>
|
|
||||||
* chyxion@163.com <br>
|
|
||||||
* Dec 3, 2014 11:25:17 AM
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class CodeGenBaseTool {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FreeMarkerConfigurer fmCfg;
|
|
||||||
@Autowired
|
|
||||||
private JdbcTemplate jdbcTpl;
|
|
||||||
@Autowired
|
|
||||||
private ConfigProperties configProps;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private Set<String> baseCols = new HashSet<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* render FreeMarker Template
|
|
||||||
* @param ftl
|
|
||||||
* @param model
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SneakyThrows
|
|
||||||
public String renderFtl(final String ftl, final Map<String, ?> model) {
|
|
||||||
log.info("Render FreeMarker template [{}].", ftl);
|
|
||||||
try (val resourceAsStream = CodeGenBaseTool.class.getResourceAsStream(ftl);
|
|
||||||
val reader = new InputStreamReader(
|
|
||||||
resourceAsStream,
|
|
||||||
StandardCharsets.UTF_8)) {
|
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(
|
|
||||||
new Template(ftl, reader, fmCfg.getConfiguration()), model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* render string FreeMarker Template
|
|
||||||
*
|
|
||||||
* @param strFtl
|
|
||||||
* @param model
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SneakyThrows
|
|
||||||
public String renderStrFtl(final String strFtl, final Map<String, ?> model) {
|
|
||||||
log.info("Render string FreeMarker template [{}].", strFtl);
|
|
||||||
try (val reader = new StringReader(strFtl)) {
|
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(
|
|
||||||
new Template(strFtl, reader, fmCfg.getConfiguration()), model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Map<String, Object>> tables() {
|
|
||||||
if (jdbcTpl != null) {
|
|
||||||
return jdbcTpl.execute((ConnectionCallback<List<Map<String, Object>>>) conn -> {
|
|
||||||
val tables = new LinkedList<Map<String, Object>>();
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
val md = conn.getMetaData();
|
|
||||||
val database = conn.getCatalog();
|
|
||||||
rs = md.getTables(null, null, "%", new String[] {"TABLE"});
|
|
||||||
while (rs.next()) {
|
|
||||||
val mapTable = new HashMap<String, Object>(8);
|
|
||||||
val table = rs.getString(3).toLowerCase();
|
|
||||||
|
|
||||||
mapTable.put("id", table);
|
|
||||||
mapTable.put("text", table);
|
|
||||||
mapTable.put("table", table);
|
|
||||||
mapTable.put("tableComment", getTableComment(database, table));
|
|
||||||
|
|
||||||
final String trimPrefixTableName;
|
|
||||||
val tablePrefix = configProps.getTablePrefix();
|
|
||||||
if (StringUtils.isNotBlank(tablePrefix) &&
|
|
||||||
table.startsWith(tablePrefix + "_")) {
|
|
||||||
log.info("Table prefix [{}] found, trim.", tablePrefix);
|
|
||||||
trimPrefixTableName = table.substring(
|
|
||||||
tablePrefix.length() + 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trimPrefixTableName = table;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapTable.put("model", StringUtils.capitalize(
|
|
||||||
WordUtils.convertToCamelCase(trimPrefixTableName)));
|
|
||||||
mapTable.put("leaf", true);
|
|
||||||
val keys = keys(md, table);
|
|
||||||
mapTable.put("keys", keys);
|
|
||||||
val indexes = indexes(md, table, false);
|
|
||||||
mapTable.put("indexes", indexes);
|
|
||||||
mapTable.put("cols", cols(md, table, keys, indexes));
|
|
||||||
tables.add(mapTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
JdbcUtils.closeResultSet(rs);
|
|
||||||
}
|
|
||||||
return tables;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// --
|
|
||||||
// private methods
|
|
||||||
private List<Map<String, Object>> cols(final DatabaseMetaData md,
|
|
||||||
final String table, Set<String> keys,
|
|
||||||
final Set<String> indexes) {
|
|
||||||
val cols = new LinkedList<Map<String, Object>>();
|
|
||||||
|
|
||||||
try (val rs = md.getColumns(null, "%", table, "%")) {
|
|
||||||
while (rs.next()) {
|
|
||||||
val col = new HashMap<String, Object>(16);
|
|
||||||
val colName = rs.getString("COLUMN_NAME");
|
|
||||||
col.put("isKey", keys.contains(colName));
|
|
||||||
col.put("isIndex", indexes.contains(colName));
|
|
||||||
col.put("col", colName);
|
|
||||||
col.put("name", WordUtils.toCamel(colName));
|
|
||||||
val size = rs.getInt("COLUMN_SIZE");
|
|
||||||
col.put("size", size);
|
|
||||||
String type = rs.getString("TYPE_NAME").toLowerCase();
|
|
||||||
String javaType = "String";
|
|
||||||
|
|
||||||
val notNull = rs.getInt("NULLABLE") == 0;
|
|
||||||
|
|
||||||
if (type.endsWith("char")) {
|
|
||||||
type = type + "(" + size + ")";
|
|
||||||
}
|
|
||||||
else if (type.contains("date") || type.contains("time")) {
|
|
||||||
javaType = "Date";
|
|
||||||
}
|
|
||||||
else if (type.equals("bit")) {
|
|
||||||
javaType = "Boolean";
|
|
||||||
}
|
|
||||||
else if (type.equals("int")) {
|
|
||||||
javaType = "Integer";
|
|
||||||
}
|
|
||||||
else if (type.equals("bigint")) {
|
|
||||||
javaType = "Long";
|
|
||||||
}
|
|
||||||
else if (type.contains("int")) {
|
|
||||||
javaType = "Integer";
|
|
||||||
}
|
|
||||||
else if (type.equals("float")) {
|
|
||||||
javaType = "Float";
|
|
||||||
}
|
|
||||||
else if (type.contains("double")) {
|
|
||||||
javaType = "Double";
|
|
||||||
}
|
|
||||||
else if (type.contains("blob")) {
|
|
||||||
javaType = "byte[]";
|
|
||||||
}
|
|
||||||
|
|
||||||
col.put("sqlType", type);
|
|
||||||
col.put("javaType", javaType);
|
|
||||||
col.put("notNull", notNull);
|
|
||||||
cols.add(col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Get table columns error caused", e);
|
|
||||||
}
|
|
||||||
return cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> keys(final DatabaseMetaData md, final String table) {
|
|
||||||
val keys = new TreeSet<String>();
|
|
||||||
try (val rs = md.getPrimaryKeys(null, null, table)) {
|
|
||||||
while (rs.next()) {
|
|
||||||
keys.add(rs.getString("COLUMN_NAME"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Get table keys error caused", e);
|
|
||||||
}
|
|
||||||
// find unique indexes
|
|
||||||
if (keys.isEmpty()) {
|
|
||||||
return indexes(md, table, true);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> indexes(final DatabaseMetaData md, final String table, final boolean unique) {
|
|
||||||
val keys = new TreeSet<String>();
|
|
||||||
try (val rs = md.getIndexInfo(null, null, table, false, false)) {
|
|
||||||
while (rs.next()) {
|
|
||||||
if (unique && rs.getBoolean("NON_UNIQUE")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
keys.add(rs.getString("COLUMN_NAME"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Get table indexes error caused", e);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTableComment(final String database, final String table) {
|
|
||||||
return jdbcTpl.queryForObject("select table_comment from information_schema.tables where table_schema = ? and table_name = ?",
|
|
||||||
new Object[] {database, table}, String.class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,354 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.service.support;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import me.chyxion.tigon.form.FC0;
|
|
||||||
import me.chyxion.tigon.form.FU0;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import me.chyxion.tigon.form.FormList;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import me.chyxion.tigon.mybatis.Table;
|
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
|
||||||
import me.chyxion.tigon.util.WordUtils;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import me.chyxion.tigon.mybatis.BaseMapper;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import me.chyxion.tigon.kit.json.JsonService;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import me.chyxion.tigon.codegen.model.GenItem;
|
|
||||||
import me.chyxion.tigon.codegen.model.GenConfig;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import me.chyxion.tigon.web.test.ControllerTestTool;
|
|
||||||
import me.chyxion.tigon.codegen.configprop.BaseClass;
|
|
||||||
import me.chyxion.tigon.codegen.configprop.BasicItem;
|
|
||||||
import me.chyxion.tigon.service.BaseCrudByFormService;
|
|
||||||
import me.chyxion.tigon.codegen.service.CodeGenService;
|
|
||||||
import me.chyxion.tigon.codegen.service.CodeGenBaseTool;
|
|
||||||
import me.chyxion.tigon.web.controller.BaseCrudController;
|
|
||||||
import me.chyxion.tigon.codegen.controller.SiteController;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import me.chyxion.tigon.codegen.configprop.ConfigProperties;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import me.chyxion.tigon.service.support.BaseCrudByFormServiceSupport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @version 0.0.1
|
|
||||||
* @since 0.0.1
|
|
||||||
* @author Shaun Chyxion <br>
|
|
||||||
* chyxion@163.com <br>
|
|
||||||
* Oct 6, 2014 1:10:02 PM
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class CodeGenServiceSupport implements CodeGenService, InitializingBean {
|
|
||||||
private static final Map<String, String> TYPE_PACKAGES =
|
|
||||||
new HashMap<String, String>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
{
|
|
||||||
put(Date.class.getSimpleName(), Date.class.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@Autowired
|
|
||||||
private JsonService json;
|
|
||||||
private GenConfig genConfig;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CodeGenBaseTool baseTool;
|
|
||||||
@Autowired
|
|
||||||
private ConfigProperties configProps;
|
|
||||||
private final Map<String, Object> moduleConfig = new HashMap<>(8);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void process(String model,
|
|
||||||
final List<Map<String, Object>> columns,
|
|
||||||
final SiteController.GenForm form) {
|
|
||||||
val minusJoinedModelName =
|
|
||||||
WordUtils.convertCamelCase(model, "-").toLowerCase();
|
|
||||||
|
|
||||||
model = StringUtils.capitalize(model);
|
|
||||||
val fmDataModel = new HashMap<String, Object>(20);
|
|
||||||
fmDataModel.putAll(moduleConfig);
|
|
||||||
fmDataModel.put("srcMainDir", "src/main/java");
|
|
||||||
fmDataModel.put("srcTestDir", "src/test/java");
|
|
||||||
|
|
||||||
fmDataModel.put("genView", form.isGenView());
|
|
||||||
fmDataModel.put("genController", form.isGenController());
|
|
||||||
fmDataModel.put("genService", form.isGenService());
|
|
||||||
fmDataModel.put("genMapper", form.isGenMapper());
|
|
||||||
fmDataModel.put("genModel", form.isGenModel());
|
|
||||||
fmDataModel.put("genForm", form.isGenForm());
|
|
||||||
|
|
||||||
val table = form.getTable();
|
|
||||||
fmDataModel.put("table", table.toLowerCase());
|
|
||||||
fmDataModel.put("notNull", false);
|
|
||||||
fmDataModel.put("notBlank", false);
|
|
||||||
fmDataModel.put("cacheEnabled",
|
|
||||||
configProps.getMapper().isCacheEnabled());
|
|
||||||
fmDataModel.put("useGeneratedKeys", false);
|
|
||||||
|
|
||||||
// collect col names
|
|
||||||
String idType = null;
|
|
||||||
val colNames = new ArrayList<String>(columns.size());
|
|
||||||
for (val col : columns) {
|
|
||||||
final String colName = ((String) col.get("col")).toLowerCase();
|
|
||||||
colNames.add(colName);
|
|
||||||
// find id type
|
|
||||||
if ("id".equals(colName)) {
|
|
||||||
String javaType = (String) col.get("javaType");
|
|
||||||
if (ArrayUtils.contains(
|
|
||||||
new String[] {"int", "long", "boolean", "double", "byte"},
|
|
||||||
javaType)) {
|
|
||||||
javaType = "int".equals(javaType) ?
|
|
||||||
Integer.class.getSimpleName() :
|
|
||||||
StringUtils.capitalize(javaType);
|
|
||||||
}
|
|
||||||
idType = javaType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String baseModelName;
|
|
||||||
final String baseModelFullName;
|
|
||||||
final Collection<String> modelBaseFields;
|
|
||||||
|
|
||||||
// custom super class
|
|
||||||
val modelBaseClass = configProps.getModel().getBaseClass();
|
|
||||||
val modelSuperClassName = modelBaseClass.getName();
|
|
||||||
if (StringUtils.isNotBlank(modelSuperClassName)) {
|
|
||||||
String modelSuperClassImportName = modelBaseClass.getFullName();
|
|
||||||
Assert.state(StringUtils.isNotBlank(modelSuperClassImportName),
|
|
||||||
"config 'codegen.model.super-class.import-name' required");
|
|
||||||
baseModelName = modelSuperClassName;
|
|
||||||
baseModelFullName = modelBaseClass.isImportRequired() ?
|
|
||||||
modelSuperClassImportName : null;
|
|
||||||
|
|
||||||
modelBaseFields = configProps.getModel().getBaseClass().getFields();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.info("No base model specified.");
|
|
||||||
baseModelName = null;
|
|
||||||
baseModelFullName = null;
|
|
||||||
modelBaseFields = Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
fmDataModel.put("baseModelFullName", baseModelFullName);
|
|
||||||
fmDataModel.put("baseModelName", baseModelName);
|
|
||||||
|
|
||||||
fmDataModel.put("tableAnnotationClassName", Table.class.getName());
|
|
||||||
fmDataModel.put("tableAnnotationName", Table.class.getSimpleName());
|
|
||||||
|
|
||||||
val imports = new HashSet<String>();
|
|
||||||
val colsWithoutBase = columns;
|
|
||||||
val colIt = colsWithoutBase.iterator();
|
|
||||||
|
|
||||||
while (colIt.hasNext()) {
|
|
||||||
val col = colIt.next();
|
|
||||||
// col name
|
|
||||||
val colName = ((String) col.get("col")).toLowerCase();
|
|
||||||
// prop name
|
|
||||||
val propName = (String) col.get("name");
|
|
||||||
log.info("Process model col [{}] field.", colName, propName);
|
|
||||||
if (!modelBaseFields.contains(propName)) {
|
|
||||||
// for setName
|
|
||||||
col.put("Name", StringUtils.capitalize(propName));
|
|
||||||
if ((Boolean) col.get("notNull")) {
|
|
||||||
if ("String".equals(col.get("javaType"))) {
|
|
||||||
fmDataModel.put("notBlank", true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fmDataModel.put("notNull", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// imports
|
|
||||||
val imp = TYPE_PACKAGES.get(col.get("javaType"));
|
|
||||||
if (StringUtils.isNotBlank(imp)) {
|
|
||||||
imports.add(imp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove base col
|
|
||||||
else {
|
|
||||||
log.info("Remove base col [{}].", colName);
|
|
||||||
colIt.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmDataModel.put("idType", idType);
|
|
||||||
fmDataModel.put("cols", colsWithoutBase);
|
|
||||||
fmDataModel.put("fcProps", newPropsWithoutBase(colsWithoutBase,
|
|
||||||
configProps.getFormCreate().getBaseClass().getFields()));
|
|
||||||
fmDataModel.put("fuProps", newPropsWithoutBase(colsWithoutBase,
|
|
||||||
configProps.getFormUpdate().getBaseClass().getFields()));
|
|
||||||
fmDataModel.put("imports", imports);
|
|
||||||
|
|
||||||
fmDataModel.put("ModelName", model);
|
|
||||||
fmDataModel.put("Model", model);
|
|
||||||
fmDataModel.put("urlPrefix", configProps.getController().getUrlPrefix());
|
|
||||||
fmDataModel.put("minusJoinedModelName", minusJoinedModelName);
|
|
||||||
|
|
||||||
// search
|
|
||||||
fmDataModel.put("searchName", Search.class.getSimpleName());
|
|
||||||
fmDataModel.put("searchFullName", Search.class.getName());
|
|
||||||
|
|
||||||
// controller
|
|
||||||
fmDataModel.put("baseControllerName", BaseCrudController.class.getSimpleName());
|
|
||||||
fmDataModel.put("baseControllerFullName", BaseCrudController.class.getName());
|
|
||||||
|
|
||||||
fmDataModel.put("FormList", FormList.class.getSimpleName());
|
|
||||||
fmDataModel.put("formListFullName", FormList.class.getName());
|
|
||||||
addFormSuperClass(fmDataModel);
|
|
||||||
|
|
||||||
// service interface
|
|
||||||
fmDataModel.put("baseServiceName", BaseCrudByFormService.class.getSimpleName());
|
|
||||||
fmDataModel.put("baseServiceFullName", BaseCrudByFormService.class.getName());
|
|
||||||
// server impl
|
|
||||||
fmDataModel.put("baseServiceSupportName", BaseCrudByFormServiceSupport.class.getSimpleName());
|
|
||||||
fmDataModel.put("baseServiceSupportFullName", BaseCrudByFormServiceSupport.class.getName());
|
|
||||||
|
|
||||||
// mapper
|
|
||||||
fmDataModel.put("baseMapperName", BaseMapper.class.getSimpleName());
|
|
||||||
fmDataModel.put("baseMapperFullName", BaseMapper.class.getName());
|
|
||||||
|
|
||||||
fmDataModel.put("ctrlrTestToolName", ControllerTestTool.class.getSimpleName());
|
|
||||||
fmDataModel.put("ctrlrTestToolFullName", ControllerTestTool.class.getName());
|
|
||||||
// code doc
|
|
||||||
fmDataModel.put("objDoc", doc());
|
|
||||||
|
|
||||||
// view
|
|
||||||
fmDataModel.put("nameCn", form.getTableComment());
|
|
||||||
fmDataModel.put("permName", WordUtils.convertCamelCase(model, "_").toUpperCase());
|
|
||||||
|
|
||||||
for (val genItem : genConfig.getItems()) {
|
|
||||||
if ((Boolean) fmDataModel.get(
|
|
||||||
"gen" + StringUtils.capitalize(genItem.getItem()))) {
|
|
||||||
GenItem item = genItem.copy();
|
|
||||||
item.setProjectDir(baseTool.renderStrFtl(item.getProjectDir(), fmDataModel));
|
|
||||||
item.setResult(baseTool.renderStrFtl(item.getResult(), fmDataModel));
|
|
||||||
render(item, fmDataModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> list() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void delete(List<Map<String, Object>> items, boolean dropTable) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> tables() {
|
|
||||||
return baseTool.tables();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String doc() {
|
|
||||||
if (!configProps.getFileDoc().isGen()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Object Doc
|
|
||||||
val objDocModel = new HashMap<String, Object>(4);
|
|
||||||
objDocModel.put("author", configProps.getFileDoc().getAuthor());
|
|
||||||
// time now
|
|
||||||
objDocModel.put("now", new SimpleDateFormat(
|
|
||||||
"MMM dd, yyyy HH:mm:ss").format(
|
|
||||||
System.currentTimeMillis()));
|
|
||||||
return baseTool.renderFtl("/templates/codegen/file-doc.ftl", objDocModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFormSuperClass(final Map<String, Object> fmModel) {
|
|
||||||
val fcBaseClassNames = baseFormClass(
|
|
||||||
configProps.getFormCreate().getBaseClass(), FC0.class);
|
|
||||||
fmModel.put("baseFormCreateName", fcBaseClassNames.getLeft());
|
|
||||||
fmModel.put("baseFormCreateFullName", fcBaseClassNames.getRight());
|
|
||||||
|
|
||||||
val fuBaseClassNames = baseFormClass(
|
|
||||||
configProps.getFormUpdate().getBaseClass(), FU0.class);
|
|
||||||
fmModel.put("baseFormUpdateName", fuBaseClassNames.getLeft());
|
|
||||||
fmModel.put("baseFormUpdateFullName", fuBaseClassNames.getRight());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pair<String, String> baseFormClass(final BaseClass baseClass, final Class<?> defaultFormClass) {
|
|
||||||
val name = baseClass.getName();
|
|
||||||
if (StringUtils.isNotBlank(name)) {
|
|
||||||
if (baseClass.isImportRequired()) {
|
|
||||||
final String fullName = baseClass.getFullName();
|
|
||||||
Assert.state(StringUtils.isNotBlank(fullName),
|
|
||||||
() -> "Form [" + name + "] full name required");
|
|
||||||
return Pair.of(name, fullName);
|
|
||||||
}
|
|
||||||
return Pair.of(name, null);
|
|
||||||
}
|
|
||||||
return Pair.of(defaultFormClass.getSimpleName(),
|
|
||||||
defaultFormClass.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
protected String render(final GenItem args, Map<String, ?> model) {
|
|
||||||
log.info("Do render, args [{}].", args);
|
|
||||||
|
|
||||||
// write result
|
|
||||||
val result = new File(
|
|
||||||
new File(configProps.getWorkDir(),
|
|
||||||
args.getProjectDir()), args.getResult());
|
|
||||||
log.info("Write result to file [{}].", result);
|
|
||||||
FileUtils.write(result, baseTool.renderFtl(args.getTemplate(), model),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
return args.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
ReflectionUtils.doWithFields(ConfigProperties.class, field -> {
|
|
||||||
field.setAccessible(true);
|
|
||||||
val name = field.getName();
|
|
||||||
log.info("Super model field [{}] found.", name);
|
|
||||||
val item = (BasicItem) ReflectionUtils.getField(field, configProps);
|
|
||||||
moduleConfig.put(name + "ProjectDir", item.getProjectDir());
|
|
||||||
val pkg = item.getBasePackage();
|
|
||||||
if (StringUtils.isNotBlank(pkg)) {
|
|
||||||
moduleConfig.put(name + "Pkg", pkg);
|
|
||||||
moduleConfig.put(name + "PkgDir", pkg.replace('.', '/'));
|
|
||||||
}
|
|
||||||
}, field -> BasicItem.class.isAssignableFrom(field.getType()));
|
|
||||||
|
|
||||||
try (val ins = CodeGenServiceSupport.class.getResourceAsStream("/codegen.json")) {
|
|
||||||
genConfig = json.parse(
|
|
||||||
IOUtils.toString(ins, StandardCharsets.UTF_8), GenConfig.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Map<String, Object>> newPropsWithoutBase(final List<Map<String, Object>> baseProps, final Collection<String> baseFields) {
|
|
||||||
val props = new ArrayList<>(baseProps);
|
|
||||||
val it = props.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
if (baseFields.contains(it.next().get("name"))) {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
{
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"item": "model",
|
|
||||||
"projectDir": "${modelProjectDir}",
|
|
||||||
"template": "/templates/codegen/model.ftl",
|
|
||||||
"result": "src/main/java/${modelPkgDir}/${Model}.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "form",
|
|
||||||
"projectDir": "${formCreateProjectDir}",
|
|
||||||
"template": "/templates/codegen/form-create.ftl",
|
|
||||||
"result": "src/main/java/${formCreatePkgDir}/FormCreate${Model}.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "form",
|
|
||||||
"projectDir": "${formUpdateProjectDir}",
|
|
||||||
"template": "/templates/codegen/form-update.ftl",
|
|
||||||
"result": "src/main/java/${formUpdatePkgDir}/FormUpdate${Model}.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "mapper",
|
|
||||||
"projectDir": "${mapperProjectDir}",
|
|
||||||
"template": "/templates/codegen/mapper.ftl",
|
|
||||||
"result": "src/main/java/${mapperPkgDir}/${Model}Mapper.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "mapper",
|
|
||||||
"projectDir": "${mapperProjectDir}",
|
|
||||||
"template": "/templates/codegen/mapper-xml.ftl",
|
|
||||||
"result": "src/main/java/${mapperPkgDir}/${Model}Mapper.xml"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "mapper",
|
|
||||||
"projectDir": "${mapperProjectDir}",
|
|
||||||
"template": "/templates/codegen/mapper-test.ftl",
|
|
||||||
"result": "src/test/java/${mapperPkgDir}/${Model}MapperTest.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "service",
|
|
||||||
"projectDir": "${serviceProjectDir}",
|
|
||||||
"template": "/templates/codegen/service.ftl",
|
|
||||||
"result": "src/main/java/${servicePkgDir}/${Model}Service.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "service",
|
|
||||||
"projectDir": "${serviceImplProjectDir}",
|
|
||||||
"template": "/templates/codegen/service-impl.ftl",
|
|
||||||
"result": "src/main/java/${serviceImplPkgDir}/${Model}ServiceImpl.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "controller",
|
|
||||||
"projectDir": "${controllerProjectDir}",
|
|
||||||
"template": "/templates/codegen/controller.ftl",
|
|
||||||
"result": "src/main/java/${controllerPkgDir}/${Model}Controller.java"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/service.ftl",
|
|
||||||
"result": "app/services/${minusJoinedModelName}/service.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/route-list.ftl",
|
|
||||||
"result": "app/routes/${minusJoinedModelName}/list.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/route-create.ftl",
|
|
||||||
"result": "app/routes/${minusJoinedModelName}/create.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/route-edit.ftl",
|
|
||||||
"result": "app/routes/${minusJoinedModelName}/edit.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/tpl-list.ftl",
|
|
||||||
"result": "app/templates/${minusJoinedModelName}/list.hbs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/tpl-create.ftl",
|
|
||||||
"result": "app/templates/${minusJoinedModelName}/create.hbs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item": "view",
|
|
||||||
"projectDir": "${viewProjectDir}",
|
|
||||||
"template": "/templates/codegen/view/tpl-edit.ftl",
|
|
||||||
"result": "app/templates/${minusJoinedModelName}/edit.hbs"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration debug="true" scan="true" scanPeriod="180 seconds">>
|
|
||||||
|
|
||||||
<property name="log.level" value="DEBUG" />
|
|
||||||
<property name="log.dir" value=".logs" />
|
|
||||||
|
|
||||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<withJansi>true</withJansi>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%magenta(%d{"yyyy-MM-dd HH:mm:ss,SSS"}) [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>${log.dir}/app.log</file>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{"yyyy-MM-dd HH:mm:ss,SSS"} [%thread] %-5level %logger{15} %msg %n</pattern>
|
|
||||||
</encoder>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>${log.dir}/%d{yyyy-MM, aux}/app-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
|
||||||
<maxFileSize>32MB</maxFileSize>
|
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
|
||||||
</rollingPolicy>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework" level="INFO" additivity="false">
|
|
||||||
<appender-ref ref="Console" />
|
|
||||||
<!--<appender-ref ref="File" />-->
|
|
||||||
</logger>
|
|
||||||
<root level="${log.level}">
|
|
||||||
<appender-ref ref="Console" />
|
|
||||||
<!--<appender-ref ref="File" />-->
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
|||||||
package ${controllerPkg};
|
|
||||||
|
|
||||||
<#list cols as prop>
|
|
||||||
<#if prop.javaType == 'Date'>
|
|
||||||
import java.util.Date;
|
|
||||||
<#break>
|
|
||||||
</#if>
|
|
||||||
</#list>
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import ${ctrlrTestToolFullName};
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@WebAppConfiguration
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
@ContextConfiguration({
|
|
||||||
"classpath*:spring/spring-*.xml",
|
|
||||||
})
|
|
||||||
public class ${ModelName}ControllerTest {
|
|
||||||
@Autowired
|
|
||||||
private ${ctrlrTestToolName} t;
|
|
||||||
/**
|
|
||||||
* test list
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testList() {
|
|
||||||
// TODO Modify Mock${ModelName}Mapper#listPage To Complete Test Logic
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
|
||||||
params.put("start", "0");
|
|
||||||
params.put("limit", "10");
|
|
||||||
t.assertSuccess(t.print(t.get("${urlPrefix!}/${minusJoinedModelName}/list")));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* test create
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testCreate() {
|
|
||||||
// TODO Modify Mock${ModelName}Mapper#insert To Complete Test Logic
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
|
||||||
<#list cols as prop>
|
|
||||||
<#if prop.javaType == 'Date'>
|
|
||||||
params.put("${prop.name}", new Date());
|
|
||||||
<#elseif prop.javaType == 'String'>
|
|
||||||
params.put("${prop.name}", "String Value");
|
|
||||||
<#elseif prop.javaType == 'boolean'>
|
|
||||||
params.put("${prop.name}", false);
|
|
||||||
<#elseif prop.javaType == 'int'>
|
|
||||||
params.put("${prop.name}", 1);
|
|
||||||
<#elseif prop.javaType == 'long'>
|
|
||||||
params.put("${prop.name}", 1L);
|
|
||||||
<#elseif prop.javaType == 'float'>
|
|
||||||
params.put("${prop.name}", 1.0F);
|
|
||||||
<#elseif prop.javaType == 'double'>
|
|
||||||
params.put("${prop.name}", 1.0D);
|
|
||||||
</#if>
|
|
||||||
</#list>
|
|
||||||
t.print(t.put("${urlPrefix!}/${minusJoinedModelName}/create", params));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* test find
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testFind() {
|
|
||||||
// TODO Modify Mock${ModelName}Mapper#find to complete test logic
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
|
||||||
params.put("id", "1");
|
|
||||||
t.assertSuccess(t.print(t.get("${urlPrefix!}/${minusJoinedModelName}/find", params)));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* test update
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testUpdate() {
|
|
||||||
// TODO Modify Mock${ModelName}Mapper#update to complete test logic
|
|
||||||
final Map<String, Object> params = new HashMap<String, Object>();
|
|
||||||
params.put("id", 1);
|
|
||||||
<#list cols as prop>
|
|
||||||
<#if prop.javaType == 'Date'>
|
|
||||||
params.put("${prop.name}", new Date());
|
|
||||||
<#elseif prop.javaType == 'String'>
|
|
||||||
params.put("${prop.name}", "String Value Updated");
|
|
||||||
<#elseif prop.javaType == 'boolean'>
|
|
||||||
params.put("${prop.name}", true);
|
|
||||||
<#elseif prop.javaType == 'int'>
|
|
||||||
params.put("${prop.name}", 2);
|
|
||||||
<#elseif prop.javaType == 'long'>
|
|
||||||
params.put("${prop.name}", 2L);
|
|
||||||
<#elseif prop.javaType == 'float'>
|
|
||||||
params.put("${prop.name}", 2.0F);
|
|
||||||
<#elseif prop.javaType == 'double'>
|
|
||||||
params.put("${prop.name}", 2.0D);
|
|
||||||
</#if>
|
|
||||||
</#list>
|
|
||||||
t.print(t.post("${urlPrefix!}/${minusJoinedModelName}/update", params));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* test delete one row
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testDelete() {
|
|
||||||
// TODO Modify Mock${ModelName}Mapper#delete to complete test logic
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
|
||||||
params.put("id", "1");
|
|
||||||
t.assertSuccess(t.print(t.post("${urlPrefix!}/${minusJoinedModelName}/delete", params)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package ${controllerPkg};
|
|
||||||
|
|
||||||
import ${modelPkg}.${ModelName};
|
|
||||||
import ${formListFullName};
|
|
||||||
import ${formCreatePkg}.FormCreate${ModelName};
|
|
||||||
import ${formUpdatePkg}.FormUpdate${ModelName};
|
|
||||||
import ${baseControllerFullName};
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("${urlPrefix!}/${minusJoinedModelName}")
|
|
||||||
public class ${ModelName}Controller
|
|
||||||
extends ${baseControllerName}<${idType},
|
|
||||||
${ModelName},
|
|
||||||
${FormList},
|
|
||||||
FormCreate${ModelName},
|
|
||||||
FormUpdate${ModelName}> {
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author ${author}
|
|
||||||
* @date ${now}
|
|
||||||
*/
|
|
@ -1,24 +0,0 @@
|
|||||||
package ${formCreatePkg};
|
|
||||||
<#import "/codegen/commons.ftl" as CodeGen>
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
<#if baseFormCreateFullName?has_content>
|
|
||||||
import ${baseFormCreateFullName};
|
|
||||||
</#if>
|
|
||||||
<#list imports as p>
|
|
||||||
import ${p};
|
|
||||||
</#list>
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class FormCreate${ModelName} extends ${baseFormCreateName} {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
<#list fcProps as prop>
|
|
||||||
private ${prop.javaType} ${prop.name};
|
|
||||||
</#list>
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package ${formUpdatePkg};
|
|
||||||
<#import "/codegen/commons.ftl" as CodeGen>
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
<#if baseFormUpdateFullName?has_content>
|
|
||||||
import ${baseFormUpdateFullName};
|
|
||||||
</#if>
|
|
||||||
<#list imports as p>
|
|
||||||
import ${p};
|
|
||||||
</#list>
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class FormUpdate${ModelName} extends ${baseFormUpdateName} {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
<#list fuProps as prop>
|
|
||||||
private ${prop.javaType} ${prop.name};
|
|
||||||
</#list>
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package ${mapperPkg};
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import ${searchFullName};
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
@ContextConfiguration("classpath*:spring/spring-*.xml")
|
|
||||||
public class ${ModelName}MapperTest extends AbstractTransactionalJUnit4SpringContextTests {
|
|
||||||
@Autowired
|
|
||||||
private ${ModelName}Mapper mapper;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapperTest() {
|
|
||||||
mapper.list(new Search().limit(8));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<#if objDoc??><#if objDoc?has_content>
|
|
||||||
<!--
|
|
||||||
${objDoc}
|
|
||||||
-->
|
|
||||||
</#if></#if>
|
|
||||||
<!DOCTYPE mapper PUBLIC
|
|
||||||
"-//mybatis.org//DTD Mapper 3.0//EN"
|
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="${mapperPkg}.${ModelName}Mapper">
|
|
||||||
<#if cacheEnabled>
|
|
||||||
<!-- Redis Cache -->
|
|
||||||
<cache type="me.chyxion.tigon.mybatis.cache.RedisCache" />
|
|
||||||
</#if>
|
|
||||||
</mapper>
|
|
@ -1,22 +0,0 @@
|
|||||||
package ${serviceImplPkg};
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ${modelPkg}.${ModelName};
|
|
||||||
import ${mapperPkg}.${ModelName}Mapper;
|
|
||||||
import ${servicePkg}.${ModelName}Service;
|
|
||||||
import ${formCreatePkg}.FormCreate${ModelName};
|
|
||||||
import ${formUpdatePkg}.FormUpdate${ModelName};
|
|
||||||
import ${baseServiceSupportFullName};
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
@Service
|
|
||||||
public class ${ModelName}ServiceImpl
|
|
||||||
extends ${baseServiceSupportName}<${idType},
|
|
||||||
${ModelName},
|
|
||||||
FormCreate${ModelName},
|
|
||||||
FormUpdate${ModelName},
|
|
||||||
${ModelName}Mapper>
|
|
||||||
implements ${ModelName}Service {
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package ${servicePkg};
|
|
||||||
|
|
||||||
import ${modelPkg}.${ModelName};
|
|
||||||
import ${formCreatePkg}.FormCreate${ModelName};
|
|
||||||
import ${formUpdatePkg}.FormUpdate${ModelName};
|
|
||||||
import ${baseServiceFullName};
|
|
||||||
|
|
||||||
<#if objDoc?has_content>
|
|
||||||
${objDoc}
|
|
||||||
</#if>
|
|
||||||
public interface ${ModelName}Service
|
|
||||||
extends ${baseServiceName}<${idType},
|
|
||||||
${ModelName},
|
|
||||||
FormCreate${ModelName},
|
|
||||||
FormUpdate${ModelName}> {
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import BaseRoute from '../base';
|
|
||||||
|
|
||||||
export default BaseRoute.extend({
|
|
||||||
perm: 'PERM_VIEW_${permName}_CREATE',
|
|
||||||
breadcrumbs: [{route: '${minusJoinedModelName}.list', text: '${nameCn}列表'}, {text: '创建${nameCn}'}],
|
|
||||||
model(params) {
|
|
||||||
return {
|
|
||||||
active: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
import BaseEditRoute from '../base-edit';
|
|
||||||
|
|
||||||
export default BaseEditRoute.extend({
|
|
||||||
perm: 'PERM_VIEW_${permName}_EDIT',
|
|
||||||
afterModel(model) {
|
|
||||||
this.set('breadcrumbs',
|
|
||||||
[{route: '${minusJoinedModelName}.list', text: '${nameCn}列表'},
|
|
||||||
{text: '编辑${nameCn}[' + model.id + ']'}]);
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,6 +0,0 @@
|
|||||||
import BaseListRoute from '../base-list';
|
|
||||||
|
|
||||||
export default BaseListRoute.extend({
|
|
||||||
perm: 'PERM_VIEW_${permName}_LIST',
|
|
||||||
breadcrumbs: [{text: '${nameCn}列表'}]
|
|
||||||
});
|
|
@ -1,6 +0,0 @@
|
|||||||
import Service from '../service';
|
|
||||||
|
|
||||||
export default Service.extend({
|
|
||||||
modelName: '${ModelName}',
|
|
||||||
// constraints: { }
|
|
||||||
});
|
|
@ -1,9 +0,0 @@
|
|||||||
{{#form-content}}
|
|
||||||
<hr />
|
|
||||||
{{form-input name='name' label='名称'}}
|
|
||||||
{{form-input name='account' label='账户'}}
|
|
||||||
{{form-input name='note' label='备注'}}
|
|
||||||
<hr />
|
|
||||||
{{form-footer-buttons type='create'}}
|
|
||||||
{{/form-content}}
|
|
||||||
{{outlet}}
|
|
@ -1,9 +0,0 @@
|
|||||||
{{#form-content}}
|
|
||||||
{{form-input type='hidden' name='id'}}
|
|
||||||
{{form-input name='name' label='名称'}}
|
|
||||||
{{form-input-enabled}}
|
|
||||||
{{form-input name='note' label='备注'}}
|
|
||||||
<hr />
|
|
||||||
{{form-footer-buttons type='update'}}
|
|
||||||
{{/form-content}}
|
|
||||||
{{outlet}}
|
|
@ -1,73 +0,0 @@
|
|||||||
<div class="widget-box transparent" style="padding-top: 2px; border: 1px solid #ddd;">
|
|
||||||
{{#grid-header}}
|
|
||||||
{{#has-perm 'PERM_VIEW_${permName}_CREATE'}}
|
|
||||||
<li>
|
|
||||||
{{#link-to '${minusJoinedModelName}.create'}}
|
|
||||||
<i class="ace-icon fa fa-plus-circle bigger-110 green"></i>
|
|
||||||
新建${nameCn}
|
|
||||||
{{/link-to}}
|
|
||||||
</li>
|
|
||||||
{{/has-perm}}
|
|
||||||
{{/grid-header}}
|
|
||||||
<div class="widget-body">
|
|
||||||
<!-- #section:custom/scrollbar -->
|
|
||||||
<div class="widget-main no-padding">
|
|
||||||
<table class="table table-striped table-bordered table-hover dataTable">
|
|
||||||
<thead class="thin-border-bottom">
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
名称
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
<i class="ace-icon fa fa-sticky-note-o bigger-110"></i>
|
|
||||||
备注
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
<i class="ace-icon fa fa-exchange bigger-110 hidden-480"></i>
|
|
||||||
{{th-filter name='active'
|
|
||||||
text='状态'
|
|
||||||
dialog-title='状态'
|
|
||||||
options=(array (hash value=true text='启用')
|
|
||||||
(hash value=false text='禁用'))
|
|
||||||
}}
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
<i class="ace-icon fa fa-cogs bigger-110 hidden-480"></i>
|
|
||||||
管理
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{#each model.data as |it|}}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{it.name}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{editable-cell model=it field='note'}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{status-cell model=it}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="btn-group">
|
|
||||||
{{#has-perm 'PERM_VIEW_${permName}_EDIT'}}
|
|
||||||
{{status-toggle-button model=it}}
|
|
||||||
{{edit-btn route-name='${minusJoinedModelName}.edit' model-id=it.id perm='PERM_VIEW_${permName}_EDIT'}}
|
|
||||||
{{/has-perm}}
|
|
||||||
{{#has-perm 'PERM_VIEW_${permName}_DELETE'}}
|
|
||||||
{{#unless it.active}}
|
|
||||||
{{delete-button model=it}}
|
|
||||||
{{/unless}}
|
|
||||||
{{/has-perm}}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{{pagination-bar}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{outlet}}
|
|
@ -1,31 +0,0 @@
|
|||||||
package me.chyxion.tigon.codegen.test;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import me.chyxion.tigon.codegen.TigonCodeGen;
|
|
||||||
import me.chyxion.tigon.codegen.service.CodeGenBaseTool;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Mar 14, 2021 22:31:32
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@SpringBootTest(classes = TigonCodeGen.class)
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
public class TestDriver {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CodeGenBaseTool tool;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void runTest() {
|
|
||||||
val tables = tool.tables();
|
|
||||||
log.info("Tables [{}].", tables);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
tigon:
|
|
||||||
codegen:
|
|
||||||
datasource:
|
|
||||||
password: yobr_query!
|
|
||||||
url: jdbc:mysql://192.168.3.5/yobr-daily?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
|
|
||||||
username: yobr_query
|
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration debug="true">
|
|
||||||
|
|
||||||
<property name="log.level" value="DEBUG" />
|
|
||||||
<property name="log.dir" value=".logs" />
|
|
||||||
|
|
||||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<withJansi>true</withJansi>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%magenta(%d{"yyyy-MM-dd HH:mm:ss,SSS"}) [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>${log.dir}/app.log</file>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{"yyyy-MM-dd HH:mm:ss,SSS"} [%thread] %-5level %logger{15} %msg %n</pattern>
|
|
||||||
</encoder>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>${log.dir}/%d{yyyy-MM, aux}/app-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
|
||||||
<maxFileSize>32MB</maxFileSize>
|
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
|
||||||
</rollingPolicy>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework" level="TRACE" additivity="false">
|
|
||||||
<appender-ref ref="Console" />
|
|
||||||
<appender-ref ref="File" />
|
|
||||||
</logger>
|
|
||||||
<root level="${log.level}">
|
|
||||||
<appender-ref ref="Console" />
|
|
||||||
<appender-ref ref="File" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
||||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
|
||||||
</beans>
|
|
@ -1 +0,0 @@
|
|||||||
# Tigon Common
|
|
@ -1,73 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://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
|
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>tigon-common</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
<name>Tigon Common</name>
|
|
||||||
<description>Tigon Common</description>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>me.chyxion.tigon</groupId>
|
|
||||||
<artifactId>tigon</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>bson</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!--For Form Copy-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-beans</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- For Form Validate -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate.validator</groupId>
|
|
||||||
<artifactId>hibernate-validator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Test -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-slf4j-impl</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-core</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,34 +0,0 @@
|
|||||||
package me.chyxion.tigon.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* blank string format to null
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* null => null
|
|
||||||
* "" => null
|
|
||||||
* " " => null
|
|
||||||
* "abc" => "abc"
|
|
||||||
* " abc " => "abc"
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Jun 15, 2016 11:20:48 AM
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
|
||||||
public @interface Trim {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* blank as null
|
|
||||||
*
|
|
||||||
* @return blank as null if true
|
|
||||||
*/
|
|
||||||
boolean blankAsNull() default true;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.annotation.json;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 集合、Array空元素清理
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 20:38:54
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
|
||||||
public @interface EmptyElCleanup {
|
|
||||||
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package me.chyxion.tigon.annotation.json;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserialize JSON empty object to null
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 20:38:54
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
|
||||||
public @interface EmptyObjectToNull {
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package me.chyxion.tigon.annotation.json;
|
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON 反序列化回调
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 21, 2022 10:17:19
|
|
||||||
*/
|
|
||||||
@Target({ElementType.METHOD})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface PostDeserialize {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制访问私有方法
|
|
||||||
*
|
|
||||||
* @return true if force access
|
|
||||||
*/
|
|
||||||
boolean forceAccess() default false;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
package me.chyxion.tigon;
|
|
@ -1,18 +0,0 @@
|
|||||||
package me.chyxion.tigon.test;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @version 0.0.1
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2016 10:45:07 AM
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class TestDriver {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void run() {
|
|
||||||
log.info("Run.");
|
|
||||||
}
|
|
||||||
}
|
|
3
deploy
Executable file
3
deploy
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
mvn clean deploy -DskipTests -U -DaltDeploymentRepository=snapshot::default::http://101.231.57.218:8081/nexus/content/repositories/snapshots/
|
4
deploy_oss
Executable file
4
deploy_oss
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# mvn clean deploy -DskipTests -U -Prelease -DaltDeploymentRepository=oss::default::https://oss.sonatype.org/service/local/staging/deploy/maven2/
|
||||||
|
mvn clean deploy -DskipTests -Dmaven.javadoc.skip=true -U -Prelease -DaltDeploymentRepository=oss::default::https://oss.sonatype.org/content/repositories/snapshots
|
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
46d94f9b2e77fe81c9774dddb4c96228baf2ac7f
|
|
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://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
|
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.sencha.extjs</groupId>
|
|
||||||
<artifactId>extjs</artifactId>
|
|
||||||
<version>4.2.1.883</version>
|
|
||||||
<name>Sencha ExtJS</name>
|
|
||||||
<description>Sencha ExtJS</description>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
</project>
|
|
@ -1 +0,0 @@
|
|||||||
267b9ac958463fd470940ad908f8a50b8e770138
|
|
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.sencha.extjs</groupId>
|
|
||||||
<artifactId>extjs</artifactId>
|
|
||||||
<version>4.2.1.883</version>
|
|
||||||
|
|
||||||
<versioning>
|
|
||||||
<release>4.2.1.883</release>
|
|
||||||
<versions>
|
|
||||||
<version>4.2.1.883</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20200503111212</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
@ -1 +0,0 @@
|
|||||||
87791c43904f064234ca9ce207ddafef
|
|
@ -1 +0,0 @@
|
|||||||
c26a74fe148ac826ac990036e1fb3a5ed5a34a1f
|
|
57
extjs/pom.xml
vendored
57
extjs/pom.xml
vendored
@ -1,57 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://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
|
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>tigon-extjs</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
<name>Tigon Ext JS</name>
|
|
||||||
<description>Tigon Ext JS</description>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>me.chyxion.tigon</groupId>
|
|
||||||
<artifactId>tigon</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sencha.extjs</groupId>
|
|
||||||
<artifactId>extjs</artifactId>
|
|
||||||
<version>4.2.1.883</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<version>3.3.0</version>
|
|
||||||
<configuration>
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>make-assembly</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>extjs-repo</id>
|
|
||||||
<name>ExtJS</name>
|
|
||||||
<url>file://${project.basedir}/local-repo/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
</project>
|
|
@ -1,98 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.config;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import me.chyxion.tigon.i18n.resolver.I18n;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import me.chyxion.tigon.i18n.resolver.impl.I18nResolverImpl;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 11:26:34
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class I18nConfiguration {
|
|
||||||
private static final PathMatchingResourcePatternResolver resolver =
|
|
||||||
new PathMatchingResourcePatternResolver(MethodHandles.lookup().getClass().getClassLoader());
|
|
||||||
|
|
||||||
private final ReloadableResourceBundleMessageSource messageSource = new MultipleMessageSource();
|
|
||||||
{
|
|
||||||
// 扫描出来
|
|
||||||
messageSource.setBasenames(getMessageSourceBasenames());
|
|
||||||
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MultipleMessageSource extends ReloadableResourceBundleMessageSource {
|
|
||||||
private static final String PROPERTIES_SUFFIX = ".properties";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected PropertiesHolder refreshProperties(final String filename, final PropertiesHolder propHolder) {
|
|
||||||
if (filename.startsWith(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
|
|
||||||
return refreshClassPathProperties(filename, propHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.refreshProperties(filename, propHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertiesHolder refreshClassPathProperties(final String filename, final PropertiesHolder propHolder) {
|
|
||||||
val properties = new Properties();
|
|
||||||
long lastModified = -1;
|
|
||||||
try {
|
|
||||||
val resources = resolver.getResources(filename + PROPERTIES_SUFFIX);
|
|
||||||
for (val resource : resources) {
|
|
||||||
val holder = super.refreshProperties(
|
|
||||||
resource.getURI().toString().replace(PROPERTIES_SUFFIX, ""), propHolder);
|
|
||||||
properties.putAll(holder.getProperties());
|
|
||||||
if (lastModified < resource.lastModified()) {
|
|
||||||
lastModified = resource.lastModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (final IOException e) {
|
|
||||||
log.warn("Refresh class path properties error caused.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PropertiesHolder(properties, lastModified);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MessageSource messageSource() {
|
|
||||||
return messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public I18n i18nResolver(final MessageSource messageSource) {
|
|
||||||
return new I18nResolverImpl(messageSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
String[] getMessageSourceBasenames() {
|
|
||||||
val resources = resolver.getResources("classpath*:i18n/**/messages*.properties");
|
|
||||||
if (resources != null) {
|
|
||||||
val setBasenames = new HashSet<String>(resources.length);
|
|
||||||
for (val resource : resources) {
|
|
||||||
setBasenames.add(resource.getURI().toString().replaceAll(
|
|
||||||
".*(i18n(?:/\\w+)?/messages.*)_\\w+_\\w+.properties.*", "classpath*:$1"));
|
|
||||||
}
|
|
||||||
log.info("I18n message source basenames [{}] scanned.", setBasenames);
|
|
||||||
return setBasenames.toArray(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// default
|
|
||||||
log.info("No message source basenames scanned, use default [classpath:i18n/messages].");
|
|
||||||
return new String[] {"classpath*:i18n/messages"};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.constant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 国际化消息前缀
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 17, 2022 10:22:57
|
|
||||||
*/
|
|
||||||
public class I18nMsgKeyPrefix {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误消息
|
|
||||||
*/
|
|
||||||
public static final String ERRMSG = "ERRMSG.";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 枚举名称
|
|
||||||
*/
|
|
||||||
public static final String ENUM = "ENUM.";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表头
|
|
||||||
*/
|
|
||||||
public static final String TABLE_HEADER = "TABLE_HEADER.";
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.resolver;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Collection;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import me.chyxion.tigon.i18n.resolver.impl.I18nResolverImpl;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 10:41:50
|
|
||||||
*/
|
|
||||||
@Validated
|
|
||||||
public interface I18n {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
static String t(@NotBlank final String code, final Object ... args) {
|
|
||||||
return I18nResolverImpl.getStaticInstance().getI18nText(code, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param locale 区域位置
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
static String t(@NotNull Locale locale, @NotBlank final String code, final Object ... args) {
|
|
||||||
return I18nResolverImpl.getStaticInstance().getI18nText(locale, code, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
String getI18nText(@NotBlank String code, Object ... args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
<T> String getI18nText(@NotBlank String code, Collection<T> args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param locale 区域位置
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
String getI18nText(@NotNull Locale locale, @NotBlank String code, Object ... args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取国际化文本
|
|
||||||
*
|
|
||||||
* @param locale 区域位置
|
|
||||||
* @param code 国际化代码
|
|
||||||
* @param args 占位参数
|
|
||||||
* @return 国际化文本
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
<T> String getI18nText(@NotNull Locale locale, @NotBlank String code, Collection<T> args);
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.resolver.impl;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import lombok.Getter;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import me.chyxion.tigon.i18n.resolver.I18n;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 10:41:35
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class I18nResolverImpl implements I18n, InitializingBean {
|
|
||||||
private final MessageSource messageSource;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private static I18n staticInstance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getI18nText(final String code, final Object ... args) {
|
|
||||||
return getI18nText(LocaleContextHolder.getLocale(), code, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> String getI18nText(final String code, final Collection<T> args) {
|
|
||||||
return getI18nText(LocaleContextHolder.getLocale(), code, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getI18nText(final Locale locale, final String code, final Object ... args) {
|
|
||||||
val message = messageSource.getMessage(code, args, null, locale);
|
|
||||||
log.debug("Get i18n text, code [{}] result [{}].", code, message);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> String getI18nText(final Locale locale, final String code, final Collection<T> args) {
|
|
||||||
if (args != null && !args.isEmpty()) {
|
|
||||||
return getI18nText(locale, code, args.toArray());
|
|
||||||
}
|
|
||||||
return getI18nText(locale, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
staticInstance = this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
|
||||||
me.chyxion.tigon.i18n.config.I18nConfiguration
|
|
@ -1,37 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.test;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import me.chyxion.tigon.i18n.resolver.I18n;
|
|
||||||
import org.junit.Test;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Locale;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 11:32:49
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@SpringBootTest(classes = Main.class)
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
public class I18nResolverTest {
|
|
||||||
@Autowired
|
|
||||||
private MessageSource messageSource;
|
|
||||||
@Autowired
|
|
||||||
private I18n i18n;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMessageSource() {
|
|
||||||
val message = messageSource.getMessage("param.could.not.be.blank", new Object[] {"参数"}, Locale.CHINA);
|
|
||||||
log.info("message [{}].", message);
|
|
||||||
log.info("i18n text [{}].", i18n.getI18nText("param.could.not.be.blank", "请求参数"));
|
|
||||||
log.info("i18n text2 [{}].", i18n.getI18nText("param.could.not.be.blank", Arrays.asList("请求参数")));
|
|
||||||
log.info("i18n text3 [{}].", I18n.t("param.could.not.be.blank", Arrays.asList("请求参数")));
|
|
||||||
log.info("format: {0} {1} {2}", 1, 2, 3);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.test;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 11:30:53
|
|
||||||
*/
|
|
||||||
@SpringBootApplication
|
|
||||||
public class Main {
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package me.chyxion.tigon.i18n.test;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2022 11:31:55
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class TestDriver {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRun() {
|
|
||||||
log.info("TRUE: {}", Boolean.TRUE.toString());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
# common config
|
|
||||||
server:
|
|
||||||
port: 7001
|
|
||||||
|
|
||||||
spring:
|
|
||||||
jackson:
|
|
||||||
default-property-inclusion: NON_NULL
|
|
||||||
time-zone: GMT+8
|
|
||||||
servlet:
|
|
||||||
multipart:
|
|
||||||
max-file-size: 128MB
|
|
||||||
max-request-size: 128MB
|
|
@ -1 +0,0 @@
|
|||||||
bp.could.not.be.blank=BP could not be blank
|
|
@ -1 +0,0 @@
|
|||||||
bp.could.not.be.blank=BP不可以为空
|
|
@ -1,3 +0,0 @@
|
|||||||
javax.validation.constraints.NotEmpty.message=could not be empty
|
|
||||||
param.could.not.be.blank={0}不可以为空
|
|
||||||
errmsg.500=Oh, shit!
|
|
@ -1,4 +0,0 @@
|
|||||||
javax.validation.constraints.NotEmpty.message=不能为空
|
|
||||||
javax.validation.constraints.NotBlank.message=不可以为空
|
|
||||||
param.could.not.be.blank={0}不允许为空
|
|
||||||
errmsg.500=卧槽!
|
|
@ -1 +0,0 @@
|
|||||||
uc.could.not.be.blank=UC could not be blank
|
|
@ -1 +0,0 @@
|
|||||||
uc.could.not.be.blank=UC不可以为空
|
|
@ -1,38 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration debug="true" scan="true" scanPeriod="42 seconds">>
|
|
||||||
|
|
||||||
<property name="log.dir" value="${LOG_DIR:-.logs}"/>
|
|
||||||
<property name="log.level" value="${LOG_LEVEL:-DEBUG}"/>
|
|
||||||
|
|
||||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<withJansi>true</withJansi>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%magenta(%d{"yyyy-MM-dd HH:mm:ss,SSS"}) [%thread][%X{traceId}] %highlight(%-5level) %cyan(%logger{15}) - %msg %n
|
|
||||||
</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>${log.dir}/app.log</file>
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{"yyyy-MM-dd HH:mm:ss,SSS"} [%thread][%X{traceId}] %-5level %logger{15} %msg %n</pattern>
|
|
||||||
</encoder>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>${log.dir}/%d{yyyy-MM, aux}/app-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
|
||||||
<maxFileSize>32MB</maxFileSize>
|
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
|
||||||
</rollingPolicy>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework" level="${log.level}" additivity="false">
|
|
||||||
<appender-ref ref="Console"/>
|
|
||||||
<appender-ref ref="File"/>
|
|
||||||
</logger>
|
|
||||||
|
|
||||||
<root level="${log.level}">
|
|
||||||
<appender-ref ref="Console"/>
|
|
||||||
<appender-ref ref="File"/>
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
||||||
|
|
28
install.sh
28
install.sh
@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# get real path of softlink
|
|
||||||
get_real_path() {
|
|
||||||
local f="$1"
|
|
||||||
while [ -h "$f" ]; do
|
|
||||||
ls=`ls -ld "$f"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
f="$link"
|
|
||||||
else
|
|
||||||
f=`dirname "$f"`/"$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "$f"
|
|
||||||
}
|
|
||||||
|
|
||||||
prg_path=$(get_real_path "$0")
|
|
||||||
echo "Script path [$prg_path]"
|
|
||||||
|
|
||||||
# Service Home
|
|
||||||
pushd $(dirname "$prg_path") > /dev/null
|
|
||||||
WORK_DIR=$(pwd)
|
|
||||||
echo "Work dir [$WORK_DIR]"
|
|
||||||
|
|
||||||
mvn -T 4C -DskipTests clean flatten:flatten source:jar install
|
|
||||||
|
|
||||||
popd > /dev/null
|
|
@ -1 +0,0 @@
|
|||||||
# Tigon Kit
|
|
77
kit/pom.xml
77
kit/pom.xml
@ -1,77 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://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
|
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<artifactId>tigon-kit</artifactId>
|
|
||||||
<name>Tigon Kit</name>
|
|
||||||
<description>Tigon Kit</description>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>me.chyxion.tigon</groupId>
|
|
||||||
<artifactId>tigon</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate.validator</groupId>
|
|
||||||
<artifactId>hibernate-validator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>bson</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-context</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>me.chyxion.tigon</groupId>
|
|
||||||
<artifactId>tigon-common</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Test -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-logging</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,62 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.bean;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Collection;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Jun 02, 2021 15:18:17
|
|
||||||
*/
|
|
||||||
@Validated
|
|
||||||
public interface BeanService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object to map
|
|
||||||
*
|
|
||||||
* @param object object
|
|
||||||
* @return map
|
|
||||||
*/
|
|
||||||
Map<String, Object> toMap(Object object);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert type
|
|
||||||
*
|
|
||||||
* @param obj object
|
|
||||||
* @param type Type-erased type to parameterize
|
|
||||||
* @param paramClasses Type parameters to apply
|
|
||||||
* @param <T> type
|
|
||||||
* @return convert result
|
|
||||||
*/
|
|
||||||
<T> T convert(Object obj, @NotNull Class<T> type, Class<?> ... paramClasses);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert list type
|
|
||||||
*
|
|
||||||
* @param list list
|
|
||||||
* @param elementType Type-erased type to parameterize
|
|
||||||
* @param paramClasses Type parameters to apply
|
|
||||||
* @param <T> type
|
|
||||||
* @return convert result
|
|
||||||
*/
|
|
||||||
<T> List<T> convert(Collection<?> list, @NotNull Class<T> elementType, Class<?> ... paramClasses);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assign value
|
|
||||||
*
|
|
||||||
* @param to to object
|
|
||||||
* @param from from object
|
|
||||||
* @return assign result
|
|
||||||
*/
|
|
||||||
<T> T assign(T to, Object from);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* copy object
|
|
||||||
*
|
|
||||||
* @param from from object
|
|
||||||
* @return assign result
|
|
||||||
*/
|
|
||||||
<T> T copy(T from);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.config;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import me.chyxion.tigon.kit.json.JsonService;
|
|
||||||
import me.chyxion.tigon.kit.sequence.IdSequence;
|
|
||||||
import me.chyxion.tigon.kit.json.impl.JacksonImpl;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import me.chyxion.tigon.kit.sequence.impl.IdSequenceImpl;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Jul 08, 2021 11:11:32
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class TigonKitConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public JsonService jsonService(
|
|
||||||
@Autowired(required = false)
|
|
||||||
final ObjectMapper objectMapper) {
|
|
||||||
return new JacksonImpl(objectMapper != null ?
|
|
||||||
objectMapper.copy() : new ObjectMapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public IdSequence idSequence() {
|
|
||||||
return new IdSequenceImpl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.List;
|
|
||||||
import me.chyxion.tigon.kit.bean.BeanService;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import me.chyxion.tigon.kit.json.impl.JacksonImpl;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 22, 2021 16:01:20
|
|
||||||
*/
|
|
||||||
public interface JsonService extends BeanService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get object mapper
|
|
||||||
* @return object mapper
|
|
||||||
*/
|
|
||||||
ObjectMapper getObjectMapper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse json
|
|
||||||
*
|
|
||||||
* @param data json data
|
|
||||||
* @param type result type
|
|
||||||
* @param <T> result type
|
|
||||||
* @return result object
|
|
||||||
*/
|
|
||||||
<T> T parse(@NotBlank String data, Class<T> type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse json object
|
|
||||||
*
|
|
||||||
* @param data data
|
|
||||||
* @return map result
|
|
||||||
*/
|
|
||||||
Map<String, Object> parseObject(@NotBlank String data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse json array
|
|
||||||
*
|
|
||||||
* @param data json data
|
|
||||||
* @return json array list
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> parseArray(@NotBlank String data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse json array
|
|
||||||
*
|
|
||||||
* @param data json data
|
|
||||||
* @param elementType Type-erased type to parameterize
|
|
||||||
* @param paramClasses Type parameters to apply
|
|
||||||
* @param <T> element type
|
|
||||||
* @return json array list
|
|
||||||
*/
|
|
||||||
<T> List<T> parseArray(@NotBlank String data, @NotNull Class<T> elementType, Class<?> ... paramClasses);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* object to json string
|
|
||||||
*
|
|
||||||
* @param object object
|
|
||||||
* @return json string
|
|
||||||
*/
|
|
||||||
String toJSONString(Object object);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* object to json string
|
|
||||||
*
|
|
||||||
* @param object object
|
|
||||||
* @param pretty pretty format
|
|
||||||
* @return json string
|
|
||||||
*/
|
|
||||||
String toJSONString(Object object, boolean pretty);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查对象是否为{}或者null
|
|
||||||
*
|
|
||||||
* @param object object
|
|
||||||
* @return true if object is empty
|
|
||||||
*/
|
|
||||||
boolean isEmpty(Object object);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查对象是否不为{}或者null
|
|
||||||
*
|
|
||||||
* @param object object
|
|
||||||
* @return true if object is not empty
|
|
||||||
*/
|
|
||||||
default boolean isNotEmpty(Object object) {
|
|
||||||
return !isEmpty(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* static get JsonService
|
|
||||||
*
|
|
||||||
* @return JsonService
|
|
||||||
*/
|
|
||||||
static JsonService getInstance() {
|
|
||||||
return JacksonImpl.getInstance();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
|
||||||
import me.chyxion.tigon.kit.json.serializer.FinanceValueSerializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 财务数据JSON序列化格式化,保留2位小数
|
|
||||||
*
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 24, 2022 10:09:17
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@JacksonAnnotationsInside
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@JsonSerialize(using = FinanceValueSerializer.class)
|
|
||||||
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
|
|
||||||
public @interface FinanceValue {
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 21, 2022 15:33:32
|
|
||||||
*/
|
|
||||||
interface DeserializeModifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* modify json deserialized result
|
|
||||||
* @param parser json parser
|
|
||||||
* @param classInfo class info
|
|
||||||
* @param object object
|
|
||||||
* @return object
|
|
||||||
*/
|
|
||||||
Object modify(JsonParser parser, AnnotatedClass classInfo, Object object);
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.io.IOException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
import me.chyxion.tigon.annotation.Trim;
|
|
||||||
import com.fasterxml.jackson.databind.*;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import me.chyxion.tigon.annotation.json.EmptyElCleanup;
|
|
||||||
import me.chyxion.tigon.annotation.json.EmptyObjectToNull;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.Annotated;
|
|
||||||
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
|
|
||||||
import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 21:12:10
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class DeserializeModifierDelegatingDeserializer extends DelegatingDeserializer {
|
|
||||||
private final BeanDescription beanDescription;
|
|
||||||
|
|
||||||
private static final Class<?>[] ANNOTATION = new Class<?>[] {
|
|
||||||
Trim.class,
|
|
||||||
EmptyObjectToNull.class,
|
|
||||||
EmptyElCleanup.class,
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final DeserializeModifier[] MODIFIERS = new DeserializeModifier[] {
|
|
||||||
new TrimDeserializeModifier(),
|
|
||||||
new EmptyElCleanupDeserializeModifier(),
|
|
||||||
new EmptyObjectToNullDeserializeModifier()
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to return a Module with this deserializer suitable for insertion into an ObjectMapper
|
|
||||||
*
|
|
||||||
* @return a SimpleModule.
|
|
||||||
*/
|
|
||||||
public static Module getSimpleModule() {
|
|
||||||
log.info("Registering EmptyObjectToNullDelegatingDeserializer");
|
|
||||||
return new SimpleModule().setDeserializerModifier(new BeanDeserializerModifier() {
|
|
||||||
@Override
|
|
||||||
public JsonDeserializer<?> modifyDeserializer(final DeserializationConfig config,
|
|
||||||
final BeanDescription beanDescription,
|
|
||||||
final JsonDeserializer<?> originalDeserializer) {
|
|
||||||
val classInfo = beanDescription.getClassInfo();
|
|
||||||
if (hasAnnotation(classInfo)) {
|
|
||||||
log.debug("Bean description {} @EmptyObjectToNull found.", classInfo);
|
|
||||||
return new DeserializeModifierDelegatingDeserializer(originalDeserializer, beanDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StreamSupport.stream(classInfo.fields().spliterator(), true).
|
|
||||||
anyMatch(field -> hasAnnotation(field))) {
|
|
||||||
log.debug("Bean description field {} @EmptyObjectToNull found.", classInfo);
|
|
||||||
return new DeserializeModifierDelegatingDeserializer(originalDeserializer, beanDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
return originalDeserializer;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private DeserializeModifierDelegatingDeserializer(final JsonDeserializer<?> delegate, final BeanDescription beanDescription) {
|
|
||||||
super(delegate);
|
|
||||||
this.beanDescription = beanDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected JsonDeserializer<?> newDelegatingInstance(final JsonDeserializer<?> newDelegatee) {
|
|
||||||
return new DeserializeModifierDelegatingDeserializer(newDelegatee, beanDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
|
|
||||||
val obj = super.deserialize(p, ctxt);
|
|
||||||
val classInfo = beanDescription.getClassInfo();
|
|
||||||
|
|
||||||
for (val modifier : MODIFIERS) {
|
|
||||||
modifier.modify(p, classInfo, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean hasAnnotation(final Annotated annotated) {
|
|
||||||
for (val annotation : ANNOTATION) {
|
|
||||||
if (annotated.hasAnnotation(annotation)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import com.fasterxml.jackson.databind.*;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import me.chyxion.tigon.annotation.json.EmptyElCleanup;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 21:12:10
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
class EmptyElCleanupDeserializeModifier implements DeserializeModifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object modify(final JsonParser parser, final AnnotatedClass classInfo, final Object obj) {
|
|
||||||
|
|
||||||
if (classInfo.hasAnnotation(EmptyElCleanup.class)) {
|
|
||||||
log.debug("@EmptyElCleanup found on class [{}].", classInfo.getAnnotated());
|
|
||||||
classInfo.fields().forEach(field ->
|
|
||||||
emptyElementCleanup((ObjectMapper) parser.getCodec(), obj, field.getAnnotated()));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
classInfo.fields().forEach(field -> {
|
|
||||||
if (field.hasAnnotation(EmptyElCleanup.class)) {
|
|
||||||
log.debug("@EmptyElCleanup found on field [{}] of class [{}].", field.getName(), classInfo.getAnnotated());
|
|
||||||
emptyElementCleanup((ObjectMapper) parser.getCodec(), obj, field.getAnnotated());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void emptyElementCleanup(final ObjectMapper objectMapper,
|
|
||||||
final Object object,
|
|
||||||
final Field field) {
|
|
||||||
|
|
||||||
ReflectionUtils.makeAccessible(field);
|
|
||||||
val value = ReflectionUtils.getField(field, object);
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
if (value instanceof Collection) {
|
|
||||||
val it = ((Collection) value).iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
val el = it.next();
|
|
||||||
if (isNullOrEmpty(objectMapper, el)) {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
val fieldType = field.getType();
|
|
||||||
if (fieldType.isArray()) {
|
|
||||||
val length = Array.getLength(value);
|
|
||||||
if (length > 0) {
|
|
||||||
val newList = new ArrayList<>(length);
|
|
||||||
for (int i = 0; i < length; ++i) {
|
|
||||||
val el = Array.get(value, i);
|
|
||||||
if (!isNullOrEmpty(objectMapper, el)) {
|
|
||||||
newList.add(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReflectionUtils.setField(field, object,
|
|
||||||
listToArray(newList, fieldType.getComponentType()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isNullOrEmpty(final ObjectMapper objectMapper, final Object object) {
|
|
||||||
if (object == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
val jsonNode = objectMapper.valueToTree(object);
|
|
||||||
|
|
||||||
if (jsonNode.isValueNode()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonNode.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
Object listToArray(final List<?> list, final Class<?> elType) {
|
|
||||||
val array = Array.newInstance(elType, list.size());
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (val e : list) {
|
|
||||||
Array.set(array, i++, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import me.chyxion.tigon.annotation.json.EmptyObjectToNull;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 21:12:10
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
class EmptyObjectToNullDeserializeModifier implements DeserializeModifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object modify(final JsonParser parser, final AnnotatedClass classInfo, final Object obj) {
|
|
||||||
|
|
||||||
if (classInfo.hasAnnotation(EmptyObjectToNull.class)) {
|
|
||||||
log.debug("@EmptyObjectToNull found on class [{}].", classInfo.getAnnotated());
|
|
||||||
classInfo.fields().forEach(field ->
|
|
||||||
setEmptyFieldNull((ObjectMapper) parser.getCodec(), obj, field.getAnnotated()));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
classInfo.fields().forEach(field -> {
|
|
||||||
if (field.hasAnnotation(EmptyObjectToNull.class)) {
|
|
||||||
log.debug("@EmptyObjectToNull found on field [{}] of class [{}].", field.getName(), classInfo.getAnnotated());
|
|
||||||
setEmptyFieldNull((ObjectMapper) parser.getCodec(), obj, field.getAnnotated());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEmptyFieldNull(final ObjectMapper objectMapper, final Object object, final Field field) {
|
|
||||||
ReflectionUtils.makeAccessible(field);
|
|
||||||
val value = ReflectionUtils.getField(field, object);
|
|
||||||
if (value != null) {
|
|
||||||
if (isEmpty(objectMapper, value)) {
|
|
||||||
ReflectionUtils.setField(field, object, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEmpty(final ObjectMapper objectMapper, final Object object) {
|
|
||||||
val jsonNode = objectMapper.valueToTree(object);
|
|
||||||
|
|
||||||
if (jsonNode.isValueNode()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonNode.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.io.IOException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
import com.fasterxml.jackson.databind.*;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import me.chyxion.tigon.annotation.json.PostDeserialize;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
|
|
||||||
import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 21:12:10
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class PostDeserializeDelegatingDeserializer extends DelegatingDeserializer {
|
|
||||||
private final BeanDescription beanDescription;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to return a Module with this deserializer suitable for insertion into an ObjectMapper
|
|
||||||
*
|
|
||||||
* @return a SimpleModule.
|
|
||||||
*/
|
|
||||||
public static Module getSimpleModule() {
|
|
||||||
log.info("Registering JacksonPostHookDeserializer");
|
|
||||||
return new SimpleModule().setDeserializerModifier(new BeanDeserializerModifier() {
|
|
||||||
@Override
|
|
||||||
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
|
|
||||||
BeanDescription beanDescription,
|
|
||||||
JsonDeserializer<?> originalDeserializer) {
|
|
||||||
val classInfo = beanDescription.getClassInfo();
|
|
||||||
|
|
||||||
if (StreamSupport.stream(classInfo.memberMethods().spliterator(), true).
|
|
||||||
anyMatch(m -> m.hasAnnotation(PostDeserialize.class))) {
|
|
||||||
log.debug("BeanDescription {} ", classInfo);
|
|
||||||
|
|
||||||
return new PostDeserializeDelegatingDeserializer(originalDeserializer, beanDescription);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return originalDeserializer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
private PostDeserializeDelegatingDeserializer(JsonDeserializer<?> delegate, BeanDescription beanDescription) {
|
|
||||||
super(delegate);
|
|
||||||
this.beanDescription = beanDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected JsonDeserializer<?> newDelegatingInstance(final JsonDeserializer<?> newDelegatee) {
|
|
||||||
return new PostDeserializeDelegatingDeserializer(newDelegatee, beanDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
|
||||||
val obj = super.deserialize(p, ctxt);
|
|
||||||
|
|
||||||
beanDescription.getClassInfo().memberMethods().forEach(method -> {
|
|
||||||
if (method.hasAnnotation(PostDeserialize.class)) {
|
|
||||||
log.debug("Invoking method {} on {} ", method.getName(), beanDescription.getBeanClass());
|
|
||||||
try {
|
|
||||||
if (method.getAnnotation(PostDeserialize.class).forceAccess()) {
|
|
||||||
log.debug("Modifying access for {}", method);
|
|
||||||
method.fixAccess(true);
|
|
||||||
}
|
|
||||||
method.callOn(obj);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
log.error("Caught exception calling method", e);
|
|
||||||
throw new RuntimeException("Failed to call @JsonPostDeserialize annotated method in class " +
|
|
||||||
beanDescription.getClassInfo().getName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.deserializer;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import me.chyxion.tigon.annotation.Trim;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 20, 2022 21:12:10
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
class TrimDeserializeModifier implements DeserializeModifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object modify(final JsonParser p, final AnnotatedClass classInfo, final Object obj) {
|
|
||||||
if (classInfo.hasAnnotation(Trim.class)) {
|
|
||||||
log.debug("@Trim found on class [{}].", classInfo.getAnnotated());
|
|
||||||
classInfo.fields().forEach(field ->
|
|
||||||
trimFieldValue(obj,
|
|
||||||
field.getAnnotated(),
|
|
||||||
classInfo.getAnnotation(Trim.class).blankAsNull()));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
classInfo.fields().forEach(field -> {
|
|
||||||
if (field.hasAnnotation(Trim.class)) {
|
|
||||||
log.debug("@Trim found on field [{}] of class [{}].", field.getName(), classInfo.getAnnotated());
|
|
||||||
trimFieldValue(obj,
|
|
||||||
field.getAnnotated(),
|
|
||||||
field.getAnnotation(Trim.class).blankAsNull());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void trimFieldValue(final Object object, final Field field, final boolean blankAsNull) {
|
|
||||||
ReflectionUtils.makeAccessible(field);
|
|
||||||
val value = ReflectionUtils.getField(field, object);
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof String) {
|
|
||||||
val newVal = blankAsNull ?
|
|
||||||
StringUtils.trimToNull((String) value) :
|
|
||||||
StringUtils.trim((String) value);
|
|
||||||
|
|
||||||
if (newVal == null) {
|
|
||||||
ReflectionUtils.setField(field, object, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newVal.equals(value)) {
|
|
||||||
ReflectionUtils.setField(field, object, newVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
val fieldType = field.getType();
|
|
||||||
if (field.isAnnotationPresent(Trim.class) &&
|
|
||||||
!fieldType.isAnnotationPresent(Trim.class)) {
|
|
||||||
ReflectionUtils.doWithFields(fieldType, subField -> trimFieldValue(value, subField, blankAsNull));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.impl;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.util.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import me.chyxion.tigon.kit.json.JsonService;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
||||||
import me.chyxion.tigon.kit.json.deserializer.PostDeserializeDelegatingDeserializer;
|
|
||||||
import me.chyxion.tigon.kit.json.deserializer.DeserializeModifierDelegatingDeserializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Sep 26, 2019 19:21:14
|
|
||||||
*/
|
|
||||||
public class JacksonImpl implements JsonService, InitializingBean {
|
|
||||||
@Getter
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
@Getter
|
|
||||||
private static JsonService instance;
|
|
||||||
|
|
||||||
public JacksonImpl(final ObjectMapper objectMapper) {
|
|
||||||
this.objectMapper = objectMapper;
|
|
||||||
this.objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
|
|
||||||
// Enable assign NULL
|
|
||||||
this.objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
|
||||||
this.objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
|
|
||||||
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
|
||||||
|
|
||||||
this.objectMapper.registerModule(DeserializeModifierDelegatingDeserializer.getSimpleModule());
|
|
||||||
this.objectMapper.registerModule(PostDeserializeDelegatingDeserializer.getSimpleModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public <T> T parse(final String data, final Class<T> type) {
|
|
||||||
return objectMapper.readValue(data, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Map<String, Object> parseObject(final String data) {
|
|
||||||
val typeFactory = objectMapper.getTypeFactory();
|
|
||||||
val mapJavaType = typeFactory.constructParametricType(Map.class, String.class, Object.class);
|
|
||||||
return objectMapper.readValue(data, mapJavaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings({"unchecked"})
|
|
||||||
public List<Map<String, Object>> parseArray(final String data) {
|
|
||||||
return (List) parseArray(data, Map.class, String.class, Object.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public <T> List<T> parseArray(final String data, final Class<T> elementType, final Class<?> ... paramClasses) {
|
|
||||||
val typeFactory = objectMapper.getTypeFactory();
|
|
||||||
|
|
||||||
if (paramClasses != null && paramClasses.length > 0) {
|
|
||||||
val elJavaType = typeFactory.constructParametricType(elementType, paramClasses);
|
|
||||||
return objectMapper.readValue(data, typeFactory.constructCollectionType(List.class, elJavaType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectMapper.readValue(data, typeFactory.constructCollectionType(List.class, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public String toJSONString(final Object object) {
|
|
||||||
return objectMapper.writeValueAsString(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public String toJSONString(final Object object, final boolean pretty) {
|
|
||||||
return pretty ? objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object)
|
|
||||||
: toJSONString(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty(final Object object) {
|
|
||||||
if (object == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
val jsonNode = objectMapper.valueToTree(object);
|
|
||||||
|
|
||||||
if (jsonNode.isValueNode()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonNode.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Map<String, Object> toMap(final Object object) {
|
|
||||||
return objectMapper.convertValue(object, Map.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> T convert(final Object obj, final Class<T> type, final Class<?> ... paramClasses) {
|
|
||||||
if (obj == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramClasses != null && paramClasses.length > 0) {
|
|
||||||
val javaType = objectMapper.getTypeFactory().constructParametricType(type, paramClasses);
|
|
||||||
return objectMapper.convertValue(obj, javaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectMapper.convertValue(obj, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> List<T> convert(final Collection<?> list, final Class<T> elementType, final Class<?> ... paramClasses) {
|
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramClasses != null && paramClasses.length > 0) {
|
|
||||||
val typeFactory = objectMapper.getTypeFactory();
|
|
||||||
val elJavaType = typeFactory.constructParametricType(elementType, paramClasses);
|
|
||||||
return objectMapper.convertValue(list, typeFactory.constructCollectionType(List.class, elJavaType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (List<T>) convert((Object) list, List.class, elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> T copy(T from) {
|
|
||||||
return (T) objectMapper.convertValue(from, from.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public Object assign(final Object to, final Object from) {
|
|
||||||
val jsonNode = objectMapper.valueToTree(from);
|
|
||||||
return objectMapper.readerForUpdating(to).readValue(jsonNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.json.serializer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Apr 24, 2022 09:58:02
|
|
||||||
*/
|
|
||||||
public class FinanceValueSerializer extends JsonSerializer<Number> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void serialize(final Number value,
|
|
||||||
final JsonGenerator gen,
|
|
||||||
final SerializerProvider serializers) throws IOException {
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
//write the word 'null' if there's no value available
|
|
||||||
gen.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "###,###,##0.00";
|
|
||||||
gen.writeString(new DecimalFormat("0.00").format(value));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.sequence;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Jul 08, 2021 10:55:39
|
|
||||||
*/
|
|
||||||
public interface IdSequence {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get sequence
|
|
||||||
*
|
|
||||||
* @return id
|
|
||||||
*/
|
|
||||||
String get();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get uuid
|
|
||||||
*
|
|
||||||
* @return uuid
|
|
||||||
*/
|
|
||||||
String uuid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get uuid
|
|
||||||
*
|
|
||||||
* @param lowerCase lower case
|
|
||||||
* @return uuid
|
|
||||||
*/
|
|
||||||
String uuid(boolean lowerCase);
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.sequence.impl;
|
|
||||||
|
|
||||||
import lombok.val;
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import me.chyxion.tigon.kit.sequence.IdSequence;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date Jul 08, 2021 10:55:45
|
|
||||||
*/
|
|
||||||
public class IdSequenceImpl implements IdSequence {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return ObjectId.get().toHexString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String uuid() {
|
|
||||||
return uuid(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String uuid(final boolean lowerCase) {
|
|
||||||
val uuid = UUID.randomUUID();
|
|
||||||
val strUuid = Long.toHexString(uuid.getMostSignificantBits())
|
|
||||||
+ Long.toHexString(uuid.getLeastSignificantBits());
|
|
||||||
return lowerCase ? strUuid : strUuid.toUpperCase();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
|
||||||
me.chyxion.tigon.kit.config.TigonKitConfiguration
|
|
@ -1,201 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit;
|
|
||||||
|
|
||||||
import me.chyxion.tigon.kit.json.annotation.FinanceValue;
|
|
||||||
import lombok.*;
|
|
||||||
import me.chyxion.tigon.kit.model.UserCtrlrReq;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import me.chyxion.tigon.kit.json.JsonService;
|
|
||||||
import me.chyxion.tigon.kit.model.UserServReq;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2021 16:37:08
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@SpringBootTest(classes = TestDriver.class)
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
public class JsonServiceTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private JsonService jsonService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConvert() {
|
|
||||||
val userCtrlrReq = new UserCtrlrReq();
|
|
||||||
userCtrlrReq.setName("donghuang");
|
|
||||||
userCtrlrReq.setGender("male");
|
|
||||||
userCtrlrReq.setDeleted(true);
|
|
||||||
log.info("Result1 [{}].", jsonService.toJSONString(userCtrlrReq));
|
|
||||||
val convert = jsonService.convert(userCtrlrReq, UserServReq.class);
|
|
||||||
log.info("Result [{}].", convert);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetInstance() {
|
|
||||||
val userCtrlrReq = new UserCtrlrReq();
|
|
||||||
userCtrlrReq.setName("donghuang");
|
|
||||||
userCtrlrReq.setGender("male");
|
|
||||||
userCtrlrReq.setDeleted(true);
|
|
||||||
val jsonService = JsonService.getInstance();
|
|
||||||
log.info("Result1 [{}].", jsonService.toJSONString(userCtrlrReq));
|
|
||||||
val convert = jsonService.convert(userCtrlrReq, UserServReq.class);
|
|
||||||
log.info("Result [{}].", convert);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCopy() {
|
|
||||||
val userCtrlrReq = new UserCtrlrReq();
|
|
||||||
userCtrlrReq.setName("donghuang");
|
|
||||||
userCtrlrReq.setGender("male");
|
|
||||||
userCtrlrReq.setDeleted(true);
|
|
||||||
val convert = jsonService.copy(userCtrlrReq);
|
|
||||||
log.info("Copy result [{}].", convert);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAssign() {
|
|
||||||
val userCtrlrReq = new UserCtrlrReq();
|
|
||||||
userCtrlrReq.setName("donghuang");
|
|
||||||
// userCtrlrReq.setGender("male");
|
|
||||||
userCtrlrReq.setDeleted(false);
|
|
||||||
|
|
||||||
val user1 = new UserServReq();
|
|
||||||
user1.setName("donghuang");
|
|
||||||
user1.setGender("male");
|
|
||||||
user1.setIsDeleted(true);
|
|
||||||
|
|
||||||
log.info("Result1 [{}].", user1);
|
|
||||||
log.info("Result2 [{}].", jsonService.assign(user1, userCtrlrReq));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConvert1() {
|
|
||||||
val convert = jsonService.convert("1", Integer.class);
|
|
||||||
log.info("Result [{}].", convert);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConvert2() {
|
|
||||||
val convert = jsonService.convert("1", Integer.class);
|
|
||||||
log.info("Result [{}].", convert);
|
|
||||||
log.info("Result [{}].", jsonService.convert("MALE", Gender.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Gender {
|
|
||||||
MALE,
|
|
||||||
FEMALE
|
|
||||||
}
|
|
||||||
|
|
||||||
@Value("${value1:${value2:#{null}}}")
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValue() {
|
|
||||||
log.info("Value: {}", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsEmpty() {
|
|
||||||
log.info("Value: {}", jsonService.isEmpty(new Object()));
|
|
||||||
log.info("Value: {}", jsonService.isEmpty(new HashMap<>()));
|
|
||||||
log.info("Value: {}", jsonService.isEmpty(new HashMap<String, String>(){{put("foo", "bar");}}));
|
|
||||||
log.info("Value: {}", jsonService.isEmpty(new ArrayList<>()));
|
|
||||||
|
|
||||||
log.info("Value: {}", jsonService.isEmpty("123"));
|
|
||||||
log.info("Value: {}", jsonService.isEmpty(123));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
static class Model1 {
|
|
||||||
private Date date;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
static class Model2 {
|
|
||||||
private Long date;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
static class Model3 {
|
|
||||||
private List<String> data;
|
|
||||||
private List<Model1> modelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
static class Model4 {
|
|
||||||
private List<Long> data;
|
|
||||||
private List<Model2> modelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConvert3() {
|
|
||||||
log.info("Model2: {}", jsonService.convert(new Model1(new Date()), Model2.class));
|
|
||||||
log.info("Model1: {}", jsonService.convert(new Model2(System.currentTimeMillis()), Model1.class));
|
|
||||||
List<Integer> intList1 = jsonService.convert(Arrays.asList("1", "2", "3"), Integer.class);
|
|
||||||
log.info("List: {}", intList1);
|
|
||||||
|
|
||||||
List<List> intList2 = jsonService.convert(
|
|
||||||
Arrays.asList(Arrays.asList("1"), Arrays.asList("2"), Arrays.asList("3")),
|
|
||||||
List.class, Integer.class);
|
|
||||||
|
|
||||||
log.info("List: {}", intList2);
|
|
||||||
val model4 = jsonService.convert(
|
|
||||||
new Model3(Arrays.asList("1"), Arrays.asList(new Model1(new Date()))), Model4.class);
|
|
||||||
log.info("Model4: {}", model4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
static class FinanceValueModel {
|
|
||||||
@FinanceValue
|
|
||||||
private BigDecimal value1;
|
|
||||||
@FinanceValue
|
|
||||||
private Long value2;
|
|
||||||
@FinanceValue
|
|
||||||
private Double value3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFinanceValue() {
|
|
||||||
val model = new FinanceValueModel();
|
|
||||||
model.setValue1(new BigDecimal(1000));
|
|
||||||
model.setValue2(1000L);
|
|
||||||
model.setValue3(99.99);
|
|
||||||
log.info("FinanceValue: {}", jsonService.toJSONString(model));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseArray() {
|
|
||||||
val data = jsonService.parseArray("[{\"key\":\"value\"}]");
|
|
||||||
log.info("Parse array: {}", data);
|
|
||||||
val array2 = jsonService.parseArray("[1, 2, 3]", Long.class);
|
|
||||||
log.info("Parse array: {}", array2);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.ImportResource;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2021 16:38:34
|
|
||||||
*/
|
|
||||||
@SpringBootApplication
|
|
||||||
@ImportResource("classpath*:spring/spring-*.xml")
|
|
||||||
public class TestDriver {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2021 16:45:28
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public class UserCtrlrReq implements Serializable {
|
|
||||||
private String name;
|
|
||||||
private String gender;
|
|
||||||
private Boolean deleted;
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package me.chyxion.tigon.kit.model;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Donghuang
|
|
||||||
* @date May 13, 2021 16:46:07
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public class UserServReq implements Serializable {
|
|
||||||
private String name;
|
|
||||||
private String gender;
|
|
||||||
@JsonProperty("deleted")
|
|
||||||
private Boolean isDeleted;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
spring:
|
|
||||||
jackson:
|
|
||||||
default-property-inclusion: ALWAYS
|
|
||||||
|
|
||||||
# value2: value2
|
|
||||||
# value1: value1
|
|
@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
||||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
|
||||||
|
|
||||||
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
|
|
||||||
<property name="dateFormat">
|
|
||||||
<bean class="java.text.SimpleDateFormat">
|
|
||||||
<constructor-arg value="yyyy-MM-dd'T'HH:mm:ssXXX" />
|
|
||||||
</bean>
|
|
||||||
</property>
|
|
||||||
<property name="timeZone" value="GMT+8" />
|
|
||||||
<property name="serializationInclusion" value="NON_NULL" />
|
|
||||||
</bean>
|
|
||||||
</beans>
|
|
@ -1 +0,0 @@
|
|||||||
#tigon-base-model
|
|
@ -1 +0,0 @@
|
|||||||
package me.chyxion.tigon.controller;
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user