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