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 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 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 @@ +[![码云Gitee](https://gitee.com/binary/weixin-java-mp-demo-springboot/badge/star.svg?theme=blue)](https://gitee.com/binary/weixin-java-mp-demo-springboot) +[![Github](http://github-svg-buttons.herokuapp.com/star.svg?user=binarywang&repo=weixin-java-mp-demo-springboot&style=flat&background=1081C1)](https://github.com/binarywang/weixin-java-mp-demo-springboot) +[![Build Status](https://travis-ci.org/binarywang/weixin-java-mp-demo-springboot.svg?branch=master)](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 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