feat(修复): 查询商品详情出错,解决跨域

Signed-off-by: bunny <1319900154@qq.com>
This commit is contained in:
bunny 2024-03-27 18:39:15 +08:00
parent e491620e6f
commit 531a205911
17 changed files with 279 additions and 44 deletions

View File

@ -12,7 +12,6 @@ import java.util.Map;
@Data
@Schema(description = "商品详情对象")
public class ProductItemVo {
@Schema(description = "商品sku信息")
private ProductSku productSku;
@ -30,5 +29,4 @@ public class ProductItemVo {
@Schema(description = "商品规格对应商品skuId信息")
private Map<String, Object> skuSpecValueMap;
}

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
// 烦你吗
// 状态码
private Integer code;
// 返回消息
private String message;

View File

@ -2,10 +2,8 @@ package com.atguigu.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.atguigu")
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);

View File

@ -17,16 +17,16 @@ spring:
locator:
enabled: true
# 解决跨域
# globalcors:
# cors-configurations:
# '[/**]':
# allowedOriginPatterns: "*"
# # 允许请求中携带的头信息
# allowedHeaders: "*"
# # 运行跨域的请求方式
# allowedMethods: "*"
# # 跨域检测的有效期,单位s
# maxAge: 36000
globalcors:
cors-configurations:
'[/**]':
allowedOriginPatterns: "*"
# 允许请求中携带的头信息
allowedHeaders: "*"
# 运行跨域的请求方式
allowedMethods: "*"
# 跨域检测的有效期,单位s
maxAge: 36000
# 路由
routes:
- id: service-product

View File

@ -5,16 +5,10 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@ComponentScan("com.atguigu")
@EnableCaching// 开启缓存注解
@MapperScan("com.atguigu.*.mapper")
@EnableTransactionManagement // 开启注解方式的事务管理
@EnableScheduling
@MapperScan("com.atguigu.product.mapper")
@Slf4j
public class ProductApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,99 @@
package com.atguigu.product.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
@Slf4j
public class RedisConfiguration {
/**
* 使用StringRedisSerializer序列化为字符串
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
log.info("RedisConfiguration===>使用StringRedisSerializer序列化为字符串");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
// 设置key序列化为string
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置value序列化为JSON使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
/**
* 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
*/
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
log.info("RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题");
StringRedisSerializer redisSerializer = new StringRedisSerializer();
// json序列化
Jackson2JsonRedisSerializer<Object> serializer = jsonRedisSerializer();
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(redisCacheConfiguration).build();
return cacheManager;
}
/**
* 指定的日期模式
*/
public Jackson2JsonRedisSerializer<Object> jsonRedisSerializer() {
log.info("RedisConfiguration===>指定的日期模式");
ObjectMapper mapper = new ObjectMapper();
// 设置ObjectMapper访问权限
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 记录序列化之后的数据类型方便反序列化
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
// 关闭默认的日期格式化方式默认UTC日期格式 yyyy-MM-ddTHH:mm:ss.SSS
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// LocalDatetime序列化默认不兼容jdk8日期序列化
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(timeModule);
return new Jackson2JsonRedisSerializer<>(mapper, Object.class);
}
}

View File

@ -17,7 +17,6 @@ import java.util.List;
@RestController
@RequestMapping("/api/product/category/")
@Slf4j
// @CrossOrigin
public class CategoryController {
@Autowired
private CategoryService categoryService;

View File

@ -18,9 +18,8 @@ import java.util.List;
@Tag(name = "首页接口管理")
@RestController
@RequestMapping(value = "/api/product/index")
@RequestMapping("/api/product/index")
@Slf4j
// @CrossOrigin
public class IndexController {
@Autowired
private CategoryService categoryService;

View File

@ -3,11 +3,12 @@ package com.atguigu.product.controller;
import com.atguigu.product.service.ProductService;
import com.atguigu.spzx.model.dto.h5.ProductSkuDto;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.h5.ProductItemVo;
import com.atguigu.spzx.model.vo.result.Result;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -16,17 +17,24 @@ import org.springframework.web.bind.annotation.RestController;
@Tag(name = "商品列表管理")
@RestController
@RequestMapping(value = "/api/product")
@RequestMapping("/api/product/")
@Slf4j
public class ProductController {
@Autowired
private ProductService productService;
@Operation(summary = "分页查询")
@GetMapping(value = "{page}/{limit}")
public Result<PageInfo<ProductSku>> findByPage(@Parameter(name = "page", description = "当前页码", required = true) @PathVariable Integer page,
@Parameter(name = "limit", description = "每页记录数", required = true) @PathVariable Integer limit,
@Parameter(name = "productSkuDto", description = "搜索条件对象", required = false) ProductSkuDto productSkuDto) {
public Result<PageInfo<ProductSku>> findByPage(@PathVariable Integer page, @PathVariable Integer limit, ProductSkuDto productSkuDto) {
PageInfo<ProductSku> pageInfo = productService.findByPage(page, limit, productSkuDto);
return Result.success(pageInfo);
}
@Operation(summary = "商品详情")
@GetMapping("item/{skuId}")
public Result<ProductItemVo> item(@PathVariable Long skuId) {
ProductItemVo vo = productService.item(skuId);
return Result.success(vo);
}
}

View File

@ -0,0 +1,9 @@
package com.atguigu.product.mapper;
import com.atguigu.spzx.model.entity.product.ProductDetails;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ProductDetailMapper {
ProductDetails getByProductId(Long productId);
}

View File

@ -0,0 +1,13 @@
package com.atguigu.product.mapper;
import com.atguigu.spzx.model.entity.product.Product;
public interface ProductMapper {
/**
* 当前商品信息
*
* @param productId productId
* @return Product
*/
Product getById(Long productId);
}

View File

@ -22,4 +22,20 @@ public interface ProductSkuMapper {
* @return PageInfo<ProductSku>
*/
List<ProductSku> findByPage(ProductSkuDto productSkuDto);
/**
* 当前sku信息
*
* @param skuId skuId
* @return ProductSku
*/
ProductSku getById(Long skuId);
/**
* 同一个商品下面的sku信息列表
*
* @param productId productId
* @return List<ProductSku>
*/
List<ProductSku> findByProductId(Long productId);
}

View File

@ -2,6 +2,7 @@ package com.atguigu.product.service;
import com.atguigu.spzx.model.dto.h5.ProductSkuDto;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.h5.ProductItemVo;
import com.github.pagehelper.PageInfo;
import java.util.List;
@ -23,4 +24,12 @@ public interface ProductService {
* @return PageInfo<ProductSku>
*/
PageInfo<ProductSku> findByPage(Integer page, Integer limit, ProductSkuDto productSkuDto);
/**
* 商品详情
*
* @param skuId skuId
* @return ProductItemVo
*/
ProductItemVo item(Long skuId);
}

View File

@ -1,21 +1,34 @@
package com.atguigu.product.service.impl;
import com.alibaba.fastjson.JSON;
import com.atguigu.product.mapper.ProductDetailMapper;
import com.atguigu.product.mapper.ProductMapper;
import com.atguigu.product.mapper.ProductSkuMapper;
import com.atguigu.product.service.ProductService;
import com.atguigu.spzx.model.dto.h5.ProductSkuDto;
import com.atguigu.spzx.model.entity.product.Product;
import com.atguigu.spzx.model.entity.product.ProductDetails;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.h5.ProductItemVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductSkuMapper productSkuMapper;
@Autowired
private ProductMapper productMapper;
@Autowired
private ProductDetailMapper productDetailsMapper;
/**
* 根据销量排序获取前十条数据
@ -42,4 +55,38 @@ public class ProductServiceImpl implements ProductService {
startPage.close();
return new PageInfo<>(productSkuList);
}
/**
* 商品详情
*
* @param skuId skuId
* @return ProductItemVo
*/
@Override
public ProductItemVo item(Long skuId) {
// 当前sku信息
ProductSku productSku = productSkuMapper.getById(skuId);
// 当前商品信息
Product product = productMapper.getById(productSku.getProductId());
// 同一个商品下面的sku信息列表
List<ProductSku> productSkuList = productSkuMapper.findByProductId(productSku.getProductId());
// 建立sku规格与skuId对应关系
Map<String, Object> skuSpecValueMap = new HashMap<>();
productSkuList.forEach(item -> {
skuSpecValueMap.put(item.getSkuSpec(), item.getId());
});
// 商品详情信息
ProductDetails productDetails = productDetailsMapper.getByProductId(productSku.getProductId());
ProductItemVo productItemVo = new ProductItemVo();
productItemVo.setProductSku(productSku);
productItemVo.setProduct(product);
productItemVo.setDetailsImageUrlList(Arrays.asList(productDetails.getImageUrls().split(",")));
productItemVo.setSliderUrlList(Arrays.asList(product.getSliderUrls().split(",")));
productItemVo.setSpecValueList(JSON.parseArray(product.getSpecValue()));
productItemVo.setSkuSpecValueMap(skuSpecValueMap);
return productItemVo;
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.product.mapper.ProductDetailMapper">
<!-- 用于select查询公用抽取的列 -->
<sql id="columns">
id,product_id,image_urls,create_time,update_time,is_deleted
</sql>
<select id="getByProductId" resultType="com.atguigu.spzx.model.entity.product.ProductDetails">
select
<include refid="columns"/>
from product_details
where
product_id = #{productId}
</select>
</mapper>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.product.mapper.ProductMapper">
<!-- 用于select查询公用抽取的列 -->
<sql id="columns">
id,name,brand_id,category1_id,category2_id,category3_id,unit_name,slider_urls,spec_value,status,audit_status,audit_message,create_time,update_time,is_deleted
</sql>
<!-- 当前商品信息 -->
<select id="getById" resultType="com.atguigu.spzx.model.entity.product.Product">
select
<include refid="columns"/>
from product
where
id = #{id}
</select>
</mapper>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.product.mapper.ProductSkuMapper">
<!-- 根据销量排序,获取前十条数据 -->
<select id="selectProductSkuBySale" resultType="com.atguigu.spzx.model.entity.product.ProductSku">
SELECT psku.*
@ -51,4 +50,18 @@
order by sku.sale_price desc
</if>
</select>
<!-- 当前sku信息 -->
<select id="getById" resultType="com.atguigu.spzx.model.entity.product.ProductSku">
select *
from product_sku
where id = #{id}
</select>
<!-- 同一个商品下面的sku信息列表 -->
<select id="findByProductId" resultType="com.atguigu.spzx.model.entity.product.ProductSku">
select *
from product_sku
where product_id = #{productId}
</select>
</mapper>