5.24 网关 登录校验

This commit is contained in:
zhangsan 2025-05-24 22:24:52 +08:00
parent 5698a1d597
commit bf50a915d7
32 changed files with 616 additions and 56 deletions

View File

@ -50,6 +50,21 @@
<artifactId>hm-api</artifactId>
<version>1.0.0</version>
</dependency>
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>

View File

@ -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;
}

View File

@ -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<CartMapper, Cart> 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<CartMapper, Cart> implements IC
@Override
public List<CartVO> queryMyCarts() {
// 1.查询我的购物车列表
List<Cart> carts = lambdaQuery().eq(Cart::getUserId,1L /*UserContext.getUser()*/).list();
List<Cart> carts = lambdaQuery().eq(Cart::getUserId,UserContext.getUser()).list();
if (CollUtils.isEmpty(carts)) {
return CollUtils.emptyList();
}
@ -118,9 +119,9 @@ public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> 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())
);
}
}

View File

@ -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

View File

@ -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 # 共享日志配置

View File

@ -11,7 +11,11 @@
<artifactId>hm-api</artifactId>
<dependencies>
<dependency>
<groupId>com.heima</groupId>
<artifactId>hm-common</artifactId>
<version>1.0.0</version>
</dependency>
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@ -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());
}
};
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hmall.common.config.MyBatisConfig,\
com.hmall.common.config.JsonConfig
com.hmall.common.config.JsonConfig,\
com.hmall.common.config.MvcConfig

56
hm-gateway/pom.xml Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>hmall</artifactId>
<groupId>com.heima</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hm-gateway</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!--common-->
<dependency>
<groupId>com.heima</groupId>
<artifactId>hm-common</artifactId>
<version>1.0.0</version>
</dependency>
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -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);
}
}

View File

@ -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<String> includePaths;
private List<String> excludePaths;
}

View File

@ -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);
}

View File

@ -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());
}
}

View File

@ -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<Void> 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<String> 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;
}
}

View File

@ -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<Void> 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可根据实际需求调整
}
}

View File

@ -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");
}
}
}

View File

@ -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

Binary file not shown.

View File

@ -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}

View File

@ -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<ItemDTO> search(ItemPageQuery query) {
// 分页查询
Page<Item> 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);
}
}

View File

@ -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;
/**

View File

@ -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<ItemMapper, Item> implements II
@Override
public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
// 1. 防空参数为 null 空集合直接返回空列表
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
List<Item> 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);
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -17,6 +17,7 @@
<module>hm-api</module>
<module>trade-service</module>
<module>pay-service</module>
<module>hm-gateway</module>
</modules>
<parent>
@ -36,7 +37,7 @@
<spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<hutool.version>5.8.11</hutool.version>
<mysql.version>8.0.23</mysql.version>
<mysql.version>8.0.24</mysql.version>
</properties>
<!-- 对依赖包进行管理 -->

View File

@ -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) {

View File

@ -93,6 +93,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
order.setId(orderId);
order.setStatus(2);
order.setPayTime(LocalDateTime.now());
order.setCreateTime(LocalDateTime.now());
updateById(order);
}

View File

@ -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

View File

@ -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