commit 0d439a2f43bf61bca65f17b073225b49e80c61d9 Author: zhouzhou <754746838@qq.com> Date: Mon Dec 25 18:59:05 2023 +0800 分布式框架 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..70279e0 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..ee2c34b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..132404b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/bwie-api/.gitignore b/bwie-api/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-api/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-api/bwie-system-api/.gitignore b/bwie-api/bwie-system-api/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-api/bwie-system-api/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-api/bwie-system-api/pom.xml b/bwie-api/bwie-system-api/pom.xml new file mode 100644 index 0000000..6a74681 --- /dev/null +++ b/bwie-api/bwie-system-api/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + com.bwie + bwie-api + 1.0-SNAPSHOT + + + bwie-system-api + + + 8 + 8 + UTF-8 + + + + + com.bwie + bwie-common-core + + + diff --git a/bwie-api/bwie-system-api/src/main/resources/META-INF/spring.factories b/bwie-api/bwie-system-api/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..0f81e72 --- /dev/null +++ b/bwie-api/bwie-system-api/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.bwie.system.api.factory.RemoteXxxFallbackFactory,\ + com.bwie.system.api.factory.RemoteXxxLogFallbackFactory diff --git a/bwie-api/pom.xml b/bwie-api/pom.xml new file mode 100644 index 0000000..3ff8e12 --- /dev/null +++ b/bwie-api/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + + + bwie-api + pom + + bwie-system-api + + + + 8 + 8 + UTF-8 + + + diff --git a/bwie-auth/.gitignore b/bwie-auth/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-auth/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-auth/pom.xml b/bwie-auth/pom.xml new file mode 100644 index 0000000..b8047f3 --- /dev/null +++ b/bwie-auth/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + + + bwie-auth + + + 8 + 8 + UTF-8 + + + + + com.bwie + bwie-common-core + + + + javax.servlet + servlet-api + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.bwie + bwie-system-api + + + diff --git a/bwie-auth/src/main/java/com/bwie/auth/AuthApplication.java b/bwie-auth/src/main/java/com/bwie/auth/AuthApplication.java new file mode 100644 index 0000000..df3f2e5 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/AuthApplication.java @@ -0,0 +1,24 @@ +package com.bwie.auth; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @Author: zhx + * @Package: com.bwie.auth + * @Datetime: 2023/12/25 17:26 + * @Filename: AuthApplication + * @Description: + */ +@SpringBootApplication +@EnableFeignClients(basePackages = "com.bwie") +public class AuthApplication { + + public static void main(String[] args) { + + SpringApplication.run(AuthApplication.class,args); + + } + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java b/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java new file mode 100644 index 0000000..aeb1b54 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java @@ -0,0 +1,25 @@ +package com.bwie.auth.controller; + +import com.bwie.auth.service.AuthService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RestController; + +/** + * @Author: zhx + * @Package: com.bwie.auth.controller + * @Datetime: 2023/12/25 17:25 + * @Filename: AuthController + * @Description: + */ +@RestController +@Log4j2 +public class AuthController { + + @Autowired + private AuthService authService; + + + + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java b/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java new file mode 100644 index 0000000..3ee20d8 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java @@ -0,0 +1,12 @@ +package com.bwie.auth.service; + +/** + * @Author: zhx + * @Package: com.bwie.auth.service + * @Datetime: 2023/12/25 17:25 + * @Filename: AuthService + * @Description: + */ + +public interface AuthService { +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java b/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java new file mode 100644 index 0000000..f5449c9 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java @@ -0,0 +1,18 @@ +package com.bwie.auth.service.impl; + +import org.springframework.stereotype.Service; + +/** + * @Author: zhx + * @Package: com.bwie.auth.service.impl + * @Datetime: 2023/12/25 17:25 + * @Filename: AuthServiceImpl + * @Description: + */ +@Service +public class AuthServiceImpl { + + + + +} diff --git a/bwie-auth/src/main/resources/bootstrap.yml b/bwie-auth/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..c1a01ac --- /dev/null +++ b/bwie-auth/src/main/resources/bootstrap.yml @@ -0,0 +1,31 @@ +# Tomcat +server: + port: 9001 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwie-auth + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 124.223.114.120:8848 + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa + config: + # 配置中心地址 + server-addr: 124.223.114.120:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa diff --git a/bwie-common/.gitignore b/bwie-common/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-common/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-common/bwie-common-core/.gitignore b/bwie-common/bwie-common-core/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-common/bwie-common-core/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-common/bwie-common-core/pom.xml b/bwie-common/bwie-common-core/pom.xml new file mode 100644 index 0000000..4a972bc --- /dev/null +++ b/bwie-common/bwie-common-core/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + com.bwie + bwie-common + 1.0-SNAPSHOT + + + bwie-common-core + + + 8 + 8 + UTF-8 + + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + io.jsonwebtoken + jjwt + + + + com.alibaba + fastjson + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.apache.commons + commons-lang3 + + + + org.projectlombok + lombok + + + + cn.hutool + hutool-all + + + + com.aliyun + dysmsapi20170525 + + + + javax.servlet + servlet-api + + + + org.springframework.boot + spring-boot-starter-amqp + + + com.alibaba + druid + 1.2.20 + compile + + + diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ConfirmCallbackConfig.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ConfirmCallbackConfig.java new file mode 100644 index 0000000..6970292 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ConfirmCallbackConfig.java @@ -0,0 +1,48 @@ +package com.bwie.common.config; + +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到 broker的确认 重写 confirm 方法 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ConfirmCallbackConfig implements RabbitTemplate.ConfirmCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + /** + * 当前类被初始化的时候执行的方法 + * + */ + @PostConstruct + public void init() { + // 设置 rabbitTemplate 的消息发送到交换机确认 + rabbitTemplate.setConfirmCallback(this); + } + + /** + * 消息发送到交换机 无论成功或者失败 都会执行 + * + * @param correlationData correlation data for the callback. + * @param ack true for ack, false for nack true 成功 false 失败 + * @param cause An optional cause, for nack, when available, otherwise null. + */ + @Override + public void confirm(CorrelationData correlationData, boolean ack, String cause) { + if (ack) { + System.out.println("消息发送到broker成功!"); + } else { + System.out.println("消息发送到broker失败,失败的原因是:" + cause); + } + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/RabbitmqConfig.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/RabbitmqConfig.java new file mode 100644 index 0000000..335f160 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/RabbitmqConfig.java @@ -0,0 +1,16 @@ +package com.bwie.common.config; + +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitmqConfig { + // 消息转换配置 SimpleMessageConverter String byte[] serializable + @Bean + public MessageConverter jsonMessageConverter() { + return new Jackson2JsonMessageConverter(); + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ReturnsCallbackConfig.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ReturnsCallbackConfig.java new file mode 100644 index 0000000..e1522bf --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/config/ReturnsCallbackConfig.java @@ -0,0 +1,40 @@ +package com.bwie.common.config; + +import org.springframework.amqp.core.ReturnedMessage; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到队列的确认 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ReturnsCallbackConfig implements RabbitTemplate.ReturnsCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @PostConstruct + public void init() { + rabbitTemplate.setReturnsCallback(this); + } + + /** + * 只有发送到队列失败才会执行 + * + * @param returnedMessage the returned message and metadata. + */ + @Override + public void returnedMessage(ReturnedMessage returnedMessage) { + System.out.println("消息" + returnedMessage.getMessage().toString() + + "被交换机" + returnedMessage.getExchange() + "回退!" + + "退回原因为:" + returnedMessage.getReplyText()); + // TODO 补偿 可以再发 做日志记录 + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/Constants.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/Constants.java new file mode 100644 index 0000000..2fdc9fe --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/Constants.java @@ -0,0 +1,18 @@ +package com.bwie.common.constants; + +/** + * @description: 系统常量 + * @author DongZl + */ +public class Constants { + /** + * 成功标记 + */ + public static final Integer SUCCESS = 200; + public static final String SUCCESS_MSG = "操作成功"; + /** + * 失败标记 + */ + public static final Integer ERROR = 500; + public static final String ERROR_MSG = "操作异常"; +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/JwtConstants.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/JwtConstants.java new file mode 100644 index 0000000..03692c1 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/JwtConstants.java @@ -0,0 +1,29 @@ +package com.bwie.common.constants; + +/** + * @author DongZl + * @description: Jwt常量 + */ +public class JwtConstants { + + /** + * 用户ID字段 + */ + public static final String DETAILS_USER_ID = "user_id"; + + /** + * 用户名字段 + */ + public static final String DETAILS_USERNAME = "username"; + + /** + * 用户标识 + */ + public static final String USER_KEY = "user_key"; + + /** + * 令牌秘钥 + */ + public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/TokenConstants.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/TokenConstants.java new file mode 100644 index 0000000..1871fb7 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/constants/TokenConstants.java @@ -0,0 +1,24 @@ +package com.bwie.common.constants; + +/** + * @author DongZl + * @description: 令牌常量 + */ +public class TokenConstants { + /** + * 缓存有效期,默认720(分钟) + */ + public final static long EXPIRATION = 720; + /** + * 缓存刷新时间,默认120(分钟) + */ + public final static long REFRESH_TIME = 120; + /** + * 权限缓存前缀 + */ + public final static String LOGIN_TOKEN_KEY = "login_tokens:"; + /** + * token标识 + */ + public static final String TOKEN = "token"; +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/exception/auth/AuthException.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/exception/auth/AuthException.java new file mode 100644 index 0000000..97cdb87 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/exception/auth/AuthException.java @@ -0,0 +1,32 @@ +package com.bwie.common.exception.auth; + +/** + * @ClassName: + * @Description: 自定义异常 + * @Author: zhuwenqiang + * @Date: 2023/12/19 + */ +public class AuthException extends RuntimeException { + + /** + * 状态码 + */ + private int code; + + /** + * 错误信息 + */ + private String message; + + public AuthException() {} + + public AuthException(String message) { + super(message); + } + + public AuthException(int code, String message) { + this.code = code; + this.message = message; + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..747ba58 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java @@ -0,0 +1,41 @@ +package com.bwie.common.handler; + +import com.bwie.common.exception.auth.AuthException; +import com.bwie.common.result.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; + +/** + * @ClassName: + * @Description: 全局异常处理器 + * @Author: zhuwenqiang + * @Date: 2023/12/19 + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 处理 auth exception 程序出现了 AuthException 则会进入这个方法 + * @param ex + * @return + */ + @ExceptionHandler(AuthException.class) + public Result authExceptionHandler(HttpServletRequest request, AuthException ex) { + String requestURI = request.getRequestURI(); + logger.error("请求URI:{},出现了异常,异常信息:{}", requestURI, ex.getMessage()); + return Result.error(ex.getMessage()); + } +// +// @ExceptionHandler(Exception.class) +// public Result exceptionHandler() { +// +// } + + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/PageResult.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/PageResult.java new file mode 100644 index 0000000..85ecdda --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/PageResult.java @@ -0,0 +1,34 @@ +package com.bwie.common.result; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author DongZl + * @description: 列表返回结果集 + */ +@Data +public class PageResult implements Serializable { + /** + * 总条数 + */ + private long total; + /** + * 结果集合 + */ + private List list; + public PageResult() { + } + public PageResult(long total, List list) { + this.total = total; + this.list = list; + } + public static PageResult toPageResult(long total, List list){ + return new PageResult(total , list); + } + public static Result> toResult(long total, List list){ + return Result.success(PageResult.toPageResult(total,list)); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/Result.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/Result.java new file mode 100644 index 0000000..30b1e73 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/result/Result.java @@ -0,0 +1,76 @@ +package com.bwie.common.result; + +import com.bwie.common.constants.Constants; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author DongZl + * @description: 响应信息主体 + */ +@Data +public class Result implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 成功 + */ + public static final int SUCCESS = Constants.SUCCESS; + /** + * 失败 + */ + public static final int FAIL = Constants.ERROR; + /** + * 返回状态码 + */ + private int code; + /** + * 响应信息 + */ + private String msg; + /** + * 响应数据 + */ + private T data; + + public static Result success() { + return restResult(null, SUCCESS, Constants.SUCCESS_MSG); + } + + public static Result success(T data) { + return restResult(data, SUCCESS, Constants.SUCCESS_MSG); + } + + public static Result success(T data, String msg) { + return restResult(data, SUCCESS, msg); + } + + public static Result error() { + return restResult(null, FAIL, Constants.ERROR_MSG); + } + + public static Result error(String msg) { + return restResult(null, FAIL, msg); + } + + public static Result error(T data) { + return restResult(data, FAIL, Constants.ERROR_MSG); + } + + public static Result error(T data, String msg) { + return restResult(data, FAIL, msg); + } + + public static Result error(int code, String msg) { + return restResult(null, code, msg); + } + + private static Result restResult(T data, int code, String msg) { + Result apiResult = new Result<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/CharsetKit.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/CharsetKit.java new file mode 100644 index 0000000..31ff709 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/CharsetKit.java @@ -0,0 +1,92 @@ +package com.bwie.common.text; + + +import com.bwie.common.utils.StringUtils; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * 字符集工具类 + * + * @author bwie + */ +public class CharsetKit { + /** + * ISO-8859-1 + */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** + * UTF-8 + */ + public static final String UTF_8 = "UTF-8"; + /** + * GBK + */ + public static final String GBK = "GBK"; + + /** + * ISO-8859-1 + */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** + * UTF-8 + */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** + * GBK + */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转换为Charset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) { + if (null == srcCharset) { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) { + destCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return 系统字符集编码 + */ + public static String systemCharset() { + return Charset.defaultCharset().name(); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/Convert.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/Convert.java new file mode 100644 index 0000000..8340e15 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/Convert.java @@ -0,0 +1,860 @@ +package com.bwie.common.text; + + +import com.bwie.common.utils.StringUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author bwie + */ +public class Convert { + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof String) { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof Character) { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Byte) { + return (Byte) value; + } + if (value instanceof Number) { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Byte.parseByte(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Short) { + return (Short) value; + } + if (value instanceof Number) { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Short.parseShort(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Number) { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return NumberFormat.getInstance().parse(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Integer) { + return (Integer) value; + } + if (value instanceof Number) { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Integer.parseInt(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) { + if (StringUtils.isEmpty(str)) { + return new Integer[]{}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) { + if (StringUtils.isEmpty(str)) { + return new Long[]{}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Long) { + return (Long) value; + } + if (value instanceof Number) { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Double) { + return (Double) value; + } + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Float) { + return (Float) value; + } + if (value instanceof Number) { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Float.parseFloat(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Boolean) { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) { + if (value == null) { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Enum.valueOf(clazz, valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigInteger) { + return (BigInteger) value; + } + if (value instanceof Long) { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigInteger(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } + if (value instanceof Long) { + return new BigDecimal((Long) value); + } + if (value instanceof Double) { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigDecimal(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) { + if (null == obj) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof byte[] || obj instanceof Byte[]) { + if (obj instanceof byte[]) { + return str((byte[]) obj, charset); + } else { + Byte[] bytes = (Byte[]) obj; + int length = bytes.length; + byte[] dest = new byte[length]; + for (int i = 0; i < length; i++) { + dest[i] = bytes[i]; + } + return str(dest, charset); + } + } else if (obj instanceof ByteBuffer) { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) { + if (data == null) { + return null; + } + + if (null == charset) { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) { + if (data == null) { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) { + if (null == charset) { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') { + c[i] = '\u3000'; + } else if (c[i] < '\177') { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') { + c[i] = ' '; + } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') { + c[i] = (char) (c[i] - 65248); + } + } + return new String(c); + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) { + String[] fraction = {"角", "分"}; + String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; + String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}}; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) { + // 优化double计算精度丢失问题 + BigDecimal nNum = new BigDecimal(n); + BigDecimal decimal = new BigDecimal(10); + BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN); + double d = scale.doubleValue(); + s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/StrFormatter.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/StrFormatter.java new file mode 100644 index 0000000..8ecf2e2 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/text/StrFormatter.java @@ -0,0 +1,76 @@ +package com.bwie.common.text; + +import com.bwie.common.utils.StringUtils; + +/** + * 字符串格式化 + * + * @author bwie + */ +public class StrFormatter { + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) { + if (com.alibaba.druid.util.StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) { + if (handledPosition == 0) { + return strPattern; + } else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } else { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } else { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } else { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/AESUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/AESUtils.java new file mode 100644 index 0000000..fe0f7ce --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/AESUtils.java @@ -0,0 +1,250 @@ +package com.bwie.common.utils; + +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Base64Utils; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + + +/** + * @ClassName AESUtils + * @Description 描述 + * @Author WenSha.Wan + * @Date 2023/7/8 上午7:48 + */ +public class AESUtils { + + + /** + * 日志相关 + */ + private static final Logger LOGGER = LoggerFactory.getLogger(AESUtils.class); + /** + * 编码 + */ + private static final String ENCODING = "UTF-8"; + /** + * 算法定义 + */ + private static final String AES_ALGORITHM = "AES"; + /** + * 指定填充方式 + */ + private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding"; + private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding"; + /** + * 偏移量(CBC中使用,增强加密算法强度) + */ + private static final String IV_SEED = "1234567812345678"; + + /** + * AES加密 + * @param content 待加密内容 + * @param aesKey 密码 + * @return + */ + public static String encrypt(String content, String aesKey){ + if(StringUtils.isBlank(content)){ + LOGGER.info("AES encrypt: the content is null!"); + return null; + } + //判断秘钥是否为16位 + if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ + try { + //对密码进行编码 + byte[] bytes = aesKey.getBytes(ENCODING); + //设置加密算法,生成秘钥 + SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); + // "算法/模式/补码方式" + Cipher cipher = Cipher.getInstance(CIPHER_PADDING); + //选择加密 + cipher.init(Cipher.ENCRYPT_MODE, skeySpec); + //根据待加密内容生成字节数组 + byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING)); + //返回base64字符串 + return Base64Utils.encodeToString(encrypted); + } catch (Exception e) { + LOGGER.info("AES encrypt exception:" + e.getMessage()); + throw new RuntimeException(e); + } + + }else { + LOGGER.info("AES encrypt: the aesKey is null or error!"); + return null; + } + } + + /** + * 解密 + * + * @param content 待解密内容 + * @param aesKey 密码 + * @return + */ + public static String decrypt(String content, String aesKey){ + if(StringUtils.isBlank(content)){ + LOGGER.info("AES decrypt: the content is null!"); + return null; + } + //判断秘钥是否为16位 + if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ + try { + //对密码进行编码 + byte[] bytes = aesKey.getBytes(ENCODING); + //设置解密算法,生成秘钥 + SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); + // "算法/模式/补码方式" + Cipher cipher = Cipher.getInstance(CIPHER_PADDING); + //选择解密 + cipher.init(Cipher.DECRYPT_MODE, skeySpec); + + //先进行Base64解码 + byte[] decodeBase64 = Base64Utils.decodeFromString(content); + + //根据待解密内容进行解密 + byte[] decrypted = cipher.doFinal(decodeBase64); + //将字节数组转成字符串 + return new String(decrypted, ENCODING); + } catch (Exception e) { + LOGGER.info("AES decrypt exception:" + e.getMessage()); + throw new RuntimeException(e); + } + + }else { + LOGGER.info("AES decrypt: the aesKey is null or error!"); + return null; + } + } + + /** + * AES_CBC加密 + * + * @param content 待加密内容 + * @param aesKey 密码 + * @return + */ + public static String encryptCBC(String content, String aesKey){ + if(StringUtils.isBlank(content)){ + LOGGER.info("AES_CBC encrypt: the content is null!"); + return null; + } + //判断秘钥是否为16位 + if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ + try { + //对密码进行编码 + byte[] bytes = aesKey.getBytes(ENCODING); + //设置加密算法,生成秘钥 + SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); + // "算法/模式/补码方式" + Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING); + //偏移 + IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING)); + //选择加密 + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); + //根据待加密内容生成字节数组 + byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING)); + //返回base64字符串 + return Base64Utils.encodeToString(encrypted); + } catch (Exception e) { + LOGGER.info("AES_CBC encrypt exception:" + e.getMessage()); + throw new RuntimeException(e); + } + + }else { + LOGGER.info("AES_CBC encrypt: the aesKey is null or error!"); + return null; + } + } + + /** + * AES_CBC解密 + * + * @param content 待解密内容 + * @param aesKey 密码 + * @return + */ + public static String decryptCBC(String content, String aesKey){ + if(StringUtils.isBlank(content)){ + LOGGER.info("AES_CBC decrypt: the content is null!"); + return null; + } + //判断秘钥是否为16位 + if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ + try { + //对密码进行编码 + byte[] bytes = aesKey.getBytes(ENCODING); + //设置解密算法,生成秘钥 + SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); + //偏移 + IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING)); + // "算法/模式/补码方式" + Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING); + //选择解密 + cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); + + //先进行Base64解码 + byte[] decodeBase64 = Base64Utils.decodeFromString(content); + + //根据待解密内容进行解密 + byte[] decrypted = cipher.doFinal(decodeBase64); + //将字节数组转成字符串 + return new String(decrypted, ENCODING); + } catch (Exception e) { + LOGGER.info("AES_CBC decrypt exception:" + e.getMessage()); + throw new RuntimeException(e); + } + + }else { + LOGGER.info("AES_CBC decrypt: the aesKey is null or error!"); + return null; + } + } + + public static void main(String[] args) { + // AES支持三种长度的密钥:128位、192位、256位。 + // 代码中这种就是128位的加密密钥,16字节 * 8位/字节 = 128位。 +// String random = RandomStringUtils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890"); +// String random = RandomStringUtils.random(16, "123456"); +// System.out.println("随机key:" + random); +// System.out.println(); +// +// System.out.println("---------加密---------"); +// String aesResult = encrypt("测试AES加密12", random); +// System.out.println("aes加密结果:" + aesResult); +// System.out.println(); +// +// System.out.println("---------解密---------"); +// String decrypt = decrypt(aesResult, random); +// System.out.println("aes解密结果:" + decrypt); +// System.out.println(); +// +// +// System.out.println("--------AES_CBC加密解密---------"); +// String cbcResult = encryptCBC("测试AES加密12456", random); +// System.out.println("aes_cbc加密结果:" + cbcResult); +// System.out.println(); +// +// System.out.println("---------解密CBC---------"); +// String cbcDecrypt = decryptCBC(cbcResult, random); +// System.out.println("aes解密结果:" + cbcDecrypt); +// System.out.println(); + + + //加密 + String encrypt1 = encrypt ("123", "1234567890000000"); + System.out.println ("123加密后 1====================={"+encrypt1); + + //解密 +// decrypt ("/83VCGvDN+C5pvYN/19pBQ==") + + } + + + + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/CodeEntity.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/CodeEntity.java new file mode 100644 index 0000000..891b307 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/CodeEntity.java @@ -0,0 +1,15 @@ +package com.bwie.common.utils; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class CodeEntity { + + private String phone; + private String code; + + + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/FastUtil.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/FastUtil.java new file mode 100644 index 0000000..3dbda5b --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/FastUtil.java @@ -0,0 +1,55 @@ +package com.bwie.common.utils; + +import org.springframework.stereotype.Component; +import com.github.tobato.fastdfs.domain.fdfs.StorePath; +import com.github.tobato.fastdfs.service.FastFileStorageClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +/** + * @BelongsProject: 0107day02 + * @BelongsPackage: com.bw.config + * @Author: zhupengfei + * @CreateTime: 2023-02-01 08:52 + */ +@Component +public class FastUtil { + private static final Logger log = LoggerFactory.getLogger(FastUtil.class); + + @Resource + private FastFileStorageClient storageClient ; + + /** + * 上传文件 + */ + public String upload(MultipartFile multipartFile) throws Exception{ + String originalFilename = multipartFile.getOriginalFilename(). + substring(multipartFile.getOriginalFilename(). + lastIndexOf(".") + 1); + StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage( + multipartFile.getInputStream(), + multipartFile.getSize(),originalFilename , null); + return storePath.getFullPath(); + } + /** + * 删除文件 + */ + public String deleteFile(String fileUrl) { + if (StringUtils.isEmpty(fileUrl)) { + log.info("fileUrl == >>文件路径为空..."); + return "文件路径不能为空"; + } + try { + StorePath storePath = StorePath.parseFromUrl(fileUrl); + storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); + } catch (Exception e) { + log.error(e.getMessage()); + } + return "删除成功"; + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/GenCodeUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/GenCodeUtils.java new file mode 100644 index 0000000..24a9722 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/GenCodeUtils.java @@ -0,0 +1,87 @@ +package com.bwie.common.utils; + +import java.util.Random; + +/** + * @author DongZl + * @description: 生成验证码工具类 + * @Date 2023-5-11 上午 10:09 + */ +public class GenCodeUtils { + + /** + * 数字类型 + */ + private static final String NUMBER_STR = "0123456789"; + /** + * 字母类型 + */ + private static final String LETTERS_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /** + * 短信验证码长度 + */ + private static final Integer SMS_CODE_LENGTH = 4; + + /** + * 生成短信四位验证码 + * @return 验证码 + */ + public static String genLetterStrSms(){ + return genCode(LETTERS_STR, SMS_CODE_LENGTH); + } + + /** + * 生成短信四位验证码 + * @return 验证码 + */ + public static String genNumberCodeSms(){ + return genCode(NUMBER_STR, SMS_CODE_LENGTH); + } + + /** + * 生成验证码 + * @param codeLength 验证码长度 + * @return 验证码 + */ + public static String genLetterStr(int codeLength){ + return genCode(LETTERS_STR, codeLength); + } + + /** + * 生成验证码 + * @param codeLength 验证码长度 + * @return 验证码 + */ + public static String genNumberCode( int codeLength){ + return genCode(NUMBER_STR, codeLength); + } + + /** + * 生成验证码 + * @param str 验证码字符串 + * @param codeLength 验证码长度 + * @return 验证码 + */ + public static String genCode (String str, int codeLength){ + //将字符串转换为一个新的字符数组。 + char[] verificationCodeArray = str.toCharArray(); + Random random = new Random(); + //计数器 + int count = 0; + StringBuilder stringBuilder = new StringBuilder(); + do { + //随机生成一个随机数 + int index = random.nextInt(verificationCodeArray.length); + char c = verificationCodeArray[index]; + //限制四位不重复数字 + if (stringBuilder.indexOf(String.valueOf(c)) == -1) { + stringBuilder.append(c); + //计数器加1 + count++; + } + //当count等于4时结束,随机生成四位数的验证码 + } while (count != codeLength); + return stringBuilder.toString(); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/HttpUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/HttpUtils.java new file mode 100644 index 0000000..8b943fd --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/HttpUtils.java @@ -0,0 +1,312 @@ +package com.bwie.common.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +public class HttpUtils { + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + +} \ No newline at end of file diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/JwtUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/JwtUtils.java new file mode 100644 index 0000000..f560aa9 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/JwtUtils.java @@ -0,0 +1,109 @@ +package com.bwie.common.utils; + +import com.bwie.common.constants.JwtConstants; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import java.util.Map; + +/** + * @description: Jwt工具类 + * @author DongZl + */ +public class JwtUtils { + + /** + * 秘钥 + */ + public static String secret = JwtConstants.SECRET; + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + public static String createToken(Map claims){ + String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + public static Claims parseToken(String token){ + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + /** + * 根据令牌获取用户标识 + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserKey(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.USER_KEY); + } + /** + * 根据令牌获取用户标识 + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserKey(Claims claims){ + return getValue(claims, JwtConstants.USER_KEY); + } + /** + * 根据令牌获取用户ID + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserId(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.DETAILS_USER_ID); + } + /** + * 根据身份信息获取用户ID + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserId(Claims claims){ + return getValue(claims, JwtConstants.DETAILS_USER_ID); + } + /** + * 根据令牌获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public static String getUserName(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.DETAILS_USERNAME); + } + /** + * 根据身份信息获取用户名 + * + * @param claims 身份信息 + * @return 用户名 + */ + public static String getUserName(Claims claims){ + return getValue(claims, JwtConstants.DETAILS_USERNAME); + } + /** + * 根据身份信息获取键值 + * + * @param claims 身份信息 + * @param key 键 + * @return 值 + */ + public static String getValue(Claims claims, String key){ + Object obj = claims.get(key); + return obj == null ? "" : obj.toString(); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/MsgUtil.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/MsgUtil.java new file mode 100644 index 0000000..5593088 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/MsgUtil.java @@ -0,0 +1,66 @@ +package com.bwie.common.utils; + +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class MsgUtil { + //取code + @Cacheable(key = "#phone",value = "bbb") + public String getCacheCode(String phone){ + + return null; + } + + //把当前注解的返回值装进去 //存code + @CachePut(key = "#codeEntity.phone",value = "bbb") + public String saveCacheCode(CodeEntity codeEntity){ + + return codeEntity.getCode(); + } + + public String sendMsg(String phone,String code){ + String result = null; + String host = "https://gyytz.market.alicloudapi.com"; + String path = "/sms/smsSend"; + String method = "POST"; + String appcode = "7ac0173f69ac4737a4ec5a5c4c6ca3b5"; + Map headers = new HashMap(); + //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appcode); + Map querys = new HashMap(); + querys.put("mobile", phone); + querys.put("param", "**code**:"+code+",**minute**:5"); + +//smsSignId(短信前缀)和templateId(短信模板),可登录国阳云控制台自助申请。参考文档:http://help.guoyangyun.com/Problem/Qm.html + + querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2"); + querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad"); + Map bodys = new HashMap(); + + + try { + /** + * 重要提示如下: + * HttpUtils请从\r\n\t \t* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java\r\n\t \t* 下载 + * + * 相应的依赖请参照 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml + */ + HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); +// System.out.println(response.toString()); + //获取response的body + result = EntityUtils.toString(response.getEntity()); + System.out.println(result); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/OssUtil.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/OssUtil.java new file mode 100644 index 0000000..9c1383f --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/OssUtil.java @@ -0,0 +1,153 @@ +package com.bwie.common.utils; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.GetObjectRequest; +import com.aliyun.oss.model.PutObjectRequest; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * Oss服务调用 + */ +@Log4j2 +public class OssUtil { + + /** + * Endpoint 存储对象概述 阿里云主账号AccessKey,accessKeySecret拥有所有API的访问权限 访问路径前缀 存储对象概述 + */ + private static String endPoint = "oss-cn-shanghai.aliyuncs.com"; + private static String accessKeyId = "LTAI5tD2tppzLQ4Rb6yKYyph"; + private static String accessKeySecret = "KEKNKwVvDq7PZLjE63NPBouqHXox4Q"; + private static String accessPre = "https://dzlmuyu.oss-cn-shanghai.aliyuncs.com/"; + + /** + * bucket名称 + * @return + */ + private static String bucketName = "dzlmuyu"; + + private static OSS ossClient ; + + static { + ossClient = new OSSClientBuilder().build( + endPoint, + accessKeyId, + accessKeySecret); + log.info("oss服务连接成功!"); + } + + /** + * 默认路径上传本地文件 + * @param filePath + */ + public static String uploadFile(String filePath){ + return uploadFileForBucket(bucketName,getOssFilePath(filePath) ,filePath); + } + + /** + * 默认路径上传multipartFile文件 + * @param multipartFile + */ + public static String uploadMultipartFile(MultipartFile multipartFile) { + return uploadMultipartFile(bucketName,getOssFilePath(multipartFile.getOriginalFilename()),multipartFile); + } + /** + * 上传 multipartFile 类型文件 + * @param bucketName + * @param ossPath + * @param multipartFile + */ + public static String uploadMultipartFile(String bucketName , String ossPath , MultipartFile multipartFile){ + InputStream inputStream = null; + try { + inputStream = multipartFile.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + return accessPre+ossPath; + } + + /** + * 使用File上传PutObject上传文件 ** 程序默认使用次方法上传 + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + */ + public static String uploadFileForBucket(String bucketName , String ossPath , String filePath) { + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath, new File(filePath)); + + // 上传 + ossClient.putObject(putObjectRequest); + return accessPre+ossPath; + } + + /** + * 使用文件流上传到指定的bucket实例 + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + */ + public static String uploadFileInputStreamForBucket(String bucketName , String ossPath , String filePath){ + + // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。 + InputStream inputStream = null; + try { + inputStream = new FileInputStream(filePath); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。 + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + return accessPre+ossPath; + } + + public static void uploadFileInputStreamForBucket(String bucketName , String ossPath , InputStream inputStream ){ + ossClient.putObject(bucketName, ossPath, inputStream); + } + + /** + * 下载 + * @param ossFilePath + * @param filePath + */ + public static void downloadFile(String ossFilePath , String filePath ){ + downloadFileForBucket(bucketName , ossFilePath , filePath); + } + /** + * 下载 + * @param bucketName 实例名称 + * @param ossFilePath oss存储路径 + * @param filePath 本地文件路径 + */ + public static void downloadFileForBucket(String bucketName , String ossFilePath , String filePath ){ + ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(filePath)); + } + + /** + * + * @return + */ + public static String getOssDefaultPath(){ + LocalDateTime now = LocalDateTime.now(); + String url = + now.getYear()+"/"+ + now.getMonth()+"/"+ + now.getDayOfMonth()+"/"+ + now.getHour()+"/"+ + now.getMinute()+"/"; + return url; + } + + public static String getOssFilePath(String filePath){ + String fileSuf = filePath.substring(filePath.indexOf(".") + 1); + return getOssDefaultPath() + UUID.randomUUID().toString() + "." + fileSuf; + } + +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/StringUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/StringUtils.java new file mode 100644 index 0000000..93c47fd --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/StringUtils.java @@ -0,0 +1,68 @@ +package com.bwie.common.utils; + +import org.springframework.util.AntPathMatcher; + +import java.util.Collection; +import java.util.List; + +/** + * @author DongZl + * @description: 字符串处理工具类 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) { + return object == null; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) { + return isNull(coll) || coll.isEmpty(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) { + if (isEmpty(str) || isEmpty(strs)) { + return false; + } + for (String pattern : strs) { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } +} diff --git a/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/TelSmsUtils.java b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/TelSmsUtils.java new file mode 100644 index 0000000..77a395e --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/java/com/bwie/common/utils/TelSmsUtils.java @@ -0,0 +1,88 @@ +package com.bwie.common.utils; + +import com.alibaba.fastjson.JSONObject; +import com.aliyun.dysmsapi20170525.Client; +import com.aliyun.dysmsapi20170525.models.SendSmsRequest; +import com.aliyun.dysmsapi20170525.models.SendSmsResponse; +import com.aliyun.teaopenapi.models.Config; +import lombok.extern.log4j.Log4j2; + +import java.util.Map; + +/** + * 短信工具类 + */ +@Log4j2 +public class TelSmsUtils { + + /** + * 阿里云主账号AccessKey,accessKeySecret拥有所有API的访问权限 + */ + private static String accessKeyId = "204250583"; + private static String accessKeySecret = "rDrLLGT0SqKA3IykgXwlgCgxuKCPLeca"; + private static String templateCode = "a4ab2ca295e44e23a4a85fd6ecbc907a"; + + /** + * 短信访问域名 + */ + private static String endpoint = "dysmsapi.aliyuncs.com"; + /** + * 短信签名 + */ + private static String signName = "登录验证"; + + /** + * 实例化短信对象 + */ + private static Client client; + + static { + log.info("初始化短信服务开始"); + long startTime = System.currentTimeMillis(); + try { + client = initClient(); + log.info("初始化短信成功:{}",signName); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("初始化短信服务结束:耗时:{}MS",(System.currentTimeMillis()-startTime)); + } + /** + * 初始化短信对象 + * @return + * @throws Exception + */ + private static Client initClient() throws Exception{ + Config config = new Config() + // 您的AccessKey ID + .setAccessKeyId(accessKeyId) + // 您的AccessKey Secret + .setAccessKeySecret(accessKeySecret); + // 访问的域名 + config.endpoint = endpoint; + return new Client(config); + } + + /** + * 发送单条短信 + * @param tel + * @param sendDataMap + */ + public static String sendSms(String tel , Map sendDataMap){ + SendSmsRequest sendSmsRequest = new SendSmsRequest() + .setPhoneNumbers(tel) + .setSignName(signName) + .setTemplateCode(templateCode) + .setTemplateParam(JSONObject.toJSONString(sendDataMap)); + SendSmsResponse sendSmsResponse = null; + try { + log.info("发送短信验证码:消息内容是:【{}】", JSONObject.toJSONString(sendDataMap)); + sendSmsResponse = client.sendSms(sendSmsRequest); + } catch (Exception e) { + log.error("短信发送异常,手机号:【{}】,短信内容:【{}】,异常信息:【{}】", tel, sendDataMap, e); + } + // SendSmsResponseBody + return JSONObject.toJSONString(sendSmsResponse.getBody()); + } + +} diff --git a/bwie-common/bwie-common-core/src/main/resources/META-INF/spring.factories b/bwie-common/bwie-common-core/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..269b382 --- /dev/null +++ b/bwie-common/bwie-common-core/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.bwie.common.config.ConfirmCallbackConfig,\ + com.bwie.common.config.ReturnsCallbackConfig,\ + com.bwie.common.handler.GlobalExceptionHandler diff --git a/bwie-common/bwie-common-log/.gitignore b/bwie-common/bwie-common-log/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-common/bwie-common-log/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-common/bwie-common-log/pom.xml b/bwie-common/bwie-common-log/pom.xml new file mode 100644 index 0000000..d195929 --- /dev/null +++ b/bwie-common/bwie-common-log/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + com.bwie + bwie-common + 1.0-SNAPSHOT + + + bwie-common-log + + + 8 + 8 + UTF-8 + + + + com.bwie + bwie-common-core + + + + com.bwie + bwie-system-api + + + diff --git a/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/BusinessType.java b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/BusinessType.java new file mode 100644 index 0000000..4f78de5 --- /dev/null +++ b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/BusinessType.java @@ -0,0 +1,31 @@ +package com.bwie.common.log.enums; + +/** + * @ClassName: + * @Description: 操作类型 + * @Author: zhuwenqiang + * @Date: 2023/12/22 + */ +public enum BusinessType { + + /** + * 其他 + */ + OTHER, + + /** + * 添加 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE + +} diff --git a/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/OperStatus.java b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/OperStatus.java new file mode 100644 index 0000000..f0f30c7 --- /dev/null +++ b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/enums/OperStatus.java @@ -0,0 +1,15 @@ +package com.bwie.common.log.enums; + +/** + * @ClassName: + * @Description: + * @Author: zhuwenqiang + * @Date: 2023/12/22 + */ +public enum OperStatus { + + SUCCESS, + + FAIL + +} diff --git a/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/filter/PropertyPreExcludeFilter.java b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/filter/PropertyPreExcludeFilter.java new file mode 100644 index 0000000..a4b7d76 --- /dev/null +++ b/bwie-common/bwie-common-log/src/main/java/com/bwie/common/log/filter/PropertyPreExcludeFilter.java @@ -0,0 +1,27 @@ +package com.bwie.common.log.filter; + +import com.alibaba.fastjson.serializer.SimplePropertyPreFilter; + +/** + * @ClassName: + * @Description: 对象转JSON字符串过滤指定字段 + * @Author: zhuwenqiang + * @Date: 2023/12/23 + */ +public class PropertyPreExcludeFilter extends SimplePropertyPreFilter { + + public PropertyPreExcludeFilter() {} + + /** + * 过滤指定属性 + * @param filters 需要过滤的属性 + * @return + */ + public PropertyPreExcludeFilter addExclude(String ...filters) { + for (int i = 0; i < filters.length; i++) { + this.getExcludes().add(filters[i]); + } + return this; + } + +} diff --git a/bwie-common/bwie-common-log/src/main/resources/META-INF/spring.factories b/bwie-common/bwie-common-log/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..32c3536 --- /dev/null +++ b/bwie-common/bwie-common-log/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.bwie.common.log.aspect.LogAspect,\ + com.bwie.common.log.service.SyncLogService diff --git a/bwie-common/pom.xml b/bwie-common/pom.xml new file mode 100644 index 0000000..01e2bc0 --- /dev/null +++ b/bwie-common/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + + + bwie-common + pom + + bwie-common-log + bwie-common-core + + + + 8 + 8 + UTF-8 + + + diff --git a/bwie-gateway/.gitignore b/bwie-gateway/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-gateway/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-gateway/pom.xml b/bwie-gateway/pom.xml new file mode 100644 index 0000000..bb592f2 --- /dev/null +++ b/bwie-gateway/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + + + bwie-gateway + + + 8 + 8 + UTF-8 + + + + + com.bwie + bwie-common-core + + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + com.alibaba.cloud + spring-cloud-alibaba-sentinel-gateway + + + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + + + diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java b/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java new file mode 100644 index 0000000..5705d6f --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java @@ -0,0 +1,32 @@ +package com.bwie.gateway.config; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * @description: 放行白名单配置 + * @author DongZl + */ +@Configuration +@RefreshScope +@ConfigurationProperties(prefix = "ignore") +@Data +@Log4j2 +public class IgnoreWhiteConfig { + /** + * 放行白名单配置,网关不校验此处的白名单 + */ + private List whites = new ArrayList<>(); + + public void setWhites(List whites) { + log.info("加载网关路径白名单:{}", JSONObject.toJSONString(whites)); + this.whites = whites; + } +} diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java b/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java new file mode 100644 index 0000000..451af82 --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java @@ -0,0 +1,103 @@ +package com.bwie.gateway.filters; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.constants.TokenConstants; +import com.bwie.common.domain.SysUser; +import com.bwie.common.utils.JwtUtils; +import com.bwie.common.utils.StringUtils; +import com.bwie.gateway.config.IgnoreWhiteConfig; +import com.bwie.gateway.utils.GatewayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @ClassName: + * @Description: 鉴权过滤器 拦截请求验证 token + * @Author: zhuwenqiang + * @Date: 2023/10/19 + */ +@Component +public class AuthFilter implements GlobalFilter, Ordered { + + @Autowired + private IgnoreWhiteConfig ignoreWhitesConfig; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 过滤方法 只要在这个方法中实现业务 验证 token + *

+ * 会将不拦截的请求 配置到 配置文件中 + * + * @param exchange 请求的上下文 获取请求和响应对象 + * @param chain 网关过滤器链 放行 + * @return + */ + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // 获取系统白名单请求 + List whites = ignoreWhitesConfig.getWhites(); + // 判断 当前 请求是否是 白名单的请求 + // 获取当前请求的 URI + ServerHttpRequest request = exchange.getRequest(); + String path = request.getURI().getPath(); + if (StringUtils.matches(path, whites)) { + // 白名单请求 放行 + return chain.filter(exchange); + } + // 验证 token 非空 + String token = request.getHeaders().getFirst(TokenConstants.TOKEN); + if (StringUtils.isBlank(token)) { + // 提示错误信息 + return GatewayUtils.errorResponse(exchange, "token不能为空!"); + } + // 合法性验证 + String userKey = null; + try { + userKey = JwtUtils.getUserKey(token); + } catch (Exception e) { + return GatewayUtils.errorResponse(exchange, "token不合法!"); + } + // token 有效性验证 + // 获取 userKey + if (!redisTemplate.hasKey(TokenConstants.LOGIN_TOKEN_KEY + userKey)) { + // 提示错误信息 + return GatewayUtils.errorResponse(exchange, "token过期!"); + } + // 续期 登录在10分钟以内自动续期 + // 获取用户的登录时间 + String userJSON = redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey); + SysUser sysUser = JSONObject.parseObject(userJSON, SysUser.class); + Date loginDate = sysUser.getLoginDate(); + long min = DateUtil.between(loginDate, new Date(), DateUnit.MINUTE); + if (min <= 10) { + redisTemplate.expire(TokenConstants.LOGIN_TOKEN_KEY + userKey, 30, TimeUnit.MINUTES); + } + // 放行 + return chain.filter(exchange); + } + + /** + * 过滤器的执行顺序 【过滤器可以有多个】 返回的值越小 优先级越高 + * + * @return + */ + @Override + public int getOrder() { + return 0; + } +} diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java b/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java new file mode 100644 index 0000000..7b789e5 --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java @@ -0,0 +1,98 @@ +package com.bwie.gateway.utils; + +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.result.Result; +import com.bwie.common.utils.StringUtils; +import lombok.extern.log4j.Log4j2; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * @author DongZl + * @description: 网关处理工具类 + */ +@Log4j2 +public class GatewayUtils { + /** + * 添加请求头参数 + * @param mutate 修改对象 + * @param key 键 + * @param value 值 + */ + public static void addHeader(ServerHttpRequest.Builder mutate, String key, Object value) { + if (StringUtils.isEmpty(key)){ + log.warn("添加请求头参数键不可以为空"); + return; + } + if (value == null) { + log.warn("添加请求头参数:[{}]值为空",key); + return; + } + String valueStr = value.toString(); + mutate.header(key, valueStr); + log.info("添加请求头参数成功 - 键:[{}] , 值:[{}]", key , value); + } + + /** + * 删除请求头参数 + * @param mutate 修改对象 + * @param key 键 + */ + public static void removeHeader(ServerHttpRequest.Builder mutate, String key) { + if (StringUtils.isEmpty(key)){ + log.warn("删除请求头参数键不可以为空"); + return; + } + mutate.headers(httpHeaders -> httpHeaders.remove(key)).build(); + log.info("删除请求头参数 - 键:[{}]",key); + } + + /** + * 错误结果响应 + * @param exchange 响应上下文 + * @param msg 响应消息 + * @return + */ + public static Mono errorResponse(ServerWebExchange exchange, String msg, HttpStatus httpStatus) { + ServerHttpResponse response = exchange.getResponse(); + //设置HTTP响应头状态 + response.setStatusCode(httpStatus); + //设置HTTP响应头文本格式 + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json"); + //定义响应内容 + Result result = Result.error(msg); + String resultJson = JSONObject.toJSONString(result); + log.error("[鉴权异常处理]请求路径:[{}],异常信息:[{}],响应结果:[{}]", exchange.getRequest().getPath(), msg, resultJson); + DataBuffer dataBuffer = response.bufferFactory().wrap(resultJson.getBytes()); + //进行响应 + return response.writeWith(Mono.just(dataBuffer)); + } + + /** + * 错误结果响应 + * @param exchange 响应上下文 + * @param msg 响应消息 + * @return + */ + public static Mono errorResponse(ServerWebExchange exchange, String msg) { + ServerHttpResponse response = exchange.getResponse(); + //设置HTTP响应头状态 + response.setStatusCode(HttpStatus.OK); + //设置HTTP响应头文本格式 + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json"); + //定义响应内容 + Result result = Result.error(msg); + String resultJson = JSONObject.toJSONString(result); + log.error("[鉴权异常处理]请求路径:[{}],异常信息:[{}],响应结果:[{}]", exchange.getRequest().getPath(), msg, resultJson); + DataBuffer dataBuffer = response.bufferFactory().wrap(resultJson.getBytes()); + //进行响应 + return response.writeWith(Mono.just(dataBuffer)); + } + + +} diff --git a/bwie-gateway/src/main/resources/bootstrap.yml b/bwie-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..bcfbb22 --- /dev/null +++ b/bwie-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,31 @@ +# Tomcat +server: + port: 18080 +# Spring +spring: + application: + # 应用名称 + name: bwie-gateway + profiles: + # 环境配置 + active: dev + main: + # 允许使用循环引用 + allow-circular-references: true + # 允许定义相同的bean对象 去覆盖原有的 + allow-bean-definition-overriding: true + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 124.223.114.120:8848 + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa + config: + # 配置中心地址 + server-addr: 124.223.114.120:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa \ No newline at end of file diff --git a/bwie-modules/.gitignore b/bwie-modules/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-modules/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-modules/bwie-system/.gitignore b/bwie-modules/bwie-system/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-modules/bwie-system/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-modules/bwie-system/pom.xml b/bwie-modules/bwie-system/pom.xml new file mode 100644 index 0000000..8956092 --- /dev/null +++ b/bwie-modules/bwie-system/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.bwie + bwie-modules + 1.0-SNAPSHOT + + + bwie-system + + + 8 + 8 + UTF-8 + + + + + com.bwie + bwie-common-core + + + javax.servlet + servlet-api + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba + druid-spring-boot-starter + + + + mysql + mysql-connector-java + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + com.bwie + bwie-common-log + + + diff --git a/bwie-modules/bwie-system/src/main/resources/bootstrap.yml b/bwie-modules/bwie-system/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..2ebec53 --- /dev/null +++ b/bwie-modules/bwie-system/src/main/resources/bootstrap.yml @@ -0,0 +1,43 @@ +# Tomcat +server: + port: 9002 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwie-user + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 124.223.114.120:8848 + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa + config: + # 配置中心地址 + server-addr: 124.223.114.120:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + namespace: 00f412e2-0405-407b-a17e-0f5b2528f0fa +fdfs: + so-timeout: 1500 # socket 连接时长 + connect-timeout: 600 # 连接 tracker 服务器超时时长 + # 这两个是你服务器的 IP 地址,注意 23000 端口也要打开,阿里云服务器记得配置安全组。tracker 要和 stroage 服务进行交流 + tracker-list: 124.223.114.120:22122 + web-server-url: 124.223.114.120:8888 + pool: + jmx-enabled: false + # 生成缩略图 + thumb-image: + height: 500 + width: 500 \ No newline at end of file diff --git a/bwie-modules/pom.xml b/bwie-modules/pom.xml new file mode 100644 index 0000000..d28dec8 --- /dev/null +++ b/bwie-modules/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + + + bwie-modules + pom + + bwie-system + + + + 8 + 8 + UTF-8 + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..31ed86b --- /dev/null +++ b/pom.xml @@ -0,0 +1,144 @@ + + + 4.0.0 + + com.bwie + day15-1 + 1.0-SNAPSHOT + pom + + bwie-common + bwie-auth + bwie-api + bwie-gateway + bwie-modules + + + + 8 + 8 + UTF-8 + 2.6.2 + 2021.0.0 + 2021.1 + 2.0.4 + 1.0-SNAPSHOT + 0.9.1 + 1.2.80 + 5.8.3 + 2.0.1 + 1.2.8 + 2.2.2 + 1.4.1 + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + com.alibaba.nacos + nacos-client + ${nacos-client.version} + + + + com.bwie + bwie-common + ${bwie-common.version} + + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + + cn.hutool + hutool-all + ${hutool-all.version} + + + + com.aliyun + dysmsapi20170525 + ${dysmsapi.version} + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.version} + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.version} + + + + javax.servlet + servlet-api + 2.5 + + + + com.bwie + bwie-system-api + 1.0-SNAPSHOT + + + + com.bwie + bwie-common-core + 1.0-SNAPSHOT + + + com.bwie + bwie-common-log + 1.0-SNAPSHOT + + + + +