diff --git a/demo-parent.iml b/demo-parent.iml
deleted file mode 100644
index 8cffef8f8c4301df1a8a7a3f088e426b49ce1220..0000000000000000000000000000000000000000
--- a/demo-parent.iml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/kafka/pom.xml b/demo/pom.xml
similarity index 51%
rename from kafka/pom.xml
rename to demo/pom.xml
index 6210217cb623516db04312bdc2d244cd3e40f0f7..d706fc4a64472e85145cdcab439d2b26a67f2482 100644
--- a/kafka/pom.xml
+++ b/demo/pom.xml
@@ -9,33 +9,29 @@
4.0.0
- kafka
-
+ demo
- org.springframework.kafka
- spring-kafka
+ org.springframework.boot
+ spring-boot-starter-web
- com.alibaba
- fastjson
- 1.2.56
+ com.baomidou
+ mybatis-plus-boot-starter
- org.projectlombok
- lombok
- provided
+ com.baomidou
+ mybatis-plus-generator
- org.springframework.kafka
- spring-kafka-test
- test
+ mysql
+ mysql-connector-java
+
- org.apache.commons
- commons-lang3
- 3.9
+ org.freemarker
+ freemarker
-
+
\ No newline at end of file
diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/CodeGenerator.java b/demo/src/main/java/com/duanledexianxianxian/demo/CodeGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4b222cf027fc7e234dacc5f92ea61d6f88ac298
--- /dev/null
+++ b/demo/src/main/java/com/duanledexianxianxian/demo/CodeGenerator.java
@@ -0,0 +1,130 @@
+package com.duanledexianxianxian.demo;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * 代码生成器
+ */
+public class CodeGenerator {
+ /**
+ * 读取控制台内容
+ *
+ * @param tip the tip
+ * @return the string
+ */
+ public static String scanner(String tip) {
+ Scanner scanner = new Scanner(System.in);
+ StringBuilder help = new StringBuilder();
+ help.append("请输入" + tip + ":");
+ System.out.println(help.toString());
+ if (scanner.hasNext()) {
+ String ipt = scanner.next();
+ if (StringUtils.isNotEmpty(ipt)) {
+ return ipt;
+ }
+ }
+ throw new MybatisPlusException("请输入正确的" + tip + "!");
+ }
+
+ /**
+ * The entry point of application.
+ *
+ * @param args the input arguments
+ */
+ public static void main(String[] args) {
+ // 代码生成器
+ AutoGenerator mpg = new AutoGenerator();
+
+ // 全局配置
+ GlobalConfig gc = new GlobalConfig();
+ // 项目路径
+ String projectPath = "F:/@project@/@dianli@/springboot-demo/demo";
+ gc.setOutputDir(projectPath + "/src/main/java");
+ gc.setAuthor("duanledexianxianxian");
+ gc.setOpen(false);
+ gc.setFileOverride(true);
+ gc.setBaseResultMap(true);
+ gc.setBaseColumnList(true);
+ // gc.setSwagger2(true); 实体属性 Swagger2 注解
+ mpg.setGlobalConfig(gc);
+
+ // 数据源配置
+ DataSourceConfig dsc = new DataSourceConfig();
+ dsc.setUrl("jdbc:mysql://rm-bp1451sz2b7q8w95xvo.mysql.rds.aliyuncs.com:3306/convention?useUnicode=true&useSSL=false&characterEncoding=utf8");
+ // dsc.setSchemaName("public");
+ dsc.setDriverName("com.mysql.cj.jdbc.Driver");
+ dsc.setUsername("convention");
+ dsc.setPassword("Convention123");
+ mpg.setDataSource(dsc);
+
+ // 包配置
+ PackageConfig pc = new PackageConfig();
+ pc.setModuleName(scanner("模块名"));
+ pc.setParent("com.duanledexianxianxian.demo");
+ mpg.setPackageInfo(pc);
+
+ // 自定义配置
+ InjectionConfig cfg = new InjectionConfig() {
+ @Override
+ public void initMap() {
+ // to do nothing
+ }
+ };
+
+ // 如果模板引擎是 freemarker
+ String templatePath = "/templates/mapper.xml.ftl";
+ // 如果模板引擎是 velocity
+ // String templatePath = "/templates/mapper.xml.vm";
+
+ // 自定义输出配置
+ List focList = new ArrayList<>();
+ // 自定义配置会被优先输出
+ focList.add(new FileOutConfig(templatePath) {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+ return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+ }
+ });
+
+ cfg.setFileOutConfigList(focList);
+ mpg.setCfg(cfg);
+
+ // 配置模板
+ TemplateConfig templateConfig = new TemplateConfig();
+
+ templateConfig.setXml(null);
+ mpg.setTemplate(templateConfig);
+
+ // 策略配置
+ StrategyConfig strategy = new StrategyConfig();
+ strategy.setNaming(NamingStrategy.underline_to_camel);
+ strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+// strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
+ strategy.setEntityLombokModel(true);
+ strategy.setRestControllerStyle(true);
+ // 公共父类
+// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
+ // 写于父类中的公共字段
+// strategy.setSuperEntityColumns("id");
+ strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
+ strategy.setControllerMappingHyphenStyle(true);
+ strategy.setTablePrefix(pc.getModuleName() + "_");
+ mpg.setStrategy(strategy);
+ mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+ mpg.execute();
+ }
+}
diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/common/util/BeanUtils.java b/demo/src/main/java/com/duanledexianxianxian/demo/common/util/BeanUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..d043c9f7d7ff7aeed0963b178f80cd76a3c2aa9c
--- /dev/null
+++ b/demo/src/main/java/com/duanledexianxianxian/demo/common/util/BeanUtils.java
@@ -0,0 +1,575 @@
+package com.duanledexianxianxian.demo.common.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+
+/**
+ * BeanUtil提供一系列与bean相关的操作.
+ *
+ * @author duanledexianxianxian
+ * @date 2019-02-14 23:35:22
+ */
+public class BeanUtils extends org.springframework.beans.BeanUtils {
+
+ /**
+ * The constant logger.
+ */
+ private static Logger logger = LoggerFactory.getLogger(BeanUtils.class);
+ /**
+ * The constant SERIAL_VERSION_UID.
+ */
+ private static final String SERIAL_VERSION_UID = "serialVersionUID";
+
+ /**
+ * The constant COMPARE_TYPE_INTEGER.
+ */
+ private static final String COMPARE_TYPE_INTEGER = "java.lang.Integer";
+ /**
+ * The constant COMPARE_TYPE_STRING.
+ */
+ private static final String COMPARE_TYPE_STRING = "java.lang.String";
+
+
+ /**
+ * Copy properties.
+ *
+ * @param source the source
+ * @param target the target
+ * @throws BeansException the beans exception
+ */
+ public static void copyProperties(Object source, Object target) throws BeansException {
+ copyProperties(source, target, null, (String[]) null);
+ }
+
+ /**
+ * Copy properties.
+ *
+ * @param source the source
+ * @param target the target
+ * @param editable the editable
+ * @param ignoreProperties the ignore properties
+ * @throws BeansException the beans exception
+ */
+ private static void copyProperties(Object source, Object target, Class> editable, String... ignoreProperties)
+ throws BeansException {
+
+ Assert.notNull(source, "Source must not be null");
+ Assert.notNull(target, "Target must not be null");
+
+ Class> actualEditable = target.getClass();
+ if (editable != null) {
+ if (!editable.isInstance(target)) {
+ throw new IllegalArgumentException("Target class [" + target.getClass().getName()
+ + "] not assignable to Editable class [" + editable.getName() + "]");
+ }
+ actualEditable = editable;
+ }
+ PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
+ List ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
+
+ for (PropertyDescriptor targetPd : targetPds) {
+ Method writeMethod = targetPd.getWriteMethod();
+ boolean ignoreCondition = ignoreList == null || !ignoreList.contains(targetPd.getName());
+ if (writeMethod != null && ignoreCondition) {
+ PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
+ if (sourcePd != null) {
+ Method readMethod = sourcePd.getReadMethod();
+ boolean isAssignable = ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType());
+ if (readMethod != null && isAssignable) {
+ try {
+ setReadMethod(readMethod);
+ Object value = readMethod.invoke(source);
+ // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等
+ setWriteMethodMethod(value, writeMethod, target);
+ } catch (Throwable ex) {
+ throw new FatalBeanException(
+ "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets read method.
+ *
+ * @param readMethod the read method
+ */
+ private static void setReadMethod(Method readMethod) {
+ if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
+ readMethod.setAccessible(true);
+ }
+ }
+
+ /**
+ * Sets write method method.
+ *
+ * @param value the value
+ * @param writeMethod the write method
+ * @param target the target
+ * @throws Exception the exception
+ */
+ private static void setWriteMethodMethod(Object value, Method writeMethod, Object target) throws Exception {
+ if (value != null) {
+ if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
+ writeMethod.setAccessible(true);
+ }
+ writeMethod.invoke(target, value);
+ }
+ }
+
+
+ /**
+ * 复制对象.
+ *
+ * @param the type parameter
+ * @param entity the entity
+ * @param targetCls the target cls
+ * @return the t
+ */
+ public static T copyObject(Object entity, Class extends T> targetCls) {
+ // 如果entity,直接返回null
+ if (entity == null) {
+ return null;
+ }
+ Object target = null;
+ try {
+ target = targetCls.newInstance();
+ copyProperties(entity, target);
+ } catch (InstantiationException | IllegalAccessException e) {
+ logger.error("error:{}", e);
+ }
+ return (T) target;
+ }
+
+ /**
+ * 复制对象
+ *
+ * @param list the list
+ * @param targetCls the target cls
+ * @return list list
+ */
+ public static List copyList(List list, Class> targetCls) {
+ List resultList = new ArrayList();
+ if (list != null && list.size() > 0) {
+ for (Object entity : list) {
+ resultList.add(copyObject(entity, targetCls));
+ }
+ }
+ return resultList;
+ }
+
+
+ /**
+ * java反射bean的get方法
+ *
+ * @param objectClass the object class
+ * @param fieldName the field name
+ * @return get method
+ */
+ @SuppressWarnings("unchecked")
+ public static Method getGetMethod(Class objectClass, String fieldName) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("get");
+ sb.append(fieldName.substring(0, 1).toUpperCase());
+ sb.append(fieldName.substring(1));
+ try {
+ return objectClass.getMethod(sb.toString());
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ logger.error("error:{}", e);
+ }
+ return null;
+ }
+
+
+ /**
+ * java反射bean的set方法
+ *
+ * @param objectClass the object class
+ * @param fieldName the field name
+ * @return set method
+ */
+ @SuppressWarnings("unchecked")
+ public static Method getSetMethod(Class objectClass, String fieldName) {
+ try {
+ Class[] parameterTypes = new Class[1];
+ Field field = objectClass.getDeclaredField(fieldName);
+ parameterTypes[0] = field.getType();
+ StringBuffer sb = new StringBuffer();
+ sb.append("set");
+ sb.append(fieldName.substring(0, 1).toUpperCase());
+ sb.append(fieldName.substring(1));
+ Method method = objectClass.getMethod(sb.toString(), parameterTypes);
+ return method;
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("error:{}", e);
+ }
+ return null;
+ }
+
+
+ /**
+ * 执行set方法
+ *
+ * @param o 执行对象
+ * @param fieldName 属性
+ * @param value 值
+ */
+ public static void invokeSet(Object o, String fieldName, Object value) {
+ Method method = getSetMethod(o.getClass(), fieldName);
+ try {
+ method.invoke(o, new Object[]{value});
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("error:{}", e);
+ }
+ }
+
+ /**
+ * 这个函数主要用于将字符串和数字型分开 前台都是字符串 根据model类型转换 现在仅支持String int 不是这两个类型不做set函数
.
+ *
+ * @param o the o
+ * @param fieldName the field name
+ * @param value the value
+ */
+ public static void invokeSetStringInt(Object o, String fieldName, String value) {
+ Method method = getGetMethod(o.getClass(), fieldName);
+ String type = method.getReturnType().getName();
+ if (COMPARE_TYPE_INTEGER.equals(type)) {
+ invokeSet(o, fieldName, (value == null) ? null : Integer.parseInt(value));
+ } else if (COMPARE_TYPE_STRING.equals(type)) {
+ invokeSet(o, fieldName, value);
+ } else {
+ logger.error("set 函数不能设置Sting和int以外的函数,设置类型:" + type + ",方法:" + method.getName());
+ }
+ }
+
+ /**
+ * 执行get方法
+ *
+ * @param o 执行对象
+ * @param fieldName 属性
+ * @return the object
+ */
+ public static Object invokeGet(Object o, String fieldName) {
+ Method method = getGetMethod(o.getClass(), fieldName);
+ try {
+ return method.invoke(o, new Object[0]);
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("error:{}", e);
+ }
+ return null;
+ }
+
+
+ /**
+ * 将返回值包装成String 如果是空则仍然保持空.
+ *
+ * @param o the o
+ * @param fieldName the field name
+ * @return the string
+ */
+ public static String invokeGetString(Object o, String fieldName) {
+ Object obj = invokeGet(o, fieldName);
+ return (obj == null) ? null : String.valueOf(obj);
+ }
+
+
+ /**
+ * Merger obj object.
+ *
+ * @param 项目域对象如果为空,则直接返回产品域对象项目域对象字段属性为空,则使用产品域覆盖项目域字段
+ * @param parent 产品域对象
+ * @param son 项目域对象
+ * @param refClass class对象
+ * @return the object
+ */
+ public static Object mergerObj(T parent, T son, Class> refClass) {
+ Object obj = null;
+ try {
+ obj = refClass.newInstance();
+ if (parent == null) {
+ obj = son;
+ } else if (son == null) {
+ obj = parent;
+ } else {
+ for (Field field : refClass.getDeclaredFields()) {
+ String fieldName = field.getName();
+ if (SERIAL_VERSION_UID.equalsIgnoreCase(fieldName)) {
+ continue;
+ }
+ Object value = invokeGet(son, fieldName);
+ if (value == null) {
+ value = invokeGet(parent, fieldName);
+ }
+ invokeSet(obj, fieldName, value);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("error:{}", e);
+ }
+ logger.debug("Page object:" + obj);
+ return obj;
+ }
+
+
+ /**
+ * Merger obj object.
+ *
+ * @param the type parameter
+ * @param parent the parent
+ * @param son the son
+ * @param refClassParent the ref class parent
+ * @param refClassSon the ref class son
+ * @return the object
+ */
+ public static Object mergerObj(T parent, T son, Class> refClassParent, Class> refClassSon) {
+ return mergerObj(parent, son, refClassParent, refClassSon, null);
+ }
+
+
+ /**
+ * Merger obj object.
+ *
+ * @param 父对象为空,则直接返回子对象
+ * 子对象为空,则将子对象域父对象相同的字段拷贝给obj
+ * 父对象与子对象都不为空,现将子对象的值拷贝给obj,在将子对象与父对象相同的字段拷贝给obj
+ * 例如:比如指标与业务视图字段合并,则指标为父对象、业务视图字段为子对象变量命名有问题
+ * @param parent 父对象
+ * @param son 子对象
+ * @param refClassParent 父class对象
+ * @param refClassSon 子class对象
+ * @param prefix 前缀
+ * @return the object
+ */
+ public static Object mergerObj(T parent, T son, Class> refClassParent,
+ Class> refClassSon, String prefix) {
+ Map publicFieldMap = new HashMap<>(100);
+ Object obj = null;
+ try {
+ //比较父class对象与子class对象,找出字段相同的字段
+ for (Field pField : refClassParent.getDeclaredFields()) {
+ for (Field sField : refClassSon.getDeclaredFields()) {
+ if (sField.getName().equals(pField.getName())) {
+ publicFieldMap.put(pField.getName(), sField.getName());
+ break;
+ } else if (prefix != null && sField.getName().equals(prefix + pField.getName())) {
+ publicFieldMap.put(pField.getName(), sField.getName());
+ break;
+ }
+ }
+ }
+
+ obj = refClassSon.newInstance();
+ //父对象为空,直接返回父对象给obj
+ if (parent == null) {
+ obj = son;
+ } else
+ //子对象为空,将父对象中与子对象中相同字段的值复制给obj
+ if (son == null) {
+ for (Map.Entry entry : publicFieldMap.entrySet()) {
+ if (SERIAL_VERSION_UID.equalsIgnoreCase(entry.getValue())) {
+ continue;
+ }
+ Object value = invokeGet(parent, entry.getValue());
+ invokeSet(obj, entry.getValue(), value);
+ }
+ } else {
+ //先将子对象拷贝给obj
+ for (Field field : refClassSon.getDeclaredFields()) {
+ if (SERIAL_VERSION_UID.equalsIgnoreCase(field.getName())) {
+ continue;
+ }
+ Object value = invokeGet(son, field.getName());
+ invokeSet(obj, field.getName(), value);
+ }
+ //将相同字段的值拷贝给obj
+ for (Map.Entry entry : publicFieldMap.entrySet()) {
+ String pFieldName = entry.getKey();
+ if (SERIAL_VERSION_UID.equalsIgnoreCase(entry.getValue())) {
+ continue;
+ }
+ Object value = invokeGet(son, entry.getValue());
+ if (null == value || "".equals(value)) {
+ value = invokeGet(parent, pFieldName);
+ }
+ invokeSet(obj, entry.getValue(), value);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("error:{}", e);
+ }
+ return obj;
+ }
+
+
+ /**
+ * Division obj t.
+ *
+ * @param the type parameter
+ * @param parent 父对象
+ * @param son 子对象
+ * @param newSon 新的子对象
+ * @param refClass class对象
+ * @return T t
+ */
+ public static T divisionObj(T parent, T son, T newSon, Class> refClass) {
+ return divisionObj(parent, son, newSon, refClass, "");
+ }
+
+
+ /**
+ * 比较产品域对象、项目域对象、页面对象,返回最后需要插入数据库中的对象
+ *
+ * @param the type parameter
+ * @param parent 父对象
+ * @param son 子对象
+ * @param newSon 新的子对象
+ * @param refClass class对象
+ * @param excludeFields 不需要比较字段的列表
+ * @return T t
+ */
+ public static T divisionObj(T parent, T son, T newSon, Class> refClass, String... excludeFields) {
+ for (Field field : refClass.getDeclaredFields()) {
+ if (SERIAL_VERSION_UID.equalsIgnoreCase(field.getName())) {
+ continue;
+ }
+ //排除不需要比较的字段
+ if (!"".equals(excludeFields) && Arrays.asList(excludeFields).contains(field.getName())) {
+ continue;
+ }
+ /*项目域不存在,则说明该元素只是项目化没有修改,表里面不存在*/
+ Object valueSon = (son == null) ? null : invokeGet(son, field.getName());
+ /*子对象的对应的属性为空,则继承与产品域的属性,如果没有修改则继续继承*/
+ if (valueSon == null) {
+ Object valueNewSon = invokeGet(newSon, field.getName());
+ Object valueParent = invokeGet(parent, field.getName());
+ if (valueParent != null && valueParent.equals(valueNewSon)) {
+ invokeSet(newSon, field.getName(), null);
+ }
+ }
+ }
+ return newSon;
+ }
+
+ /**
+ * 应用场景,产品域字段列表跟项目域字段列表合并,以keyName作为主键,相同的keyName,则使用项目域的覆盖产品域的
+ *
+ * @param the type parameter
+ * @param parentList 父域列表
+ * @param sonList 子域列表
+ * @param keyName 主键
+ * @return list list
+ */
+ public static List mergerList(List parentList, List sonList, String keyName) {
+ List resultList = new ArrayList();
+ Map