ショッピングカート機能
1. ショッピングカートモジュール
1. カートサービスを作成する
まずカート マイクロサービスを作成し、次に関連する依存関係を追加し、構成を設定し、アノテーションをリリースする必要があります。
<dependencies>
<dependency>
<groupId>com.msb.mall</groupId>
<artifactId>mall-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
次に、プロパティファイルの設定
server.port=40000
spring.application.name=mall-cart
spring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=false
次に、構成センターの構成を追加します: bootstrap.yml ファイル
spring.application.name=mall-cart
spring.cloud.nacos.config.server-addr=192.168.56.100:8848
登録センターの注釈をリリースする
2. Nginxの設定
まず、Windowsのホストに対応するドメイン名を指定します
対応する静的リソースを Nginx の static/cart ディレクトリにコピーします。
次に、Nginx 設定ファイルを変更します。
次に、nginxサービスを再起動します
docker restart nginx
3. ゲートウェイサービスを構成する
Nginx がcart.msb.com
このドメイン名へのアクセスを受信すると、サービスをゲートウェイ サービスにリバース プロキシします。このとき、ゲートウェイ サービスはリクエストをショッピング カート サービスにルーティングする必要があります。ゲートウェイサービスの構成を変更する必要があります
最後に、テンプレート ページ内の静的リソースのパスを調整するだけです。
次に、サービスアクセスを開始します
2. ショッピングカート機能
1.ショッピングカートモード処理
ショッピング カート内のデータがどのように保存されるかについて説明します。ショッピングカート内に複数の商品が表示されます
次に、対応するデータを Redis に保存することを選択できますが、レコード数が多いため、対応するデータの保存構造を慎重に検討する必要があります。
[
{
skuId:1,subTile:'华为',price:666}
,{
skuId:1,subTile:'华为',price:666}
,{
skuId:1,subTile:'华为',price:666}
]
そうすると後から商品の追加や削除、個数を変更する際にリスト内のデータを全て取り出して操作したいデータを見つけてRedisに書き戻す必要があり面倒です。この方法は明らかにお勧めできませんが、現時点では、ハッシュして保存することを検討できます。
このように一つ一つ対応していけば上記よりも柔軟に対応できます。バックエンド サービスに保存する構造は次のとおりです。
Map<String,Map<String,CartItemVo>>
2. ショッピングカートVO
ショッピング カートの情報ストレージのために、対応する 2 つの VO オブジェクトを作成します。
package com.msb.mall.vo;
import java.math.BigDecimal;
import java.util.List;
/**
* 购物车中的商品信息
*/
public class CartItem {
// 商品的编号 SkuId
private Long skuId;
// 商品的图片
private String image;
// 商品的标题
private String title;
// 是否选中
private boolean check = true;
// 商品的销售属性
private List<String> skuAttr;
// 商品的单价
private BigDecimal price;
// 购买的数量
private Integer count;
// 商品的总价
private BigDecimal totalPrice;
public Long getSkuId() {
return skuId;
}
public void setSkuId(Long skuId) {
this.skuId = skuId;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isCheck() {
return check;
}
public void setCheck(boolean check) {
this.check = check;
}
public List<String> getSkuAttr() {
return skuAttr;
}
public void setSkuAttr(List<String> 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() {
// 商品的总价 price * count
return price.multiply(new BigDecimal(count));
}
}
カート
package com.msb.mall.vo;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
/**
* 购物车
*/
public class Cart {
// 购物车中的商品种类
private Integer countType;
// 选中的商品数量
private Integer checkCountNum;
// 选中商品的总价
private BigDecimal totalAmount;
// 购物中存储的商品信息
private List<CartItem> items;
public Integer getCountType() {
return items.size();
}
public Integer getCheckCountNum() {
Integer count = 0;
for (CartItem item : items) {
if (item.isCheck()){
count += item.getCount();
}
}
return count;
}
public BigDecimal getTotalAmount() {
BigDecimal amount = new BigDecimal(0);
for (CartItem item : items) {
if (item.isCheck()){
amount = amount.add(item.getTotalPrice());
}
}
return amount;
}
public List<CartItem> getItems() {
return items;
}
public void setItems(List<CartItem> items) {
this.items = items;
}
}
3. 認証情報
ショッピング カート サービスの現在のログイン ユーザー情報に基づいて、Redis の対応するショッピング カート情報をクエリする必要があります。まず、Redis の関連する依存関係をインポートする必要があります。同時に、認証済みのセッション情報を共有するために、前述の SpringSession を使用する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
プロパティファイル情報の追加
server.port=40000
spring.application.name=mall-cart
spring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=false
spring.redis.host=192.168.56.100
spring.redis.port=6379
spring.thymeleaf.enabled=false
spring.session.store-type=redis
server.servlet.session.timeout=30m
spring.session.redis.namespace=spring:session
Cookie設定情報を追加する
@Configuration
public class MySessionConfig {
/**
* 自定义Cookie的配置
* @return
*/
@Bean
public CookieSerializer cookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setDomainName("msb.com"); // 设置session对应的一级域名
cookieSerializer.setCookieName("msbsession");
return cookieSerializer;
}
/**
* 对存储在Redis中的数据指定序列化的方式
* @return
*/
@Bean
public RedisSerializer<Object> redisSerializer(){
return new GenericJackson2JsonRedisSerializer();
}
}
カスタムインターセプターを追加する
/**
* 我们自定义的拦截器:帮助我们获取当前登录的用户信息
* 通过Session共享获取的
*/
public class AuthInterceptor implements HandlerInterceptor {
// 本地线程对象 Map<thread,Object>
public static ThreadLocal<MemberVO> threadLocal = new ThreadLocal();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 通过HttpSession获取当前登录的用户信息
HttpSession session = request.getSession();
Object attribute = session.getAttribute(AuthConstant.AUTH_SESSION_REDIS);
if(attribute != null){
MemberVO memberVO = (MemberVO) attribute;
threadLocal.set(memberVO);
}
return true;
}
}
レジスタインターセプタ
@Configuration
public class MyWebInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");
}
}
次に、ログインしてコントローラー サービス テストにアクセスします。
4. ページジャンプ
製品詳細ページから [ショッピング カートの追加] をクリックして、ショッピング カートを追加するロジックを完了します。
5. ショッピング カート ロジックを追加する
具体的には、ショッピング カートを追加するロジックと、サービス内の製品の SKUid と数量を取得した後に実装するロジックを完成させます。
特定のコアコード
/**
* 把商品添加到购物车中
* @param skuId
* @param num
* @return
*/
@Override
public CartItem addCart(Long skuId, Integer num) throws Exception {
BoundHashOperations<String, Object, Object> hashOperations = getCartKeyOperation();
// 如果Redis存储在商品的信息,那么我们只需要修改商品的数量就可以了
Object o = hashOperations.get(skuId.toString());
if(o != null){
// 说明已经存在了这个商品那么修改商品的数量即可
String json = (String) o;
CartItem item = JSON.parseObject(json, CartItem.class);
item.setCount(item.getCount()+num);
hashOperations.put(skuId.toString(),JSON.toJSONString(item));
return item;
}
CartItem item = new CartItem();
CompletableFuture future1 = CompletableFuture.runAsync(()->{
// 1.远程调用获取 商品信息
R r = productFeignService.info(skuId);
String skuInfoJSON = (String) r.get("skuInfoJSON");
SkuInfoVo vo = JSON.parseObject(skuInfoJSON,SkuInfoVo.class);
item.setCheck(true);
item.setCount(num);
item.setPrice(vo.getPrice());
item.setImage(vo.getSkuDefaultImg());
item.setSkuId(skuId);
item.setTitle(vo.getSkuTitle());
},executor);
CompletableFuture future2 = CompletableFuture.runAsync(()->{
// 2.获取商品的销售属性
List<String> skuSaleAttrs = productFeignService.getSkuSaleAttrs(skuId);
item.setSkuAttr(skuSaleAttrs);
},executor);
CompletableFuture.allOf(future1,future2).get();
// 3.把数据存储在Redis中
String json = JSON.toJSONString(item);
hashOperations.put(skuId.toString(),json);
return item;
}
private BoundHashOperations<String, Object, Object> getCartKeyOperation() {
// hash key: cart:1 skuId:cartItem
MemberVO memberVO = AuthInterceptor.threadLocal.get();
String cartKey = CartConstant.CART_PERFIX + memberVO.getId();
BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(cartKey);
return hashOperations;
}
6. ショッピングカートのホームページ
ショッピング カートに商品を追加した後、[チェックアウト] をクリックしてショッピング カート ページに移動し、現在ログインしているすべてのユーザーのショッピング カートの商品情報をバックグラウンドで照会し、ページに表示する必要があります。
次に、ページ内のデータを処理します