Skip to content

Commit

Permalink
添加购物车模块
Browse files Browse the repository at this point in the history
  • Loading branch information
hanggegreat committed Feb 24, 2019
1 parent 6b2b367 commit 21ab6fd
Show file tree
Hide file tree
Showing 21 changed files with 359 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ ly:
secret: leyou@Login(Auth}*^31)&lollipop% # 登录校验的密钥
pubKeyPath: G:/test/rsa.pub # 公钥地址
priKeyPath: G:/test/rsa.pri # 私钥地址
expire: 30 # 过期时间,单位分钟
expire: 1800 # 过期时间,单位秒
cookieName: LY_TOKEN
42 changes: 42 additions & 0 deletions ly-cart/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>leyou</artifactId>
<groupId>cn.lollipop</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>ly-cart</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.lollipop</groupId>
<artifactId>ly-auth-common</artifactId>
<version>${leyou-latest.version}</version>
</dependency>
<dependency>
<groupId>cn.lollipop</groupId>
<artifactId>ly-common</artifactId>
<version>${leyou-latest.version}</version>
</dependency>
</dependencies>
</project>
18 changes: 18 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/CartApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cn.lollipop;

import cn.lollipop.cart.config.JwtProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableConfigurationProperties(JwtProperties.class)
public class CartApplication {
public static void main(String[] args) {
SpringApplication.run(CartApplication.class, args);
}
}
25 changes: 25 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/config/JwtProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cn.lollipop.cart.config;

import cn.lollipop.auth.utils.RsaUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;
import java.security.PublicKey;

@Data
@Slf4j
@ConfigurationProperties(prefix = "ly.jwt")
public class JwtProperties {
private String pubKeyPath;
private String cookieName;

private PublicKey publicKey;

// 实例化完成后进行公钥的读取
@PostConstruct
public void init() throws Exception {
publicKey = RsaUtils.getPublicKey(pubKeyPath);
}
}
22 changes: 22 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/config/MvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cn.lollipop.cart.config;

import cn.lollipop.cart.interceptor.UserInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {
private final UserInterceptor userInterceptor;

@Autowired
public MvcConfig(UserInterceptor userInterceptor) {
this.userInterceptor = userInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor).addPathPatterns("/**");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cn.lollipop.cart.interceptor;

import cn.lollipop.auth.pojo.UserInfo;
import cn.lollipop.auth.utils.JwtUtils;
import cn.lollipop.cart.config.JwtProperties;
import cn.lollipop.cart.utils.ThreadLocalUtils;
import cn.lollipop.common.ExceptionConstant;
import cn.lollipop.common.exception.LyException;
import cn.lollipop.common.util.CookieUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class UserInterceptor implements HandlerInterceptor {
private final JwtProperties prop;

@Autowired
public UserInterceptor(JwtProperties prop) {
this.prop = prop;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取Cookie中的token
String token = CookieUtils.getCookieValue(request, prop.getCookieName());
try {
// 解析token
UserInfo user = JwtUtils.getInfoFromToken(token, prop.getPublicKey());
ThreadLocalUtils.set(user);
return true;
} catch (Exception e) {
log.error("[购物车服务],用户认证失败!");
throw new LyException(ExceptionConstant.UNAUTHORIZED);
}
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ThreadLocalUtils.remove();
}
}
15 changes: 15 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/pojo/Cart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cn.lollipop.cart.pojo;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Cart {
private Long skuId;// 商品id
private String title;// 标题
private String image;// 图片
private Long price;// 加入购物车时的价格
private Integer num;// 购买数量
private String ownSpec;// 商品规格参数
}
61 changes: 61 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/service/CartService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cn.lollipop.cart.service;

import cn.lollipop.auth.pojo.UserInfo;
import cn.lollipop.cart.pojo.Cart;
import cn.lollipop.cart.utils.ThreadLocalUtils;
import cn.lollipop.common.ExceptionConstant;
import cn.lollipop.common.exception.LyException;
import cn.lollipop.common.util.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartService {
private final StringRedisTemplate redisTemplate;

private static final String KEY_PREFIX = "cart:user:id:";

@Autowired
public CartService(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}

public void addCart(Cart cart) {
// 获取当前登录用户
UserInfo user = ThreadLocalUtils.get();
// key
String key = KEY_PREFIX + user.getId();
// hashKey
String hashKey = String.valueOf(cart.getSkuId());
int num = cart.getNum();

BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(key);
// 判断当前购物车商品是否存在
if (operations.hasKey(hashKey)) {
// 修改数量
String json = operations.get(hashKey).toString();
cart = JsonUtils.parse(json, Cart.class);
cart.setNum(num + cart.getNum());
}
operations.put(hashKey, JsonUtils.serialize(cart));
}

public List<Cart> queryCartList() {
// 获取当前登录用户
UserInfo user = ThreadLocalUtils.get();
// key
String key = KEY_PREFIX + user.getId();
if (!redisTemplate.hasKey(key)) {
throw new LyException(ExceptionConstant.CART_NOT_FOUND);
}

BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(key);
return operations.values().stream()
.map(o -> JsonUtils.parse(o.toString(), Cart.class)).collect(Collectors.toList());
}
}
22 changes: 22 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/utils/ThreadLocalUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cn.lollipop.cart.utils;

import cn.lollipop.auth.pojo.UserInfo;

public class ThreadLocalUtils {
private static final ThreadLocal<UserInfo> threadLocal = new ThreadLocal<>();

private ThreadLocalUtils() {
}

public static void set(UserInfo user) {
threadLocal.set(user);
}

public static void remove() {
threadLocal.remove();
}

public static UserInfo get() {
return threadLocal.get();
}
}
45 changes: 45 additions & 0 deletions ly-cart/src/main/java/cn/lollipop/cart/web/CartController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cn.lollipop.cart.web;

import cn.lollipop.cart.pojo.Cart;
import cn.lollipop.cart.service.CartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class CartController {
private final CartService cartService;

@Autowired
public CartController(CartService cartService) {
this.cartService = cartService;
}

/**
* 新增购物车
*
* @param cart
* @return
*/
@PostMapping
public ResponseEntity<Void> addCart(@RequestBody Cart cart) {
cartService.addCart(cart);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

/**
* 查询购物车
*
* @return
*/
@GetMapping("list")
public ResponseEntity<List<Cart>> queryCartList() {
return ResponseEntity.ok(cartService.queryCartList());
}
}
19 changes: 19 additions & 0 deletions ly-cart/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
server:
port: 8088
spring:
application:
name: cart-service
redis:
host: 192.168.161.101
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka
registry-fetch-interval-seconds: 10
instance:
prefer-ip-address: true
ip-address: 127.0.0.1
ly:
jwt:
pubKeyPath: G:/test/rsa.pub # 公钥地址
cookieName: LY_TOKEN # cookie的名称
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public enum ExceptionConstant {
GOODS_DETAIL_NOT_FOUND(404, "商品详细信息不存在!"),
GOODS_STOCK_NOT_FOUND(404, "商品库存信息不存在!"),
CREATE_TOKEN_ERROR(500, "用户凭证创建失败!"),
UNAUTHORIZED(403, "未授权用户");
UNAUTHORIZED(403, "未授权用户"),
CART_NOT_FOUND(404, "购物车为空");

private int code;
private String msg;
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions ly-gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ zuul:
search-service: /search/** # 搜索微服务
user-service: /user/** # 用户微服务
auth-service: /auth/** # 授权中心微服务
cart-service: /cart/** # 购物车微服务
upload-service: # 文件上传微服务
path: /upload/**
serviceId: upload-service
Expand Down
1 change: 1 addition & 0 deletions ly-gateway/target/classes/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ zuul:
search-service: /search/** # 搜索微服务
user-service: /user/** # 用户微服务
auth-service: /auth/** # 授权中心微服务
cart-service: /cart/** # 购物车微服务
upload-service: # 文件上传微服务
path: /upload/**
serviceId: upload-service
Expand Down
Loading

0 comments on commit 21ab6fd

Please sign in to comment.