feat(修复): 查询商品详情出错,解决跨域
Signed-off-by: bunny <1319900154@qq.com>
This commit is contained in:
parent
e491620e6f
commit
531a205911
|
@ -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;
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
|
|||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Result<T> {
|
||||
// 烦你吗
|
||||
// 状态码
|
||||
private Integer code;
|
||||
// 返回消息
|
||||
private String message;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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-dd’T’HH: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);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ import java.util.List;
|
|||
@RestController
|
||||
@RequestMapping("/api/product/category/")
|
||||
@Slf4j
|
||||
// @CrossOrigin
|
||||
public class CategoryController {
|
||||
@Autowired
|
||||
private CategoryService categoryService;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue