From bf50a915d7dac19b67703df70043b6100e88a7a2 Mon Sep 17 00:00:00 2001
From: zhangsan <646228430@qq.com>
Date: Sat, 24 May 2025 22:24:52 +0800
Subject: [PATCH] =?UTF-8?q?5.24=20=E7=BD=91=E5=85=B3=20=E7=99=BB=E5=BD=95?=
=?UTF-8?q?=E6=A0=A1=E9=AA=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
cart-service/pom.xml | 15 ++++
.../com/hmall/cart/config/CartProperties.java | 12 +++
.../cart/service/impl/CartServiceImpl.java | 9 +-
.../src/main/resources/application.yaml | 47 ++--------
.../src/main/resources/bootstrap.yaml | 14 +++
hm-api/pom.xml | 6 +-
.../hmall/api/config/DefaultFeignConfig.java | 25 ++++++
.../com/hmall/common/config/MvcConfig.java | 19 ++++
.../interceptors/UserInfoInterceptor.java | 29 +++++++
.../main/resources/META-INF/spring.factories | 3 +-
hm-gateway/pom.xml | 56 ++++++++++++
.../com/hmall/gateway/GateWayApplication.java | 11 +++
.../hmall/gateway/config/AuthProperties.java | 15 ++++
.../hmall/gateway/config/JwtProperties.java | 17 ++++
.../hmall/gateway/config/SecurityConfig.java | 33 +++++++
.../gateway/filters/AuthGlobalFilter.java | 79 +++++++++++++++++
.../hmall/gateway/filters/MyGlobalFilter.java | 29 +++++++
.../java/com/hmall/gateway/utils/JwtTool.java | 82 ++++++++++++++++++
hm-gateway/src/main/resources/application.yml | 42 +++++++++
hm-gateway/src/main/resources/hmall.jks | Bin 0 -> 2711 bytes
.../src/main/resources/application.yaml | 2 +-
.../item/controller/SearchController.java | 40 +++++++++
.../com/hmall/item/mapper/ItemMapper.java | 2 +-
.../item/service/impl/ItemServiceImpl.java | 24 ++++-
.../src/main/resources/application.yaml | 12 ++-
.../java/com/hmall/pay/PayApplication.java | 3 +-
.../src/main/resources/application.yaml | 12 ++-
pom.xml | 3 +-
.../com/hmall/trade/TradeApplication.java | 6 +-
.../trade/service/impl/OrderServiceImpl.java | 1 +
.../src/main/resources/application.yaml | 12 ++-
.../src/main/resources/application.yaml | 12 ++-
32 files changed, 616 insertions(+), 56 deletions(-)
create mode 100644 cart-service/src/main/java/com/hmall/cart/config/CartProperties.java
create mode 100644 cart-service/src/main/resources/bootstrap.yaml
create mode 100644 hm-api/src/main/java/com/hmall/api/config/DefaultFeignConfig.java
create mode 100644 hm-common/src/main/java/com/hmall/common/config/MvcConfig.java
create mode 100644 hm-common/src/main/java/com/hmall/common/interceptors/UserInfoInterceptor.java
create mode 100644 hm-gateway/pom.xml
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/GateWayApplication.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/config/AuthProperties.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/config/JwtProperties.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/config/SecurityConfig.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/filters/AuthGlobalFilter.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/filters/MyGlobalFilter.java
create mode 100644 hm-gateway/src/main/java/com/hmall/gateway/utils/JwtTool.java
create mode 100644 hm-gateway/src/main/resources/application.yml
create mode 100644 hm-gateway/src/main/resources/hmall.jks
create mode 100644 item-service/src/main/java/com/hmall/item/controller/SearchController.java
diff --git a/cart-service/pom.xml b/cart-service/pom.xml
index 4a58ef4..23eb9e1 100644
--- a/cart-service/pom.xml
+++ b/cart-service/pom.xml
@@ -50,6 +50,21 @@
hm-api
1.0.0
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bootstrap
+
${project.artifactId}
diff --git a/cart-service/src/main/java/com/hmall/cart/config/CartProperties.java b/cart-service/src/main/java/com/hmall/cart/config/CartProperties.java
new file mode 100644
index 0000000..1f8386b
--- /dev/null
+++ b/cart-service/src/main/java/com/hmall/cart/config/CartProperties.java
@@ -0,0 +1,12 @@
+package com.hmall.cart.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "hm.cart")
+public class CartProperties {
+ private Integer maxAmount;
+}
diff --git a/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java b/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java
index 4aeefad..8db022f 100644
--- a/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java
+++ b/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
+import com.hmall.cart.config.CartProperties;
import com.hmall.cart.domain.dto.CartFormDTO;
import com.hmall.cart.domain.po.Cart;
import com.hmall.cart.domain.vo.CartVO;
@@ -38,7 +39,7 @@ import java.util.stream.Collectors;
public class CartServiceImpl extends ServiceImpl implements ICartService {
private final ItemClient itemClient; //@RequiredArgsConstructor会为final字段生成构造器
-
+ private final CartProperties cartProperties;
@Override
public void addItem2Cart(CartFormDTO cartFormDTO) {
@@ -66,7 +67,7 @@ public class CartServiceImpl extends ServiceImpl implements IC
@Override
public List queryMyCarts() {
// 1.查询我的购物车列表
- List carts = lambdaQuery().eq(Cart::getUserId,1L /*UserContext.getUser()*/).list();
+ List carts = lambdaQuery().eq(Cart::getUserId,UserContext.getUser()).list();
if (CollUtils.isEmpty(carts)) {
return CollUtils.emptyList();
}
@@ -118,9 +119,9 @@ public class CartServiceImpl extends ServiceImpl implements IC
long count = lambdaQuery()
.eq(Cart::getUserId, userId)
.count(); // ← 这里返回 long
- if (count >= 10) {
+ if (count >= cartProperties.getMaxAmount()) {
throw new BizIllegalException(
- StrUtil.format("用户购物车课程不能超过{}", 10)
+ StrUtil.format("用户购物车课程不能超过{}", cartProperties.getMaxAmount())
);
}
}
diff --git a/cart-service/src/main/resources/application.yaml b/cart-service/src/main/resources/application.yaml
index 3aae4ff..521993a 100644
--- a/cart-service/src/main/resources/application.yaml
+++ b/cart-service/src/main/resources/application.yaml
@@ -1,47 +1,14 @@
server:
port: 8082
-spring:
- application:
- name: cart-service
- profiles:
- active: local
- datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hm-cart?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
- driver-class-name: com.mysql.cj.jdbc.Driver
- username: root
- password: ${hm.db.pw}
-mybatis-plus:
- configuration:
- default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
- global-config:
- db-config:
- update-strategy: not_null
- id-type: auto
-logging:
- level:
- com.hmall: debug
- pattern:
- dateformat: HH:mm:ss:SSS
- file:
- path: "logs/${spring.application.name}"
-knife4j:
- enable: true
- openapi:
- title: 黑马商城购物车接口文档
- description: "黑马商城购物车接口文档"
- email: zhangsan@itcast.cn
- concat: 宇哥
- url: https://www.itcast.cn
- version: v1.0.0
- group:
- default:
- group-name: default
- api-rule: package
- api-rule-resources:
- - com.hmall.cart.controller
-
feign:
httpclient:
enabled: true # 使用 Apache HttpClient(默认关闭)
+hm:
+ swagger:
+ title: 购物车服务接口文档
+ package: com.hmall.cart.controller
+ db:
+ database: hm-cart
+
# keytool -genkeypair -alias hmall -keyalg RSA -keypass hmall123 -keystore hmall.jks -storepass hmall123
\ No newline at end of file
diff --git a/cart-service/src/main/resources/bootstrap.yaml b/cart-service/src/main/resources/bootstrap.yaml
new file mode 100644
index 0000000..a6008d1
--- /dev/null
+++ b/cart-service/src/main/resources/bootstrap.yaml
@@ -0,0 +1,14 @@
+spring:
+ application:
+ name: cart-service # 服务名称
+ profiles:
+ active: local
+ cloud:
+ nacos:
+ server-addr: 124.71.159.195:8848 # nacos地址
+ config:
+ file-extension: yaml # 文件后缀名
+ shared-configs: # 共享配置
+ - dataId: shared_jdbc.yaml # 共享mybatis配置
+ - dataId: shared_log.yaml # 共享日志配置
+ - dataId: shared_swagger.yaml # 共享日志配置
\ No newline at end of file
diff --git a/hm-api/pom.xml b/hm-api/pom.xml
index 556f683..e99ee32 100644
--- a/hm-api/pom.xml
+++ b/hm-api/pom.xml
@@ -11,7 +11,11 @@
hm-api
-
+
+ com.heima
+ hm-common
+ 1.0.0
+
org.springframework.cloud
diff --git a/hm-api/src/main/java/com/hmall/api/config/DefaultFeignConfig.java b/hm-api/src/main/java/com/hmall/api/config/DefaultFeignConfig.java
new file mode 100644
index 0000000..d575a6b
--- /dev/null
+++ b/hm-api/src/main/java/com/hmall/api/config/DefaultFeignConfig.java
@@ -0,0 +1,25 @@
+package com.hmall.api.config;
+
+import com.hmall.common.utils.UserContext;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.context.annotation.Bean;
+
+public class DefaultFeignConfig {
+ @Bean
+ public RequestInterceptor userInfoRequestInterceptor(){
+ return new RequestInterceptor() {
+ @Override
+ public void apply(RequestTemplate template) {
+ // 获取登录用户
+ Long userId = UserContext.getUser();
+ if(userId == null) {
+ // 如果为空则直接跳过
+ return;
+ }
+ // 如果不为空则放入请求头中,传递给下游微服务
+ template.header("user-info", userId.toString());
+ }
+ };
+ }
+}
diff --git a/hm-common/src/main/java/com/hmall/common/config/MvcConfig.java b/hm-common/src/main/java/com/hmall/common/config/MvcConfig.java
new file mode 100644
index 0000000..ca7200c
--- /dev/null
+++ b/hm-common/src/main/java/com/hmall/common/config/MvcConfig.java
@@ -0,0 +1,19 @@
+package com.hmall.common.config;
+
+import com.hmall.common.interceptors.UserInfoInterceptor;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Configuration;
+
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@ConditionalOnClass(DispatcherServlet.class)
+public class MvcConfig implements WebMvcConfigurer {
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new UserInfoInterceptor());
+ }
+}
diff --git a/hm-common/src/main/java/com/hmall/common/interceptors/UserInfoInterceptor.java b/hm-common/src/main/java/com/hmall/common/interceptors/UserInfoInterceptor.java
new file mode 100644
index 0000000..10291ed
--- /dev/null
+++ b/hm-common/src/main/java/com/hmall/common/interceptors/UserInfoInterceptor.java
@@ -0,0 +1,29 @@
+package com.hmall.common.interceptors;
+
+import cn.hutool.core.util.StrUtil;
+import com.hmall.common.utils.UserContext;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class UserInfoInterceptor implements HandlerInterceptor {
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ // 1.获取请求头中的用户信息
+ String userInfo = request.getHeader("user-info");
+ // 2.判断是否为空
+ if (StrUtil.isNotBlank(userInfo)) {
+ // 不为空,保存到ThreadLocal
+ UserContext.setUser(Long.valueOf(userInfo));
+ }
+ // 3.放行
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ // 移除用户
+ UserContext.removeUser();
+ }
+}
diff --git a/hm-common/src/main/resources/META-INF/spring.factories b/hm-common/src/main/resources/META-INF/spring.factories
index 46f5f33..ea50f47 100644
--- a/hm-common/src/main/resources/META-INF/spring.factories
+++ b/hm-common/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hmall.common.config.MyBatisConfig,\
- com.hmall.common.config.JsonConfig
\ No newline at end of file
+ com.hmall.common.config.JsonConfig,\
+ com.hmall.common.config.MvcConfig
\ No newline at end of file
diff --git a/hm-gateway/pom.xml b/hm-gateway/pom.xml
new file mode 100644
index 0000000..f4b3232
--- /dev/null
+++ b/hm-gateway/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ hmall
+ com.heima
+ 1.0.0
+
+ 4.0.0
+
+ hm-gateway
+
+
+ 17
+ 17
+
+
+
+
+ com.heima
+ hm-common
+ 1.0.0
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/GateWayApplication.java b/hm-gateway/src/main/java/com/hmall/gateway/GateWayApplication.java
new file mode 100644
index 0000000..ef661cd
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/GateWayApplication.java
@@ -0,0 +1,11 @@
+package com.hmall.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class GateWayApplication {
+ public static void main(String[] args){
+ SpringApplication.run(GateWayApplication.class,args);
+ }
+}
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/config/AuthProperties.java b/hm-gateway/src/main/java/com/hmall/gateway/config/AuthProperties.java
new file mode 100644
index 0000000..433e55f
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/config/AuthProperties.java
@@ -0,0 +1,15 @@
+package com.hmall.gateway.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "hm.auth")
+public class AuthProperties {
+ private List includePaths;
+ private List excludePaths;
+}
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/config/JwtProperties.java b/hm-gateway/src/main/java/com/hmall/gateway/config/JwtProperties.java
new file mode 100644
index 0000000..d545647
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/config/JwtProperties.java
@@ -0,0 +1,17 @@
+package com.hmall.gateway.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+
+@Data
+@ConfigurationProperties(prefix = "hm.jwt")
+public class JwtProperties {
+ private Resource location;
+ private String password;
+ private String alias;
+ private Duration tokenTTL = Duration.ofMinutes(10);
+}
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/config/SecurityConfig.java b/hm-gateway/src/main/java/com/hmall/gateway/config/SecurityConfig.java
new file mode 100644
index 0000000..0048618
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/config/SecurityConfig.java
@@ -0,0 +1,33 @@
+package com.hmall.gateway.config;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
+
+import java.security.KeyPair;
+
+@Configuration
+@EnableConfigurationProperties(JwtProperties.class)
+public class SecurityConfig {
+
+ @Bean
+ public PasswordEncoder passwordEncoder(){
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ public KeyPair keyPair(JwtProperties properties){
+ // 获取秘钥工厂
+ KeyStoreKeyFactory keyStoreKeyFactory =
+ new KeyStoreKeyFactory(
+ properties.getLocation(),
+ properties.getPassword().toCharArray());
+ //读取钥匙对
+ return keyStoreKeyFactory.getKeyPair(
+ properties.getAlias(),
+ properties.getPassword().toCharArray());
+ }
+}
\ No newline at end of file
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/filters/AuthGlobalFilter.java b/hm-gateway/src/main/java/com/hmall/gateway/filters/AuthGlobalFilter.java
new file mode 100644
index 0000000..70476d9
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/filters/AuthGlobalFilter.java
@@ -0,0 +1,79 @@
+package com.hmall.gateway.filters;
+import com.hmall.common.exception.UnauthorizedException;
+import com.hmall.common.utils.CollUtils;
+import com.hmall.gateway.config.AuthProperties;
+import com.hmall.gateway.utils.JwtTool;
+import lombok.RequiredArgsConstructor;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+@Component
+@RequiredArgsConstructor
+@EnableConfigurationProperties(AuthProperties.class)
+public class AuthGlobalFilter implements GlobalFilter, Ordered {
+
+ private final JwtTool jwtTool;
+
+ private final AuthProperties authProperties;
+
+ private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ // 1.获取Request
+ ServerHttpRequest request = exchange.getRequest();
+ // 2.判断是否不需要拦截
+ if(isExclude(request.getPath().toString())){
+ // 无需拦截,直接放行
+ return chain.filter(exchange);
+ }
+ // 3.获取请求头中的token
+ String token = null;
+ List headers = request.getHeaders().get("authorization");
+ if (!CollUtils.isEmpty(headers)) {
+ token = headers.get(0);
+ }
+ // 4.校验并解析token
+ Long userId = null;
+ try {
+ userId = jwtTool.parseToken(token);
+ } catch (UnauthorizedException e) {
+ // 如果无效,拦截
+ ServerHttpResponse response = exchange.getResponse();
+ response.setRawStatusCode(401);
+ return response.setComplete();
+ }
+
+ // 5.如果有效,传递用户信息
+ String userInfo = userId.toString();
+ ServerWebExchange modifiedExchange = exchange.mutate()
+ .request(builder -> builder.header("user-info", userInfo))
+ .build();
+ // 6.放行
+ return chain.filter(modifiedExchange);
+ }
+
+ private boolean isExclude(String antPath) {
+ for (String pathPattern : authProperties.getExcludePaths()) {
+ if(antPathMatcher.match(pathPattern, antPath)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+}
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/filters/MyGlobalFilter.java b/hm-gateway/src/main/java/com/hmall/gateway/filters/MyGlobalFilter.java
new file mode 100644
index 0000000..5faaf04
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/filters/MyGlobalFilter.java
@@ -0,0 +1,29 @@
+package com.hmall.gateway.filters;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+@Component
+public class MyGlobalFilter implements GlobalFilter, Ordered {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ // TODO 模拟登录校验逻辑
+ ServerHttpRequest request = exchange.getRequest();
+ HttpHeaders headers = request.getHeaders();
+ System.out.println("headers = " + headers);
+ // 放行
+ return chain.filter(exchange);
+ }
+
+ @Override
+ public int getOrder() {
+ return 0; // 这里图中缺少order值,暂设为0,可根据实际需求调整
+ }
+}
\ No newline at end of file
diff --git a/hm-gateway/src/main/java/com/hmall/gateway/utils/JwtTool.java b/hm-gateway/src/main/java/com/hmall/gateway/utils/JwtTool.java
new file mode 100644
index 0000000..3717612
--- /dev/null
+++ b/hm-gateway/src/main/java/com/hmall/gateway/utils/JwtTool.java
@@ -0,0 +1,82 @@
+package com.hmall.gateway.utils;
+
+import cn.hutool.core.exceptions.ValidateException;
+import cn.hutool.jwt.JWT;
+import cn.hutool.jwt.JWTValidator;
+import cn.hutool.jwt.signers.JWTSigner;
+import cn.hutool.jwt.signers.JWTSignerUtil;
+import com.hmall.common.exception.UnauthorizedException;
+import org.springframework.stereotype.Component;
+
+import java.security.KeyPair;
+import java.time.Duration;
+import java.util.Date;
+
+@Component
+public class JwtTool {
+ private final JWTSigner jwtSigner;
+
+ public JwtTool(KeyPair keyPair) {
+ this.jwtSigner = JWTSignerUtil.createSigner("rs256", keyPair);
+ }
+
+ /**
+ * 创建 access-token
+ *
+ * @param userId 用户信息
+ * @return access-token
+ */
+ public String createToken(Long userId, Duration ttl) {
+ // 1.生成jws
+ return JWT.create()
+ .setPayload("user", userId)
+ .setExpiresAt(new Date(System.currentTimeMillis() + ttl.toMillis()))
+ .setSigner(jwtSigner)
+ .sign();
+ }
+
+ /**
+ * 解析token
+ *
+ * @param token token
+ * @return 解析刷新token得到的用户信息
+ */
+ public Long parseToken(String token) {
+ // 1.校验token是否为空
+ if (token == null) {
+ throw new UnauthorizedException("未登录");
+ }
+ // 2.校验并解析jwt
+ JWT jwt;
+ try {
+ jwt = JWT.of(token).setSigner(jwtSigner);
+ } catch (Exception e) {
+ throw new UnauthorizedException("无效的token", e);
+ }
+ // 2.校验jwt是否有效
+ if (!jwt.verify()) {
+ // 验证失败
+ throw new UnauthorizedException("无效的token");
+ }
+ // 3.校验是否过期
+ try {
+ JWTValidator.of(jwt).validateDate();
+ } catch (ValidateException e) {
+ throw new UnauthorizedException("token已经过期");
+ }
+ // 4.数据格式校验
+ Object userPayload = jwt.getPayload("user");
+ if (userPayload == null) {
+ // 数据为空
+ throw new UnauthorizedException("无效的token");
+ }
+
+ // 5.数据解析
+ try {
+ return Long.valueOf(userPayload.toString());
+ } catch (RuntimeException e) {
+ // 数据格式有误
+ throw new UnauthorizedException("无效的token");
+ }
+ }
+}
\ No newline at end of file
diff --git a/hm-gateway/src/main/resources/application.yml b/hm-gateway/src/main/resources/application.yml
new file mode 100644
index 0000000..fbc0d80
--- /dev/null
+++ b/hm-gateway/src/main/resources/application.yml
@@ -0,0 +1,42 @@
+server:
+ port: 8080
+spring:
+ application:
+ name: gateway
+ cloud:
+ nacos:
+ server-addr: 124.71.159.195:8848
+ gateway:
+ routes:
+ - id: item # 路由规则id,自定义,唯一
+ uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表
+ predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务
+ - Path=/items/**,/search/** # 这里是以请求路径作为判断规则
+ - id: cart
+ uri: lb://cart-service
+ predicates:
+ - Path=/carts/**
+ - id: user
+ uri: lb://user-service
+ predicates:
+ - Path=/users/**,/addresses/**
+ - id: trade
+ uri: lb://trade-service
+ predicates:
+ - Path=/orders/**
+ - id: pay
+ uri: lb://pay-service
+ predicates:
+ - Path=/pay-orders/**
+hm:
+ jwt:
+ location: classpath:hmall.jks
+ alias: hmall
+ password: hmall123
+ tokenTTL: 30m
+ auth:
+ excludePaths:
+ - /search/**
+ - /users/login
+ - /items/**
+ - /hi
diff --git a/hm-gateway/src/main/resources/hmall.jks b/hm-gateway/src/main/resources/hmall.jks
new file mode 100644
index 0000000000000000000000000000000000000000..a34bd33d09d4c33b13769213e6c07c2267cce162
GIT binary patch
literal 2711
zcma)+cQhM}8pe}ILhLW9P(T2^2!cTX2w^D9HO>_1K?erP
zf!Uc1xM1i=8tQB9Awe=@l?En&N0I{yr?ks8q1gUD&77!=1Il1w;7shw{+Js>*%oqg
zSaod~_JhF?7#x(IlDw`8d&6Rn{fmebw+~9^WwB($~{W{}M
zpGa6hl2804zbZ5mHOUf*nNvZHABX#t3QXF9<9Y*-0gO2do~=SNqIbGdb$}Y)1C8
zXyuL#^haq!isIQ=PhfX)K0*-oToJxIUrTVp-UBAmhGS%wbeA9{FxRv$+Zlf#2D|
zMJPQu*9*5PmUNM8e3M^%bkgcZQgd9U7qYXEdv5k)!7bFtdeIZcmx8??ATNnJa!L8_
zq>D3x$L$92p-sjtn0T9$LkF<>#xIN+!}2799QHL><8SfuG*Vo*Uw0dM+3D^J7RLGV
zEVdc_`3EY^N@%yzh@V8a?vqzkNa^f(>Fhkp2F#sE#o4g+33mG7RHuthC*=ki2k@VP
zI9Y{g%iz(_dUpMWE(~zYwi5-SopTQ(Ug-h8Geoe5vJhjvCQkdnw
zhQY@{A*x+HudUCz?t2zh-F9Nt<_>~A={_Evb9{1qtE$8XZX$z%b&tA-cWUfLL^$F<
zefSyUbsPieS>?MB9k2E?_h9O53vuM+98wx#CMb4&_SN0k>&3Lt{Lex1>n3vpS=hBt
z;iee+B4-058Pj9_=_&CHIYQDE)hYAVr~(YPeL#D*-u_K!`&rhW^-fqAA~B#et&y%3
zh+U42Ee#L}<_2DgXbsoYfSn<~&)
zPAuX;y7D?am}5j@gLPS|lf7r2oX&Jm`F8_#NGUx7a8Z6_;Ih-@@Xf8)8$_Eb-a{ug
zlbMlzTku5T;)B%kvQjA)ZX7T2=J+(PT^&!{>oQ-*iKjhp_mL-Cci_Z1Yt}IC;&Je_
zQGe!`FXu3mC>QG8<7v4rf<=))YP7EDZVauv!1B1U0;ilS8DDMQ92(7W2VVFi|-SfYKtfYRN9Wp1Gfyy=9BhjP7J
zzHpH6rn84Xd%1e)&Tu9}h>-AwXAVsAvgz;JpzhBV6W0wybUaF|-M7lF27g}Nz{RA`
ztLPyFe%B?8TZLJK5#R;z1z-R;01hGkkHn+G4d%R#_4N=_(a=&;)lySYQB_mdKoG$A
z-%s>VG68(|7xDuE0l${#KML@Fm2{gBo?s0-dQ(_!0nRM#r?rzVyk!q_YTy!Iq
z{qe%~o7z^B=4b0t!lLM1lQ2s9ovH!hdW`xdR0AH3!M^$PX5{1kh?cCrXVaQf8SpkV(G
z;$ih>F6ZPoId*Fmz4pd(rMG`9uUAV!Hdzbx@?)5FpUAJEG<+#kt-QV)M{~-tL3(OK
z0k@oWin}_43UlNem~W)VERM?YixKY`*FVa@eCx2|@V3pXS*QH1U|r$0l~ms59{OoG
z_hzw5*z40b8fI;mp40d?IIhcW8iV`6Bs1dhbW}ZnAm(h^3#7
z{sbPTc-9oy=)oB&kYL}$eJt|$uvgGAmn6;fv0mMu_o_LSu~c#zr0eexhge@A(MZnK
zYjzqltUoI`T5i65c`#ohqZaX`v<=%XnfyIsl@ZrLQUBt|kMe=)ugtQ$C*smS9>#`f
z^ABuErq!HX>EdW!&%%x|ZMJ)@jGZc$XiEd9bRAz&A>@$L
zxlxwP!)E&Vf?@t{vvo#Yc!b2kxb7O)SF4M+(=$+N17nGYwW{;rxWE~fJE%W7)cEIV
zGG)dUD;!+3mKSXCM@V7%wxYB}PU%@s7W8{KrzR1hhY&}=pb&XhI*=d)0Oo$!({e_C
uQpH62W+}}XVj|zYG4BNCPS~2Erd)e6g7$a0VPy&!oz{sz1 search(ItemPageQuery query) {
+ // 分页查询
+ Page- result = itemService.lambdaQuery()
+ .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
+ .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
+ .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
+ .eq(Item::getStatus, 1)
+ .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
+ .page(query.toMpPage("update_time", false));
+ // 封装并返回
+ return PageDTO.of(result, ItemDTO.class);
+ }
+}
diff --git a/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java b/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java
index 179ff7a..f1b6a2d 100644
--- a/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java
+++ b/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java
@@ -2,8 +2,8 @@ package com.hmall.item.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.item.domain.po.Item;
-import com.hmall.item.domain.dto.OrderDetailDTO;
import org.apache.ibatis.annotations.Update;
/**
diff --git a/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java b/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java
index 739bd77..e261e18 100644
--- a/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java
+++ b/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java
@@ -13,6 +13,7 @@ import com.hmall.item.service.IItemService;
import org.springframework.stereotype.Service;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -41,6 +42,27 @@ public class ItemServiceImpl extends ServiceImpl implements II
@Override
public List queryItemByIds(Collection ids) {
- return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
+ // 1. 防空:参数为 null 或 空集合,直接返回空列表
+ if (ids == null || ids.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List
- items;
+ try {
+ // 2. 真正去查
+ items = listByIds(ids);
+ } catch (Exception e) {
+ // 3. 捕获底层任何异常,记录并返回空列表
+ System.out.println("no");
+ return Collections.emptyList();
+ }
+
+ // 4. 再防空:数据库里一个都没查到,也返回空
+ if (items == null || items.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // 5. 正常转换
+ return BeanUtils.copyList(items, ItemDTO.class);
}
}
diff --git a/item-service/src/main/resources/application.yaml b/item-service/src/main/resources/application.yaml
index d3de1a3..1addd78 100644
--- a/item-service/src/main/resources/application.yaml
+++ b/item-service/src/main/resources/application.yaml
@@ -10,10 +10,20 @@ spring:
profiles:
active: local
datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hm-item?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://${hm.db.host}:3307/hm-item?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${hm.db.pw}
+ hikari:
+ # 比你数据库空闲断连时间再小一点,这里示例用 20 分钟
+ max-lifetime: 1200000 # 20 分钟,单位 ms
+ idle-timeout: 600000 # 10 分钟,长时间不用就回收
+ connection-timeout: 30000 # 30 秒 等待可用连接
+ minimum-idle: 5 # 保持最少 5 个空闲
+ maximum-pool-size: 10 # 池中最大连接数,根据并发量调整
+ validation-timeout: 5000 # 验证一个连接可用时的超时时间
+ # (可选)强制每次从池里拿连接前跑一下简单检查:
+ connection-test-query: SELECT 1
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
diff --git a/pay-service/src/main/java/com/hmall/pay/PayApplication.java b/pay-service/src/main/java/com/hmall/pay/PayApplication.java
index 0216fa6..2819a5b 100644
--- a/pay-service/src/main/java/com/hmall/pay/PayApplication.java
+++ b/pay-service/src/main/java/com/hmall/pay/PayApplication.java
@@ -1,12 +1,13 @@
package com.hmall.pay;
+import com.hmall.api.config.DefaultFeignConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@MapperScan("com.hmall.pay.mapper")
-@EnableFeignClients(basePackages= "com.hmall.api.client")
+@EnableFeignClients(basePackages= "com.hmall.api.client",defaultConfiguration = DefaultFeignConfig.class)
@SpringBootApplication
public class PayApplication {
public static void main(String[] args) {
diff --git a/pay-service/src/main/resources/application.yaml b/pay-service/src/main/resources/application.yaml
index 2815d9c..2e43187 100644
--- a/pay-service/src/main/resources/application.yaml
+++ b/pay-service/src/main/resources/application.yaml
@@ -9,10 +9,20 @@ spring:
profiles:
active: local
datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hm-pay?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://${hm.db.host}:3307/hm-pay?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${hm.db.pw}
+ hikari:
+ # 比你数据库空闲断连时间再小一点,这里示例用 20 分钟
+ max-lifetime: 1200000 # 20 分钟,单位 ms
+ idle-timeout: 600000 # 10 分钟,长时间不用就回收
+ connection-timeout: 30000 # 30 秒 等待可用连接
+ minimum-idle: 5 # 保持最少 5 个空闲
+ maximum-pool-size: 10 # 池中最大连接数,根据并发量调整
+ validation-timeout: 5000 # 验证一个连接可用时的超时时间
+ # (可选)强制每次从池里拿连接前跑一下简单检查:
+ connection-test-query: SELECT 1
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
diff --git a/pom.xml b/pom.xml
index fc5f300..d85091e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
hm-api
trade-service
pay-service
+ hm-gateway
@@ -36,7 +37,7 @@
2021.0.4.0
3.5.2
5.8.11
- 8.0.23
+ 8.0.24
diff --git a/trade-service/src/main/java/com/hmall/trade/TradeApplication.java b/trade-service/src/main/java/com/hmall/trade/TradeApplication.java
index de60d85..a58e03b 100644
--- a/trade-service/src/main/java/com/hmall/trade/TradeApplication.java
+++ b/trade-service/src/main/java/com/hmall/trade/TradeApplication.java
@@ -1,12 +1,16 @@
package com.hmall.trade;
+import com.hmall.api.config.DefaultFeignConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@MapperScan("com.hmall.trade.mapper")
-@EnableFeignClients(basePackages= "com.hmall.api.client")
+@EnableFeignClients(
+ basePackages = "com.hmall.api.client",
+ defaultConfiguration = DefaultFeignConfig.class
+)
@SpringBootApplication
public class TradeApplication {
public static void main(String[] args) {
diff --git a/trade-service/src/main/java/com/hmall/trade/service/impl/OrderServiceImpl.java b/trade-service/src/main/java/com/hmall/trade/service/impl/OrderServiceImpl.java
index 3f721aa..e9136ac 100644
--- a/trade-service/src/main/java/com/hmall/trade/service/impl/OrderServiceImpl.java
+++ b/trade-service/src/main/java/com/hmall/trade/service/impl/OrderServiceImpl.java
@@ -93,6 +93,7 @@ public class OrderServiceImpl extends ServiceImpl implements
order.setId(orderId);
order.setStatus(2);
order.setPayTime(LocalDateTime.now());
+ order.setCreateTime(LocalDateTime.now());
updateById(order);
}
diff --git a/trade-service/src/main/resources/application.yaml b/trade-service/src/main/resources/application.yaml
index 7e86336..172e6f6 100644
--- a/trade-service/src/main/resources/application.yaml
+++ b/trade-service/src/main/resources/application.yaml
@@ -9,10 +9,20 @@ spring:
profiles:
active: local
datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hm-trade?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://${hm.db.host}:3307/hm-trade?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${hm.db.pw}
+ hikari:
+ # 比你数据库空闲断连时间再小一点,这里示例用 20 分钟
+ max-lifetime: 1200000 # 20 分钟,单位 ms
+ idle-timeout: 600000 # 10 分钟,长时间不用就回收
+ connection-timeout: 30000 # 30 秒 等待可用连接
+ minimum-idle: 5 # 保持最少 5 个空闲
+ maximum-pool-size: 10 # 池中最大连接数,根据并发量调整
+ validation-timeout: 5000 # 验证一个连接可用时的超时时间
+ # (可选)强制每次从池里拿连接前跑一下简单检查:
+ connection-test-query: SELECT 1
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
diff --git a/user-service/src/main/resources/application.yaml b/user-service/src/main/resources/application.yaml
index 1c50136..fbbcf3b 100644
--- a/user-service/src/main/resources/application.yaml
+++ b/user-service/src/main/resources/application.yaml
@@ -9,10 +9,20 @@ spring:
profiles:
active: local
datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hm-user?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://${hm.db.host}:3307/hm-user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${hm.db.pw}
+ hikari:
+ # 比你数据库空闲断连时间再小一点,这里示例用 20 分钟
+ max-lifetime: 1200000 # 20 分钟,单位 ms
+ idle-timeout: 600000 # 10 分钟,长时间不用就回收
+ connection-timeout: 30000 # 30 秒 等待可用连接
+ minimum-idle: 5 # 保持最少 5 个空闲
+ maximum-pool-size: 10 # 池中最大连接数,根据并发量调整
+ validation-timeout: 5000 # 验证一个连接可用时的超时时间
+ # (可选)强制每次从池里拿连接前跑一下简单检查:
+ connection-test-query: SELECT 1
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler