From 8a500b3455b9cc65fba37ecab3c23fa4252ece5b Mon Sep 17 00:00:00 2001 From: litianxiang Date: Wed, 22 Apr 2026 11:16:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E6=9C=8D=E5=8A=A1=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../interceptor/UserContextInterceptor.java | 48 ++++++++++++++++ .../config/PrimaryDataSourceConfig.java | 57 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 .gitignore create mode 100644 src/main/java/com/aida/seller/common/interceptor/UserContextInterceptor.java create mode 100644 src/main/java/com/aida/seller/config/PrimaryDataSourceConfig.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/src/main/java/com/aida/seller/common/interceptor/UserContextInterceptor.java b/src/main/java/com/aida/seller/common/interceptor/UserContextInterceptor.java new file mode 100644 index 0000000..a6d4621 --- /dev/null +++ b/src/main/java/com/aida/seller/common/interceptor/UserContextInterceptor.java @@ -0,0 +1,48 @@ +package com.aida.seller.common.interceptor; + +import com.aida.seller.common.context.UserContext; +import com.aida.seller.model.vo.AuthPrincipalVo; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 从 Gateway 转发的请求头中读取已鉴权的用户身份,写入 UserContext。 + *

+ * Gateway 验证 JWT 后将 X-User-Id 和 X-User-Info 写入请求头, + * 此拦截器负责将信息填充到 ThreadLocal,供业务代码使用。 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class UserContextInterceptor implements HandlerInterceptor { + + private static final String USER_ID_HEADER = "X-User-Id"; + private static final String USER_INFO_HEADER = "X-User-Info"; + + private final ObjectMapper objectMapper; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String userInfoJson = request.getHeader(USER_INFO_HEADER); + if (userInfoJson != null && !userInfoJson.isBlank()) { + try { + AuthPrincipalVo principal = objectMapper.readValue(userInfoJson, AuthPrincipalVo.class); + UserContext.setUserHolder(principal); + } catch (Exception e) { + log.warn("Failed to parse X-User-Info header: {}", e.getMessage()); + } + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, + Object handler, Exception ex) { + UserContext.delete(); + } +} diff --git a/src/main/java/com/aida/seller/config/PrimaryDataSourceConfig.java b/src/main/java/com/aida/seller/config/PrimaryDataSourceConfig.java new file mode 100644 index 0000000..decf195 --- /dev/null +++ b/src/main/java/com/aida/seller/config/PrimaryDataSourceConfig.java @@ -0,0 +1,57 @@ +package com.aida.seller.config; + +import com.baomidou.mybatisplus.core.config.GlobalConfig; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import javax.sql.DataSource; + +@Configuration +@MapperScan(basePackages = "com.aida.seller.module.*.mapper", sqlSessionFactoryRef = "primarySqlSessionFactory") +public class PrimaryDataSourceConfig { + + @Autowired + private MybatisPlusInterceptor mybatisPlusInterceptor; + + @Primary + @Bean(name = "primaryDataSource") + @ConfigurationProperties(prefix = "spring.datasource.primary") + public DataSource dataSource() { + return DataSourceBuilder.create().build(); + } + + @Primary + @Bean(name = "primarySqlSessionFactory") + public SqlSessionFactory sqlSessionFactory( + @Qualifier("primaryDataSource") DataSource dataSource, + ApplicationContext applicationContext) throws Exception { + MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean(); + bean.setDataSource(dataSource); + bean.setMapperLocations(applicationContext.getResources("classpath*:/mapper/**/*.xml")); + + GlobalConfig globalConfig = new GlobalConfig(); + globalConfig.setBanner(false); + bean.setGlobalConfig(globalConfig); + + bean.setPlugins(mybatisPlusInterceptor); + return bean.getObject(); + } + + @Primary + @Bean(name = "primarySqlSessionTemplate") + public SqlSessionTemplate sqlSessionTemplate( + @Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory); + } +}