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 0000000..a34bd33
Binary files /dev/null and b/hm-gateway/src/main/resources/hmall.jks differ
diff --git a/hm-service/src/main/resources/application.yaml b/hm-service/src/main/resources/application.yaml
index 6d701b4..5a49d37 100644
--- a/hm-service/src/main/resources/application.yaml
+++ b/hm-service/src/main/resources/application.yaml
@@ -6,7 +6,7 @@ spring:
profiles:
active: local
datasource:
- url: jdbc:mysql://${hm.db.host}:3307/hmall?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://${hm.db.host}:3307/hmall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${hm.db.pw}
diff --git a/item-service/src/main/java/com/hmall/item/controller/SearchController.java b/item-service/src/main/java/com/hmall/item/controller/SearchController.java
new file mode 100644
index 0000000..e67a09b
--- /dev/null
+++ b/item-service/src/main/java/com/hmall/item/controller/SearchController.java
@@ -0,0 +1,40 @@
+package com.hmall.item.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.hmall.api.dto.ItemDTO;
+import com.hmall.common.domain.PageDTO;
+
+import com.hmall.item.domain.po.Item;
+import com.hmall.item.domain.query.ItemPageQuery;
+import com.hmall.item.service.IItemService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = "搜索相关接口")
+@RestController
+@RequestMapping("/search")
+@RequiredArgsConstructor
+public class SearchController {
+
+ private final IItemService itemService;
+
+ @ApiOperation("搜索商品")
+ @GetMapping("/list")
+ public PageDTO 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