From c0eabe572bcfd9d425df974bef887495560ecae5 Mon Sep 17 00:00:00 2001 From: Kirk Lin Date: Sat, 10 Jul 2021 15:57:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=9F=8E=E4=B8=9A=E5=8A=A1-->=20?= =?UTF-8?q?=E8=B4=AD=E7=89=A9=E8=BD=A6=20-=20ThreadLocal=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E9=89=B4=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kkmall/cart/KkmallCartApplication.java | 2 + .../lkk/kkmall/cart/config/CartWebConfig.java | 22 ++++ .../cart/controller/CartController.java | 38 +++++++ .../cart/interceptor/CartInterceptor.java | 70 ++++++++++++ .../name/lkk/kkmall/cart/to/UserInfoTo.java | 32 ++++++ .../java/name/lkk/kkmall/cart/vo/Cart.java | 87 +++++++++++++++ .../name/lkk/kkmall/cart/vo/CartItem.java | 102 ++++++++++++++++++ .../lkk/common/constant/CartConstant.java | 18 ++-- .../lkk/common/constant/DomainConstant.java | 14 +++ 9 files changed, 378 insertions(+), 7 deletions(-) create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/config/CartWebConfig.java create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/controller/CartController.java create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/interceptor/CartInterceptor.java create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/to/UserInfoTo.java create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/Cart.java create mode 100644 kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/CartItem.java create mode 100644 kkmall-common/src/main/java/name/lkk/common/constant/DomainConstant.java diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/KkmallCartApplication.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/KkmallCartApplication.java index 75258af..04aab6c 100644 --- a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/KkmallCartApplication.java +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/KkmallCartApplication.java @@ -4,9 +4,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; @SpringBootApplication @EnableDiscoveryClient +@EnableRedisHttpSession @EnableFeignClients("name.lkk.kkmall.cart.feign") public class KkmallCartApplication { diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/config/CartWebConfig.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/config/CartWebConfig.java new file mode 100644 index 0000000..ea632a9 --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/config/CartWebConfig.java @@ -0,0 +1,22 @@ +package name.lkk.kkmall.cart.config; + +import name.lkk.kkmall.cart.interceptor.CartInterceptor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author: kirklin + * @date: 2021/7/10 3:33 下午 + * @description: 添加拦截器 + */ +@Configuration +public class CartWebConfig implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + WebMvcConfigurer.super.addInterceptors(registry); + registry.addInterceptor(new CartInterceptor()).addPathPatterns("/**"); + + } +} diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/controller/CartController.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/controller/CartController.java new file mode 100644 index 0000000..e144f6e --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/controller/CartController.java @@ -0,0 +1,38 @@ +package name.lkk.kkmall.cart.controller; + +import lombok.extern.slf4j.Slf4j; +import name.lkk.kkmall.cart.interceptor.CartInterceptor; +import name.lkk.kkmall.cart.to.UserInfoTo; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author: kirklin + * @date: 2021/7/10 3:39 下午 + * @description: + */ +@Slf4j +@Controller +public class CartController { + + /** + * 去购物车页面的请求 + * 浏览器有一个cookie:user-key 标识用户的身份,一个月过期 + * 如果第一次使用jd的购物车功能,都会给一个临时的用户身份: + * 浏览器以后保存,每次访问都会带上这个cookie; + *

+ * 登录:session有 + * 没登录:按照cookie里面带来user-key来做 + * 第一次,如果没有临时用户,自动创建一个临时用户 + * + * @return + */ + @GetMapping({"/", "/cart.html"}) + public String carListPage() { + //快速得到用户信息:id,user-key + UserInfoTo userInfoTo = CartInterceptor.userInfoToThreadLocal.get(); + log.info(userInfoTo.toString()); + return "cartList"; + } + +} diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/interceptor/CartInterceptor.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/interceptor/CartInterceptor.java new file mode 100644 index 0000000..affec47 --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/interceptor/CartInterceptor.java @@ -0,0 +1,70 @@ +package name.lkk.kkmall.cart.interceptor; + +import name.lkk.common.constant.AuthServerConstant; +import name.lkk.common.constant.CartConstant; +import name.lkk.common.constant.DomainConstant; +import name.lkk.common.vo.MemberRsepVo; +import name.lkk.kkmall.cart.to.UserInfoTo; +import org.springframework.util.ObjectUtils; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.UUID; + +/** + * @author: kirklin + * @date: 2021/7/10 3:12 下午 + * @description: 购物车拦截器。在执行业务之前 判断用户是否登录,并使用ThreadLocal封装UserInfoTo + */ +public class CartInterceptor implements HandlerInterceptor { + public static ThreadLocal userInfoToThreadLocal = new InheritableThreadLocal<>(); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + UserInfoTo userInfoTo = new UserInfoTo(); + HttpSession session = request.getSession(); + MemberRsepVo user = (MemberRsepVo) session.getAttribute(AuthServerConstant.LOGIN_USER); + if (user != null) { + //用户已经登陆了 + userInfoTo.setUsername(user.getUsername()); + userInfoTo.setUserId(user.getId()); + } + Cookie[] cookies = request.getCookies(); + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + String name = cookie.getName(); + if (name.equals(CartConstant.TEMP_USER_COOKIE_NAME)) { + userInfoTo.setUserKey(cookie.getValue()); + userInfoTo.setTempUser(true); + } + } + } + if (ObjectUtils.isEmpty(userInfoTo.getUserKey())) { + String uuid = UUID.randomUUID().toString().replace("-", ""); + userInfoTo.setUserKey(uuid); + } + userInfoToThreadLocal.set(userInfoTo); + return HandlerInterceptor.super.preHandle(request, response, handler); + } + + /** + * 执行完毕之后分配临时用户让浏览器保存 + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); + UserInfoTo userInfoTo = userInfoToThreadLocal.get(); + userInfoToThreadLocal.remove(); + if (!userInfoTo.isTempUser()) { + Cookie cookie = new Cookie(CartConstant.TEMP_USER_COOKIE_NAME, userInfoTo.getUserKey()); + // 设置这个cookie作用域 过期时间 + cookie.setDomain(DomainConstant.MALL_DOMAIN); + cookie.setMaxAge(CartConstant.TEMP_USER_COOKIE_TIME_OUT); + response.addCookie(cookie); + } + } +} diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/to/UserInfoTo.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/to/UserInfoTo.java new file mode 100644 index 0000000..1c6d452 --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/to/UserInfoTo.java @@ -0,0 +1,32 @@ +package name.lkk.kkmall.cart.to; + +import lombok.Data; +import lombok.ToString; + +/** + * @author kirklin + */ +@ToString +@Data +public class UserInfoTo { + + /** + * 存储已登录用户在数据库中的ID + */ + private Long userId; + + /** + * 存储用户名 + */ + private String username; + + /** + * 配分一个临时的user-key + */ + private String userKey; + + /** + * 判断是否是临时用户 + */ + private boolean tempUser = false; +} diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/Cart.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/Cart.java new file mode 100644 index 0000000..bff565d --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/Cart.java @@ -0,0 +1,87 @@ +package name.lkk.kkmall.cart.vo; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 购物车,!本VO的GET,SET方法非默认实现。 + */ +public class Cart { + + private List items; + + /** + * 商品的数量 + */ + private Integer countNum; + + /** + * 商品的类型数量 + */ + private Integer countType; + + /** + * 整个购物车的总价 + */ + private BigDecimal totalAmount; + + /** + * 减免的价格 + */ + private BigDecimal reduce = new BigDecimal("0.00"); + + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + /** + * 计算商品的总量 + * + * @return + */ + public Integer getCountNum() { + int count = 0; + if (this.items != null && this.items.size() > 0) { + for (CartItem item : this.items) { + count += item.getCount(); + } + } + return count; + } + + public Integer getCountType() { + int count = 0; + if (this.items != null && this.items.size() > 0) { + for (CartItem item : this.items) { + count += 1; + } + } + return count; + } + + public BigDecimal getTotalAmount() { + BigDecimal amount = new BigDecimal("0"); + if (this.items != null && this.items.size() > 0) { + for (CartItem item : this.items) { + if (item.getCheck()) { + BigDecimal totalPrice = item.getTotalPrice(); + amount = amount.add(totalPrice); + } + } + } + return amount.subtract(this.getReduce()); + } + + public BigDecimal getReduce() { + return reduce; + } + + public void setReduce(BigDecimal reduce) { + this.reduce = reduce; + } +} diff --git a/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/CartItem.java b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/CartItem.java new file mode 100644 index 0000000..d9e5552 --- /dev/null +++ b/kkmall-cart/src/main/java/name/lkk/kkmall/cart/vo/CartItem.java @@ -0,0 +1,102 @@ +package name.lkk.kkmall.cart.vo; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 购物车商品项,!本VO的GET,SET方法非默认实现。 + */ +public class CartItem { + + private Long skuId; + + /** + * 是否被选中 + */ + private Boolean check = true; + + private String title; + + private String image; + + private List skuAttr; + + /** + * 价格 + */ + private BigDecimal price; + + /** + * 数量 + */ + private Integer count; + + private BigDecimal totalPrice; + + public Long getSkuId() { + return skuId; + } + + public void setSkuId(Long skuId) { + this.skuId = skuId; + } + + public Boolean getCheck() { + return check; + } + + public void setCheck(Boolean check) { + this.check = check; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public List getSkuAttr() { + return skuAttr; + } + + public void setSkuAttr(List skuAttr) { + this.skuAttr = skuAttr; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + /** + * 手动计算总价 + */ + public BigDecimal getTotalPrice() { + return this.price.multiply(new BigDecimal("" + this.count)); + } + + public void setTotalPrice(BigDecimal totalPrice) { + this.totalPrice = totalPrice; + } +} diff --git a/kkmall-common/src/main/java/name/lkk/common/constant/CartConstant.java b/kkmall-common/src/main/java/name/lkk/common/constant/CartConstant.java index c54d167..5b885a0 100644 --- a/kkmall-common/src/main/java/name/lkk/common/constant/CartConstant.java +++ b/kkmall-common/src/main/java/name/lkk/common/constant/CartConstant.java @@ -1,13 +1,17 @@ package name.lkk.common.constant; /** - *

Title: CartConstant

- * Description: - * date:2020/6/27 22:37 + * 购物车常量 + * + * @author kirklin */ public class CartConstant { - - public static final String TEMP_USER_COOKIE_NAME = "user-key"; - - public static final int TEMP_USER_COOKIE_TIME_OUT = 60 * 60 * 24 * 30; + /** + * 购物车临时用户COOKIE + */ + public static final String TEMP_USER_COOKIE_NAME = "user-key"; + /** + * 购物车临时用户COOKIE过期时间 + */ + public static final int TEMP_USER_COOKIE_TIME_OUT = 60 * 60 * 24 * 30; } diff --git a/kkmall-common/src/main/java/name/lkk/common/constant/DomainConstant.java b/kkmall-common/src/main/java/name/lkk/common/constant/DomainConstant.java new file mode 100644 index 0000000..883511c --- /dev/null +++ b/kkmall-common/src/main/java/name/lkk/common/constant/DomainConstant.java @@ -0,0 +1,14 @@ +package name.lkk.common.constant; + +/** + * @author: kirklin + * @date: 2021/7/10 3:29 下午 + * @description: 域名常量 + */ +public class DomainConstant { + + public static final String MALL_DOMAIN = "kkmall.com"; + public static final String MALL_HTTP_DOMAIN = "http://kkmall.com"; + public static final String MALL_HTTPS_DOMAIN = "https://kkmall.com"; + +}