From 531a205911485984c626619b2a611952d533bbd4 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Wed, 27 Mar 2024 18:39:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=BF=AE=E5=A4=8D):=20=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=95=86=E5=93=81=E8=AF=A6=E6=83=85=E5=87=BA=E9=94=99=EF=BC=8C?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=B7=A8=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: bunny <1319900154@qq.com> --- .../spzx/model/vo/h5/ProductItemVo.java | 26 +++-- .../atguigu/spzx/model/vo/result/Result.java | 2 +- .../atguigu/gateway/GatewayApplication.java | 2 - .../src/main/resources/application.yml | 22 ++--- .../atguigu/product/ProductApplication.java | 8 +- .../product/config/RedisConfiguration.java | 99 +++++++++++++++++++ .../controller/CategoryController.java | 1 - .../product/controller/IndexController.java | 3 +- .../product/controller/ProductController.java | 18 +++- .../product/mapper/ProductDetailMapper.java | 9 ++ .../atguigu/product/mapper/ProductMapper.java | 13 +++ .../product/mapper/ProductSkuMapper.java | 16 +++ .../product/service/ProductService.java | 9 ++ .../service/impl/ProductServiceImpl.java | 47 +++++++++ .../mapper/product/ProductDetailMapper.xml | 16 +++ .../mapper/product/ProductMapper.xml | 17 ++++ .../mapper/product/ProductSkuMapper.xml | 15 ++- 17 files changed, 279 insertions(+), 44 deletions(-) create mode 100644 spzx-service/service-product/src/main/java/com/atguigu/product/config/RedisConfiguration.java create mode 100644 spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductDetailMapper.java create mode 100644 spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductMapper.java create mode 100644 spzx-service/service-product/src/main/resources/mapper/product/ProductDetailMapper.xml create mode 100644 spzx-service/service-product/src/main/resources/mapper/product/ProductMapper.xml diff --git a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/h5/ProductItemVo.java b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/h5/ProductItemVo.java index bba64d5..19ac84c 100644 --- a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/h5/ProductItemVo.java +++ b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/h5/ProductItemVo.java @@ -12,23 +12,21 @@ import java.util.Map; @Data @Schema(description = "商品详情对象") public class ProductItemVo { + @Schema(description = "商品sku信息") + private ProductSku productSku; - @Schema(description = "商品sku信息") - private ProductSku productSku; + @Schema(description = "商品信息") + private Product product; - @Schema(description = "商品信息") - private Product product; + @Schema(description = "商品轮播图列表") + private List sliderUrlList; - @Schema(description = "商品轮播图列表") - private List sliderUrlList; + @Schema(description = "商品详情图片列表") + private List detailsImageUrlList; - @Schema(description = "商品详情图片列表") - private List detailsImageUrlList; - - @Schema(description = "商品规格信息") - private JSONArray specValueList; - - @Schema(description = "商品规格对应商品skuId信息") - private Map skuSpecValueMap; + @Schema(description = "商品规格信息") + private JSONArray specValueList; + @Schema(description = "商品规格对应商品skuId信息") + private Map skuSpecValueMap; } \ No newline at end of file diff --git a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/Result.java b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/Result.java index 74fd12f..0614daa 100644 --- a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/Result.java +++ b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/Result.java @@ -8,7 +8,7 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class Result { - // 烦你吗 + // 状态码 private Integer code; // 返回消息 private String message; diff --git a/spzx-server-gateway/src/main/java/com/atguigu/gateway/GatewayApplication.java b/spzx-server-gateway/src/main/java/com/atguigu/gateway/GatewayApplication.java index 90bf5e9..f999f80 100644 --- a/spzx-server-gateway/src/main/java/com/atguigu/gateway/GatewayApplication.java +++ b/spzx-server-gateway/src/main/java/com/atguigu/gateway/GatewayApplication.java @@ -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); diff --git a/spzx-server-gateway/src/main/resources/application.yml b/spzx-server-gateway/src/main/resources/application.yml index 30fd7a9..e36cd0a 100644 --- a/spzx-server-gateway/src/main/resources/application.yml +++ b/spzx-server-gateway/src/main/resources/application.yml @@ -16,17 +16,17 @@ spring: discovery: 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 diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/ProductApplication.java b/spzx-service/service-product/src/main/java/com/atguigu/product/ProductApplication.java index ea99464..32e40d4 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/ProductApplication.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/ProductApplication.java @@ -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) { diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/config/RedisConfiguration.java b/spzx-service/service-product/src/main/java/com/atguigu/product/config/RedisConfiguration.java new file mode 100644 index 0000000..7850f3b --- /dev/null +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/config/RedisConfiguration.java @@ -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 redisTemplate(LettuceConnectionFactory connectionFactory) { + log.info("RedisConfiguration===>使用StringRedisSerializer序列化为字符串"); + + RedisTemplate 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 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 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); + } +} \ No newline at end of file diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/CategoryController.java b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/CategoryController.java index 2749e65..ac2db63 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/CategoryController.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/CategoryController.java @@ -17,7 +17,6 @@ import java.util.List; @RestController @RequestMapping("/api/product/category/") @Slf4j -// @CrossOrigin public class CategoryController { @Autowired private CategoryService categoryService; diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/IndexController.java b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/IndexController.java index 8aa8dc7..d3e525b 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/IndexController.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/IndexController.java @@ -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; diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/ProductController.java b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/ProductController.java index 803f419..9c0c6d2 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/controller/ProductController.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/controller/ProductController.java @@ -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> 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> findByPage(@PathVariable Integer page, @PathVariable Integer limit, ProductSkuDto productSkuDto) { PageInfo pageInfo = productService.findByPage(page, limit, productSkuDto); return Result.success(pageInfo); } + + @Operation(summary = "商品详情") + @GetMapping("item/{skuId}") + public Result item(@PathVariable Long skuId) { + ProductItemVo vo = productService.item(skuId); + + return Result.success(vo); + } } \ No newline at end of file diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductDetailMapper.java b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductDetailMapper.java new file mode 100644 index 0000000..b78f1d5 --- /dev/null +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductDetailMapper.java @@ -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); +} \ No newline at end of file diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductMapper.java b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductMapper.java new file mode 100644 index 0000000..7130f79 --- /dev/null +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductMapper.java @@ -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); +} diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductSkuMapper.java b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductSkuMapper.java index 5862a8a..f8cde6a 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductSkuMapper.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/mapper/ProductSkuMapper.java @@ -22,4 +22,20 @@ public interface ProductSkuMapper { * @return PageInfo */ List findByPage(ProductSkuDto productSkuDto); + + /** + * 当前sku信息 + * + * @param skuId skuId + * @return ProductSku + */ + ProductSku getById(Long skuId); + + /** + * 同一个商品下面的sku信息列表 + * + * @param productId productId + * @return List + */ + List findByProductId(Long productId); } diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/service/ProductService.java b/spzx-service/service-product/src/main/java/com/atguigu/product/service/ProductService.java index dbc2b36..d6b30ca 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/service/ProductService.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/service/ProductService.java @@ -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 */ PageInfo findByPage(Integer page, Integer limit, ProductSkuDto productSkuDto); + + /** + * 商品详情 + * + * @param skuId skuId + * @return ProductItemVo + */ + ProductItemVo item(Long skuId); } diff --git a/spzx-service/service-product/src/main/java/com/atguigu/product/service/impl/ProductServiceImpl.java b/spzx-service/service-product/src/main/java/com/atguigu/product/service/impl/ProductServiceImpl.java index f5e518a..74e35f6 100644 --- a/spzx-service/service-product/src/main/java/com/atguigu/product/service/impl/ProductServiceImpl.java +++ b/spzx-service/service-product/src/main/java/com/atguigu/product/service/impl/ProductServiceImpl.java @@ -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 productSkuList = productSkuMapper.findByProductId(productSku.getProductId()); + + // 建立sku规格与skuId对应关系 + Map 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; + } } diff --git a/spzx-service/service-product/src/main/resources/mapper/product/ProductDetailMapper.xml b/spzx-service/service-product/src/main/resources/mapper/product/ProductDetailMapper.xml new file mode 100644 index 0000000..9afde56 --- /dev/null +++ b/spzx-service/service-product/src/main/resources/mapper/product/ProductDetailMapper.xml @@ -0,0 +1,16 @@ + + + + + + id,product_id,image_urls,create_time,update_time,is_deleted + + + + diff --git a/spzx-service/service-product/src/main/resources/mapper/product/ProductMapper.xml b/spzx-service/service-product/src/main/resources/mapper/product/ProductMapper.xml new file mode 100644 index 0000000..6afc38e --- /dev/null +++ b/spzx-service/service-product/src/main/resources/mapper/product/ProductMapper.xml @@ -0,0 +1,17 @@ + + + + + + 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 + + + + + diff --git a/spzx-service/service-product/src/main/resources/mapper/product/ProductSkuMapper.xml b/spzx-service/service-product/src/main/resources/mapper/product/ProductSkuMapper.xml index b80db3b..8577fb2 100644 --- a/spzx-service/service-product/src/main/resources/mapper/product/ProductSkuMapper.xml +++ b/spzx-service/service-product/src/main/resources/mapper/product/ProductSkuMapper.xml @@ -1,7 +1,6 @@ - + + + + + +