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
|
||||
!.gitkeep
|
||||
*.iml
|
||||
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
|
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