diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..224e480
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+# Created by .ignore support plugin (hsz.mobi)
+### Java template
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+.idea/
+*.iml
+target/
+
diff --git a/epdc-common-clienttoken/pom.xml b/epdc-common-clienttoken/pom.xml
new file mode 100644
index 0000000..cf3b50a
--- /dev/null
+++ b/epdc-common-clienttoken/pom.xml
@@ -0,0 +1,133 @@
+
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 4.0.0
+
+ epdc-common-clienttoken
+ jar
+
+ epdc-common-clienttoken
+ http://www.example.com
+ 客户端token
+
+
+
+ com.esua.epdc
+ epdc-commons-tools
+ ${project.version}
+
+
+
+ com.esua.epdc
+ epdc-user-client
+ ${project.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ com.vaadin.external.google
+ android-json
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+ compile
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure-processor
+ compile
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+ provided
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.7.0
+
+
+
+
+ ${project.artifactId}
+
+
+
+ maven-clean-plugin
+
+
+
+ maven-resources-plugin
+
+
+ maven-compiler-plugin
+
+ true
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ ${project.build.sourceEncoding}
+
+
+
+ maven-surefire-plugin
+
+
+ maven-war-plugin
+
+
+ maven-install-plugin
+
+
+ maven-deploy-plugin
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+
+
+
+
+
+
+ ${project.basedir}/src/main/java
+
+
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/Login.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/Login.java
new file mode 100644
index 0000000..9b622b1
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/Login.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2018 人人开源 http://www.renren.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.elink.esua.epdc.common.token.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 登录效验
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2017/9/23 14:30
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Login {
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/LoginUser.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/LoginUser.java
new file mode 100644
index 0000000..e19370c
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/LoginUser.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2018 人人开源 http://www.renren.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.elink.esua.epdc.common.token.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 登录用户信息
+ *
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2017-03-23 20:39
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LoginUser {
+
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/NeedClientToken.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/NeedClientToken.java
new file mode 100644
index 0000000..897a004
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/annotation/NeedClientToken.java
@@ -0,0 +1,13 @@
+package com.elink.esua.epdc.common.token.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)//生命注释保留时长,这里无需反射使用,使用CLASS级别
+@Target(ElementType.METHOD)//生命可以使用此注解的元素级别类型(如类、方法变量等)
+public @interface NeedClientToken {
+
+ boolean value() default true;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/DeptDataScopeDTO.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/DeptDataScopeDTO.java
new file mode 100644
index 0000000..08d4c51
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/DeptDataScopeDTO.java
@@ -0,0 +1,27 @@
+package com.elink.esua.epdc.common.token.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ *
+ * 用户所有角色权限信息
+ *
+ * @Author:liuchuang
+ * @Date:2019/11/19 23:48
+ */
+@Data
+public class DeptDataScopeDTO implements Serializable {
+ private static final long serialVersionUID = -6319876948812713836L;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/TokenDto.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/TokenDto.java
new file mode 100644
index 0000000..b530dc9
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/TokenDto.java
@@ -0,0 +1,60 @@
+package com.elink.esua.epdc.common.token.dto;
+
+import com.elink.esua.epdc.dto.UserTagInfo;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 用户token
+ *
+ * @author rongchao
+ * @Date 18-10-31
+ */
+@Data
+public class TokenDto implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ private String userId;
+
+ /**
+ * 昵称
+ */
+ private String nickname;
+
+ /**
+ * 用户头像
+ */
+ private String faceImg;
+
+ /**
+ * 手机号
+ */
+ private String mobile;
+
+ /**
+ * 真实姓名
+ */
+ private String realName;
+
+ /**
+ * 网格ID
+ */
+ private Long gridId;
+
+ /**
+ * 性别(女性-0,男性-1)
+ */
+ private String sex;
+
+ /**
+ * 用户标签信息列表
+ */
+ private List userTagInfos;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserAuthorizationDTO.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserAuthorizationDTO.java
new file mode 100644
index 0000000..afee518
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserAuthorizationDTO.java
@@ -0,0 +1,48 @@
+package com.elink.esua.epdc.common.token.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ *
+ * 工作端用户授权信息
+ *
+ * @Author:liuchuang
+ * @Date:2019/11/19 20:17
+ */
+@Data
+public class WorkUserAuthorizationDTO implements Serializable {
+ private static final long serialVersionUID = -4230190448906007120L;
+
+ /**
+ * 令牌
+ */
+ private String token;
+
+ /**
+ * 过期时长,单位秒
+ */
+ private Integer expire;
+
+ /**
+ * 部门名称
+ */
+ private String deptName;
+
+ /**
+ * 用户标签key
+ */
+ private String userTagKey;
+
+ /**
+ * 注册状态 0-未注册,1-已注册
+ */
+ private String registerState;
+
+ /**
+ * 用户所有角色权限信息
+ */
+ private List deptDataScopeList;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserLoginDTO.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserLoginDTO.java
new file mode 100644
index 0000000..0e28ca1
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserLoginDTO.java
@@ -0,0 +1,29 @@
+package com.elink.esua.epdc.common.token.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ *
+ * 工作端用户登录信息
+ *
+ * @Author:liuchuang
+ * @Date:2019/11/19 20:19
+ */
+@Data
+public class WorkUserLoginDTO implements Serializable {
+ private static final long serialVersionUID = 1905641243346550379L;
+
+ @NotBlank(message="用户名不能为空")
+ private String username;
+
+ @NotBlank(message="密码不能为空")
+ private String password;
+
+ @NotBlank(message="微信code不能为空")
+ private String wxCode;
+
+ private String openId;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserTokenFormDTO.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserTokenFormDTO.java
new file mode 100644
index 0000000..43ac896
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/dto/WorkUserTokenFormDTO.java
@@ -0,0 +1,25 @@
+package com.elink.esua.epdc.common.token.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ *
+ * 工作端获取token Form DTO
+ *
+ * @Author:liuchuang
+ * @Date:2019/11/19 20:35
+ */
+@Data
+public class WorkUserTokenFormDTO implements Serializable {
+ private static final long serialVersionUID = -2239027109939769097L;
+
+ @NotNull(message = "用户ID不能为空")
+ private Long id;
+
+ @NotBlank(message = "用户名不能为空")
+ private String username;
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/enums/ErrorCode.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/enums/ErrorCode.java
new file mode 100644
index 0000000..7111872
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/enums/ErrorCode.java
@@ -0,0 +1,46 @@
+package com.elink.esua.epdc.common.token.enums;
+
+import com.elink.esua.epdc.common.token.error.IErrorCode;
+
+/**
+ * client token错误码
+ *
+ * @author rongchao
+ * @Date 18-11-24
+ */
+public enum ErrorCode implements IErrorCode {
+
+ SUCCESS(0, "请求成功"),
+
+ ERR10001(10001, "clientToken不合法或者已过期"),
+ ERR10002(10002, "无法获取当前用户的信息,无法生成clientToken。"),
+ ERR10003(10003, "clientToken生成失败,请重试。"),
+ ERR10004(10004, "返回的Object类型不是EsuaResponse,无法添加token!"),
+ ERR10005(10005, "clentToken不能为空"),
+
+ ERR500(500, "Internal Server Error"),
+ ERR501(501, "参数绑定异常"),
+
+ ERR(ErrorCode.COMMON_ERR_CODE, "其他异常");
+
+ private int code;
+
+ private String msg;
+
+ ErrorCode(final int code, final String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public static final int COMMON_ERR_CODE = -1;
+
+ @Override
+ public int getCode() {
+ return code;
+ }
+
+ @Override
+ public String getMsg() {
+ return msg;
+ }
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/error/IErrorCode.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/error/IErrorCode.java
new file mode 100644
index 0000000..3d83f9f
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/error/IErrorCode.java
@@ -0,0 +1,11 @@
+package com.elink.esua.epdc.common.token.error;
+
+/**
+ * @author rongchao
+ * @Date 18-11-20
+ */
+public interface IErrorCode {
+ int getCode();
+
+ String getMsg();
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/property/TokenPropertise.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/property/TokenPropertise.java
new file mode 100644
index 0000000..352c03e
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/property/TokenPropertise.java
@@ -0,0 +1,23 @@
+package com.elink.esua.epdc.common.token.property;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@Component
+@ConfigurationProperties(prefix = "token")
+public class TokenPropertise {
+
+ private long expire = 7200L;
+
+ public long getExpire() {
+ return expire;
+ }
+
+ public void setExpire(long expire) {
+ this.expire = expire;
+ }
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/CpUserDetailRedis.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/CpUserDetailRedis.java
new file mode 100644
index 0000000..178c4a2
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/CpUserDetailRedis.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.common.token.util;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.map.MapUtil;
+import com.elink.esua.epdc.common.token.dto.TokenDto;
+import com.elink.esua.epdc.commons.tools.redis.RedisKeys;
+import com.elink.esua.epdc.commons.tools.redis.RedisUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * CP用户Redis
+ *
+ * @author rongchao
+ * @since 1.0.0
+ */
+@Component
+public class CpUserDetailRedis {
+
+ @Autowired
+ private RedisUtils redisUtils;
+
+ public void set(TokenDto user, long expire) {
+ if (user == null) {
+ return;
+ }
+ String key = RedisKeys.getCpUserKey(user.getUserId());
+ //bean to map
+ Map map = BeanUtil.beanToMap(user, false, true);
+ redisUtils.hMSet(key, map, expire);
+ }
+
+ /**
+ * 缓存用户信息,不同于{@link CpUserDetailRedis#set(TokenDto, long)}之处在于存放进redis时,拼接key的后缀可以自定义
+ *
+ * @param user 用户信息
+ * @param expire 超时时长
+ * @param redisKeySuffix redis的key的后缀
+ * @return void
+ * @author work@yujt.net.cn
+ * @date 2020/1/31 15:13
+ */
+ public void set(TokenDto user, long expire, String redisKeySuffix) {
+ if (user == null) {
+ return;
+ }
+ String key = RedisKeys.getCpUserKey(redisKeySuffix);
+ //bean to map
+ Map map = BeanUtil.beanToMap(user, false, true);
+ redisUtils.hMSet(key, map, expire);
+ }
+
+ /**
+ * 获取token信息
+ *
+ * @param userId
+ * @return
+ */
+ public TokenDto get(String userId) {
+ String key = RedisKeys.getCpUserKey(userId);
+
+ Map map = redisUtils.hGetAll(key);
+ if (MapUtil.isEmpty(map)) {
+ return null;
+ }
+
+ //map to bean
+ TokenDto user = BeanUtil.mapToBean(map, TokenDto.class, true);
+
+ return user;
+ }
+
+ /**
+ * 删除用户信息
+ *
+ * @param userId
+ */
+ public void logout(String userId) {
+ redisUtils.delete(RedisKeys.getCpUserKey(userId));
+ }
+
+ /**
+ * 设置redis时间
+ *
+ * @param userId
+ * @param expire
+ * @author rongchao
+ */
+ public boolean expire(String userId, long expire) {
+ return redisUtils.expire(RedisKeys.getCpUserKey(userId), expire);
+ }
+
+ /**
+ * 查询token剩余时间
+ *
+ * @param userId
+ * @return long
+ * @author yujintao
+ * @date 2019/9/9 14:18
+ */
+ public long getExpire(String userId) {
+ return redisUtils.getExpire(RedisKeys.getCpUserKey(userId));
+ }
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/IdentityNoAnalysisUtil.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/IdentityNoAnalysisUtil.java
new file mode 100644
index 0000000..ca24774
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/IdentityNoAnalysisUtil.java
@@ -0,0 +1,178 @@
+package com.elink.esua.epdc.common.token.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 用户工具类
+ *
+ * @author wanggongfeng
+ * @Date 19-12-16
+ */
+public class IdentityNoAnalysisUtil {
+ /**
+ * 15位身份证号
+ */
+ private static final Integer FIFTEEN_ID_CARD=15;
+ /**
+ * 18位身份证号
+ */
+ private static final Integer EIGHTEEN_ID_CARD=18;
+ private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+
+ /**
+ * 从身份证号码中获取生日
+ * @param idno
+ * @return null表示idno错误,未获取到生日
+ */
+ public static Date getBirthDay(String idno){
+ if(!isValid(idno)){
+ return null;
+ }
+ return toBirthDay(idno.substring(6, 14));
+ }
+
+ /**
+ * 根据身份证号获取性别
+ * @param IDCard
+ * @return
+ */
+ public static String getSex(String IDCard){
+ String sex ="";
+ if (StringUtils.isNotBlank(IDCard)){
+ //15位身份证号
+ if (IDCard.length() == FIFTEEN_ID_CARD){
+ if (Integer.parseInt(IDCard.substring(14, 15)) % 2 == 0) {
+ sex = "女";
+ } else {
+ sex = "男";
+ }
+ //18位身份证号
+ }else if(IDCard.length() == EIGHTEEN_ID_CARD){
+ // 判断性别
+ if (Integer.parseInt(IDCard.substring(16).substring(0, 1)) % 2 == 0) {
+ sex = "女";
+ } else {
+ sex = "男";
+ }
+ }
+ }
+ return sex;
+ }
+
+ /**
+ * 根据身份证号获取年龄
+ * @param IDCard
+ * @return
+ */
+ public static Integer getAge(String IDCard){
+ Integer age = 0;
+ Date date = new Date();
+ if (StringUtils.isNotBlank(IDCard)&& isValid(IDCard)){
+ //15位身份证号
+ if (IDCard.length() == FIFTEEN_ID_CARD){
+ // 身份证上的年份(15位身份证为1980年前的)
+ String uyear = "19" + IDCard.substring(6, 8);
+ // 身份证上的月份
+ String uyue = IDCard.substring(8, 10);
+ // 当前年份
+ String fyear = format.format(date).substring(0, 4);
+ // 当前月份
+ String fyue = format.format(date).substring(5, 7);
+ if (Integer.parseInt(uyue) <= Integer.parseInt(fyue)) {
+ age = Integer.parseInt(fyear) - Integer.parseInt(uyear) + 1;
+ // 当前用户还没过生
+ } else {
+ age = Integer.parseInt(fyear) - Integer.parseInt(uyear);
+ }
+ //18位身份证号
+ }else if(IDCard.length() == EIGHTEEN_ID_CARD){
+ // 身份证上的年份
+ String year = IDCard.substring(6).substring(0, 4);
+ // 身份证上的月份
+ String yue = IDCard.substring(10).substring(0, 2);
+ // 当前年份
+ String fyear = format.format(date).substring(0, 4);
+ // 当前月份
+ String fyue = format.format(date).substring(5, 7);
+ // 当前月份大于用户出身的月份表示已过生日
+ if (Integer.parseInt(yue) <= Integer.parseInt(fyue)) {
+ age = Integer.parseInt(fyear) - Integer.parseInt(year) + 1;
+ // 当前用户还没过生日
+ } else {
+ age = Integer.parseInt(fyear) - Integer.parseInt(year);
+ }
+ }
+ }
+ return age;
+ }
+
+ /**
+ * 身份证验证
+ * @param id 号码内容
+ * @return 是否有效
+ */
+ public static boolean isValid(String id){
+ Boolean validResult = true;
+ //校验长度只能为15或18
+ int len = id.length();
+ if (len != FIFTEEN_ID_CARD && len != EIGHTEEN_ID_CARD){
+ validResult = false;
+ }
+ //校验生日
+ if (!validDate(id)){
+ validResult = false;
+ }
+ return validResult;
+ }
+
+ /**
+ * 校验生日
+ * @param id
+ * @return
+ */
+ private static boolean validDate(String id)
+ {
+ try
+ {
+ String birth = id.length() == 15 ? "19" + id.substring(6, 12) : id.substring(6, 14);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+ Date birthDate = sdf.parse(birth);
+ if (!birth.equals(sdf.format(birthDate))){
+ return false;
+ }
+ }
+ catch (ParseException e)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 转换成日期
+ * @param birthday
+ * @return
+ */
+ private static Date toBirthDay(String birthday){
+ try{
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.YEAR, Integer.parseInt(birthday.substring(0, 4)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(birthday.substring(4, 6)) - 1);//月份从0开始,所以减1
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(birthday.substring(6, 8)));
+ //以下设置意义不大
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+
+ return calendar.getTime();
+ }catch (Exception e){
+ return null;
+ }
+ }
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/TokenUtil.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/TokenUtil.java
new file mode 100644
index 0000000..eebd4f7
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/TokenUtil.java
@@ -0,0 +1,51 @@
+package com.elink.esua.epdc.common.token.util;
+
+import com.elink.esua.epdc.common.token.dto.TokenDto;
+import com.elink.esua.epdc.common.token.property.TokenPropertise;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * token服务类
+ *
+ * @author rongchao
+ * @Date 18-10-31
+ */
+@Component
+public class TokenUtil {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private TokenPropertise tokenPropertise;
+
+ @Autowired
+ private CpUserDetailRedis redisUtils;
+
+ public TokenDto getTokenInfo(String userId) {
+ TokenDto tokenDto = redisUtils.get(userId);
+ return tokenDto;
+ }
+
+ public void expireToken(String userId) {
+ redisUtils.logout(userId);
+ }
+
+ public boolean delayToken(String userId) {
+ return redisUtils.expire(userId, tokenPropertise.getExpire());
+ }
+
+ /**
+ * 获取token过期时间
+ *
+ * @param userId
+ * @return long
+ * @author yujintao
+ * @date 2019/9/9 14:19
+ */
+ public long getExpire(String userId) {
+ return redisUtils.getExpire(userId);
+ }
+}
diff --git a/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/UserUtil.java b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/UserUtil.java
new file mode 100644
index 0000000..2e09b38
--- /dev/null
+++ b/epdc-common-clienttoken/src/main/java/com/elink/esua/epdc/common/token/util/UserUtil.java
@@ -0,0 +1,55 @@
+package com.elink.esua.epdc.common.token.util;
+
+import com.elink.esua.epdc.common.token.dto.TokenDto;
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.utils.WebUtil;
+
+/**
+ * 用户工具类
+ *
+ * @author rongchao
+ * @Date 18-11-20
+ */
+public class UserUtil {
+
+ /**
+ * 获取当前用户信息
+ *
+ * @return
+ */
+ public static TokenDto getCurrentUser() {
+ return (TokenDto) WebUtil.getAttributesFromRequest(Constant.APP_USER_KEY);
+ }
+
+ /**
+ * 获取当前用户信息
+ *
+ * @return com.elink.esua.common.token.dto.UserTokenDto
+ * @author yujintao
+ * @date 2018/12/5 9:24
+ */
+ public static TokenDto getCurrentUserInfo() {
+ TokenDto tokenDto = getCurrentUser();
+ if (tokenDto == null) {
+ return null;
+ }
+ return tokenDto;
+ }
+
+ /**
+ * 获取当前用户ID
+ *
+ * @return
+ */
+ public static String getCurrentUserId() {
+ TokenDto tokenDto = getCurrentUser();
+ if (tokenDto == null) {
+ return null;
+ }
+ return tokenDto.getUserId();
+ }
+
+ public static void setCurrentUser(TokenDto user) {
+ WebUtil.setAttributesFromRequest(Constant.APP_USER_KEY, user);
+ }
+}
diff --git a/epdc-commons-api-version-control/pom.xml b/epdc-commons-api-version-control/pom.xml
new file mode 100644
index 0000000..725dbbd
--- /dev/null
+++ b/epdc-commons-api-version-control/pom.xml
@@ -0,0 +1,52 @@
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 4.0.0
+
+ epdc-commons-api-version-control
+ jar
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ com.vaadin.external.google
+ android-json
+
+
+
+
+
+
+ ${project.artifactId}
+ ${project.basedir}/src/main/java
+
+
+
\ No newline at end of file
diff --git a/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiRequestMappingHandlerMapping.java b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiRequestMappingHandlerMapping.java
new file mode 100644
index 0000000..16cd859
--- /dev/null
+++ b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiRequestMappingHandlerMapping.java
@@ -0,0 +1,42 @@
+package com.elink.esua.epdc.commons.api.version;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.servlet.mvc.condition.RequestCondition;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author rongchao
+ * @Date 18-11-24
+ */
+public class ApiRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
+ @Override
+ protected RequestCondition> getCustomMethodCondition(Method method) {
+ return createCondition(method.getClass());
+ }
+
+ @Override
+ protected RequestCondition> getCustomTypeCondition(Class> handlerType) {
+ return createCondition(handlerType);
+ }
+
+ private static RequestCondition createCondition(Class> clazz) {
+ RequestMapping classRequestMapping = AnnotationUtils.findAnnotation(clazz, RequestMapping.class);
+ if (classRequestMapping == null) {
+ return null;
+ }
+ StringBuilder mappingUrlBuilder = new StringBuilder();
+ if (classRequestMapping.value().length > 0) {
+ mappingUrlBuilder.append(classRequestMapping.value()[0]);
+ }
+ String mappingUrl = mappingUrlBuilder.toString();
+ String mappingUrlVersion = "{version}";
+ if (!mappingUrl.contains(mappingUrlVersion)) {
+ return null;
+ }
+ ApiVersion apiVersion = AnnotationUtils.findAnnotation(clazz, ApiVersion.class);
+ return apiVersion == null ? new ApiVersionCondition(1) : new ApiVersionCondition(apiVersion.value());
+ }
+}
\ No newline at end of file
diff --git a/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersion.java b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersion.java
new file mode 100644
index 0000000..c40e521
--- /dev/null
+++ b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersion.java
@@ -0,0 +1,22 @@
+package com.elink.esua.epdc.commons.api.version;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author rongchao
+ * @Date 18-11-24
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ApiVersion {
+
+ /**
+ * 版本号
+ *
+ * @return
+ */
+ int value();
+}
\ No newline at end of file
diff --git a/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersionCondition.java b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersionCondition.java
new file mode 100644
index 0000000..8dcfc8e
--- /dev/null
+++ b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/ApiVersionCondition.java
@@ -0,0 +1,48 @@
+package com.elink.esua.epdc.commons.api.version;
+
+import org.springframework.web.servlet.mvc.condition.RequestCondition;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author rongchao
+ * @Date 18-11-24
+ */
+public class ApiVersionCondition implements RequestCondition {
+ private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("/v(\\d+).*");
+
+ private int apiVersion;
+
+ ApiVersionCondition(int apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ public int getApiVersion() {
+ return apiVersion;
+ }
+
+
+ @Override
+ public ApiVersionCondition combine(ApiVersionCondition apiVersionCondition) {
+ return new ApiVersionCondition(apiVersionCondition.getApiVersion());
+ }
+
+ @Override
+ public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {
+ Matcher m = VERSION_PREFIX_PATTERN.matcher(httpServletRequest.getRequestURI());
+ if (m.find()) {
+ Integer version = Integer.valueOf(m.group(1));
+ if (version >= this.apiVersion) {
+ return this;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) {
+ return apiVersionCondition.getApiVersion() - this.apiVersion;
+ }
+}
diff --git a/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/config/WebMvcRegistrationsConfig.java b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/config/WebMvcRegistrationsConfig.java
new file mode 100644
index 0000000..0c9e46e
--- /dev/null
+++ b/epdc-commons-api-version-control/src/main/java/com/elink/esua/epdc/commons/api/version/config/WebMvcRegistrationsConfig.java
@@ -0,0 +1,19 @@
+package com.elink.esua.epdc.commons.api.version.config;
+
+import com.elink.esua.epdc.commons.api.version.ApiRequestMappingHandlerMapping;
+import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+/**
+ * @author rongchao
+ * @Date 18-11-24
+ */
+@Configuration
+public class WebMvcRegistrationsConfig implements WebMvcRegistrations {
+
+ @Override
+ public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
+ return new ApiRequestMappingHandlerMapping();
+ }
+}
diff --git a/epdc-commons-dynamic-datasource/pom.xml b/epdc-commons-dynamic-datasource/pom.xml
new file mode 100644
index 0000000..2bd8d4e
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ epdc-commons-dynamic-datasource
+ jar
+
+
+
+ com.esua.epdc
+ epdc-commons-mybatis
+ 1.0.0
+ provided
+
+
+
+ io.seata
+ seata-all
+ provided
+
+
+
+
+ ${project.artifactId}
+
+
+
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/annotation/DataSource.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/annotation/DataSource.java
new file mode 100644
index 0000000..f039460
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/annotation/DataSource.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 多数据源注解
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource {
+ String value() default "";
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/aspect/DataSourceAspect.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/aspect/DataSourceAspect.java
new file mode 100644
index 0000000..024c188
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/aspect/DataSourceAspect.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.aspect;
+
+import com.elink.esua.epdc.commons.dynamic.datasource.annotation.DataSource;
+import com.elink.esua.epdc.commons.dynamic.datasource.config.DynamicDataSource;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+/**
+ * 多数据源,切面处理类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Aspect
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class DataSourceAspect {
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Pointcut("@annotation(com.elink.esua.epdc.commons.dynamic.datasource.annotation.DataSource) " +
+ "|| @within(com.elink.esua.epdc.commons.dynamic.datasource.annotation.DataSource)")
+ public void dataSourcePointCut() {
+
+ }
+
+ @Around("dataSourcePointCut()")
+ public Object around(ProceedingJoinPoint point) throws Throwable {
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ Class targetClass = point.getTarget().getClass();
+ Method method = signature.getMethod();
+
+ DataSource targetDataSource = (DataSource)targetClass.getAnnotation(DataSource.class);
+ DataSource methodDataSource = method.getAnnotation(DataSource.class);
+ if(targetDataSource != null || methodDataSource != null){
+ String value;
+ if(methodDataSource != null){
+ value = methodDataSource.value();
+ }else {
+ value = targetDataSource.value();
+ }
+
+ DynamicDataSource.setDataSource(value);
+ logger.debug("set datasource is {}", value);
+ }
+
+ try {
+ return point.proceed();
+ } finally {
+ DynamicDataSource.clearDataSource();
+ logger.debug("clean datasource");
+ }
+ }
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSource.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSource.java
new file mode 100644
index 0000000..40c9285
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSource.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.config;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * 多数据源
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource {
+ private static ThreadLocal contextHolder = new ThreadLocal<>();
+
+ @Override
+ protected Object determineCurrentLookupKey() {
+ return contextHolder.get();
+ }
+
+ public static void setDataSource(String dataSource) {
+ contextHolder.set(dataSource);
+ }
+
+ public static void clearDataSource() {
+ contextHolder.remove();
+ }
+
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceConfig.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceConfig.java
new file mode 100644
index 0000000..7482711
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceConfig.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.elink.esua.epdc.commons.dynamic.datasource.properties.DataSourceProperties;
+import com.elink.esua.epdc.commons.dynamic.datasource.properties.DynamicDataSourceProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 配置多数据源
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Configuration
+@EnableConfigurationProperties(DynamicDataSourceProperties.class)
+public class DynamicDataSourceConfig {
+ @Autowired
+ private DynamicDataSourceProperties properties;
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.druid")
+ public DataSourceProperties dataSourceProperties() {
+ return new DataSourceProperties();
+ }
+
+ @Bean
+ public DynamicDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) {
+ DynamicDataSource dynamicDataSource = new DynamicDataSource();
+ dynamicDataSource.setTargetDataSources(getDynamicDataSource());
+
+ //默认数据源
+ DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties);
+ dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
+
+ return dynamicDataSource;
+ }
+
+ private Map getDynamicDataSource(){
+ Map dataSourcePropertiesMap = properties.getDatasource();
+ Map targetDataSources = new HashMap<>(dataSourcePropertiesMap.size());
+ dataSourcePropertiesMap.forEach((k, v) -> {
+ DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v);
+ targetDataSources.put(k, druidDataSource);
+ });
+
+ return targetDataSources;
+ }
+
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceFactory.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceFactory.java
new file mode 100644
index 0000000..4983304
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/config/DynamicDataSourceFactory.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.elink.esua.epdc.commons.dynamic.datasource.properties.DataSourceProperties;
+import com.elink.esua.epdc.commons.dynamic.datasource.properties.DataSourceProperties;
+
+import java.sql.SQLException;
+
+/**
+ * DruidDataSource
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class DynamicDataSourceFactory {
+
+ public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) {
+ DruidDataSource druidDataSource = new DruidDataSource();
+ druidDataSource.setDriverClassName(properties.getDriverClassName());
+ druidDataSource.setUrl(properties.getUrl());
+ druidDataSource.setUsername(properties.getUsername());
+ druidDataSource.setPassword(properties.getPassword());
+
+ druidDataSource.setInitialSize(properties.getInitialSize());
+ druidDataSource.setMaxActive(properties.getMaxActive());
+ druidDataSource.setMinIdle(properties.getMinIdle());
+ druidDataSource.setMaxWait(properties.getMaxWait());
+ druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
+ druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
+ druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
+ druidDataSource.setValidationQuery(properties.getValidationQuery());
+ druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
+ druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
+ druidDataSource.setTestOnReturn(properties.isTestOnReturn());
+ druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
+ druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
+ druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements());
+
+ try {
+ druidDataSource.setFilters(properties.getFilters());
+ druidDataSource.init();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return druidDataSource;
+ }
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DataSourceProperties.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DataSourceProperties.java
new file mode 100644
index 0000000..b870e66
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DataSourceProperties.java
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.properties;
+
+/**
+ * 多数据源属性
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class DataSourceProperties {
+ private String driverClassName;
+ private String url;
+ private String username;
+ private String password;
+
+ /**
+ * Druid默认参数
+ */
+ private int initialSize = 2;
+ private int maxActive = 10;
+ private int minIdle = -1;
+ private long maxWait = 60 * 1000L;
+ private long timeBetweenEvictionRunsMillis = 60 * 1000L;
+ private long minEvictableIdleTimeMillis = 1000L * 60L * 30L;
+ private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
+ private String validationQuery = "select 1";
+ private int validationQueryTimeout = -1;
+ private boolean testOnBorrow = false;
+ private boolean testOnReturn = false;
+ private boolean testWhileIdle = true;
+ private boolean poolPreparedStatements = false;
+ private int maxOpenPreparedStatements = -1;
+ private boolean sharePreparedStatements = false;
+ private String filters = "stat,wall";
+
+ public String getDriverClassName() {
+ return driverClassName;
+ }
+
+ public void setDriverClassName(String driverClassName) {
+ this.driverClassName = driverClassName;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public int getInitialSize() {
+ return initialSize;
+ }
+
+ public void setInitialSize(int initialSize) {
+ this.initialSize = initialSize;
+ }
+
+ public int getMaxActive() {
+ return maxActive;
+ }
+
+ public void setMaxActive(int maxActive) {
+ this.maxActive = maxActive;
+ }
+
+ public int getMinIdle() {
+ return minIdle;
+ }
+
+ public void setMinIdle(int minIdle) {
+ this.minIdle = minIdle;
+ }
+
+ public long getMaxWait() {
+ return maxWait;
+ }
+
+ public void setMaxWait(long maxWait) {
+ this.maxWait = maxWait;
+ }
+
+ public long getTimeBetweenEvictionRunsMillis() {
+ return timeBetweenEvictionRunsMillis;
+ }
+
+ public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
+ this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ }
+
+ public long getMinEvictableIdleTimeMillis() {
+ return minEvictableIdleTimeMillis;
+ }
+
+ public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
+ this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ }
+
+ public long getMaxEvictableIdleTimeMillis() {
+ return maxEvictableIdleTimeMillis;
+ }
+
+ public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
+ this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
+ }
+
+ public String getValidationQuery() {
+ return validationQuery;
+ }
+
+ public void setValidationQuery(String validationQuery) {
+ this.validationQuery = validationQuery;
+ }
+
+ public int getValidationQueryTimeout() {
+ return validationQueryTimeout;
+ }
+
+ public void setValidationQueryTimeout(int validationQueryTimeout) {
+ this.validationQueryTimeout = validationQueryTimeout;
+ }
+
+ public boolean isTestOnBorrow() {
+ return testOnBorrow;
+ }
+
+ public void setTestOnBorrow(boolean testOnBorrow) {
+ this.testOnBorrow = testOnBorrow;
+ }
+
+ public boolean isTestOnReturn() {
+ return testOnReturn;
+ }
+
+ public void setTestOnReturn(boolean testOnReturn) {
+ this.testOnReturn = testOnReturn;
+ }
+
+ public boolean isTestWhileIdle() {
+ return testWhileIdle;
+ }
+
+ public void setTestWhileIdle(boolean testWhileIdle) {
+ this.testWhileIdle = testWhileIdle;
+ }
+
+ public boolean isPoolPreparedStatements() {
+ return poolPreparedStatements;
+ }
+
+ public void setPoolPreparedStatements(boolean poolPreparedStatements) {
+ this.poolPreparedStatements = poolPreparedStatements;
+ }
+
+ public int getMaxOpenPreparedStatements() {
+ return maxOpenPreparedStatements;
+ }
+
+ public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {
+ this.maxOpenPreparedStatements = maxOpenPreparedStatements;
+ }
+
+ public boolean isSharePreparedStatements() {
+ return sharePreparedStatements;
+ }
+
+ public void setSharePreparedStatements(boolean sharePreparedStatements) {
+ this.sharePreparedStatements = sharePreparedStatements;
+ }
+
+ public String getFilters() {
+ return filters;
+ }
+
+ public void setFilters(String filters) {
+ this.filters = filters;
+ }
+}
diff --git a/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java
new file mode 100644
index 0000000..e3b5bc6
--- /dev/null
+++ b/epdc-commons-dynamic-datasource/src/main/java/com/elink/esua/epdc/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.dynamic.datasource.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 多数据源属性
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@ConfigurationProperties(prefix = "dynamic")
+public class DynamicDataSourceProperties {
+ private Map datasource = new LinkedHashMap<>();
+
+ public Map getDatasource() {
+ return datasource;
+ }
+
+ public void setDatasource(Map datasource) {
+ this.datasource = datasource;
+ }
+}
diff --git a/epdc-commons-mybatis/pom.xml b/epdc-commons-mybatis/pom.xml
new file mode 100644
index 0000000..9437162
--- /dev/null
+++ b/epdc-commons-mybatis/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ epdc-commons-mybatis
+ jar
+
+
+ 3.1.2
+ 8.0.17
+ 1.1.18
+ 4.0
+ 11.2.0.3
+
+
+
+
+ com.esua.epdc
+ epdc-commons-tools
+ 1.0.0
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatisplus.version}
+
+
+ com.baomidou
+ mybatis-plus-generator
+
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ ${druid.version}
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.version}
+
+
+
+ com.oracle
+ ojdbc6
+ ${oracle.version}
+
+
+
+ com.microsoft.sqlserver
+ sqljdbc4
+ ${sqlserver.version}
+
+
+
+ org.postgresql
+ postgresql
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-seata
+
+
+ io.seata
+ seata-all
+
+
+
+
+
+ ${project.artifactId}
+
+
+
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/annotation/DataFilter.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/annotation/DataFilter.java
new file mode 100644
index 0000000..319cc1f
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/annotation/DataFilter.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 数据过滤注解
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataFilter {
+ /**
+ * 表的别名
+ */
+ String tableAlias() default "";
+
+ /**
+ * 查询条件前缀,可选值有:[where、and]
+ */
+ String prefix() default "";
+
+ /**
+ * 用户ID
+ */
+ String userId() default "creator";
+
+ /**
+ * 部门ID
+ */
+ String deptId() default "dept_id";
+
+ /**
+ * 是否拼接用户ID
+ */
+ boolean isPendingCreator() default true;
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/aspect/DataFilterAspect.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/aspect/DataFilterAspect.java
new file mode 100644
index 0000000..6a1f7e6
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/aspect/DataFilterAspect.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.aspect;
+
+import cn.hutool.core.collection.CollUtil;
+import com.elink.esua.epdc.commons.mybatis.annotation.DataFilter;
+import com.elink.esua.epdc.commons.mybatis.entity.DataScope;
+import com.elink.esua.epdc.commons.mybatis.annotation.DataFilter;
+import com.elink.esua.epdc.commons.mybatis.entity.DataScope;
+import com.elink.esua.epdc.commons.tools.enums.SuperAdminEnum;
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.exception.ErrorCode;
+import com.elink.esua.epdc.commons.tools.exception.RenException;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 数据过滤,切面处理类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Aspect
+@Component
+public class DataFilterAspect {
+ @Pointcut("@annotation(com.elink.esua.epdc.commons.mybatis.annotation.DataFilter)")
+ public void dataFilterCut() {
+
+ }
+
+ @Before("dataFilterCut()")
+ public void dataFilter(JoinPoint point) {
+ Object params = point.getArgs()[0];
+ if(params != null && params instanceof Map){
+ UserDetail user = SecurityUser.getUser();
+
+ //如果不是超级管理员,则进行数据过滤
+ if(user.getSuperAdmin() == SuperAdminEnum.NO.value()){
+ Map map = (Map)params;
+ String sqlFilter = getSqlFilter(user, point);
+ map.put(Constant.SQL_FILTER, new DataScope(sqlFilter));
+ }
+
+ return ;
+ }
+
+ throw new RenException(ErrorCode.DATA_SCOPE_PARAMS_ERROR);
+ }
+
+ /**
+ * 获取数据过滤的SQL
+ */
+ private String getSqlFilter(UserDetail user, JoinPoint point){
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ DataFilter dataFilter = signature.getMethod().getAnnotation(DataFilter.class);
+ //获取表的别名
+ String tableAlias = dataFilter.tableAlias();
+ if(StringUtils.isNotBlank(tableAlias)){
+ tableAlias += ".";
+ }
+
+ StringBuilder sqlFilter = new StringBuilder();
+
+ //查询条件前缀
+ String prefix = dataFilter.prefix();
+ if(StringUtils.isNotBlank(prefix)){
+ sqlFilter.append(" ").append(prefix);
+ }
+
+ sqlFilter.append(" (");
+
+ //部门ID列表
+ List deptIdList = user.getDeptIdList();
+ if(CollUtil.isNotEmpty(deptIdList)){
+ sqlFilter.append(tableAlias).append(dataFilter.deptId());
+
+ sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");
+ }
+
+ //查询本人数据
+ if (dataFilter.isPendingCreator()) {
+ if(CollUtil.isNotEmpty(deptIdList)){
+ sqlFilter.append(" or ");
+ }
+ sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId());
+ }
+ sqlFilter.append(")");
+
+ return sqlFilter.toString();
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/DataSourceConfig.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/DataSourceConfig.java
new file mode 100644
index 0000000..1f1b5a3
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/DataSourceConfig.java
@@ -0,0 +1,166 @@
+package com.elink.esua.epdc.commons.mybatis.config;
+
+import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
+import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import io.seata.rm.datasource.DataSourceProxy;
+import org.apache.ibatis.mapping.DatabaseIdProvider;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import javax.sql.DataSource;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * seata分布式事务数据源
+ *
+ * @author rongchao
+ * @Date 19-8-21
+ */
+@Configuration
+@EnableConfigurationProperties({MybatisPlusProperties.class})
+public class DataSourceConfig implements InitializingBean {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ private final MybatisPlusProperties properties;
+ private final Interceptor[] interceptors;
+ private final ResourceLoader resourceLoader;
+ private final DatabaseIdProvider databaseIdProvider;
+ private final List configurationCustomizers;
+ private final List mybatisPlusPropertiesCustomizers;
+ private final ApplicationContext applicationContext;
+
+ public DataSourceConfig(MybatisPlusProperties properties, ObjectProvider interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider> configurationCustomizersProvider, ObjectProvider> mybatisPlusPropertiesCustomizerProvider, ApplicationContext applicationContext) {
+ this.properties = properties;
+ this.interceptors = (Interceptor[]) interceptorsProvider.getIfAvailable();
+ this.resourceLoader = resourceLoader;
+ this.databaseIdProvider = (DatabaseIdProvider) databaseIdProvider.getIfAvailable();
+ this.configurationCustomizers = (List) configurationCustomizersProvider.getIfAvailable();
+ this.mybatisPlusPropertiesCustomizers = (List) mybatisPlusPropertiesCustomizerProvider.getIfAvailable();
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ if (!CollectionUtils.isEmpty(this.mybatisPlusPropertiesCustomizers)) {
+ this.mybatisPlusPropertiesCustomizers.forEach((i) -> {
+ i.customize(this.properties);
+ });
+ }
+
+ this.checkConfigFileExists();
+ }
+
+ private void checkConfigFileExists() {
+ if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
+ Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
+ Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
+ }
+
+ }
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+ DataSourceProxy dataSourceProxy = new DataSourceProxy(dataSource);
+ MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
+ factory.setDataSource(dataSourceProxy);
+ factory.setVfs(SpringBootVFS.class);
+ if (StringUtils.hasText(this.properties.getConfigLocation())) {
+ factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
+ }
+
+ this.applyConfiguration(factory);
+ if (this.properties.getConfigurationProperties() != null) {
+ factory.setConfigurationProperties(this.properties.getConfigurationProperties());
+ }
+
+ if (!ObjectUtils.isEmpty(this.interceptors)) {
+ factory.setPlugins(this.interceptors);
+ }
+
+ if (this.databaseIdProvider != null) {
+ factory.setDatabaseIdProvider(this.databaseIdProvider);
+ }
+
+ if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
+ factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
+ }
+
+ if (this.properties.getTypeAliasesSuperType() != null) {
+ factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
+ }
+
+ if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
+ factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
+ }
+
+ if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
+ factory.setMapperLocations(this.properties.resolveMapperLocations());
+ }
+
+ if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
+ factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
+ }
+
+ GlobalConfig globalConfig = this.properties.getGlobalConfig();
+ if (this.applicationContext.getBeanNamesForType(MetaObjectHandler.class, false, false).length > 0) {
+ MetaObjectHandler metaObjectHandler = (MetaObjectHandler) this.applicationContext.getBean(MetaObjectHandler.class);
+ globalConfig.setMetaObjectHandler(metaObjectHandler);
+ }
+
+ if (this.applicationContext.getBeanNamesForType(IKeyGenerator.class, false, false).length > 0) {
+ IKeyGenerator keyGenerator = (IKeyGenerator) this.applicationContext.getBean(IKeyGenerator.class);
+ globalConfig.getDbConfig().setKeyGenerator(keyGenerator);
+ }
+
+ if (this.applicationContext.getBeanNamesForType(ISqlInjector.class, false, false).length > 0) {
+ ISqlInjector iSqlInjector = (ISqlInjector) this.applicationContext.getBean(ISqlInjector.class);
+ globalConfig.setSqlInjector(iSqlInjector);
+ }
+
+ factory.setGlobalConfig(globalConfig);
+ return factory.getObject();
+ }
+
+ private void applyConfiguration(MybatisSqlSessionFactoryBean factory) {
+ MybatisConfiguration configuration = this.properties.getConfiguration();
+ if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
+ configuration = new MybatisConfiguration();
+ }
+
+ if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
+ Iterator var3 = this.configurationCustomizers.iterator();
+
+ while (var3.hasNext()) {
+ ConfigurationCustomizer customizer = (ConfigurationCustomizer) var3.next();
+ customizer.customize(configuration);
+ }
+ }
+
+ factory.setConfiguration(configuration);
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/MybatisPlusConfig.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..1bf1429
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/config/MybatisPlusConfig.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.config;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.elink.esua.epdc.commons.mybatis.interceptor.DataFilterInterceptor;
+import com.elink.esua.epdc.commons.mybatis.interceptor.DataFilterInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+
+/**
+ * mybatis-plus配置
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Configuration
+public class MybatisPlusConfig {
+
+ /**
+ * 配置数据权限
+ */
+ @Bean
+ @Order(1)
+ public DataFilterInterceptor dataFilterInterceptor() {
+ return new DataFilterInterceptor();
+ }
+
+ /**
+ * 配置分页
+ */
+ @Bean
+ @Order(0)
+ public PaginationInterceptor paginationInterceptor() {
+ return new PaginationInterceptor();
+ }
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/dao/BaseDao.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/dao/BaseDao.java
new file mode 100644
index 0000000..f2e20b3
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/dao/BaseDao.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * 基础Dao
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface BaseDao extends BaseMapper {
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEntity.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEntity.java
new file mode 100644
index 0000000..dc15053
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEntity.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 基础实体类,所有实体都需要继承
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public abstract class BaseEntity implements Serializable {
+ /**
+ * id
+ */
+ @TableId(type = IdType.ID_WORKER)
+ private Long id;
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Long creator;
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createDate;
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEpdcEntity.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEpdcEntity.java
new file mode 100644
index 0000000..285bc79
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/BaseEpdcEntity.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 基础实体类,所有实体都需要继承
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public abstract class BaseEpdcEntity implements Serializable {
+ /**
+ * id
+ */
+ @TableId(type = IdType.UUID)
+ private String id;
+
+ /**
+ * 乐观锁
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Integer revision;
+
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createdBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date createdTime;
+
+ /**
+ * 修改者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updatedBy;
+
+ /**
+ * 修改时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date updatedTime;
+
+ /**
+ * 是否已删除(0-未删除,1-已删除)
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @TableLogic
+ private String delFlag;
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DataScope.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DataScope.java
new file mode 100644
index 0000000..3b57b47
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DataScope.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.entity;
+
+/**
+ * 数据范围
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class DataScope {
+ private String sqlFilter;
+
+ public DataScope(String sqlFilter) {
+ this.sqlFilter = sqlFilter;
+ }
+
+ public String getSqlFilter() {
+ return sqlFilter;
+ }
+
+ public void setSqlFilter(String sqlFilter) {
+ this.sqlFilter = sqlFilter;
+ }
+
+ @Override
+ public String toString() {
+ return this.sqlFilter;
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DeptScope.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DeptScope.java
new file mode 100644
index 0000000..cc66e73
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/entity/DeptScope.java
@@ -0,0 +1,36 @@
+package com.elink.esua.epdc.commons.mybatis.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 部门冗余字段基类
+ *
+ * @author rongchao
+ * @Date 19-12-18
+ */
+@Data
+public abstract class DeptScope extends BaseEpdcEntity implements Serializable {
+
+ /***
+ *所有部门名称
+ */
+ private String allDeptNames;
+
+ /***
+ *所有部门ID
+ */
+ private String allDeptIds;
+
+ /***
+ *父所有部门
+ */
+ private String parentDeptNames;
+
+ /***
+ *父所有部门
+ */
+ private String parentDeptIds;
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/DelFlagEnum.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/DelFlagEnum.java
new file mode 100644
index 0000000..7ab4ac9
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/DelFlagEnum.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.enums;
+
+/**
+ * 删除标识枚举类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum DelFlagEnum {
+ NORMAL(0),
+ DEL(1);
+
+ private int value;
+
+ DelFlagEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/EpdcDelFlagEnum.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/EpdcDelFlagEnum.java
new file mode 100644
index 0000000..e88c272
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/enums/EpdcDelFlagEnum.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.enums;
+
+/**
+ * 删除标识枚举
+ *
+ * @author yujintao
+ * @date 2019/8/19 10:37
+ */
+public enum EpdcDelFlagEnum {
+ /**
+ * 未删
+ */
+ NORMAL("0"),
+ /**
+ * 已删
+ */
+ DEL("1");
+
+ private String value;
+
+ EpdcDelFlagEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/handler/FieldMetaObjectHandler.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/handler/FieldMetaObjectHandler.java
new file mode 100644
index 0000000..1a6fbc1
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/handler/FieldMetaObjectHandler.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.handler;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.elink.esua.epdc.commons.mybatis.entity.BaseEntity;
+import com.elink.esua.epdc.commons.mybatis.entity.BaseEpdcEntity;
+import com.elink.esua.epdc.commons.mybatis.enums.DelFlagEnum;
+import com.elink.esua.epdc.commons.mybatis.enums.EpdcDelFlagEnum;
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.constant.FieldConstant;
+import com.elink.esua.epdc.commons.tools.constant.NumConstant;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * 公共字段,自动填充值
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class FieldMetaObjectHandler implements MetaObjectHandler {
+ private final static String CREATE_DATE = "createDate";
+ private final static String CREATOR = "creator";
+ private final static String UPDATE_DATE = "updateDate";
+ private final static String UPDATER = "updater";
+ private final static String DEPT_ID = "deptId";
+
+ @Override
+ public void insertFill(MetaObject metaObject) {
+ UserDetail user = SecurityUser.getUser();
+ Date date = new Date();
+ if (metaObject.getOriginalObject() instanceof BaseEpdcEntity) {
+ String userId = user == null ? Constant.APP_USER_FLAG : String.valueOf(user.getId());
+ Long deptId = user == null ? null : user.getDeptId();
+ setFieldValByName(FieldConstant.CREATED_TIME_HUMP, date, metaObject);
+ setFieldValByName(FieldConstant.CREATED_BY_HUMP, userId, metaObject);
+ setFieldValByName(FieldConstant.UPDATED_TIME_HUMP, date, metaObject);
+ setFieldValByName(FieldConstant.UPDATED_BY_HUMP, userId, metaObject);
+ setFieldValByName(FieldConstant.REVISION_HUMP, NumConstant.ZERO, metaObject);
+ //删除标识
+ setFieldValByName(FieldConstant.DEL_FLAG_HUMP, EpdcDelFlagEnum.NORMAL.value(), metaObject);
+ // 数据权限标志
+ setInsertFieldValByName(DEPT_ID, deptId, metaObject);
+ } else {
+ if (user == null) {
+ return;
+ }
+ //创建者
+ setFieldValByName(CREATOR, user.getId(), metaObject);
+ //创建时间
+ setFieldValByName(CREATE_DATE, date, metaObject);
+ //创建者所属部门
+ setInsertFieldValByName(DEPT_ID, user.getDeptId(), metaObject);
+ //更新者
+ setFieldValByName(UPDATER, user.getId(), metaObject);
+ //更新时间
+ setFieldValByName(UPDATE_DATE, date, metaObject);
+ //删除标识
+ setFieldValByName(FieldConstant.DEL_FLAG_HUMP, DelFlagEnum.NORMAL.value(), metaObject);
+ }
+ }
+
+ @Override
+ public void updateFill(MetaObject metaObject) {
+
+ Object originalObject = metaObject.getOriginalObject();
+ Long id = SecurityUser.getUserId();
+
+ boolean fillEntity = false;
+ boolean fillEsuaEntity = false;
+ if (originalObject instanceof BaseEntity) {
+ fillEntity = true;
+ } else if (originalObject instanceof BaseEpdcEntity) {
+ fillEsuaEntity = true;
+ } else {
+ if (metaObject.hasGetter(Constants.ENTITY)) {
+ Object et = metaObject.getValue(Constants.ENTITY);
+ if (et instanceof BaseEpdcEntity) {
+ fillEsuaEntity = true;
+ } else if (et instanceof BaseEntity) {
+ fillEntity = true;
+ }
+ }
+ }
+ if (fillEntity) {
+ id = null == id ? NumConstant.ZERO_L : id;
+ //更新者
+ setFieldValByName(UPDATER, id, metaObject);
+ //更新时间
+ setFieldValByName(UPDATE_DATE, new Date(), metaObject);
+ } else if (fillEsuaEntity) {
+ String userId = null == id ? Constant.APP_USER_FLAG : String.valueOf(id);
+ setFieldValByName(FieldConstant.UPDATED_BY_HUMP, userId, metaObject);
+ setFieldValByName(FieldConstant.UPDATED_TIME_HUMP, new Date(), metaObject);
+ }
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/interceptor/DataFilterInterceptor.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/interceptor/DataFilterInterceptor.java
new file mode 100644
index 0000000..eca7922
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/interceptor/DataFilterInterceptor.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.interceptor;
+
+import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
+import com.elink.esua.epdc.commons.mybatis.entity.DataScope;
+import com.elink.esua.epdc.commons.mybatis.entity.DataScope;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+
+import java.sql.Connection;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * 数据过滤
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
+public class DataFilterInterceptor extends AbstractSqlParserHandler implements Interceptor {
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
+ MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
+
+ // SQL解析
+ this.sqlParser(metaObject);
+
+ // 先判断是不是SELECT操作
+ MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
+ if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
+ return invocation.proceed();
+ }
+
+ // 针对定义了rowBounds,做为mapper接口方法的参数
+ BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
+ String originalSql = boundSql.getSql();
+ Object paramObj = boundSql.getParameterObject();
+
+ // 判断参数里是否有DataScope对象
+ DataScope scope = null;
+ if (paramObj instanceof DataScope) {
+ scope = (DataScope) paramObj;
+ } else if (paramObj instanceof Map) {
+ for (Object arg : ((Map) paramObj).values()) {
+ if (arg instanceof DataScope) {
+ scope = (DataScope) arg;
+ break;
+ }
+ }
+ }
+
+ // 不用数据过滤
+ if (scope == null) {
+ return invocation.proceed();
+ }
+
+ // 拼接新SQL
+ String orderBy = "ORDER BY";
+ String groupBy = "GROUP BY";
+ if (originalSql.indexOf(groupBy) > -1) {
+ originalSql = originalSql.replace(groupBy, scope.getSqlFilter() + groupBy);
+ } else if (originalSql.indexOf(orderBy) > -1) {
+ originalSql = originalSql.replace(orderBy, scope.getSqlFilter() + orderBy);
+ } else {
+ originalSql = originalSql + scope.getSqlFilter();
+ }
+
+ // 重写SQL
+ metaObject.setValue("delegate.boundSql.sql", originalSql);
+ return invocation.proceed();
+ }
+
+ @Override
+ public Object plugin(Object target) {
+ if (target instanceof StatementHandler) {
+ return Plugin.wrap(target, this);
+ }
+ return target;
+ }
+
+ @Override
+ public void setProperties(Properties properties) {
+
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/BaseService.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/BaseService.java
new file mode 100644
index 0000000..1ff5a86
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/BaseService.java
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.service;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * 基础服务接口,所有Service接口都要继承
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface BaseService {
+
+ /**
+ * 逻辑删除
+ * @param ids ids
+ * @param entity 实体
+ *
+ * @return boolean
+ */
+ boolean logicDelete(Long[] ids, Class entity);
+
+ /**
+ *
+ * 插入一条记录(选择字段,策略插入)
+ *
+ *
+ * @param entity 实体对象
+ */
+ boolean insert(T entity);
+
+ /**
+ *
+ * 插入(批量),该方法不支持 Oracle、SQL Server
+ *
+ *
+ * @param entityList 实体对象集合
+ */
+ boolean insertBatch(Collection entityList);
+
+ /**
+ *
+ * 插入(批量)
+ *
+ *
+ * @param entityList 实体对象集合
+ * @param batchSize 插入批次数量
+ */
+ boolean insertBatch(Collection entityList, int batchSize);
+
+ /**
+ *
+ * 根据 ID 选择修改
+ *
+ *
+ * @param entity 实体对象
+ */
+ boolean updateById(T entity);
+
+ /**
+ *
+ * 根据 whereEntity 条件,更新记录
+ *
+ *
+ * @param entity 实体对象
+ * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
+ */
+ boolean update(T entity, Wrapper updateWrapper);
+
+ /**
+ *
+ * 根据ID 批量更新
+ *
+ *
+ * @param entityList 实体对象集合
+ */
+ boolean updateBatchById(Collection entityList);
+
+ /**
+ *
+ * 根据ID 批量更新
+ *
+ *
+ * @param entityList 实体对象集合
+ * @param batchSize 更新批次数量
+ */
+ boolean updateBatchById(Collection entityList, int batchSize);
+
+ /**
+ *
+ * 根据 ID 查询
+ *
+ *
+ * @param id 主键ID
+ */
+ T selectById(Serializable id);
+
+ /**
+ *
+ * 根据 ID 删除
+ *
+ *
+ * @param id 主键ID
+ */
+ boolean deleteById(Serializable id);
+
+ /**
+ *
+ * 删除(根据ID 批量删除)
+ *
+ *
+ * @param idList 主键ID列表
+ */
+ boolean deleteBatchIds(Collection extends Serializable> idList);
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/CrudService.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/CrudService.java
new file mode 100644
index 0000000..da39665
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/CrudService.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.service;
+
+import com.elink.esua.epdc.commons.tools.page.PageData;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CRUD基础服务接口
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public interface CrudService extends BaseService {
+
+ PageData page(Map params);
+
+ List list(Map params);
+
+ D get(Long id);
+
+ void save(D dto);
+
+ void update(D dto);
+
+ void delete(Long[] ids);
+
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/BaseServiceImpl.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/BaseServiceImpl.java
new file mode 100644
index 0000000..bc7f6b4
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/BaseServiceImpl.java
@@ -0,0 +1,301 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
+import com.elink.esua.epdc.commons.mybatis.service.BaseService;
+import com.elink.esua.epdc.commons.mybatis.utils.EntityUtils;
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.page.PageData;
+import com.elink.esua.epdc.commons.tools.utils.ConvertUtils;
+import org.apache.ibatis.binding.MapperMethod;
+import org.apache.ibatis.session.SqlSession;
+import org.mybatis.spring.SqlSessionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 基础服务类,所有Service都要继承
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public abstract class BaseServiceImpl, T> implements BaseService {
+
+ @Autowired
+ protected M baseDao;
+
+ /**
+ * 获取分页对象
+ *
+ * @param params 分页查询参数
+ * @param defaultOrderField 默认排序字段
+ * @param isAsc 排序方式
+ */
+ protected IPage getPage(Map params, String defaultOrderField, boolean isAsc) {
+ Page page = initPage(params);
+
+ //默认排序
+ if (StringUtils.isNotEmpty(defaultOrderField)) {
+ if (isAsc) {
+ page.addOrder(OrderItem.asc(defaultOrderField));
+ } else {
+ page.addOrder(OrderItem.desc(defaultOrderField));
+ }
+ }
+ return page;
+ }
+
+ /**
+ * 获取分页对象
+ *
+ * @param params 分页查询参数
+ * @return com.baomidou.mybatisplus.core.metadata.IPage
+ * @author yujintao
+ * @date 2019/6/12 10:57
+ */
+ protected IPage getPage(Map params) {
+ Page page = initPage(params);
+ return page;
+ }
+
+ /**
+ * 初始化分页对象
+ *
+ * @param params 分页查询参数
+ * @return com.baomidou.mybatisplus.core.metadata.IPage
+ * @author yujintao
+ * @date 2019/6/12 10:57
+ */
+ private Page initPage(Map params) {
+ //分页参数
+ long curPage = 1;
+ long limit = 10;
+
+ if (params.get(Constant.PAGE) != null) {
+ curPage = Long.parseLong((String) params.get(Constant.PAGE));
+ }
+ if (params.get(Constant.LIMIT) != null) {
+ limit = Long.parseLong((String) params.get(Constant.LIMIT));
+ }
+
+ //分页对象
+ Page page = new Page<>(curPage, limit);
+
+ //分页参数
+ params.put(Constant.PAGE, page);
+
+ //排序字段
+ String orderField = (String) params.get(Constant.ORDER_FIELD);
+ String order = (String) params.get(Constant.ORDER);
+
+ //前端字段排序
+ if (StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)) {
+ if (Constant.ASC.equalsIgnoreCase(order)) {
+ return page.addOrder(OrderItem.asc(orderField));
+ } else {
+ return page.addOrder(OrderItem.desc(orderField));
+ }
+ }
+
+ return page;
+ }
+
+ protected PageData getPageData(List> list, long total, Class target) {
+ List targetList = ConvertUtils.sourceToTarget(list, target);
+
+ return new PageData<>(targetList, total);
+ }
+
+ protected PageData getPageData(IPage page, Class target) {
+ return getPageData(page.getRecords(), page.getTotal(), target);
+ }
+
+ protected Map paramsToLike(Map params, String... likes) {
+ for (String like : likes) {
+ String val = (String) params.get(like);
+ if (StringUtils.isNotEmpty(val)) {
+ params.put(like, "%" + val + "%");
+ } else {
+ params.put(like, null);
+ }
+ }
+ return params;
+ }
+
+ /**
+ * 逻辑删除
+ *
+ * @param ids ids
+ * @param entity 实体
+ * @return boolean
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean logicDelete(Long[] ids, Class entity) {
+ List entityList = EntityUtils.deletedBy(ids, entity);
+
+ return updateBatchById(entityList);
+ }
+
+ /**
+ *
+ * 判断数据库操作是否成功
+ *
+ *
+ * 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
+ *
+ *
+ * @param result 数据库操作返回影响条数
+ * @return boolean
+ */
+ protected static boolean retBool(Integer result) {
+ return SqlHelper.retBool(result);
+ }
+
+ protected Class currentModelClass() {
+ return (Class) ReflectionKit.getSuperClassGenericType(getClass(), 1);
+ }
+
+ /**
+ *
+ * 批量操作 SqlSession
+ *
+ */
+ protected SqlSession sqlSessionBatch() {
+ return SqlHelper.sqlSessionBatch(currentModelClass());
+ }
+
+ /**
+ * 释放sqlSession
+ *
+ * @param sqlSession session
+ */
+ protected void closeSqlSession(SqlSession sqlSession) {
+ SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(currentModelClass()));
+ }
+
+ /**
+ * 获取SqlStatement
+ *
+ * @param sqlMethod
+ * @return
+ */
+ protected String sqlStatement(SqlMethod sqlMethod) {
+ return SqlHelper.table(currentModelClass()).getSqlStatement(sqlMethod.getMethod());
+ }
+
+ @Override
+ public boolean insert(T entity) {
+ return BaseServiceImpl.retBool(baseDao.insert(entity));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean insertBatch(Collection entityList) {
+ return insertBatch(entityList, 100);
+ }
+
+ /**
+ * 批量插入
+ *
+ * @param entityList
+ * @param batchSize
+ * @return
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean insertBatch(Collection entityList, int batchSize) {
+ SqlSession batchSqlSession = sqlSessionBatch();
+ int i = 0;
+ String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
+ try {
+ for (T anEntityList : entityList) {
+ batchSqlSession.insert(sqlStatement, anEntityList);
+ if (i >= 1 && i % batchSize == 0) {
+ batchSqlSession.flushStatements();
+ }
+ i++;
+ }
+ batchSqlSession.flushStatements();
+ } finally {
+ closeSqlSession(batchSqlSession);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updateById(T entity) {
+ return BaseServiceImpl.retBool(baseDao.updateById(entity));
+ }
+
+ @Override
+ public boolean update(T entity, Wrapper updateWrapper) {
+ return BaseServiceImpl.retBool(baseDao.update(entity, updateWrapper));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean updateBatchById(Collection entityList) {
+ return updateBatchById(entityList, 30);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean updateBatchById(Collection entityList, int batchSize) {
+ if (CollectionUtils.isEmpty(entityList)) {
+ throw new IllegalArgumentException("Error: entityList must not be empty");
+ }
+ SqlSession batchSqlSession = sqlSessionBatch();
+ int i = 0;
+ String sqlStatement = sqlStatement(SqlMethod.UPDATE_BY_ID);
+ try {
+ for (T anEntityList : entityList) {
+ MapperMethod.ParamMap param = new MapperMethod.ParamMap<>();
+ param.put(Constants.ENTITY, anEntityList);
+ batchSqlSession.update(sqlStatement, param);
+ if (i >= 1 && i % batchSize == 0) {
+ batchSqlSession.flushStatements();
+ }
+ i++;
+ }
+ batchSqlSession.flushStatements();
+ } finally {
+ closeSqlSession(batchSqlSession);
+ }
+ return true;
+ }
+
+ @Override
+ public T selectById(Serializable id) {
+ return baseDao.selectById(id);
+ }
+
+ @Override
+ public boolean deleteById(Serializable id) {
+ return SqlHelper.delBool(baseDao.deleteById(id));
+ }
+
+ @Override
+ public boolean deleteBatchIds(Collection extends Serializable> idList) {
+ return SqlHelper.delBool(baseDao.deleteBatchIds(idList));
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/CrudServiceImpl.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/CrudServiceImpl.java
new file mode 100644
index 0000000..cc40449
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/service/impl/CrudServiceImpl.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import com.elink.esua.epdc.commons.mybatis.service.CrudService;
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.page.PageData;
+import com.elink.esua.epdc.commons.tools.utils.ConvertUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CRUD基础服务类
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public abstract class CrudServiceImpl, T, D> extends BaseServiceImpl implements CrudService {
+
+ protected Class currentDtoClass() {
+ return (Class) ReflectionKit.getSuperClassGenericType(getClass(), 2);
+ }
+
+ @Override
+ public PageData page(Map params) {
+ IPage page = baseDao.selectPage(
+ getPage(params, Constant.CREATE_DATE, false),
+ getWrapper(params)
+ );
+
+ return getPageData(page, currentDtoClass());
+ }
+
+ @Override
+ public List list(Map params) {
+ List entityList = baseDao.selectList(getWrapper(params));
+
+ return ConvertUtils.sourceToTarget(entityList, currentDtoClass());
+ }
+
+ public abstract QueryWrapper getWrapper(Map params);
+
+ @Override
+ public D get(Long id) {
+ T entity = baseDao.selectById(id);
+
+ return ConvertUtils.sourceToTarget(entity, currentDtoClass());
+ }
+
+ @Override
+ public void save(D dto) {
+ T entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
+ insert(entity);
+ }
+
+ @Override
+ public void update(D dto) {
+ T entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
+ updateById(entity);
+ }
+
+ @Override
+ public void delete(Long[] ids) {
+ baseDao.deleteBatchIds(Arrays.asList(ids));
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/DeptEntityUtils.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/DeptEntityUtils.java
new file mode 100644
index 0000000..b4d4c79
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/DeptEntityUtils.java
@@ -0,0 +1,74 @@
+package com.elink.esua.epdc.commons.mybatis.utils;
+
+import com.elink.esua.epdc.commons.mybatis.entity.DeptScope;
+import lombok.Data;
+
+/**
+ * 部门信息实体工具类
+ *
+ * @author rongchao
+ * @Date 19-12-18
+ */
+public class DeptEntityUtils {
+
+ @Data
+ public static class DeptDto {
+ /**
+ * 父所有部门ID
+ */
+ private String parentDeptIds;
+ /**
+ * 父所有部门
+ */
+ private String parentDeptNames;
+ /**
+ * 所有部门ID
+ */
+ private String allDeptIds;
+ /**
+ * 所有部门
+ */
+ private String allDeptNames;
+ }
+
+ /**
+ * 装载部门信息
+ *
+ * @param dto
+ * @param entityClass
+ * @return T
+ * @author rongchao
+ * @since 2019-12-18
+ */
+ public static T loadDeptInfo(DeptDto dto, Class entityClass) {
+ try {
+ T t = entityClass.newInstance();
+ t.setAllDeptIds(dto.getAllDeptIds());
+ t.setAllDeptNames(dto.getAllDeptNames());
+ t.setParentDeptIds(dto.getParentDeptIds());
+ t.setParentDeptNames(dto.getParentDeptNames());
+ return t;
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 装载部门信息
+ *
+ * @param dto
+ * @param entity
+ * @return void
+ * @author rongchao
+ * @since 2019-12-18
+ */
+ public static void loadDeptInfo(DeptDto dto, T entity) {
+ entity.setAllDeptIds(dto.getAllDeptIds());
+ entity.setAllDeptNames(dto.getAllDeptNames());
+ entity.setParentDeptIds(dto.getParentDeptIds());
+ entity.setParentDeptNames(dto.getParentDeptNames());
+ }
+}
diff --git a/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/EntityUtils.java b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/EntityUtils.java
new file mode 100644
index 0000000..4eaa0c3
--- /dev/null
+++ b/epdc-commons-mybatis/src/main/java/com/elink/esua/epdc/commons/mybatis/utils/EntityUtils.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.mybatis.utils;
+
+import com.elink.esua.epdc.commons.mybatis.enums.DelFlagEnum;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * 实体工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class EntityUtils {
+
+ /**
+ * 设置删除信息
+ * @param ids ids
+ * @param entity 实体
+ */
+ public static List deletedBy(Long[] ids, Class entity) {
+ List entityList = new ArrayList<>(ids.length);
+ for(Long id : ids){
+ T entityObject = deletedBy(id, entity);
+ entityList.add(entityObject);
+ }
+
+ return entityList;
+ }
+
+ /**
+ * 设置删除信息
+ * @param id id
+ * @param entity 实体
+ */
+ public static T deletedBy(Long id, Class entity) {
+ Map map = new HashMap<>(4);
+ map.put("id", id);
+ map.put("updater", SecurityUser.getUserId());
+ map.put("updateDate", new Date());
+ map.put("delFlag", DelFlagEnum.DEL.value());
+
+ T entityObject = null;
+ try {
+ entityObject = entity.newInstance();
+ } catch (Exception e) {
+
+ }
+
+ for (Map.Entry entry : map.entrySet()) {
+ setValue(entityObject, entry.getKey(), entry.getValue());
+ }
+
+ return entityObject;
+ }
+
+ private static void setValue(T entity, String key, Object value) {
+ Class> clazz = entity.getClass();
+
+ for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ field.setAccessible(true);
+
+ if (field.getName().equalsIgnoreCase(key)) {
+ try {
+ field.set(entity, value);
+ } catch (IllegalAccessException e) {
+ continue;
+ }
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/epdc-commons-tools-phone/pom.xml b/epdc-commons-tools-phone/pom.xml
new file mode 100644
index 0000000..ede08a0
--- /dev/null
+++ b/epdc-commons-tools-phone/pom.xml
@@ -0,0 +1,42 @@
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 4.0.0
+
+ epdc-commons-tools-phone
+ jar
+
+
+
+ com.googlecode.libphonenumber
+ libphonenumber
+ 8.8.8
+
+
+ com.googlecode.libphonenumber
+ carrier
+ 1.75
+
+
+ com.googlecode.libphonenumber
+ geocoder
+ 2.85
+
+
+ com.googlecode.libphonenumber
+ prefixmapper
+ 2.85
+
+
+
+
+ ${project.artifactId}
+
+
\ No newline at end of file
diff --git a/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneDto.java b/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneDto.java
new file mode 100644
index 0000000..eb8f3fe
--- /dev/null
+++ b/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneDto.java
@@ -0,0 +1,79 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+/**
+ * 电话DTO
+ *
+ * @author rongchao
+ * @Date 18-12-11
+ */
+public class PhoneDto {
+
+ /**
+ * 省份名称
+ */
+ private String provinceName;
+
+ /**
+ * 城市名称
+ */
+ private String cityName;
+
+ /**
+ * 运营商:移动/电信/联通
+ */
+ private String carrier;
+
+ /**
+ * 省份名称
+ *
+ * @return 获取provinceName属性值
+ */
+ public String getProvinceName() {
+ return provinceName;
+ }
+
+ /**
+ * 省份名称
+ *
+ * @param provinceName 设置 provinceName 属性值为参数值 provinceName
+ */
+ public void setProvinceName(String provinceName) {
+ this.provinceName = provinceName;
+ }
+
+ /**
+ * 城市名称
+ *
+ * @return 获取cityName属性值
+ */
+ public String getCityName() {
+ return cityName;
+ }
+
+ /**
+ * 城市名称
+ *
+ * @param cityName 设置 cityName 属性值为参数值 cityName
+ */
+ public void setCityName(String cityName) {
+ this.cityName = cityName;
+ }
+
+ /**
+ * 运营商:移动/电信/联通
+ *
+ * @return 获取carrier属性值
+ */
+ public String getCarrier() {
+ return carrier;
+ }
+
+ /**
+ * 运营商:移动/电信/联通
+ *
+ * @param carrier 设置 carrier 属性值为参数值 carrier
+ */
+ public void setCarrier(String carrier) {
+ this.carrier = carrier;
+ }
+}
diff --git a/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneUtil.java b/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneUtil.java
new file mode 100644
index 0000000..e9af526
--- /dev/null
+++ b/epdc-commons-tools-phone/src/main/java/com/elink/esua/epdc/commons/tools/utils/PhoneUtil.java
@@ -0,0 +1,175 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+/**
+ * @author rongchao
+ * @Date 18-12-11
+ */
+
+import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
+
+import java.util.Locale;
+
+/**
+ * 手机号归属地查询
+ * jar依赖:com.googlecode.libphonenumber(Libphonenumber、Geocoder、Prefixmapper
+ * 、Carrier) pom依赖:http://mvnrepository.com/search?q=libphonenumber
+ * 项目地址:https://github.com/googlei18n/libphonenumber
+ *
+ * @author rongchao
+ * @Date 18-12-11
+ */
+public class PhoneUtil {
+
+ /**
+ * 直辖市
+ */
+ private final static String[] MUNICIPALITY = {"北京市", "天津市", "上海市", "重庆市"};
+
+ /**
+ * 自治区
+ */
+ private final static String[] AUTONOMOUS_REGION = {"新疆", "内蒙古", "西藏", "宁夏", "广西"};
+
+ private static PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil
+ .getInstance();
+
+ /**
+ * 提供与电话号码相关的运营商信息
+ */
+ private static PhoneNumberToCarrierMapper carrierMapper = PhoneNumberToCarrierMapper
+ .getInstance();
+
+ /**
+ * 提供与电话号码有关的地理信息
+ */
+ private static PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder
+ .getInstance();
+
+ /**
+ * 中国大陆区区号
+ */
+ private final static int COUNTRY_CODE = 86;
+
+ /**
+ * 根据手机号 判断手机号是否有效
+ *
+ * @param phoneNumber 手机号码
+ * @return true-有效 false-无效
+ */
+ public static boolean checkPhoneNumber(String phoneNumber) {
+ long phone = Long.parseLong(phoneNumber);
+
+ PhoneNumber pn = new PhoneNumber();
+ pn.setCountryCode(COUNTRY_CODE);
+ pn.setNationalNumber(phone);
+
+ return phoneNumberUtil.isValidNumber(pn);
+
+ }
+
+ /**
+ * 根据手机号 判断手机运营商
+ *
+ * @param phoneNumber 手机号码
+ * @return 如:广东省广州市移动
+ */
+ public static String getCarrier(String phoneNumber) {
+
+ long phone = Long.parseLong(phoneNumber);
+
+ PhoneNumber pn = new PhoneNumber();
+ pn.setCountryCode(COUNTRY_CODE);
+ pn.setNationalNumber(phone);
+ // 返回结果只有英文,自己转成成中文
+ String carrierEn = carrierMapper.getNameForNumber(pn, Locale.ENGLISH);
+ String carrierZh = "";
+ switch (carrierEn) {
+ case "China Mobile":
+ carrierZh += "移动";
+ break;
+ case "China Unicom":
+ carrierZh += "联通";
+ break;
+ case "China Telecom":
+ carrierZh += "电信";
+ break;
+ default:
+ break;
+ }
+ return carrierZh;
+ }
+
+ /**
+ * 根据手机号 获取手机归属地
+ *
+ * @param phoneNumber 手机号码
+ * @return 如:广东省广州市
+ */
+ public static String getGeo(String phoneNumber) {
+ long phone = Long.parseLong(phoneNumber);
+
+ PhoneNumber pn = new PhoneNumber();
+ pn.setCountryCode(COUNTRY_CODE);
+ pn.setNationalNumber(phone);
+ return geocoder.getDescriptionForNumber(pn, Locale.CHINESE);
+ }
+
+ /**
+ * 根据手机号 获取手机信息模型
+ *
+ *
+ * 若返回值为null,则说明该号码无效
+ *
+ *
+ * @param phoneNumber 手机号码
+ * @return 手机信息模型PhoneModel
+ */
+ public static PhoneDto getPhoneDto(String phoneNumber) {
+ if (checkPhoneNumber(phoneNumber)) {
+ String geo = getGeo(phoneNumber);
+ PhoneDto phoneDto = new PhoneDto();
+ String carrier = getCarrier(phoneNumber);
+ phoneDto.setCarrier(carrier);
+ // 直辖市
+ for (String val : MUNICIPALITY) {
+ if (geo.equals(val)) {
+ phoneDto.setProvinceName(val.replace("市", ""));
+ phoneDto.setCityName(val);
+ return phoneDto;
+ }
+ }
+ // 自治区
+ for (String val : AUTONOMOUS_REGION) {
+ if (geo.startsWith(val)) {
+ phoneDto.setProvinceName(val);
+ phoneDto.setCityName(geo.replace(val, ""));
+ return phoneDto;
+ }
+ }
+
+ // 其它
+ String[] splitArr = geo.split("省");
+ if (splitArr != null && splitArr.length == 2) {
+ phoneDto.setProvinceName(splitArr[0]);
+ phoneDto.setCityName(splitArr[1]);
+ return phoneDto;
+ }
+ }
+ return null;
+ }
+
+ public static void main(String[] args) {
+ PhoneDto phoneDto = PhoneUtil.getPhoneDto("13701001254");
+ if (phoneDto != null) {
+ System.out.println(phoneDto.getProvinceName());
+ System.out.println(phoneDto.getCityName());
+ System.out.println(phoneDto.getCarrier());
+ } else {
+ System.err.println("该号码无效");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/epdc-commons-tools-wx-ma/pom.xml b/epdc-commons-tools-wx-ma/pom.xml
new file mode 100644
index 0000000..9b330e1
--- /dev/null
+++ b/epdc-commons-tools-wx-ma/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 4.0.0
+
+ 1.0.0
+ epdc-commons-tools-wx-ma
+ jar
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+ compile
+
+
+ com.github.binarywang
+ weixin-java-miniapp
+ 3.6.0
+
+
+
+
diff --git a/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/utils/WxMaServiceUtils.java b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/utils/WxMaServiceUtils.java
new file mode 100644
index 0000000..dafd82d
--- /dev/null
+++ b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/utils/WxMaServiceUtils.java
@@ -0,0 +1,46 @@
+package com.elink.esua.epdc.utils;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import com.elink.esua.epdc.wx.ma.WxMaConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 获取小程序业务工具
+ *
+ * @author work@yujt.net.cn
+ * @date 2019/11/25 13:29
+ */
+@Component
+public class WxMaServiceUtils {
+
+ @Value("${wx.ma.appId.normal}")
+ private String APPID_NORMAL;
+
+ @Value("${wx.ma.appId.work}")
+ private String APPID_WORK;
+
+ /**
+ * 获取党群e家 普通居民端配置
+ *
+ * @return cn.binarywang.wx.miniapp.api.WxMaService
+ * @author work@yujt.net.cn
+ * @date 2019/11/25 16:09
+ */
+ public final WxMaService normalWxMaService() {
+ final WxMaService wxMaService = WxMaConfig.getMaService(APPID_NORMAL);
+ return wxMaService;
+ }
+
+ /**
+ * 获取党群e家 工作端配置
+ *
+ * @return cn.binarywang.wx.miniapp.api.WxMaService
+ * @author work@yujt.net.cn
+ * @date 2019/11/25 16:10
+ */
+ public final WxMaService workWxMaService() {
+ final WxMaService wxMaService = WxMaConfig.getMaService(APPID_WORK);
+ return wxMaService;
+ }
+}
diff --git a/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaConfig.java b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaConfig.java
new file mode 100644
index 0000000..79af52f
--- /dev/null
+++ b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaConfig.java
@@ -0,0 +1,148 @@
+package com.elink.esua.epdc.wx.ma;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
+import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
+import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
+import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
+import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
+import me.chanjar.weixin.common.error.WxErrorException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author Binary Wang
+ */
+@Configuration
+@EnableConfigurationProperties(WxMaProperties.class)
+public class WxMaConfig {
+
+ private WxMaProperties properties;
+
+ private static Map routers = Maps.newHashMap();
+ private static Map maServices = Maps.newHashMap();
+
+ @Autowired
+ public WxMaConfig(WxMaProperties properties) {
+ this.properties = properties;
+ }
+
+ public static WxMaService getMaService(String appid) {
+ WxMaService wxService = maServices.get(appid);
+ if (wxService == null) {
+ throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
+ }
+
+ return wxService;
+ }
+
+ public static WxMaMessageRouter getRouter(String appid) {
+ return routers.get(appid);
+ }
+
+ @PostConstruct
+ public void init() {
+ List configs = this.properties.getConfigs();
+ if (configs == null) {
+ throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
+ }
+
+ maServices = configs.stream()
+ .map(a -> {
+ WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
+ config.setAppid(a.getAppid());
+ config.setSecret(a.getSecret());
+ config.setToken(a.getToken());
+ config.setAesKey(a.getAesKey());
+ config.setMsgDataFormat(a.getMsgDataFormat());
+
+ WxMaService service = new WxMaServiceImpl();
+ service.setWxMaConfig(config);
+ routers.put(a.getAppid(), this.newRouter(service));
+ return service;
+ }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
+ }
+
+ private WxMaMessageRouter newRouter(WxMaService service) {
+ final WxMaMessageRouter router = new WxMaMessageRouter(service);
+ router
+ .rule().handler(logHandler).next()
+ .rule().async(false).content("模板").handler(templateMsgHandler).end()
+ .rule().async(false).content("文本").handler(textHandler).end()
+ .rule().async(false).content("图片").handler(picHandler).end()
+ .rule().async(false).content("二维码").handler(qrcodeHandler).end();
+ return router;
+ }
+
+ private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) -> {
+ service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
+ .templateId("此处更换为自己的模板id")
+ .formId("自己替换可用的formid")
+ .data(Lists.newArrayList(
+ new WxMaTemplateData("keyword1", "339208499", "#173177")))
+ .toUser(wxMessage.getFromUser())
+ .build());
+ return null;
+ };
+
+ private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
+ System.out.println("收到消息:" + wxMessage.toString());
+ service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
+ .toUser(wxMessage.getFromUser()).build());
+ return null;
+ };
+
+ private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
+ service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
+ .toUser(wxMessage.getFromUser()).build());
+ return null;
+ };
+
+ private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
+ try {
+ WxMediaUploadResult uploadResult = service.getMediaService()
+ .uploadMedia("image", "png",
+ ClassLoader.getSystemResourceAsStream("tmp.png"));
+ service.getMsgService().sendKefuMsg(
+ WxMaKefuMessage
+ .newImageBuilder()
+ .mediaId(uploadResult.getMediaId())
+ .toUser(wxMessage.getFromUser())
+ .build());
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ };
+
+ private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
+ try {
+ final File file = service.getQrcodeService().createQrcode("123", 430);
+ WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
+ service.getMsgService().sendKefuMsg(
+ WxMaKefuMessage
+ .newImageBuilder()
+ .mediaId(uploadResult.getMediaId())
+ .toUser(wxMessage.getFromUser())
+ .build());
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ };
+
+}
diff --git a/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaProperties.java b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaProperties.java
new file mode 100644
index 0000000..f00ab8c
--- /dev/null
+++ b/epdc-commons-tools-wx-ma/src/main/java/com/elink/esua/epdc/wx/ma/WxMaProperties.java
@@ -0,0 +1,48 @@
+package com.elink.esua.epdc.wx.ma;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.List;
+
+/**
+ * 微信小程序框架配置类
+ *
+ * @author rongchao
+ * @Date 19-5-13
+ */
+@Data
+@ConfigurationProperties(prefix = "wx.ma")
+public class WxMaProperties {
+
+ private List configs;
+
+ @Data
+ public static class Config {
+ /**
+ * 设置微信小程序的appid
+ */
+ private String appid;
+
+ /**
+ * 设置微信小程序的Secret
+ */
+ private String secret;
+
+ /**
+ * 设置微信小程序消息服务器配置的token
+ */
+ private String token;
+
+ /**
+ * 设置微信小程序消息服务器配置的EncodingAESKey
+ */
+ private String aesKey;
+
+ /**
+ * 消息格式,XML或者JSON
+ */
+ private String msgDataFormat;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/.editorconfig b/epdc-commons-tools-wx-mp/.editorconfig
new file mode 100644
index 0000000..775be5b
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/.editorconfig
@@ -0,0 +1,14 @@
+# EditorConfig: http://editorconfig.org/
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/epdc-commons-tools-wx-mp/.travis.yml b/epdc-commons-tools-wx-mp/.travis.yml
new file mode 100644
index 0000000..5d2a769
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/.travis.yml
@@ -0,0 +1,13 @@
+language: java
+jdk:
+ - openjdk8
+
+script: "mvn clean package -Dmaven.test.skip=true"
+
+branches:
+ only:
+ - master
+
+notifications:
+ email:
+ - binarywang@vip.qq.com
diff --git a/epdc-commons-tools-wx-mp/README.md b/epdc-commons-tools-wx-mp/README.md
new file mode 100644
index 0000000..790d56b
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/README.md
@@ -0,0 +1,58 @@
+[](https://gitee.com/binary/weixin-java-mp-demo-springboot)
+[](https://github.com/binarywang/weixin-java-mp-demo-springboot)
+[](https://travis-ci.org/binarywang/weixin-java-mp-demo-springboot)
+-----------------------
+
+### 本Demo基于Spring Boot构建,实现微信公众号后端开发功能。
+### 本项目为WxJava的Demo演示程序,更多Demo请[查阅此处](https://github.com/Wechat-Group/WxJava/blob/master/demo.md)。
+#### 如有问题请[【在此提问】](https://github.com/binarywang/weixin-java-mp-demo-springboot/issues),谢谢配合。
+
+
+
+## 使用步骤:
+1. 请注意,本demo为简化代码编译时加入了lombok支持,如果不了解lombok的话,请先学习下相关知识,比如可以阅读[此文章](https://mp.weixin.qq.com/s/cUc-bUcprycADfNepnSwZQ);
+1. 另外,新手遇到问题,请务必先阅读[【开发文档首页】](https://github.com/Wechat-Group/WxJava/wiki)的常见问题部分,可以少走很多弯路,节省不少时间。
+1. 配置:复制 `/src/main/resources/application.yml.template` 或修改其扩展名生成 `application.yml` 文件,根据自己需要填写相关配置(需要注意的是:yml文件内的属性冒号后面的文字之前需要加空格,可参考已有配置,否则属性会设置不成功);
+2. 主要配置说明如下:
+```
+wx:
+ mp:
+ configs:
+ - appId: 1111 (一个公众号的appid)
+ secret: 1111(公众号的appsecret)
+ token: 111 (接口配置里的Token值)
+ aesKey: 111 (接口配置里的EncodingAESKey值)
+ - appId: 2222 (另一个公众号的appid,以下同上)
+ secret: 1111
+ token: 111
+ aesKey: 111
+```
+3. 运行Java程序:`WxMpDemoApplication`;
+4. 配置微信公众号中的接口地址:http://公网可访问域名/wx/portal/xxxxx (注意,xxxxx为对应公众号的appid值);
+5. 根据自己需要修改各个handler的实现,加入自己的业务逻辑。
+
diff --git a/epdc-commons-tools-wx-mp/pom.xml b/epdc-commons-tools-wx-mp/pom.xml
new file mode 100644
index 0000000..4a9e3d3
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 1.0.0
+ epdc-commons-tools-wx-mp
+ jar
+
+
+
+
+
+ 3.6.0
+ 1.8
+ 1.8
+ UTF-8
+ UTF-8
+ zh_CN
+ wechat-mp-demo
+
+
+
+
+ com.github.binarywang
+ weixin-java-mp
+ ${weixin-java-mp.version}
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+ compile
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ compile
+ true
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure-processor
+ compile
+ true
+
+
+
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/AbstractBuilder.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/AbstractBuilder.java
new file mode 100644
index 0000000..dc270da
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/AbstractBuilder.java
@@ -0,0 +1,17 @@
+package com.elink.esua.epdc.wx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public abstract class AbstractBuilder {
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+ public abstract WxMpXmlOutMessage build(String content,
+ WxMpXmlMessage wxMessage, WxMpService service);
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/ImageBuilder.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/ImageBuilder.java
new file mode 100644
index 0000000..8daf22d
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/ImageBuilder.java
@@ -0,0 +1,24 @@
+package com.elink.esua.epdc.wx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public class ImageBuilder extends AbstractBuilder {
+
+ @Override
+ public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+ WxMpService service) {
+
+ WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+
+ return m;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/TextBuilder.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/TextBuilder.java
new file mode 100644
index 0000000..93ea480
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/builder/TextBuilder.java
@@ -0,0 +1,22 @@
+package com.elink.esua.epdc.wx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public class TextBuilder extends AbstractBuilder {
+
+ @Override
+ public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+ WxMpService service) {
+ WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+ return m;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpConfiguration.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpConfiguration.java
new file mode 100644
index 0000000..59a027c
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpConfiguration.java
@@ -0,0 +1,113 @@
+package com.elink.esua.epdc.wx.mp.config;
+
+import com.elink.esua.epdc.wx.mp.handler.*;
+import lombok.AllArgsConstructor;
+import me.chanjar.weixin.mp.api.WxMpMessageRouter;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
+import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static me.chanjar.weixin.common.api.WxConsts.EventType;
+import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
+import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE;
+import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType.CLICK;
+import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType.VIEW;
+import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
+import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
+import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*;
+import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY;
+
+/**
+ * wechat mp configuration
+ *
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@AllArgsConstructor
+@Configuration
+@EnableConfigurationProperties(WxMpProperties.class)
+public class WxMpConfiguration {
+ private final LogHandler logHandler;
+ private final NullHandler nullHandler;
+ private final KfSessionHandler kfSessionHandler;
+ private final StoreCheckNotifyHandler storeCheckNotifyHandler;
+ private final LocationHandler locationHandler;
+ private final MenuHandler menuHandler;
+ private final MsgHandler msgHandler;
+ private final UnsubscribeHandler unsubscribeHandler;
+ private final SubscribeHandler subscribeHandler;
+ private final ScanHandler scanHandler;
+ private final WxMpProperties properties;
+
+ @Bean
+ public WxMpService wxMpService() {
+ // 代码里 getConfigs()处报错的同学,请注意仔细阅读项目说明,你的IDE需要引入lombok插件!!!!
+ final List configs = this.properties.getConfigs();
+ if (configs == null) {
+ throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
+ }
+
+ WxMpService service = new WxMpServiceImpl();
+ service.setMultiConfigStorages(configs
+ .stream().map(a -> {
+ WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
+ configStorage.setAppId(a.getAppId());
+ configStorage.setSecret(a.getSecret());
+ configStorage.setToken(a.getToken());
+ configStorage.setAesKey(a.getAesKey());
+ return configStorage;
+ }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o)));
+ return service;
+ }
+
+ @Bean
+ public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
+ final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
+
+ // 记录所有事件的日志 (异步执行)
+ newRouter.rule().handler(this.logHandler).next();
+
+ // 接收客服会话管理事件
+ newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
+ .handler(this.kfSessionHandler).end();
+ newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
+ .handler(this.kfSessionHandler).end();
+ newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
+ .handler(this.kfSessionHandler).end();
+
+ // 门店审核事件
+ newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
+
+ // 自定义菜单事件
+ newRouter.rule().async(false).msgType(EVENT).event(CLICK).handler(this.menuHandler).end();
+
+ // 点击菜单连接事件
+ newRouter.rule().async(false).msgType(EVENT).event(VIEW).handler(this.nullHandler).end();
+
+ // 关注事件
+ newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
+
+ // 取消关注事件
+ newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
+
+ // 上报地理位置事件
+ newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end();
+
+ // 接收地理位置消息
+ newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();
+
+ // 扫码事件
+ newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end();
+
+ // 默认
+ newRouter.rule().async(false).handler(this.msgHandler).end();
+
+ return newRouter;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpProperties.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpProperties.java
new file mode 100644
index 0000000..6a1aa59
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/config/WxMpProperties.java
@@ -0,0 +1,46 @@
+package com.elink.esua.epdc.wx.mp.config;
+
+import com.elink.esua.epdc.wx.mp.utils.JsonUtils;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.List;
+
+/**
+ * wechat mp properties
+ *
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Data
+@ConfigurationProperties(prefix = "wx.mp")
+public class WxMpProperties {
+ private List configs;
+
+ @Data
+ public static class MpConfig {
+ /**
+ * 设置微信公众号的appid
+ */
+ private String appId;
+
+ /**
+ * 设置微信公众号的app secret
+ */
+ private String secret;
+
+ /**
+ * 设置微信公众号的token
+ */
+ private String token;
+
+ /**
+ * 设置微信公众号的EncodingAESKey
+ */
+ private String aesKey;
+ }
+
+ @Override
+ public String toString() {
+ return JsonUtils.toJson(this);
+ }
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/AbstractHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/AbstractHandler.java
new file mode 100644
index 0000000..b3a89e7
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/AbstractHandler.java
@@ -0,0 +1,12 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public abstract class AbstractHandler implements WxMpMessageHandler {
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/KfSessionHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/KfSessionHandler.java
new file mode 100644
index 0000000..46df4a7
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/KfSessionHandler.java
@@ -0,0 +1,25 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class KfSessionHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ //TODO 对会话做处理
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LocationHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LocationHandler.java
new file mode 100644
index 0000000..9089a15
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LocationHandler.java
@@ -0,0 +1,44 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import com.elink.esua.epdc.wx.mp.builder.TextBuilder;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class LocationHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) {
+ //TODO 接收处理用户发送的地理位置消息
+ try {
+ String content = "感谢反馈,您的的地理位置已收到!";
+ return new TextBuilder().build(content, wxMessage, null);
+ } catch (Exception e) {
+ this.logger.error("位置消息接收处理失败", e);
+ return null;
+ }
+ }
+
+ //上报地理位置事件
+ this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
+ wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
+
+ //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
+
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LogHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LogHandler.java
new file mode 100644
index 0000000..1ff3ec3
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/LogHandler.java
@@ -0,0 +1,25 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import com.elink.esua.epdc.wx.mp.utils.JsonUtils;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class LogHandler extends AbstractHandler {
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage));
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MenuHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MenuHandler.java
new file mode 100644
index 0000000..249d87e
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MenuHandler.java
@@ -0,0 +1,36 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class MenuHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) {
+
+ String msg = String.format("type:%s, event:%s, key:%s",
+ wxMessage.getMsgType(), wxMessage.getEvent(),
+ wxMessage.getEventKey());
+ if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) {
+ return null;
+ }
+
+ return WxMpXmlOutMessage.TEXT().content(msg)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MsgHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MsgHandler.java
new file mode 100644
index 0000000..21f8b48
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/MsgHandler.java
@@ -0,0 +1,52 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import com.elink.esua.epdc.wx.mp.builder.TextBuilder;
+import com.elink.esua.epdc.wx.mp.utils.JsonUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class MsgHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) {
+
+ if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
+ //TODO 可以选择将消息保存到本地
+ }
+
+ //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服
+ try {
+ if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服")
+ && weixinService.getKefuService().kfOnlineList()
+ .getKfOnlineList().size() > 0) {
+ return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE()
+ .fromUser(wxMessage.getToUser())
+ .toUser(wxMessage.getFromUser()).build();
+ }
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ //TODO 组装回复消息
+ String content = "收到信息内容:" + JsonUtils.toJson(wxMessage);
+
+ return new TextBuilder().build(content, wxMessage, weixinService);
+
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/NullHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/NullHandler.java
new file mode 100644
index 0000000..f762908
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/NullHandler.java
@@ -0,0 +1,24 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class NullHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/ScanHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/ScanHandler.java
new file mode 100644
index 0000000..407f946
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/ScanHandler.java
@@ -0,0 +1,25 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class ScanHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map,
+ WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
+ // 扫码事件处理
+ return null;
+ }
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/StoreCheckNotifyHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/StoreCheckNotifyHandler.java
new file mode 100644
index 0000000..cd1cd25
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/StoreCheckNotifyHandler.java
@@ -0,0 +1,27 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 门店审核事件处理
+ *
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class StoreCheckNotifyHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ // TODO 处理门店审核事件
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/SubscribeHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/SubscribeHandler.java
new file mode 100644
index 0000000..88aac68
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/SubscribeHandler.java
@@ -0,0 +1,71 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import java.util.Map;
+
+import com.elink.esua.epdc.wx.mp.builder.TextBuilder;
+import org.springframework.stereotype.Component;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class SubscribeHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) throws WxErrorException {
+
+ this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUser());
+
+ // 获取微信用户基本信息
+ try {
+ WxMpUser userWxInfo = weixinService.getUserService()
+ .userInfo(wxMessage.getFromUser(), null);
+ if (userWxInfo != null) {
+ // TODO 可以添加关注用户到本地数据库
+ }
+ } catch (WxErrorException e) {
+ if (e.getError().getErrorCode() == 48001) {
+ this.logger.info("该公众号没有获取用户信息权限!");
+ }
+ }
+
+
+ WxMpXmlOutMessage responseResult = null;
+ try {
+ responseResult = this.handleSpecial(wxMessage);
+ } catch (Exception e) {
+ this.logger.error(e.getMessage(), e);
+ }
+
+ if (responseResult != null) {
+ return responseResult;
+ }
+
+ try {
+ return new TextBuilder().build("感谢关注", wxMessage, weixinService);
+ } catch (Exception e) {
+ this.logger.error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+
+ /**
+ * 处理特殊请求,比如如果是扫码进来的,可以做相应处理
+ */
+ private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
+ throws Exception {
+ //TODO
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/UnsubscribeHandler.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/UnsubscribeHandler.java
new file mode 100644
index 0000000..4a4723d
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/handler/UnsubscribeHandler.java
@@ -0,0 +1,27 @@
+package com.elink.esua.epdc.wx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class UnsubscribeHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ String openId = wxMessage.getFromUser();
+ this.logger.info("取消关注用户 OPENID: " + openId);
+ // TODO 可以更新本地数据库为取消关注状态
+ return null;
+ }
+
+}
diff --git a/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/utils/JsonUtils.java b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/utils/JsonUtils.java
new file mode 100644
index 0000000..0c88b15
--- /dev/null
+++ b/epdc-commons-tools-wx-mp/src/main/java/com/elink/esua/epdc/wx/mp/utils/JsonUtils.java
@@ -0,0 +1,16 @@
+package com.elink.esua.epdc.wx.mp.utils;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public class JsonUtils {
+ public static String toJson(Object obj) {
+ Gson gson = new GsonBuilder()
+ .setPrettyPrinting()
+ .create();
+ return gson.toJson(obj);
+ }
+}
diff --git a/epdc-commons-tools/pom.xml b/epdc-commons-tools/pom.xml
new file mode 100644
index 0000000..2f985fa
--- /dev/null
+++ b/epdc-commons-tools/pom.xml
@@ -0,0 +1,116 @@
+
+
+ 4.0.0
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ epdc-commons-tools
+ jar
+
+
+ 6.0.12.Final
+ 3.7
+ 1.3.3
+ 2.6
+ 4.1.8
+ 3.1.0
+ 2.9.9
+ 1.2.59
+ 1.11.3
+ 1.18.4
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ org.hibernate
+ hibernate-validator
+ ${hibernate.validator.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons.lang.version}
+
+
+ commons-fileupload
+ commons-fileupload
+ ${commons.fileupload.version}
+
+
+ commons-io
+ commons-io
+ ${commons.io.version}
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+ cn.afterturn
+ easypoi-base
+ ${easypoi.version}
+
+
+ cn.afterturn
+ easypoi-web
+ ${easypoi.version}
+
+
+ joda-time
+ joda-time
+ ${joda.time.version}
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+ org.jsoup
+ jsoup
+ ${jsoup.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+ ${project.artifactId}
+
+
+
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LogOperation.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LogOperation.java
new file mode 100644
index 0000000..2080c34
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LogOperation.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 操作日志注解
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface LogOperation {
+ String value() default "";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LoginUser.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LoginUser.java
new file mode 100644
index 0000000..ef06ef6
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/annotation/LoginUser.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 登录用户信息
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LoginUser {
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/aspect/LogOperationAspect.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/aspect/LogOperationAspect.java
new file mode 100644
index 0000000..c9ef3ed
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/aspect/LogOperationAspect.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.aspect;
+
+import com.alibaba.fastjson.JSON;
+import com.elink.esua.epdc.commons.tools.annotation.LogOperation;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import com.elink.esua.epdc.commons.tools.utils.HttpContextUtils;
+import com.elink.esua.epdc.commons.tools.utils.IpUtils;
+import com.elink.esua.epdc.commons.tools.annotation.LogOperation;
+import com.elink.esua.epdc.commons.tools.config.ModuleConfig;
+import com.elink.esua.epdc.commons.tools.log.SysLogOperation;
+import com.elink.esua.epdc.commons.tools.log.enums.LogTypeEnum;
+import com.elink.esua.epdc.commons.tools.log.enums.OperationStatusEnum;
+import com.elink.esua.epdc.commons.tools.log.producer.LogProducer;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import com.elink.esua.epdc.commons.tools.utils.HttpContextUtils;
+import com.elink.esua.epdc.commons.tools.utils.IpUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+/**
+ * 操作日志,切面处理类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Aspect
+@Component
+public class LogOperationAspect {
+ @Autowired
+ private ModuleConfig moduleConfig;
+ @Autowired
+ private LogProducer logProducer;
+
+ @Pointcut("@annotation(com.elink.esua.epdc.commons.tools.annotation.LogOperation)")
+ public void logPointCut() {
+
+ }
+
+ @Around("logPointCut()")
+ public Object around(ProceedingJoinPoint point) throws Throwable {
+ long beginTime = System.currentTimeMillis();
+ try {
+ //执行方法
+ Object result = point.proceed();
+
+ //执行时长(毫秒)
+ long time = System.currentTimeMillis() - beginTime;
+ //保存日志
+ saveLog(point, time, OperationStatusEnum.SUCCESS.value());
+
+ return result;
+ }catch(Exception e) {
+ //执行时长(毫秒)
+ long time = System.currentTimeMillis() - beginTime;
+ //保存日志
+ saveLog(point, time, OperationStatusEnum.FAIL.value());
+
+ throw e;
+ }
+ }
+
+
+ private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status) {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+
+ SysLogOperation log = new SysLogOperation();
+ LogOperation annotation = method.getAnnotation(LogOperation.class);
+ if(annotation != null){
+ //注解上的描述
+ log.setOperation(annotation.value());
+ }
+
+ //登录用户信息
+ UserDetail user = SecurityUser.getUser();
+ if(user != null){
+ log.setCreator(user.getId());
+ log.setCreatorName(user.getUsername());
+ }
+
+ log.setType(LogTypeEnum.OPERATION.value());
+ log.setModule(moduleConfig.getName());
+ log.setStatus(status);
+ log.setRequestTime((int)time);
+ log.setCreateDate(new Date());
+
+ //请求相关信息
+ HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
+ log.setIp(IpUtils.getIpAddr(request));
+ log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
+ log.setRequestUri(request.getRequestURI());
+ log.setRequestMethod(request.getMethod());
+
+ //请求参数
+ Object[] args = joinPoint.getArgs();
+ try{
+ String params = JSON.toJSONString(args[0]);
+ log.setRequestParams(params);
+ }catch (Exception e){
+
+ }
+
+ //保存到Redis队列里
+ logProducer.saveLog(log);
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/config/ModuleConfig.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/config/ModuleConfig.java
new file mode 100644
index 0000000..31f156c
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/config/ModuleConfig.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.config;
+
+/**
+ * 模块配置信息
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface ModuleConfig {
+ /**
+ * 获取模块名称
+ */
+ String getName();
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/Constant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/Constant.java
new file mode 100644
index 0000000..293fbd0
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/Constant.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * 常量
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface Constant {
+ /**
+ * 成功
+ */
+ int SUCCESS = 1;
+ /**
+ * 失败
+ */
+ int FAIL = 0;
+ /**
+ * OK
+ */
+ String OK = "OK";
+ /**
+ * 用户标识
+ */
+ String USER_KEY = "userId";
+ /**
+ * 菜单根节点标识
+ */
+ Long MENU_ROOT = 0L;
+ /**
+ * 部门根节点标识
+ */
+ Long DEPT_ROOT = 0L;
+ /**
+ * 分类根节点标识
+ */
+ Long CATEGORY_ROOT = 0L;
+ /**
+ * 数据字典根节点标识
+ */
+ Long DICT_ROOT = 0L;
+ /**
+ * 升序
+ */
+ String ASC = "asc";
+ /**
+ * 降序
+ */
+ String DESC = "desc";
+ /**
+ * 删除字段名
+ */
+ String DEL_FLAG = "del_flag";
+ /**
+ * 创建时间字段名
+ */
+ String CREATE_DATE = "create_date";
+
+ /**
+ * 数据权限过滤
+ */
+ String SQL_FILTER = "sqlFilter";
+ /**
+ * 当前页码
+ */
+ String PAGE = "page";
+ /**
+ * 每页显示记录数
+ */
+ String LIMIT = "limit";
+ /**
+ * 排序字段
+ */
+ String ORDER_FIELD = "orderField";
+ /**
+ * 排序方式
+ */
+ String ORDER = "order";
+ /**
+ * token header
+ */
+ String TOKEN_HEADER = "token";
+ /**
+ * authorization header
+ */
+ String AUTHORIZATION_HEADER = "authorization";
+ /**
+ * APP用户标识
+ */
+ String APP_USER_KEY = "appUserId";
+ /**
+ * 移动端用户标识
+ */
+ String APP_USER_FLAG = "APP_USER";
+ /**
+ * 版本控制用
+ */
+ String VERSION_CONTROL = "/{version}";
+ /**
+ * 移动端接口标识
+ */
+ String EPDC_APP = "epdc-app/";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/FieldConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/FieldConstant.java
new file mode 100644
index 0000000..f31cc19
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/FieldConstant.java
@@ -0,0 +1,54 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+
+/**
+ * 常用字段常量
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2019/8/20 10:11
+ */
+public interface FieldConstant {
+
+ String ID = "ID";
+ String ID_HUMP = "id";
+
+ String REVISION = "REVISION";
+ String REVISION_HUMP = "revision";
+
+ String CREATED_BY = "CREATED_BY";
+ String CREATED_BY_HUMP = "createdBy";
+
+ String CREATED_TIME = "CREATED_TIME";
+ String CREATED_TIME_HUMP = "createdTime";
+
+ String UPDATED_BY = "UPDATED_BY";
+ String UPDATED_BY_HUMP = "updatedBy";
+
+ String UPDATED_TIME = "UPDATED_TIME";
+ String UPDATED_TIME_HUMP = "updatedTime";
+
+ String DEL_FLAG = "DEL_FLAG";
+ String DEL_FLAG_HUMP = "delFlag";
+
+ String NAME = "NAME";
+ String NAME_HUMP = "name";
+
+ String MOBILE = "MOBILE";
+ String MOBILE_HUMP = "mobile";
+
+ String STATE = "STATE";
+ String STATE_HUMP = "state";
+
+ String STREET_ID = "STREET_ID";
+ String STREET_ID_HUMP = "streetId";
+
+ String COMMUNITY_ID = "COMMUNITY_ID";
+ String COMMUNITY_ID_HUMP = "communityId";
+
+ String GRID_ID = "GRID_ID";
+ String GRID_ID_HUMP = "gridId";
+
+
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NacosConfigConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NacosConfigConstant.java
new file mode 100644
index 0000000..c3c2d71
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NacosConfigConstant.java
@@ -0,0 +1,12 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * Nacos配置中心相关常量
+ *
+ * @author rongchao
+ * @Date 20-1-15
+ */
+public interface NacosConfigConstant {
+
+ String CONFIG_GROUP = "EPDC_CONFIG_GROUP";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NumConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NumConstant.java
new file mode 100644
index 0000000..b790210
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/NumConstant.java
@@ -0,0 +1,47 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * 常用数字常量
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2019/8/19 10:28
+ */
+public interface NumConstant {
+
+ int TWO_NEG = -2;
+ int ONE_NEG = -1;
+ int ZERO = 0;
+ int ONE = 1;
+ int TWO = 2;
+ int THREE = 3;
+ int FOUR = 4;
+ int SIX = 6;
+ int SEVEN = 7;
+ int EIGHT = 8;
+ int NINE = 9;
+ int TEN = 10;
+ int ELEVEN = 11;
+ int TWELVE = 12;
+
+ int FIFTEEN = 15;
+ int TWENTY = 20;
+ int THIRTY = 30;
+ int FORTY = 40;
+ int FIFTY = 50;
+ int ONE_HUNDRED = 100;
+
+ long ZERO_L = 0L;
+ long ONE_L = 1L;
+ long TWO_L = 2L;
+ long THREE_L = 3L;
+ long FOUR_L = 4L;
+
+ String ZERO_STR = "0";
+ String ONE_STR = "1";
+ String TWO_STR = "2";
+ String THREE_STR = "3";
+ String FOUR_STR = "4";
+ String FIVE_STR = "5";
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/OrganizationTypeConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/OrganizationTypeConstant.java
new file mode 100644
index 0000000..c22fe45
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/OrganizationTypeConstant.java
@@ -0,0 +1,34 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * 机构类型
+ * @Author LC
+ * @Date 2019/9/16 10:30
+ */
+public interface OrganizationTypeConstant {
+
+ /**
+ * 区党委
+ */
+ String ORG_TYPE_DISTRICT_PARTY = "district_party";
+ /**
+ * 区直部门
+ */
+ String ORG_TYPE_DISTRICT_DEPT = "district_dept";
+ /**
+ * 街道党工委
+ */
+ String ORG_TYPE_STREET_PARTY = "street_party";
+ /**
+ * 街道部门
+ */
+ String ORG_TYPE_STREET_DEPT = "street_dept";
+ /**
+ * 社区党工委
+ */
+ String ORG_TYPE_COMMUNITY_PARTY = "community_party";
+ /**
+ * 网格党支部
+ */
+ String ORG_TYPE_GRID_PARTY = "grid_party";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/PointsConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/PointsConstant.java
new file mode 100644
index 0000000..f5eb872
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/PointsConstant.java
@@ -0,0 +1,13 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/16 19:38
+ * @Description: 积分用
+ */
+public interface PointsConstant {
+ /**
+ * 手动调整积分编码
+ */
+ String ruleCode ="hand_regulation";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/ServiceConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/ServiceConstant.java
new file mode 100644
index 0000000..7dd45bf
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/ServiceConstant.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.constant;
+
+/**
+ * 微服务名称常量
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface ServiceConstant {
+ /**
+ * 系统服务
+ */
+ String EPDC_ADMIN_SERVER = "epdc-admin-server";
+ /**
+ * 授权服务
+ */
+ String EPDC_AUTH_SERVER = "epdc-auth-server";
+ /**
+ * 路由
+ */
+ String EPDC_GATEWAY_SERVER = "epdc-gateway-server";
+ /**
+ * 任务模块
+ */
+ String EPDC_JOB_SERVER = "epdc-job-server";
+ /**
+ * 消息通知模块
+ */
+ String EPDC_MESSAGE_SERVER = "epdc-message-server";
+ /**
+ * 文件对象模块
+ */
+ String EPDC_OSS_SERVER = "epdc-oss-server";
+ /**
+ * 爱心互助模块
+ */
+ String EPDC_HEART_SERVER = "epdc-heart-server";
+ /**
+ * 友邻社群模块
+ */
+ String EPDC_GROUP_SERVER = "epdc-group-server";
+ /**
+ * 新闻公告模块
+ */
+ String EPDC_NEWS_SERVER = "epdc-news-server";
+ /**
+ * 党群议事模块
+ */
+ String EPDC_EVENTS_SERVER = "epdc-events-server";
+ /**
+ * 生活服务模块
+ */
+ String EPDC_SERVICES_SERVER = "epdc-services-server";
+ /**
+ * 移动端接口模块
+ */
+ String EPDC_APP_SERVER = "epdc-app-server";
+ /**
+ * APP用户模块
+ */
+ String EPDC_USER_SERVER = "epdc-user-server";
+ /**
+ * DEMO服务
+ */
+ String EPDC_DEMO_SERVER = "epdc-demo-server";
+ /**
+ * websocket服务
+ */
+ String EPDC_WEBSOCKET_SERVER = "epdc-websocket-server";
+ /**
+ * 绩效考核模块
+ */
+ String EPDC_KPI_SERVER = "epdc-kpi-server";
+
+ /**
+ * 定制功能模块
+ */
+ String EPDC_CUSTOM_SERVER = "epdc-custom-server";
+
+ /**
+ * 积分模块
+ */
+ String EPDC_POINTS_SERVER = "epdc-points-server";
+
+ /**
+ * 开放接口模块
+ */
+ String EPDC_API_SERVER = "epdc-api-server";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/StrConstant.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/StrConstant.java
new file mode 100644
index 0000000..583d683
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/StrConstant.java
@@ -0,0 +1,41 @@
+package com.elink.esua.epdc.commons.tools.constant;
+
+import org.apache.commons.codec.CharEncoding;
+import org.springframework.http.MediaType;
+
+
+/**
+ * 字符串常量
+ *
+ * @author work@yujt.net.cn
+ * @date 2019/12/13 11:19
+ */
+public interface StrConstant {
+
+ String UTF_8 = CharEncoding.UTF_8;
+
+ String ISO_8859_1 = CharEncoding.ISO_8859_1;
+
+ String JAVASCRIPT = "javascript";
+
+ String APPLICATION_JSON_UTF8_VALUE = MediaType.APPLICATION_JSON_UTF8_VALUE;
+
+ String EXCEL_SUFFIX_2003 = ".xls";
+
+ String EXCEL_SUFFIX_2007 = ".xlsx";
+
+ /**
+ * 连字符号、短杠
+ */
+ String HYPHEN = "-";
+
+ /**
+ * 英文逗号
+ */
+ String COMMA = ",";
+
+ /**
+ * 冒号
+ */
+ String COLON = ":";
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/convert/DateConverter.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/convert/DateConverter.java
new file mode 100644
index 0000000..abf96ce
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/convert/DateConverter.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.convert;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 日期转换
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Component
+public class DateConverter implements Converter {
+ private static final Logger logger = LoggerFactory.getLogger(DateConverter.class);
+ private static List formatList = new ArrayList<>(5);
+ static {
+ formatList.add("yyyy-MM");
+ formatList.add("yyyy-MM-dd");
+ formatList.add("yyyy-MM-dd hh:mm");
+ formatList.add("yyyy-MM-dd hh:mm:ss");
+ formatList.add("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+ }
+
+ @Override
+ public Date convert(String source) {
+ String value = source.trim();
+ if (StringUtils.isEmpty(value)) {
+ return null;
+ }
+
+ if(source.matches("^\\d{4}-\\d{1,2}$")){
+ return parseDate(source, formatList.get(0));
+ }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
+ return parseDate(source, formatList.get(1));
+ }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){
+ return parseDate(source, formatList.get(2));
+ }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
+ return parseDate(source, formatList.get(3));
+ }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}.*T.*\\d{1,2}:\\d{1,2}:\\d{1,2}.*..*$")){
+ return parseDate(source, formatList.get(4));
+ } else {
+ throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
+ }
+ }
+
+ /**
+ * 格式化日期
+ * @param dateStr String 字符型日期
+ * @param format String 格式
+ * @return Date 日期
+ */
+ public Date parseDate(String dateStr, String format) {
+ Date date = null;
+ try {
+ DateFormat dateFormat = new SimpleDateFormat(format);
+ date = dateFormat.parse(dateStr);
+ } catch (Exception e) {
+ logger.error("Formatted date with date: {} and format : {} ", dateStr, format);
+ }
+ return date;
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/InterfaceLogBusinessTypeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/InterfaceLogBusinessTypeEnum.java
new file mode 100644
index 0000000..347e080
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/InterfaceLogBusinessTypeEnum.java
@@ -0,0 +1,36 @@
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/25 16:27
+ * @Description: 接口日志表业务类型枚举类
+ */
+public enum InterfaceLogBusinessTypeEnum {
+ REPORT_ITEM("1", "项目上报网格化平台"),
+ PULL_ITEM_HANDLE_PROCESS("2", "查询网格化平台处理情况"),
+ SYNC_TASK_DISPATCH("3","派遣"),
+ SYNC_TASK_END("4","结案");
+ private String value;
+ private String name;
+
+ InterfaceLogBusinessTypeEnum(String value, String name) {
+ this.value = value;
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/SuperAdminEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/SuperAdminEnum.java
new file mode 100644
index 0000000..20cf012
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/SuperAdminEnum.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * 超级管理员枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum SuperAdminEnum {
+ YES(1),
+ NO(0);
+
+ private int value;
+
+ SuperAdminEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserAuthTypeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserAuthTypeEnum.java
new file mode 100644
index 0000000..3c372e4
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserAuthTypeEnum.java
@@ -0,0 +1,35 @@
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * 用户认证类别枚举类
+ *
+ * @author rongchao
+ * @Date 19-12-19
+ */
+public enum UserAuthTypeEnum {
+
+ /**
+ * 居民认证
+ */
+ RESIDENT_AUTH("0"),
+
+ /**
+ * 党员认证
+ */
+ PARTY_AUTH("1"),
+
+ /**
+ * 志愿者认证
+ */
+ VOLUNTEER_AUTH("2");
+
+ private String value;
+
+ UserAuthTypeEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserSexEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserSexEnum.java
new file mode 100644
index 0000000..3bcc815
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserSexEnum.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * 用户性别 枚举类
+ *
+ * @author work@yujt.net.cn
+ * @date 2019/11/18 14:30
+ */
+public enum UserSexEnum {
+
+ /**
+ * 男
+ */
+ MALE("1"),
+
+ /**
+ * 女
+ */
+ FEMALE("0"),
+
+ /**
+ * 男
+ */
+ WX_MALE("1"),
+
+ /**
+ * 女
+ */
+ WX_FEMALE("2"),
+
+ /**
+ * 未知
+ */
+ WX_UNKNOWN_SEX("0");
+
+ private String sex;
+
+ UserSexEnum(String sex) {
+ this.sex = sex;
+ }
+
+ public String sex() {
+ return sex;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserTagEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserTagEnum.java
new file mode 100644
index 0000000..d347111
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/UserTagEnum.java
@@ -0,0 +1,28 @@
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/17 19:11
+ * @Description: 用户身份枚举类
+ */
+public enum UserTagEnum {
+ /**
+ * 党员
+ */
+ PARTY_MEMBER("partymember"),
+
+ /**
+ * 志愿者
+ */
+ VOLUNTEER("volunteer");
+
+ private String value;
+
+ UserTagEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/YesOrNoEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/YesOrNoEnum.java
new file mode 100644
index 0000000..ca35dc4
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/YesOrNoEnum.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.enums;
+
+/**
+ * 常用开关枚举:0否;1是
+ *
+ * @author yujintao
+ * @date 2019/8/19 10:34
+ */
+public enum YesOrNoEnum {
+ /**
+ * 是
+ */
+ YES("1"),
+ /**
+ * 否
+ */
+ NO("0");
+
+ private String value;
+
+ YesOrNoEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsBehaviorCodeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsBehaviorCodeEnum.java
new file mode 100644
index 0000000..dfaab97
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsBehaviorCodeEnum.java
@@ -0,0 +1,40 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2020/2/6 14:01
+ * @Description: 积分行为编码
+ */
+public enum PointsBehaviorCodeEnum {
+ LIKE("like", "赞"),
+ DISLIKE("dislike", "踩"),
+ SHARE("share", "分享"),
+ CLOCK("clock", "打卡"),
+ COMMENT("comment", "评论"),
+ BREAK_PROMISE("break_promise", "爽约"),
+ JOIN_ACT("join_act", "活动积分");
+
+ private String behaviorCode;
+ private String name;
+
+ PointsBehaviorCodeEnum(String behaviorCode, String name) {
+ this.behaviorCode = behaviorCode;
+ this.name = name;
+ }
+
+ public String getBehaviorCode() {
+ return behaviorCode;
+ }
+
+ public void setBehaviorCode(String behaviorCode) {
+ this.behaviorCode = behaviorCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsLimitTimeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsLimitTimeEnum.java
new file mode 100644
index 0000000..a3092ed
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsLimitTimeEnum.java
@@ -0,0 +1,27 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/13 09:43
+ * @Description: 积分规则限制时限枚举类
+ */
+public enum PointsLimitTimeEnum {
+ /**
+ * 限制时限(0-分钟,1-小时,2-日,3-月,4-年)
+ */
+ LIMIT_TIME_MINUTE("0"),
+ LIMIT_TIME_HOUR("1"),
+ LIMIT_TIME_DAY("2"),
+ LIMIT_TIME_MONTH("3"),
+ LIMIT_TIME_YEAR("4");
+
+ private String value;
+
+ PointsLimitTimeEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationEnum.java
new file mode 100644
index 0000000..6aa3fa9
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationEnum.java
@@ -0,0 +1,24 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/13 09:31
+ * @Description: 积分操作类型枚举类
+ */
+public enum PointsOperationEnum {
+ /**
+ * 规则操作类型(0-减积分,1-加积分)
+ */
+ OPERATION_TYPE_ADD("1"),
+ OPERATION_TYPE_SUBSTRACT("0");
+
+ private String operationType;
+
+ PointsOperationEnum(String operationType) {
+ this.operationType = operationType;
+ }
+
+ public String getOperationType() {
+ return operationType;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationModeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationModeEnum.java
new file mode 100644
index 0000000..c486cfb
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsOperationModeEnum.java
@@ -0,0 +1,34 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/13 09:33
+ * @Description: 积分操作方式枚举类
+ */
+public enum PointsOperationModeEnum {
+
+ /**
+ * user-用户操作
+ */
+ OPERATION_MODE_USER("user"),
+
+ /**
+ * admin-管理员操作
+ */
+ OPERATION_MODE_ADMIN("admin"),
+
+ /**
+ * sys-系统操作
+ */
+ OPERATION_MODE_SYS("sys");
+
+ private String operationMode;
+
+ PointsOperationModeEnum(String operationMode) {
+ this.operationMode = operationMode;
+ }
+
+ public String getOperationMode() {
+ return operationMode;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleAvailableEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleAvailableEnum.java
new file mode 100644
index 0000000..0ed15d1
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleAvailableEnum.java
@@ -0,0 +1,26 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/12 15:04
+ * @Description: 积分规则可用标志枚举类
+ */
+public enum PointsRuleAvailableEnum {
+
+
+ /**
+ * 可用标记(0-不可用,1-可用)
+ */
+ AVAILABLE_TRUE("1"),
+ AVAILABLE_FALSE("0");
+
+ private String value;
+
+ PointsRuleAvailableEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleCodeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleCodeEnum.java
new file mode 100644
index 0000000..280e37b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsRuleCodeEnum.java
@@ -0,0 +1,36 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2020/2/6 14:00
+ * @Description: 积分规则编码
+ */
+public enum PointsRuleCodeEnum {
+ CANCEL_ACT("cancel_act", "取消报名系统扣减积分"),
+ CONFIRM_JOIN_ACT("confirm_join_act", "参与活动确认积分");
+
+ private String ruleCode;
+ private String name;
+
+ PointsRuleCodeEnum(String ruleCode, String name) {
+ this.ruleCode = ruleCode;
+ this.name = name;
+ }
+
+ public String getRuleCode() {
+ return ruleCode;
+ }
+
+ public void setRuleCode(String ruleCode) {
+ this.ruleCode = ruleCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsUpperLimitEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsUpperLimitEnum.java
new file mode 100644
index 0000000..d65c768
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/enums/pointsenum/PointsUpperLimitEnum.java
@@ -0,0 +1,28 @@
+package com.elink.esua.epdc.commons.tools.enums.pointsenum;
+
+/**
+ * @Auther: yinzuomei
+ * @Date: 2019/12/13 09:48
+ * @Description: 积分是否有上限限制 枚举类
+ */
+public enum PointsUpperLimitEnum {
+ /**
+ * 是
+ */
+ YES("1"),
+
+ /**
+ * 否
+ */
+ NO("0");
+
+ private String value;
+
+ PointsUpperLimitEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ErrorCode.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ErrorCode.java
new file mode 100644
index 0000000..097b9ef
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ErrorCode.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.exception;
+
+/**
+ * 错误编码,由5位数字组成,前2位为模块编码,后3位为业务编码
+ *
+ * 如:10001(10代表系统模块,001代表业务代码)
+ *
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface ErrorCode {
+ int INTERNAL_SERVER_ERROR = 500;
+ int UNAUTHORIZED = 401;
+ int FORBIDDEN = 403;
+
+ int NOT_NULL = 10001;
+ int DB_RECORD_EXISTS = 10002;
+ int PARAMS_GET_ERROR = 10003;
+ int ACCOUNT_PASSWORD_ERROR = 10004;
+ int ACCOUNT_DISABLE = 10005;
+ int IDENTIFIER_NOT_NULL = 10006;
+ int CAPTCHA_ERROR = 10007;
+ int SUB_MENU_EXIST = 10008;
+ int PASSWORD_ERROR = 10009;
+ int ACCOUNT_NOT_EXIST = 10010;
+ int SUPERIOR_DEPT_ERROR = 10011;
+ int SUPERIOR_MENU_ERROR = 10012;
+ int DATA_SCOPE_PARAMS_ERROR = 10013;
+ int DEPT_SUB_DELETE_ERROR = 10014;
+ int DEPT_USER_DELETE_ERROR = 10015;
+ int JSON_FORMAT_ERROR = 10016;
+ int PARSING_ERROR = 10017;
+ int INVALID_ERROR = 10018;
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ExceptionUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ExceptionUtils.java
new file mode 100644
index 0000000..ce4b434
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/ExceptionUtils.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.exception;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Exception工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public class ExceptionUtils {
+
+ /**
+ * 获取异常信息
+ * @param ex 异常
+ * @return 返回异常信息
+ */
+ public static String getErrorStackTrace(Exception ex){
+ StringWriter sw = null;
+ PrintWriter pw = null;
+ try {
+ sw = new StringWriter();
+ pw = new PrintWriter(sw, true);
+ ex.printStackTrace(pw);
+ }finally {
+ try {
+ if(pw != null) {
+ pw.close();
+ }
+ } catch (Exception e) {
+
+ }
+ try {
+ if(sw != null) {
+ sw.close();
+ }
+ } catch (IOException e) {
+
+ }
+ }
+
+ return sw.toString();
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenException.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenException.java
new file mode 100644
index 0000000..e105f5d
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenException.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.exception;
+
+
+import com.elink.esua.epdc.commons.tools.utils.MessageUtils;
+
+/**
+ * 自定义异常
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class RenException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ private int code;
+ private String msg;
+
+ public RenException(int code) {
+ this.code = code;
+ this.msg = MessageUtils.getMessage(code);
+ }
+
+ public RenException(int code, String... params) {
+ this.code = code;
+ this.msg = MessageUtils.getMessage(code, params);
+ }
+
+ public RenException(int code, Throwable e) {
+ super(e);
+ this.code = code;
+ this.msg = MessageUtils.getMessage(code);
+ }
+
+ public RenException(int code, Throwable e, String... params) {
+ super(e);
+ this.code = code;
+ this.msg = MessageUtils.getMessage(code, params);
+ }
+
+ public RenException(String msg) {
+ super(msg);
+ this.code = ErrorCode.INTERNAL_SERVER_ERROR;
+ this.msg = msg;
+ }
+
+ public RenException(String msg, Throwable e) {
+ super(msg, e);
+ this.code = ErrorCode.INTERNAL_SERVER_ERROR;
+ this.msg = msg;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenExceptionHandler.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenExceptionHandler.java
new file mode 100644
index 0000000..edc729d
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/exception/RenExceptionHandler.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.exception;
+
+import cn.hutool.core.map.MapUtil;
+import com.alibaba.fastjson.JSON;
+import com.elink.esua.epdc.commons.tools.config.ModuleConfig;
+import com.elink.esua.epdc.commons.tools.log.SysLogError;
+import com.elink.esua.epdc.commons.tools.log.enums.LogTypeEnum;
+import com.elink.esua.epdc.commons.tools.log.producer.LogProducer;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.utils.HttpContextUtils;
+import com.elink.esua.epdc.commons.tools.utils.IpUtils;
+import com.elink.esua.epdc.commons.tools.utils.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.Map;
+
+
+/**
+ * 异常处理器
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@RestControllerAdvice
+public class RenExceptionHandler {
+ private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class);
+ @Autowired
+ private ModuleConfig moduleConfig;
+ @Autowired
+ private LogProducer logProducer;
+
+ /**
+ * 处理自定义异常
+ */
+ @ExceptionHandler(RenException.class)
+ public Result handleRRException(RenException ex){
+ Result result = new Result();
+ result.error(ex.getCode(), ex.getMsg());
+
+ return result;
+ }
+
+ @ExceptionHandler(DuplicateKeyException.class)
+ public Result handleDuplicateKeyException(DuplicateKeyException ex){
+ Result result = new Result();
+ result.error(ErrorCode.DB_RECORD_EXISTS);
+
+ return result;
+ }
+
+ @ExceptionHandler(Exception.class)
+ public Result handleException(Exception ex){
+ logger.error(ex.getMessage(), ex);
+
+ saveLog(ex);
+
+ return new Result().error();
+ }
+
+ /**
+ * 保存异常日志
+ */
+ private void saveLog(Exception ex){
+ SysLogError log = new SysLogError();
+ log.setType(LogTypeEnum.ERROR.value());
+ log.setModule(moduleConfig.getName());
+
+ //请求相关信息
+ HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
+ log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
+ log.setRequestUri(request.getRequestURI());
+ log.setRequestMethod(request.getMethod());
+ log.setIp(IpUtils.getIpAddr(request));
+ Map params = HttpContextUtils.getParameterMap(request);
+ if(MapUtil.isNotEmpty(params)){
+ log.setRequestParams(JSON.toJSONString(params));
+ }
+
+ //登录用户ID
+ log.setCreator(SecurityUser.getUserId());
+
+ //异常信息
+ log.setErrorInfo(ExceptionUtils.getErrorStackTrace(ex));
+
+ //保存到Redis队列里
+ log.setCreateDate(new Date());
+ logProducer.saveLog(log);
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/feign/FeignConfig.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/feign/FeignConfig.java
new file mode 100644
index 0000000..03f3917
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/feign/FeignConfig.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.feign;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+
+/**
+ * Feign调用,携带header
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Configuration
+public class FeignConfig implements RequestInterceptor {
+ @Override
+ public void apply(RequestTemplate template) {
+ RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+ if (requestAttributes == null) {
+ return;
+ }
+
+ HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
+ Enumeration headerNames = request.getHeaderNames();
+ if (headerNames != null) {
+ while (headerNames.hasMoreElements()) {
+ String name = headerNames.nextElement();
+ Enumeration values = request.getHeaders(name);
+ while (values.hasMoreElements()) {
+ String value = values.nextElement();
+ template.header(name, value);
+ }
+ }
+ }
+
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/BaseLog.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/BaseLog.java
new file mode 100644
index 0000000..f23d92b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/BaseLog.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Log基类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public abstract class BaseLog implements Serializable {
+ /**
+ * 日志类型
+ */
+ private Integer type;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogError.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogError.java
new file mode 100644
index 0000000..0658feb
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogError.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log;
+
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 异常日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+@EqualsAndHashCode(callSuper=false)
+public class SysLogError extends BaseLog {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 模块名称,如:sys
+ */
+ private String module;
+ /**
+ * 请求URI
+ */
+ private String requestUri;
+ /**
+ * 请求方式
+ */
+ private String requestMethod;
+ /**
+ * 请求参数
+ */
+ private String requestParams;
+ /**
+ * 用户代理
+ */
+ private String userAgent;
+ /**
+ * 操作IP
+ */
+ private String ip;
+ /**
+ * 异常信息
+ */
+ private String errorInfo;
+ /**
+ * 创建者
+ */
+ private Long creator;
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogLogin.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogLogin.java
new file mode 100644
index 0000000..9d5d81a
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogLogin.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 登录日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+@EqualsAndHashCode(callSuper=false)
+public class SysLogLogin extends BaseLog {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 用户操作 0:用户登录 1:用户退出
+ */
+ private Integer operation;
+ /**
+ * 状态 0:失败 1:成功 2:账号已锁定
+ */
+ private Integer status;
+ /**
+ * 用户代理
+ */
+ private String userAgent;
+ /**
+ * 操作IP
+ */
+ private String ip;
+ /**
+ * 用户名
+ */
+ private String creatorName;
+ /**
+ * 创建者
+ */
+ private Long creator;
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogOperation.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogOperation.java
new file mode 100644
index 0000000..2b04dc7
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/SysLogOperation.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 操作日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+@EqualsAndHashCode(callSuper=false)
+public class SysLogOperation extends BaseLog {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 模块名称,如:sys
+ */
+ private String module;
+ /**
+ * 用户操作
+ */
+ private String operation;
+ /**
+ * 请求URI
+ */
+ private String requestUri;
+ /**
+ * 请求方式
+ */
+ private String requestMethod;
+ /**
+ * 请求参数
+ */
+ private String requestParams;
+ /**
+ * 请求时长(毫秒)
+ */
+ private Integer requestTime;
+ /**
+ * 用户代理
+ */
+ private String userAgent;
+ /**
+ * 操作IP
+ */
+ private String ip;
+ /**
+ * 状态 0:失败 1:成功
+ */
+ private Integer status;
+ /**
+ * 用户名
+ */
+ private String creatorName;
+ /**
+ * 创建者
+ */
+ private Long creator;
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LogTypeEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LogTypeEnum.java
new file mode 100644
index 0000000..2e43a1b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LogTypeEnum.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log.enums;
+
+/**
+ * 日志类型枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum LogTypeEnum {
+ /**
+ * 登录日志
+ */
+ LOGIN(0),
+ /**
+ * 操作日志
+ */
+ OPERATION(1),
+ /**
+ * 异常日志
+ */
+ ERROR(2);
+
+ private int value;
+
+ LogTypeEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginOperationEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginOperationEnum.java
new file mode 100644
index 0000000..33ff00e
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginOperationEnum.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log.enums;
+
+/**
+ * 登录操作枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum LoginOperationEnum {
+ /**
+ * 用户登录
+ */
+ LOGIN(0),
+ /**
+ * 用户退出
+ */
+ LOGOUT(1);
+
+ private int value;
+
+ LoginOperationEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginStatusEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginStatusEnum.java
new file mode 100644
index 0000000..91e0237
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/LoginStatusEnum.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log.enums;
+
+/**
+ * 登录状态枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum LoginStatusEnum {
+ /**
+ * 失败
+ */
+ FAIL(0),
+ /**
+ * 成功
+ */
+ SUCCESS(1),
+ /**
+ * 账号已锁定
+ */
+ LOCK(2);
+
+ private int value;
+
+ LoginStatusEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/OperationStatusEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/OperationStatusEnum.java
new file mode 100644
index 0000000..b695db8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/enums/OperationStatusEnum.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log.enums;
+
+/**
+ * 操作状态枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum OperationStatusEnum {
+ /**
+ * 失败
+ */
+ FAIL(0),
+ /**
+ * 成功
+ */
+ SUCCESS(1);
+
+ private int value;
+
+ OperationStatusEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/producer/LogProducer.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/producer/LogProducer.java
new file mode 100644
index 0000000..eee6a50
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/log/producer/LogProducer.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.log.producer;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.elink.esua.epdc.commons.tools.log.BaseLog;
+import com.elink.esua.epdc.commons.tools.redis.RedisKeys;
+import com.elink.esua.epdc.commons.tools.redis.RedisUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.*;
+
+/**
+ * 日志通过redis队列,异步保存到数据库
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class LogProducer {
+ @Autowired
+ private RedisUtils redisUtils;
+ ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("log-producer-pool-%d").build();
+ ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L,TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
+
+ /**
+ * 保存Log到Redis消息队列
+ */
+ public void saveLog(BaseLog log){
+ String key = RedisKeys.getSysLogKey();
+
+ //异步保存到队列
+ pool.execute(() -> redisUtils.leftPush(key, log, RedisUtils.NOT_EXPIRE));
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/page/PageData.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/page/PageData.java
new file mode 100644
index 0000000..53641a8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/page/PageData.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.page;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public class PageData implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 总记录数
+ */
+ private int total;
+
+ /**
+ * 列表数据
+ */
+ private List list;
+
+ /**
+ * 分页
+ * @param list 列表数据
+ * @param total 总记录数
+ */
+ public PageData(List list, long total) {
+ this.list = list;
+ this.total = (int) total;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisConfig.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisConfig.java
new file mode 100644
index 0000000..81d9873
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisConfig.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.redis;
+
+import com.elink.esua.epdc.commons.tools.redis.serializer.JsonRedisSerializer;
+import com.elink.esua.epdc.commons.tools.redis.serializer.JsonRedisSerializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import javax.annotation.Resource;
+
+/**
+ * Redis配置
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Configuration
+public class RedisConfig {
+ @Resource
+ private RedisConnectionFactory factory;
+
+ @Bean
+ public RedisTemplate redisTemplate() {
+ RedisTemplate redisTemplate = new RedisTemplate<>();
+ redisTemplate.setKeySerializer(new StringRedisSerializer());
+ redisTemplate.setValueSerializer(new JsonRedisSerializer<>(Object.class));
+ redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+ redisTemplate.setHashValueSerializer(new JsonRedisSerializer<>(Object.class));
+ redisTemplate.setConnectionFactory(factory);
+
+ return redisTemplate;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisKeys.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisKeys.java
new file mode 100644
index 0000000..16bc967
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisKeys.java
@@ -0,0 +1,236 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.redis;
+
+/**
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class RedisKeys {
+
+ /**
+ * 党建redis前缀
+ */
+ private static String rootPrefix = "epdc:";
+
+ /**
+ * 系统参数Key
+ */
+ public static String getSysParamsKey() {
+ return rootPrefix.concat("sys:params");
+ }
+
+ /**
+ * 登录验证码Key
+ */
+ public static String getLoginCaptchaKey(String uuid) {
+ return rootPrefix.concat("sys:captcha:").concat(uuid);
+ }
+
+ /**
+ * 登录用户Key
+ */
+ public static String getSecurityUserKey(Long id) {
+ return rootPrefix.concat("sys:security:user:").concat(String.valueOf(id));
+ }
+
+ /**
+ * 系统日志Key
+ */
+ public static String getSysLogKey() {
+ return rootPrefix.concat("sys:log");
+ }
+
+ /**
+ * 系统资源Key
+ */
+ public static String getSysResourceKey() {
+ return rootPrefix.concat("sys:resource");
+ }
+
+ /**
+ * 用户菜单导航Key
+ */
+ public static String getUserMenuNavKey(Long userId, String language) {
+ return rootPrefix.concat("sys:user:nav:").concat(String.valueOf(userId)).concat("_").concat(language);
+ }
+
+ /**
+ * 用户菜单导航Key
+ */
+ public static String getUserMenuNavKey(Long userId) {
+ return rootPrefix.concat("sys:user:nav:").concat(String.valueOf(userId)).concat("_*");
+ }
+
+ /**
+ * 用户权限标识Key
+ */
+ public static String getUserPermissionsKey(Long userId) {
+ return rootPrefix.concat("sys:user:permissions:").concat(String.valueOf(userId));
+ }
+
+ public static String getCpUserKey(String id) {
+ return rootPrefix.concat("sys:security:cpuser:").concat(id);
+ }
+
+ /**
+ * 获取简要区划信息key
+ *
+ * @param areaId 行政区划ID
+ * @return java.lang.String
+ * @author yujintao
+ * @date 2019/9/3 16:28
+ */
+ public static String getSimpleAreaKey(String areaId) {
+ return rootPrefix.concat("config:simple:area:").concat(areaId);
+ }
+
+ /**
+ * 获取简要数据字典key
+ *
+ * @param dictType 数据字典类型
+ * @return java.lang.String
+ * @author yujintao
+ * @date 2019/9/3 16:28
+ */
+ public static String getSimpleDictKey(String dictType) {
+ return rootPrefix.concat("config:simple:dict:").concat(dictType);
+ }
+
+ /**
+ * 拼接手机验证码key
+ *
+ * @param phone
+ * @return java.lang.String
+ * @author yujintao
+ * @date 2019/9/6 17:03
+ */
+ public static String getPhoneSmsCodeKey(String phone) {
+ return rootPrefix.concat("phone:sms:code:").concat(phone);
+ }
+
+ /**
+ * 用户请求发送短信接口,记录本次请求时间,保存一分钟
+ *
+ * @param phone
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/12/6 19:05
+ */
+ public static String getPhoneSmsHistoryKey(String phone) {
+ return rootPrefix.concat("phone:sms:history:").concat(phone);
+ }
+
+ /**
+ * 管理员有数据权限的部门层级关系
+ *
+ * @param userId 用户id
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/11/28 09:56
+ */
+ public static String getAdminUserDeptOptionKey(Long userId) {
+ return rootPrefix.concat("options:dept:user:").concat(String.valueOf(userId));
+ }
+
+ /**
+ * 管理员完整部门层级关系
+ *
+ * @param userId 用户id
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/11/28 09:56
+ */
+ public static String getAllAdminUserDeptOptionKey(Long userId) {
+ return rootPrefix.concat("options:dept:user:all:").concat(String.valueOf(userId));
+ }
+
+ /**
+ * 存放部门层级关系,主要用于获取拼接后的部门id和部门名称
+ *
+ * @param deptId
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/12/20 20:34
+ */
+ public static String getDeptOptionKey(Long deptId) {
+ return rootPrefix.concat("options:dept:common:").concat(String.valueOf(deptId));
+ }
+
+ /**
+ * 事件分类
+ */
+ public static String getEventsCategoryKey() {
+ return rootPrefix.concat("options:category:events");
+ }
+
+ /***
+ * 部门所有层级关系
+ * @param
+ * @return java.lang.String
+ * @author qushutong
+ * @date 2019/12/13 15:03
+ */
+ public static String getAllDeptOptionKey() {
+ return rootPrefix.concat("options:dept:all:");
+ }
+
+ /**
+ * @param
+ * @return java.lang.String
+ * @Author yinzuomei
+ * @Description 部门所有层级关系-二级只要街道党工委
+ * @Date 2020/1/31 11:39
+ **/
+ public static String getAllDeptOptionKeyForEpiDemic() {
+ return rootPrefix.concat("options:dept:epidemic:all:");
+ }
+
+ /**
+ * @Author wanggongfeng
+ * @Description常用语
+ */
+ public static String getPhraseListKey() {
+ return rootPrefix.concat("heart:phrase:list");
+ }
+
+ /**
+ * @param ruleCode 积分规则编码
+ * @return java.lang.String
+ * @Author yinzuomei
+ * @Description 积分规则
+ * @Date 2019/12/12 10:02
+ **/
+ public static String getPointsRuleKey(String ruleCode) {
+ return rootPrefix.concat("config:points:rule:").concat(ruleCode);
+ }
+
+ /**
+ * 按项目分类设置项目响应/关闭时限
+ *
+ * @param categoryId
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/12/20 20:38
+ */
+ public static String getKpiItemTimeLimitKey(String categoryId) {
+ return rootPrefix.concat("config:kpi:itemtimelimit:").concat(categoryId);
+ }
+
+ /**
+ * 存储议题响应/关闭时限
+ *
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/12/20 20:39
+ */
+ public static String getKpiIssueTimeLimitKey() {
+ return rootPrefix.concat("config:kpi:itemtimelimit");
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisUtils.java
new file mode 100644
index 0000000..a91c333
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/RedisUtils.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Redis工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class RedisUtils {
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ /**
+ * 默认过期时长为24小时,单位:秒
+ */
+ public final static long DEFAULT_EXPIRE = 60 * 60 * 24L;
+ /**
+ * 过期时长为1小时,单位:秒
+ */
+ public final static long HOUR_ONE_EXPIRE = 60 * 60 * 1L;
+ /**
+ * 过期时长为6小时,单位:秒
+ */
+ public final static long HOUR_SIX_EXPIRE = 60 * 60 * 6L;
+ /**
+ * 过期时长为5分钟,单位:秒
+ */
+ public final static long MINUTE_FIVE_EXPIRE = 60 * 5 * 1L;
+ /**
+ * 过期时长为1分钟,单位:秒
+ */
+ public final static long MINUTE_ONE_EXPIRE = 60 * 1 * 1L;
+ /**
+ * 过期时长为10分钟,单位:秒
+ */
+ public final static long MINUTE_TEN_EXPIRE = 60 * 10 * 1L;
+ /**
+ * 过期时长为30分钟,单位:秒
+ */
+ public final static long MINUTE_THIRTY_EXPIRE = 60 * 30 * 1L;
+ /**
+ * 不设置过期时长
+ */
+ public final static long NOT_EXPIRE = -1L;
+
+ public void set(String key, Object value, long expire) {
+ redisTemplate.opsForValue().set(key, value);
+ if (expire != NOT_EXPIRE) {
+ expire(key, expire);
+ }
+ }
+
+ public void set(String key, Object value) {
+ set(key, value, DEFAULT_EXPIRE);
+ }
+
+ public Object get(String key, long expire) {
+ Object value = redisTemplate.opsForValue().get(key);
+ if (expire != NOT_EXPIRE) {
+ expire(key, expire);
+ }
+ return value;
+ }
+
+ public Object get(String key) {
+ return get(key, NOT_EXPIRE);
+ }
+
+ public Set keys(String pattern) {
+ return redisTemplate.keys(pattern);
+ }
+
+ public void deleteByPattern(String pattern) {
+ redisTemplate.delete(keys(pattern));
+ }
+
+ public void delete(String key) {
+ redisTemplate.delete(key);
+ }
+
+ public void delete(Collection keys) {
+ redisTemplate.delete(keys);
+ }
+
+ public Object hGet(String key, String field) {
+ return redisTemplate.opsForHash().get(key, field);
+ }
+
+ public Map hGetAll(String key) {
+ HashOperations hashOperations = redisTemplate.opsForHash();
+ return hashOperations.entries(key);
+ }
+
+ public void hMSet(String key, Map map) {
+ hMSet(key, map, DEFAULT_EXPIRE);
+ }
+
+ public void hMSet(String key, Map map, long expire) {
+ redisTemplate.opsForHash().putAll(key, map);
+
+ if (expire != NOT_EXPIRE) {
+ expire(key, expire);
+ }
+ }
+
+ public void hSet(String key, String field, Object value) {
+ hSet(key, field, value, DEFAULT_EXPIRE);
+ }
+
+ public void hSet(String key, String field, Object value, long expire) {
+ redisTemplate.opsForHash().put(key, field, value);
+
+ if (expire != NOT_EXPIRE) {
+ expire(key, expire);
+ }
+ }
+
+ public boolean expire(String key, long expire) {
+ return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
+ }
+
+ public long getExpire(String key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ public void hDel(String key, Object... fields) {
+ redisTemplate.opsForHash().delete(key, fields);
+ }
+
+ public void leftPush(String key, Object value) {
+ leftPush(key, value, DEFAULT_EXPIRE);
+ }
+
+ public void leftPush(String key, Object value, long expire) {
+ redisTemplate.opsForList().leftPush(key, value);
+
+ if (expire != NOT_EXPIRE) {
+ expire(key, expire);
+ }
+ }
+
+ public Object rightPop(String key) {
+ return redisTemplate.opsForList().rightPop(key);
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/UserDetailRedis.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/UserDetailRedis.java
new file mode 100644
index 0000000..afb4258
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/UserDetailRedis.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.redis;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.map.MapUtil;
+import com.elink.esua.epdc.commons.tools.security.enums.UserKillEnum;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import com.elink.esua.epdc.commons.tools.security.enums.UserKillEnum;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 用户Redis
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class UserDetailRedis {
+ @Autowired
+ private RedisUtils redisUtils;
+
+ public void set(UserDetail user, long expire) {
+ if (user == null) {
+ return;
+ }
+ String key = RedisKeys.getSecurityUserKey(user.getId());
+ //bean to map
+ user.setKill(UserKillEnum.NO.value());
+ Map map = BeanUtil.beanToMap(user, false, true);
+ redisUtils.hMSet(key, map, expire);
+
+ //用户登录时,清空菜单导航、权限标识
+ redisUtils.delete(RedisKeys.getUserMenuNavKey(user.getId()));
+ redisUtils.delete(RedisKeys.getUserPermissionsKey(user.getId()));
+ }
+
+ public UserDetail get(Long id) {
+ String key = RedisKeys.getSecurityUserKey(id);
+
+ Map map = redisUtils.hGetAll(key);
+ if (MapUtil.isEmpty(map)) {
+ return null;
+ }
+
+ //map to bean
+ UserDetail user = BeanUtil.mapToBean(map, UserDetail.class, true);
+
+ return user;
+ }
+
+ /**
+ * 用户退出
+ * @param id 用户ID
+ */
+ public void logout(Long id) {
+ String key = RedisKeys.getSecurityUserKey(id);
+ redisUtils.hSet(key, "kill", UserKillEnum.YES.value());
+
+ //清空菜单导航、权限标识
+ redisUtils.deleteByPattern(RedisKeys.getUserMenuNavKey(id));
+ redisUtils.delete(RedisKeys.getUserPermissionsKey(id));
+ redisUtils.delete(RedisKeys.getAdminUserDeptOptionKey(id));
+ redisUtils.delete(RedisKeys.getAllAdminUserDeptOptionKey(id));
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/serializer/JsonRedisSerializer.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/serializer/JsonRedisSerializer.java
new file mode 100644
index 0000000..bb36feb
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/redis/serializer/JsonRedisSerializer.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.redis.serializer;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.util.IOUtils;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+
+/**
+ * Redis序列化
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class JsonRedisSerializer implements RedisSerializer {
+ private static ParserConfig defaultRedisConfig = new ParserConfig();
+ static {
+ defaultRedisConfig.setAutoTypeSupport(true);
+ }
+
+ private Class type;
+
+ public JsonRedisSerializer(Class type) {
+ this.type = type;
+ }
+
+ @Override
+ public byte[] serialize(T t) throws SerializationException {
+ if (t == null) {
+ return new byte[0];
+ }
+ return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(IOUtils.UTF8);
+ }
+
+ @Override
+ public T deserialize(byte[] bytes) throws SerializationException {
+ if (bytes == null || bytes.length <= 0) {
+ return null;
+ }
+ String str = new String(bytes, IOUtils.UTF8);
+
+ return JSON.parseObject(str, type, defaultRedisConfig);
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/bo/ResourceBO.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/bo/ResourceBO.java
new file mode 100644
index 0000000..09b7e38
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/bo/ResourceBO.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.bo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 资源
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public class ResourceBO implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 资源URL
+ */
+ private String resourceUrl;
+ /**
+ * 请求方式(如:GET、POST、PUT、DELETE)
+ */
+ private String resourceMethod;
+ /**
+ * 认证等级 0:权限认证 1:登录认证 2:无需认证
+ */
+ private Integer authLevel;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/config/WebMvcConfig.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/config/WebMvcConfig.java
new file mode 100644
index 0000000..c0b8038
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/config/WebMvcConfig.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.config;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.serializer.ToStringSerializer;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import com.elink.esua.epdc.commons.tools.security.resolver.UserDetailHandlerMethodArgumentResolver;
+import com.google.common.collect.Lists;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.ByteArrayHttpMessageConverter;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.ResourceHttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+/**
+ * MVC配置
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+ @Autowired
+ private UserDetailHandlerMethodArgumentResolver userDetailHandlerMethodArgumentResolver;
+
+ @Override
+ public void addArgumentResolvers(List argumentResolvers) {
+ argumentResolvers.add(userDetailHandlerMethodArgumentResolver);
+ }
+
+ @Override
+ public void configureMessageConverters(List> converters) {
+ converters.add(new ByteArrayHttpMessageConverter());
+ converters.add(new StringHttpMessageConverter());
+ converters.add(new ResourceHttpMessageConverter());
+ converters.add(new AllEncompassingFormHttpMessageConverter());
+ converters.add(new StringHttpMessageConverter());
+ converters.add(fastJsonHttpMessageConverters());
+ }
+
+ @Bean
+ public FastJsonHttpMessageConverter fastJsonHttpMessageConverters() {
+ //创建fastJson消息转换器
+ FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
+
+ //升级最新版本需加=============================================================
+ List supportedMediaTypes = Lists.newArrayList();
+ supportedMediaTypes.add(MediaType.APPLICATION_JSON);
+ supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
+ supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
+ supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
+ supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
+ supportedMediaTypes.add(MediaType.APPLICATION_PDF);
+ supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
+ supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
+ supportedMediaTypes.add(MediaType.APPLICATION_XML);
+ supportedMediaTypes.add(MediaType.IMAGE_GIF);
+ supportedMediaTypes.add(MediaType.IMAGE_JPEG);
+ supportedMediaTypes.add(MediaType.IMAGE_PNG);
+ supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
+ supportedMediaTypes.add(MediaType.TEXT_HTML);
+ supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
+ supportedMediaTypes.add(MediaType.TEXT_PLAIN);
+ supportedMediaTypes.add(MediaType.TEXT_XML);
+ fastConverter.setSupportedMediaTypes(supportedMediaTypes);
+
+ //创建配置类
+ FastJsonConfig fastJsonConfig = new FastJsonConfig();
+ //修改配置返回内容的过滤
+ //WriteNullListAsEmpty :List字段如果为null,输出为[],而非null
+ //WriteNullStringAsEmpty : 字符类型字段如果为null,输出为"",而非null
+ //DisableCircularReferenceDetect :消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
+ //WriteNullBooleanAsFalse:Boolean字段如果为null,输出为false,而非null
+ //WriteMapNullValue:是否输出值为null的字段,默认为false
+ fastJsonConfig.setSerializerFeatures(
+ SerializerFeature.WriteMapNullValue,
+ SerializerFeature.WriteNullListAsEmpty,
+ SerializerFeature.WriteNullStringAsEmpty,
+ SerializerFeature.WriteNullBooleanAsFalse,
+ SerializerFeature.PrettyFormat,
+ SerializerFeature.DisableCircularReferenceDetect,
+ SerializerFeature.WriteDateUseDateFormat,
+ SerializerFeature.WriteNullNumberAsZero
+ );
+ fastJsonConfig.getSerializeConfig().put(Long.class, ToStringSerializer.instance);
+ fastConverter.setFastJsonConfig(fastJsonConfig);
+ return fastConverter;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/ResourceAuthEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/ResourceAuthEnum.java
new file mode 100644
index 0000000..097f3b0
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/ResourceAuthEnum.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.enums;
+
+/**
+ * 资源认证枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum ResourceAuthEnum {
+ /**
+ * 权限认证
+ */
+ PERMISSIONS_AUTH(0),
+ /**
+ * 登录认证
+ */
+ LOGIN_AUTH(1),
+ /**
+ * 无需认证
+ */
+ NO_AUTH(2);
+
+
+ private int value;
+
+ ResourceAuthEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/UserKillEnum.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/UserKillEnum.java
new file mode 100644
index 0000000..444c304
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/enums/UserKillEnum.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.enums;
+
+/**
+ * 用户被踢出枚举
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public enum UserKillEnum {
+ YES(1),
+ NO(0);
+
+ private int value;
+
+ UserKillEnum(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCrypt.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCrypt.java
new file mode 100644
index 0000000..d2b9f92
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCrypt.java
@@ -0,0 +1,663 @@
+package com.elink.esua.epdc.commons.tools.security.password;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+
+import java.security.SecureRandom;
+
+/**
+ * BCrypt implements OpenBSD-style Blowfish password hashing using the scheme described in
+ * "A Future-Adaptable Password Scheme" by Niels Provos and David Mazieres.
+ *
+ * This password hashing system tries to thwart off-line password cracking using a
+ * computationally-intensive hashing algorithm, based on Bruce Schneier's Blowfish cipher.
+ * The work factor of the algorithm is parameterised, so it can be increased as computers
+ * get faster.
+ *
+ * Usage is really simple. To hash a password for the first time, call the hashpw method
+ * with a random salt, like this:
+ *
+ *
+ * String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt());
+ *
+ *
+ * To check whether a plaintext password matches one that has been hashed previously, use
+ * the checkpw method:
+ *
+ *
+ * if (BCrypt.checkpw(candidate_password, stored_hash))
+ * System.out.println("It matches");
+ * else
+ * System.out.println("It does not match");
+ *
+ *
+ * The gensalt() method takes an optional parameter (log_rounds) that determines the
+ * computational complexity of the hashing:
+ *
+ *
+ * String strong_salt = BCrypt.gensalt(10)
+ * String stronger_salt = BCrypt.gensalt(12)
+ *
+ *
+ * The amount of work increases exponentially (2**log_rounds), so each increment is twice
+ * as much work. The default log_rounds is 10, and the valid range is 4 to 31.
+ *
+ * @author Damien Miller
+ */
+public class BCrypt {
+ // BCrypt parameters
+
+ private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
+ private static final int BCRYPT_SALT_LEN = 16;
+ // Blowfish parameters
+ private static final int BLOWFISH_NUM_ROUNDS = 16;
+ // Initial contents of key schedule
+ private static final int P_orig[] = { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
+ 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b };
+ private static final int S_orig[] = { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,
+ 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5,
+ 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27,
+ 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993,
+ 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af,
+ 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5,
+ 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68,
+ 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4,
+ 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248,
+ 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4,
+ 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd,
+ 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc,
+ 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0,
+ 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8,
+ 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01,
+ 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64,
+ 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8,
+ 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86,
+ 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e,
+ 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a,
+ 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6,
+ 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+ 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+ 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+ 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+ 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+ 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+ 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+ 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+ 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+ 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+ 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+ 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+ 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+ 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+ 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+ 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+ 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7,
+ 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546,
+ 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941,
+ 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c,
+ 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856,
+ 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87,
+ 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70,
+ 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1,
+ 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1,
+ 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa,
+ 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37,
+ 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24,
+ 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7,
+ 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f,
+ 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71,
+ 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74,
+ 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0,
+ 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df,
+ 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641,
+ 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de,
+ 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5,
+ 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212,
+ 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315,
+ 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d,
+ 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6,
+ 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da,
+ 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d,
+ 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc,
+ 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2,
+ 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8,
+ 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46,
+ 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40,
+ 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e,
+ 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d,
+ 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b,
+ 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667,
+ 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb,
+ 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df,
+ 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891,
+ 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5,
+ 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00,
+ 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76,
+ 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0,
+ 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 };
+ // bcrypt IV: "OrpheanBeholderScryDoubt"
+ static private final int bf_crypt_ciphertext[] = { 0x4f727068, 0x65616e42,
+ 0x65686f6c, 0x64657253, 0x63727944, 0x6f756274 };
+ // Table for Base64 encoding
+ static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+ 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+ 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+ // Table for Base64 decoding
+ static private final byte index_64[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1 };
+ static final int MIN_LOG_ROUNDS = 4;
+ static final int MAX_LOG_ROUNDS = 31;
+ // Expanded Blowfish key
+ private int P[];
+ private int S[];
+
+ /**
+ * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note
+ * that this is not compatible with the standard MIME-base64
+ * encoding.
+ *
+ * @param d the byte array to encode
+ * @param len the number of bytes to encode
+ * @param rs the destination buffer for the base64-encoded string
+ * @exception IllegalArgumentException if the length is invalid
+ */
+ static void encode_base64(byte d[], int len, StringBuilder rs)
+ throws IllegalArgumentException {
+ int off = 0;
+ int c1, c2;
+
+ if (len <= 0 || len > d.length) {
+ throw new IllegalArgumentException("Invalid len");
+ }
+
+ while (off < len) {
+ c1 = d[off++] & 0xff;
+ rs.append(base64_code[(c1 >> 2) & 0x3f]);
+ c1 = (c1 & 0x03) << 4;
+ if (off >= len) {
+ rs.append(base64_code[c1 & 0x3f]);
+ break;
+ }
+ c2 = d[off++] & 0xff;
+ c1 |= (c2 >> 4) & 0x0f;
+ rs.append(base64_code[c1 & 0x3f]);
+ c1 = (c2 & 0x0f) << 2;
+ if (off >= len) {
+ rs.append(base64_code[c1 & 0x3f]);
+ break;
+ }
+ c2 = d[off++] & 0xff;
+ c1 |= (c2 >> 6) & 0x03;
+ rs.append(base64_code[c1 & 0x3f]);
+ rs.append(base64_code[c2 & 0x3f]);
+ }
+ }
+
+ /**
+ * Look up the 3 bits base64-encoded by the specified character, range-checking
+ * against conversion table
+ * @param x the base64-encoded value
+ * @return the decoded value of x
+ */
+ private static byte char64(char x) {
+ if (x > index_64.length) {
+ return -1;
+ }
+ return index_64[x];
+ }
+
+ /**
+ * Decode a string encoded using bcrypt's base64 scheme to a byte array. Note that
+ * this is *not* compatible with the standard MIME-base64 encoding.
+ * @param s the string to decode
+ * @param maxolen the maximum number of bytes to decode
+ * @return an array containing the decoded bytes
+ * @throws IllegalArgumentException if maxolen is invalid
+ */
+ static byte[] decode_base64(String s, int maxolen) throws IllegalArgumentException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream(maxolen);
+ int off = 0, slen = s.length(), olen = 0;
+ byte c1, c2, c3, c4, o;
+
+ if (maxolen <= 0) {
+ throw new IllegalArgumentException("Invalid maxolen");
+ }
+
+ while (off < slen - 1 && olen < maxolen) {
+ c1 = char64(s.charAt(off++));
+ c2 = char64(s.charAt(off++));
+ if (c1 == -1 || c2 == -1) {
+ break;
+ }
+ o = (byte) (c1 << 2);
+ o |= (c2 & 0x30) >> 4;
+ out.write(o);
+ if (++olen >= maxolen || off >= slen) {
+ break;
+ }
+ c3 = char64(s.charAt(off++));
+ if (c3 == -1) {
+ break;
+ }
+ o = (byte) ((c2 & 0x0f) << 4);
+ o |= (c3 & 0x3c) >> 2;
+ out.write(o);
+ if (++olen >= maxolen || off >= slen) {
+ break;
+ }
+ c4 = char64(s.charAt(off++));
+ o = (byte) ((c3 & 0x03) << 6);
+ o |= c4;
+ out.write(o);
+ ++olen;
+ }
+
+ return out.toByteArray();
+ }
+
+ /**
+ * Blowfish encipher a single 64-bit block encoded as two 32-bit halves
+ * @param lr an array containing the two 32-bit half blocks
+ * @param off the position in the array of the blocks
+ */
+ private final void encipher(int lr[], int off) {
+ int i, n, l = lr[off], r = lr[off + 1];
+
+ l ^= P[0];
+ for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
+ // Feistel substitution on left word
+ n = S[(l >> 24) & 0xff];
+ n += S[0x100 | ((l >> 16) & 0xff)];
+ n ^= S[0x200 | ((l >> 8) & 0xff)];
+ n += S[0x300 | (l & 0xff)];
+ r ^= n ^ P[++i];
+
+ // Feistel substitution on right word
+ n = S[(r >> 24) & 0xff];
+ n += S[0x100 | ((r >> 16) & 0xff)];
+ n ^= S[0x200 | ((r >> 8) & 0xff)];
+ n += S[0x300 | (r & 0xff)];
+ l ^= n ^ P[++i];
+ }
+ lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
+ lr[off + 1] = l;
+ }
+
+ /**
+ * Cycically extract a word of key material
+ * @param data the string to extract the data from
+ * @param offp a "pointer" (as a one-entry array) to the current offset into data
+ * @return the next word of material from data
+ */
+ private static int streamtoword(byte data[], int offp[]) {
+ int i;
+ int word = 0;
+ int off = offp[0];
+
+ for (i = 0; i < 4; i++) {
+ word = (word << 8) | (data[off] & 0xff);
+ off = (off + 1) % data.length;
+ }
+
+ offp[0] = off;
+ return word;
+ }
+
+ /**
+ * Initialise the Blowfish key schedule
+ */
+ private void init_key() {
+ P = (int[]) P_orig.clone();
+ S = (int[]) S_orig.clone();
+ }
+
+ /**
+ * Key the Blowfish cipher
+ * @param key an array containing the key
+ */
+ private void key(byte key[]) {
+ int i;
+ int koffp[] = { 0 };
+ int lr[] = { 0, 0 };
+ int plen = P.length, slen = S.length;
+
+ for (i = 0; i < plen; i++) {
+ P[i] = P[i] ^ streamtoword(key, koffp);
+ }
+
+ for (i = 0; i < plen; i += 2) {
+ encipher(lr, 0);
+ P[i] = lr[0];
+ P[i + 1] = lr[1];
+ }
+
+ for (i = 0; i < slen; i += 2) {
+ encipher(lr, 0);
+ S[i] = lr[0];
+ S[i + 1] = lr[1];
+ }
+ }
+
+ /**
+ * Perform the "enhanced key schedule" step described by Provos and Mazieres in
+ * "A Future-Adaptable Password Scheme" http://www.openbsd.org/papers/bcrypt-paper.ps
+ * @param data salt information
+ * @param key password information
+ */
+ private void ekskey(byte data[], byte key[]) {
+ int i;
+ int koffp[] = { 0 }, doffp[] = { 0 };
+ int lr[] = { 0, 0 };
+ int plen = P.length, slen = S.length;
+
+ for (i = 0; i < plen; i++) {
+ P[i] = P[i] ^ streamtoword(key, koffp);
+ }
+
+ for (i = 0; i < plen; i += 2) {
+ lr[0] ^= streamtoword(data, doffp);
+ lr[1] ^= streamtoword(data, doffp);
+ encipher(lr, 0);
+ P[i] = lr[0];
+ P[i + 1] = lr[1];
+ }
+
+ for (i = 0; i < slen; i += 2) {
+ lr[0] ^= streamtoword(data, doffp);
+ lr[1] ^= streamtoword(data, doffp);
+ encipher(lr, 0);
+ S[i] = lr[0];
+ S[i + 1] = lr[1];
+ }
+ }
+
+ static long roundsForLogRounds(int log_rounds) {
+ if (log_rounds < 4 || log_rounds > 31) {
+ throw new IllegalArgumentException("Bad number of rounds");
+ }
+ return 1L << log_rounds;
+ }
+
+ /**
+ * Perform the central password hashing step in the bcrypt scheme
+ * @param password the password to hash
+ * @param salt the binary salt to hash with the password
+ * @param log_rounds the binary logarithm of the number of rounds of hashing to apply
+ * @return an array containing the binary hashed password
+ */
+ private byte[] crypt_raw(byte password[], byte salt[], int log_rounds) {
+ int cdata[] = (int[]) bf_crypt_ciphertext.clone();
+ int clen = cdata.length;
+ byte ret[];
+
+ long rounds = roundsForLogRounds(log_rounds);
+
+ init_key();
+ ekskey(salt, password);
+ for (long i = 0; i < rounds; i++) {
+ key(password);
+ key(salt);
+ }
+
+ for (int i = 0; i < 64; i++) {
+ for (int j = 0; j < (clen >> 1); j++) {
+ encipher(cdata, j << 1);
+ }
+ }
+
+ ret = new byte[clen * 4];
+ for (int i = 0, j = 0; i < clen; i++) {
+ ret[j++] = (byte) ((cdata[i] >> 24) & 0xff);
+ ret[j++] = (byte) ((cdata[i] >> 16) & 0xff);
+ ret[j++] = (byte) ((cdata[i] >> 8) & 0xff);
+ ret[j++] = (byte) (cdata[i] & 0xff);
+ }
+ return ret;
+ }
+
+ /**
+ * Hash a password using the OpenBSD bcrypt scheme
+ * @param password the password to hash
+ * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
+ * @return the hashed password
+ * @throws IllegalArgumentException if invalid salt is passed
+ */
+ public static String hashpw(String password, String salt) throws IllegalArgumentException {
+ BCrypt B;
+ String real_salt;
+ byte passwordb[], saltb[], hashed[];
+ char minor = (char) 0;
+ int rounds, off = 0;
+ StringBuilder rs = new StringBuilder();
+
+ if (salt == null) {
+ throw new IllegalArgumentException("salt cannot be null");
+ }
+
+ int saltLength = salt.length();
+
+ if (saltLength < 28) {
+ throw new IllegalArgumentException("Invalid salt");
+ }
+
+ if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
+ throw new IllegalArgumentException("Invalid salt version");
+ }
+ if (salt.charAt(2) == '$') {
+ off = 3;
+ }
+ else {
+ minor = salt.charAt(2);
+ if (minor != 'a' || salt.charAt(3) != '$') {
+ throw new IllegalArgumentException("Invalid salt revision");
+ }
+ off = 4;
+ }
+
+ if (saltLength - off < 25) {
+ throw new IllegalArgumentException("Invalid salt");
+ }
+
+ // Extract number of rounds
+ if (salt.charAt(off + 2) > '$') {
+ throw new IllegalArgumentException("Missing salt rounds");
+ }
+ rounds = Integer.parseInt(salt.substring(off, off + 2));
+
+ real_salt = salt.substring(off + 3, off + 25);
+ try {
+ passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException uee) {
+ throw new AssertionError("UTF-8 is not supported");
+ }
+
+ saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
+
+ B = new BCrypt();
+ hashed = B.crypt_raw(passwordb, saltb, rounds);
+
+ rs.append("$2");
+ if (minor >= 'a') {
+ rs.append(minor);
+ }
+ rs.append("$");
+ if (rounds < 10) {
+ rs.append("0");
+ }
+ rs.append(rounds);
+ rs.append("$");
+ encode_base64(saltb, saltb.length, rs);
+ encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);
+ return rs.toString();
+ }
+
+ /**
+ * Generate a salt for use with the BCrypt.hashpw() method
+ * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+ * factor therefore increases as 2**log_rounds. Minimum 4, maximum 31.
+ * @param random an instance of SecureRandom to use
+ * @return an encoded salt value
+ */
+ public static String gensalt(int log_rounds, SecureRandom random) {
+ if (log_rounds < MIN_LOG_ROUNDS || log_rounds > MAX_LOG_ROUNDS) {
+ throw new IllegalArgumentException("Bad number of rounds");
+ }
+ StringBuilder rs = new StringBuilder();
+ byte rnd[] = new byte[BCRYPT_SALT_LEN];
+
+ random.nextBytes(rnd);
+
+ rs.append("$2a$");
+ if (log_rounds < 10) {
+ rs.append("0");
+ }
+ rs.append(log_rounds);
+ rs.append("$");
+ encode_base64(rnd, rnd.length, rs);
+ return rs.toString();
+ }
+
+ /**
+ * Generate a salt for use with the BCrypt.hashpw() method
+ * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+ * factor therefore increases as 2**log_rounds. Minimum 4, maximum 31.
+ * @return an encoded salt value
+ */
+ public static String gensalt(int log_rounds) {
+ return gensalt(log_rounds, new SecureRandom());
+ }
+
+ /**
+ * Generate a salt for use with the BCrypt.hashpw() method, selecting a reasonable
+ * default for the number of hashing rounds to apply
+ * @return an encoded salt value
+ */
+ public static String gensalt() {
+ return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS);
+ }
+
+ /**
+ * Check that a plaintext password matches a previously hashed one
+ * @param plaintext the plaintext password to verify
+ * @param hashed the previously-hashed password
+ * @return true if the passwords match, false otherwise
+ */
+ public static boolean checkpw(String plaintext, String hashed) {
+ return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));
+ }
+
+ static boolean equalsNoEarlyReturn(String a, String b) {
+ char[] caa = a.toCharArray();
+ char[] cab = b.toCharArray();
+
+ if (caa.length != cab.length) {
+ return false;
+ }
+
+ byte ret = 0;
+ for (int i = 0; i < caa.length; i++) {
+ ret |= caa[i] ^ cab[i];
+ }
+ return ret == 0;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCryptPasswordEncoder.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCryptPasswordEncoder.java
new file mode 100644
index 0000000..6ba2e55
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/BCryptPasswordEncoder.java
@@ -0,0 +1,82 @@
+package com.elink.esua.epdc.commons.tools.security.password;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.security.SecureRandom;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients
+ * can optionally supply a "strength" (a.k.a. log rounds in BCrypt) and a SecureRandom
+ * instance. The larger the strength parameter the more work will have to be done
+ * (exponentially) to hash the passwords. The default value is 10.
+ *
+ * @author Dave Syer
+ *
+ */
+public class BCryptPasswordEncoder implements PasswordEncoder {
+ private Pattern BCRYPT_PATTERN = Pattern
+ .compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private final int strength;
+
+ private final SecureRandom random;
+
+ public BCryptPasswordEncoder() {
+ this(-1);
+ }
+
+ /**
+ * @param strength the log rounds to use, between 4 and 31
+ */
+ public BCryptPasswordEncoder(int strength) {
+ this(strength, null);
+ }
+
+ /**
+ * @param strength the log rounds to use, between 4 and 31
+ * @param random the secure random instance to use
+ *
+ */
+ public BCryptPasswordEncoder(int strength, SecureRandom random) {
+ if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {
+ throw new IllegalArgumentException("Bad strength");
+ }
+ this.strength = strength;
+ this.random = random;
+ }
+
+ @Override
+ public String encode(CharSequence rawPassword) {
+ String salt;
+ if (strength > 0) {
+ if (random != null) {
+ salt = BCrypt.gensalt(strength, random);
+ }
+ else {
+ salt = BCrypt.gensalt(strength);
+ }
+ }
+ else {
+ salt = BCrypt.gensalt();
+ }
+ return BCrypt.hashpw(rawPassword.toString(), salt);
+ }
+
+ @Override
+ public boolean matches(CharSequence rawPassword, String encodedPassword) {
+ if (encodedPassword == null || encodedPassword.length() == 0) {
+ logger.warn("Empty encoded password");
+ return false;
+ }
+
+ if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
+ logger.warn("Encoded password does not look like BCrypt");
+ return false;
+ }
+
+ return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordEncoder.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordEncoder.java
new file mode 100644
index 0000000..da8faf9
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordEncoder.java
@@ -0,0 +1,30 @@
+package com.elink.esua.epdc.commons.tools.security.password;
+
+/**
+ * Service interface for encoding passwords.
+ *
+ * The preferred implementation is {@code BCryptPasswordEncoder}.
+ *
+ * @author Keith Donald
+ */
+public interface PasswordEncoder {
+
+ /**
+ * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
+ * greater hash combined with an 8-byte or greater randomly generated salt.
+ */
+ String encode(CharSequence rawPassword);
+
+ /**
+ * Verify the encoded password obtained from storage matches the submitted raw
+ * password after it too is encoded. Returns true if the passwords match, false if
+ * they do not. The stored password itself is never decoded.
+ *
+ * @param rawPassword the raw password to encode and match
+ * @param encodedPassword the encoded password from storage to compare with
+ * @return true if the raw password, after encoding, matches the encoded password from
+ * storage
+ */
+ boolean matches(CharSequence rawPassword, String encodedPassword);
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordUtils.java
new file mode 100644
index 0000000..50d6dc8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/password/PasswordUtils.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.password;
+
+/**
+ * 密码工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class PasswordUtils {
+ private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+
+ /**
+ * 加密
+ * @param str 字符串
+ * @return 返回加密字符串
+ */
+ public static String encode(String str){
+ return passwordEncoder.encode(str);
+ }
+
+
+ /**
+ * 比较密码是否相等
+ * @param str 明文密码
+ * @param password 加密后密码
+ * @return true:成功 false:失败
+ */
+ public static boolean matches(String str, String password){
+ return passwordEncoder.matches(str, password);
+ }
+
+
+ public static void main(String[] args) {
+ String str = "admin";
+ String password = encode(str);
+
+ System.out.println(password);
+ System.out.println(matches(str, password));
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/resolver/UserDetailHandlerMethodArgumentResolver.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/resolver/UserDetailHandlerMethodArgumentResolver.java
new file mode 100644
index 0000000..4110f4b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/resolver/UserDetailHandlerMethodArgumentResolver.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.resolver;
+
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import com.elink.esua.epdc.commons.tools.security.user.SecurityUser;
+import com.elink.esua.epdc.commons.tools.security.user.UserDetail;
+import org.springframework.core.MethodParameter;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+/**
+ * 当前登录用户
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class UserDetailHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
+
+ @Override
+ public boolean supportsParameter(MethodParameter parameter) {
+ return parameter.getParameterType().isAssignableFrom(UserDetail.class);
+ }
+
+ @Override
+ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
+ NativeWebRequest request, WebDataBinderFactory factory) {
+ //获取用户信息
+ UserDetail user = SecurityUser.getUser();
+
+ return user;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/CpUserDetail.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/CpUserDetail.java
new file mode 100644
index 0000000..0ef01eb
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/CpUserDetail.java
@@ -0,0 +1,42 @@
+package com.elink.esua.epdc.commons.tools.security.user;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * APP用户详情
+ *
+ * @author rongchao
+ * @Date 19-5-13
+ */
+@Data
+public class CpUserDetail implements Serializable {
+
+ private static final long serialVersionUID = 6172109654041516399L;
+
+ /**
+ * 用户ID
+ */
+ private String id;
+
+ /**
+ * 昵称
+ */
+ private String nickname;
+
+ /**
+ * 真实姓名
+ */
+ private String realName;
+
+ /**
+ * 手机号
+ */
+ private String mobile;
+
+ /**
+ * 令牌
+ */
+ private String token;
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/SecurityUser.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/SecurityUser.java
new file mode 100644
index 0000000..c613e50
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/SecurityUser.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.user;
+
+import com.elink.esua.epdc.commons.tools.constant.Constant;
+import com.elink.esua.epdc.commons.tools.redis.UserDetailRedis;
+import com.elink.esua.epdc.commons.tools.utils.HttpContextUtils;
+import com.elink.esua.epdc.commons.tools.utils.SpringContextUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 用户
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class SecurityUser {
+ private static UserDetailRedis userDetailRedis;
+ static {
+ userDetailRedis = SpringContextUtils.getBean(UserDetailRedis.class);
+ }
+
+ /**
+ * 获取用户信息
+ */
+ public static UserDetail getUser(){
+ Long userId = getUserId();
+ if(userId == null){
+ return null;
+ }
+
+ UserDetail user = userDetailRedis.get(userId);
+ return user;
+ }
+
+ /**
+ * 获取用户ID
+ */
+ public static Long getUserId() {
+ HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
+ if(request == null){
+ return null;
+ }
+
+ String userId = request.getHeader(Constant.USER_KEY);
+ if(StringUtils.isBlank(userId)){
+ return null;
+ }
+ return Long.parseLong(userId);
+ }
+
+ /**
+ * 获取部门ID
+ */
+ public static Long getDeptId() {
+ UserDetail user = getUser();
+ if(user == null){
+ return null;
+ }
+
+ return user.getDeptId();
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/UserDetail.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/UserDetail.java
new file mode 100644
index 0000000..8c0ab64
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/security/user/UserDetail.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.security.user;
+
+import com.elink.esua.epdc.commons.tools.security.bo.ResourceBO;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 登录用户信息
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+public class UserDetail implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+ private String username;
+ private String realName;
+ private String headUrl;
+ private Integer gender;
+ private String email;
+ private String mobile;
+ private Long deptId;
+ private String deptName;
+ private String password;
+ private Integer status;
+ private Integer superAdmin;
+ /**
+ * 是否被管理员踢出 0:正常 1:被踢出,无权调用接口
+ */
+ private int kill;
+ /**
+ * 部门数据权限
+ */
+ private List deptIdList;
+ /**
+ * 用户资源列表
+ */
+ private List resourceList;
+ /**
+ * 机构类型
+ */
+ private String typeKey;
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ConvertUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ConvertUtils.java
new file mode 100644
index 0000000..7b06498
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ConvertUtils.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 转换工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class ConvertUtils {
+ private static Logger logger = LoggerFactory.getLogger(ConvertUtils.class);
+
+ public static T sourceToTarget(Object source, Class target){
+ if(source == null){
+ return null;
+ }
+ T targetObject = null;
+ try {
+ targetObject = target.newInstance();
+ BeanUtils.copyProperties(source, targetObject);
+ } catch (Exception e) {
+ logger.error("convert error ", e);
+ }
+
+ return targetObject;
+ }
+
+ public static List sourceToTarget(Collection> sourceList, Class target){
+ if(sourceList == null){
+ return null;
+ }
+
+ List targetList = new ArrayList<>(sourceList.size());
+ try {
+ for(Object source : sourceList){
+ T targetObject = target.newInstance();
+ BeanUtils.copyProperties(source, targetObject);
+ targetList.add(targetObject);
+ }
+ }catch (Exception e){
+ logger.error("convert error ", e);
+ }
+
+ return targetList;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/DateUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/DateUtils.java
new file mode 100644
index 0000000..0de5d28
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/DateUtils.java
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 日期处理工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class DateUtils {
+
+ /** 时间格式(yyyy-MM-dd) */
+ public final static String DATE_PATTERN = "yyyy-MM-dd";
+
+ /** 时间格式(yyyy-MM-dd HH:mm:ss) */
+ public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+
+ /** 时间格式(yyyyMMddHHmmss) */
+ public final static String DATE_TIME_NO_SPLIT = "yyyyMMddHHmmss";
+
+ /**
+ * 日期格式化 日期格式为:yyyy-MM-dd
+ * @param date 日期
+ * @return 返回yyyy-MM-dd格式日期
+ */
+ public static String format(Date date) {
+ return format(date, DATE_PATTERN);
+ }
+
+ /**
+ * 日期格式化 日期格式为:yyyy-MM-dd
+ * @param date 日期
+ * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
+ * @return 返回yyyy-MM-dd格式日期
+ */
+ public static String format(Date date, String pattern) {
+ if(date != null){
+ SimpleDateFormat df = new SimpleDateFormat(pattern);
+ return df.format(date);
+ }
+ return null;
+ }
+
+ /**
+ * 日期解析
+ * @param date 日期
+ * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
+ * @return 返回Date
+ */
+ public static Date parse(String date, String pattern) {
+ try {
+ return new SimpleDateFormat(pattern).parse(date);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 字符串转换成日期
+ * @param strDate 日期字符串
+ * @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
+ */
+ public static Date stringToDate(String strDate, String pattern) {
+ if (StringUtils.isBlank(strDate)){
+ return null;
+ }
+
+ DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
+ return fmt.parseLocalDateTime(strDate).toDate();
+ }
+
+ /**
+ * 根据周数,获取开始日期、结束日期
+ * @param week 周期 0本周,-1上周,-2上上周,1下周,2下下周
+ * @return 返回date[0]开始日期、date[1]结束日期
+ */
+ public static Date[] getWeekStartAndEnd(int week) {
+ DateTime dateTime = new DateTime();
+ LocalDate date = new LocalDate(dateTime.plusWeeks(week));
+
+ date = date.dayOfWeek().withMinimumValue();
+ Date beginDate = date.toDate();
+ Date endDate = date.plusDays(6).toDate();
+ return new Date[]{beginDate, endDate};
+ }
+
+ /**
+ * 对日期的【秒】进行加/减
+ *
+ * @param date 日期
+ * @param seconds 秒数,负数为减
+ * @return 加/减几秒后的日期
+ */
+ public static Date addDateSeconds(Date date, int seconds) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusSeconds(seconds).toDate();
+ }
+
+ /**
+ * 对日期的【分钟】进行加/减
+ *
+ * @param date 日期
+ * @param minutes 分钟数,负数为减
+ * @return 加/减几分钟后的日期
+ */
+ public static Date addDateMinutes(Date date, int minutes) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusMinutes(minutes).toDate();
+ }
+
+ /**
+ * 对日期的【小时】进行加/减
+ *
+ * @param date 日期
+ * @param hours 小时数,负数为减
+ * @return 加/减几小时后的日期
+ */
+ public static Date addDateHours(Date date, int hours) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusHours(hours).toDate();
+ }
+
+ /**
+ * 对日期的【天】进行加/减
+ *
+ * @param date 日期
+ * @param days 天数,负数为减
+ * @return 加/减几天后的日期
+ */
+ public static Date addDateDays(Date date, int days) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusDays(days).toDate();
+ }
+
+ /**
+ * 对日期的【周】进行加/减
+ *
+ * @param date 日期
+ * @param weeks 周数,负数为减
+ * @return 加/减几周后的日期
+ */
+ public static Date addDateWeeks(Date date, int weeks) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusWeeks(weeks).toDate();
+ }
+
+ /**
+ * 对日期的【月】进行加/减
+ *
+ * @param date 日期
+ * @param months 月数,负数为减
+ * @return 加/减几月后的日期
+ */
+ public static Date addDateMonths(Date date, int months) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusMonths(months).toDate();
+ }
+
+ /**
+ * 对日期的【年】进行加/减
+ *
+ * @param date 日期
+ * @param years 年数,负数为减
+ * @return 加/减几年后的日期
+ */
+ public static Date addDateYears(Date date, int years) {
+ DateTime dateTime = new DateTime(date);
+ return dateTime.plusYears(years).toDate();
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ExcelUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ExcelUtils.java
new file mode 100644
index 0000000..f3f675b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ExcelUtils.java
@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import cn.afterturn.easypoi.excel.ExcelExportUtil;
+import cn.afterturn.easypoi.excel.entity.ExportParams;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.BeanUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Excel工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class ExcelUtils {
+
+ /**
+ * Excel导出
+ *
+ * @param response response
+ * @param fileName 文件名
+ * @param list 数据List
+ * @param pojoClass 对象Class
+ */
+ public static void exportExcel(HttpServletResponse response, String fileName, Collection> list,
+ Class> pojoClass) throws IOException {
+ if(StringUtils.isBlank(fileName)){
+ //当前日期
+ fileName = DateUtils.format(new Date());
+ }
+
+ Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), pojoClass, list);
+ Sheet sheet1 = workbook.getSheetAt(0);
+ sheet1.setDefaultColumnWidth(50*256);
+ sheet1.setDefaultRowHeight((short)(2*256));
+ response.setCharacterEncoding("UTF-8");
+ response.setHeader("content-Type", "application/vnd.ms-excel");
+ response.setHeader("Content-Disposition",
+ "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls");
+ ServletOutputStream out = response.getOutputStream();
+ workbook.write(out);
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Excel导出,先sourceList转换成List,再导出
+ *
+ * @param response response
+ * @param fileName 文件名
+ * @param sourceList 原数据List
+ * @param targetClass 目标对象Class
+ */
+ public static void exportExcelToTarget(HttpServletResponse response, String fileName, Collection> sourceList,
+ Class> targetClass) throws Exception {
+ List targetList = new ArrayList<>(sourceList.size());
+ for(Object source : sourceList){
+ Object target = targetClass.newInstance();
+ BeanUtils.copyProperties(source, target);
+ targetList.add(target);
+ }
+
+ exportExcel(response, fileName, targetList, targetClass);
+ }
+
+ /**
+ * 获取单元格内容
+ * @param cell
+ * @return
+ */
+ public static String getCellContent(Cell cell){
+ String value = "";
+ if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
+ value = String.valueOf(cell.getNumericCellValue());
+ } else {
+ value = cell.getStringCellValue();
+ }
+ //内容超过25个字进行长度限制,否则数据库会超限
+ /*if(value.length() > 25){
+ value = value.substring(0,25) + "...";
+ }*/
+ return value;
+ }
+
+ /**
+ * 获取excle版本
+ * @param mFile
+ * @return
+ */
+ public static String getExcelInfo(MultipartFile mFile) {
+ String fileName = mFile.getOriginalFilename();// 获取文件名
+ String isExcel2003 = "true";// 根据文件名判断文件是2003版本还是2007版本
+ try {
+ if (!validateExcel(fileName)) {// 验证文件名是否合格
+ return "";
+ }
+ if (isExcel2007(fileName)) {
+ isExcel2003 = "false";
+ }
+ return isExcel2003;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 验证EXCEL文件
+ * @param filePath
+ * @return
+ */
+ public static boolean validateExcel(String filePath) {
+ if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
+ return false;
+ }
+ return true;
+ }
+
+ // @描述:是否是2003的excel,返回true是2003
+ public static boolean isExcel2003(String filePath) {
+ return filePath.matches("^.+\\.(?i)(xls)$");
+ }
+ // @描述:是否是2007的excel,返回true是2007
+ public static boolean isExcel2007(String filePath) {
+ return filePath.matches("^.+\\.(?i)(xlsx)$");
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/GPSUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/GPSUtils.java
new file mode 100644
index 0000000..ad1e5f9
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/GPSUtils.java
@@ -0,0 +1,155 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+/**
+ * @Description
+ * @Author yinzuomei
+ * @Date 2019/12/27 10:00
+ */
+public class GPSUtils {
+ public static double pi = 3.1415926535897932384626;
+ public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
+ public static double a = 6378245.0;
+ public static double ee = 0.00669342162296594323;
+
+ public static double transformLat(double x, double y) {
+ double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ + 0.2 * Math.sqrt(Math.abs(x));
+ ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
+ ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
+ ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
+ return ret;
+ }
+
+ public static double transformLon(double x, double y) {
+ double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
+ * Math.sqrt(Math.abs(x));
+ ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
+ ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
+ ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
+ * pi)) * 2.0 / 3.0;
+ return ret;
+ }
+
+ public static double[] transform(double lat, double lon) {
+ if (outOfChina(lat, lon)) {
+ return new double[]{lat, lon};
+ }
+ double dLat = transformLat(lon - 105.0, lat - 35.0);
+ double dLon = transformLon(lon - 105.0, lat - 35.0);
+ double radLat = lat / 180.0 * pi;
+ double magic = Math.sin(radLat);
+ magic = 1 - ee * magic * magic;
+ double sqrtMagic = Math.sqrt(magic);
+ dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
+ dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
+ double mgLat = lat + dLat;
+ double mgLon = lon + dLon;
+ return new double[]{mgLat, mgLon};
+ }
+
+ public static boolean outOfChina(double lat, double lon) {
+ if (lon < 72.004 || lon > 137.8347)
+ return true;
+ if (lat < 0.8293 || lat > 55.8271)
+ return true;
+ return false;
+ }
+
+ /**
+ * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
+ *
+ * @param lat
+ * @param lon
+ * @return
+ */
+ public static double[] gps84_To_Gcj02(double lat, double lon) {
+ if (outOfChina(lat, lon)) {
+ return new double[]{lat, lon};
+ }
+ double dLat = transformLat(lon - 105.0, lat - 35.0);
+ double dLon = transformLon(lon - 105.0, lat - 35.0);
+ double radLat = lat / 180.0 * pi;
+ double magic = Math.sin(radLat);
+ magic = 1 - ee * magic * magic;
+ double sqrtMagic = Math.sqrt(magic);
+ dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
+ dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
+ double mgLat = lat + dLat;
+ double mgLon = lon + dLon;
+ return new double[]{mgLat, mgLon};
+ }
+
+ /**
+ * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
+ */
+ public static double[] gcj02_To_Gps84(double lat, double lon) {
+ double[] gps = transform(lat, lon);
+ double lontitude = lon * 2 - gps[1];
+ double latitude = lat * 2 - gps[0];
+ return new double[]{latitude, lontitude};
+ }
+
+ /**
+ * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
+ *
+ * @param lat
+ * @param lon
+ */
+ public static double[] gcj02_To_Bd09(double lat, double lon) {
+ double x = lon, y = lat;
+ double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
+ double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
+ double tempLon = z * Math.cos(theta) + 0.0065;
+ double tempLat = z * Math.sin(theta) + 0.006;
+ double[] gps = {tempLat, tempLon};
+ return gps;
+ }
+
+ /**
+ * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
+ * bd_lat * @param bd_lon * @return
+ */
+ public static double[] bd09_To_Gcj02(double lat, double lon) {
+ double x = lon - 0.0065, y = lat - 0.006;
+ double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
+ double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
+ double tempLon = z * Math.cos(theta);
+ double tempLat = z * Math.sin(theta);
+ double[] gps = {tempLat, tempLon};
+ return gps;
+ }
+
+ /**
+ * 将gps84转为bd09
+ *
+ * @param lat
+ * @param lon
+ * @return
+ */
+ public static double[] gps84_To_bd09(double lat, double lon) {
+ double[] gcj02 = gps84_To_Gcj02(lat, lon);
+ double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);
+ return bd09;
+ }
+
+ public static double[] bd09_To_gps84(double lat, double lon) {
+ double[] gcj02 = bd09_To_Gcj02(lat, lon);
+ double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
+ //保留小数点后六位
+ gps84[0] = retain6(gps84[0]);
+ gps84[1] = retain6(gps84[1]);
+ return gps84;
+ }
+
+ /**
+ * 保留小数点后六位
+ *
+ * @param num
+ * @return
+ */
+ private static double retain6(double num) {
+ String result = String.format("%.6f", num);
+ return Double.valueOf(result);
+ }
+}
+
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/HttpContextUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/HttpContextUtils.java
new file mode 100644
index 0000000..d723bb6
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/HttpContextUtils.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Http工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class HttpContextUtils {
+
+ public static HttpServletRequest getHttpServletRequest() {
+ RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+ if(requestAttributes == null){
+ return null;
+ }
+
+ return ((ServletRequestAttributes) requestAttributes).getRequest();
+ }
+
+ public static Map getParameterMap(HttpServletRequest request) {
+ Enumeration parameters = request.getParameterNames();
+
+ Map params = new HashMap<>();
+ while (parameters.hasMoreElements()) {
+ String parameter = parameters.nextElement();
+ String value = request.getParameter(parameter);
+ if (StringUtils.isNotBlank(value)) {
+ params.put(parameter, value);
+ }
+ }
+
+ return params;
+ }
+
+ public static String getLanguage() {
+ //默认语言
+ String defaultLanguage = "zh-CN";
+ //request
+ HttpServletRequest request = getHttpServletRequest();
+ if(request == null){
+ return defaultLanguage;
+ }
+
+ //请求语言
+ defaultLanguage = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
+
+ return defaultLanguage;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IdentityNoUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IdentityNoUtils.java
new file mode 100644
index 0000000..0d48190
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IdentityNoUtils.java
@@ -0,0 +1,355 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 身份证号工具
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2019/9/7 13:11
+ */
+public class IdentityNoUtils implements Serializable {
+
+ /**
+ * 15位身份证号
+ */
+ private static final Integer FIFTEEN_ID_CARD = 15;
+ /**
+ * 18位身份证号
+ */
+ private static final Integer EIGHTEEN_ID_CARD = 18;
+ /**
+ * 数字格式校验
+ */
+ private static Pattern NUMBER_PATTERN = Pattern.compile("[0-9]*");
+ /**
+ * 日期格式校验
+ */
+ private static Pattern DATE_PATTERN = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
+ /**
+ * 18位身份证中最后一位校验码
+ */
+ private final static char[] VERIFY_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
+ /**
+ * 18位身份证中,各个数字的生成校验码时的权值
+ */
+ private final static int[] VERIFY_CODE_WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
+
+ /**
+ * 根据身份证号获取性别 0女;1男
+ *
+ * @param IDCard 完整身份证号码
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 14:26
+ */
+ public static String getSex(String IDCard) {
+ if (StringUtils.isNotBlank(IDCard)) {
+ if (IDCard.length() == FIFTEEN_ID_CARD) {
+ if (Integer.parseInt(IDCard.substring(14, 15)) % 2 == 0) {
+ return sexEnum.FEMALE.value;
+ } else {
+ return sexEnum.MALE.value;
+ }
+ } else if (IDCard.length() == EIGHTEEN_ID_CARD) {
+ if (Integer.parseInt(IDCard.substring(16).substring(0, 1)) % 2 == 0) {
+ return sexEnum.FEMALE.value;
+ } else {
+ return sexEnum.MALE.value;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 根据身份证号获取年龄
+ *
+ * @param IDCard 完整身份证号码
+ * @return java.lang.Integer
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 14:26
+ */
+ public static Integer getAge(String IDCard) {
+ int age;
+ LocalDate now = LocalDate.now();
+ int nowYear = now.getYear();
+ int nowMonth = now.getMonthValue();
+ int cardYear = 0;
+ int cardMonth = 0;
+ if (StringUtils.isNotBlank(IDCard) && isValid(IDCard)) {
+ if (IDCard.length() == FIFTEEN_ID_CARD) {
+ // 身份证上的年份(15位身份证为1980年前的)
+ String uyear = "19" + IDCard.substring(6, 8);
+ cardYear = Integer.parseInt(uyear);
+ // 身份证上的月份
+ String uyue = IDCard.substring(8, 10);
+ cardMonth = Integer.parseInt(uyue);
+ } else if (IDCard.length() == EIGHTEEN_ID_CARD) {
+ // 身份证上的年份
+ String year = IDCard.substring(6).substring(0, 4);
+ cardYear = Integer.parseInt(year);
+ // 身份证上的月份
+ String yue = IDCard.substring(10).substring(0, 2);
+ cardMonth = Integer.parseInt(yue);
+ }
+ }
+ // 当前月份大于用户出身的月份表示已过生日
+ if (cardMonth <= nowMonth) {
+ age = nowYear - cardYear + 1;
+ // 当前用户还没过生
+ } else {
+ age = nowYear - cardYear;
+ }
+ return age;
+ }
+
+ /**
+ * 根据身份证号获取出生日期
+ *
+ * @param IDCard 完整身份证号码
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 14:26
+ */
+ public static String getBirthday(String IDCard) {
+ String year = "";
+ String month = "";
+ String day = "";
+ if (StringUtils.isNotBlank(IDCard)) {
+ //15位身份证号
+ if (IDCard.length() == FIFTEEN_ID_CARD) {
+ // 身份证上的年份(15位身份证为1980年前的)
+ year = "19" + IDCard.substring(6, 8);
+ //身份证上的月份
+ month = IDCard.substring(8, 10);
+ //身份证上的日期
+ day = IDCard.substring(10, 12);
+ //18位身份证号
+ } else if (IDCard.length() == EIGHTEEN_ID_CARD) {
+ // 身份证上的年份
+ year = IDCard.substring(6).substring(0, 4);
+ // 身份证上的月份
+ month = IDCard.substring(10).substring(0, 2);
+ //身份证上的日期
+ day = IDCard.substring(12).substring(0, 2);
+ }
+ }
+ return year + "-" + month + "-" + day;
+ }
+
+ /**
+ * 身份证验证是否有效
+ *
+ * @param id 号码内容
+ * @return boolean
+ * @author
+ * @date
+ */
+ public static boolean isValid(String id) {
+ Boolean validResult = true;
+ //校验长度只能为15或18
+ int len = id.length();
+ if (len != FIFTEEN_ID_CARD && len != EIGHTEEN_ID_CARD) {
+ validResult = false;
+ }
+ //校验生日
+ if (!validDate(id)) {
+ validResult = false;
+ }
+ return validResult;
+ }
+
+ /**
+ * 校验生日
+ *
+ * @param id
+ * @return
+ */
+ private static boolean validDate(String id) {
+ try {
+ String birth = id.length() == FIFTEEN_ID_CARD ? "19" + id.substring(6, 12) : id.substring(6, 14);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+ Date birthDate = sdf.parse(birth);
+ if (!birth.equals(sdf.format(birthDate))) {
+ return false;
+ }
+ } catch (ParseException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 验证身份证号码,验证通过返回null
+ *
+ * @param idStr 完整身份证号码
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 14:26
+ */
+ public static String IdentityNoVerification(String idStr) {
+ String iDCardNo = null;
+ //判断号码的长度 15位或18位
+ if (idStr.length() != FIFTEEN_ID_CARD && idStr.length() != EIGHTEEN_ID_CARD) {
+ return "身份证号码长度应该为15位或18位";
+ }
+ if (idStr.length() == EIGHTEEN_ID_CARD) {
+ iDCardNo = idStr.substring(0, 17);
+ } else if (idStr.length() == FIFTEEN_ID_CARD) {
+ iDCardNo = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
+ }
+ if (isStrNum(iDCardNo) == false) {
+ return "身份证15位号码都应为数字;18位号码除最后一位外,都应为数字";
+ }
+ //判断出生年月
+ int year = Integer.parseInt(iDCardNo.substring(6, 10));
+ String strMonth = iDCardNo.substring(10, 12);
+ String strDay = iDCardNo.substring(12, 14);
+
+ String birthDay = year + "-" + strMonth + "-" + strDay;
+ if (isStrDate(birthDay) == false) {
+ return "身份证生日无效";
+ }
+ LocalDate now = LocalDate.now();
+ if ((now.getYear() - year) > 150 || now.isBefore(LocalDate.parse(birthDay))) {
+ return "身份证生日不在有效范围";
+ }
+ int month = Integer.parseInt(strMonth);
+ if (month > 12 || month == 0) {
+ return "身份证月份无效";
+ }
+ int day = Integer.parseInt(strDay);
+ if (day > 31 || day == 0) {
+ return "身份证日期无效";
+ }
+ //判断地区码
+ Hashtable h = GetAreaCode();
+ if (h.get(iDCardNo.substring(0, 2)) == null) {
+ return "身份证地区编码错误";
+ }
+ //判断最后一位
+ int theLastOne = 0;
+ for (int i = 0; i < 17; i++) {
+ theLastOne = theLastOne + Integer.parseInt(String.valueOf(iDCardNo.charAt(i))) * VERIFY_CODE_WEIGHT[i];
+ }
+ int modValue = theLastOne % 11;
+ char strVerifyCode = VERIFY_CODE[modValue];
+ iDCardNo = iDCardNo + strVerifyCode;
+ if (idStr.length() == EIGHTEEN_ID_CARD && !iDCardNo.equals(idStr)) {
+ return "身份证无效,不是合法的身份证号码";
+ }
+ return null;
+ }
+
+ /**
+ * 地区代码
+ *
+ * @return Hashtable
+ */
+ private static Hashtable GetAreaCode() {
+ Hashtable hashtable = new Hashtable<>();
+ hashtable.put("11", "北京");
+ hashtable.put("12", "天津");
+ hashtable.put("13", "河北");
+ hashtable.put("14", "山西");
+ hashtable.put("15", "内蒙古");
+ hashtable.put("21", "辽宁");
+ hashtable.put("22", "吉林");
+ hashtable.put("23", "黑龙江");
+ hashtable.put("31", "上海");
+ hashtable.put("32", "江苏");
+ hashtable.put("33", "浙江");
+ hashtable.put("34", "安徽");
+ hashtable.put("35", "福建");
+ hashtable.put("36", "江西");
+ hashtable.put("37", "山东");
+ hashtable.put("41", "河南");
+ hashtable.put("42", "湖北");
+ hashtable.put("43", "湖南");
+ hashtable.put("44", "广东");
+ hashtable.put("45", "广西");
+ hashtable.put("46", "海南");
+ hashtable.put("50", "重庆");
+ hashtable.put("51", "四川");
+ hashtable.put("52", "贵州");
+ hashtable.put("53", "云南");
+ hashtable.put("54", "西藏");
+ hashtable.put("61", "陕西");
+ hashtable.put("62", "甘肃");
+ hashtable.put("63", "青海");
+ hashtable.put("64", "宁夏");
+ hashtable.put("65", "新疆");
+ hashtable.put("71", "台湾");
+ hashtable.put("81", "香港");
+ hashtable.put("82", "澳门");
+ hashtable.put("91", "国外");
+ return hashtable;
+ }
+
+ /**
+ * 判断字符串是否为数字
+ *
+ * @param str
+ * @return boolean
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 13:58
+ */
+ private static boolean isStrNum(String str) {
+ Matcher isNum = NUMBER_PATTERN.matcher(str);
+ if (isNum.matches()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 判断字符串是否为日期格式
+ *
+ * @param strDate
+ * @return boolean
+ * @author work@yujt.net.cn
+ * @date 2019/9/20 13:57
+ */
+ public static boolean isStrDate(String strDate) {
+ Matcher m = DATE_PATTERN.matcher(strDate);
+ if (m.matches()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ enum sexEnum {
+ /**
+ * 暂停
+ */
+ FEMALE("0"),
+ /**
+ * 正常
+ */
+ MALE("1");
+
+ private String value;
+
+ sexEnum(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IpUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IpUtils.java
new file mode 100644
index 0000000..7a0643d
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/IpUtils.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * IP工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class IpUtils {
+ private static Logger logger = LoggerFactory.getLogger(IpUtils.class);
+
+ public static String getIpAddr(HttpServletRequest request) {
+ String ip = null;
+ try {
+ ip = request.getHeader("x-forwarded-for");
+ if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ } catch (Exception e) {
+ logger.error("IpUtils ERROR ", e);
+ }
+
+ return ip;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/LocalDateUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/LocalDateUtils.java
new file mode 100644
index 0000000..133340b
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/LocalDateUtils.java
@@ -0,0 +1,51 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+
+import java.time.*;
+import java.util.Date;
+
+/**
+ * @author work@yujt.net.cn
+ * @date 2019/12/13 15:05
+ */
+public class LocalDateUtils {
+
+
+ public static LocalDateTime dateToLocalDateTime(Date date) {
+ Instant instant = date.toInstant();
+ ZoneId zone = ZoneId.systemDefault();
+ return LocalDateTime.ofInstant(instant, zone);
+ }
+
+ public static LocalDate dateToLocalDate(Date date) {
+ Instant instant = date.toInstant();
+ ZoneId zone = ZoneId.systemDefault();
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
+ return localDateTime.toLocalDate();
+ }
+
+ public static YearMonth dateToYearMonth(Date date) {
+ LocalDate localDate = dateToLocalDate(date);
+ return YearMonth.of(localDate.getYear(), localDate.getMonthValue());
+ }
+
+ public static LocalTime dateToLocalTime(Date date) {
+ Instant instant = date.toInstant();
+ ZoneId zone = ZoneId.systemDefault();
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
+ return localDateTime.toLocalTime();
+ }
+
+ public static Date localDateTimeToDate(LocalDateTime localDateTime) {
+ ZoneId zone = ZoneId.systemDefault();
+ Instant instant = localDateTime.atZone(zone).toInstant();
+ return Date.from(instant);
+ }
+
+ public static Date localDateToDate(LocalDate localDate) {
+ ZoneId zone = ZoneId.systemDefault();
+ Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
+ return Date.from(instant);
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/MessageUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/MessageUtils.java
new file mode 100644
index 0000000..05dd40a
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/MessageUtils.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+
+/**
+ * 国际化
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class MessageUtils {
+ private static MessageSource messageSource;
+ static {
+ messageSource = (MessageSource)SpringContextUtils.getBean("messageSource");
+ }
+
+ public static String getMessage(int code){
+ return getMessage(code, new String[0]);
+ }
+
+ public static String getMessage(int code, String... params){
+ return messageSource.getMessage(code+"", params, LocaleContextHolder.getLocale());
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ModuleUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ModuleUtils.java
new file mode 100644
index 0000000..3c75b28
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/ModuleUtils.java
@@ -0,0 +1,113 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.elink.esua.epdc.commons.tools.constant.StrConstant;
+import com.elink.esua.epdc.commons.tools.exception.RenException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.CharEncoding;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.StringUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.UUID;
+
+/**
+ * 工具类
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2019/9/5 14:44
+ */
+@Slf4j
+public class ModuleUtils {
+
+ /**
+ * feignclient降级处理错误返回
+ *
+ * @param serverName 服务模块名
+ * @param methodName 方法名,打印到日志文件
+ * @param params 参数,打印的日志文件
+ * @return com.elink.esua.commons.tools.utils.Result
+ * @author yujintao
+ * @date 2019/9/5 14:44
+ */
+ public static Result feignConError(String serverName, String methodName, Object... params) {
+ String errorMessage = "Failure to connect " + serverName;
+ String errorLog = errorMessage + "::[method]->{}::[params]->{}";
+ log.error(errorLog, methodName, JSON.toJSONString(params));
+ return new Result().error(errorMessage);
+ }
+
+ /**
+ * 生成uuid
+ *
+ * @return java.lang.String
+ * @author yujintao
+ * @date 2019/9/5 14:44
+ */
+ public static String generateUUID() {
+ return UUID.randomUUID().toString().replace(StrConstant.HYPHEN, "");
+ }
+
+ /**
+ * 字符串转换为base64
+ *
+ * @param params
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2020/2/6 16:39
+ */
+ public static String encodeByBase64(String params) {
+ if (StringUtils.isEmpty(params)) {
+ return null;
+ }
+ try {
+ return Base64Utils.encodeToUrlSafeString(params.getBytes(CharEncoding.UTF_8));
+ } catch (UnsupportedEncodingException e) {
+ throw new RenException("字符串编码方法异常");
+ }
+ }
+
+ /**
+ * base64解码
+ *
+ * @param base64Str
+ * @return java.lang.String
+ * @author work@yujt.net.cn
+ * @date 2020/2/6 16:48
+ */
+ public static String decodeFromBase64(String base64Str) {
+ if (StringUtils.isEmpty(base64Str)) {
+ return null;
+ }
+ try {
+ return new String(Base64Utils.decodeFromUrlSafeString(base64Str), CharEncoding.UTF_8);
+ } catch (UnsupportedEncodingException e) {
+ throw new RenException("字符串编码方法异常");
+ }
+ }
+
+ /**
+ * 验证字符串是否是日期格式
+ *
+ * @param str 被验证的字符串
+ * @param dateFormat 指定日期格式
+ * @return boolean
+ * @author work@yujt.net.cn
+ * @date 2020/2/7 10:53
+ */
+ public static boolean isValidDate(String str, String dateFormat) {
+ boolean convertSuccess = true;
+ // 指定日期格式
+ SimpleDateFormat format = new SimpleDateFormat(dateFormat);
+ try {
+ format.setLenient(false);
+ format.parse(str);
+ } catch (ParseException e) {
+ convertSuccess = false;
+ }
+ return convertSuccess;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/RandomUtil.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/RandomUtil.java
new file mode 100644
index 0000000..bb1fc6f
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/RandomUtil.java
@@ -0,0 +1,40 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import java.util.Random;
+
+/**
+ * @author rongchao
+ * @Date 18-12-17
+ */
+public class RandomUtil {
+ /**
+ * 根据需要生成指定长度的纯数字随机数,这个随机数的每一位都是从(0-9)这个产生的一位
+ *
+ * @param codeLen
+ * @return
+ */
+ public static String getNewRandomCode(int codeLen) {
+ Random randomCode = new Random();
+ String strCode = "";
+ while (codeLen > 0) {
+ int charCode = randomCode.nextInt(9);
+ strCode += charCode;
+ codeLen--;
+ }
+ return strCode;
+ }
+
+ public static int getRandomNum(int min, int max) {
+ Random random = new Random();
+ return random.nextInt(max - min + 1) + min;
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 10000; i++) {
+ int s = RandomUtil.getRandomNum(1, 10);
+ if (s < 1 || s > 10) {
+ System.out.println(s);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/Result.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/Result.java
new file mode 100644
index 0000000..f87da0d
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/Result.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import com.elink.esua.epdc.commons.tools.exception.ErrorCode;
+
+import java.io.Serializable;
+
+/**
+ * 响应数据
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class Result implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 编码:0表示成功,其他值表示失败
+ */
+ private int code = 0;
+ /**
+ * 消息内容
+ */
+ private String msg = "success";
+ /**
+ * 响应数据
+ */
+ private T data;
+
+ public Result ok(T data) {
+ this.setData(data);
+ return this;
+ }
+
+ public boolean success() {
+ return code == 0 ? true : false;
+ }
+
+ public Result error() {
+ this.code = ErrorCode.INTERNAL_SERVER_ERROR;
+ this.msg = MessageUtils.getMessage(this.code);
+ return this;
+ }
+
+ public Result error(int code) {
+ this.code = code;
+ this.msg = MessageUtils.getMessage(this.code);
+ return this;
+ }
+
+ public Result error(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ return this;
+ }
+
+ public Result error(String msg) {
+ this.code = ErrorCode.INTERNAL_SERVER_ERROR;
+ this.msg = msg;
+ return this;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/SpringContextUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/SpringContextUtils.java
new file mode 100644
index 0000000..5f726d4
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/SpringContextUtils.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Spring Context 工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Component
+public class SpringContextUtils implements ApplicationContextAware {
+ public static ApplicationContext applicationContext;
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ SpringContextUtils.applicationContext = applicationContext;
+ }
+
+ public static Object getBean(String name) {
+ return applicationContext.getBean(name);
+ }
+
+ public static T getBean(Class requiredType) {
+ return applicationContext.getBean(requiredType);
+ }
+
+ public static T getBean(String name, Class requiredType) {
+ return applicationContext.getBean(name, requiredType);
+ }
+
+ public static boolean containsBean(String name) {
+ return applicationContext.containsBean(name);
+ }
+
+ public static boolean isSingleton(String name) {
+ return applicationContext.isSingleton(name);
+ }
+
+ public static Class extends Object> getType(String name) {
+ return applicationContext.getType(name);
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeNode.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeNode.java
new file mode 100644
index 0000000..a8385ac
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeNode.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 树节点,所有需要实现树节点的,都需要继承该类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class TreeNode implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 主键
+ */
+ private Long id;
+ /**
+ * 上级ID
+ */
+ private Long pid;
+ /**
+ * 子节点列表
+ */
+ private List children = new ArrayList<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getPid() {
+ return pid;
+ }
+
+ public void setPid(Long pid) {
+ this.pid = pid;
+ }
+
+ public List getChildren() {
+ return children;
+ }
+
+ public void setChildren(List children) {
+ this.children = children;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeUtils.java
new file mode 100644
index 0000000..b20a3e8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/TreeUtils.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.utils;
+
+import com.elink.esua.epdc.commons.tools.validator.AssertUtils;
+import com.elink.esua.epdc.commons.tools.validator.AssertUtils;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 树形结构工具类,如:菜单、部门等
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class TreeUtils {
+
+ /**
+ * 根据pid,构建树节点
+ */
+ public static List build(List treeNodes, Long pid) {
+ //pid不能为空
+ AssertUtils.isNull(pid, "pid");
+
+ List treeList = new ArrayList<>();
+ for(T treeNode : treeNodes) {
+ if (pid.equals(treeNode.getPid())) {
+ treeList.add(findChildren(treeNodes, treeNode));
+ }
+ }
+
+ return treeList;
+ }
+
+ /**
+ * 查找子节点
+ */
+ private static T findChildren(List treeNodes, T rootNode) {
+ for(T treeNode : treeNodes) {
+ if(rootNode.getId().equals(treeNode.getPid())) {
+ rootNode.getChildren().add(findChildren(treeNodes, treeNode));
+ }
+ }
+ return rootNode;
+ }
+
+ /**
+ * 构建树节点
+ */
+ public static List build(List treeNodes) {
+ List result = new ArrayList<>();
+
+ //list转map
+ Map nodeMap = new LinkedHashMap<>(treeNodes.size());
+ for(T treeNode : treeNodes){
+ nodeMap.put(treeNode.getId(), treeNode);
+ }
+
+ for(T node : nodeMap.values()) {
+ T parent = nodeMap.get(node.getPid());
+ if(parent != null && !(node.getId().equals(parent.getId()))){
+ parent.getChildren().add(node);
+ continue;
+ }
+
+ result.add(node);
+ }
+
+ return result;
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadFileUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadFileUtils.java
new file mode 100644
index 0000000..95d136a
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadFileUtils.java
@@ -0,0 +1,17 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import java.io.File;
+
+/**
+ *
+ * 图片上传工具类
+ *
+ * @Author:liuchuang
+ * @Date:2019/11/22 16:28
+ */
+public class UploadFileUtils {
+
+ public static String uploadFile(File file) {
+ return "";
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadImageUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadImageUtils.java
new file mode 100644
index 0000000..90c7fc8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/UploadImageUtils.java
@@ -0,0 +1,124 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpEntity;
+import sun.net.www.http.HttpClient;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * @Author LC
+ * @Date 2019/9/11 14:53
+ */
+public class UploadImageUtils {
+
+ /**
+ * 从微信下载图片
+ * @Params: [params]
+ * @Return: java.lang.String
+ * @Author: liuchuang
+ * @Date: 2019/9/11 17:04
+ */
+ public static String downloadImageFromWx(Map params) throws Exception {
+ InputStream inputStream = getMediaStream(params.get("accessTokenUrl"), params.get("mediaUrl"), params.get("mediaId"), params.get("appid"), params.get("secret"));
+ if (null == inputStream) {
+ return null;
+ }
+ byte[] data = null;
+ ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len = 0;
+ while((len = inputStream.read(buffer, 0, 1024)) != -1){
+ swapStream.write(buffer, 0, len);
+ }
+ data = swapStream.toByteArray();
+ String base64 = "data:image/png;base64,"+Base64.encodeBase64String(data);
+ return base64;
+ }
+
+ /**
+ * 获取临时素材
+ */
+ private static InputStream getMediaStream(String accessTokenUrl, String mediaUrl, String mediaId, String appid, String secret)throws IOException {
+ String access_token = getAccessToken(accessTokenUrl, appid, secret);
+ String params = "access_token=" + access_token + "&media_id=" + mediaId;
+ InputStream is = null;
+ try {
+ String urlNameString = mediaUrl + "?" + params;
+ URL urlGet = new URL(urlNameString);
+ HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
+ http.setRequestMethod("GET"); // 必须是get方式请求
+ http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
+ http.setDoOutput(true);
+ http.setDoInput(true);
+ http.connect();
+ if (!http.getContentType().contains("image")) {
+ return null;
+ }
+ // 获取文件转化为byte流
+ is = http.getInputStream();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return is;
+ }
+
+ /**
+ * 获取微信Jsapi的accessToken
+ * 这里获取的获取微信Jsapi的accessToken跟小程序以及其他的不一样
+ */
+ public static String getAccessToken(String accessTokenUrl, String appId, String secret) {
+ accessTokenUrl = accessTokenUrl.replace("APPID", appId).replace("APPSECRET", secret);
+ JSONObject jsonObj = doHttpGet(accessTokenUrl);
+ String accessToken = jsonObj.getString("access_token");
+ return accessToken;
+ }
+
+ /**
+ * 发送GET请求
+ * @Params: [requestUrl, params]
+ * @Return: java.lang.String
+ * @Author: liuchuang
+ * @Date: 2019/8/5 14:25
+ */
+ public static JSONObject doHttpGet(String requestUrl) {
+ JSONObject jsonObj = null;
+ // buffer用于接受返回的字符
+ StringBuffer buffer = new StringBuffer();
+ try {
+ // 建立URL,把请求地址给补全,其中urlEncode()方法用于把params里的参数给取出来
+ URL url = new URL(requestUrl);
+ // 打开http连接
+ HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
+ httpUrlConn.setDoInput(true);
+ httpUrlConn.setRequestMethod("GET");
+ httpUrlConn.connect();
+ // 获得输入
+ InputStream inputStream = httpUrlConn.getInputStream();
+ InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+ // 将bufferReader的值给放到buffer里
+ String str = null;
+ while ((str = bufferedReader.readLine()) != null) {
+ buffer.append(str);
+ }
+ // 关闭bufferReader和输入流
+ bufferedReader.close();
+ inputStreamReader.close();
+ inputStream.close();
+ // 断开连接
+ httpUrlConn.disconnect();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ jsonObj = JSONObject.parseObject(buffer.toString());
+ return jsonObj;
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/WebUtil.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/WebUtil.java
new file mode 100644
index 0000000..5cf6c89
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/utils/WebUtil.java
@@ -0,0 +1,66 @@
+package com.elink.esua.epdc.commons.tools.utils;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Web工具类
+ *
+ * @author rongchao
+ * @Date 18-11-20
+ */
+public class WebUtil {
+
+ public static HttpServletRequest getHttpServletRequest() {
+ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ HttpServletRequest request = requestAttributes.getRequest();
+ return request;
+ }
+
+ public static Object getAttributesFromRequest(String paramName) {
+ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ return requestAttributes.getAttribute(paramName, RequestAttributes.SCOPE_REQUEST);
+ }
+
+ public static void setAttributesFromRequest(String paramName, Object obj) {
+ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ requestAttributes.setAttribute(paramName, obj, RequestAttributes.SCOPE_REQUEST);
+ }
+
+ /**
+ * 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
+ *
+ * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
+ * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
+ *
+ * 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130,
+ * 192.168.1.100
+ *
+ * 用户真实IP为: 192.168.1.110
+ *
+ * @return
+ */
+ public static String getIpAddress() {
+ HttpServletRequest request = getHttpServletRequest();
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ return ip;
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/AssertUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/AssertUtils.java
new file mode 100644
index 0000000..052dad1
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/AssertUtils.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ArrayUtil;
+import com.elink.esua.epdc.commons.tools.exception.ErrorCode;
+import com.elink.esua.epdc.commons.tools.exception.RenException;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 校验工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class AssertUtils {
+
+ public static void isBlank(String str, String... params) {
+ isBlank(str, ErrorCode.NOT_NULL, params);
+ }
+
+ public static void isBlank(String str, Integer code, String... params) {
+ if(code == null){
+ throw new RenException(ErrorCode.NOT_NULL, "code");
+ }
+
+ if (StringUtils.isBlank(str)) {
+ throw new RenException(code, params);
+ }
+ }
+
+ public static void isNull(Object object, String... params) {
+ isNull(object, ErrorCode.NOT_NULL, params);
+ }
+
+ public static void isNull(Object object, Integer code, String... params) {
+ if(code == null){
+ throw new RenException(ErrorCode.NOT_NULL, "code");
+ }
+
+ if (object == null) {
+ throw new RenException(code, params);
+ }
+ }
+
+ public static void isArrayEmpty(Object[] array, String... params) {
+ isArrayEmpty(array, ErrorCode.NOT_NULL, params);
+ }
+
+ public static void isArrayEmpty(Object[] array, Integer code, String... params) {
+ if(code == null){
+ throw new RenException(ErrorCode.NOT_NULL, "code");
+ }
+
+ if(ArrayUtil.isEmpty(array)){
+ throw new RenException(code, params);
+ }
+ }
+
+ public static void isListEmpty(List> list, String... params) {
+ isListEmpty(list, ErrorCode.NOT_NULL, params);
+ }
+
+ public static void isListEmpty(List> list, Integer code, String... params) {
+ if(code == null){
+ throw new RenException(ErrorCode.NOT_NULL, "code");
+ }
+
+ if(CollUtil.isEmpty(list)){
+ throw new RenException(code, params);
+ }
+ }
+
+ public static void isMapEmpty(Map map, String... params) {
+ isMapEmpty(map, ErrorCode.NOT_NULL, params);
+ }
+
+ public static void isMapEmpty(Map map, Integer code, String... params) {
+ if(code == null){
+ throw new RenException(ErrorCode.NOT_NULL, "code");
+ }
+
+ if(MapUtil.isEmpty(map)){
+ throw new RenException(code, params);
+ }
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/ValidatorUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/ValidatorUtils.java
new file mode 100644
index 0000000..89548d1
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/ValidatorUtils.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator;
+
+import com.elink.esua.epdc.commons.tools.exception.RenException;
+import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
+import org.springframework.context.support.ResourceBundleMessageSource;
+import org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import java.util.Set;
+
+/**
+ * hibernate-validator校验工具类
+ * 参考文档:http://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class ValidatorUtils {
+ private static Validator validator;
+
+ static {
+ validator = Validation.byDefaultProvider().configure().messageInterpolator(
+ new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(getMessageSource())))
+ .buildValidatorFactory().getValidator();
+ }
+
+ private static ResourceBundleMessageSource getMessageSource() {
+ ResourceBundleMessageSource bundleMessageSource = new ResourceBundleMessageSource();
+ bundleMessageSource.setDefaultEncoding("UTF-8");
+ bundleMessageSource.setBasenames("i18n/validation", "i18n/validation_common");
+ return bundleMessageSource;
+ }
+
+ /**
+ * 校验对象
+ * @param object 待校验对象
+ * @param groups 待校验的组
+ * @throws RenException 校验不通过,则报RenException异常
+ */
+ public static void validateEntity(Object object, Class>... groups)
+ throws RenException {
+ Set> constraintViolations = validator.validate(object, groups);
+ if (!constraintViolations.isEmpty()) {
+ ConstraintViolation constraint = constraintViolations.iterator().next();
+ throw new RenException(constraint.getMessage());
+ }
+ }
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AddGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AddGroup.java
new file mode 100644
index 0000000..5edf56e
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AddGroup.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 新增 Group
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface AddGroup {
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AliyunGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AliyunGroup.java
new file mode 100644
index 0000000..bb42775
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/AliyunGroup.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 阿里云
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface AliyunGroup {
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/DefaultGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/DefaultGroup.java
new file mode 100644
index 0000000..a2537f8
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/DefaultGroup.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 默认 Group
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface DefaultGroup {
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/Group.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/Group.java
new file mode 100644
index 0000000..0374ff5
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/Group.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+import javax.validation.GroupSequence;
+
+/**
+ * 定义校验顺序,如果AddGroup组失败,则UpdateGroup组不会再校验
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@GroupSequence({AddGroup.class, UpdateGroup.class})
+public interface Group {
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QcloudGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QcloudGroup.java
new file mode 100644
index 0000000..b4f6e5e
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QcloudGroup.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 腾讯云
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface QcloudGroup {
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QiniuGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QiniuGroup.java
new file mode 100644
index 0000000..98bee05
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/QiniuGroup.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 七牛
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface QiniuGroup {
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/UpdateGroup.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/UpdateGroup.java
new file mode 100644
index 0000000..ddbf888
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/validator/group/UpdateGroup.java
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.validator.group;
+
+/**
+ * 修改 Group
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface UpdateGroup {
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssFilter.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssFilter.java
new file mode 100644
index 0000000..69b570c
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssFilter.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.xss;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * XSS过滤
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class XssFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig config) throws ServletException {
+
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
+ (HttpServletRequest) request);
+ chain.doFilter(xssRequest, response);
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssHttpServletRequestWrapper.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..d56d3f0
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssHttpServletRequestWrapper.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.elink.esua.epdc.commons.tools.xss;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * XSS过滤处理
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+ HttpServletRequest orgRequest;
+
+ public XssHttpServletRequestWrapper(HttpServletRequest request) {
+ super(request);
+ orgRequest = request;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ //非json类型,直接返回
+ if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
+ return super.getInputStream();
+ }
+
+ //为空,直接返回
+ String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);
+ if (StringUtils.isBlank(json)) {
+ return super.getInputStream();
+ }
+
+ //xss过滤
+ json = xssEncode(json);
+ final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
+ return new ServletInputStream() {
+ @Override
+ public boolean isFinished() {
+ return true;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+
+ }
+
+ @Override
+ public int read() {
+ return bis.read();
+ }
+ };
+ }
+
+ @Override
+ public String getParameter(String name) {
+ String value = super.getParameter(xssEncode(name));
+ if (StringUtils.isNotBlank(value)) {
+ value = xssEncode(value);
+ }
+ return value;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ String[] parameters = super.getParameterValues(name);
+ if (parameters == null || parameters.length == 0) {
+ return null;
+ }
+
+ for (int i = 0; i < parameters.length; i++) {
+ parameters[i] = xssEncode(parameters[i]);
+ }
+ return parameters;
+ }
+
+ @Override
+ public Map getParameterMap() {
+ Map map = new LinkedHashMap<>();
+ Map parameters = super.getParameterMap();
+ for (String key : parameters.keySet()) {
+ String[] values = parameters.get(key);
+ for (int i = 0; i < values.length; i++) {
+ values[i] = xssEncode(values[i]);
+ }
+ map.put(key, values);
+ }
+ return map;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ String value = super.getHeader(xssEncode(name));
+ if (StringUtils.isNotBlank(value)) {
+ value = xssEncode(value);
+ }
+ return value;
+ }
+
+ private String xssEncode(String input) {
+ return XssUtils.filter(input);
+ }
+
+ /**
+ * 获取最原始的request
+ */
+ public HttpServletRequest getOrgRequest() {
+ return orgRequest;
+ }
+
+ /**
+ * 获取最原始的request
+ */
+ public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
+ if (request instanceof XssHttpServletRequestWrapper) {
+ return ((XssHttpServletRequestWrapper) request).getOrgRequest();
+ }
+
+ return request;
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssUtils.java b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssUtils.java
new file mode 100644
index 0000000..d03988a
--- /dev/null
+++ b/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/xss/XssUtils.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+package com.elink.esua.epdc.commons.tools.xss;
+
+import org.jsoup.Jsoup;
+import org.jsoup.safety.Whitelist;
+
+/**
+ * XSS过滤工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public class XssUtils extends Whitelist {
+
+ /**
+ * XSS过滤
+ */
+ public static String filter(String html){
+ return Jsoup.clean(html, xssWhitelist());
+ }
+
+ /**
+ * XSS过滤白名单
+ */
+ private static Whitelist xssWhitelist(){
+ return new Whitelist()
+ //支持的标签
+ .addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "dl",
+ "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol", "p", "pre", "q", "small",
+ "strike", "strong","sub", "sup", "table", "tbody", "td","tfoot", "th", "thead", "tr", "u","ul",
+ "embed","object","param","span")
+
+ //支持的标签属性
+ .addAttributes("a", "href", "class", "style", "target", "rel", "nofollow")
+ .addAttributes("blockquote", "cite")
+ .addAttributes("code", "class", "style")
+ .addAttributes("col", "span", "width")
+ .addAttributes("colgroup", "span", "width")
+ .addAttributes("img", "align", "alt", "height", "src", "title", "width", "class", "style")
+ .addAttributes("ol", "start", "type")
+ .addAttributes("q", "cite")
+ .addAttributes("table", "summary", "width", "class", "style")
+ .addAttributes("tr", "abbr", "axis", "colspan", "rowspan", "width", "style")
+ .addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width", "style")
+ .addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope","width", "style")
+ .addAttributes("ul", "type", "style")
+ .addAttributes("pre", "class", "style")
+ .addAttributes("div", "class", "id", "style")
+ .addAttributes("embed", "src", "wmode", "flashvars", "pluginspage", "allowFullScreen", "allowfullscreen",
+ "quality", "width", "height", "align", "allowScriptAccess", "allowscriptaccess", "allownetworking", "type")
+ .addAttributes("object", "type", "id", "name", "data", "width", "height", "style", "classid", "codebase")
+ .addAttributes("param", "name", "value")
+ .addAttributes("span", "class", "style")
+
+ //标签属性对应的协议
+ .addProtocols("a", "href", "ftp", "http", "https", "mailto")
+ .addProtocols("img", "src", "http", "https")
+ .addProtocols("blockquote", "cite", "http", "https")
+ .addProtocols("cite", "cite", "http", "https")
+ .addProtocols("q", "cite", "http", "https")
+ .addProtocols("embed", "src", "http", "https");
+ }
+
+ public static void main(String[] args) {
+ StringBuilder html = new StringBuilder();
+ html.append("人人开源 ");
+
+ System.out.println(filter(html.toString()));
+ }
+
+}
diff --git a/epdc-commons-tools/src/main/resources/i18n/messages_common.properties b/epdc-commons-tools/src/main/resources/i18n/messages_common.properties
new file mode 100644
index 0000000..c95e013
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/messages_common.properties
@@ -0,0 +1,22 @@
+#Default
+500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38
+401=\u672A\u6388\u6743
+403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650
+10001={0}\u4E0D\u80FD\u4E3A\u7A7A
+10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55
+10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25
+10004=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF
+10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528
+10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
+10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
+10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
+10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
+10010=\u8D26\u53F7\u4E0D\u5B58\u5728
+10011=\u4E0A\u7EA7\u90E8\u95E8\u4E0D\u80FD\u4E3A\u81EA\u8EAB
+10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB
+10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570
+10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8
+10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237
+10016=\u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528JSON\u683C\u5F0F
+10017=\u89E3\u6790{0}\u51FA\u932F
+10018=\u65E0\u6548\u7684{0}
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/messages_common_en_US.properties b/epdc-commons-tools/src/main/resources/i18n/messages_common_en_US.properties
new file mode 100644
index 0000000..8573769
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/messages_common_en_US.properties
@@ -0,0 +1,22 @@
+#English
+500=Internal Server Error
+401=Unauthorized
+403=Denied access, no permission
+10001={0} can not be empty
+10002=This record already exists in the database
+10003=Fetch parameter failed
+10004=Wrong account or password
+10005=The account has been disabled
+10006=The unique identifier cannot be empty
+10007=The verification code is not correct
+10008=Remove the submenu or button first
+10009=The original password is incorrect
+10010=The account does not exist
+10011=The superior department cannot be for itself
+10012=The superior menu cannot be for itself
+10013=Data permission interface, which can only be a Map type parameter
+10014=Please delete the subordinate department first
+10015=Please delete the user under the department first
+10016=The parameter format is incorrect. Please use JSON format.
+10017=Parsing {0} error
+10018=Invalid {0}
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_CN.properties b/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_CN.properties
new file mode 100644
index 0000000..c54bffb
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_CN.properties
@@ -0,0 +1,22 @@
+#\u7B80\u4F53\u4E2D\u6587
+500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38
+401=\u672A\u6388\u6743
+403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650
+10001={0}\u4E0D\u80FD\u4E3A\u7A7A
+10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55
+10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25
+10004=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF
+10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528
+10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
+10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
+10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
+10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
+10010=\u8D26\u53F7\u4E0D\u5B58\u5728
+10011=\u4E0A\u7EA7\u90E8\u95E8\u4E0D\u80FD\u4E3A\u81EA\u8EAB
+10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB
+10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570
+10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8
+10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237
+10016=\u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528JSON\u683C\u5F0F
+10017=\u89E3\u6790{0}\u51FA\u9519
+10018=\u65E0\u6548\u7684{0}
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_TW.properties b/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_TW.properties
new file mode 100644
index 0000000..aedf118
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/messages_common_zh_TW.properties
@@ -0,0 +1,22 @@
+#\u7E41\u4F53\u4E2D\u6587
+500=\u670D\u52D9\u5668\u5167\u90E8\u7570\u5E38
+401=\u672A\u6388\u6B0A
+403=\u62D2\u7D55\u8A2A\u554F\uFF0C\u6C92\u6709\u6B0A\u9650
+10001={0}\u4E0D\u80FD\u70BA\u7A7A
+10002=\u6578\u64DA\u5EAB\u4E2D\u5DF2\u5B58\u5728\u8A72\u8A18\u9304
+10003=\u7372\u53D6\u53C3\u6578\u5931\u6557
+10004=\u8CEC\u865F\u6216\u5BC6\u78BC\u932F\u8AA4
+10005=\u8CEC\u865F\u5DF2\u88AB\u505C\u7528
+10006=\u552F\u4E00\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A
+10007=\u9A57\u8B49\u78BC\u4E0D\u6B63\u78BA
+10008=\u5148\u522A\u9664\u5B50\u83DC\u55AE\u6216\u6309\u9215
+10009=\u539F\u5BC6\u78BC\u4E0D\u6B63\u78BA
+10010=\u8CEC\u865F\u4E0D\u5B58\u5728
+10011=\u4E0A\u7D1A\u90E8\u9580\u4E0D\u80FD\u70BA\u81EA\u8EAB
+10012=\u4E0A\u7D1A\u83DC\u55AE\u4E0D\u80FD\u70BA\u81EA\u8EAB
+10013=\u6578\u64DA\u6B0A\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u985E\u578B\u53C3\u6578
+10014=\u8ACB\u5148\u522A\u9664\u4E0B\u7D1A\u90E8\u9580
+10015=\u8ACB\u5148\u522A\u9664\u90E8\u9580\u4E0B\u7684\u7528\u6236
+10016=\u53C3\u6578\u683C\u5F0F\u4E0D\u6B63\u78BA\uFF0C\u8ACB\u4F7F\u7528JSON\u683C\u5F0F
+10017=\u89E3\u6790{0}\u51FA\u932F
+10018=\u7121\u6548\u7684{0}
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/validation_common.properties b/epdc-commons-tools/src/main/resources/i18n/validation_common.properties
new file mode 100644
index 0000000..0fc4dff
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/validation_common.properties
@@ -0,0 +1,33 @@
+#Default
+id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
+id.null=ID\u5FC5\u987B\u4E3A\u7A7A
+pid.require=\u4E0A\u7EA7ID\uFF0C\u4E0D\u80FD\u4E3A\u7A7A
+sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
+
+sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
+
+sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
+sysuser.email.require=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
+sysuser.mobile.require=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.superadmin.range=\u8D85\u7EA7\u7BA1\u7406\u5458\u53D6\u503C\u8303\u56F40~1
+sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
+sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
+
+sysmenu.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u83DC\u5355
+sysmenu.name.require=\u83DC\u5355\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+sysmenu.type.range=\u83DC\u5355\u7C7B\u578B\u53D6\u503C\u8303\u56F40~1
+
+sysdept.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u90E8\u95E8
+sysdept.name.require=\u90E8\u95E8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+
+sysrole.name.require=\u89D2\u8272\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+
+sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
+sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/validation_common_en_US.properties b/epdc-commons-tools/src/main/resources/i18n/validation_common_en_US.properties
new file mode 100644
index 0000000..bdf51e9
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/validation_common_en_US.properties
@@ -0,0 +1,33 @@
+#English
+id.require=ID can not be empty
+id.null=ID has to be empty
+pid.require=Parent ID, cannot be empty
+sysmenu.sort.number=The sort value cannot be less than 0
+
+sysparams.paramcode.require=Parameter encoding cannot be empty
+sysparams.paramvalue.require=Parameter values cannot be empty
+
+sysuser.username.require=The username cannot be empty
+sysuser.password.require=The password cannot be empty
+sysuser.realname.require=The realname cannot be empty
+sysuser.gender.range=Gender ranges from 0 to 2
+sysuser.email.require=Mailbox cannot be empty
+sysuser.email.error=Incorrect email format
+sysuser.mobile.require=The phone number cannot be empty
+sysuser.deptId.require=Departments cannot be empty
+sysuser.superadmin.range=Super administrator values range from 0 to 1
+sysuser.status.range=State ranges from 0 to 1
+sysuser.captcha.require=The captcha cannot be empty
+sysuser.uuid.require=The unique identifier cannot be empty
+
+sysmenu.pid.require=Please select superior menu
+sysmenu.name.require=Menu name cannot be empty
+sysmenu.type.range=Menu type ranges from 0 to 1
+
+sysdept.pid.require=Please select superior department
+sysdept.name.require=The department name cannot be empty
+
+sysrole.name.require=The role name cannot be empty
+
+sysdict.type.require=The dictionary type cannot be empty
+sysdict.name.require=The dictionary name cannot be empty
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_CN.properties b/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_CN.properties
new file mode 100644
index 0000000..07a7d88
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_CN.properties
@@ -0,0 +1,33 @@
+#\u7B80\u4F53\u4E2D\u6587
+id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
+id.null=ID\u5FC5\u987B\u4E3A\u7A7A
+pid.require=\u4E0A\u7EA7ID\uFF0C\u4E0D\u80FD\u4E3A\u7A7A
+sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
+
+sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
+
+sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
+sysuser.email.require=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
+sysuser.mobile.require=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.superadmin.range=\u8D85\u7EA7\u7BA1\u7406\u5458\u53D6\u503C\u8303\u56F40~1
+sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
+sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
+sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
+
+sysmenu.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u83DC\u5355
+sysmenu.name.require=\u83DC\u5355\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+sysmenu.type.range=\u83DC\u5355\u7C7B\u578B\u53D6\u503C\u8303\u56F40~1
+
+sysdept.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u90E8\u95E8
+sysdept.name.require=\u90E8\u95E8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+
+sysrole.name.require=\u89D2\u8272\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
+
+sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
+sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
\ No newline at end of file
diff --git a/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_TW.properties b/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_TW.properties
new file mode 100644
index 0000000..4aa71af
--- /dev/null
+++ b/epdc-commons-tools/src/main/resources/i18n/validation_common_zh_TW.properties
@@ -0,0 +1,33 @@
+#\u7E41\u4F53\u4E2D\u6587
+id.require=ID\u4E0D\u80FD\u70BA\u7A7A
+id.null=ID\u5FC5\u9808\u70BA\u7A7A
+pid.require=\u4E0A\u7D1AID\uFF0C\u4E0D\u80FD\u70BA\u7A7A
+sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u65BC0
+
+sysparams.paramcode.require=\u53C3\u6578\u7DE8\u78BC\u4E0D\u80FD\u70BA\u7A7A
+sysparams.paramvalue.require=\u53C3\u6578\u503C\u4E0D\u80FD\u70BA\u7A7A
+
+sysuser.username.require=\u7528\u6236\u540D\u4E0D\u80FD\u70BA\u7A7A
+sysuser.password.require=\u5BC6\u78BC\u4E0D\u80FD\u70BA\u7A7A
+sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u70BA\u7A7A
+sysuser.gender.range=\u6027\u5225\u53D6\u503C\u7BC4\u570D0~2
+sysuser.email.require=\u90F5\u7BB1\u4E0D\u80FD\u70BA\u7A7A
+sysuser.email.error=\u90F5\u7BB1\u683C\u5F0F\u4E0D\u6B63\u78BA
+sysuser.mobile.require=\u624B\u6A5F\u865F\u4E0D\u80FD\u70BA\u7A7A
+sysuser.deptId.require=\u90E8\u9580\u4E0D\u80FD\u70BA\u7A7A
+sysuser.superadmin.range=\u8D85\u7D1A\u7BA1\u7406\u54E1\u53D6\u503C\u7BC4\u570D0~1
+sysuser.status.range=\u72C0\u614B\u53D6\u503C\u7BC4\u570D0~1
+sysuser.captcha.require=\u9A57\u8B49\u78BC\u4E0D\u80FD\u70BA\u7A7A
+sysuser.uuid.require=\u552F\u4E00\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A
+
+sysmenu.pid.require=\u8ACB\u9078\u64C7\u4E0A\u7D1A\u83DC\u55AE
+sysmenu.name.require=\u83DC\u55AE\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
+sysmenu.type.range=\u83DC\u55AE\u985E\u578B\u53D6\u503C\u7BC4\u570D0~1
+
+sysdept.pid.require=\u8ACB\u9078\u64C7\u4E0A\u7D1A\u90E8\u9580
+sysdept.name.require=\u90E8\u9580\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
+
+sysrole.name.require=\u89D2\u8272\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
+
+sysdict.type.require=\u5B57\u5178\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
+sysdict.name.require=\u5B57\u5178\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b72188f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-parent
+ 1.0.0
+
+
+ epdc-cloud-commons
+ pom
+
+
+ epdc-commons-tools
+ epdc-commons-mybatis
+ epdc-commons-dynamic-datasource
+ epdc-commons-api-version-control
+ epdc-commons-tools-phone
+ epdc-common-clienttoken
+ epdc-commons-tools-wx-ma
+ epdc-commons-tools-wx-mp
+ shibei-gird-sdk
+ spring-boot-httpclient-starter
+
+
diff --git a/shibei-gird-sdk/pom.xml b/shibei-gird-sdk/pom.xml
new file mode 100644
index 0000000..a26e35e
--- /dev/null
+++ b/shibei-gird-sdk/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+
+ 4.0.0
+
+ shibei-gird-sdk
+ jar
+
+ 市北网格化服务接口封装
+
+
+ 1.4.11.1
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+ provided
+
+
+
+ com.thoughtworks.xstream
+ xstream
+ ${xstream.version}
+
+
+
+ com.esua.epdc
+ spring-boot-httpclient-starter
+ 1.0.0
+ compile
+
+
+
+ org.springframework
+ spring-context
+ 5.1.9.RELEASE
+ compile
+
+
+ com.google.guava
+ guava
+ 26.0-jre
+ compile
+
+
+ cn.hutool
+ hutool-all
+ 4.1.8
+ compile
+
+
+ org.apache.httpcomponents
+ httpcore
+
+
+
+
+ shibei-gird-webservice
+
+ ${project.basedir}/src/main/java
+
+
+
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/ShiBeiCityGridApi.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/ShiBeiCityGridApi.java
new file mode 100644
index 0000000..7e78b3c
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/ShiBeiCityGridApi.java
@@ -0,0 +1,57 @@
+package com.elink.esua.epdc.gird.shibei.api;
+
+
+import com.elink.esua.epdc.gird.shibei.dto.GetZSBInputInfoDto;
+import com.elink.esua.epdc.gird.shibei.dto.GridDto;
+import com.elink.esua.epdc.gird.shibei.dto.SearchCaseProcessByTaskIdDto;
+import com.elink.esua.epdc.gird.shibei.dto.form.SendInputInfoFormDto;
+import com.elink.esua.epdc.gird.shibei.dto.form.SendWenXinEvaluateInfoFormDto;
+
+/**
+ * 市北城市网格化平台API接口
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+public interface ShiBeiCityGridApi {
+
+ /**
+ * 案件信息上报
+ *
+ * @param caseReportFormDto
+ * @return
+ */
+ GridDto sendInputInfo(SendInputInfoFormDto caseReportFormDto);
+
+ /**
+ * 新案件信息上报
+ *
+ * @param caseReportFormDto
+ * @return
+ */
+ GridDto newSendInputInfo(SendInputInfoFormDto caseReportFormDto);
+
+ /**
+ * 评价事件接口
+ *
+ * @return
+ */
+ GridDto sendWenXinEvaluateInfo(SendWenXinEvaluateInfoFormDto sendWenXinEvaluateInfoFormDto);
+
+ /**
+ * 案件信息查询
+ *
+ * @param beginTime YYYY-MM-DD
+ * @param endTime YYYY-MM-DD
+ * @param repoter 上报人唯一编码
+ * @return
+ */
+ GetZSBInputInfoDto getZSBInputInfo(String beginTime, String endTime, String repoter);
+
+ /**
+ * 查询办理进度接口
+ *
+ * @param taskId 要查询办理进度的任务号
+ */
+ SearchCaseProcessByTaskIdDto searchCaseProcessByTaskId(String taskId);
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/impl/ShiBeiCityGridApiImpl.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/impl/ShiBeiCityGridApiImpl.java
new file mode 100644
index 0000000..94aafdb
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/api/impl/ShiBeiCityGridApiImpl.java
@@ -0,0 +1,118 @@
+package com.elink.esua.epdc.gird.shibei.api.impl;
+
+import com.elink.esua.epdc.gird.shibei.api.ShiBeiCityGridApi;
+import com.elink.esua.epdc.gird.shibei.contants.ApiConstants;
+import com.elink.esua.epdc.gird.shibei.dto.GetZSBInputInfoDto;
+import com.elink.esua.epdc.gird.shibei.dto.GridDto;
+import com.elink.esua.epdc.gird.shibei.dto.SearchCaseProcessByTaskIdDto;
+import com.elink.esua.epdc.gird.shibei.dto.form.SendInputInfoFormDto;
+import com.elink.esua.epdc.gird.shibei.dto.form.SendWenXinEvaluateInfoFormDto;
+import com.elink.esua.epdc.gird.shibei.util.XstreamUtil;
+import com.elink.esua.httpclient.HttpClientUtils;
+import com.elink.esua.httpclient.ResultDto;
+import com.google.common.collect.Maps;
+import org.apache.http.HttpStatus;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.Map;
+
+/*
+ * 市北城市网格化平台API接口
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@Component
+public class ShiBeiCityGridApiImpl implements ShiBeiCityGridApi {
+
+ @Autowired
+ private HttpClientUtils httpClientUtils;
+
+ private Logger LOGGER = LogManager.getLogger(HttpClientUtils.class);
+
+ @Override
+ public GridDto sendInputInfo(SendInputInfoFormDto caseReportFormDto) {
+ Map map = Maps.newHashMap();
+ map.put("srtXml", XstreamUtil.objectToXml(caseReportFormDto));
+ GridDto girdDto = this.requestGird(ApiConstants.SendInputInfo, map, GridDto.class);
+ if (girdDto == null) {
+ LOGGER.error("案件上报失败,案件内部编号:{}", caseReportFormDto.getHotLinesn());
+ return null;
+ } else {
+ return girdDto;
+ }
+ }
+
+ @Override
+ public GridDto newSendInputInfo(SendInputInfoFormDto caseReportFormDto) {
+ Map map = Maps.newHashMap();
+ map.put("srtXml", XstreamUtil.objectToXml(caseReportFormDto));
+ LOGGER.info("strXml" + map.get("srtXml"));
+ GridDto girdDto = this.requestGird(ApiConstants.newSendInputInfo, map, GridDto.class);
+ if (girdDto == null) {
+ LOGGER.error("案件上报失败,案件内部编号:{}", caseReportFormDto.getHotLinesn());
+ return null;
+ } else {
+ return girdDto;
+ }
+ }
+
+ @Override
+ public GridDto sendWenXinEvaluateInfo(SendWenXinEvaluateInfoFormDto sendWenXinEvaluateInfoFormDto) {
+ Map map = Maps.newHashMap();
+ map.put("taskId", sendWenXinEvaluateInfoFormDto.getTaskId());
+ map.put("evaluateType", sendWenXinEvaluateInfoFormDto.getEvaluateType());
+ GridDto girdDto = this.requestGird(ApiConstants.SendWenXinEvaluateInfo, map, GridDto.class);
+ if (girdDto == null) {
+ LOGGER.error("案件评价失败,案件taskId为:{}", sendWenXinEvaluateInfoFormDto.getTaskId());
+ return null;
+ } else {
+ return girdDto;
+ }
+ }
+
+ @Override
+ public GetZSBInputInfoDto getZSBInputInfo(String beginTime, String endTime, String repoter) {
+ Map map = Maps.newHashMap();
+ map.put("beginTime", beginTime);
+ map.put("endTime", endTime);
+ map.put("repoter", repoter);
+ GetZSBInputInfoDto getZSBInputInfoDto = this.requestGird(ApiConstants.GetZSBInputInfo, map, GetZSBInputInfoDto.class);
+ if (getZSBInputInfoDto == null) {
+ LOGGER.error("案件信息查询失败,上报人:{}", repoter);
+ return null;
+ } else {
+ return getZSBInputInfoDto;
+ }
+ }
+
+ @Override
+ public SearchCaseProcessByTaskIdDto searchCaseProcessByTaskId(String taskId) {
+ Map map = Maps.newHashMap();
+ map.put("taskId", taskId);
+ SearchCaseProcessByTaskIdDto searchCaseProcessByTaskIdDto = this.requestGird(ApiConstants.SearchCaseProcessByTaskId, map, SearchCaseProcessByTaskIdDto.class);
+ if (searchCaseProcessByTaskIdDto == null) {
+ LOGGER.error("根据taskId搜索案件进度失败,案件taskId为:{}", taskId);
+ return null;
+ } else {
+ return searchCaseProcessByTaskIdDto;
+ }
+ }
+
+ private T requestGird(String requestUrl, Map parmas, Class clazz) {
+ try {
+ ResultDto result = httpClientUtils.postForm(requestUrl, parmas);
+ if (result.getResponseStatusCode() == HttpStatus.SC_OK) {
+ return XstreamUtil.xmlToObject(result.getResult(), clazz);
+ }
+ } catch (IOException e) {
+ LOGGER.error("调用市北网格化平台失败,请求地址:{},异常:{}", requestUrl, e.getMessage());
+ }
+ return null;
+ }
+
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/constant/CommonConstants.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/constant/CommonConstants.java
new file mode 100644
index 0000000..b6a0c5f
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/constant/CommonConstants.java
@@ -0,0 +1,47 @@
+package com.elink.esua.epdc.gird.shibei.constant;
+
+/**
+ * 定义公用常量
+ *
+ * @author yinzuomei
+ * @email yinzuomei@elink-cn.com
+ * @date 2019-12-25
+ */
+public class CommonConstants {
+
+ public static int NUMBER_ONE = 1;
+ /**
+ * 案件来源
+ */
+ public static int INFO_SOURCE_ID=123;
+
+ /**
+ * 渠道来源
+ */
+ public static int REPORT_DEPT=123;
+
+ /**
+ * 案件属性
+ */
+ public static String INFO_TYPE_ID = "18";
+
+ /**
+ * 案件大类
+ */
+ public static String INFO_BC = "01";
+
+ /**
+ * 案件小类
+ */
+ public static String INFO_SC="01";
+
+ /**
+ * 案件子类
+ */
+ public static String INFO_ZC="01";
+
+ /**
+ * 字符:/
+ */
+ public static String CHAR_ASCII_47 = "/";
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ApiConstants.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ApiConstants.java
new file mode 100644
index 0000000..9a426a2
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ApiConstants.java
@@ -0,0 +1,37 @@
+package com.elink.esua.epdc.gird.shibei.contants;
+
+/**
+ * webservice API接口地址常量
+ *
+ * @author rongchao
+ * @Date 18-12-4
+ */
+public class ApiConstants {
+
+ /**
+ * 案件信息上报
+ */
+ public static final String SendInputInfo = "http://60.209.152.68:8083/CityGridInterfaceServiceWebService/WebService.asmx/SendInputInfo";
+
+ /**
+ * 案件信息上报
+ */
+ public static final String newSendInputInfo = "http://60.209.152.68:8083/CityGridInterfaceServiceWebService1.0/WebService.asmx/SendInputInfo";
+
+
+ /**
+ * 评价事件接口
+ */
+ public static final String SendWenXinEvaluateInfo = "http://60.209.152.68:8083/SendToCityGrid/WebService.asmx/SendWenXinEvaluateInfo";
+
+ /**
+ * 案件信息查询
+ */
+ public static final String GetZSBInputInfo = "http://60.209.152.68:8083/SendToCityGrid/WebService.asmx/GetZSBInputInfo";
+
+ /**
+ * 查询办理进度接口
+ */
+ public static final String SearchCaseProcessByTaskId = "http://60.209.152.68:8083/CityGridInterfaceServiceWebService1.0/WebService.asmx/SearchCaseProcessByTaskId";
+
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ResponseConstants.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ResponseConstants.java
new file mode 100644
index 0000000..e6ac9e3
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/contants/ResponseConstants.java
@@ -0,0 +1,15 @@
+package com.elink.esua.epdc.gird.shibei.contants;
+
+/**
+ * 响应常量
+ *
+ * @author rongchao
+ * @Date 18-12-9
+ */
+public class ResponseConstants {
+
+ /**
+ * 成功调用标识
+ */
+ public static final String return_code_success = "1";
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoDto.java
new file mode 100644
index 0000000..3dee296
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoDto.java
@@ -0,0 +1,26 @@
+package com.elink.esua.epdc.gird.shibei.dto;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+import java.util.List;
+
+/**
+ * 案件信息查询返回信息
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@XStreamAlias("result")
+public class GetZSBInputInfoDto {
+
+ @XStreamAlias("request")
+ private List request;
+
+ public List getRequest() {
+ return request;
+ }
+
+ public void setRequest(List request) {
+ this.request = request;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoItemDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoItemDto.java
new file mode 100644
index 0000000..ea0516f
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GetZSBInputInfoItemDto.java
@@ -0,0 +1,199 @@
+package com.elink.esua.epdc.gird.shibei.dto;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 案件信息查询返回信息
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+public class GetZSBInputInfoItemDto {
+
+ @XStreamAlias("status")
+ private String status;
+
+ @XStreamAlias("taskid")
+ private String taskid;
+
+ @XStreamAlias("discovertime")
+ private String discovertime;
+
+ @XStreamAlias("reporter")
+ private String reporter;
+
+ @XStreamAlias("hotlinesn")
+ private String hotlinesn;
+
+ @XStreamAlias("infosourceid")
+ private String infosourceid;
+
+ @XStreamAlias("infotypeid")
+ private String infotypeid;
+
+ @XStreamAlias("infobccode")
+ private String infobccode;
+
+ @XStreamAlias("infosccode")
+ private String infosccode;
+
+ @XStreamAlias("infozccode")
+ private String infozccode;
+
+ @XStreamAlias("streetcode")
+ private String streetcode;
+
+ @XStreamAlias("address")
+ private String address;
+
+ @XStreamAlias("description")
+ private String description;
+
+ @XStreamAlias("accepttime")
+ private String accepttime;
+
+ @XStreamAlias("acceptmark")
+ private String acceptmark;
+
+ @XStreamAlias("endnote")
+ private String endnote;
+
+ @XStreamAlias("endtime")
+ private String endtime;
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getTaskid() {
+ return taskid;
+ }
+
+ public void setTaskid(String taskid) {
+ this.taskid = taskid;
+ }
+
+ public String getDiscovertime() {
+ return discovertime;
+ }
+
+ public void setDiscovertime(String discovertime) {
+ this.discovertime = discovertime;
+ }
+
+ public String getReporter() {
+ return reporter;
+ }
+
+ public void setReporter(String reporter) {
+ this.reporter = reporter;
+ }
+
+ public String getHotlinesn() {
+ return hotlinesn;
+ }
+
+ public void setHotlinesn(String hotlinesn) {
+ this.hotlinesn = hotlinesn;
+ }
+
+ public String getInfosourceid() {
+ return infosourceid;
+ }
+
+ public void setInfosourceid(String infosourceid) {
+ this.infosourceid = infosourceid;
+ }
+
+ public String getInfotypeid() {
+ return infotypeid;
+ }
+
+ public void setInfotypeid(String infotypeid) {
+ this.infotypeid = infotypeid;
+ }
+
+ public String getInfobccode() {
+ return infobccode;
+ }
+
+ public void setInfobccode(String infobccode) {
+ this.infobccode = infobccode;
+ }
+
+ public String getInfosccode() {
+ return infosccode;
+ }
+
+ public void setInfosccode(String infosccode) {
+ this.infosccode = infosccode;
+ }
+
+ public String getInfozccode() {
+ return infozccode;
+ }
+
+ public void setInfozccode(String infozccode) {
+ this.infozccode = infozccode;
+ }
+
+ public String getStreetcode() {
+ return streetcode;
+ }
+
+ public void setStreetcode(String streetcode) {
+ this.streetcode = streetcode;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getAccepttime() {
+ return accepttime;
+ }
+
+ public void setAccepttime(String accepttime) {
+ this.accepttime = accepttime;
+ }
+
+ public String getAcceptmark() {
+ return acceptmark;
+ }
+
+ public void setAcceptmark(String acceptmark) {
+ this.acceptmark = acceptmark;
+ }
+
+ public String getEndnote() {
+ return endnote;
+ }
+
+ public void setEndnote(String endnote) {
+ this.endnote = endnote;
+ }
+
+ public String getEndtime() {
+ return endtime;
+ }
+
+ public void setEndtime(String endtime) {
+ this.endtime = endtime;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GridDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GridDto.java
new file mode 100644
index 0000000..194001b
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/GridDto.java
@@ -0,0 +1,69 @@
+package com.elink.esua.epdc.gird.shibei.dto;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 案件上报返回信息
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@XStreamAlias("DataReturn")
+public class GridDto {
+
+ /**
+ * 保存结果 1失败 0成功(非空)
+ */
+ @XStreamAlias("ReturnCode")
+ private String returnCode;
+
+ /**
+ * 保存日志,异常将写入异常日志
+ */
+ @XStreamAlias("ReturnDescription")
+ private String returnDescription;
+
+ /**
+ * (非空)
+ */
+ @XStreamAlias("TASKID")
+ private String taskId;
+
+ /**
+ * 外系统编号(非空)
+ */
+ @XStreamAlias("HotLinesn")
+ private String hotLinesn;
+
+ public String getReturnCode() {
+ return returnCode;
+ }
+
+ public void setReturnCode(String returnCode) {
+ this.returnCode = returnCode;
+ }
+
+ public String getReturnDescription() {
+ return returnDescription;
+ }
+
+ public void setReturnDescription(String returnDescription) {
+ this.returnDescription = returnDescription;
+ }
+
+ public String getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(String taskId) {
+ this.taskId = taskId;
+ }
+
+ public String getHotLinesn() {
+ return hotLinesn;
+ }
+
+ public void setHotLinesn(String hotLinesn) {
+ this.hotLinesn = hotLinesn;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdDto.java
new file mode 100644
index 0000000..a23c6c4
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdDto.java
@@ -0,0 +1,27 @@
+package com.elink.esua.epdc.gird.shibei.dto;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import java.util.List;
+
+/**
+ * 查询办理进度接口返回DTO
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@XStreamAlias("result")
+public class SearchCaseProcessByTaskIdDto {
+
+ @XStreamImplicit(itemFieldName = "request")
+ List request;
+
+ public List getRequest() {
+ return request;
+ }
+
+ public void setRequest(List request) {
+ this.request = request;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdItemDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdItemDto.java
new file mode 100644
index 0000000..b9159e8
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/SearchCaseProcessByTaskIdItemDto.java
@@ -0,0 +1,90 @@
+package com.elink.esua.epdc.gird.shibei.dto;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 查询办理进度接口返回DTO
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+@XStreamAlias("request")
+public class SearchCaseProcessByTaskIdItemDto {
+
+ @XStreamAlias("taskid")
+ private String taskid;
+
+ @XStreamAlias("itemname")
+ private String itemname;
+
+ @XStreamAlias("username")
+ private String username;
+
+ @XStreamAlias("deptname")
+ private String deptname;
+
+ @XStreamAlias("inserttime")
+ private String inserttime;
+
+ @XStreamAlias("note")
+ private String note;
+
+ @XStreamAlias("operatetype")
+ private String operatetype;
+
+ public String getTaskid() {
+ return taskid;
+ }
+
+ public void setTaskid(String taskid) {
+ this.taskid = taskid;
+ }
+
+ public String getItemname() {
+ return itemname;
+ }
+
+ public void setItemname(String itemname) {
+ this.itemname = itemname;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getDeptname() {
+ return deptname;
+ }
+
+ public void setDeptname(String deptname) {
+ this.deptname = deptname;
+ }
+
+ public String getInserttime() {
+ return inserttime;
+ }
+
+ public void setInserttime(String inserttime) {
+ this.inserttime = inserttime;
+ }
+
+ public String getNote() {
+ return note;
+ }
+
+ public void setNote(String note) {
+ this.note = note;
+ }
+
+ public String getOperatetype() {
+ return operatetype;
+ }
+
+ public void setOperatetype(String operatetype) {
+ this.operatetype = operatetype;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ImageFile.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ImageFile.java
new file mode 100644
index 0000000..7a1d4cc
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ImageFile.java
@@ -0,0 +1,28 @@
+package com.elink.esua.epdc.gird.shibei.dto.form;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import java.util.List;
+
+/**
+ * 图片
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2018/12/20 16:19
+ */
+@XStreamAlias("ImageFile")
+public class ImageFile {
+
+ @XStreamImplicit(itemFieldName = "File")
+ private List reportFileList;
+
+ public List getReportFileList() {
+ return reportFileList;
+ }
+
+ public void setReportFileList(List reportFileList) {
+ this.reportFileList = reportFileList;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ReportFile.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ReportFile.java
new file mode 100644
index 0000000..0a27ba8
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/ReportFile.java
@@ -0,0 +1,48 @@
+package com.elink.esua.epdc.gird.shibei.dto.form;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+/**
+ * 上报的文件
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2018/12/20 16:50
+ */
+@XStreamAlias("File")
+public class ReportFile {
+
+ @XStreamAsAttribute
+ private String name;
+
+ @XStreamAsAttribute
+ private String url;
+
+ @XStreamAsAttribute
+ private String base64string;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getBase64string() {
+ return base64string;
+ }
+
+ public void setBase64string(String base64string) {
+ this.base64string = base64string;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendInputInfoFormDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendInputInfoFormDto.java
new file mode 100644
index 0000000..f1f98fb
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendInputInfoFormDto.java
@@ -0,0 +1,355 @@
+package com.elink.esua.epdc.gird.shibei.dto.form;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 案件上报表单DTO
+ *
+ * @author rongchao
+ * @Date 18-11-30
+ */
+@XStreamAlias("Request")
+public class SendInputInfoFormDto implements Serializable {
+
+ private static final long serialVersionUID = 2907455292265057580L;
+
+ /**
+ * 必填
+ * 案件来源 62(网格系统分配)
+ */
+ @XStreamAlias("InfoSourceID")
+ private int infoSourceID;
+
+ /**
+ * 必填
+ * 渠道来源 62(网格系统分配)
+ */
+ @XStreamAlias("ReportDept")
+ private int reportDept;
+
+ /**
+ * 必填
+ * 案件类型 1(网格系统分配)
+ */
+ @XStreamAlias("InfoTypeID")
+ private String infoTypeID;
+
+ /**
+ * 必填
+ * 案件大类 99(网格系统分配)
+ */
+ @XStreamAlias("InfoBC")
+ private String infoBC;
+
+ /**
+ * 必填
+ * 案件小类 01(网格系统分配)
+ */
+ @XStreamAlias("InfoSC")
+ private String infoSC;
+
+ /**
+ * 必填
+ * 案件子类 01(网格系统分配)
+ */
+ @XStreamAlias("InfoZC")
+ private String infoZC;
+
+ /**
+ * 必填
+ * 发生地址
+ */
+ @XStreamAlias("StandardAddress")
+ private String standardAddress;
+
+ /**
+ * 必填
+ * 问题描述
+ */
+ @XStreamAlias("Description")
+ private String description;
+
+ /**
+ * 反映人 上报人昵称
+ */
+ @XStreamAlias("ReportPerson")
+ private String reportPerson;
+
+ /**
+ * 联系方式
+ */
+ @XStreamAlias("ContactMode")
+ private String contactMode;
+
+ /**
+ * 必填
+ * 坐标X
+ */
+ @XStreamAlias("CoordX")
+ private BigDecimal coordX;
+
+ /**
+ * 必填
+ * 坐标Y
+ */
+ @XStreamAlias("CoordY")
+ private BigDecimal coordY;
+
+ /**
+ * 监督员编号 空字符串
+ */
+ @XStreamAlias("Keepersn")
+ private String keepersn;
+
+ /**
+ * 必填
+ * 发现时间 YYYY-MM-DD HH24:MI:SS
+ */
+ @XStreamAlias("InsertTime")
+ private Date insertTime;
+
+ /**
+ * 必填
+ * 操作人 上报人唯一标识符
+ */
+ @XStreamAlias("InsertUser")
+ private String insertUser;
+
+ /**
+ * 部件编号 空字符串
+ */
+ @XStreamAlias("Partsn")
+ private String partsn;
+
+ /**
+ * 部件状态 空字符串
+ */
+ @XStreamAlias("PartState")
+ private String partState;
+
+ /**
+ * 必填
+ * 外系统编号 若没有编号,建议默认0
+ */
+ @XStreamAlias("HotLinesn")
+ private String hotLinesn;
+
+ /**
+ * 多媒体图片
+ */
+ @XStreamAlias("ImageFile")
+ private ImageFile imageFile;
+
+ /**
+ * 多媒体声音
+ */
+ @XStreamAlias("WaveFile")
+ private com.elink.esua.epdc.gird.shibei.dto.form.WaveFile waveFile;
+
+ /**
+ * 必填
+ * 外系统编码 130099(网格系统分配)
+ */
+ @XStreamAlias("DeptCode")
+ private String deptCode;
+
+ /**
+ * 街道编码
+ */
+ @XStreamAlias("StreetCode")
+ private String streetCode;
+
+ /**
+ * 网格编码
+ */
+ @XStreamAlias("GridCode")
+ private String gridCode;
+
+ public int getInfoSourceID() {
+ return infoSourceID;
+ }
+
+ public void setInfoSourceID(int infoSourceID) {
+ this.infoSourceID = infoSourceID;
+ }
+
+ public int getReportDept() {
+ return reportDept;
+ }
+
+ public void setReportDept(int reportDept) {
+ this.reportDept = reportDept;
+ }
+
+ public String getInfoTypeID() {
+ return infoTypeID;
+ }
+
+ public void setInfoTypeID(String infoTypeID) {
+ this.infoTypeID = infoTypeID;
+ }
+
+ public String getInfoBC() {
+ return infoBC;
+ }
+
+ public void setInfoBC(String infoBC) {
+ this.infoBC = infoBC;
+ }
+
+ public String getInfoSC() {
+ return infoSC;
+ }
+
+ public void setInfoSC(String infoSC) {
+ this.infoSC = infoSC;
+ }
+
+ public String getInfoZC() {
+ return infoZC;
+ }
+
+ public void setInfoZC(String infoZC) {
+ this.infoZC = infoZC;
+ }
+
+ public String getStandardAddress() {
+ return standardAddress;
+ }
+
+ public void setStandardAddress(String standardAddress) {
+ this.standardAddress = standardAddress;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getReportPerson() {
+ return reportPerson;
+ }
+
+ public void setReportPerson(String reportPerson) {
+ this.reportPerson = reportPerson;
+ }
+
+ public String getContactMode() {
+ return contactMode;
+ }
+
+ public void setContactMode(String contactMode) {
+ this.contactMode = contactMode;
+ }
+
+ public BigDecimal getCoordX() {
+ return coordX;
+ }
+
+ public void setCoordX(BigDecimal coordX) {
+ this.coordX = coordX;
+ }
+
+ public BigDecimal getCoordY() {
+ return coordY;
+ }
+
+ public void setCoordY(BigDecimal coordY) {
+ this.coordY = coordY;
+ }
+
+ public String getKeepersn() {
+ return keepersn;
+ }
+
+ public void setKeepersn(String keepersn) {
+ this.keepersn = keepersn;
+ }
+
+ public Date getInsertTime() {
+ return insertTime;
+ }
+
+ public void setInsertTime(Date insertTime) {
+ this.insertTime = insertTime;
+ }
+
+ public String getInsertUser() {
+ return insertUser;
+ }
+
+ public void setInsertUser(String insertUser) {
+ this.insertUser = insertUser;
+ }
+
+ public String getPartsn() {
+ return partsn;
+ }
+
+ public void setPartsn(String partsn) {
+ this.partsn = partsn;
+ }
+
+ public String getPartState() {
+ return partState;
+ }
+
+ public void setPartState(String partState) {
+ this.partState = partState;
+ }
+
+ public String getHotLinesn() {
+ return hotLinesn;
+ }
+
+ public void setHotLinesn(String hotLinesn) {
+ this.hotLinesn = hotLinesn;
+ }
+
+ public String getDeptCode() {
+ return deptCode;
+ }
+
+ public void setDeptCode(String deptCode) {
+ this.deptCode = deptCode;
+ }
+
+ public String getGridCode() {
+ return gridCode;
+ }
+
+ public void setGridCode(String gridCode) {
+ this.gridCode = gridCode;
+ }
+
+ public String getStreetCode() {
+ return streetCode;
+ }
+
+ public void setStreetCode(String streetCode) {
+ this.streetCode = streetCode;
+ }
+
+ public ImageFile getImageFile() {
+ return imageFile;
+ }
+
+ public void setImageFile(ImageFile imageFile) {
+ this.imageFile = imageFile;
+ }
+
+ public com.elink.esua.epdc.gird.shibei.dto.form.WaveFile getWaveFile() {
+ return waveFile;
+ }
+
+ public void setWaveFile(com.elink.esua.epdc.gird.shibei.dto.form.WaveFile waveFile) {
+ this.waveFile = waveFile;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendWenXinEvaluateInfoFormDto.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendWenXinEvaluateInfoFormDto.java
new file mode 100644
index 0000000..afc56ce
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/SendWenXinEvaluateInfoFormDto.java
@@ -0,0 +1,40 @@
+package com.elink.esua.epdc.gird.shibei.dto.form;
+
+import java.io.Serializable;
+
+/**
+ * 评价事件接口表单DTO
+ *
+ * @author rongchao
+ * @Date 18-12-3
+ */
+public class SendWenXinEvaluateInfoFormDto implements Serializable {
+
+ private static final long serialVersionUID = -7268286268923469987L;
+ /**
+ * 开始时间 格式:1990-01-01
+ */
+ private String taskId;
+
+ /**
+ * 满意标识:
+ * 3:基本满意,1:一般,2:不满意,0:满意,4:未表态
+ */
+ private String evaluateType;
+
+ public String getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(String taskId) {
+ this.taskId = taskId;
+ }
+
+ public String getEvaluateType() {
+ return evaluateType;
+ }
+
+ public void setEvaluateType(String evaluateType) {
+ this.evaluateType = evaluateType;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/WaveFile.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/WaveFile.java
new file mode 100644
index 0000000..d1b3eec
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/dto/form/WaveFile.java
@@ -0,0 +1,28 @@
+package com.elink.esua.epdc.gird.shibei.dto.form;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import java.util.List;
+
+/**
+ * 音频
+ *
+ * @author yujintao
+ * @email yujintao@elink-cn.com
+ * @date 2018/12/20 16:28
+ */
+@XStreamAlias("WaveFile")
+public class WaveFile {
+
+ @XStreamImplicit(itemFieldName = "File")
+ private List reportFileList;
+
+ public List getReportFileList() {
+ return reportFileList;
+ }
+
+ public void setReportFileList(List reportFileList) {
+ this.reportFileList = reportFileList;
+ }
+}
diff --git a/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/util/XstreamUtil.java b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/util/XstreamUtil.java
new file mode 100644
index 0000000..d540bac
--- /dev/null
+++ b/shibei-gird-sdk/src/main/java/com/elink/esua/epdc/gird/shibei/util/XstreamUtil.java
@@ -0,0 +1,51 @@
+package com.elink.esua.epdc.gird.shibei.util;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.basic.DateConverter;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
+import com.thoughtworks.xstream.io.xml.XppDriver;
+
+import java.util.TimeZone;
+
+/**
+ * @author rongchao
+ * @Date 18-12-4
+ */
+public class XstreamUtil {
+
+ /**
+ * 将xml转换为bean
+ *
+ * @param 泛型
+ * @param xml 要转换为bean的xml
+ * @param cls bean对应的Class
+ * @return xml转换为bean
+ */
+ public static T xmlToObject(String xml, Class cls) {
+ XStream xStream = new XStream(new DomDriver());
+ XStream.setupDefaultSecurity(xStream);
+ xStream.allowTypes(new Class[]{cls});
+ //xstream使用注解转换
+ xStream.processAnnotations(cls);
+ return (T) xStream.fromXML(xStream.fromXML(xml).toString());
+ }
+
+ /**
+ * 将bean转换为xml
+ *
+ * @param obj
+ * @return
+ */
+ public static String objectToXml(Object obj) {
+ //解决下划线问题
+ XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
+ xStream.registerConverter(new DateConverter("yyyy-MM-dd HH:mm:ss", null, TimeZone.getTimeZone("GMT+8")));
+ XStream.setupDefaultSecurity(xStream);
+ xStream.allowTypes(new Class[]{obj.getClass()});
+ //xstream使用注解转换
+ xStream.processAnnotations(obj.getClass());
+ return xStream.toXML(obj);
+ }
+
+}
diff --git a/spring-boot-httpclient-starter/pom.xml b/spring-boot-httpclient-starter/pom.xml
new file mode 100644
index 0000000..f1860c8
--- /dev/null
+++ b/spring-boot-httpclient-starter/pom.xml
@@ -0,0 +1,112 @@
+
+
+
+
+ com.esua.epdc.shibei
+ epdc-cloud-commons
+ 1.0.0
+
+ 4.0.0
+
+ spring-boot-httpclient-starter
+ jar
+
+ spring-boot-httpclient-starter
+ http://www.example.com
+ http请求工具
+
+
+ 4.5.6
+ 26.0-jre
+ 1.2.17
+
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ com.vaadin.external.google
+ android-json
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+ provided
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${httpclient.version}
+
+
+
+ com.google.guava
+ guava
+ 26.0-jre
+ compile
+
+
+
+
+ common-spring-boot-httpclient-starter
+
+
+ maven-clean-plugin
+
+
+
+ maven-resources-plugin
+
+
+ maven-compiler-plugin
+
+ true
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ ${project.build.sourceEncoding}
+
+
+
+ maven-surefire-plugin
+
+
+ maven-war-plugin
+
+
+ maven-install-plugin
+
+
+ maven-deploy-plugin
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+
+
+
+
+
+
+ ${project.basedir}/src/main/java
+
+
diff --git a/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientAutoConfigration.java b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientAutoConfigration.java
new file mode 100644
index 0000000..778d395
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientAutoConfigration.java
@@ -0,0 +1,112 @@
+package com.elink.esua.httpclient;
+
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpRequest;
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.net.ssl.SSLException;
+import java.io.InterruptedIOException;
+import java.net.UnknownHostException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author rongchao
+ * @Date 18-11-27
+ */
+@Configuration
+@EnableConfigurationProperties({HttpClientProperty.class})
+public class HttpClientAutoConfigration {
+
+ @Autowired
+ private HttpClientProperty httpClientProperty;
+
+ /**
+ * HttpClient的重试处理机制
+ *
+ * @return
+ */
+ @Bean
+ public HttpRequestRetryHandler httpRequestRetryHandler() {
+ // 请求重试
+ final int retryTime = httpClientProperty.getRetryTime();
+ return (exception, executionCount, context) -> {
+ // Do not retry if over max retry count,如果重试次数超过了retryTime,则不再重试请求
+ if (executionCount >= retryTime) {
+ return false;
+ }
+ // 服务端断掉客户端的连接异常
+ if (exception instanceof NoHttpResponseException) {
+ return true;
+ }
+ // time out 超时重试
+ if (exception instanceof InterruptedIOException) {
+ return true;
+ }
+ // Unknown host
+ if (exception instanceof UnknownHostException) {
+ return false;
+ }
+ // Connection refused
+ if (exception instanceof ConnectTimeoutException) {
+ return false;
+ }
+ // SSL handshake exception
+ if (exception instanceof SSLException) {
+ return false;
+ }
+ HttpClientContext clientContext = HttpClientContext.adapt(context);
+ HttpRequest request = clientContext.getRequest();
+ if (!(request instanceof HttpEntityEnclosingRequest)) {
+ return true;
+ }
+ return false;
+ };
+ }
+
+ /**
+ * 连接池管理
+ *
+ * @return
+ */
+ @Bean
+ public PoolingHttpClientConnectionManager poolingClientConnectionManager() {
+ PoolingHttpClientConnectionManager poolHttpcConnManager = new PoolingHttpClientConnectionManager(60, TimeUnit.SECONDS);
+ // 最大连接数
+ poolHttpcConnManager.setMaxTotal(httpClientProperty.getConnMaxTotal());
+ // 路由基数
+ poolHttpcConnManager.setDefaultMaxPerRoute(httpClientProperty.getMaxPerRoute());
+ return poolHttpcConnManager;
+ }
+
+ /**
+ * @return
+ */
+ @Bean
+ public RequestConfig requestConfig() {
+ return RequestConfig.custom()
+ .setConnectionRequestTimeout(httpClientProperty.getConnectRequestTimeout())
+ .setConnectTimeout(httpClientProperty.getConnectTimeout())
+ .setSocketTimeout(httpClientProperty.getSocketTimeout())
+ .build();
+ }
+
+ @Bean
+ public HttpClientManagerFactoryBen httpClientManagerFactoryBen() {
+ return new HttpClientManagerFactoryBen(httpRequestRetryHandler(), poolingClientConnectionManager(), requestConfig());
+ }
+
+ @Bean
+ public HttpClientUtils httpClientUtils() {
+ return new HttpClientUtils(httpClientManagerFactoryBen());
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientManagerFactoryBen.java b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientManagerFactoryBen.java
new file mode 100644
index 0000000..2e4b957
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientManagerFactoryBen.java
@@ -0,0 +1,83 @@
+package com.elink.esua.httpclient;
+
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 描述:HttpClient客户端封装
+ *
+ * @author rongchao
+ * @Date 18-11-27
+ */
+public class HttpClientManagerFactoryBen implements FactoryBean, InitializingBean, DisposableBean {
+
+ public HttpClientManagerFactoryBen(HttpRequestRetryHandler httpRequestRetryHandler, PoolingHttpClientConnectionManager poolHttpcConnManager, RequestConfig config) {
+ this.httpRequestRetryHandler = httpRequestRetryHandler;
+ this.poolHttpcConnManager = poolHttpcConnManager;
+ this.config = config;
+ }
+
+ /**
+ * FactoryBean生成的目标对象
+ */
+ private CloseableHttpClient client;
+
+ private HttpRequestRetryHandler httpRequestRetryHandler;
+
+ private PoolingHttpClientConnectionManager poolHttpcConnManager;
+
+ private RequestConfig config;
+
+ // 销毁上下文时,销毁HttpClient实例
+ @Override
+ public void destroy() throws Exception {
+ /*
+ * 调用httpClient.close()会先shut down connection manager,然后再释放该HttpClient所占用的所有资源,
+ * 关闭所有在使用或者空闲的connection包括底层socket。由于这里把它所使用的connection manager关闭了,
+ * 所以在下次还要进行http请求的时候,要重新new一个connection manager来build一个HttpClient,
+ * 也就是在需要关闭和新建Client的情况下,connection manager不能是单例的.
+ */
+ if (null != this.client) {
+ this.client.close();
+ }
+ }
+
+ @Override// 初始化实例
+ public void afterPropertiesSet() throws Exception {
+ /*
+ * 建议此处使用HttpClients.custom的方式来创建HttpClientBuilder,而不要使用HttpClientBuilder.create()方法来创建HttpClientBuilder
+ * 从官方文档可以得出,HttpClientBuilder是非线程安全的,但是HttpClients确实Immutable的,immutable 对象不仅能够保证对象的状态不被改变,
+ * 而且还可以不使用锁机制就能被其他线程共享
+ */
+ this.client = HttpClients.custom().setConnectionManager(poolHttpcConnManager)
+ .setRetryHandler(httpRequestRetryHandler)
+ .setDefaultRequestConfig(config)
+ .build();
+ }
+
+ // 返回实例的类型
+ @Override
+ public CloseableHttpClient getObject() throws Exception {
+ return this.client;
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return (this.client == null ? CloseableHttpClient.class : this.client.getClass());
+ }
+
+ // 构建的实例为单例
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientProperty.java b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientProperty.java
new file mode 100644
index 0000000..8567b6f
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientProperty.java
@@ -0,0 +1,93 @@
+package com.elink.esua.httpclient;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author rongchao
+ * @Date 18-11-27
+ */
+@Configuration
+@ConfigurationProperties(prefix = "httpclient.config")
+public class HttpClientProperty {
+
+ private int retryTime = 3;
+
+ private int connMaxTotal = 300;
+
+ private int maxPerRoute = 20;
+
+ private int timeToLive = 60;
+
+ private int keepAliveTime = 30;
+
+ private int connectTimeout = 1000;
+
+ private int connectRequestTimeout = 500;
+
+ private int socketTimeout = 10000;
+
+ public int getRetryTime() {
+ return retryTime;
+ }
+
+ public void setRetryTime(int retryTime) {
+ this.retryTime = retryTime;
+ }
+
+ public int getConnMaxTotal() {
+ return connMaxTotal;
+ }
+
+ public void setConnMaxTotal(int connMaxTotal) {
+ this.connMaxTotal = connMaxTotal;
+ }
+
+ public int getMaxPerRoute() {
+ return maxPerRoute;
+ }
+
+ public void setMaxPerRoute(int maxPerRoute) {
+ this.maxPerRoute = maxPerRoute;
+ }
+
+ public int getTimeToLive() {
+ return timeToLive;
+ }
+
+ public void setTimeToLive(int timeToLive) {
+ this.timeToLive = timeToLive;
+ }
+
+ public int getKeepAliveTime() {
+ return keepAliveTime;
+ }
+
+ public void setKeepAliveTime(int keepAliveTime) {
+ this.keepAliveTime = keepAliveTime;
+ }
+
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public int getConnectRequestTimeout() {
+ return connectRequestTimeout;
+ }
+
+ public void setConnectRequestTimeout(int connectRequestTimeout) {
+ this.connectRequestTimeout = connectRequestTimeout;
+ }
+
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+}
diff --git a/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientUtils.java b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientUtils.java
new file mode 100644
index 0000000..be78b16
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/HttpClientUtils.java
@@ -0,0 +1,172 @@
+package com.elink.esua.httpclient;
+
+import org.apache.commons.codec.CharEncoding;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.ParseException;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+import java.net.URI;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author rongchao
+ * @Date 18-12-3
+ */
+public class HttpClientUtils {
+
+ private static final Logger LOGGER = LogManager.getLogger(HttpClientUtils.class);
+
+ private CloseableHttpClient client;
+
+ public HttpClientUtils(HttpClientManagerFactoryBen httpClientBean) {
+ try {
+ this.client = httpClientBean.getObject();
+ } catch (Exception e) {
+ LOGGER.error("CloseableHttpClient构建失败", e);
+ e.printStackTrace();
+ }
+ }
+
+ private static ResultDto getResult(CloseableHttpResponse response) {
+ String result = null;
+ HttpEntity httpEntity = null;
+ try {
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ httpEntity = response.getEntity();
+ result = EntityUtils.toString(httpEntity, CharEncoding.UTF_8);
+ // 释放连接
+ EntityUtils.consumeQuietly(httpEntity);
+ } else {
+ LOGGER.error("拉取失败,错误编码为:{},错误信息:{}", response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase());
+ }
+ } catch (ParseException e) {
+ LOGGER.error("getResult方法格式转换异常ParseException");
+ e.printStackTrace();
+ } catch (IOException e) {
+ LOGGER.error("getResult方法IO异常IOException");
+ e.printStackTrace();
+ } finally {
+ EntityUtils.consumeQuietly(httpEntity);
+ }
+ ResultDto resultDto = new ResultDto();
+ resultDto.setResponseStatusCode(response.getStatusLine().getStatusCode());
+ resultDto.setResult(result);
+ return resultDto;
+ }
+
+ /**
+ * post json 提交方式
+ *
+ * @param url
+ * @param json
+ * @return map
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws KeyManagementException
+ * @throws IOException
+ * @throws ClientProtocolException
+ */
+ public ResultDto postJSON(String url, String json) {
+ CloseableHttpResponse response = null;
+ try {
+ HttpPost httpPost = new HttpPost(url);
+ StringEntity stringEntity = new StringEntity(json, CharEncoding.UTF_8);
+ stringEntity.setContentEncoding(CharEncoding.UTF_8);
+ // 发送json数据需要设置contentType
+ stringEntity.setContentType("application/json");
+ httpPost.setEntity(stringEntity);
+ response = client.execute(httpPost);
+ return getResult(response);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * post form 提交方式
+ *
+ * @param url
+ * @param map
+ * @return map
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws KeyManagementException
+ * @throws IOException
+ * @throws ClientProtocolException
+ */
+ public ResultDto postForm(String url, Map map) throws ClientProtocolException, IOException {
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
+ List formParams = new ArrayList();
+ for (Map.Entry kv : map.entrySet()) {
+ formParams.add(new BasicNameValuePair(kv.getKey(), (String) kv.getValue()));
+ }
+ HttpEntity entity = new UrlEncodedFormEntity(formParams, CharEncoding.UTF_8);
+ httpPost.setEntity(entity);
+ return getResult(client.execute(httpPost));
+ }
+
+ /**
+ * get 提交方式
+ *
+ * @param url
+ * @param headerMap
+ * @param paramMap
+ * @return
+ * @throws KeyManagementException
+ * @throws NoSuchAlgorithmException
+ * @throws KeyStoreException
+ * @throws ClientProtocolException
+ * @throws IOException
+ */
+ public ResultDto get(String url, Map headerMap, Map paramMap) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, ClientProtocolException, IOException {
+ HttpGet httpGet = new HttpGet();
+ if (headerMap != null) {
+ for (String key : headerMap.keySet()) {
+ httpGet.setHeader(key, headerMap.get(key));
+ }
+ }
+ List formparams = setHttpParams(paramMap);
+ String param = URLEncodedUtils.format(formparams, "UTF-8");
+ httpGet.setURI(URI.create(url + "?" + param));
+ return getResult(client.execute(httpGet));
+ }
+
+ /**
+ * 设置请求参数
+ *
+ * @param paramMap
+ * @return
+ */
+ private List setHttpParams(Map paramMap) {
+ List formparams = new ArrayList();
+ if (paramMap != null) {
+ Set> set = paramMap.entrySet();
+ for (Map.Entry entry : set) {
+ formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ }
+ return formparams;
+ }
+}
diff --git a/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/ResultDto.java b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/ResultDto.java
new file mode 100644
index 0000000..fb39e61
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/java/com/elink/esua/httpclient/ResultDto.java
@@ -0,0 +1,34 @@
+package com.elink.esua.httpclient;
+
+/**
+ * @author rongchao
+ * @Date 18-12-4
+ */
+public class ResultDto {
+
+ /**
+ * 响应状态编码
+ */
+ private Integer responseStatusCode;
+
+ /**
+ * 响应结果字符串
+ */
+ private String result;
+
+ public Integer getResponseStatusCode() {
+ return responseStatusCode;
+ }
+
+ public void setResponseStatusCode(Integer responseStatusCode) {
+ this.responseStatusCode = responseStatusCode;
+ }
+
+ public String getResult() {
+ return result;
+ }
+
+ public void setResult(String result) {
+ this.result = result;
+ }
+}
diff --git a/spring-boot-httpclient-starter/src/main/resources/META-INF/spring.factories b/spring-boot-httpclient-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..961954a
--- /dev/null
+++ b/spring-boot-httpclient-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.elink.esua.httpclient.HttpClientAutoConfigration
\ No newline at end of file