dobbinfw-core/.gitignore
New file @@ -0,0 +1,28 @@ # Compiled class file *.class /target /.idea *.iml # 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* dobbinfw-core/README.md
New file @@ -0,0 +1,40 @@ ## Dobbin Framework Logo #### 一、项目背景 > 为了快速落地项目、快速搭建脚手架,dobbinsoft开发一套基于SpringBoot MyBatis的框架,并手搓了如参数校验、文档生成、限流、鉴权等等常用功能。core包中包括工具类、注解、模型等。 #### 二、快速开始 ##### 2.1. 下载代码 您可以在国内开源社区Gitee下载(推荐):https://gitee.com/iotechn/dobbinfw-core 您可以在国际开源社区Github下载:https://github.com/iotechn/dobbinfw-core ##### 2.2. maven引入 请确定您已经将 JAVA_HOME 配置,并将mvn命令配置到PATH中,若出现找不到命令,或找不到JAVA_HOME,[请参考此文档](https://blog.csdn.net/weixin_44548718/article/details/108635409) 在项目根目录,打开命令行。并执行 : ```shell mvn install -Dmaven.test.skip=true ``` 引入maven坐标到工程pom.xml文件中。 ```xml <groupId>com.dobbinsoft</groupId> <artifactId>fw-core</artifactId> <version>1.0-SNAPSHOT</version> ``` #### 三、常见问题 ##### 3.1. 为何分离core包? 部分项目,需要拆分微服务,这类项目需要将接口暴露给其他微服务系统,通常提供一个api包,api包不需要引入过重依赖,使用此框架则只需要引入core包即可。 #### 四、贡献 & 社区 您可以直接在仓库中发布Pull Request。本项目欢迎所有开发者一起维护,并永久开源。 dobbinfw-core/pom.xml
New file @@ -0,0 +1,86 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.dobbinsoft</groupId> <artifactId>fw-core</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <!-- 配置编译时保留参数名 --> <configuration> <debuglevel>lines,vars,source</debuglevel> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> </plugins> </build> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- HuTool 工具包 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.6.0</version> </dependency> <!-- 阿里巴巴 json 解析 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <!-- 腾讯云短信 --> <dependency> <groupId>com.github.qcloudsms</groupId> <artifactId>qcloudsms</artifactId> <version>1.0.5</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> <optional>true</optional> </dependency> </dependencies> <distributionManagement> <repository> <id>rdc-snapshot</id> <name>Aliyun Xiao</name> <url>https://packages.aliyun.com/maven/repository/2084582-snapshot-Vrq4iK/</url> </repository> </distributionManagement> </project> dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/Const.java
New file @@ -0,0 +1,49 @@ package com.dobbinsoft.fw.core; import java.util.*; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-11 * Time: 下午11:43 */ public class Const { public static final Set<Class> IGNORE_PARAM_LIST = new HashSet<Class>(); static { IGNORE_PARAM_LIST.add(boolean.class); IGNORE_PARAM_LIST.add(byte.class); IGNORE_PARAM_LIST.add(char.class); IGNORE_PARAM_LIST.add(short.class); IGNORE_PARAM_LIST.add(int.class); IGNORE_PARAM_LIST.add(long.class); IGNORE_PARAM_LIST.add(float.class); IGNORE_PARAM_LIST.add(double.class); IGNORE_PARAM_LIST.add(Byte.class); IGNORE_PARAM_LIST.add(Character.class); IGNORE_PARAM_LIST.add(Short.class); IGNORE_PARAM_LIST.add(Integer.class); IGNORE_PARAM_LIST.add(Long.class); IGNORE_PARAM_LIST.add(String.class); IGNORE_PARAM_LIST.add(Float.class); IGNORE_PARAM_LIST.add(Double.class); IGNORE_PARAM_LIST.add(Boolean.class); } public static final int CACHE_ONE_DAY = 60 * 60 * 24; public static final int CACHE_ONE_YEAR = 60 * 60 * 24 * 365; public static final String USER_ACCESS_TOKEN = "ACCESSTOKEN"; public static final String USER_REDIS_PREFIX = "USER_SESSION_"; public static final String ADMIN_ACCESS_TOKEN = "ADMINTOKEN"; public static final String ADMIN_REDIS_PREFIX = "ADMIN_SESSION_"; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/HttpMethod.java
New file @@ -0,0 +1,34 @@ package com.dobbinsoft.fw.core.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-03-25 * Time: 下午1:12 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface HttpMethod { String description(); ResultType type() default ResultType.COMMONS; RateLimitType rateLimit() default RateLimitType.NONE; int rateWindow() default 60; int rate() default 1; String retName() default ""; int maxAge() default -1; String permission() default ""; String permissionParentName() default ""; String permissionName() default ""; boolean openPlatform() default false; /** * 从网关上构建一个实例 * @return */ Class loadBean() default void.class; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/HttpOpenApi.java
New file @@ -0,0 +1,20 @@ package com.dobbinsoft.fw.core.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-03-25 * Time: 下午1:12 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface HttpOpenApi { String group(); String description(); } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/HttpParam.java
New file @@ -0,0 +1,35 @@ package com.dobbinsoft.fw.core.annotation; import com.dobbinsoft.fw.core.enums.BaseEnums; import com.dobbinsoft.fw.core.enums.EmptyEnums; import java.lang.annotation.*; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-03-25 * Time: 下午1:12 */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface HttpParam { String name(); HttpParamType type() default HttpParamType.COMMON; String description() default ""; String valueDef() default ""; Class arrayClass() default Object.class; /** * 绑定枚举 * @return */ Class<? extends BaseEnums> enums() default EmptyEnums.class; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/HttpParamType.java
New file @@ -0,0 +1,20 @@ package com.dobbinsoft.fw.core.annotation; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-03-25 * Time: 下午1:12 */ public enum HttpParamType { HEADER, COMMON, USER_ID, ADMIN_ID, IP, FILE ; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/RateLimitType.java
New file @@ -0,0 +1,17 @@ package com.dobbinsoft.fw.core.annotation; /** * ClassName: RateLimitType * Description: TODO * * @author: e-weichaozheng * @date: 2021-04-12 */ public enum RateLimitType { USER_ID, IP, ALL, NONE } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/ResultType.java
New file @@ -0,0 +1,13 @@ package com.dobbinsoft.fw.core.annotation; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-24 * Time: 下午5:03 */ public enum ResultType { COMMONS, COOKIE; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/doc/ApiEntity.java
New file @@ -0,0 +1,21 @@ package com.dobbinsoft.fw.core.annotation.doc; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created with IntelliJ IDEA. * Description: 描述实体 * User: rize * Date: 2021-03-17 * Time: 上午9:15 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ApiEntity { String description(); } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/doc/ApiField.java
New file @@ -0,0 +1,26 @@ package com.dobbinsoft.fw.core.annotation.doc; import com.dobbinsoft.fw.core.enums.BaseEnums; import com.dobbinsoft.fw.core.enums.EmptyEnums; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created with IntelliJ IDEA. * Description: 描述实体属性 * User: rize * Date: 2021-03-17 * Time: 上午9:15 */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface ApiField { String description(); Class<? extends BaseEnums> enums() default EmptyEnums.class; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/param/CustomCheck.java
New file @@ -0,0 +1,27 @@ package com.dobbinsoft.fw.core.annotation.param; import java.lang.annotation.*; /** * Created with IntelliJ IDEA. * Description: 自定义参数校验 * User: rize * Date: 2021-03-17 * Time: 上午9:15 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @Documented public @interface CustomCheck { /** * 校验器Class对象,会从IoC中拿取 * @return */ Class beanClass(); boolean reqScope() default true; boolean respScope() default false; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/param/NotNull.java
New file @@ -0,0 +1,23 @@ package com.dobbinsoft.fw.core.annotation.param; import java.lang.annotation.*; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-20 * Time: 上午10:51 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @Documented public @interface NotNull { String message() default ""; boolean reqScope() default true; boolean respScope() default false; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/param/Range.java
New file @@ -0,0 +1,27 @@ package com.dobbinsoft.fw.core.annotation.param; import java.lang.annotation.*; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-20 * Time: 上午11:11 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @Documented public @interface Range { long min() default Long.MIN_VALUE; long max() default Long.MAX_VALUE; String message() default ""; boolean reqScope() default true; boolean respScope() default false; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/param/TextFormat.java
New file @@ -0,0 +1,41 @@ package com.dobbinsoft.fw.core.annotation.param; import java.lang.annotation.*; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-20 * Time: 上午10:51 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @Documented public @interface TextFormat { String regex() default ""; String[] contains() default {}; String[] notContains() default {}; String startWith() default ""; String endsWith() default ""; int lengthMax() default Integer.MAX_VALUE; int lengthMin() default 0; int length() default -1; boolean notChinese() default false; String message() default ""; boolean reqScope() default true; boolean respScope() default false; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/annotation/param/Validator.java
New file @@ -0,0 +1,16 @@ package com.dobbinsoft.fw.core.annotation.param; import com.dobbinsoft.fw.core.exception.ServiceException; /** * ClassName: Validator * Description: 校验器 * * @author: e-weichaozheng * @date: 2021-03-17 */ public interface Validator<T> { public boolean check(T param) throws ServiceException; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/build/AnnotationProcessor.java
New file @@ -0,0 +1,26 @@ package com.dobbinsoft.fw.core.build; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.TypeElement; import java.util.Set; /** * Description: * User: rize * Date: 2021/4/4 * Time: 13:57 */ @SupportedAnnotationTypes(value = {"com.dobbinsoft.fw.support.annotation.Table"}) @SupportedSourceVersion(value = SourceVersion.RELEASE_8) public class AnnotationProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return true; } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/entiy/SuperDTO.java
New file @@ -0,0 +1,19 @@ package com.dobbinsoft.fw.core.entiy; import lombok.Data; import java.util.Date; /** * Created by rize on 2019/7/1. */ @Data public class SuperDTO { private Long id; private Date gmtUpdate; private Date gmtCreate; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/entiy/inter/IdentityOwner.java
New file @@ -0,0 +1,14 @@ package com.dobbinsoft.fw.core.entiy.inter; /** * ClassName: IdentityOwner * Description: 有身份的 * * @author: e-weichaozheng * @date: 2021-03-17 */ public interface IdentityOwner { public Long getId(); } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/entiy/inter/PermissionOwner.java
New file @@ -0,0 +1,16 @@ package com.dobbinsoft.fw.core.entiy.inter; import java.util.List; /** * ClassName: PermissionOwner * Description: 表示一个有权限的身份 * * @author: e-weichaozheng * @date: 2021-03-16 */ public interface PermissionOwner extends IdentityOwner { public List<String> getPerms(); } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/enums/BaseEnums.java
New file @@ -0,0 +1,76 @@ package com.dobbinsoft.fw.core.enums; import cn.hutool.core.util.StrUtil; import java.io.Serializable; /** * ClassName: BaseEnums * Description: TODO * * @author: e-weichaozheng * @date: 2021-03-19 */ public interface BaseEnums<T extends Serializable> { public Serializable getCode(); public String getMsg(); public static <T extends Serializable> BaseEnums getByCode(T t, Class<? extends BaseEnums<T>> clazz) { BaseEnums<T>[] enumConstants = clazz.getEnumConstants(); for (BaseEnums baseEnums : enumConstants) { if (baseEnums.getCode().equals(t)) { return baseEnums; } } return null; } public static <T extends Serializable> String getMsgByCode(T t, Class<? extends BaseEnums<T>> clazz) { BaseEnums baseEnums = getByCode(t, clazz); if (baseEnums == null) { return null; } return baseEnums.getMsg(); } /** * 获取前端格式化需要的MAP * @return */ public default String getMap() { Class<? extends BaseEnums> clazz = this.getClass(); BaseEnums[] enumConstants = clazz.getEnumConstants(); StringBuilder sb = new StringBuilder(); sb.append("const "); sb.append(StrUtil.lowerFirst(clazz.getSimpleName())); sb.append("Map = {\n"); for (int i = 0; i < enumConstants.length; i++) { sb.append(" "); sb.append(enumConstants[i].getCode()); sb.append(": '"); sb.append(enumConstants[i].getMsg()); if (i == enumConstants.length -1) { sb.append("'\n}"); } else { sb.append("',\n"); } } return sb.toString(); } /** * 获取前端格式化需要的过滤器 * @return */ public default String getFilter() { Class<? extends BaseEnums> clazz = this.getClass(); return " " + StrUtil.lowerFirst(clazz.getSimpleName()) + "Filter(status) {\n" + " return " + StrUtil.lowerFirst(clazz.getSimpleName()) + "Map[status]\n" + " }"; } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/enums/EmptyEnums.java
New file @@ -0,0 +1,22 @@ package com.dobbinsoft.fw.core.enums; import java.io.Serializable; /** * ClassName: EmptyEnums * Description: TODO * * @author: e-weichaozheng * @date: 2021-03-19 */ public enum EmptyEnums implements BaseEnums<Integer> { ; public Integer getCode() { return 0; } public String getMsg() { return null; } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/AdminServiceException.java
New file @@ -0,0 +1,20 @@ package com.dobbinsoft.fw.core.exception; /** * Created with IntelliJ IDEA. * Description: * User: kbq * Date: 2019-07-07 * Time: 下午4:21 */ public class AdminServiceException extends ServiceException { public AdminServiceException(ServiceExceptionDefinition definition) { super(definition); } public AdminServiceException(String message, int code) { super(message,code); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/AppServiceException.java
New file @@ -0,0 +1,15 @@ package com.dobbinsoft.fw.core.exception; /** * Created by rize on 2019/7/1. */ public class AppServiceException extends ServiceException { public AppServiceException(ServiceExceptionDefinition definition) { super(definition); } public AppServiceException(String message, int code) { super(message,code); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/BizServiceException.java
New file @@ -0,0 +1,15 @@ package com.dobbinsoft.fw.core.exception; /** * Created by rize on 2019/7/1. */ public class BizServiceException extends ServiceException { public BizServiceException(ServiceExceptionDefinition definition) { super(definition); } public BizServiceException(String message, int code) { super(message,code); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/CoreExceptionDefinition.java
New file @@ -0,0 +1,25 @@ package com.dobbinsoft.fw.core.exception; /** * Created by rize on 2019/7/1. */ public class CoreExceptionDefinition { public static final ServiceExceptionDefinition THIRD_PART_SERVICE_EXCEPTION = new ServiceExceptionDefinition(0, "第三方服务异常"); public static final ServiceExceptionDefinition THIRD_PART_IO_EXCEPTION = new ServiceExceptionDefinition(0, "第三方服务网络异常"); public static ServiceExceptionDefinition buildVariableException(ServiceExceptionDefinition definition, String ...args) { String msg = definition.getMsg(); for (int i = 0; i < args.length; i++) { msg = msg.replace("${" + i + "}", args[i]); } return new ServiceExceptionDefinition(definition.getCode(), msg); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/ServiceException.java
New file @@ -0,0 +1,47 @@ package com.dobbinsoft.fw.core.exception; import java.io.Serializable; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2019-01-31 * Time: 下午8:07 */ public abstract class ServiceException extends Exception implements Serializable { private int code; private Object attach; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public Object getAttach() { return attach; } public ServiceException() { } public ServiceException(String message, int code) { super(message); this.code = code; } public ServiceException(ServiceExceptionDefinition definition) { super(definition.getMsg()); this.code = definition.getCode(); } public ServiceException attach(Object attach) { this.attach = attach; return this; } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/ServiceExceptionDefinition.java
New file @@ -0,0 +1,13 @@ package com.dobbinsoft.fw.core.exception; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class ServiceExceptionDefinition { private int code; private String msg; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/exception/ThirdPartServiceException.java
New file @@ -0,0 +1,17 @@ package com.dobbinsoft.fw.core.exception; /** * 第三方接口服务异常 * Created by rize on 2019/7/3. */ public class ThirdPartServiceException extends ServiceException { public ThirdPartServiceException(ServiceExceptionDefinition definition) { super(definition); } public ThirdPartServiceException(String message, int code) { super(message, code); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/model/GatewayResponse.java
New file @@ -0,0 +1,19 @@ package com.dobbinsoft.fw.core.model; import lombok.Data; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2018-08-12 * Time: 上午10:35 */ @Data public class GatewayResponse<T> { private int errno; private String errmsg; private T data; private long timestamp; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/util/GeneratorUtil.java
New file @@ -0,0 +1,45 @@ package com.dobbinsoft.fw.core.util; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; /** * Created by rize on 2019/7/1. */ public class GeneratorUtil { private static AtomicInteger orderIdCount = new AtomicInteger(); private static final SimpleDateFormat ORDER_ID_FORMAT = new SimpleDateFormat("yyyyMMHHmmss"); public static final String genSalt() { return genUUId().substring(0, 7); } public static String genSixVerifyCode() { String time = System.nanoTime() + ""; return time.substring(time.length() - 6); } public static String genSessionId() { return UUID.randomUUID().toString().replace("-","").toUpperCase(); } public static String genOrderId(String machineNo, String env) { int i = orderIdCount.incrementAndGet() % 1000; if (i < 1000) i += 1000; return env + machineNo + ORDER_ID_FORMAT.format(new Date()) + i; } public static String genFileName(){ return UUID.randomUUID().toString().replaceAll("-", ""); } public static String genUUId() { return UUID.randomUUID().toString().replace("-", ""); } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/util/ISessionUtil.java
New file @@ -0,0 +1,28 @@ package com.dobbinsoft.fw.core.util; import com.dobbinsoft.fw.core.entiy.inter.IdentityOwner; import com.dobbinsoft.fw.core.entiy.inter.PermissionOwner; import com.dobbinsoft.fw.core.exception.ServiceException; import java.util.List; /** * Session 相关抽取接口 */ public interface ISessionUtil<U extends IdentityOwner, A extends PermissionOwner> { public void setUser(U userDTO); public U getUser(); public void setAdmin(A adminDTO); public A getAdmin(); public Class<U> getUserClass(); public Class<A> getAdminClass(); public boolean hasPerm(String permission) throws ServiceException; } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/util/ReflectUtil.java
New file @@ -0,0 +1,223 @@ package com.dobbinsoft.fw.core.util; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * Description: * User: rize * Date: 2020/8/15 * Time: 11:01 */ public class ReflectUtil { /** * 通过Getter方法名称获取属性 * @param getterName * @return */ public static String getField(String getterName) { char[] dst = new char[getterName.length() - 3]; getterName.getChars(3, getterName.length(), dst, 0); if ('A' <= dst[0] && 'Z' >= dst[0]) { dst[0] = (char) (dst[0] + 32); } return new String(dst); } /** * 通过属性名获取 Getter 或 Setter * @param fieldName * @param prefix "get" | "set" * @return */ public static String getMethodName(String fieldName, String prefix) { char[] dst = new char[fieldName.length() + 3]; // 1. 将prefix搞进去 prefix.getChars(0, 3, dst, 0); // 2. 跟随考进去 fieldName.getChars(0, fieldName.length(), dst, 3); if ('a' <= dst[3] && 'z' >= dst[3]) { dst[3] = (char) (dst[3] - 32); } return new String(dst); } /** * 加载包字节码 * @return */ public static Map<String, byte[]> loadPackageBytes(String basePackage, boolean subPackage, boolean isInterface) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String fsBasePackage = basePackage.replace(".","/"); Map<String, byte[]> map = new HashMap<>(); try { Enumeration<URL> resources = classLoader.getResources(fsBasePackage); while(resources.hasMoreElements()) { //先获得本类的所在位置 URL url = resources.nextElement(); //url.getProtocol()是获取URL的HTTP协议。 if(url.getProtocol().equals("jar")) { //判断是不是jar包 JarURLConnection urlConnection = (JarURLConnection) url.openConnection(); JarFile jarfile = urlConnection.getJarFile(); Enumeration<JarEntry> jarEntries = jarfile.entries(); while(jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); String jarName = jarEntry.getName(); if(!jarName.endsWith(".class")) { continue; } String className = jarName.replace(".class", "").replaceAll("/", "."); if (!className.startsWith(basePackage)) { continue; } if (!subPackage) { if (!className.substring(0, className.lastIndexOf(".")).equals(basePackage)) { continue; } } if (checkClassType(isInterface, className)) { continue; } InputStream inputStream = null; try { String newUrl = url.toString().substring(0, url.toString().lastIndexOf("!") + 2) + jarName; URL classUrl = new URL(newUrl); URLConnection classUrlConnection = classUrl.openConnection(); inputStream = classUrlConnection.getInputStream(); byte[] bytes = IoUtil.readBytes(inputStream); map.put(className, bytes); } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } } } } else if (url.getProtocol().equals("file")) { // 文件系统,这是在开发的时候会用到 // file:/D:/develop/workspace/ideawork/unierp/unierp-data/target/classes/com/dobbinsoft/unierp/data/dto Map<String, File> classNameFileMap = getClassNameFileMap(new HashMap<>(), new File(url.getFile()), basePackage, subPackage); for (String className : classNameFileMap.keySet()) { if (checkClassType(isInterface, className)) { continue; } InputStream inputStream = null; try { File file = classNameFileMap.get(className); inputStream = new FileInputStream(file); byte[] bytes = IoUtil.readBytes(inputStream); map.put(className, bytes); } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } } } } else { throw new RuntimeException("不支持本包对象,请不要将接口和实体放入启动器中"); } } } catch (IOException e) { e.printStackTrace(); } return map; } private static boolean checkClassType(boolean isInterface, String className) { try { Class<?> klass = Class.forName(className); if (klass.isAnnotation() || klass.isEnum() || klass.isPrimitive()) { return true; } if (isInterface && !klass.isInterface()) { return true; } else if (!isInterface && klass.isInterface()) { return true; } } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException("未找到类:" + className); } return false; } /** * 递归获取baseDir下的类与文件映射 * @param map * @param baseDir * @return */ private static Map<String, File> getClassNameFileMap(Map<String, File> map, File baseDir, String basePackage, boolean subPackage) { if (baseDir == null || !baseDir.isDirectory()) { return map; } File[] files = baseDir.listFiles(); for (File file : files) { if (file.isDirectory() && subPackage) { // 不这么写 true idea 报黄,看着胀眼睛 getClassNameFileMap(map, file, basePackage, true); } else if (file.getName().endsWith("class")) { // 兼容 Windows String rawPackage = baseDir.toString().replace("\\", ".").replace("/", "."); String className = rawPackage.substring(rawPackage.indexOf(basePackage)) + "." + file.getName().replace(".class", ""); map.put(className, file); } } return map; } /** * 清理掉对象的空串属性 * @param object */ public static void clearEmptyString(Object object) { try { Class<?> clazz = object.getClass(); Field[] fields = clazz.getFields(); for (Field field : fields) { String getter = getMethodName(field.getName(), "get"); Method getterMethod = clazz.getMethod(getter); if (getterMethod != null) { Object res = getterMethod.invoke(object); if (res != null && res instanceof String) { // 若是返回String if (!"".equals(res)) { //设置为空 String setter = getMethodName(field.getName(), "set"); Method setterMethod = clazz.getMethod(setter); if (setterMethod != null) { setterMethod.invoke(object, null); } } } } } } catch (Exception e) { e.printStackTrace(); } } } dobbinfw-core/src/main/java/com/dobbinsoft/fw/core/util/SessionUtil.java
New file @@ -0,0 +1,83 @@ package com.dobbinsoft.fw.core.util; import com.dobbinsoft.fw.core.entiy.inter.IdentityOwner; import com.dobbinsoft.fw.core.entiy.inter.PermissionOwner; import com.dobbinsoft.fw.core.exception.ServiceException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; /** * Created by rize on 2019/2/27. * Edit by rize on 2021/3/16. */ public class SessionUtil<U extends IdentityOwner, A extends PermissionOwner> implements ISessionUtil<U, A> { private ThreadLocal<U> userLocal = new ThreadLocal<U>(); private ThreadLocal<A> adminLocal = new ThreadLocal<A>(); private Class<U> userClass; private Class<A> adminClass; public SessionUtil(Class<U> userClass, Class<A> adminClass) { this.userClass = userClass; this.adminClass = adminClass; } public void setUser(U userDTO) { userLocal.set(userDTO); } public U getUser() { return userLocal.get(); } public void setAdmin(A adminDTO) { adminLocal.set(adminDTO); } public A getAdmin() { return adminLocal.get(); } public Class<U> getUserClass() { return this.userClass; } public Class<A> getAdminClass() { return this.adminClass; } public boolean hasPerm(String permission) throws ServiceException { //拥有的权限 List<String> perms = getAdmin().getPerms(); boolean hasPerm = false; //目标匹配权限 String[] permissions = permission.split(":"); outer : for(String item : perms) { //拥有的权限点 String[] hasPer = item.split(":"); inner : for (int i = 0; i < permissions.length; i++) { if ("*".equals(hasPer[i])) { hasPerm = true; break outer; } else if (hasPer[i].equals(permissions[i])){ //此层合格 if (i == permissions.length - 1) { //若是目标层的最后一层。则表示所有层校验通过 hasPerm = true; } } else { break inner; } } } return hasPerm; } }