From 12e93ff6b2fd4a2e27bf7aeb5b3b1a5cfd0ffc78 Mon Sep 17 00:00:00 2001 From: duanledexianxianxian Date: Thu, 19 Mar 2020 17:58:09 +0800 Subject: [PATCH] init --- demo-parent.iml | 68 --- {kafka => demo}/pom.xml | 30 +- .../demo/CodeGenerator.java | 130 ++++ .../demo/common/util/BeanUtils.java | 575 ++++++++++++++++++ .../demo/domain/dto/MenuDTO.java | 48 ++ .../demo/domain/dto/UserDTO.java | 54 ++ .../demo/domain/model/query/MenuForm.java | 48 ++ .../demo/domain/model/query/MenuQuery.java | 23 + .../demo/domain/model/query/UserForm.java | 47 ++ .../demo/domain/model/query/UserQuery.java | 40 ++ .../demo/domain/model/vo/MenuVO.java | 45 ++ .../demo/domain/model/vo/UserDetailVO.java | 52 ++ .../demo/domain/model/vo/UserVO.java | 47 ++ demo/src/main/resources/application.yml | 0 kafka/README.md | 23 - kafka/kafka.iml | 101 --- .../demo/kafka/Application.java | 21 - .../demo/kafka/consumer/TestConsumer.java | 26 - .../kafka/controller/KafkaController.java | 24 - .../demo/kafka/listener/AppListener.java | 66 -- .../demo/kafka/model/Student.java | 35 -- kafka/src/main/resources/application.yml | 38 -- menu/pom.xml | 16 - .../demo/Application.java | 94 --- .../com/duanledexianxianxian/demo/Menu.java | 18 - .../com/duanledexianxianxian/demo/MenuVO.java | 21 - pom.xml | 74 ++- 27 files changed, 1178 insertions(+), 586 deletions(-) delete mode 100644 demo-parent.iml rename {kafka => demo}/pom.xml (51%) create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/CodeGenerator.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/common/util/BeanUtils.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/MenuDTO.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/UserDTO.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuForm.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuQuery.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserForm.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserQuery.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/MenuVO.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserDetailVO.java create mode 100644 demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserVO.java create mode 100644 demo/src/main/resources/application.yml delete mode 100644 kafka/README.md delete mode 100644 kafka/kafka.iml delete mode 100644 kafka/src/main/java/com/duanledexianxianxian/demo/kafka/Application.java delete mode 100644 kafka/src/main/java/com/duanledexianxianxian/demo/kafka/consumer/TestConsumer.java delete mode 100644 kafka/src/main/java/com/duanledexianxianxian/demo/kafka/controller/KafkaController.java delete mode 100644 kafka/src/main/java/com/duanledexianxianxian/demo/kafka/listener/AppListener.java delete mode 100644 kafka/src/main/java/com/duanledexianxianxian/demo/kafka/model/Student.java delete mode 100644 kafka/src/main/resources/application.yml delete mode 100644 menu/pom.xml delete mode 100644 menu/src/main/java/com/duanledexianxianxian/demo/Application.java delete mode 100644 menu/src/main/java/com/duanledexianxianxian/demo/Menu.java delete mode 100644 menu/src/main/java/com/duanledexianxianxian/demo/MenuVO.java diff --git a/demo-parent.iml b/demo-parent.iml deleted file mode 100644 index 8cffef8..0000000 --- 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 6210217..d706fc4 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 0000000..f4b222c --- /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 0000000..d043c9f --- /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 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 map = new HashMap<>(100); + if (parentList == null) { + resultList.addAll(sonList); + return resultList; + } + if (sonList == null) { + resultList.addAll(parentList); + return resultList; + } + resultList.addAll(parentList); + for (T obj : parentList) { + Object keyFieldName = invokeGet(obj, keyName); + map.put(keyFieldName, obj); + } + int size = sonList.size(); + for (int i = 0; i < size; i++) { + Object keyFieldName = invokeGet(sonList.get(i), keyName); + if (map.containsKey(keyFieldName)) { + resultList.remove(map.get(keyFieldName)); + resultList.add(i, sonList.get(i)); + } else { + resultList.add(sonList.get(i)); + } + } + return resultList; + } + + + /** + * 返回dto的所有属性字段名称 返回其中所有字段(除serialVersionUID之外) 可以用于设置值. + * + * @param the type parameter + * @param refClass the ref class + * @return the string [ ] + */ + public static String[] getAllFieldName(Class refClass) { + Field[] allField = refClass.getDeclaredFields(); + List allFieldList = new ArrayList(); + for (int i = 0, j = 0; i < allField.length; i++) { + String filedName = allField[i].getName(); + if (!SERIAL_VERSION_UID.equalsIgnoreCase(filedName)) { + allFieldList.add(filedName); + } + } + return allFieldList.toArray(new String[allFieldList.size()]); + } + + + /** + * 返回dto的所有Field字段 返回其中所有字段(除serialVersionUID之外) 可以用于设置值. + * + * @param the type parameter + * @param refClass the ref class + * @return the field [ ] + */ + public static Field[] getAllField(Class refClass) { + Field[] allField = refClass.getDeclaredFields(); + List allFieldList = new ArrayList(); + for (int i = 0, j = 0; i < allField.length; i++) { + if (!SERIAL_VERSION_UID.equalsIgnoreCase(allField[i].getName())) { + allFieldList.add(allField[i]); + } + } + return allFieldList.toArray(new Field[allFieldList.size()]); + } + + + /** + * 获取指定字段名称查找在class中的对应的Field对象(包括查找父类) + * + * @param clazz 指定的class + * @param fieldName 字段名称 + * @return Field对象 class field + */ + public static Field getClassField(Class clazz, String fieldName) { + if (!Object.class.getName().equals(clazz.getName())) { + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + if (field.getName().equals(fieldName)) { + return field; + } + } + Class superClass = clazz.getSuperclass(); + if (superClass != null) { + // 简单的递归一下 + return getClassField(superClass, fieldName); + } + } + return null; + } + + +} + diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/MenuDTO.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/MenuDTO.java new file mode 100644 index 0000000..923d35d --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/MenuDTO.java @@ -0,0 +1,48 @@ +package com.duanledexianxianxian.demo.domain.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 菜单传输对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class MenuDTO implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + + /** + * 菜单编号 + */ + private Long menuId; + + /** + * 菜单url + */ + private String menuUrl; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 菜单编码 + */ + private String menuCode; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/UserDTO.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/UserDTO.java new file mode 100644 index 0000000..1b0011b --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/dto/UserDTO.java @@ -0,0 +1,54 @@ +package com.duanledexianxianxian.demo.domain.dto; + +import com.duanledexianxianxian.demo.domain.entity.Menu; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; + +/** + * 用户传输对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class UserDTO implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 年龄 + */ + private Integer age; + + /** + * 生日 + */ + private LocalDate birthday; + + /** + * 菜单列表 + */ + List menuList; + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuForm.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuForm.java new file mode 100644 index 0000000..8dfb283 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuForm.java @@ -0,0 +1,48 @@ +package com.duanledexianxianxian.demo.domain.model.query; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 菜单表单对象 + * + * @author duanledexianxianxian + * @since 2020-03-19 + */ +@Data +public class MenuForm implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 用户编号 + */ + private Long userId; + /** + * 菜单编号 + */ + private Long menuId; + + /** + * 菜单url + */ + private String menuUrl; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 菜单编码 + */ + private String menuCode; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuQuery.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuQuery.java new file mode 100644 index 0000000..7abe451 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/MenuQuery.java @@ -0,0 +1,23 @@ +package com.duanledexianxianxian.demo.domain.model.query; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 菜单查询对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class MenuQuery implements Serializable { + + /** + * 菜单名称 + */ + private String menuName; + + + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserForm.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserForm.java new file mode 100644 index 0000000..1c5d98a --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserForm.java @@ -0,0 +1,47 @@ +package com.duanledexianxianxian.demo.domain.model.query; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + * 用户表单对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class UserForm implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 年龄 + */ + private Integer age; + + /** + * 生日 + */ + private LocalDate birthday; + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserQuery.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserQuery.java new file mode 100644 index 0000000..e31f052 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/query/UserQuery.java @@ -0,0 +1,40 @@ +package com.duanledexianxianxian.demo.domain.model.query; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + * 用户查询对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class UserQuery implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + /** + * The Page num. + */ + Long pageNum=1L; + /** + * The Page size. + */ + Long pageSize=10L; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/MenuVO.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/MenuVO.java new file mode 100644 index 0000000..d52f421 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/MenuVO.java @@ -0,0 +1,45 @@ +package com.duanledexianxianxian.demo.domain.model.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 菜单vo对象 + * + * @author duanledexianxianxian + * @since 2020-03-19 + */ +@Data +public class MenuVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单编号 + */ + private Long menuId; + + /** + * 菜单url + */ + private String menuUrl; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 菜单编码 + */ + private String menuCode; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserDetailVO.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserDetailVO.java new file mode 100644 index 0000000..1164354 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserDetailVO.java @@ -0,0 +1,52 @@ +package com.duanledexianxianxian.demo.domain.model.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; + +/** + * 用户vo对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class UserDetailVO implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 年龄 + */ + private Integer age; + + /** + * 生日 + */ + private LocalDate birthday; + + /** + * The Menu list. + */ + private List menuList; +} diff --git a/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserVO.java b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserVO.java new file mode 100644 index 0000000..dd7f8e1 --- /dev/null +++ b/demo/src/main/java/com/duanledexianxianxian/demo/domain/model/vo/UserVO.java @@ -0,0 +1,47 @@ +package com.duanledexianxianxian.demo.domain.model.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + * 用户vo对象 + * + * @author duanledexianxianxian + * @since 2020 -03-19 + */ +@Data +public class UserVO implements Serializable { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = 1L; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + + /** + * 用户昵称 + */ + private String nickName; + + /** + * 年龄 + */ + private Integer age; + + /** + * 生日 + */ + private LocalDate birthday; + +} diff --git a/demo/src/main/resources/application.yml b/demo/src/main/resources/application.yml new file mode 100644 index 0000000..e69de29 diff --git a/kafka/README.md b/kafka/README.md deleted file mode 100644 index f5a3232..0000000 --- a/kafka/README.md +++ /dev/null @@ -1,23 +0,0 @@ -##### kafka配置 - -``` -bootstrap.servers:kafka server的地址 - -acks:写入kafka时,leader负责一个该partion读写,当写入partition时,需要将记录同步到repli节点,all是全部同步节点都返回成功,leader才返回ack。 - -retris:写入失败时,重试次数。当leader节点失效,一个repli节点会替代成为leader节点,此时可能出现写入失败,当retris为0时,produce不会重复。retirs重发,此时repli节点完全成为leader节点,不会产生消息丢失。 - -batch.size:produce积累到一定数据,一次发送。 - -buffer.memory: produce积累数据一次发送,缓存大小达到buffer.memory就发送数据。 - -linger.ms :当设置了缓冲区,消息就不会即时发送,如果消息总不够条数、或者消息不够buffer大小就不发送了吗?当消息超过linger时间,也会发送。 - -key/value serializer:序列化类。 -``` - -### 关于kafka序列化/反序列化 - -https://www.jianshu.com/p/5da86afed228 - -自定义Serializer和Deserializer非常痛苦,还有很多类型不支持,非常脆弱。复杂类型的支持更是一件痛苦的事情,不同版本之间的兼容性问题更是一个极大的挑战。由于Serializer和Deserializer影响到上下游系统,导致牵一发而动全身。自定义序列化&反序列化实现不是能力的体现,而是逗比的体现。所以强烈不建议自定义实现序列化&反序列化,推荐直接使用StringSerializer和StringDeserializer,然后使用json作为标准的数据传输格式。 \ No newline at end of file diff --git a/kafka/kafka.iml b/kafka/kafka.iml deleted file mode 100644 index 85ab1e7..0000000 --- a/kafka/kafka.iml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/Application.java b/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/Application.java deleted file mode 100644 index fd0a87d..0000000 --- a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/Application.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.duanledexianxianxian.demo.kafka; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author duanledexianxianxian - * @date 2019/10/18 23:32 - * @since 1.0.0 - */ -@SpringBootApplication -@Slf4j -public class Application { - - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - - } -} diff --git a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/consumer/TestConsumer.java b/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/consumer/TestConsumer.java deleted file mode 100644 index 0459282..0000000 --- a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/consumer/TestConsumer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.duanledexianxianxian.demo.kafka.consumer; - -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.stereotype.Component; - -/** - * kafka消费者测试 - * - * @author fengyuchenglun - * @version 1.0.0 - */ -@Component -public class TestConsumer { - - /** - * Listen. - * - * @param record the record - * @throws Exception the exception - */ - @KafkaListener(topics = "topic_second") - public void listen(ConsumerRecord record) throws Exception { - System.out.printf("topic = %s, offset = %d, value = %s \n", record.topic(), record.offset(), record.value()); - } -} diff --git a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/controller/KafkaController.java b/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/controller/KafkaController.java deleted file mode 100644 index c6878ba..0000000 --- a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/controller/KafkaController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.duanledexianxianxian.demo.kafka.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author duanledexianxianxian - * @date 2019/10/18 23:50 - * @since 1.0.0 - */ -@RestController -public class KafkaController { - @Autowired - private KafkaTemplate kafkaTemplate; - - @GetMapping("/message/send") - public boolean send(@RequestParam String message){ - kafkaTemplate.send("testTopic",message); - return true; - } -} diff --git a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/listener/AppListener.java b/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/listener/AppListener.java deleted file mode 100644 index fee2774..0000000 --- a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/listener/AppListener.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.duanledexianxianxian.demo.kafka.listener; - -import com.alibaba.fastjson.JSONObject; -import com.duanledexianxianxian.demo.kafka.model.Student; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.concurrent.BasicThreadFactory; -import org.apache.tomcat.util.threads.ThreadPoolExecutor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.Random; -import java.util.concurrent.*; - -/** - * @author duanledexianxianxian - * @date 2019/10/19 0:44 - * @since 1.0.0 - */ -@Component -@Slf4j -public class AppListener implements ApplicationListener { - @Autowired - private KafkaTemplate kafkaTemplate; - - - @Override - public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { - - ThreadFactory namedThreadFactory = new BasicThreadFactory.Builder().namingPattern("producer-kafka-pool-%d").daemon(true).build(); - - ExecutorService pool = new ThreadPoolExecutor(5, 200, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); - int i = 0; - while (true) { - int finalI = i; - pool.execute(() -> { - this.sendData(finalI); - // sleep 5 seconds - }); - - try { - Thread.sleep(new Random().nextInt(6) * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - i++; - } - } - - private void sendData(int i) { - Student student = new Student(); - student.setStudentId(String.valueOf(i)); - student.setName("duanledexianxianxian" + new Random().nextInt(20)); - student.setAge(new Random().nextInt(19) + 6); - student.setSex(Byte.valueOf(String.valueOf((new Random().nextInt(2))))); - log.info("Thread:{} Send Data:{}", Thread.currentThread().getName(), student); - kafkaTemplate.send("topic_first", JSONObject.toJSONString(student)); - } -} diff --git a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/model/Student.java b/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/model/Student.java deleted file mode 100644 index da1a583..0000000 --- a/kafka/src/main/java/com/duanledexianxianxian/demo/kafka/model/Student.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.duanledexianxianxian.demo.kafka.model; - -import lombok.Data; - -import java.io.Serializable; - -/** - * 学生实体类 - * - * @author duanledexianxianxian - * @date 2019/10/19 0:32 - * @since 1.0.0 - */ -@Data -public class Student implements Serializable { - private static final long serialVersionUID = -4572819276161640638L; - /** - * 学生学号 - */ - private String studentId; - /** - * 学生姓名 - */ - private String name; - /** - * 学生年龄 - */ - private Integer age; - /** - * 学生性别 - * 0-男 - * 1-女 - */ - private Byte sex; -} diff --git a/kafka/src/main/resources/application.yml b/kafka/src/main/resources/application.yml deleted file mode 100644 index 9ad2db8..0000000 --- a/kafka/src/main/resources/application.yml +++ /dev/null @@ -1,38 +0,0 @@ -spring: - kafka: - # 指定kafka server的地址,集群配多个,中间,逗号隔开 - bootstrap-servers: 113.105.144.9:9104 - #=============== provider ======================= - producer: - # 写入失败时,重试次数。当leader节点失效,一个repli节点会替代成为leader节点,此时可能出现写入失败, - # 当retris为0时,produce不会重复。retirs重发,此时repli节点完全成为leader节点,不会产生消息丢失。 - retries: 0 - # 每次批量发送消息的数量,produce积累到一定数据,一次发送 - batch-size: 16384 - # produce积累数据一次发送,缓存大小达到buffer.memory就发送数据 - buffer-memory: 33554432 - # 指定消息key和消息体的编解码方式 - key-serializer: org.apache.kafka.common.serialization.StringSerializer - value-serializer: org.apache.kafka.common.serialization.StringSerializer - properties: - #当设置了缓冲区,消息就不会即时发送,如果消息总不够条数、或者消息不够buffer大小就不发送了吗?当消息超过linger时间,也会发送。 - linger.ms: 1 - #procedure要求leader在考虑完成请求之前收到的确认数,用于控制发送记录在服务端的持久化,其值可以为如下: - #acks = 0 如果设置为零,则生产者将不会等待来自服务器的任何确认,该记录将立即添加到套接字缓冲区并视为已发送。在这种情况下,无法保证服务器已收到记录,并且重试配置将不会生效(因为客户端通常不会知道任何故障),为每条记录返回的偏移量始终设置为-1。 - #acks = 1 这意味着leader会将记录写入其本地日志,但无需等待所有副本服务器的完全确认即可做出回应,在这种情况下,如果leader在确认记录后立即失败,但在将数据复制到所有的副本服务器之前,则记录将会丢失。 - #acks = all 这意味着leader将等待完整的同步副本集以确认记录,这保证了只要至少一个同步副本服务器仍然存活,记录就不会丢失,这是最强有力的保证,这相当于acks = -1的设置。 - #可以设置的值为:all, -1, 0, 1 - acks: 1 - - #=============== consumer ======================= - consumer: - group-id: test - # enable.auto.commit:true --> 设置自动提交offset - enable-auto-commit: true - # auto-commit'为true,则消费者偏移自动提交给Kafka的频率(以毫秒为单位),默认值为5000。: - auto-commit-interval: 100ms - # 指定消息key和消息体的编解码方式 - key-deserializer: org.apache.kafka.common.serialization.StringDeserializer - value-deserializer: org.apache.kafka.common.serialization.StringDeserializer - properties: - session.timeout.ms: 15000 \ No newline at end of file diff --git a/menu/pom.xml b/menu/pom.xml deleted file mode 100644 index 6aba2a9..0000000 --- a/menu/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - demo-parent - com.duanledexianxianxian.demo - 1.0-SNAPSHOT - - 4.0.0 - - menu - - - - \ No newline at end of file diff --git a/menu/src/main/java/com/duanledexianxianxian/demo/Application.java b/menu/src/main/java/com/duanledexianxianxian/demo/Application.java deleted file mode 100644 index 47325f1..0000000 --- a/menu/src/main/java/com/duanledexianxianxian/demo/Application.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.duanledexianxianxian.demo; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.Lists; -import org.springframework.beans.BeanUtils; -import org.springframework.util.CollectionUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author duanledexianxianxian - * @date 2020/1/12 23:51 - * @since 1.0.0 - */ -public class Application { - private static String[][] menus = { - {null, "0001", "用户管理", "/urlMgr"}, - {"0001", "00010001", "用户管理-添加用户", "/urlMgr/add"}, - {"0001", "00010002", "用户管理-修改用户", "/urlMgr/edit"}, - {"0001", "00010003", "用户管理-删除用户", "/urlMgr/delete"}, - {"0001", "00010004", "用户管理-查询用户", "/urlMgr/query"}, - {null, "0002", "系统管理", "/systemMgr"}, - {"0002", "00020001", "系统管理-系统管理0001", "/systemMgr/0001"}, - {"00020001", "000200010001", "系统管理-系统管理0001-系统管理0001", "/systemMgr/0001/0001"}, - {"000200010001", "0002000100010001", "系统管理-系统管理0001-系统管理0001-系统管理0001", "/systemMgr/0001/0001/0001"}, - }; - - public static void main(String[] args) { - List menuList = Lists.newArrayList(); - Arrays.asList(menus).forEach(x -> { - Menu menu = new Menu(); - menu.setParentMenuCode(x[0]); - menu.setMenuCode(x[1]); - menu.setMenuTitle(x[2]); - menu.setMenuUrl(x[3]); - menuList.add(menu); - }); - - menuList.forEach(x -> System.out.println(x.toString())); - MenuVO menuVO = getTreeMenuVO(menuList); - ObjectMapper mapper = new ObjectMapper(); - try { - System.out.println(mapper.writeValueAsString(menuVO)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - } - - /** - * 平级列表转成树结构 - * @param menuList - * @return - */ - private static MenuVO getTreeMenuVO(List menuList) { - if (CollectionUtils.isEmpty(menuList)) { - return null; - } - List menuVOList = Lists.newArrayList(); - // 类型转换 一层循环 - menuList.forEach(x -> { - MenuVO menuVO = new MenuVO(); - BeanUtils.copyProperties(x, menuVO); - menuVOList.add(menuVO); - }); - // 转成map 二层循环 一层与二层可以合并 - Map menuMap = menuVOList.stream().collect(Collectors.toMap(MenuVO::getMenuCode, x -> x)); - // 构建根节点 - MenuVO menuVO = new MenuVO(); - menuVO.setParentMenuCode(null); - menuVO.setMenuCode("root"); - menuVO.setMenuTitle("根节点"); - - // 转换逻辑 三层循环 - for (MenuVO menu : menuVOList) { - if (menuMap.containsKey(menu.getParentMenuCode())) { - if (menuMap.get(menu.getParentMenuCode()).getChildren() == null) { - menuMap.get(menu.getParentMenuCode()).setChildren(Lists.newArrayList()); - } - menuMap.get(menu.getParentMenuCode()).getChildren().add(menu); - - } else { - if (menuVO.getChildren() == null) { - menuVO.setChildren(Lists.newArrayList()); - } - menuVO.getChildren().add(menu); - } - } - return menuVO; - } -} diff --git a/menu/src/main/java/com/duanledexianxianxian/demo/Menu.java b/menu/src/main/java/com/duanledexianxianxian/demo/Menu.java deleted file mode 100644 index b5dac88..0000000 --- a/menu/src/main/java/com/duanledexianxianxian/demo/Menu.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.duanledexianxianxian.demo; - -import lombok.Data; - -/** - * 菜单 - * - * @author duanledexianxianxian - * @date 2020/1/12 23:49 - * @since 1.0.0 - */ -@Data -public class Menu { - private String parentMenuCode; - private String menuCode; - private String menuTitle; - private String menuUrl; -} diff --git a/menu/src/main/java/com/duanledexianxianxian/demo/MenuVO.java b/menu/src/main/java/com/duanledexianxianxian/demo/MenuVO.java deleted file mode 100644 index ece311a..0000000 --- a/menu/src/main/java/com/duanledexianxianxian/demo/MenuVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.duanledexianxianxian.demo; - -import lombok.Data; - -import java.util.List; - -/** - * 菜单 - * - * @author duanledexianxianxian - * @date 2020/1/12 23:49 - * @since 1.0.0 - */ -@Data -public class MenuVO { - private String parentMenuCode; - private String menuCode; - private String menuTitle; - private String menuUrl; - private List children; -} diff --git a/pom.xml b/pom.xml index 06796d7..b10a18f 100644 --- a/pom.xml +++ b/pom.xml @@ -9,45 +9,83 @@ pom 1.0-SNAPSHOT - kafka - menu + demo org.springframework.boot spring-boot-starter-parent - 2.1.6.RELEASE + 2.1.3.RELEASE + + + + org.projectlombok + lombok + 1.18.10 + provided + + + com.jayway.jsonpath + json-path + test + + + + com.google.guava + guava + 23.0 + + + + com.baomidou + mybatis-plus-boot-starter + 3.3.1 + + + + com.baomidou + mybatis-plus-generator + 3.3.1 + + + + org.apache.commons + commons-lang3 + 3.9 + + + + - - org.springframework.boot - spring-boot-starter-web - org.projectlombok lombok - 1.18.10 - provided - org.springframework.boot - spring-boot-starter-test - test + org.apache.commons + commons-lang3 - - com.jayway.jsonpath - json-path - test - - com.google.guava guava 23.0 + + org.springframework.boot + spring-boot-starter-test + test + + + org.projectlombok + lombok + + + + 1.8 -- GitLab