源对象类型
15 | * @param 目标对象类型
16 | * @return P对象
17 | */
18 | P convert(F source, Class entityClass);
19 | }
20 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/test/java/io/github/opensabre/persistence/entity/po/User.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity.po;
2 |
3 | import io.github.opensabre.persistence.entity.vo.UserVo;
4 | import lombok.*;
5 |
6 | import java.util.Date;
7 |
8 | @Data
9 | @NoArgsConstructor
10 | @RequiredArgsConstructor
11 | @EqualsAndHashCode(callSuper = true)
12 | public class User extends BasePo {
13 | @NonNull
14 | private String name;
15 | private Integer age;
16 | private String sex;
17 | private Date birthday;
18 | }
--------------------------------------------------------------------------------
/opensabre-starter-rpc/src/main/java/io/github/opensabre/rpc/openfeign/config/OpensabreFeignConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.rpc.openfeign.config;
2 |
3 | import io.github.opensabre.boot.config.YamlPropertyLoaderFactory;
4 | import org.springframework.boot.autoconfigure.AutoConfiguration;
5 | import org.springframework.context.annotation.PropertySource;
6 |
7 | @AutoConfiguration
8 | @PropertySource(value = {"classpath:opensabre-rpc.yml"}, encoding = "UTF8", factory = YamlPropertyLoaderFactory.class)
9 | public class OpensabreFeignConfig {
10 | }
11 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 | # 触发脚本的事件 这里为push代码之后触发
3 | on: [push]
4 | # 定义一个发行任务
5 | jobs:
6 | build:
7 | # 任务运行的环境
8 | runs-on: ubuntu-latest
9 | # 任务的步骤
10 | steps:
11 | # 1. 声明 checkout 仓库代码到工作区
12 | - uses: actions/checkout@v2
13 | # 2. 安装Java 环境 这里会用到的参数就是 Git Action secrets中配置的,
14 | - name: Set up JDK 17
15 | uses: actions/setup-java@v1
16 | with:
17 | java-version: 17
18 | # 3.编译打包
19 | - name: Build with Maven
20 | run: mvn -B package javadoc:javadoc --file pom.xml
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/log/desensitizer/NameLogBackDesensitizer.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.desensitizer;
2 |
3 | import io.github.opensabre.boot.sensitive.rule.DefaultSensitiveRule;
4 |
5 | /**
6 | * 姓名脱敏器
7 | * 日志中形如 姓名:张三 / name=李四 等形如此类的中文姓名敏感数据进行屏蔽
8 | *
9 | * @author zhoutaoo
10 | */
11 | public class NameLogBackDesensitizer extends PrefixLogBackDesensitizer {
12 |
13 | public NameLogBackDesensitizer() {
14 | super(DefaultSensitiveRule.NAME, 3);
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/opensabre-starter-cache/src/main/java/io/github/opensabre/cache/redis/JetCacheConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.cache.redis;
2 |
3 | import com.alicp.jetcache.autoconfigure.JetCacheAutoConfiguration;
4 | import org.springframework.boot.autoconfigure.AutoConfiguration;
5 | import org.springframework.context.annotation.PropertySource;
6 |
7 | /**
8 | * 打开Redis缓存配置类
9 | */
10 | @AutoConfiguration(before = JetCacheAutoConfiguration.class)
11 | @PropertySource(value = "classpath:opensabre-cache.properties", encoding = "UTF8")
12 | public class JetCacheConfig {
13 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/entity/RestMappingInfo.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.entity;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 | import lombok.RequiredArgsConstructor;
6 |
7 | /**
8 | * Rest注册信息
9 | */
10 | @Data
11 | @RequiredArgsConstructor
12 | public class RestMappingInfo {
13 | /**
14 | * Rest 的path url,如:/user/{name}
15 | */
16 | @NonNull
17 | private String url;
18 | /**
19 | * Rest 的方法,如:GET/POST ..
20 | */
21 | @NonNull
22 | private String method;
23 | }
24 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/event/DefaultAuditEventHandler.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.event;
2 |
3 | import lombok.NonNull;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.context.ApplicationListener;
6 |
7 | /**
8 | * 默认 AuditEvent Listener
9 | */
10 | @Slf4j
11 | public class DefaultAuditEventHandler implements ApplicationListener {
12 |
13 | @Override
14 | public void onApplicationEvent(@NonNull AuditEvent event) {
15 | log.info("AuditEvent received: {}", event);
16 | }
17 | }
--------------------------------------------------------------------------------
/opensabre-starter-register/src/main/java/io/github/opensabre/register/config/OpensabreDiscoveryConfiguration.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.register.config;
2 |
3 | import io.github.opensabre.boot.config.YamlPropertyLoaderFactory;
4 | import org.springframework.boot.autoconfigure.AutoConfiguration;
5 | import org.springframework.context.annotation.PropertySource;
6 |
7 | @AutoConfiguration
8 | @PropertySource(value = {"classpath:opensabre-register.yml"}, encoding = "UTF8", factory = YamlPropertyLoaderFactory.class)
9 | public class OpensabreDiscoveryConfiguration {
10 | }
11 |
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/entity/vo/BaseVo.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.entity.vo;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * VO对象的基类
11 | */
12 | @Data
13 | @NoArgsConstructor
14 | public class BaseVo implements Serializable {
15 | /**
16 | * VO对象唯一id
17 | */
18 | @Schema(title = "对象唯一id", description = "对象唯一id", requiredMode = Schema.RequiredMode.REQUIRED)
19 | private String id;
20 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/annotations/EnabledAudit.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.annotations;
2 |
3 | import io.github.opensabre.boot.aspect.AuditAspect;
4 | import io.github.opensabre.boot.event.DefaultAuditEventHandler;
5 | import org.springframework.context.annotation.Import;
6 |
7 | import java.lang.annotation.*;
8 |
9 | /**
10 | * 审计日志注解
11 | */
12 | @Target(ElementType.TYPE)
13 | @Retention(RetentionPolicy.RUNTIME)
14 | @Documented
15 | @Import({AuditAspect.class, DefaultAuditEventHandler.class})
16 | public @interface EnabledAudit {
17 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/entity/SwaggerInfo.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.entity;
2 |
3 | import lombok.Data;
4 | import org.springframework.boot.context.properties.ConfigurationProperties;
5 |
6 | @Data
7 | @ConfigurationProperties(prefix = "opensabre.rest.swagger")
8 | public class SwaggerInfo {
9 | private String version;
10 | private String title;
11 | private String description;
12 | private String licenseUrl;
13 | private String licenseName;
14 | private String wikiUrl;
15 | private String wikiDocumentation;
16 | }
17 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/config/OpensabreServiceConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.config;
2 |
3 |
4 | import io.github.opensabre.boot.event.OpensabreStartedEventHandler;
5 | import io.github.opensabre.boot.rest.MappingInfoHandler;
6 | import org.springframework.boot.autoconfigure.AutoConfiguration;
7 | import org.springframework.context.annotation.Import;
8 |
9 | /**
10 | * Opensabre Rest信息事件通知配置类
11 | */
12 | @AutoConfiguration
13 | @Import({OpensabreStartedEventHandler.class, MappingInfoHandler.class})
14 | public class OpensabreServiceConfig {
15 | }
16 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/test/java/io/github/opensabre/persistence/entity/form/UserForm.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity.form;
2 |
3 | import io.github.opensabre.common.web.entity.form.BaseForm;
4 | import io.github.opensabre.persistence.entity.po.User;
5 | import lombok.*;
6 |
7 | import java.util.Date;
8 |
9 | @Data
10 | @NoArgsConstructor
11 | @RequiredArgsConstructor
12 | @EqualsAndHashCode(callSuper = true)
13 | public class UserForm extends BaseForm {
14 | @NonNull
15 | private String name;
16 | private Integer age;
17 | private String sex;
18 | private Date birthday;
19 | }
20 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/log/desensitizer/PasswordLogBackDesensitizer.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.desensitizer;
2 |
3 | import io.github.opensabre.boot.sensitive.rule.DefaultSensitiveRule;
4 |
5 | /**
6 | * 密码的脱敏器
7 | * 在动态脱敏器没有初使化前,默认使用该脱敏器。
8 | * 主要对于系统启动时可能存在的敏感信息,如密码/凭证/key等。
9 | * 如 passwd:123456 / key=123456 等形如此类的敏感数据进行屏蔽
10 | *
11 | * @author zhoutaoo
12 | */
13 | public class PasswordLogBackDesensitizer extends PrefixLogBackDesensitizer {
14 |
15 | public PasswordLogBackDesensitizer() {
16 | super(DefaultSensitiveRule.PASSWORD, 3);
17 | }
18 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/test/java/io/github/opensabre/persistence/entity/form/UserQueryForm.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity.form;
2 |
3 | import io.github.opensabre.persistence.entity.param.UserParam;
4 | import lombok.Data;
5 | import lombok.EqualsAndHashCode;
6 | import lombok.NonNull;
7 | import lombok.RequiredArgsConstructor;
8 |
9 | import java.util.Date;
10 |
11 | @Data
12 | @RequiredArgsConstructor
13 | @EqualsAndHashCode(callSuper = true)
14 | public class UserQueryForm extends BaseQueryForm {
15 | @NonNull
16 | private String name;
17 | private Date createdTimeStart;
18 | private Date createdTimeEnd;
19 | }
20 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/test/java/io/github/opensabre/boot/crypt/JasyptTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.crypt;
2 |
3 | import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.junit.jupiter.api.Assertions.assertEquals;
7 |
8 | public class JasyptTest {
9 |
10 | @Test
11 | public void jasyptTest() {
12 | //加密工具
13 | StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
14 | //生成秘钥的公钥
15 | encryptor.setPassword("Pa55w0rd@opensabre");
16 | //加密
17 | String ciphertext = encryptor.decrypt("yLMBDZMhsJziMcceIT1IWw==");
18 | assertEquals("123456", ciphertext);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/log/desensitizer/LogBackDesensitizer.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.desensitizer;
2 |
3 | import ch.qos.logback.classic.spi.ILoggingEvent;
4 |
5 | /**
6 | * logback脱敏器
7 | *
8 | * @author zhoutaoo
9 | */
10 | public interface LogBackDesensitizer {
11 | /**
12 | * 是否支持脱敏
13 | *
14 | * @param event 日志事件
15 | * @return true/false 支持/不支持
16 | */
17 | boolean support(ILoggingEvent event);
18 |
19 | /**
20 | * 脱敏接口定义
21 | *
22 | * @param event 事件
23 | * @param originStr 原始字串
24 | * @return 脱敏后的字串
25 | */
26 | String desensitize(final ILoggingEvent event, String originStr);
27 | }
28 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ${AnsiColor.BRIGHT_YELLOW}${AnsiStyle.BOLD}
2 | ___ _
3 | / _ \ _ __ ___ _ __ ___ __ _ | |__ _ __ ___
4 | | | | | | '_ \ / _ \ | '_ \ / __| / _` | | '_ \ | '__| / _ \
5 | | |_| | | |_) | | __/ | | | | \__ \ | (_| | | |_) | | | | __/
6 | \___/ | .__/ \___| |_| |_| |___/ \__,_| |_.__/ |_| \___|
7 | |_|
8 | ${AnsiColor.CYAN}${AnsiStyle.BOLD}
9 | :: Java :: (v${java.version})
10 | :: Spring Boot :: ${spring-boot.formatted-version}
11 | :: Opensabre :: ${opensabre.formatted-version}
12 | :: Application :: (v${git.build.version})
13 | ${AnsiStyle.NORMAL}
--------------------------------------------------------------------------------
/opensabre-starter-rpc/src/main/java/io/github/opensabre/rpc/openfeign/config/OpensabreLoadBalancerConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.rpc.openfeign.config;
2 |
3 | import io.github.opensabre.boot.config.YamlPropertyLoaderFactory;
4 | import org.springframework.boot.autoconfigure.AutoConfiguration;
5 | import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
6 | import org.springframework.context.annotation.PropertySource;
7 |
8 | /**
9 | * 负载均衡配置
10 | */
11 | @AutoConfiguration
12 | @LoadBalancerClients(defaultConfiguration = OpensabreLoadBalancerBean.class)
13 | @PropertySource(value = {"classpath:opensabre-rpc.yml"}, encoding = "UTF8", factory = YamlPropertyLoaderFactory.class)
14 | public class OpensabreLoadBalancerConfig {
15 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/config/OpensabreBootConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.config;
2 |
3 | import io.github.opensabre.common.web.exception.DefaultGlobalExceptionHandlerAdvice;
4 | import io.github.opensabre.common.web.rest.RestResponseBodyAdvice;
5 | import org.springframework.boot.autoconfigure.AutoConfiguration;
6 | import org.springframework.context.annotation.Import;
7 | import org.springframework.context.annotation.PropertySource;
8 |
9 | /**
10 | * 初使化全局报文和全局异常配置
11 | */
12 | @AutoConfiguration
13 | @PropertySource(value = "classpath:opensabre-boot.properties", encoding = "UTF8")
14 | @Import({DefaultGlobalExceptionHandlerAdvice.class, RestResponseBodyAdvice.class})
15 | public class OpensabreBootConfig {
16 | }
17 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/resources/opensabre-persistence.properties:
--------------------------------------------------------------------------------
1 | # 默认mysql
2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3 | # 默认表名 _ 转驼峰
4 | mybatis-plus.configuration.map-underscore-to-camel-case=true
5 | # 逻辑已删除值(默认为 Y)
6 | mybatis-plus.global-config.db-config.logic-delete-value=Y
7 | # 逻辑未删除值(默认为 N)
8 | mybatis-plus.global-config.db-config.logic-not-delete-value=N
9 | #==============mybatis plugs插件默认===============#
10 | # 持久化mybatis分页插件,默认mysql
11 | opensabre.persistence.interceptor.pagination.enabled=true
12 | opensabre.persistence.interceptor.pagination.dbType=mysql
13 | # 持久化mybatis全表扫描插件
14 | opensabre.persistence.interceptor.blockattack.enabled=true
15 | # 持久化mybatis隐患sql插件
16 | opensabre.persistence.interceptor.illegalsql.enabled=false
17 |
--------------------------------------------------------------------------------
/opensabre-starter-rpc/src/main/resources/opensabre-rpc.yml:
--------------------------------------------------------------------------------
1 | feign:
2 | circuitbreaker:
3 | enabled: true
4 | sentinel:
5 | enabled: true
6 | httpclient:
7 | hc5:
8 | enabled: true
9 | compression:
10 | request:
11 | enabled: true
12 | response:
13 | enabled: true
14 | client:
15 | config:
16 | default:
17 | connectTimeout: 5000
18 | readTimeout: 10000
19 | loggerLevel: basic
20 | spring:
21 | cloud:
22 | sentinel:
23 | enabled: true
24 | datasource:
25 | opensabre:
26 | nacos:
27 | server-addr: ${REGISTER_HOST:localhost}:${REGISTER_PORT:8848}
28 | groupId: DEFAULT_GROUP
29 | dataId: ${spring.application.name}-sentinel.json
30 | rule-type: flow
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/rest/strategy/CustomSensitiveStrategy.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.rest.strategy;
2 |
3 | import io.github.opensabre.boot.sensitive.rule.SensitiveRule;
4 |
5 | /**
6 | * 自定义脱敏策略
7 | */
8 | public class CustomSensitiveStrategy implements SensitiveStrategy {
9 |
10 | private final SensitiveRule sensitiveRule;
11 |
12 | /**
13 | * @param sensitiveRule 脱敏规则
14 | */
15 | public CustomSensitiveStrategy(SensitiveRule sensitiveRule) {
16 | this.sensitiveRule = sensitiveRule;
17 | }
18 |
19 | /**
20 | * 脱敏处理
21 | *
22 | * @param str 原字符
23 | * @return 脱敏后的字符
24 | */
25 | public String desensitizing(SensitiveRule type, String str) {
26 | return sensitiveRule.replace(str);
27 | }
28 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/annotations/Audit.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.annotations;
2 |
3 | import java.lang.annotation.*;
4 |
5 | /**
6 | * 审计日志注解
7 | */
8 | @Target(ElementType.METHOD)
9 | @Retention(RetentionPolicy.RUNTIME)
10 | @Documented
11 | public @interface Audit {
12 |
13 | /**
14 | * 操作类型
15 | */
16 | OperationType operationType();
17 |
18 | /**
19 | * 操作描述
20 | */
21 | String description();
22 |
23 | /**
24 | * 操作模块
25 | */
26 | String module() default "";
27 |
28 | /**
29 | * 是否记录请求参数
30 | */
31 | boolean request() default true;
32 |
33 | /**
34 | * 是否记录响应结果
35 | */
36 | boolean response() default false;
37 |
38 | /**
39 | * 目标对象关键信息,可支持 spel
40 | */
41 | String key() default "";
42 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/entity/form/BaseForm.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.entity.form;
2 |
3 | import io.github.opensabre.common.web.entity.convert.EntityModelConverter;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import lombok.Data;
6 |
7 | import java.io.Serializable;
8 |
9 | @Data
10 | @Schema
11 | public class BaseForm implements Serializable {
12 | /**
13 | * 用户名
14 | */
15 | @Schema(title = "用户名", description = "Form提交时操作人的用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
16 | private String username;
17 |
18 | /**
19 | * Form转化为Po
20 | *
21 | * @param clazz Po类
22 | * @return 返回Po
23 | */
24 | public P toPo(Class
clazz) {
25 | return EntityModelConverter.getInstance().convert(this, clazz);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/config/YamlPropertyLoaderFactory.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.config;
2 |
3 | import lombok.NonNull;
4 | import org.springframework.boot.env.YamlPropertySourceLoader;
5 | import org.springframework.core.env.PropertySource;
6 | import org.springframework.core.io.support.DefaultPropertySourceFactory;
7 | import org.springframework.core.io.support.EncodedResource;
8 |
9 | import java.io.IOException;
10 |
11 | /**
12 | * 加载yaml的Factory
13 | */
14 | public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
15 |
16 | @Override
17 | public @NonNull PropertySource> createPropertySource(String name, EncodedResource resource) throws IOException {
18 | return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()).get(0);
19 | }
20 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/validator/Mobile.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.validator;
2 |
3 | import jakarta.validation.Constraint;
4 | import jakarta.validation.Payload;
5 | import java.lang.annotation.Documented;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | import static java.lang.annotation.ElementType.*;
10 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
11 |
12 | /**
13 | * 中国手机号校验器
14 | */
15 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
16 | @Retention(RUNTIME)
17 | @Constraint(validatedBy = MobileValidator.class)//标明由哪个类执行校验逻辑
18 | @Documented
19 | public @interface Mobile {
20 | /**
21 | * 校验失败提示信息
22 | *
23 | * @return 校验失败提示信息
24 | */
25 | String message() default "手机号格式错误";
26 |
27 | Class>[] groups() default {};
28 |
29 | Class extends Payload>[] payload() default {};
30 | }
31 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/rest/strategy/DefaultSensitiveStrategy.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.rest.strategy;
2 |
3 | import io.github.opensabre.boot.sensitive.rule.DefaultSensitiveRule;
4 | import io.github.opensabre.boot.sensitive.rule.SensitiveRule;
5 |
6 | import java.util.Arrays;
7 |
8 | import static io.github.opensabre.boot.sensitive.rule.DefaultSensitiveRule.values;
9 |
10 | /**
11 | * 默认的脱敏策略
12 | */
13 | public class DefaultSensitiveStrategy implements SensitiveStrategy {
14 |
15 | /**
16 | * 脱敏处理
17 | *
18 | * @param str 原字符
19 | * @return 脱敏后的字符
20 | */
21 | public String desensitizing(SensitiveRule type, String str) {
22 | DefaultSensitiveRule sensitiveRule = Arrays.stream(values()).sequential()
23 | .filter(rule -> rule.equals(type))
24 | .findFirst().orElse(DefaultSensitiveRule.CUSTOM);
25 | return sensitiveRule.replace(str);
26 | }
27 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/validator/MobileValidator.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.validator;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | import jakarta.validation.ConstraintValidator;
6 | import jakarta.validation.ConstraintValidatorContext;
7 | import java.util.regex.Pattern;
8 |
9 | /**
10 | * 手机号校验判定类
11 | */
12 | public class MobileValidator implements ConstraintValidator {
13 | /**
14 | * 中国手机号正则
15 | */
16 | public static final String REG_MOBILE = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
17 |
18 | @Override
19 | public void initialize(Mobile constraintAnnotation) {
20 | }
21 |
22 | @Override
23 | public boolean isValid(String value, ConstraintValidatorContext context) {
24 | //为空时不进行校验
25 | if (StringUtils.isBlank(value))
26 | return true;
27 | return Pattern.matches(REG_MOBILE, value);
28 | }
29 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/java/io/github/opensabre/persistence/exception/PersistenceExceptionHandlerAdvice.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.exception;
2 |
3 | import io.github.opensabre.common.core.entity.vo.Result;
4 | import io.github.opensabre.common.core.exception.SystemErrorType;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.core.annotation.Order;
7 | import org.springframework.dao.DuplicateKeyException;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.RestControllerAdvice;
10 |
11 | @Slf4j
12 | @Order(100)
13 | @RestControllerAdvice
14 | public class PersistenceExceptionHandlerAdvice {
15 |
16 | @ExceptionHandler(value = {DuplicateKeyException.class})
17 | public Result duplicateKeyException(DuplicateKeyException ex) {
18 | log.error("primary key duplication exception:{}", ex.getMessage());
19 | return Result.fail(SystemErrorType.DUPLICATE_PRIMARY_KEY);
20 | }
21 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/log/desensitizer/AbstractLogBackDesensitizer.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.desensitizer;
2 |
3 | import ch.qos.logback.classic.spi.ILoggingEvent;
4 |
5 | /**
6 | * 日志脱敏处理器抽象类
7 | *
8 | * @author zhoutaoo
9 | */
10 | public abstract class AbstractLogBackDesensitizer implements LogBackDesensitizer {
11 | /**
12 | * 如果实现类支持,再执行脱敏的动作
13 | *
14 | * @param event 日志事件
15 | * @param originStr 日志信息
16 | * @return 脱敏后的字符
17 | */
18 | @Override
19 | public String desensitize(ILoggingEvent event, String originStr) {
20 | if (support(event))
21 | return desensitizing(event, originStr);
22 | return originStr;
23 | }
24 |
25 | /**
26 | * 脱敏执行
27 | *
28 | * @param event 日志事件
29 | * @param originStr 日志信息
30 | * @return 脱敏后的字符
31 | */
32 | public abstract String desensitizing(ILoggingEvent event, String originStr);
33 | }
34 |
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/validator/EnumStringValidator.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.validator;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | import jakarta.validation.ConstraintValidator;
6 | import jakarta.validation.ConstraintValidatorContext;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | /**
11 | * 枚举字符串校验注解判定器
12 | */
13 | public class EnumStringValidator implements ConstraintValidator {
14 | /**
15 | * 枚举字串,被校验对象,包含在内的字串
16 | */
17 | private List enumStringList;
18 |
19 | @Override
20 | public void initialize(EnumString constraintAnnotation) {
21 | enumStringList = Arrays.asList(constraintAnnotation.value());
22 | }
23 |
24 | @Override
25 | public boolean isValid(String value, ConstraintValidatorContext context) {
26 | //值为空时不校验
27 | if (StringUtils.isBlank(value))
28 | return true;
29 | return enumStringList.contains(value);
30 | }
31 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/metadata/OpensabreVersion.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.metadata;
2 |
3 | /**
4 | * 获取opensabre版本信息
5 | */
6 | public class OpensabreVersion {
7 | /**
8 | * Opensabre版本号环境变量Key
9 | */
10 | public static final String OPENSABRE_VERSION = "opensabre.version";
11 | /**
12 | * Opensabre完整版本号环境变量Key
13 | */
14 | public static final String OPENSABRE_FORMATTED_VERSION = "opensabre.formatted-version";
15 | /**
16 | * 私有构造方法,不允许初使化实例
17 | */
18 | private OpensabreVersion() {
19 | }
20 |
21 | /**
22 | * 获取Opensabre版本号
23 | *
24 | * @return 版本号 如:1.x
25 | */
26 | public static String getVersion() {
27 | return OpensabreVersion.class.getPackage().getImplementationVersion();
28 | }
29 |
30 | /**
31 | * 获取Opensabre完整版本号
32 | *
33 | * @return 版本号,如:(v1.x.x)
34 | */
35 | public static String getVersionString() {
36 | return " (v" + getVersion() + ")";
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/opensabre-starter-register/src/main/java/io/github/opensabre/register/config/OpensabreNacosDiscoveryConfiguration.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.register.config;
2 |
3 | import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
4 | import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
5 | import jakarta.annotation.PostConstruct;
6 | import jakarta.annotation.Resource;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.boot.autoconfigure.AutoConfiguration;
9 |
10 | /**
11 | * 初使化元数据,将元数据注册到注册中心
12 | */
13 | @Slf4j
14 | @AutoConfiguration
15 | @ConditionalOnNacosDiscoveryEnabled
16 | public class OpensabreNacosDiscoveryConfiguration {
17 |
18 | @Resource
19 | private NacosDiscoveryProperties nacosDiscoveryProperties;
20 |
21 | /**
22 | * 将Opensabre元数据注册到注册中心
23 | */
24 | @PostConstruct
25 | public void initNacos() {
26 | log.info("Opensabre Metadata Register NacosDiscoveryConfig");
27 | // 原来的元数据全部不变
28 | nacosDiscoveryProperties.getMetadata().putAll(new Metadata().getMetadata());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/resources/META-INF/spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "groups": [
3 | ],
4 | "properties": [
5 | {
6 | "name": "opensabre.rest.result.framework.excludes",
7 | "type": "java.lang.String",
8 | "description": "Opensabre Framework Restful Unified Response Packet Format Exclusion Package Name, Multiple Package Names Are Separated By ',' ."
9 | },
10 | {
11 | "name": "opensabre.rest.result.excludes",
12 | "type": "java.lang.String",
13 | "description": "Opensabre Application Restful Unified Response Packet Format Exclusion Package Name, Multiple Package Names Are Separated By ',' ."
14 | },
15 | {
16 | "name": "opensabre.sensitive.log.enabled",
17 | "type": "java.lang.Boolean",
18 | "description": "Opensabre Application Sensitive log Enabled, Default is 'true' ."
19 | },
20 | {
21 | "name": "opensabre.sensitive.log.rules",
22 | "type": "java.lang.String",
23 | "description": "Opensabre Application Sensitive log rules, Default is 'mobile,idCard,phone' ."
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "groups": [
3 | ],
4 | "properties": [
5 | {
6 | "name": "opensabre.rest.result.framework.excludes",
7 | "type": "java.lang.String",
8 | "description": "Opensabre Framework Restful Unified Response Packet Format Exclusion Package Name, Multiple Package Names Are Separated By ',' ."
9 | },
10 | {
11 | "name": "opensabre.rest.result.excludes",
12 | "type": "java.lang.String",
13 | "description": "Opensabre Application Restful Unified Response Packet Format Exclusion Package Name, Multiple Package Names Are Separated By ',' ."
14 | },
15 | {
16 | "name": "opensabre.sensitive.log.enabled",
17 | "type": "java.lang.Boolean",
18 | "description": "Opensabre Application Sensitive log Enabled, Default is 'true' ."
19 | },
20 | {
21 | "name": "opensabre.sensitive.log.rules",
22 | "type": "java.lang.String",
23 | "description": "Opensabre Application Sensitive log rules, Default is 'mobile,idCard,phone' ."
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | bus:
4 | trace:
5 | enabled: true
6 | format:
7 | date-time: yyyy-MM-dd HH:mm:ss
8 | date: yyyy-MM-dd
9 | servlet:
10 | multipart:
11 | max-request-size: "2MB"
12 | max-file-size: "2MB"
13 | jackson:
14 | time-zone: GMT+8
15 | date-format: yyyy-MM-dd HH:mm:ss
16 | # 优雅停机
17 | server:
18 | shutdown: graceful
19 | # 配置项加密密钥默认配置
20 | jasypt:
21 | encryptor:
22 | password: ${JASYPT_ENCRYPTOR_PASSWORD:Pa55w0rd@opensabre}
23 | # opensabre framework配置
24 | opensabre:
25 | sensitive:
26 | log:
27 | enabled: true # 日志脱敏开关,默认关闭
28 | rules: mobile,idCard,phone
29 | rest:
30 | result:
31 | framework:
32 | excludes: org.springdoc # 统一报文排除的包名,该包下的rest不使用统一报文,框架内置
33 | excludes: # 统一报文排除的包名,该包下的rest不使用统一报文,应用级配置
34 | # 日志相关
35 | logging:
36 | level:
37 | io.github.opensabre: info
38 | logback:
39 | rollingpolicy:
40 | max-file-size: 1GB
41 | file:
42 | path: logs
43 | config: classpath:logback-spring.xml
44 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/test/java/io/github/opensabre/persistence/exception/PersistenceExceptionHandlerAdviceTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.exception;
2 |
3 | import io.github.opensabre.common.core.entity.vo.Result;
4 | import io.github.opensabre.common.core.exception.SystemErrorType;
5 | import org.junit.jupiter.api.BeforeEach;
6 | import org.junit.jupiter.api.Test;
7 | import org.springframework.dao.DuplicateKeyException;
8 |
9 | import static org.junit.jupiter.api.Assertions.assertEquals;
10 |
11 | class PersistenceExceptionHandlerAdviceTest {
12 |
13 | private PersistenceExceptionHandlerAdvice persistenceExceptionHandlerAdvice;
14 |
15 | @BeforeEach
16 | public void before() {
17 | this.persistenceExceptionHandlerAdvice = new PersistenceExceptionHandlerAdvice();
18 | }
19 |
20 | @Test
21 | public void testDuplicateKeyException() {
22 | Result result = persistenceExceptionHandlerAdvice.duplicateKeyException(new DuplicateKeyException("主键重复"));
23 | assertEquals(SystemErrorType.DUPLICATE_PRIMARY_KEY.getCode(), result.getCode());
24 | }
25 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/core/exception/BaseException.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.core.exception;
2 |
3 | import lombok.Getter;
4 |
5 | @Getter
6 | public class BaseException extends RuntimeException {
7 | /**
8 | * 异常对应的错误类型
9 | */
10 | private final ErrorType errorType;
11 |
12 | /**
13 | * 默认是系统异常
14 | */
15 | public BaseException() {
16 | this.errorType = SystemErrorType.SYSTEM_ERROR;
17 | }
18 |
19 | /**
20 | * @param errorType 错误类型
21 | */
22 | public BaseException(ErrorType errorType) {
23 | this.errorType = errorType;
24 | }
25 |
26 | /**
27 | * @param errorType 错误类型
28 | * @param message 错误信息
29 | */
30 | public BaseException(ErrorType errorType, String message) {
31 | super(message);
32 | this.errorType = errorType;
33 | }
34 |
35 | /**
36 | * @param errorType 错误类型
37 | * @param message 错误信息
38 | * @param cause 异常
39 | */
40 | public BaseException(ErrorType errorType, String message, Throwable cause) {
41 | super(message, cause);
42 | this.errorType = errorType;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/event/OpensabreSensitiveDesensitizerProcessor.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.event;
2 |
3 | import io.github.opensabre.boot.sensitive.log.desensitizer.LogBackDesensitizer;
4 | import io.github.opensabre.boot.sensitive.log.strategy.DefaultDesensitizerStrategy;
5 | import lombok.NonNull;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.beans.BeansException;
8 | import org.springframework.beans.factory.config.BeanPostProcessor;
9 |
10 | import jakarta.annotation.Resource;
11 |
12 | @Slf4j
13 | public class OpensabreSensitiveDesensitizerProcessor implements BeanPostProcessor {
14 |
15 | @Resource
16 | private DefaultDesensitizerStrategy defaultDesensitizerStrategy;
17 |
18 | @Override
19 | public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
20 | // LogBackDesensitizer的实例自动加载
21 | if (bean instanceof LogBackDesensitizer) {
22 | log.info("postProcessAfterInitialization==> Bean Name: {}", beanName);
23 | defaultDesensitizerStrategy.addDesensitizer((LogBackDesensitizer) bean);
24 | }
25 | return bean;
26 | }
27 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/resources/META-INF/spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "groups": [
3 | ],
4 | "properties": [
5 | {
6 | "name": "opensabre.persistence.interceptor.pagination.enabled",
7 | "type": "java.lang.Boolean",
8 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, PaginationInnerInterceptor Enabled, Default Is true ."
9 | },
10 | {
11 | "name": "opensabre.persistence.interceptor.pagination.DbType",
12 | "type": "java.lang.String",
13 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, PaginationInnerInterceptor DbType Default DbType is mysql ."
14 | },
15 | {
16 | "name": "opensabre.persistence.interceptor.blockattack.enabled",
17 | "type": "java.lang.Boolean",
18 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, BlockAttackInnerInterceptor Default Is true ."
19 | },
20 | {
21 | "name": "opensabre.persistence.interceptor.illegalsql.enabled",
22 | "type": "java.lang.Boolean",
23 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, IllegalSQLInnerInterceptor Default Is false ."
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/java/io/github/opensabre/persistence/entity/param/BaseParam.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity.param;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.io.Serializable;
8 | import java.util.Date;
9 |
10 | /**
11 | * Created by zhoutaoo on 2018/6/1.
12 | *
13 | * @author zhoutaoo
14 | */
15 | @Data
16 | @NoArgsConstructor
17 | public class BaseParam implements Serializable {
18 | @Schema(title = "开始时间", description = "查询条件创建记录的开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example="2020-05-06 12:23:23")
19 | private Date createdTimeStart;
20 | @Schema(title = "结束时间", description = "查询条件创建记录的结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example="2020-05-12 12:23:23")
21 | private Date createdTimeEnd;
22 |
23 | // public QueryWrapper build() {
24 | // QueryWrapper queryWrapper = new QueryWrapper<>();
25 | // queryWrapper.ge(null != this.createdTimeStart, "created_time", this.createdTimeStart)
26 | // .le(null != this.createdTimeEnd, "created_time", this.createdTimeEnd);
27 | // return queryWrapper;
28 | // }
29 | }
30 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/resources/META-INF/additional-spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "groups": [
3 | ],
4 | "properties": [
5 | {
6 | "name": "opensabre.persistence.interceptor.pagination.enabled",
7 | "type": "java.lang.Boolean",
8 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, PaginationInnerInterceptor Enabled, Default Is true ."
9 | },
10 | {
11 | "name": "opensabre.persistence.interceptor.pagination.DbType",
12 | "type": "java.lang.String",
13 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, PaginationInnerInterceptor DbType Default DbType is mysql ."
14 | },
15 | {
16 | "name": "opensabre.persistence.interceptor.blockattack.enabled",
17 | "type": "java.lang.Boolean",
18 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, BlockAttackInnerInterceptor Default Is true ."
19 | },
20 | {
21 | "name": "opensabre.persistence.interceptor.illegalsql.enabled",
22 | "type": "java.lang.Boolean",
23 | "description": "Opensabre Framework Persistence Mybatis Plugs Interceptor, IllegalSQLInnerInterceptor Default Is false ."
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/entity/convert/EntityModelConverter.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.entity.convert;
2 |
3 | import lombok.SneakyThrows;
4 | import org.springframework.beans.BeanUtils;
5 |
6 | /**
7 | * 对象转换工具类
8 | * @author zhoutaoo
9 | */
10 | public class EntityModelConverter implements EntityConverter {
11 | private EntityModelConverter() {
12 | }
13 |
14 | /**
15 | * 返回实例
16 | *
17 | * @return 单例
18 | */
19 | public static EntityModelConverter getInstance() {
20 | return SingletonHolder.sInstance;
21 | }
22 |
23 | /**
24 | * 静态内部类单例模式
25 | * 单例初使化
26 | */
27 | private static class SingletonHolder {
28 | private static final EntityModelConverter sInstance = new EntityModelConverter();
29 | }
30 |
31 | /**
32 | * 将源对象转换为 目标对象
33 | *
34 | * @param source 源对象
35 | * @param targetClass 目标对象类型
36 | * @return 目标对象
37 | */
38 | @SneakyThrows
39 | public P convert(F source, Class targetClass) {
40 | P target = targetClass.getDeclaredConstructor().newInstance();
41 | BeanUtils.copyProperties(source, target);
42 | return target;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/event/OpensabreStartedEventHandler.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.event;
2 |
3 | import io.github.opensabre.boot.rest.MappingInfoHandler;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.context.event.ApplicationReadyEvent;
6 | import org.springframework.context.ApplicationContext;
7 | import org.springframework.context.ApplicationListener;
8 |
9 | import jakarta.annotation.Resource;
10 |
11 | /**
12 | * springboot应用启动完成后,发送Rest注册事件
13 | */
14 | @Slf4j
15 | public class OpensabreStartedEventHandler implements ApplicationListener {
16 | /**
17 | * spring上下文
18 | */
19 | @Resource
20 | private ApplicationContext context;
21 | /**
22 | * Rest信息获取处对象
23 | */
24 | @Resource
25 | MappingInfoHandler mappingInfoHandler;
26 |
27 | @Override
28 | public void onApplicationEvent(ApplicationReadyEvent event) {
29 | log.info("ApplicationReadyEvent received");
30 | mappingInfoHandler.getMappingInfo().forEach(mappingInfo -> {
31 | context.publishEvent(new MappingRegisteredEvent(mappingInfo));
32 | log.info("Mapping Registered :{}", mappingInfo);
33 | });
34 | }
35 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/metadata/OpensabreCloud.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.metadata;
2 |
3 | /**
4 | * 获取opensabre cloud相关信息,用于支持云原生多活等
5 | */
6 | public class OpensabreCloud {
7 | /**
8 | * Opensabre云部署AZ环境变量Key
9 | */
10 | public static final String OPENSABRE_CLOUD_AZ = "opensabre.cloud.az";
11 | /**
12 | * Opensabre云部署REGION环境变量Key
13 | */
14 | public static final String OPENSABRE_CLOUD_REGION = "opensabre.cloud.region";
15 | /**
16 | * 云部署时环境变量,代表可用区
17 | */
18 | public static final String ENV_CLOUD_AZ = "CLOUD_AZ";
19 | /**
20 | * 云部署时环境变量,代表地区
21 | */
22 | public static final String ENV_CLOUD_REGION = "CLOUD_REGION";
23 |
24 | /**
25 | * 私有构造方法,不允许初使化实例
26 | */
27 | private OpensabreCloud() {
28 | }
29 |
30 | /**
31 | * 从环境变量中获取Opensabre部署AZ信息
32 | *
33 | * @return 云环境AZ可用区代号
34 | */
35 | public static String getCloudAz() {
36 | return System.getenv(ENV_CLOUD_AZ);
37 | }
38 |
39 | /**
40 | * 从环境变量中获取Opensabre部署REGION信息
41 | *
42 | * @return 云环境REGION地域
43 | */
44 | public static String getCloudRegion() {
45 | return System.getenv(ENV_CLOUD_REGION);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/opensabre-starter-register/src/main/java/io/github/opensabre/register/config/Metadata.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.register.config;
2 |
3 | import io.github.opensabre.boot.metadata.OpensabreCloud;
4 | import io.github.opensabre.boot.metadata.OpensabreVersion;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | import static io.github.opensabre.boot.metadata.OpensabreCloud.OPENSABRE_CLOUD_AZ;
10 | import static io.github.opensabre.boot.metadata.OpensabreCloud.OPENSABRE_CLOUD_REGION;
11 | import static io.github.opensabre.boot.metadata.OpensabreVersion.OPENSABRE_VERSION;
12 |
13 | /**
14 | * 应用元数据类
15 | */
16 | public class Metadata {
17 |
18 | /**
19 | * 元数据存储容器
20 | */
21 | private final Map metadata = new HashMap<>();
22 |
23 | /**
24 | * 构建方法内初使化元数据
25 | */
26 | public Metadata() {
27 | metadata.put(OPENSABRE_VERSION, OpensabreVersion.getVersion());
28 | metadata.put(OPENSABRE_CLOUD_AZ, OpensabreCloud.getCloudAz());
29 | metadata.put(OPENSABRE_CLOUD_REGION, OpensabreCloud.getCloudRegion());
30 | }
31 |
32 | /**
33 | * 获取全部元数据
34 | *
35 | * @return all metadata
36 | */
37 | public Map getMetadata() {
38 | return metadata;
39 | }
40 | }
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # 相当于脚本用途的一个声明
2 | name: Maven Central Repo Deployment
3 | # 触发脚本的事件 这里为发布release之后触发
4 | on:
5 | release:
6 | types: [released]
7 | # 定义一个发行任务
8 | jobs:
9 | publish:
10 | # 任务运行的环境
11 | runs-on: ubuntu-latest
12 | # 任务的步骤
13 | steps:
14 | # 1. 声明 checkout 仓库代码到工作区
15 | - name: Checkout Git Repo
16 | uses: actions/checkout@v2
17 | # 2. 安装Java 环境 这里会用到的参数就是 Git Action secrets中配置的,
18 | # 取值要在key前面加 secrets.
19 | - name: Set up Maven Central Repo
20 | uses: actions/setup-java@v1
21 | with:
22 | java-version: 17
23 | server-id: sonatype-nexus-staging
24 | server-username: ${{ secrets.OSSRH_USER }}
25 | server-password: ${{ secrets.OSSRH_PASSWORD }}
26 | gpg-passphrase: ${{ secrets.GPG_PASSWORD }}
27 | # 3. 发布到Maven中央仓库
28 | - name: Publish to Maven Central Repo
29 | # 这里用到了其他人写的action脚本,详细可以去看他的文档。
30 | uses: samuelmeuli/action-maven-publish@v1
31 | with:
32 | server_id: ossrh
33 | gpg_private_key: ${{ secrets.GPG_SECRET }}
34 | gpg_passphrase: ${{ secrets.GPG_PASSWORD }}
35 | nexus_username: ${{ secrets.OSSRH_USER }}
36 | nexus_password: ${{ secrets.OSSRH_PASSWORD }}
--------------------------------------------------------------------------------
/opensabre-starter-rpc/src/main/java/io/github/opensabre/rpc/openfeign/config/OpensabreLoadBalancerBean.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.rpc.openfeign.config;
2 |
3 | import io.github.opensabre.rpc.loadbalance.OpensabreLoadBalancer;
4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
5 | import org.springframework.cloud.client.ServiceInstance;
6 | import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
7 | import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
8 | import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.core.env.Environment;
11 |
12 | public class OpensabreLoadBalancerBean {
13 | @Bean
14 | @ConditionalOnMissingBean
15 | public ReactorLoadBalancer reactorServiceInstanceLoadBalancer(Environment environment,
16 | LoadBalancerClientFactory loadBalancerClientFactory) {
17 | String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
18 | return new OpensabreLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
19 | }
20 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/annotations/Desensitization.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.annotations;
2 |
3 | import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
4 | import com.fasterxml.jackson.databind.annotation.JsonSerialize;
5 | import io.github.opensabre.boot.sensitive.rest.DesensitizationSerialize;
6 | import io.github.opensabre.boot.sensitive.rule.DefaultSensitiveRule;
7 |
8 | import java.lang.annotation.ElementType;
9 | import java.lang.annotation.Retention;
10 | import java.lang.annotation.RetentionPolicy;
11 | import java.lang.annotation.Target;
12 |
13 | @Retention(RetentionPolicy.RUNTIME)
14 | @Target(ElementType.FIELD)
15 | @JacksonAnnotationsInside
16 | @JsonSerialize(using = DesensitizationSerialize.class)
17 | public @interface Desensitization {
18 |
19 | /**
20 | * 脱敏数据类型,只有在CUSTOM的时候,retainPrefixCount和retainSuffixCount生效
21 | *
22 | * @return 脱敏器类型 type
23 | */
24 | DefaultSensitiveRule type() default DefaultSensitiveRule.CUSTOM;
25 |
26 | /**
27 | * @return 保留前缀个数
28 | */
29 | int retainPrefixCount() default 0;
30 |
31 | /**
32 | * @return 保留后缀个数
33 | */
34 | int retainSuffixCount() default 0;
35 |
36 | /**
37 | * @return 掩码符号
38 | */
39 | char replaceChar() default '*';
40 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/test/java/io/github/opensabre/boot/sensitive/log/desensitizer/NameLogBackDesensitizerTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.desensitizer;
2 |
3 | import ch.qos.logback.classic.spi.LoggingEvent;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.junit.jupiter.api.Assertions.assertEquals;
7 |
8 | class NameLogBackDesensitizerTest {
9 |
10 | @Test
11 | void desensitizing() {
12 | NameLogBackDesensitizer nameLogBackDesensitizer = new NameLogBackDesensitizer();
13 | LoggingEvent loggingEvent = new LoggingEvent();
14 | assertEquals("name : 张*", nameLogBackDesensitizer.desensitizing(loggingEvent, "name : 张三"));
15 | assertEquals("name: 张**", nameLogBackDesensitizer.desensitizing(loggingEvent, "name: 张三小"));
16 | assertEquals("name is 张**", nameLogBackDesensitizer.desensitizing(loggingEvent, "name is 张三小"));
17 | assertEquals("姓名:李**", nameLogBackDesensitizer.desensitizing(loggingEvent, "姓名:李四大"));
18 | assertEquals("姓名=李**", nameLogBackDesensitizer.desensitizing(loggingEvent, "姓名=李四大"));
19 | assertEquals("姓名>>李*****", nameLogBackDesensitizer.desensitizing(loggingEvent, "姓名>>李四大买买提"));
20 | assertEquals("姓名<李*****提", nameLogBackDesensitizer.desensitizing(loggingEvent, "姓名<李四大买买提提"));
21 | }
22 | }
--------------------------------------------------------------------------------
/opensabre-starter-register/src/main/java/io/github/opensabre/register/config/OpensabreNacosProjectConfiguration.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.register.config;
2 |
3 | import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
4 | import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.apache.commons.lang3.StringUtils;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.boot.autoconfigure.AutoConfiguration;
9 | import org.springframework.boot.autoconfigure.AutoConfigureBefore;
10 | import org.springframework.context.EnvironmentAware;
11 | import org.springframework.core.env.Environment;
12 |
13 | /**
14 | * 初使nacos的projectName,解决默认的订阅者应用名为空的问题
15 | */
16 | @Slf4j
17 | @AutoConfiguration
18 | @ConditionalOnNacosDiscoveryEnabled
19 | @AutoConfigureBefore({NacosDiscoveryClientConfiguration.class})
20 | public class OpensabreNacosProjectConfiguration implements EnvironmentAware {
21 |
22 | @Value("${spring.application.name}")
23 | private String applicationName;
24 |
25 | @Override
26 | public void setEnvironment(Environment environment) {
27 | if (StringUtils.isBlank(System.getProperty("project.name"))) {
28 | System.setProperty("project.name", applicationName);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/opensabre-web/src/test/java/io/github/opensabre/common/web/interceptor/UserInterceptorTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.interceptor;
2 |
3 | import io.github.opensabre.common.core.util.UserContextHolder;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.mock.web.MockHttpServletRequest;
6 | import org.springframework.mock.web.MockHttpServletResponse;
7 |
8 | import static org.junit.jupiter.api.Assertions.assertEquals;
9 | import static org.junit.jupiter.api.Assertions.assertTrue;
10 |
11 | public class UserInterceptorTest {
12 | @Test
13 | public void preHandle_当未设置token_user_那么正常处理下一个handle() throws Exception {
14 | UserInterceptor userInterceptor = new UserInterceptor();
15 | assertTrue(userInterceptor.preHandle(new MockHttpServletRequest(), new MockHttpServletResponse(), new Object()));
16 | }
17 |
18 | @Test
19 | public void preHandle_当设置token的username_那么username可以在线程中拿出来用() throws Exception {
20 | UserInterceptor userInterceptor = new UserInterceptor();
21 | MockHttpServletRequest request = new MockHttpServletRequest();
22 | request.addHeader("x-client-token-user", "{\"user_name\":\"zhangsan\"}");
23 | userInterceptor.preHandle(request, new MockHttpServletResponse(), new Object());
24 | assertEquals(UserContextHolder.getInstance().getUsername(), "zhangsan");
25 | }
26 | }
--------------------------------------------------------------------------------
/opensabre-starter-webmvc/src/test/java/io/github/opensabre/webmvc/interceptor/UserInterceptorTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.webmvc.interceptor;
2 |
3 | import io.github.opensabre.common.core.util.UserContextHolder;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.mock.web.MockHttpServletRequest;
6 | import org.springframework.mock.web.MockHttpServletResponse;
7 |
8 | import static org.junit.jupiter.api.Assertions.assertEquals;
9 | import static org.junit.jupiter.api.Assertions.assertTrue;
10 |
11 | public class UserInterceptorTest {
12 | @Test
13 | public void preHandle_当未设置token_user_那么正常处理下一个handle() throws Exception {
14 | UserInterceptor userInterceptor = new UserInterceptor();
15 | assertTrue(userInterceptor.preHandle(new MockHttpServletRequest(), new MockHttpServletResponse(), new Object()));
16 | }
17 |
18 | @Test
19 | public void preHandle_当设置token的username_那么username可以在线程中拿出来用() throws Exception {
20 | UserInterceptor userInterceptor = new UserInterceptor();
21 | MockHttpServletRequest request = new MockHttpServletRequest();
22 | request.addHeader("x-client-token-user", "{\"user_name\":\"zhangsan\"}");
23 | userInterceptor.preHandle(request, new MockHttpServletResponse(), new Object());
24 | assertEquals(UserContextHolder.getInstance().getUsername(), "zhangsan");
25 | }
26 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/log/strategy/DefaultDesensitizerStrategy.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.log.strategy;
2 |
3 | import ch.qos.logback.classic.spi.ILoggingEvent;
4 | import com.google.common.collect.Sets;
5 | import io.github.opensabre.boot.sensitive.log.desensitizer.LogBackDesensitizer;
6 | import io.github.opensabre.boot.sensitive.log.desensitizer.PasswordLogBackDesensitizer;
7 |
8 | import java.util.Set;
9 | import java.util.concurrent.atomic.AtomicReference;
10 |
11 | /**
12 | * 默认脱敏策略
13 | * 可支持多个脱敏器,循环使用全部脱敏器处理一次
14 | */
15 | public class DefaultDesensitizerStrategy implements DesensitizerStrategy {
16 | /**
17 | * 默认的脱敏器
18 | */
19 | private final Set desensitizers = Sets.newHashSet(new PasswordLogBackDesensitizer());
20 |
21 | @Override
22 | public String desensitizing(ILoggingEvent event) {
23 | AtomicReference message = new AtomicReference<>(event.getFormattedMessage());
24 | desensitizers.forEach(desensitizer -> {
25 | message.set(desensitizer.desensitize(event, message.get()));
26 | });
27 | return message.get();
28 | }
29 |
30 | /**
31 | * 追回脱敏器
32 | *
33 | * @param logBackDesensitizer 脱敏器
34 | */
35 | public void addDesensitizer(LogBackDesensitizer logBackDesensitizer) {
36 | desensitizers.add(logBackDesensitizer);
37 | }
38 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/java/io/github/opensabre/persistence/handler/PoMetaObjectHandler.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.handler;
2 |
3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
4 | import io.github.opensabre.common.core.util.UserContextHolder;
5 | import io.github.opensabre.persistence.entity.po.BasePo;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.apache.ibatis.reflection.MetaObject;
9 |
10 | import java.time.Instant;
11 | import java.util.Date;
12 |
13 | @Slf4j
14 | public class PoMetaObjectHandler implements MetaObjectHandler {
15 | /**
16 | * 获取当前交易的用户,为空返回默认system
17 | *
18 | * @return CurrentUsername
19 | */
20 | private String getCurrentUsername() {
21 | return StringUtils.defaultIfBlank(UserContextHolder.getInstance().getUsername(), BasePo.DEFAULT_USERNAME);
22 | }
23 |
24 | @Override
25 | public void insertFill(MetaObject metaObject) {
26 | this.strictInsertFill(metaObject, "createdBy", String.class, getCurrentUsername());
27 | this.strictInsertFill(metaObject, "createdTime", Date.class, Date.from(Instant.now()));
28 | this.updateFill(metaObject);
29 | }
30 |
31 | @Override
32 | public void updateFill(MetaObject metaObject) {
33 | this.strictUpdateFill(metaObject, "updatedBy", String.class, getCurrentUsername());
34 | this.strictUpdateFill(metaObject, "updatedTime", Date.class, Date.from(Instant.now()));
35 | }
36 | }
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/web/validator/EnumString.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.web.validator;
2 |
3 | import jakarta.validation.Constraint;
4 | import jakarta.validation.Payload;
5 |
6 | import java.lang.annotation.Documented;
7 | import java.lang.annotation.Repeatable;
8 | import java.lang.annotation.Retention;
9 | import java.lang.annotation.Target;
10 |
11 | import static java.lang.annotation.ElementType.*;
12 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
13 |
14 | /**
15 | * 枚举字符串校验器
16 | * 字段值只能为 value数组中的值
17 | */
18 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
19 | @Retention(RUNTIME)
20 | @Repeatable(EnumString.List.class)
21 | @Documented
22 | @Constraint(validatedBy = EnumStringValidator.class)//标明由哪个类执行校验逻辑
23 | public @interface EnumString {
24 | /**
25 | * 校验失败默认的提示信息
26 | *
27 | * @return 提示词
28 | */
29 | String message() default "类型只能为 value 列表内的值";
30 |
31 | Class>[] groups() default {};
32 |
33 | Class extends Payload>[] payload() default {};
34 |
35 | /**
36 | * @return data must in this value array
37 | */
38 | String[] value();
39 |
40 | /**
41 | * Defines several {@link EnumString} annotations on the same element.
42 | *
43 | * @see EnumString
44 | */
45 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
46 | @Retention(RUNTIME)
47 | @Documented
48 | @interface List {
49 | EnumString[] value();
50 | }
51 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/entity/AuditInfo.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.entity;
2 |
3 | import lombok.*;
4 |
5 | import java.time.LocalDateTime;
6 |
7 | import io.github.opensabre.boot.annotations.OperationType;
8 |
9 | /**
10 | * 审计日志实体
11 | */
12 | @Data
13 | @Builder
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class AuditInfo {
17 |
18 | /**
19 | * 操作类型
20 | */
21 | private OperationType operationType;
22 |
23 | /**
24 | * 操作时间
25 | */
26 | private LocalDateTime operationTime;
27 |
28 | /**
29 | * 操作人用户名
30 | */
31 | private String operatorUsername;
32 |
33 | /**
34 | * 操作描述
35 | */
36 | private String description;
37 |
38 | /**
39 | * 操作模块
40 | */
41 | private String module;
42 |
43 | /**
44 | * 操作IP地址
45 | */
46 | private String clientIp;
47 |
48 | /**
49 | * 用户代理
50 | */
51 | private String userAgent;
52 |
53 | /**
54 | * 请求方法
55 | */
56 | private String requestMethod;
57 |
58 | /**
59 | * 请求URL
60 | */
61 | private String requestUrl;
62 |
63 | /**
64 | * 请求参数
65 | */
66 | private String request;
67 |
68 | /**
69 | * 操作结果
70 | */
71 | private String response;
72 |
73 | /**
74 | * 错误信息
75 | */
76 | private String errorMessage;
77 |
78 | /**
79 | * 执行时间(毫秒)
80 | */
81 | private Long executionTime;
82 |
83 | /**
84 | * 操作目标key
85 | */
86 | private String targetKey;
87 | }
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/main/java/io/github/opensabre/persistence/entity/form/BaseQueryForm.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity.form;
2 |
3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
4 | import io.github.opensabre.common.web.entity.form.BaseForm;
5 | import io.github.opensabre.common.web.entity.convert.EntityModelConverter;
6 | import io.github.opensabre.persistence.entity.param.BaseParam;
7 | import io.swagger.v3.oas.annotations.media.Schema;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 |
11 | @Data
12 | @Schema
13 | @EqualsAndHashCode(callSuper = true)
14 | public class BaseQueryForm extends BaseForm {
15 | /**
16 | * 分页查询的参数,当前页数
17 | */
18 | @Schema(title = "当前页数", description = "分页查询的参数,当前页数", requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "1")
19 | private long current = 1;
20 | /**
21 | * 分页查询的参数,当前页面每页显示的数量
22 | */
23 | @Schema(title = "每页数量", description = "分页查询的参数,当前页面每页显示的数量", requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "10")
24 | private long size = 10;
25 |
26 | /**
27 | * QueryForm转化为Param
28 | *
29 | * @param clazz Param类
30 | * @return 返回Param
31 | */
32 | public P toParam(Class
clazz) {
33 | return EntityModelConverter.getInstance().convert(this, clazz);
34 | }
35 |
36 | /**
37 | * 从form中获取page参数,用于分页查询参数
38 | *
39 | * @return 返回分页的page
40 | */
41 | public Page
getPage() {
42 | return new Page<>(this.getCurrent(), this.getSize());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/opensabre-web/src/test/java/io/github/opensabre/common/core/exception/BaseExceptionTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.core.exception;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import static org.junit.jupiter.api.Assertions.*;
6 |
7 | class BaseExceptionTest {
8 | @Test
9 | void testNewBaseException() {
10 | assertEquals(new BaseException().getErrorType().getCode(), "-1");
11 | }
12 |
13 | @Test
14 | void testNewBaseExceptionWithErrorType() {
15 | BaseException baseException = new BaseException(SystemErrorType.ARGUMENT_NOT_VALID);
16 | assertEquals(baseException.getErrorType().getCode(), SystemErrorType.ARGUMENT_NOT_VALID.getCode());
17 | }
18 |
19 | @Test
20 | void testNewBaseExceptionWithErrorTypeAndMessage() {
21 | BaseException baseException = new BaseException(SystemErrorType.ARGUMENT_NOT_VALID, "无效参数");
22 | assertEquals(baseException.getErrorType().getCode(), SystemErrorType.ARGUMENT_NOT_VALID.getCode());
23 | assertEquals(baseException.getErrorType().getMesg(), "请求参数校验不通过");
24 | assertEquals(baseException.getMessage(), "无效参数");
25 |
26 | }
27 |
28 | @Test
29 | void testNewBaseExceptionWithErrorTypeAndMessageAndThrowable() {
30 | BaseException baseException = new BaseException(SystemErrorType.ARGUMENT_NOT_VALID, "无效参数", new RuntimeException());
31 | assertEquals(baseException.getErrorType().getCode(), SystemErrorType.ARGUMENT_NOT_VALID.getCode());
32 | assertEquals(baseException.getErrorType().getMesg(), "请求参数校验不通过");
33 | assertEquals(baseException.getMessage(), "无效参数");
34 | }
35 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/sensitive/rule/SensitiveRule.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.sensitive.rule;
2 |
3 |
4 | import cn.hutool.core.text.CharSequenceUtil;
5 |
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * 脱敏规则
10 | *
11 | * @author zhoutaoo
12 | */
13 | public interface SensitiveRule {
14 |
15 | /**
16 | * 类别
17 | * 如: 类别[电话],就包含mobile phone telephone等
18 | *
19 | * @return 保留前缀个数
20 | */
21 | String category();
22 |
23 | /**
24 | * 正则表达式
25 | *
26 | * @return 脱敏字段的正则
27 | */
28 | Pattern pattern();
29 |
30 | /**
31 | * 保留前缀个数 (需满足 大于等于 0个)
32 | *
33 | * 如: 538261, 保留前缀个数为2的话, 那么就是 53
34 | *
35 | * @return 保留前缀个数
36 | */
37 | int retainPrefixCount();
38 |
39 | /**
40 | * 保留后缀个数 (需满足 大于等于 0个)
41 | *
42 | * 如: 123456, 保留后缀个数为2的话, 那么就是 56
43 | *
44 | * @return 保留后缀个数
45 | */
46 | int retainSuffixCount();
47 |
48 | /**
49 | * 用于替代明文的 密文字符
50 | *
51 | * 如: 对123456使用*进行前2后2的脱敏, 那么就是 12**56
52 | *
53 | * @return 用于替代明文的 密文字符,默认*
54 | */
55 | default char replaceChar() {
56 | return '*';
57 | }
58 |
59 | /**
60 | * 原始字符串 替换
61 | *
62 | * @param originStr 原始字符串
63 | * @return 替换后的字符串
64 | */
65 | default String replace(String originStr) {
66 | return CharSequenceUtil.replace(originStr,
67 | this.retainPrefixCount(),
68 | originStr.length() - this.retainSuffixCount(),
69 | this.replaceChar());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/opensabre-starter-rpc/src/main/java/io/github/opensabre/rpc/openfeign/interceptor/FeignHeaderInterceptor.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.rpc.openfeign.interceptor;
2 |
3 | import com.google.common.collect.Maps;
4 | import feign.RequestInterceptor;
5 | import feign.RequestTemplate;
6 | import org.springframework.stereotype.Component;
7 | import org.springframework.web.context.request.RequestContextHolder;
8 | import org.springframework.web.context.request.ServletRequestAttributes;
9 |
10 | import jakarta.servlet.http.HttpServletRequest;
11 | import java.util.Enumeration;
12 | import java.util.Map;
13 |
14 | /**
15 | * spring cloud feign传递header
16 | *
17 | * @author zhoutaoo
18 | */
19 | @Component
20 | public class FeignHeaderInterceptor implements RequestInterceptor {
21 |
22 | /**
23 | * 获取request header 放入远程template中
24 | */
25 | @Override
26 | public void apply(RequestTemplate template) {
27 | getHeaders().forEach(template::header);
28 | }
29 |
30 | /**
31 | * 获取 request 中的所有的 header 值
32 | *
33 | * @return header map
34 | */
35 | private Map getHeaders() {
36 | HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
37 | Map map = Maps.newHashMap();
38 | Enumeration headerNames = request.getHeaderNames();
39 | while (headerNames.hasMoreElements()) {
40 | String key = headerNames.nextElement();
41 | String value = request.getHeader(key);
42 | map.put(key, value);
43 | }
44 | return map;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/core/exception/SystemErrorType.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.core.exception;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * 系统内置错误类型
7 | */
8 | @Getter
9 | public enum SystemErrorType implements ErrorType {
10 | /**
11 | * 未预料异常时均处理为该类型
12 | */
13 | SYSTEM_ERROR("-1", "系统异常"),
14 | /**
15 | * 系统繁忙,限流时
16 | */
17 | SYSTEM_BUSY("000001", "系统繁忙,请稍候再试"),
18 | /**
19 | * 未找到该资源
20 | */
21 | RESOURCE_NOT_FOUND("000404", "资源未找到"),
22 | /**
23 | * 网关转发时未找到该服务
24 | */
25 | GATEWAY_NOT_FOUND_SERVICE("010404", "服务未找到"),
26 | /**
27 | * 网关发生异常
28 | */
29 | GATEWAY_ERROR("010500", "网关异常"),
30 | /**
31 | * 网关调用后端server超时
32 | */
33 | GATEWAY_CONNECT_TIME_OUT("010002", "网关超时"),
34 | /**
35 | * Form表单字段校验不通过
36 | */
37 | ARGUMENT_NOT_VALID("020000", "请求参数校验不通过"),
38 | /**
39 | * Rest不支持的方法
40 | */
41 | METHOD_NOT_SUPPORTED("020001", "请求方法不支持"),
42 | /**
43 | * 无效Token
44 | */
45 | INVALID_TOKEN("021001", "无效token"),
46 | /**
47 | * 文件上传时,超过设定大小
48 | */
49 | UPLOAD_FILE_SIZE_LIMIT("020010", "上传文件大小超过限制"),
50 | /**
51 | * DB处理时,唯一键冲突时返回
52 | */
53 | DUPLICATE_PRIMARY_KEY("030000", "唯一键冲突");
54 |
55 | /**
56 | * 错误类型码
57 | */
58 | private final String code;
59 | /**
60 | * 错误类型描述信息
61 | */
62 | private final String mesg;
63 |
64 | /**
65 | * 构建函数
66 | *
67 | * @param code 错误代码
68 | * @param mesg 错误提示信息
69 | */
70 | SystemErrorType(String code, String mesg) {
71 | this.code = code;
72 | this.mesg = mesg;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/opensabre-starter-persistence/src/test/java/io/github/opensabre/persistence/entity/BaseEntityTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.persistence.entity;
2 |
3 | import io.github.opensabre.persistence.entity.form.UserForm;
4 | import io.github.opensabre.persistence.entity.form.UserQueryForm;
5 | import io.github.opensabre.persistence.entity.param.UserParam;
6 | import io.github.opensabre.persistence.entity.po.User;
7 | import io.github.opensabre.persistence.entity.vo.UserVo;
8 | import org.junit.jupiter.api.Assertions;
9 | import org.junit.jupiter.api.Test;
10 |
11 | import java.util.Date;
12 |
13 | class BaseEntityTest {
14 | @Test
15 | public void testQueryFormToParam() {
16 | UserQueryForm userQueryForm = new UserQueryForm("ZhangSan");
17 | userQueryForm.setCreatedTimeEnd(new Date());
18 | userQueryForm.setCreatedTimeStart(new Date());
19 | UserParam userParam = userQueryForm.toParam(UserParam.class);
20 | Assertions.assertEquals("ZhangSan", userParam.getName());
21 | }
22 |
23 | @Test
24 | public void testFormToPo() {
25 | UserForm userForm = new UserForm("ZhangSan");
26 | userForm.setAge(12);
27 | userForm.setSex("F");
28 | userForm.setBirthday(new Date());
29 | User user = userForm.toPo(User.class);
30 | Assertions.assertEquals("ZhangSan", user.getName());
31 | }
32 |
33 | @Test
34 | public void testPoToVo() {
35 | User user = new User("ZhangSan");
36 | user.setAge(12);
37 | user.setSex("F");
38 | user.setBirthday(new Date());
39 | user.setId("12");
40 | user.setCreatedTime(new Date());
41 | UserVo userVo = user.toVo(UserVo.class);
42 | Assertions.assertEquals("ZhangSan", userVo.getName());
43 | }
44 | }
--------------------------------------------------------------------------------
/opensabre-starter-eda/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | opensabre-framework
9 | io.github.opensabre
10 | ${revision}
11 |
12 |
13 | opensabre-starter-eda
14 | jar
15 |
16 | opensabre-starter-eda
17 | Opensabre Boot Eda
18 |
19 |
20 |
21 |
22 | io.github.opensabre
23 | opensabre-base-dependencies
24 | ${revision}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-bus-amqp
36 |
37 |
38 |
39 | org.projectlombok
40 | lombok
41 |
42 |
43 | io.github.opensabre
44 | opensabre-starter-boot
45 |
46 |
47 |
--------------------------------------------------------------------------------
/opensabre-starter-config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | opensabre-framework
9 | io.github.opensabre
10 | ${revision}
11 |
12 |
13 | opensabre-starter-config
14 | jar
15 |
16 | opensabre-starter-config
17 | Opensabre Boot Config
18 |
19 |
20 |
21 |
22 | io.github.opensabre
23 | opensabre-base-dependencies
24 | ${revision}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-bootstrap
36 |
37 |
38 |
39 | com.alibaba.cloud
40 | spring-cloud-starter-alibaba-nacos-config
41 |
42 |
43 | io.github.opensabre
44 | opensabre-starter-boot
45 |
46 |
47 |
--------------------------------------------------------------------------------
/opensabre-web/src/test/java/io/github/opensabre/common/core/util/UserContextHolderTest.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.core.util;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.util.HashMap;
6 |
7 | import static org.junit.jupiter.api.Assertions.assertEquals;
8 | import static org.junit.jupiter.api.Assertions.assertNotNull;
9 |
10 | class UserContextHolderTest {
11 |
12 | @Test
13 | void getInstance() {
14 | assertNotNull(UserContextHolder.getInstance());
15 | //单例,两次获取的同一个实例
16 | assertEquals(UserContextHolder.getInstance(), UserContextHolder.getInstance());
17 | }
18 |
19 | @Test
20 | void setContext() {
21 | UserContextHolder.getInstance().setContext(new HashMap<>());
22 | }
23 |
24 | @Test
25 | void getContext() {
26 | HashMap map = new HashMap<>();
27 | UserContextHolder.getInstance().setContext(map);
28 | assertEquals(UserContextHolder.getInstance().getContext(), UserContextHolder.getInstance().getContext());
29 | }
30 |
31 | @Test
32 | void getContextNotSet() {
33 | assertEquals(0, UserContextHolder.getInstance().getContext().size());
34 | }
35 |
36 | @Test
37 | void getUsername() {
38 | HashMap map = new HashMap<>();
39 | map.put(UserContextHolder.getInstance().KEY_USERNAME, "zhangsan");
40 | UserContextHolder.getInstance().setContext(map);
41 | assertEquals(UserContextHolder.getInstance().getUsername(), "zhangsan");
42 | }
43 |
44 | @Test
45 | void clear() {
46 | HashMap map = new HashMap<>();
47 | map.put(UserContextHolder.getInstance().KEY_USERNAME, "zhangsan");
48 | UserContextHolder.getInstance().setContext(map);
49 | UserContextHolder.getInstance().clear();
50 | assertEquals(0, UserContextHolder.getInstance().getContext().size());
51 | }
52 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/config/OpensabreSensitiveConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.config;
2 |
3 | import io.github.opensabre.boot.event.OpensabreSensitiveDesensitizerProcessor;
4 | import io.github.opensabre.boot.sensitive.log.LogBackCoreConverter;
5 | import io.github.opensabre.boot.sensitive.log.desensitizer.LogBackDesensitizer;
6 | import io.github.opensabre.boot.sensitive.log.desensitizer.RegxLogBackDesensitizer;
7 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
8 | import org.springframework.beans.factory.config.BeanPostProcessor;
9 | import org.springframework.boot.autoconfigure.AutoConfiguration;
10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
11 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
12 | import org.springframework.context.annotation.Bean;
13 |
14 | /**
15 | * 初使化脱敏配置
16 | */
17 | @AutoConfiguration
18 | @ConditionalOnProperty(value = "opensabre.sensitive.log.enabled", havingValue = "true")
19 | public class OpensabreSensitiveConfig {
20 |
21 | @Bean
22 | public BeanFactoryPostProcessor beanFactoryPostProcessor() {
23 | return configurableListableBeanFactory -> {
24 | LogBackCoreConverter logBackCoreConverter = LogBackCoreConverter.getInstance();
25 | configurableListableBeanFactory.registerSingleton("logBackCoreConverter", logBackCoreConverter);
26 | configurableListableBeanFactory.registerSingleton("defaultDesensitizerStrategy", logBackCoreConverter.getDesensitizerStrategy());
27 | };
28 | }
29 |
30 | @Bean
31 | public LogBackDesensitizer regxLogBackDesensitizer() {
32 | return new RegxLogBackDesensitizer();
33 | }
34 |
35 | @Bean
36 | public BeanPostProcessor opensabreSensitiveDesensitizerProcessor() {
37 | return new OpensabreSensitiveDesensitizerProcessor();
38 | }
39 | }
--------------------------------------------------------------------------------
/opensabre-starter-boot/src/main/java/io/github/opensabre/boot/rest/MappingInfoHandler.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.boot.rest;
2 |
3 | import io.github.opensabre.boot.entity.RestMappingInfo;
4 | import org.springframework.web.bind.annotation.RequestMethod;
5 | import org.springframework.web.method.HandlerMethod;
6 | import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
7 | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
8 |
9 | import jakarta.annotation.Resource;
10 | import java.util.HashSet;
11 | import java.util.Map;
12 | import java.util.Set;
13 | import java.util.stream.Collectors;
14 |
15 | /**
16 | * 获取springboot注册的Rest接口处理类
17 | *
18 | * @author zhoutaoo
19 | */
20 | public class MappingInfoHandler {
21 | /**
22 | * RequestMappingHandlerMapping类,spring web的Rest注册管理类
23 | */
24 | @Resource
25 | RequestMappingHandlerMapping requestMappingHandlerMapping;
26 |
27 | /**
28 | * 获取spring web应用所有注册的接口服务信息
29 | *
30 | * @return Set RestMappingInfo
31 | */
32 | public Set getMappingInfo() {
33 | // 拿到Handler适配器中的全部方法
34 | Map methodMap = requestMappingHandlerMapping.getHandlerMethods();
35 | Set interfaceInfos = new HashSet<>();
36 | for (RequestMappingInfo requestMappingInfo : methodMap.keySet()) {
37 | Set urls = requestMappingInfo.getPathPatternsCondition().getPatternValues();
38 | Set methods = requestMappingInfo.getMethodsCondition().getMethods();
39 | Set interfaceInfoSet = urls.stream()
40 | .flatMap(url -> methods.stream().map(method -> new RestMappingInfo(url, method.name())))
41 | .collect(Collectors.toSet());
42 | interfaceInfos.addAll(interfaceInfoSet);
43 | }
44 | return interfaceInfos;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/opensabre-web/src/main/java/io/github/opensabre/common/core/util/UserContextHolder.java:
--------------------------------------------------------------------------------
1 | package io.github.opensabre.common.core.util;
2 |
3 | import com.google.common.collect.Maps;
4 |
5 | import java.util.Map;
6 | import java.util.Optional;
7 |
8 | /**
9 | * 用户上下文
10 | */
11 | public class UserContextHolder {
12 | /**
13 | * 用户名默认key
14 | */
15 | public final String KEY_USERNAME = "user_name";
16 | /**
17 | * 用于存储线程相关变量
18 | */
19 | private final ThreadLocal