feat: 添加商品数据初始化类和CORS配置优化
添加商品数据初始化类ProductDataInitializer,用于系统启动时创建初始商品分类和商品信息 优化CORS配置,从配置文件中读取跨域设置,提高灵活性 新增DTO类ProductsDataList和UserDataList 更新开发和生产环境的配置文件,添加CORS相关配置
This commit is contained in:
@@ -1,35 +1,55 @@
|
|||||||
package com.qf.backend.config;
|
package com.qf.backend.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
import org.springframework.web.filter.CorsFilter;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CorsConfig {
|
public class CorsConfig {
|
||||||
/**
|
/**
|
||||||
* 跨域配置
|
* 跨域配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// 从配置文件中读取CORS配置
|
||||||
|
@Value("${cors.allowed-origins}")
|
||||||
|
private String allowedOrigins;
|
||||||
|
|
||||||
|
@Value("${cors.allowed-methods}")
|
||||||
|
private String allowedMethods;
|
||||||
|
|
||||||
|
@Value("${cors.allowed-headers}")
|
||||||
|
private String allowedHeaders;
|
||||||
|
|
||||||
|
@Value("${cors.allow-credentials}")
|
||||||
|
private Boolean allowCredentials;
|
||||||
|
|
||||||
|
@Value("${cors.max-age}")
|
||||||
|
private Long maxAge;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CorsFilter corsFilter(){
|
public CorsFilter corsFilter(){
|
||||||
// 创建跨域配置对象
|
// 创建跨域配置对象
|
||||||
CorsConfiguration configuration = new CorsConfiguration();
|
CorsConfiguration configuration = new CorsConfiguration();
|
||||||
// 允许的来源使用通配符,允许所有来源
|
// 允许的来源,从配置中分割
|
||||||
configuration.addAllowedOriginPattern("*");
|
String[] originStrings = allowedOrigins.split(",");
|
||||||
|
for (String origin : originStrings) {
|
||||||
|
configuration.addAllowedOriginPattern(origin.trim());
|
||||||
|
}
|
||||||
//允许携带cookie
|
//允许携带cookie
|
||||||
configuration.setAllowCredentials(true);
|
configuration.setAllowCredentials(allowCredentials);
|
||||||
|
// 允许的HTTP方法。从配置文件分割提取
|
||||||
// 明确列出允许的HTTP方法,比使用通配符更安全
|
String[] methodStrings = allowedMethods.split(",");
|
||||||
configuration.addAllowedMethod("GET");
|
for (String method : methodStrings) {
|
||||||
configuration.addAllowedMethod("POST");
|
configuration.addAllowedMethod(method.trim());
|
||||||
configuration.addAllowedMethod("PUT");
|
}
|
||||||
configuration.addAllowedMethod("DELETE");
|
// 允许的请求头。从配置文件分割提取
|
||||||
configuration.addAllowedMethod("OPTIONS");
|
String[] headerStrings = allowedHeaders.split(",");
|
||||||
configuration.addAllowedMethod("PATCH");
|
for (String header : headerStrings) {
|
||||||
// 允许所有请求头(新增)
|
configuration.addAllowedHeader(header.trim());
|
||||||
configuration.addAllowedHeader("*");
|
}
|
||||||
|
|
||||||
// 明确暴露的响应头,对于JWT认证很重要
|
// 明确暴露的响应头,对于JWT认证很重要
|
||||||
configuration.addExposedHeader("Authorization");
|
configuration.addExposedHeader("Authorization");
|
||||||
configuration.addExposedHeader("Content-Type");
|
configuration.addExposedHeader("Content-Type");
|
||||||
@@ -37,7 +57,7 @@ public class CorsConfig {
|
|||||||
configuration.addExposedHeader("Accept");
|
configuration.addExposedHeader("Accept");
|
||||||
configuration.addExposedHeader("Access-Control-Allow-Origin");
|
configuration.addExposedHeader("Access-Control-Allow-Origin");
|
||||||
// 设置最大缓存时间为1小时,减少预检请求次数
|
// 设置最大缓存时间为1小时,减少预检请求次数
|
||||||
configuration.setMaxAge(3600L);
|
configuration.setMaxAge(maxAge);
|
||||||
// 创建基于URL的CORS配置源
|
// 创建基于URL的CORS配置源
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
|
||||||
|
|||||||
5
src/main/java/com/qf/backend/dto/ProductsDataList.java
Normal file
5
src/main/java/com/qf/backend/dto/ProductsDataList.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package com.qf.backend.dto;
|
||||||
|
|
||||||
|
public class ProductsDataList {
|
||||||
|
|
||||||
|
}
|
||||||
9
src/main/java/com/qf/backend/dto/UserDataList.java
Normal file
9
src/main/java/com/qf/backend/dto/UserDataList.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.qf.backend.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.qf.backend.entity.Users;
|
||||||
|
|
||||||
|
public class UserDataList {
|
||||||
|
private List<Users> userDataList;
|
||||||
|
}
|
||||||
152
src/main/java/com/qf/backend/inti/ProductDataInitializer.java
Normal file
152
src/main/java/com/qf/backend/inti/ProductDataInitializer.java
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package com.qf.backend.inti;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.qf.backend.entity.ProductCategories;
|
||||||
|
import com.qf.backend.entity.Products;
|
||||||
|
import com.qf.backend.service.ProductCategoriesService;
|
||||||
|
import com.qf.backend.service.ProductsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品数据初始化配置类,用于在系统启动时创建初始商品分类和商品信息
|
||||||
|
* @author 30803
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ProductDataInitializer {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ProductDataInitializer.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProductCategoriesService productCategoriesService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProductsService productsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统启动时初始化商品数据
|
||||||
|
*/
|
||||||
|
// @PostConstruct
|
||||||
|
public void initProductData() {
|
||||||
|
logger.info("开始初始化商品数据...");
|
||||||
|
|
||||||
|
// 初始化商品分类
|
||||||
|
initProductCategories();
|
||||||
|
|
||||||
|
// 初始化商品信息
|
||||||
|
initProducts();
|
||||||
|
|
||||||
|
logger.info("商品数据初始化完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化商品分类
|
||||||
|
*/
|
||||||
|
private void initProductCategories() {
|
||||||
|
logger.info("开始初始化商品分类...");
|
||||||
|
|
||||||
|
// 定义初始分类信息
|
||||||
|
Object[][] categoryInfos = {
|
||||||
|
// 顶级分类
|
||||||
|
{"1", "电子产品", "0", 1, "electronics", "electronics-banner.jpg", 1, 1},
|
||||||
|
{"2", "服装鞋包", "0", 1, "clothing", "clothing-banner.jpg", 2, 1},
|
||||||
|
{"3", "家居用品", "0", 1, "home", "home-banner.jpg", 3, 1},
|
||||||
|
// 二级分类 - 电子产品
|
||||||
|
{"4", "手机数码", "1", 2, "phone", "phone-banner.jpg", 1, 1},
|
||||||
|
{"5", "电脑办公", "1", 2, "computer", "computer-banner.jpg", 2, 1},
|
||||||
|
{"6", "家用电器", "1", 2, "appliance", "appliance-banner.jpg", 3, 1},
|
||||||
|
// 二级分类 - 服装鞋包
|
||||||
|
{"7", "男装", "2", 2, "men", "men-banner.jpg", 1, 1},
|
||||||
|
{"8", "女装", "2", 2, "women", "women-banner.jpg", 2, 1},
|
||||||
|
{"9", "鞋靴", "2", 2, "shoes", "shoes-banner.jpg", 3, 1},
|
||||||
|
// 三级分类 - 手机数码
|
||||||
|
{"10", "手机", "4", 3, "mobile", "mobile-banner.jpg", 1, 1},
|
||||||
|
{"11", "耳机", "4", 3, "headphone", "headphone-banner.jpg", 2, 1},
|
||||||
|
{"12", "相机", "4", 3, "camera", "camera-banner.jpg", 3, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (Object[] categoryInfo : categoryInfos) {
|
||||||
|
String categoryName = (String) categoryInfo[1];
|
||||||
|
Long parentId = Long.parseLong((String) categoryInfo[2]);
|
||||||
|
|
||||||
|
// 检查分类是否已存在
|
||||||
|
QueryWrapper<ProductCategories> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("category_name", categoryName)
|
||||||
|
.eq("parent_id", parentId);
|
||||||
|
ProductCategories existingCategory = productCategoriesService.getOne(queryWrapper);
|
||||||
|
|
||||||
|
if (existingCategory == null) {
|
||||||
|
// 创建新分类
|
||||||
|
ProductCategories category = new ProductCategories();
|
||||||
|
category.setCategoryName(categoryName);
|
||||||
|
category.setParentId(parentId);
|
||||||
|
category.setLevel((Integer) categoryInfo[3]);
|
||||||
|
category.setIcon((String) categoryInfo[4]);
|
||||||
|
category.setBanner((String) categoryInfo[5]);
|
||||||
|
category.setSort((Integer) categoryInfo[6]);
|
||||||
|
category.setStatus((Integer) categoryInfo[7]);
|
||||||
|
|
||||||
|
productCategoriesService.save(category);
|
||||||
|
logger.info("成功创建商品分类: {}", categoryName);
|
||||||
|
} else {
|
||||||
|
logger.info("商品分类 {} 已存在,跳过创建", categoryName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("商品分类初始化完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化商品信息
|
||||||
|
*/
|
||||||
|
private void initProducts() {
|
||||||
|
logger.info("开始初始化商品信息...");
|
||||||
|
|
||||||
|
// 定义初始商品信息
|
||||||
|
Object[][] productInfos = {
|
||||||
|
{"iPhone 16 Pro", 1, 10, "最新款iPhone,搭载A18处理器", 8999.00, 7999.00, 0, 1, "iphone16.jpg"},
|
||||||
|
{"华为 Mate 70 Pro", 1, 10, "华为旗舰手机,搭载麒麟9100处理器", 7999.00, 6999.00, 0, 1, "huawei-mate70.jpg"},
|
||||||
|
{"小米 15 Pro", 1, 10, "小米旗舰手机,搭载骁龙8 Gen 4处理器", 5999.00, 4999.00, 0, 1, "xiaomi-15.jpg"},
|
||||||
|
{"MacBook Pro 14", 1, 5, "苹果笔记本,M3 Pro芯片", 14999.00, 13999.00, 0, 1, "macbook-pro.jpg"},
|
||||||
|
{"ThinkPad X1 Carbon", 1, 5, "商务笔记本,高性能低功耗", 12999.00, 11999.00, 0, 1, "thinkpad-x1.jpg"},
|
||||||
|
{"索尼 WH-1000XM5", 1, 11, "索尼降噪耳机,顶级音质", 2999.00, 2499.00, 0, 1, "sony-wh1000xm5.jpg"},
|
||||||
|
{"AirPods Pro 2", 1, 11, "苹果降噪耳机,支持空间音频", 1899.00, 1599.00, 0, 1, "airpods-pro.jpg"},
|
||||||
|
{"男士休闲裤", 1, 7, "舒适透气,适合日常穿着", 299.00, 199.00, 0, 1, "men-pants.jpg"},
|
||||||
|
{"女士连衣裙", 1, 8, "时尚优雅,适合各种场合", 399.00, 299.00, 0, 1, "women-dress.jpg"},
|
||||||
|
{"智能手表", 1, 4, "多功能智能手表,健康监测", 1599.00, 1299.00, 0, 1, "smartwatch.jpg"},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (Object[] productInfo : productInfos) {
|
||||||
|
String productName = (String) productInfo[0];
|
||||||
|
|
||||||
|
// 检查商品是否已存在
|
||||||
|
QueryWrapper<Products> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("product_name", productName);
|
||||||
|
Products existingProduct = productsService.getOne(queryWrapper);
|
||||||
|
|
||||||
|
if (existingProduct == null) {
|
||||||
|
// 创建新商品
|
||||||
|
Products product = new Products();
|
||||||
|
product.setProductName(productName);
|
||||||
|
product.setShopId(Long.valueOf((Integer) productInfo[1]));
|
||||||
|
product.setCategoryId(Long.valueOf((Integer) productInfo[2]));
|
||||||
|
product.setDescription((String) productInfo[3]);
|
||||||
|
product.setOriginalPrice(new java.math.BigDecimal(Double.toString((Double) productInfo[4])));
|
||||||
|
product.setCurrentPrice(new java.math.BigDecimal(Double.toString((Double) productInfo[5])));
|
||||||
|
product.setSalesVolume((Integer) productInfo[6]);
|
||||||
|
product.setStatus((Integer) productInfo[7]);
|
||||||
|
product.setMainImage((String) productInfo[8]);
|
||||||
|
product.setIsDeleted(0);
|
||||||
|
|
||||||
|
productsService.save(product);
|
||||||
|
logger.info("成功创建商品: {}", productName);
|
||||||
|
} else {
|
||||||
|
logger.info("商品 {} 已存在,跳过创建", productName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("商品信息初始化完成");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,3 +2,8 @@
|
|||||||
jwt.secret=your_very_strong_secret_key_that_is_at_least_32_characters_long!
|
jwt.secret=your_very_strong_secret_key_that_is_at_least_32_characters_long!
|
||||||
jwt.expiration=3600000
|
jwt.expiration=3600000
|
||||||
jwt.token-prefix=Bearer
|
jwt.token-prefix=Bearer
|
||||||
|
# CORS 配置 - 开发用(允许所有来源)
|
||||||
|
cors.allowed-origins=*
|
||||||
|
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS,PATCH
|
||||||
|
cors.allowed-headers=*
|
||||||
|
cors.exposed-headers=Authorization
|
||||||
@@ -1,4 +1,11 @@
|
|||||||
# JWT 配置 - 生产用(敏感信息从环境变量读取)
|
# JWT 配置 - 生产用(敏感信息从环境变量读取)
|
||||||
jwt.secret=${JWT_SECRET}
|
jwt.secret=${JWT_SECRET:defaultSecret}
|
||||||
jwt.expiration=${JWT_EXPIRATION:3600000}
|
jwt.expiration=${JWT_EXPIRATION:3600000}
|
||||||
jwt.token-prefix=${JWT_TOKEN_PREFIX:Bearer}
|
jwt.token-prefix=${JWT_TOKEN_PREFIX:Bearer}
|
||||||
|
# CORS 配置 - 生产用(允许所有来源)
|
||||||
|
cors.allowed-origins=*
|
||||||
|
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS,PATCH
|
||||||
|
cors.allowed-headers=*
|
||||||
|
cors.exposed-headers=Authorization
|
||||||
|
cors.allow-credentials=true
|
||||||
|
cors.max-age=3600
|
||||||
|
|||||||
Reference in New Issue
Block a user