From 0ed7a4ddcd2963fa4c48cb3b49160777e29c0481 Mon Sep 17 00:00:00 2001 From: zhuwenqiang Date: Mon, 13 Nov 2023 14:53:23 +0800 Subject: [PATCH] first commit --- bawei-auth/pom.xml | 31 +++ .../main/java/com/bawei/AuthApplication.java | 23 ++ .../bawei/auth/controller/AuthController.java | 230 ++++++++++++++++++ .../java/com/bawei/auth/feign/UserFeign.java | 32 +++ .../bawei/auth/feign/UserFeignCallback.java | 28 +++ bawei-auth/src/main/resources/application.yml | 29 +++ bawei-common/pom.xml | 72 ++++++ .../java/com/bawei/common/domain/Article.java | 51 ++++ .../com/bawei/common/domain/JwtResponse.java | 24 ++ .../com/bawei/common/domain/LoginLog.java | 37 +++ .../bawei/common/domain/SysOperationLog.java | 63 +++++ .../java/com/bawei/common/domain/SysUser.java | 27 ++ .../java/com/bawei/common/domain/User.java | 34 +++ .../common/domain/request/ArticleRequest.java | 49 ++++ .../domain/request/CodeLoginRequest.java | 24 ++ .../common/domain/request/SysUserRequest.java | 43 ++++ .../com/bawei/common/result/PageResult.java | 38 +++ .../java/com/bawei/common/result/Result.java | 64 +++++ .../java/com/bawei/common/utils/JwtUtils.java | 139 +++++++++++ .../com/bawei/common/utils/StringUtils.java | 67 +++++ .../com/bawei/common/utils/TelSmsUtils.java | 87 +++++++ bawei-eureka/pom.xml | 28 +++ .../com/bawei/eureka/EurekaApplication.java | 21 ++ .../src/main/resources/application.yml | 13 + bawei-gateway/pom.xml | 35 +++ .../com/bawei/gateway/GatewayApplication.java | 21 ++ .../gateway/config/GatewayConfiguration.java | 122 ++++++++++ .../com/bawei/gateway/filter/AuthFilter.java | 83 +++++++ .../com/bawei/gateway/filter/LogFilter.java | 19 ++ .../com/bawei/gateway/utils/GatewayUtils.java | 72 ++++++ .../src/main/resources/application.yml | 63 +++++ bawei-modules/bawei-es/pom.xml | 32 +++ .../main/java/com/bawei/es/ESApplication.java | 21 ++ .../es/controller/ArticleController.java | 102 ++++++++ .../com/bawei/es/service/ArticleService.java | 40 +++ .../es/service/impl/ArticleServiceImpl.java | 228 +++++++++++++++++ .../java/com/bawei/es/service/impl/biij.md | 148 +++++++++++ .../src/main/resources/application.yml | 15 ++ bawei-modules/bawei-mongo/pom.xml | 25 ++ .../com/bawei/mongo/MongoApplication.java | 21 ++ .../com/bawei/mongo/annotaion/SysLog.java | 19 ++ .../bawei/mongo/aop/SysOperationLogAop.java | 80 ++++++ .../mongo/controller/SysUserController.java | 167 +++++++++++++ .../src/main/resources/application.yml | 19 ++ bawei-modules/bawei-system/pom.xml | 47 ++++ .../com/bawei/system/SystemApplication.java | 22 ++ .../system/controller/UserController.java | 73 ++++++ .../com/bawei/system/mapper/UserMapper.java | 23 ++ .../com/bawei/system/service/UserService.java | 27 ++ .../system/service/impl/UserServiceImpl.java | 78 ++++++ .../src/main/resources/application.yml | 43 ++++ .../src/main/resources/mapper/UserMapper.xml | 11 + bawei-modules/pom.xml | 21 ++ pom.xml | 57 +++++ 笔记.md | 61 +++++ 55 files changed, 3049 insertions(+) create mode 100644 bawei-auth/pom.xml create mode 100644 bawei-auth/src/main/java/com/bawei/AuthApplication.java create mode 100644 bawei-auth/src/main/java/com/bawei/auth/controller/AuthController.java create mode 100644 bawei-auth/src/main/java/com/bawei/auth/feign/UserFeign.java create mode 100644 bawei-auth/src/main/java/com/bawei/auth/feign/UserFeignCallback.java create mode 100644 bawei-auth/src/main/resources/application.yml create mode 100644 bawei-common/pom.xml create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/Article.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/JwtResponse.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/LoginLog.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/SysOperationLog.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/SysUser.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/User.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/request/ArticleRequest.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/request/CodeLoginRequest.java create mode 100644 bawei-common/src/main/java/com/bawei/common/domain/request/SysUserRequest.java create mode 100644 bawei-common/src/main/java/com/bawei/common/result/PageResult.java create mode 100644 bawei-common/src/main/java/com/bawei/common/result/Result.java create mode 100644 bawei-common/src/main/java/com/bawei/common/utils/JwtUtils.java create mode 100644 bawei-common/src/main/java/com/bawei/common/utils/StringUtils.java create mode 100644 bawei-common/src/main/java/com/bawei/common/utils/TelSmsUtils.java create mode 100644 bawei-eureka/pom.xml create mode 100644 bawei-eureka/src/main/java/com/bawei/eureka/EurekaApplication.java create mode 100644 bawei-eureka/src/main/resources/application.yml create mode 100644 bawei-gateway/pom.xml create mode 100644 bawei-gateway/src/main/java/com/bawei/gateway/GatewayApplication.java create mode 100644 bawei-gateway/src/main/java/com/bawei/gateway/config/GatewayConfiguration.java create mode 100644 bawei-gateway/src/main/java/com/bawei/gateway/filter/AuthFilter.java create mode 100644 bawei-gateway/src/main/java/com/bawei/gateway/filter/LogFilter.java create mode 100644 bawei-gateway/src/main/java/com/bawei/gateway/utils/GatewayUtils.java create mode 100644 bawei-gateway/src/main/resources/application.yml create mode 100644 bawei-modules/bawei-es/pom.xml create mode 100644 bawei-modules/bawei-es/src/main/java/com/bawei/es/ESApplication.java create mode 100644 bawei-modules/bawei-es/src/main/java/com/bawei/es/controller/ArticleController.java create mode 100644 bawei-modules/bawei-es/src/main/java/com/bawei/es/service/ArticleService.java create mode 100644 bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/ArticleServiceImpl.java create mode 100644 bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/biij.md create mode 100644 bawei-modules/bawei-es/src/main/resources/application.yml create mode 100644 bawei-modules/bawei-mongo/pom.xml create mode 100644 bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/MongoApplication.java create mode 100644 bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/annotaion/SysLog.java create mode 100644 bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/aop/SysOperationLogAop.java create mode 100644 bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/controller/SysUserController.java create mode 100644 bawei-modules/bawei-mongo/src/main/resources/application.yml create mode 100644 bawei-modules/bawei-system/pom.xml create mode 100644 bawei-modules/bawei-system/src/main/java/com/bawei/system/SystemApplication.java create mode 100644 bawei-modules/bawei-system/src/main/java/com/bawei/system/controller/UserController.java create mode 100644 bawei-modules/bawei-system/src/main/java/com/bawei/system/mapper/UserMapper.java create mode 100644 bawei-modules/bawei-system/src/main/java/com/bawei/system/service/UserService.java create mode 100644 bawei-modules/bawei-system/src/main/java/com/bawei/system/service/impl/UserServiceImpl.java create mode 100644 bawei-modules/bawei-system/src/main/resources/application.yml create mode 100644 bawei-modules/bawei-system/src/main/resources/mapper/UserMapper.xml create mode 100644 bawei-modules/pom.xml create mode 100644 pom.xml create mode 100644 笔记.md diff --git a/bawei-auth/pom.xml b/bawei-auth/pom.xml new file mode 100644 index 0000000..234e887 --- /dev/null +++ b/bawei-auth/pom.xml @@ -0,0 +1,31 @@ + + + + bawei-cloud + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-auth + + + + + com.bawei + bawei-common + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + diff --git a/bawei-auth/src/main/java/com/bawei/AuthApplication.java b/bawei-auth/src/main/java/com/bawei/AuthApplication.java new file mode 100644 index 0000000..28ab5ac --- /dev/null +++ b/bawei-auth/src/main/java/com/bawei/AuthApplication.java @@ -0,0 +1,23 @@ +package com.bawei; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * 鉴权微服务启动类 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@SpringBootApplication +@EnableEurekaClient +@EnableFeignClients +public class AuthApplication { + + public static void main(String[] args) { + SpringApplication.run(AuthApplication.class); + } + +} diff --git a/bawei-auth/src/main/java/com/bawei/auth/controller/AuthController.java b/bawei-auth/src/main/java/com/bawei/auth/controller/AuthController.java new file mode 100644 index 0000000..e976267 --- /dev/null +++ b/bawei-auth/src/main/java/com/bawei/auth/controller/AuthController.java @@ -0,0 +1,230 @@ +package com.bawei.auth.controller; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.JwtResponse; +import com.bawei.common.domain.User; +import com.bawei.common.domain.request.CodeLoginRequest; +import com.bawei.common.result.Result; +import com.bawei.common.utils.JwtUtils; +import com.bawei.common.utils.StringUtils; +import com.bawei.auth.feign.UserFeign; +import com.bawei.common.utils.TelSmsUtils; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +/** + * 登录鉴权控制层 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@RestController +@Log4j2 +public class AuthController { + + @Autowired + private HttpServletRequest request; + + @Autowired + private UserFeign userFeign; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 手机号正则 + */ + private static final String REGEX_PHONE = "^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[1|8|9]))\\d{8}$"; + + /* + * 登录 + * @param user + * @return + */ + @PostMapping("/login") + public Result login(@RequestBody User user) { + log.info("功能名称:鉴权登录,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(user)); + // 1: 非空验证 + if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) { + Result result = Result.error("用户名或者密码不能为空!"); + log.info("功能名称:鉴权登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 2: 根据用户查询用户信息 + Result userByUsername = userFeign.findUserByUsername(user.getUsername()); + User loginUser = userByUsername.getData(); + if (loginUser == null) { + Result result = Result.error("用户名不存在!"); + log.info("功能名称:鉴权登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 3; 密码 + if (!user.getPassword().equals(loginUser.getPassword())) { + Result result = Result.error("密码错误!"); + log.info("功能名称:鉴权登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 4; 登录 成功 token + // 生成 userKey + String userKey = UUID.randomUUID().toString().replaceAll("-", ""); + Map jwtMap = new HashMap<>(); + jwtMap.put(JwtUtils.DETAILS_USER_ID, loginUser.getId()); + jwtMap.put(JwtUtils.USER_KEY, userKey); + String token = JwtUtils.createToken(jwtMap); + + // 将用户信息存入到 redis + redisTemplate.opsForValue().set(JwtUtils.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(loginUser), 500, TimeUnit.MINUTES); + + // 创建登录鉴权响应对象 + JwtResponse jwtResponse = new JwtResponse(); + jwtResponse.setToken(token); + jwtResponse.setExpireTime("500MIN"); + Result result = Result.success(jwtResponse); + + log.info("功能名称:鉴权登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 获取用户信息 + */ + @GetMapping("/user/info") + public Result userInfo() { + log.info("功能名称:获取用户信息,请求路径:【{}】,请求方式:【{}】", request.getRequestURI(), + request.getMethod()); + // 获取请求头 + String token = request.getHeader(JwtUtils.TOKEN); + // 获取userKey + String userKey = JwtUtils.getUserKey(token); + // 获取redis中的用户信息 + String userJson = redisTemplate.opsForValue().get(JwtUtils.LOGIN_TOKEN_KEY + userKey); + // 反序列化 json + User user = JSONObject.parseObject(userJson, User.class); + Result result = Result.success(user); + log.info("功能名称:获取用户信息,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 发送短信验证码 + * @param tel + * @return + */ + @PostMapping("/send/code/{tel}") + public Result sendCode(@PathVariable("tel") String tel) { + log.info("功能名称:发送短信验证码,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), tel); + // 验证手机号 + boolean bol = Pattern.matches(REGEX_PHONE, tel); + if (!bol) { + return Result.error("手机号不合法!"); + } + // 生成验证码 6位数字验证码 不能以 0 开头 + String code = ""; + for (int i = 0; i < 6; i++) { + int num = new Random().nextInt(10); + if (num == 0 && i == 0) { + // 重新生成 + i--; + continue; + } + code += num; + } + // 存验证码 redis + redisTemplate.opsForValue().set(tel, code, 2, TimeUnit.MINUTES); + // 发送验证码 阿里大鱼 + String finalCode = code; + TelSmsUtils.sendSms(tel, "DX10001", new HashMap() {{ + put("code", finalCode); + }}); + Result result = Result.success(); + log.info("功能名称:发送短信验证码,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 短信验证码登录 + * @param codeLoginRequest + * @return + */ + @PostMapping("/code/login") + public Result login(@RequestBody CodeLoginRequest codeLoginRequest) { + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(codeLoginRequest)); + // 非空验证 + if (StringUtils.isEmpty(codeLoginRequest.getTel()) || StringUtils.isEmpty(codeLoginRequest.getCode())) { + Result result = Result.error("手机号或者验证码不能为空!"); + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 验证手机号是否存在 + Result byTel = userFeign.findByTel(codeLoginRequest.getTel()); + if (byTel.getCode() == Result.FAIL) { + // 降级 + Result result = Result.error("服务降级了!"); + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + User loginUser = byTel.getData(); + if (loginUser == null) { + Result result = Result.error("手机号不存在!"); + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 比对验证码 + // 获取验证码 + String code = redisTemplate.opsForValue().get(codeLoginRequest.getTel()); + if (code == null || !code.equals(codeLoginRequest.getCode())) { + Result result = Result.error("验证码失效或者错误!"); + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + // 认证成功 JWT 生成 token 令牌 + // 生成UserKey + String userKey = UUID.randomUUID().toString().replaceAll("-", ""); + HashMap jwtMap = new HashMap<>(); + jwtMap.put(JwtUtils.DETAILS_USER_ID, loginUser.getId()); + jwtMap.put(JwtUtils.USER_KEY, userKey); + String token = JwtUtils.createToken(jwtMap); + + // 将用户的信息存入到 redis + redisTemplate.opsForValue().set(JwtUtils.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(loginUser), 50, TimeUnit.MINUTES); + + // 生成 JwtResponse + JwtResponse jwtResponse = new JwtResponse(); + jwtResponse.setToken(token); + jwtResponse.setExpireTime("50MIN"); + Result result = Result.success(jwtResponse); + log.info("功能名称:短信验证码登录,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + public static void main(String[] args) { + boolean matches = Pattern.matches(REGEX_PHONE, "13817253816"); + System.out.println(matches); + } + + +} diff --git a/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeign.java b/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeign.java new file mode 100644 index 0000000..fbb589f --- /dev/null +++ b/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeign.java @@ -0,0 +1,32 @@ +package com.bawei.auth.feign; + +import com.bawei.common.domain.User; +import com.bawei.common.result.Result; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +/** + * 用户远程调用 + */ +@FeignClient(name = "bawei-system", path = "/sys/user", fallback = UserFeignCallback.class) +public interface UserFeign { + + /** + * 根据用户名查询用户信息 + * @param username + * @return + */ + @GetMapping("/findUserByUsername/{username}") + public Result findUserByUsername(@PathVariable("username") String username); + + + /** + * 根据手机号查询用户信息 + * @param tel + * @return + */ + @GetMapping("/findByTel/{tel}") + public Result findByTel(@PathVariable("tel") String tel); + +} diff --git a/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeignCallback.java b/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeignCallback.java new file mode 100644 index 0000000..9f35a3e --- /dev/null +++ b/bawei-auth/src/main/java/com/bawei/auth/feign/UserFeignCallback.java @@ -0,0 +1,28 @@ +package com.bawei.auth.feign; + +import com.bawei.common.domain.User; +import com.bawei.common.result.Result; +import org.springframework.stereotype.Component; + +/** + * 系统服务远程调用降级处理类 + * + * @author zhuwenqiang + * @date 2022/11/16 + */ +@Component +public class UserFeignCallback implements UserFeign { + + @Override + public Result findUserByUsername(String username) { + User user = new User(); + return Result.error("熔断降级..."); + } + + @Override + public Result findByTel(String tel) { + User user = new User(); + user.setId(-1); + return Result.error(user); + } +} diff --git a/bawei-auth/src/main/resources/application.yml b/bawei-auth/src/main/resources/application.yml new file mode 100644 index 0000000..858fd27 --- /dev/null +++ b/bawei-auth/src/main/resources/application.yml @@ -0,0 +1,29 @@ +server: + port: 10067 +spring: + application: + name: bawei-auth + rabbitmq: + listener: + #如果手动声明listener类型,可在config声明时设置 + direct: + acknowledge-mode: MANUAL + simple: + acknowledge-mode: MANUAL + host: 127.0.0.1 + main: + allow-circular-references: true +#eureka注册中心地址 +eureka: + instance: + # 微服务实例IP地址 + instance-id: 127.0.0.1:${server.port} + # 使用IP进行访问 + prefer-ip-address: true + client: + service-url: + defaultZone: http://localhost:10086/eureka/ +# 开启熔断 +feign: + sentinel: + enabled: true diff --git a/bawei-common/pom.xml b/bawei-common/pom.xml new file mode 100644 index 0000000..f095181 --- /dev/null +++ b/bawei-common/pom.xml @@ -0,0 +1,72 @@ + + + + bawei-cloud + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-common + + + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + com.alibaba + fastjson + 1.2.79 + + + + org.apache.commons + commons-lang3 + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + org.springframework.boot + spring-boot-starter-amqp + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + com.aliyun + dysmsapi20170525 + 2.0.1 + + + + diff --git a/bawei-common/src/main/java/com/bawei/common/domain/Article.java b/bawei-common/src/main/java/com/bawei/common/domain/Article.java new file mode 100644 index 0000000..ca13539 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/Article.java @@ -0,0 +1,51 @@ +package com.bawei.common.domain; + +import lombok.Data; + +import java.util.Date; + +/** + * 文章实体类{ES} + * + * @author zhuwenqiang + * @date 2022/11/15 + */ +@Data +public class Article { + + /** + * id + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 作者 + */ + private String author; + + /** + * 文章类型 + */ + private String type; + + /** + * 价格 + */ + private Double price; + + /** + * 地址 + */ + private String address; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/JwtResponse.java b/bawei-common/src/main/java/com/bawei/common/domain/JwtResponse.java new file mode 100644 index 0000000..5ac6586 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/JwtResponse.java @@ -0,0 +1,24 @@ +package com.bawei.common.domain; + +import lombok.Data; + +/** + * 登录鉴权响应实体类 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Data +public class JwtResponse { + + /** + * token令牌 + */ + private String token; + + /** + * 过期时间 + */ + private String expireTime; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/LoginLog.java b/bawei-common/src/main/java/com/bawei/common/domain/LoginLog.java new file mode 100644 index 0000000..0360c1f --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/LoginLog.java @@ -0,0 +1,37 @@ +package com.bawei.common.domain; + +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.Date; + +/** + * 类说明 + * + * @author zhuwenqiang + * @date 2022/11/12 + */ +@Data +@Document("login_log") +public class LoginLog { + + @Id + private String id; + + /** + * 用户名 + */ + private String username; + + /** + * 登录时间 + */ + private Date loginTime; + + /** + * 登录结果 + */ + private String result; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/SysOperationLog.java b/bawei-common/src/main/java/com/bawei/common/domain/SysOperationLog.java new file mode 100644 index 0000000..0d9a96a --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/SysOperationLog.java @@ -0,0 +1,63 @@ +package com.bawei.common.domain; + +import lombok.Data; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.Date; + +/** + * 系统日志实体类 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Data +@Document("sys_operation_log") +public class SysOperationLog { + + /** + * 功能名称 + */ + private String functionName; + + /** + * 请求参数 + */ + private String reqJson; + + /** + * 响应参数 + */ + private String respJson; + + /** + * 操作时间 + */ + private Date createTime; + + /** + * 执行时长 + */ + private long runTime; + + /** + * 请求URI + */ + private String requestURI; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 类名 + */ + private String clazzName; + + /** + * 方法名 + */ + private String methodName; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/SysUser.java b/bawei-common/src/main/java/com/bawei/common/domain/SysUser.java new file mode 100644 index 0000000..04650cc --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/SysUser.java @@ -0,0 +1,27 @@ +package com.bawei.common.domain; + +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.Date; + +/** + * 系统用户实体类 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@Data +@Document("sys_user") // 规定集合名 +public class SysUser { + + @Id + private String id; + private String username; + private String password; + private int age; + private String sex; + private Date createTime; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/User.java b/bawei-common/src/main/java/com/bawei/common/domain/User.java new file mode 100644 index 0000000..a7f977c --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/User.java @@ -0,0 +1,34 @@ +package com.bawei.common.domain; + +import lombok.Data; + +/** + * 类说明 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Data +public class User { + + /** + * id + */ + private Integer id; + + /** + * 用户名 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 手机号 + */ + private String tel; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/request/ArticleRequest.java b/bawei-common/src/main/java/com/bawei/common/domain/request/ArticleRequest.java new file mode 100644 index 0000000..ca87616 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/request/ArticleRequest.java @@ -0,0 +1,49 @@ +package com.bawei.common.domain.request; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * 文章搜索请求实体类 + * + * @author zhuwenqiang + * @date 2022/11/15 + */ +@Data +public class ArticleRequest { + + /** + * 文章标题 + */ + private String title; + + /** + * 作者 + */ + private String author; + + /** + * 开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date startTime; + + /** + * 结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + /** + * 页码 + */ + private Integer pageNum = 1; + + /** + * 分页展示条数 + */ + private Integer pageSize = 2; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/request/CodeLoginRequest.java b/bawei-common/src/main/java/com/bawei/common/domain/request/CodeLoginRequest.java new file mode 100644 index 0000000..f1f1f30 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/request/CodeLoginRequest.java @@ -0,0 +1,24 @@ +package com.bawei.common.domain.request; + +import lombok.Data; + +/** + * 短信验证码请求实体类 + * + * @author zhuwenqiang + * @date 2022/11/16 + */ +@Data +public class CodeLoginRequest { + + /** + * 手机号 + */ + private String tel; + + /** + * 验证码 + */ + private String code; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/domain/request/SysUserRequest.java b/bawei-common/src/main/java/com/bawei/common/domain/request/SysUserRequest.java new file mode 100644 index 0000000..0dcb698 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/domain/request/SysUserRequest.java @@ -0,0 +1,43 @@ +package com.bawei.common.domain.request; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * 系统用户查询条件对象 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Data +public class SysUserRequest { + + /** + * 用户名 + */ + private String username; + + /** + * 性别 + */ + private String sex; + + /** + * 创建时间区间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date startTime; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + /** + * 分页 + */ + private Integer pageNum = 1; + + private Integer pageSize = 2; + +} diff --git a/bawei-common/src/main/java/com/bawei/common/result/PageResult.java b/bawei-common/src/main/java/com/bawei/common/result/PageResult.java new file mode 100644 index 0000000..f67db41 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/result/PageResult.java @@ -0,0 +1,38 @@ +package com.bawei.common.result; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 分页响应结果 + * @param + */ +@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/bawei-common/src/main/java/com/bawei/common/result/Result.java b/bawei-common/src/main/java/com/bawei/common/result/Result.java new file mode 100644 index 0000000..adc1b04 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/result/Result.java @@ -0,0 +1,64 @@ +package com.bawei.common.result; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 接口公共返回值对象 + * @param + */ +@Data +public class Result implements Serializable { + + private static final long serialVersionUID = 1L; + /** 成功 */ + public static final int SUCCESS = 100; + /** 失败 */ + public static final int FAIL = 500; + + /** + * 接口响应的状态码 + */ + private int code; + /** + * 响应信息 + */ + private String msg; + /** + * 响应的数据 + */ + private T data; + + public static Result success() { + return restResult(null, SUCCESS, "操作成功"); + } + public static Result success(T data) { + return restResult(data, SUCCESS, "操作成功"); + } + public static Result success(T data, String msg) { + return restResult(data, SUCCESS, msg); + } + public static Result error() { + return restResult(null, FAIL, "操作失败"); + } + public static Result error(String msg) { + return restResult(null, FAIL, msg); + } + public static Result error(T data) { + return restResult(data, FAIL, "操作失败"); + } + 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/bawei-common/src/main/java/com/bawei/common/utils/JwtUtils.java b/bawei-common/src/main/java/com/bawei/common/utils/JwtUtils.java new file mode 100644 index 0000000..3e8fc76 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/utils/JwtUtils.java @@ -0,0 +1,139 @@ +package com.bawei.common.utils; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import java.util.Map; + +/** + * JWT 工具类 + */ +public class JwtUtils { + + /** + * 用户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"; + + /** + * 缓存有效期,默认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"; + + public static String secret = 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, USER_KEY); + } + /** + * 根据令牌获取用户标识 + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserKey(Claims claims){ + return getValue(claims, USER_KEY); + } + /** + * 根据令牌获取用户ID + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserId(String token){ + Claims claims = parseToken(token); + return getValue(claims, DETAILS_USER_ID); + } + /** + * 根据身份信息获取用户ID + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserId(Claims claims){ + return getValue(claims, DETAILS_USER_ID); + } + /** + * 根据令牌获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public static String getUserName(String token){ + Claims claims = parseToken(token); + return getValue(claims, DETAILS_USERNAME); + } + /** + * 根据身份信息获取用户名 + * + * @param claims 身份信息 + * @return 用户名 + */ + public static String getUserName(Claims claims){ + return getValue(claims, 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/bawei-common/src/main/java/com/bawei/common/utils/StringUtils.java b/bawei-common/src/main/java/com/bawei/common/utils/StringUtils.java new file mode 100644 index 0000000..611458a --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/utils/StringUtils.java @@ -0,0 +1,67 @@ +package com.bawei.common.utils; + +import org.springframework.util.AntPathMatcher; + +import java.util.Collection; +import java.util.List; + +/** + * 字符串工具类 + */ +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/bawei-common/src/main/java/com/bawei/common/utils/TelSmsUtils.java b/bawei-common/src/main/java/com/bawei/common/utils/TelSmsUtils.java new file mode 100644 index 0000000..57e68f1 --- /dev/null +++ b/bawei-common/src/main/java/com/bawei/common/utils/TelSmsUtils.java @@ -0,0 +1,87 @@ +package com.bawei.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 = "LTAI4G6peir22sezmgXWCU5J"; + private static String accessKeySecret = "hxyjib6LR6xaQtDpY8gfIb3UDeokoz"; + + /** + * 短信访问域名 + */ + 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 templateCode SMS_153991546 + * @param sendDataMap + */ + public static String sendSms(String tel , String templateCode , 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); + } + return JSONObject.toJSONString(sendSmsResponse.getBody()); + } + +} diff --git a/bawei-eureka/pom.xml b/bawei-eureka/pom.xml new file mode 100644 index 0000000..8b4b344 --- /dev/null +++ b/bawei-eureka/pom.xml @@ -0,0 +1,28 @@ + + + + bawei-cloud + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-eureka + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + + diff --git a/bawei-eureka/src/main/java/com/bawei/eureka/EurekaApplication.java b/bawei-eureka/src/main/java/com/bawei/eureka/EurekaApplication.java new file mode 100644 index 0000000..5252030 --- /dev/null +++ b/bawei-eureka/src/main/java/com/bawei/eureka/EurekaApplication.java @@ -0,0 +1,21 @@ +package com.bawei.eureka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +/** + * 注册中心启动类 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@SpringBootApplication +@EnableEurekaServer +public class EurekaApplication { + + public static void main(String[] args) { + SpringApplication.run(EurekaApplication.class); + } + +} diff --git a/bawei-eureka/src/main/resources/application.yml b/bawei-eureka/src/main/resources/application.yml new file mode 100644 index 0000000..416507f --- /dev/null +++ b/bawei-eureka/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 10086 +spring: + application: + name: bawei-eureka +eureka: + client: + #禁止自己当做服务注册 + register-with-eureka: false + #屏蔽注册信息 + fetch-registry: false + serviceUrl: + defaultZone: http://localhost:${server.port}/eureka/ diff --git a/bawei-gateway/pom.xml b/bawei-gateway/pom.xml new file mode 100644 index 0000000..bf85f68 --- /dev/null +++ b/bawei-gateway/pom.xml @@ -0,0 +1,35 @@ + + + + bawei-cloud + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-gateway + + + + + com.bawei + bawei-common + + + org.springframework.cloud + spring-cloud-starter-gateway + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + + + + diff --git a/bawei-gateway/src/main/java/com/bawei/gateway/GatewayApplication.java b/bawei-gateway/src/main/java/com/bawei/gateway/GatewayApplication.java new file mode 100644 index 0000000..48a63df --- /dev/null +++ b/bawei-gateway/src/main/java/com/bawei/gateway/GatewayApplication.java @@ -0,0 +1,21 @@ +package com.bawei.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * 网关启动类 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@SpringBootApplication +@EnableEurekaClient +public class GatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class); + } + +} diff --git a/bawei-gateway/src/main/java/com/bawei/gateway/config/GatewayConfiguration.java b/bawei-gateway/src/main/java/com/bawei/gateway/config/GatewayConfiguration.java new file mode 100644 index 0000000..03fd9fd --- /dev/null +++ b/bawei-gateway/src/main/java/com/bawei/gateway/config/GatewayConfiguration.java @@ -0,0 +1,122 @@ +package com.bawei.gateway.config; + +import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; +import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler; +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; +import com.bawei.common.result.Result; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import javax.annotation.PostConstruct; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * sentinel限流的配置 + */ +@Configuration +public class GatewayConfiguration { + + private final List viewResolvers; + private final ServerCodecConfigurer serverCodecConfigurer; + public GatewayConfiguration(ObjectProvider> viewResolversProvider, + ServerCodecConfigurer serverCodecConfigurer) { + this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); + this.serverCodecConfigurer = serverCodecConfigurer; + } + /** + * 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler + */ + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { + return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); + } + /** + * 配置限流过滤器 + */ + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public GlobalFilter sentinelGatewayFilter() { + return new SentinelGatewayFilter(); + } + + /** + * 配置初始化的限流参数 + * 用于指定资源的限流规则. + * 1.资源名称 (路由id) + * 2.配置统计时间 + * 3.配置限流阈值 + */ + @PostConstruct + public void initGatewayRules() { + Set rules = new HashSet<>(); +// rules.add(new GatewayFlowRule("muyu-auth") +// .setCount(1) +// .setIntervalSec(1) +// ); + rules.add(new GatewayFlowRule("login_api") + .setCount(3).setIntervalSec(60) + ); + GatewayRuleManager.loadRules(rules); + } + + /** + * 自定义API限流分组 + * 1.定义分组 + * 2.对小组配置限流规则 + */ + @PostConstruct + private void initCustomizedApis() { + Set definitions = new HashSet<>(); + ApiDefinition api1 = new ApiDefinition("auth_api") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/auth/**"). //以/product-service/product/开都的所有url + setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); + }}); + ApiDefinition api2 = new ApiDefinition("login_api") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/system/sys/user/login")); //完全匹配/order-service/order 的url + }}); + definitions.add(api1); + definitions.add(api2); + GatewayApiDefinitionManager.loadApiDefinitions(definitions); + } + + /** + * 自定义限流处理器 + */ + @PostConstruct + public void initBlockHandlers() { + BlockRequestHandler blockHandler = new BlockRequestHandler() { + public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { + return ServerResponse.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(BodyInserters.fromObject(Result.error("不好意思,限流啦"))); + } + }; + GatewayCallbackManager.setBlockHandler(blockHandler); + } +} diff --git a/bawei-gateway/src/main/java/com/bawei/gateway/filter/AuthFilter.java b/bawei-gateway/src/main/java/com/bawei/gateway/filter/AuthFilter.java new file mode 100644 index 0000000..5d71363 --- /dev/null +++ b/bawei-gateway/src/main/java/com/bawei/gateway/filter/AuthFilter.java @@ -0,0 +1,83 @@ +package com.bawei.gateway.filter; + +import com.bawei.common.utils.JwtUtils; +import com.bawei.common.utils.StringUtils; +import com.bawei.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.ArrayList; +import java.util.List; + +/** + * 鉴权过滤器 + * + * @author zhuwenqiang + * @date 2022/11/12 + */ +//@Component +public class AuthFilter implements GlobalFilter, Ordered { + + /** + * 定义白名单 【不过滤】 + */ + private static final List PATHS = new ArrayList(){{ + add("/auth/login"); + }}; + + @Autowired + private RedisTemplate redisTemplate; + + + /** + * 过滤方法 【过滤请求验证 token】 + * @param exchange + * @param chain + * @return + */ + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // 获取URI 判断是否是白名单请求 + ServerHttpRequest request = exchange.getRequest(); + // 获取请求URI + String path = request.getURI().getPath(); + if (StringUtils.matches(path, PATHS)) { + // 放行 + return chain.filter(exchange); + } + // 获取请求头 获取token + String token = request.getHeaders().getFirst(JwtUtils.TOKEN); + // 验证 非空 + if (StringUtils.isEmpty(token)) { + return GatewayUtils.errorResponse(exchange, "token不能为空!"); + } + // 验证token的合法性 一旦 token 不合法 就会抛出异常 + try { + JwtUtils.parseToken(token); + } catch (Exception ex) { + return GatewayUtils.errorResponse(exchange, "token不合法!"); + } + // token 是否过期 + // 获取userKey + String userKey = JwtUtils.getUserKey(token); + Boolean bol = redisTemplate.hasKey(JwtUtils.LOGIN_TOKEN_KEY + userKey); + if (!bol) { + return GatewayUtils.errorResponse(exchange, "token过期!"); + } + // 验证通过 + return chain.filter(exchange); + } + + @Override + public int getOrder() { + return 0; + } + +} diff --git a/bawei-gateway/src/main/java/com/bawei/gateway/filter/LogFilter.java b/bawei-gateway/src/main/java/com/bawei/gateway/filter/LogFilter.java new file mode 100644 index 0000000..2ed0782 --- /dev/null +++ b/bawei-gateway/src/main/java/com/bawei/gateway/filter/LogFilter.java @@ -0,0 +1,19 @@ +package com.bawei.gateway.filter; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * 类说明 + * + * @author zhuwenqiang + * @date 2022/11/12 + */ +public class LogFilter implements GlobalFilter { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + return null; + } +} diff --git a/bawei-gateway/src/main/java/com/bawei/gateway/utils/GatewayUtils.java b/bawei-gateway/src/main/java/com/bawei/gateway/utils/GatewayUtils.java new file mode 100644 index 0000000..ed14021 --- /dev/null +++ b/bawei-gateway/src/main/java/com/bawei/gateway/utils/GatewayUtils.java @@ -0,0 +1,72 @@ +package com.bawei.gateway.utils; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.result.Result; +import com.bawei.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; + +/** + * 网关工具类 + */ +@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) { + 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/bawei-gateway/src/main/resources/application.yml b/bawei-gateway/src/main/resources/application.yml new file mode 100644 index 0000000..a532524 --- /dev/null +++ b/bawei-gateway/src/main/resources/application.yml @@ -0,0 +1,63 @@ +# Tomcat +server: + port: 18080 +#eureka注册中心地址 +eureka: + instance: + # 微服务实例IP地址 + instance-id: 127.0.0.1:${server.port} + # 使用IP进行访问 + prefer-ip-address: true + client: + service-url: + defaultZone: http://localhost:10086/eureka/ +# Spring +spring: + application: + # 应用名称 + name: bawei-gateway + main: + allow-circular-references: true + allow-bean-definition-overriding: true + web-application-type: reactive + cloud: + sentinel: + transport: + dashboard: 127.0.0.1:8081 + gateway: + globalcors: + cors-configurations: + '[/**]': + # 设置允许的域名 + allowedOrigins: + - "*" + # 允许所有头信息 + allowedHeaders: "*" + # 设置允许携带cookie + # 为true时allowedOrigins不允许为* 会报错 + allowCredentials: false + # 允许跨域请求的请求方式 + allowedMethods: + - GET + - POST + - DELETE + - PUT + discovery: + locator: + lowerCaseServiceId: true + enabled: true + routes: + # 鉴权 + - id: auth + uri: lb://bawei-auth + predicates: + - Path=/auth/** + filters: + - StripPrefix=1 + # 鉴权 + - id: system + uri: lb://bawei-system + predicates: + - Path=/system/** + filters: + - StripPrefix=1 diff --git a/bawei-modules/bawei-es/pom.xml b/bawei-modules/bawei-es/pom.xml new file mode 100644 index 0000000..3595123 --- /dev/null +++ b/bawei-modules/bawei-es/pom.xml @@ -0,0 +1,32 @@ + + + + bawei-modules + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-es + + + + + com.bawei + bawei-common + + + + org.springframework.boot + spring-boot-starter-web + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + + + + diff --git a/bawei-modules/bawei-es/src/main/java/com/bawei/es/ESApplication.java b/bawei-modules/bawei-es/src/main/java/com/bawei/es/ESApplication.java new file mode 100644 index 0000000..029fb59 --- /dev/null +++ b/bawei-modules/bawei-es/src/main/java/com/bawei/es/ESApplication.java @@ -0,0 +1,21 @@ +package com.bawei.es; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * ES搜索启动类 + * + * @author zhuwenqiang + * @date 2022/11/15 + */ +@SpringBootApplication +@EnableEurekaClient +public class ESApplication { + + public static void main(String[] args) { + SpringApplication.run(ESApplication.class); + } + +} diff --git a/bawei-modules/bawei-es/src/main/java/com/bawei/es/controller/ArticleController.java b/bawei-modules/bawei-es/src/main/java/com/bawei/es/controller/ArticleController.java new file mode 100644 index 0000000..8e73f3c --- /dev/null +++ b/bawei-modules/bawei-es/src/main/java/com/bawei/es/controller/ArticleController.java @@ -0,0 +1,102 @@ +package com.bawei.es.controller; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.Article; +import com.bawei.common.domain.request.ArticleRequest; +import com.bawei.common.result.PageResult; +import com.bawei.common.result.Result; +import com.bawei.es.service.ArticleService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +/** + * 文章控制层 + * + * @author zhuwenqiang + * @date 2022/11/15 + */ +@RestController +@RequestMapping("/article") +@Log4j2 +public class ArticleController { + + @Autowired + private HttpServletRequest request; + + @Autowired + private ArticleService articleService; + + /** + * 添加 + */ + @PostMapping + public Result add(@RequestBody Article article) { + log.info("功能名称:ES添加文章,请求路径【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(article)); + articleService.insert(article); + Result result = Result.success(); + log.info("功能名称:ES添加文章,请求路径【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 修改 + */ + @PutMapping + public Result update(@RequestBody Article article) { + log.info("功能名称:ES修改文章,请求路径【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(article)); + articleService.update(article); + Result result = Result.success(); + log.info("功能名称:ES修改文章,请求路径【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 主键查询 + */ + @GetMapping("/{id}") + public Result
findById(@PathVariable("id") String id) { + log.info("功能名称:ES主键查询文章,请求路径【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), id); + Article article = articleService.findById(id); + Result
result = Result.success(article); + log.info("功能名称:ES主键查询文章,请求路径【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 主键删除 + */ + @DeleteMapping("/{id}") + public Result delete(@PathVariable("id") String id) { + log.info("功能名称:ES删除查询文章,请求路径【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), id); + articleService.delete(id); + Result result = Result.success(); + log.info("功能名称:ES删除查询文章,请求路径【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + + /** + * 搜索 + */ + @PostMapping("/search") + public Result> search(@RequestBody ArticleRequest articleRequest) { + log.info("功能名称:文章搜索,请求路径【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(articleRequest)); + Result> result = articleService.search(articleRequest); + log.info("功能名称:文章搜索,请求路径【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + +} diff --git a/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/ArticleService.java b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/ArticleService.java new file mode 100644 index 0000000..277e262 --- /dev/null +++ b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/ArticleService.java @@ -0,0 +1,40 @@ +package com.bawei.es.service; + +import com.bawei.common.domain.Article; +import com.bawei.common.domain.request.ArticleRequest; +import com.bawei.common.result.PageResult; +import com.bawei.common.result.Result; + +public interface ArticleService { + /** + * 添加|修改文章 + * @param article + */ + void insert(Article article); + + /** + * 主键查询 + * @param id + * @return + */ + Article findById(String id); + + /** + * 删除 + * @param id + */ + void delete(String id); + + /** + * 文章搜索 + * @param articleRequest + * @return + */ + Result> search(ArticleRequest articleRequest); + + /** + * 修改 + * @param article + */ + void update(Article article); +} diff --git a/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/ArticleServiceImpl.java b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/ArticleServiceImpl.java new file mode 100644 index 0000000..2ff877a --- /dev/null +++ b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/ArticleServiceImpl.java @@ -0,0 +1,228 @@ +package com.bawei.es.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.Article; +import com.bawei.common.domain.request.ArticleRequest; +import com.bawei.common.result.PageResult; +import com.bawei.common.result.Result; +import com.bawei.common.utils.StringUtils; +import com.bawei.es.service.ArticleService; +import lombok.extern.log4j.Log4j2; +import org.apache.http.HttpHost; +import org.elasticsearch.action.delete.DeleteRequest; +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.common.text.Text; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.MatchQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; +import org.elasticsearch.search.sort.SortOrder; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Map; +import java.util.UUID; + +/** + * 文章业务层 + * + * @author zhuwenqiang + * @date 2022/11/15 + */ +@Service +@Log4j2 +public class ArticleServiceImpl implements ArticleService { + + /** + * 初始化ES高级客户端 【es 增删改查 依赖于这个客户端】 + */ + RestHighLevelClient client = new RestHighLevelClient( + RestClient.builder(new HttpHost("47.102.145.201", 9200, "http")) + ); + + /** + * 索引名 + */ + private static final String INDEX_NAME = "article"; + + @Override + public void insert(Article article) { + // 1; 创建索引请求对象 + IndexRequest indexRequest = new IndexRequest(INDEX_NAME); + // 判断id的值 // 2: 添加 设置id + if (article.getId() != null) { + // 修改 + indexRequest.id(article.getId()); + Article article1 = this.findById(article.getId()); + article.setCreateTime(article1.getCreateTime()); + } else { + // 设置 文章的创建时间 + article.setCreateTime(new Date()); + indexRequest.id(UUID.randomUUID().toString().replace("-", "")); + } + // 3: 设置数据 + indexRequest.source(JSONObject.toJSONString(article), XContentType.JSON); + // 4; 发送请求 + try { + client.index(indexRequest, RequestOptions.DEFAULT); + } catch (IOException e) { + e.printStackTrace(); + log.error("功能名称:ES添加文章,出现异常,异常信息是:【{}】,请求参数是:【{}】", e, JSONObject.toJSONString(article)); + } + } + + @Override + public Article findById(String id) { + try { + // 1: 创建 查询请求对象 + GetRequest getRequest = new GetRequest(INDEX_NAME, id); + // 2: 发送请求 + GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); + // 3: 处理结果集 + if (getResponse.isExists()) { + // 获取数据源 + String articleJson = getResponse.getSourceAsString(); + // 反序列化 Article + Article article = JSONObject.parseObject(articleJson, Article.class); + // 设置id + article.setId(getResponse.getId()); + return article; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + @Override + public void delete(String id) { + try { + // 创建删除请求对象 + DeleteRequest deleteRequest = new DeleteRequest(INDEX_NAME, id); + // 发送请求 + client.delete(deleteRequest, RequestOptions.DEFAULT); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public Result> search(ArticleRequest articleRequest) { + try { + // 总记录 + long total = 0; + // 结果集 + ArrayList
list = new ArrayList<>(); + // 构建搜索请求对象 + SearchRequest searchRequest = new SearchRequest(INDEX_NAME); + // 查询条件的载体 + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + // 构建查询条件拼接对象 + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + // 拼接条件 + // 文章标题的搜索 + if (StringUtils.isNotEmpty(articleRequest.getTitle())) { +// MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", articleRequest.getTitle()); +// boolQueryBuilder.must(queryBuilder); + boolQueryBuilder.must(QueryBuilders.matchQuery("title", articleRequest.getTitle())); + } + // 作者 + if (StringUtils.isNotEmpty(articleRequest.getAuthor())) { + boolQueryBuilder.must(QueryBuilders.matchQuery("author", articleRequest.getAuthor())); + } + // 时间区间 + if (articleRequest.getStartTime() != null) { + boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").gte(articleRequest.getStartTime().getTime())); + } + if (articleRequest.getEndTime() != null) { + boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").lte(articleRequest.getEndTime().getTime())); + } + // 把查询条件拼接对象 给 + searchSourceBuilder.query(boolQueryBuilder); + // 分页 + searchSourceBuilder.from((articleRequest.getPageNum() - 1) * articleRequest.getPageSize()); + searchSourceBuilder.size(articleRequest.getPageSize()); + // 排序 + searchSourceBuilder.sort("createTime", SortOrder.DESC); + // 高亮 + HighlightBuilder highlightBuilder = new HighlightBuilder(); + // 设置高亮字段 + highlightBuilder.field("title"); + // 设置标签 + highlightBuilder.preTags(""); + highlightBuilder.postTags(""); + // 将高亮构建器给 查询条件载体 + searchSourceBuilder.highlighter(highlightBuilder); + // 将查询条件的载体给 SearchRequest + searchRequest.source(searchSourceBuilder); + // 发送请求 + SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); + // 处理结果集 + SearchHits hits = searchResponse.getHits(); + // 获取总记录数 + total = hits.getTotalHits().value; + // 获取结果集 + SearchHit[] searchHits = hits.getHits(); + // 遍历 + for (SearchHit searchHit : searchHits) { + // 获取数据 + String sourceAsString = searchHit.getSourceAsString(); + // 范序列化 + Article article = JSONObject.parseObject(sourceAsString, Article.class); + article.setId(searchHit.getId()); + // 替换高亮字段 + Map highlightFields = searchHit.getHighlightFields(); + if (highlightFields != null) { + HighlightField highlightField = highlightFields.get("title"); + if (highlightField != null) { + // 获取高亮碎片 + Text[] fragments = highlightField.getFragments(); + String str = ""; + for (Text fragment : fragments) { + str += fragment; + } + article.setTitle(str); + } + } + // 添加到结果集 + list.add(article); + } + Result> result = PageResult.toResult(total, list); + return result; + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + @Override + public void update(Article article) { + try { + // 创建了修改请求对象 + UpdateRequest updateRequest = new UpdateRequest(INDEX_NAME, article.getId()); + // 设置修改数据 + article.setId(null); + updateRequest.doc(JSONObject.toJSONString(article), XContentType.JSON); + // 发送请求 + client.update(updateRequest, RequestOptions.DEFAULT); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + +} diff --git a/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/biij.md b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/biij.md new file mode 100644 index 0000000..fab7de0 --- /dev/null +++ b/bawei-modules/bawei-es/src/main/java/com/bawei/es/service/impl/biij.md @@ -0,0 +1,148 @@ +1、创建映射 + 【 kibana 创建索引库 规定列类型 】 +PUT /article +{ + "mappings": { + "properties": { + "title": { + "type": "text", + "analyzer": "ik_smart", + "search_analyzer": "ik_smart" + }, + "author": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "address": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_max_word" + }, + "price": { + "type": "double" + }, + "createTime": { + "type": "long" + } + } + } +} + +2、引入 依赖 + + org.elasticsearch.client + elasticsearch-rest-high-level-client + + +3、初始化客户端 + RestHighLevelClient client = new RestHighLevelClient( + RestClient.builder(new HttpHost("47.102.145.201", 9200, "http")) + ); +添加 +try { + 1、 创建索引请求对象 + IndexRequest indexRequest = new IndexRequest("索引名"); + 2、 手动设置id + indexRequest.id(UUID); + 3、 设置数据 + indexRequest.source("JSON数据", XContentType.JSON) + 4、发送请求 + client.index(indexRequest, RequestOptions.DEFAULT); +} catch(Exception ex) { + .... +} + +修改 +1、创建修改请求对象 + UpdateRequest updateRequest = new UpdateRequest("索引名", id); +2、设置数据 + 置空id + updateRequest.doc(JSON数据, XContentType.JSON) +3、发送请求 + client.update(updateRequest, RequestOption.DEFAULT) + +主键查询 +1、创建get请求对象 +GetRequest getRequest = new GetRequest(INDEX_NAME, id); +2、发送请求 +GetResponse getResponse = client.get(getRequest,RequestOption.DEFAULT); +3、处理结果集 +if (getResponse.isExists()) { + String json = getResponses.getSourceAsString(); + // 反序列化 + Article article = JSONObject.parseObject(json, Article.class); + // 设置id + article.setId(getResponse.id()); + return article +} + +删除 +1、 创建删除请求对象 +DeleteRequest deleteRequest = new DeleteRequest(INDEX_NAME, id); +2、发送请求 +client.delete(deleteRequest); + +搜索 +1、 定义总记录数 结果集 +long total = 0; +List
list = new ArrayList<>(); +2、创建搜索请求对象 +SearchRequest searchRequest = new SearchRequest(INDEX_NAME); +3、构建查询条件载体 +SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); +4、构建查询条件拼接对象 +BoolQuery boolQuery = QueryBuilders.boolQuery(); +if (xxxx) { + boolQuery.must(QueryBuilders.matchQuery("title", xxxx)); +} +if (xxx) { + boolQuery.must(QueryBuilders.rangeQuery("createTime").gte(xxx.get..getTime())); +} +5、将查询条件拼接对象 给 查询载体 +searchSourceBuilder.query(boolQuery); +6、分页 +searchSourceBuilder.form((xxxPageNum - 1) * pageSize); +searchSourceBuilder.size(pageSize); +7、排序 +searchSourceBuilder.sort("createTime", SortOrder.DESC) +将查询条件载体给SearchRequest +searchRequest.source(searchSourceBuilder); +8、发送请求 +SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); +9、处理相应的结果 +SearchHits searchHits = searchResponse.getHits(); +10、获取总记录数 +total = searchHits.getTotalHits().value; +11、获取数据 +SearchHit[] hits = searchHits.getHits(); +12、遍历 +for (SearchHit hit: hits) { + String sourceAsString = hit.getSourceAsString(); + // 反序列化 + Article article = JSONObject.parse(sourceAsString, Article.class); + // 设置id的值 + article.setId(hit.getId()); + // 添加结果集 + list.add(article); +} +PageResult.toResult(total, list); + + + + + + + + + + + + + + + + + + diff --git a/bawei-modules/bawei-es/src/main/resources/application.yml b/bawei-modules/bawei-es/src/main/resources/application.yml new file mode 100644 index 0000000..f54f5d0 --- /dev/null +++ b/bawei-modules/bawei-es/src/main/resources/application.yml @@ -0,0 +1,15 @@ +server: + port: 10070 +spring: + application: + name: bawei-es +#eureka注册中心地址 +eureka: + instance: + # 微服务实例IP地址 + instance-id: 127.0.0.1:${server.port} + # 使用IP进行访问 + prefer-ip-address: true + client: + service-url: + defaultZone: http://localhost:10086/eureka/ diff --git a/bawei-modules/bawei-mongo/pom.xml b/bawei-modules/bawei-mongo/pom.xml new file mode 100644 index 0000000..abf5bae --- /dev/null +++ b/bawei-modules/bawei-mongo/pom.xml @@ -0,0 +1,25 @@ + + + + bawei-modules + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-mongo + + + + com.bawei + bawei-common + + + org.springframework.boot + spring-boot-starter-web + + + + diff --git a/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/MongoApplication.java b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/MongoApplication.java new file mode 100644 index 0000000..5a8b4db --- /dev/null +++ b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/MongoApplication.java @@ -0,0 +1,21 @@ +package com.bawei.mongo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * mongo微服务 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@SpringBootApplication +@EnableEurekaClient +public class MongoApplication { + + public static void main(String[] args) { + SpringApplication.run(MongoApplication.class); + } + +} diff --git a/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/annotaion/SysLog.java b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/annotaion/SysLog.java new file mode 100644 index 0000000..606da7f --- /dev/null +++ b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/annotaion/SysLog.java @@ -0,0 +1,19 @@ +package com.bawei.mongo.annotaion; + +import java.lang.annotation.*; + +/** + * 自定义系统日志注解 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SysLog { + + /** + * 功能名称 + * @return + */ + String value() default ""; + +} diff --git a/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/aop/SysOperationLogAop.java b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/aop/SysOperationLogAop.java new file mode 100644 index 0000000..b365842 --- /dev/null +++ b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/aop/SysOperationLogAop.java @@ -0,0 +1,80 @@ +package com.bawei.mongo.aop; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.SysOperationLog; +import com.bawei.mongo.annotaion.SysLog; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.Calendar; +import java.util.Date; + +/** + * AOP记录系统操作日志 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Aspect +@Component +public class SysOperationLogAop { + + @Autowired + private HttpServletRequest request; + + @Autowired + private MongoTemplate mongoTemplate; + + /** + * 环绕通知 + */ + @Around("@annotation(sysLog)") + public Object doOperationLog(ProceedingJoinPoint pjp, SysLog sysLog) { + // 构建系统操作日志对象 + SysOperationLog sysOperationLog = new SysOperationLog(); + // 功能名称 + sysOperationLog.setFunctionName(sysLog.value()); + // 请求URL + sysOperationLog.setRequestURI(request.getRequestURI()); + // 请求方式 + sysOperationLog.setMethodName(request.getMethod()); + // 类名 + String clazzName = pjp.getTarget().getClass().getName(); + sysOperationLog.setClazzName(clazzName); + // 方法名称 + String methodName = pjp.getSignature().getName(); + sysOperationLog.setMethodName(methodName); + // 执行时间 + Calendar instance = Calendar.getInstance(); + instance.setTime(new Date()); + instance.add(Calendar.HOUR_OF_DAY, 8); + sysOperationLog.setCreateTime(instance.getTime()); + Object result = null; + try { + long s = System.currentTimeMillis(); + // 手动执行目标方法 + result = pjp.proceed(); + // 执行时长 + sysOperationLog.setRunTime(System.currentTimeMillis() - s); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + // 获取参数 + Object[] args = pjp.getArgs(); + if (args.length > 0) { + sysOperationLog.setReqJson(JSONObject.toJSONString(args[0])); + } + // 结果 + sysOperationLog.setRespJson(JSONObject.toJSONString(result)); + // 添加操作日志到 mongo + mongoTemplate.insert(sysOperationLog); + return result; + } + + +} diff --git a/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/controller/SysUserController.java b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/controller/SysUserController.java new file mode 100644 index 0000000..20d8b16 --- /dev/null +++ b/bawei-modules/bawei-mongo/src/main/java/com/bawei/mongo/controller/SysUserController.java @@ -0,0 +1,167 @@ +package com.bawei.mongo.controller; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.SysUser; +import com.bawei.common.domain.request.SysUserRequest; +import com.bawei.common.result.PageResult; +import com.bawei.common.result.Result; +import com.bawei.common.utils.StringUtils; +import com.bawei.mongo.annotaion.SysLog; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.swing.*; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.regex.Pattern; + +/** + * 系统用户控制层 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@RestController +@RequestMapping("/sys/user") +@Log4j2 +public class SysUserController { + + @Autowired + private MongoTemplate mongoTemplate; + + @Autowired + private HttpServletRequest request; + + /** + * 添加 + */ + @PostMapping + @SysLog("添加系统用户") + public Result add(@RequestBody SysUser sysUser) { + log.info("功能名称:添加系统用户,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(sysUser)); + // 设置创建时间 + Calendar instance = Calendar.getInstance(); + instance.setTime(new Date()); + instance.add(Calendar.HOUR_OF_DAY, 8); + sysUser.setCreateTime(instance.getTime()); + mongoTemplate.insert(sysUser); + Result result = Result.success(); + log.info("功能名称:添加系统用户,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 修改 + */ + @PutMapping + @SysLog("修改系统用户") + public Result update(@RequestBody SysUser sysUser) { + log.info("功能名称:修改系统用户,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(sysUser)); + // 修改 + // 1 构建修改条件对象 + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(sysUser.getId())); + // 2 设置修改的值 + Update update = new Update(); + if (StringUtils.isNotEmpty(sysUser.getUsername())) { + update.set("username", sysUser.getUsername()); + } + if (StringUtils.isNotEmpty(sysUser.getPassword())) { + update.set("password", sysUser.getPassword()); + } + if (sysUser.getAge() != 0) { + update.set("age", sysUser.getAge()); + } + mongoTemplate.updateFirst(query, update, SysUser.class); + Result result = Result.success(); + log.info("功能名称:修改系统用户,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + + /** + * 主键查询 + */ + @GetMapping("/{id}") + public Result findOneById(@PathVariable("id") String id) { + log.info("功能名称:主键查询,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), id); + SysUser sysUser = mongoTemplate.findById(id, SysUser.class); + Result result = Result.success(sysUser); + log.info("功能名称:主键查询,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 删除 + */ + @DeleteMapping("/{id}") + public Result deleteById(@PathVariable("id") String id) { + log.info("功能名称:主键删除,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), id); + // 构建删除的条件 + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(id)); + mongoTemplate.remove(query, SysUser.class); + Result result = Result.success(); + log.info("功能名称:主键删除,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 列表 + */ + @PostMapping("/list") + @SysLog("查询系统用户列表") + public Result> list(@RequestBody SysUserRequest sysUserRequest) { + log.info("功能名称:查询系统用户列表,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(sysUserRequest)); + // 创建查询条件对象 + Query query = new Query(); + if (StringUtils.isNotEmpty(sysUserRequest.getUsername())) { + // 模糊 正则 + Pattern compile = Pattern.compile("^.*" + sysUserRequest.getUsername() + ".*$"); + query.addCriteria(Criteria.where("username").regex(compile)); + } + if (StringUtils.isNotEmpty(sysUserRequest.getSex())) { + // 精确 + query.addCriteria(Criteria.where("sex").is(sysUserRequest.getSex())); + } + // 时间区间 + if (sysUserRequest.getStartTime() != null && sysUserRequest.getEndTime() != null) { + query.addCriteria(Criteria.where("createTime").gte(sysUserRequest.getStartTime()).lte(sysUserRequest.getEndTime())); + } else if (sysUserRequest.getStartTime() != null) { + query.addCriteria(Criteria.where("createTime").gte(sysUserRequest.getStartTime())); + } else if (sysUserRequest.getEndTime() != null) { + query.addCriteria(Criteria.where("createTime").lte(sysUserRequest.getEndTime())); + } + // 查询 总记录数 + long total = mongoTemplate.count(query, SysUser.class); + // 分页 limit - 每页展示条数 skip - 跳过多少条数据 + query.skip((sysUserRequest.getPageNum() - 1) * sysUserRequest.getPageSize()); + query.limit(sysUserRequest.getPageSize()); + // 排序 + query.with(Sort.by(Sort.Order.desc("createTime"))); + // 分页条件查询 + List userList = mongoTemplate.find(query, SysUser.class); + Result> result = PageResult.toResult(total, userList); + log.info("功能名称:查询系统用户列表,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + +} diff --git a/bawei-modules/bawei-mongo/src/main/resources/application.yml b/bawei-modules/bawei-mongo/src/main/resources/application.yml new file mode 100644 index 0000000..106353d --- /dev/null +++ b/bawei-modules/bawei-mongo/src/main/resources/application.yml @@ -0,0 +1,19 @@ +server: + port: 10069 +spring: + application: + name: bawei-mongo + data: + mongodb: + host: 47.102.145.201 + database: 2006A +#eureka注册中心地址 +eureka: + instance: + # 微服务实例IP地址 + instance-id: 127.0.0.1:${server.port} + # 使用IP进行访问 + prefer-ip-address: true + client: + service-url: + defaultZone: http://localhost:10086/eureka/ diff --git a/bawei-modules/bawei-system/pom.xml b/bawei-modules/bawei-system/pom.xml new file mode 100644 index 0000000..cda2e84 --- /dev/null +++ b/bawei-modules/bawei-system/pom.xml @@ -0,0 +1,47 @@ + + + + bawei-modules + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-system + + + + + com.bawei + bawei-common + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.0 + + + + mysql + mysql-connector-java + runtime + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.1 + + + + + diff --git a/bawei-modules/bawei-system/src/main/java/com/bawei/system/SystemApplication.java b/bawei-modules/bawei-system/src/main/java/com/bawei/system/SystemApplication.java new file mode 100644 index 0000000..bf6ea55 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/java/com/bawei/system/SystemApplication.java @@ -0,0 +1,22 @@ +package com.bawei.system; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * 系统微服务启动类 + * + * @author zhuwenqiang + * @date 2022/11/10 + */ +@SpringBootApplication +@EnableEurekaClient +public class SystemApplication { + + public static void main(String[] args) { + SpringApplication.run(SystemApplication.class); + } + +} diff --git a/bawei-modules/bawei-system/src/main/java/com/bawei/system/controller/UserController.java b/bawei-modules/bawei-system/src/main/java/com/bawei/system/controller/UserController.java new file mode 100644 index 0000000..e552cb6 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/java/com/bawei/system/controller/UserController.java @@ -0,0 +1,73 @@ +package com.bawei.system.controller; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.User; +import com.bawei.common.result.Result; +import com.bawei.system.service.UserService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +/** + * 用户控制层 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@RestController +@RequestMapping("/sys/user") +@Log4j2 +public class UserController { + + @Autowired + private UserService userService; + + @Autowired + private HttpServletRequest request; + + @PostMapping("/login") + public Result login(@RequestBody User user) { + log.info("功能名称:修改系统用户,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(user)); + Result result = userService.login(user); + log.info("功能名称:修改系统用户,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 根据用户名查询用户信息 + * @param username + * @return + */ + @GetMapping("/findUserByUsername/{username}") + public Result findUserByUsername(@PathVariable("username") String username) { + log.info("功能名称:根据用户名查询用户信息,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), username); + User user = userService.findUserByUsername(username); + Result result = Result.success(user); + log.info("功能名称:根据用户名查询用户信息,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + + /** + * 根据手机号查询用户信息 + * @param tel + * @return + */ + @GetMapping("/findByTel/{tel}") + public Result findByTel(@PathVariable("tel") String tel) { + log.info("功能名称:根据手机号查询用户信息,请求路径:【{}】,请求方式:【{}】,请求参数:【{}】", request.getRequestURI(), + request.getMethod(), tel); + User user = userService.findByTel(tel); + Result result = Result.success(user); + log.info("功能名称:根据手机号查询用户信息,请求路径:【{}】,请求方式:【{}】,响应结果:【{}】", request.getRequestURI(), + request.getMethod(), JSONObject.toJSONString(result)); + return result; + } + +} diff --git a/bawei-modules/bawei-system/src/main/java/com/bawei/system/mapper/UserMapper.java b/bawei-modules/bawei-system/src/main/java/com/bawei/system/mapper/UserMapper.java new file mode 100644 index 0000000..13252c9 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/java/com/bawei/system/mapper/UserMapper.java @@ -0,0 +1,23 @@ +package com.bawei.system.mapper; + +import com.bawei.common.domain.User; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserMapper { + + /** + * 根据用户名查询用户信息 + * @param username + * @return + */ + User findOneByUsername(String username); + + /** + * 根据手机号查询用户信息 + * @param tel + * @return + */ + User findByTel(String tel); + +} diff --git a/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/UserService.java b/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/UserService.java new file mode 100644 index 0000000..2888a28 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/UserService.java @@ -0,0 +1,27 @@ +package com.bawei.system.service; + +import com.bawei.common.domain.User; +import com.bawei.common.result.Result; + +public interface UserService { + /** + * 登录 + * @param user + * @return + */ + Result login(User user); + + /** + * 根据用户名查询用户信息 + * @param username + * @return + */ + User findUserByUsername(String username); + + /** + * 根据手机号查询用户信息 + * @param tel + * @return + */ + User findByTel(String tel); +} diff --git a/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/impl/UserServiceImpl.java b/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..21998e4 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/java/com/bawei/system/service/impl/UserServiceImpl.java @@ -0,0 +1,78 @@ +package com.bawei.system.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.bawei.common.domain.LoginLog; +import com.bawei.common.domain.User; +import com.bawei.common.result.Result; +import com.bawei.common.utils.StringUtils; +import com.bawei.system.mapper.UserMapper; +import com.bawei.system.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Service; + +import java.util.Calendar; +import java.util.Date; + +/** + * 用户业务层 + * + * @author zhuwenqiang + * @date 2022/11/11 + */ +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Autowired + private MongoTemplate mongoTemplate; + + @Override + public Result login(User user) { + // 构建日志对象 + LoginLog loginLog = new LoginLog(); + loginLog.setUsername(user.getUsername()); + Calendar instance = Calendar.getInstance(); + instance.setTime(new Date()); + instance.add(Calendar.HOUR_OF_DAY, 8); + loginLog.setLoginTime(instance.getTime()); + // 1: 非空验证 + if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) { + Result result = Result.error("用户名或者密码不能为空!"); + loginLog.setResult(JSONObject.toJSONString(result)); + mongoTemplate.insert(loginLog); + return result; + } + // 1: 根据用户名查询用户信息 + User loginUser = userMapper.findOneByUsername(user.getUsername()); + if (loginUser == null) { + Result result = Result.error("用户名不存在!"); + loginLog.setResult(JSONObject.toJSONString(result)); + mongoTemplate.insert(loginLog); + return result; + } + // 2: 密码判断 + if (!loginUser.getPassword().equals(user.getPassword())) { + Result result = Result.error("密码错误!"); + loginLog.setResult(JSONObject.toJSONString(result)); + mongoTemplate.insert(loginLog); + return result; + } + Result result = Result.success("登录成功!"); + loginLog.setResult(JSONObject.toJSONString(result)); + mongoTemplate.insert(loginLog); + return result; + } + + @Override + public User findUserByUsername(String username) { + return userMapper.findOneByUsername(username); + } + + @Override + public User findByTel(String tel) { + return userMapper.findByTel(tel); + } +} diff --git a/bawei-modules/bawei-system/src/main/resources/application.yml b/bawei-modules/bawei-system/src/main/resources/application.yml new file mode 100644 index 0000000..0777249 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/resources/application.yml @@ -0,0 +1,43 @@ +server: + port: 10068 +spring: + application: + name: bawei-system + datasource: + url: jdbc:mysql://127.0.0.1:3306/1019?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + rabbitmq: + listener: + #如果手动声明listener类型,可在config声明时设置 + direct: + acknowledge-mode: MANUAL + simple: + acknowledge-mode: MANUAL + host: 127.0.0.1 + data: + mongodb: + host: 47.102.145.201 + database: 2006A +#eureka注册中心地址 +eureka: + instance: + # 微服务实例IP地址 + instance-id: 127.0.0.1:${server.port} + # 使用IP进行访问 + prefer-ip-address: true + client: + service-url: + defaultZone: http://localhost:10086/eureka/ + +# type-aliases-package批量设置别名作用:就是在mapper.xml文件中直接写类名,不配置就需要写类的全路径名 +mybatis: + type-aliases-package: com.bawei.common.domain + mapper-locations: classpath:mapper/*.xml + configuration: + map-underscore-to-camel-case: true +# 将mapper接口所在包的日志级别改成debug,可以在控制台打印sql +logging: + level: + com.bawei.**: debug diff --git a/bawei-modules/bawei-system/src/main/resources/mapper/UserMapper.xml b/bawei-modules/bawei-system/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..25abf03 --- /dev/null +++ b/bawei-modules/bawei-system/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/bawei-modules/pom.xml b/bawei-modules/pom.xml new file mode 100644 index 0000000..6eda628 --- /dev/null +++ b/bawei-modules/pom.xml @@ -0,0 +1,21 @@ + + + + bawei-cloud + com.bawei + 1.0-SNAPSHOT + + 4.0.0 + + bawei-modules + pom + + bawei-system + bawei-mongo + bawei-es + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9e34a5a --- /dev/null +++ b/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + com.bawei + bawei-cloud + pom + 1.0-SNAPSHOT + + bawei-eureka + bawei-common + bawei-gateway + bawei-auth + bawei-modules + + + + + + + + com.bawei + bawei-common + 1.0-SNAPSHOT + + + + org.springframework.cloud + spring-cloud-dependencies + 2021.0.0 + pom + import + + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + 2021.1 + pom + import + + + + + org.springframework.boot + spring-boot-dependencies + 2.6.2 + pom + import + + + + + diff --git a/笔记.md b/笔记.md new file mode 100644 index 0000000..33fe949 --- /dev/null +++ b/笔记.md @@ -0,0 +1,61 @@ + +1、鉴权登录 JWT -> token -> 前端 -> http请求头中携带token -> 接口 -> 拦截请求 -> 验证 token +登录方法: +a、 非空验证【数据的合法性】 +b、 验证用户是否存在 【鉴权微服务不涉及数据库】 -> 远程调用 -> 系统微服务 +c、 比对密码 +d、 登录成功 -> 生成 JWT token + (1)、 用户的id + (2)、 生成 userKey -> 相当于redis的key +e、 用户信息存入redis 中 可以 是 前缀 + userKey +f、 返回 信息 【JwtResponse】 + token + expireTime + + +sentinel限流: +(1) 引入依赖 + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + +(2) 复制限流配置类 + initGatewayRules: 规定限流参数 + initCustomizedApis : 规定接口 + 方式: + (1) 对整个服务进行限流 + (2) 针对于接口进行限流 √ + + +短信验证码登录: 本月使用 阿里大鱼 +1、 发送验证码的接口 + a、入参 手机号 + b、出参 提示发送成功 + +2、 短信验证码登录接口 + a、入参: 短信验证码 以及手机号 + b、出参: token + + +1、引入sentinel的依赖 【 远程调用方 】 +2、开启熔断 +feign.sentinel.enable=true +3、解决循环依赖报错 +spring.main.allow-circular-references=true +4、代码 + hystrix +注意: 处理熔断情况 + 核心区分 熔断 还是 正常服务调通 + + + + + + + + + + + + +