文章目录

  • 0.学习目标
  • 1.搭建购物车服务
    • 1.1.创建module
    • 1.2.pom依赖
    • 1.3.配置文件
    • 1.4.启动类
  • 2.购物车功能分析
    • 2.1.需求
    • 2.2.流程图
  • 3.未登录购物车
    • 3.1.准备
      • 3.1.1购物车的数据结构
      • 3.1.2.web本地存储
        • 什么是web本地存储?
        • LocalStorage的用法
      • 3.1.3.获取num
    • 3.2.添加购物车
      • 3.2.1.点击事件
      • 3.2.2.获取数量,添加购物车
    • 3.3.查询购物车
      • 3.3.1.校验用户登录
      • 3.3.2.查询购物车
      • 3.5.2.渲染到页面
    • 3.6.修改数量
    • 3.7.删除商品
    • 3.8.选中商品
      • 3.8.1.选中一个
      • 3.8.2.初始化全选
      • 3.8.3.总价格
  • 4.已登录购物车
    • 4.1.添加登录校验
      • 4.1.1.引入JWT相关依赖
      • 4.1.2.配置公钥
      • 4.1.3.加载公钥
      • 4.1.4.编写拦截器
      • 4.1.5.配置拦截器
    • 4.2.后台购物车设计
    • 4.3.添加商品到购物车
      • 4.3.1.页面发起请求
      • 4.3.2.编写controller
      • 4.3.3.CartService
      • 4.3.4.GoodClient
      • 4.3.5.结果
    • 4.4.查询购物车
      • 4.4.1.页面发起请求
      • 4.4.2.后台实现
      • 4.4.3.测试
    • 4.5.修改商品数量
      • 4.5.1.页面发起请求
      • 4.5.2.后台实现
    • 4.6.删除购物车商品
      • 4.6.1.页面发起请求
      • 4.6.2.后台实现
  • 5.登录后购物车合并(作业)
    • 5.1 修改前台
    • 5.2 修改后台

0.学习目标

1.实现未登录状态的购物车

2.实现登陆状态下的购物车

源码及笔记:
链接:https://pan.baidu.com/s/166zDGT7MYiPCh3o70tjSkA
提取码:zau1

1.搭建购物车服务

1.1.创建module

1.2.pom依赖

<?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>com.leyou.parent</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.leyou.service</groupId><artifactId>ly-cart</artifactId><version>1.0.0-SNAPSHOT</version><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></dependencies>
</project>

1.3.配置文件

server:port: 8088
spring:application:name: cart-serviceredis:host: 192.168.56.101
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekaregistry-fetch-interval-seconds: 10instance:lease-renewal-interval-in-seconds: 5lease-expiration-duration-in-seconds: 15

1.4.启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LeyouCartApplication {public static void main(String[] args) {SpringApplication.run(LeyouCartApplication.class, args);}
}

2.购物车功能分析

2.1.需求

需求描述:

  • 用户可以在登录状态下将商品添加到购物车

    • 放入数据库
    • mongodb
    • 放入redis(采用)
  • 用户可以在未登录状态下将商品添加到购物车
    • 放入localstorage
    • cookie
    • webSQL
  • 用户可以使用购物车一起结算下单
  • 用户可以查询自己的购物车
  • 用户可以在购物车中修改购买商品的数量。
  • 用户可以在购物车中删除商品。
  • 在购物车中展示商品优惠信息
  • 提示购物车商品价格变化

2.2.流程图

这幅图主要描述了两个功能:新增商品到购物车、查询购物车。

新增商品:

  • 判断是否登录

    • 是:则添加商品到后台Redis中
    • 否:则添加商品到本地的Localstorage

无论哪种新增,完成后都需要查询购物车列表:

  • 判断是否登录

    • 否:直接查询localstorage中数据并展示
    • 是:已登录,则需要先看本地是否有数据,
      • 有:需要提交到后台添加到redis,合并数据,而后查询
      • 否:直接去后台查询redis,而后返回

3.未登录购物车

3.1.准备

3.1.1购物车的数据结构

首先分析一下未登录购物车的数据结构。

我们看下页面展示需要什么数据:

因此每一个购物车信息,都是一个对象,包含:

{skuId:2131241,title:"小米6",image:"",price:190000,num:1,ownSpec:"{"机身颜色":"陶瓷黑尊享版","内存":"6GB","机身存储":"128GB"}"
}

另外,购物车中不止一条数据,因此最终会是对象的数组。即:

[{...},{...},{...}
]

3.1.2.web本地存储

知道了数据结构,下一个问题,就是如何保存购物车数据。前面我们分析过,可以使用Localstorage来实现。Localstorage是web本地存储的一种,那么,什么是web本地存储呢?

什么是web本地存储?

web本地存储主要有两种方式:

  • LocalStorage:localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用。
  • SessionStorage:sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

LocalStorage的用法

语法非常简单:

localStorage.setItem("key","value"); // 存储数据
localStorage.getItem("key"); // 获取数据
localStorage.removeItem("key"); // 删除数据

注意:localStorage和SessionStorage都只能保存字符串

不过,在我们的common.js中,已经对localStorage进行了简单的封装:

示例:

3.1.3.获取num

添加购物车需要知道购物的数量,所以我们需要获取数量大小。我们在Vue中定义num,保存数量:

然后将num与页面的input框绑定,同时给+-的按钮绑定事件:

编写方法:

3.2.添加购物车

3.2.1.点击事件

我们看下商品详情页:

现在点击加入购物车会跳转到购物车成功页面。

不过我们不这么做,我们绑定点击事件,然后实现添加购物车功能。

addCart方法中判断用户的登录状态:

addCart(){ly.http.get("/auth/verify").then(res=>{// 已登录发送信息到后台,保存到redis中}).catch(()=>{// 未登录保存在浏览器本地的localStorage中})
}

3.2.2.获取数量,添加购物车

addCart(){ly.verifyUser().then(res=>{// 已登录发送信息到后台,保存到redis中}).catch(()=>{// 未登录保存在浏览器本地的localStorage中// 1、查询本地购物车let carts = ly.store.get("carts") || [];let cart = carts.find(c=>c.skuId===this.sku.id);// 2、判断是否存在if (cart) {// 3、存在更新数量cart.num += this.num;} else {// 4、不存在,新增cart = {skuId: this.sku.id,title: this.sku.title,price: this.sku.price,image: this.sku.images,num: this.num,ownSpec: this.ownSpec}carts.push(cart);}// 把carts写回localstoragely.store.set("carts", carts);// 跳转window.location.href = "http://www.leyou.com/cart.html";});
}

结果:

添加完成后,页面会跳转到购物车结算页面:cart.html

3.3.查询购物车

3.3.1.校验用户登录

因为会多次校验用户登录状态,因此我们封装一个校验的方法:

在common.js中:

在页面item.html中使用该方法:

3.3.2.查询购物车

页面加载时,就应该去查询购物车。

var cartVm = new Vue({el: "#cartApp",data: {ly,carts: [],// 购物车数据},created() {this.loadCarts();},methods: {loadCarts() {// 先判断登录状态ly.verifyUser().then(() => {// 已登录}).catch(() => {// 未登录this.carts = ly.store.get("carts") || [];this.selected = this.carts;})}}components: {shortcut: () => import("/js/pages/shortcut.js")}
})

刷新页面,查看控制台Vue实例:

3.5.2.渲染到页面

接下来,我们在页面中展示carts的数据:

要注意,价格的展示需要进行格式化,这里使用的是我们在common.js中定义的formatPrice方法

效果:

3.6.修改数量

我们给页面的 +-绑定点击事件,修改num 的值:

两个事件:

    increment(c) {c.num++;ly.verifyUser().then(() => {// TODO 已登录,向后台发起请求}).catch(() => {// 未登录,直接操作本地数据ly.store.set("carts", this.carts);})},decrement(c) {if (c.num <= 1) {return;}c.num--;ly.verifyUser().then(() => {// TODO 已登录,向后台发起请求}).catch(() => {// 未登录,直接操作本地数据ly.store.set("carts", this.carts);})}

3.7.删除商品

给删除按钮绑定事件:

点击事件中删除商品:

deleteCart(i){ly.verifyUser().then(res=>{// TODO,已登录购物车}).catch(()=>{// 未登录购物车this.carts.splice(i, 1);ly.store.set("carts", this.carts);})
}

3.8.选中商品

在页面中,每个购物车商品左侧,都有一个复选框,用户可以选择部分商品进行下单,而不一定是全部:

我们定义一个变量,记录所有被选中的商品:

3.8.1.选中一个

我们给商品前面的复选框与selected绑定,并且指定其值为当前购物车商品:

3.8.2.初始化全选

我们在加载完成购物车查询后,初始化全选:

3.8.3.总价格

然后编写一个计算属性,计算出选中商品总价格:

computed: {totalPrice() {return ly.formatPrice(this.selected.reduce((c1, c2) => c1 + c2.num * c2.price, 0));}
}

在页面中展示总价格:

效果:

4.已登录购物车

接下来,我们完成已登录购物车。

在刚才的未登录购物车编写时,我们已经预留好了编写代码的位置,逻辑也基本一致。

4.1.添加登录校验

购物车系统只负责登录状态的购物车处理,因此需要添加登录校验,我们通过JWT鉴权即可实现。

4.1.1.引入JWT相关依赖

我们引入之前写的鉴权工具:leyou-auth-common

<dependency><groupId>com.leyou.auth</groupId><artifactId>leyou-auth-common</artifactId><version>1.0.0-SNAPSHOT</version>
</dependency>

4.1.2.配置公钥

leyou:jwt:pubKeyPath: C:/tmp/rsa/rsa.pub # 公钥地址cookieName: LY_TOKEN # cookie的名称

4.1.3.加载公钥

代码:

@ConfigurationProperties(prefix = "leyou.jwt")
public class JwtProperties {private String pubKeyPath;// 公钥private PublicKey publicKey; // 公钥private String cookieName;private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);@PostConstructpublic void init(){try {// 获取公钥和私钥this.publicKey = RsaUtils.getPublicKey(pubKeyPath);} catch (Exception e) {logger.error("初始化公钥失败!", e);throw new RuntimeException();}}public String getPubKeyPath() {return pubKeyPath;}public void setPubKeyPath(String pubKeyPath) {this.pubKeyPath = pubKeyPath;}public PublicKey getPublicKey() {return publicKey;}public void setPublicKey(PublicKey publicKey) {this.publicKey = publicKey;}public String getCookieName() {return cookieName;}public void setCookieName(String cookieName) {this.cookieName = cookieName;}
}

4.1.4.编写拦截器

因为很多接口都需要进行登录,我们直接编写SpringMVC拦截器,进行统一登录校验。同时,我们还要把解析得到的用户信息保存起来,以便后续的接口可以使用。

代码:

public class LoginInterceptor extends HandlerInterceptorAdapter {private JwtProperties jwtProperties;// 定义一个线程域,存放登录用户private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();public LoginInterceptor(JwtProperties jwtProperties) {this.jwtProperties = jwtProperties;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 查询tokenString token = CookieUtils.getCookieValue(request, "LY_TOKEN");if (StringUtils.isBlank(token)) {// 未登录,返回401response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}// 有token,查询用户信息try {// 解析成功,证明已经登录UserInfo user = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());// 放入线程域tl.set(user);return true;} catch (Exception e){// 抛出异常,证明未登录,返回401response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {tl.remove();}public static UserInfo getLoginUser() {return tl.get();}
}

注意:

  • 这里我们使用了ThreadLocal来存储查询到的用户信息,线程内共享,因此请求到达Controller后可以共享User
  • 并且对外提供了静态的方法:getLoginUser()来获取User信息

4.1.5.配置拦截器

配置SpringMVC,使过滤器生效:

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {@Autowiredprivate JwtProperties jwtProperties;@Beanpublic LoginInterceptor loginInterceptor() {return new LoginInterceptor(jwtProperties);}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");}
}

4.2.后台购物车设计

当用户登录时,我们需要把购物车数据保存到后台,可以选择保存在数据库。但是购物车是一个读写频率很高的数据。因此我们这里选择读写效率比较高的Redis作为购物车存储。

Redis有5种不同数据结构,这里选择哪一种比较合适呢?Map<String, List>

  • 首先不同用户应该有独立的购物车,因此购物车应该以用户的作为key来存储,Value是用户的所有购物车信息。这样看来基本的k-v结构就可以了。
  • 但是,我们对购物车中的商品进行增、删、改操作,基本都需要根据商品id进行判断,为了方便后期处理,我们的购物车也应该是k-v结构,key是商品id,value才是这个商品的购物车信息。

综上所述,我们的购物车结构是一个双层Map:Map<String,Map<String,String>>

  • 第一层Map,Key是用户id
  • 第二层Map,Key是购物车中商品id,值是购物车数据

实体类:

public class Cart {private Long userId;// 用户idprivate Long skuId;// 商品idprivate String title;// 标题private String image;// 图片private Long price;// 加入购物车时的价格private Integer num;// 购买数量private String ownSpec;// 商品规格参数public Long getUserId() {return userId;}public void setUserId(Long userId) {this.userId = userId;}public Long getSkuId() {return skuId;}public void setSkuId(Long skuId) {this.skuId = skuId;}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 Long getPrice() {return price;}public void setPrice(Long price) {this.price = price;}public Integer getNum() {return num;}public void setNum(Integer num) {this.num = num;}public String getOwnSpec() {return ownSpec;}public void setOwnSpec(String ownSpec) {this.ownSpec = ownSpec;}
}

4.3.添加商品到购物车

4.3.1.页面发起请求

已登录情况下,向后台添加购物车:

ly.http.post("/cart", {skuId: this.sku.id, num: this.num}).then(res=>{window.location = "http://www.leyou.com/cart.html";
})

这里发起的是Json请求。那么我们后台也要以json接收。

4.3.2.编写controller

先分析一下:

  • 请求方式:新增,肯定是Post
  • 请求路径:/cart ,这个其实是Zuul路由的路径,我们可以不管
  • 请求参数:Json对象,包含skuId和num属性
  • 返回结果:无
@Controller
public class CartController {@Autowiredprivate CartService cartService;/*** 添加购物车** @return*/@PostMappingpublic ResponseEntity<Void> addCart(@RequestBody Cart cart) {this.cartService.addCart(cart);return ResponseEntity.ok().build();}
}

在leyou-gateway中添加路由配置:

4.3.3.CartService

这里我们不访问数据库,而是直接操作Redis。基本思路:

  • 先查询之前的购物车数据
  • 判断要添加的商品是否存在
    • 存在:则直接修改数量后写回Redis
    • 不存在:新建一条数据,然后写入Redis

代码:

@Service
public class CartService {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate GoodsClient goodsClient;static final String KEY_PREFIX = "leyou:cart:uid:";static final Logger logger = LoggerFactory.getLogger(CartService.class);public void addCart(Cart cart) {// 获取登录用户UserInfo user = LoginInterceptor.getLoginUser();// Redis的keyString key = KEY_PREFIX + user.getId();// 获取hash操作对象BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);// 查询是否存在Long skuId = cart.getSkuId();Integer num = cart.getNum();Boolean boo = hashOps.hasKey(skuId.toString());if (boo) {// 存在,获取购物车数据String json = hashOps.get(skuId.toString()).toString();cart = JsonUtils.parse(json, Cart.class);// 修改购物车数量cart.setNum(cart.getNum() + num);} else {// 不存在,新增购物车数据cart.setUserId(user.getId());// 其它商品信息,需要查询商品服务Sku sku = this.goodsClient.querySkuById(skuId);cart.setImage(StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(), ",")[0]);cart.setPrice(sku.getPrice());cart.setTitle(sku.getTitle());cart.setOwnSpec(sku.getOwnSpec());}// 将购物车数据写入redishashOps.put(cart.getSkuId().toString(), JsonUtils.serialize(cart));}
}

需要引入leyou-item-interface依赖:

<dependency><groupId>com.leyou.item</groupId><artifactId>leyou-item-interface</artifactId><version>1.0.0-SNAPSHOT</version>
</dependency>

4.3.4.GoodClient

参照搜索工程,添加GoodClient,提供根据id查询sku的接口:

@FeignClient("item-service")
public interface GoodsClient extends GoodsApi {}

在leyou-item-service中的GoodsController添加方法:

@GetMapping("sku/{id}")
public ResponseEntity<Sku> querySkuById(@PathVariable("id")Long id){Sku sku = this.goodsService.querySkuById(id);if (sku == null){return new ResponseEntity<>(HttpStatus.NOT_FOUND);}return ResponseEntity.ok(sku);
}

在leyou-item-service中的GoodsService添加方法:

public Sku querySkuById(Long id) {return this.skuMapper.selectByPrimaryKey(id);
}

4.3.5.结果

4.4.查询购物车

4.4.1.页面发起请求

购物车页面:cart.html

4.4.2.后台实现

Controller

/*** 查询购物车列表** @return*/
@GetMapping
public ResponseEntity<List<Cart>> queryCartList() {List<Cart> carts = this.cartService.queryCartList();if (carts == null) {return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);}return ResponseEntity.ok(carts);
}

Service

public List<Cart> queryCartList() {// 获取登录用户UserInfo user = LoginInterceptor.getLoginUser();// 判断是否存在购物车String key = KEY_PREFIX + user.getId();if(!this.redisTemplate.hasKey(key)){// 不存在,直接返回return null;}BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);List<Object> carts = hashOps.values();// 判断是否有数据if(CollectionUtils.isEmpty(carts)){return null;}// 查询购物车数据return carts.stream().map(o -> JsonUtils.parse(o.toString(), Cart.class)).collect(Collectors.toList());
}

4.4.3.测试

4.5.修改商品数量

4.5.1.页面发起请求

4.5.2.后台实现

Controller

@PutMapping
public ResponseEntity<Void> updateNum(@RequestBody Cart cart){this.cartService.updateCarts(cart);return ResponseEntity.noContent().build();
}

Service

public void updateCarts(Cart cart) {// 获取登陆信息UserInfo userInfo = LoginInterceptor.getUserInfo();String key = LEYOU_CART_KEY + userInfo.getId();// 获取hash操作对象BoundHashOperations<String, Object, Object> hashOperations = this.redisTemplate.boundHashOps(key);// 获取购物车信息String cartJson = hashOperations.get(cart.getSkuId().toString()).toString();Cart cart1 = JsonUtils.parse(cartJson, Cart.class);// 更新数量cart1.setNum(cart.getNum());// 写入购物车hashOperations.put(cart.getSkuId().toString(), JsonUtils.serialize(cart1));
}

4.6.删除购物车商品

4.6.1.页面发起请求

ly.http.delete("/cart/" + this.carts[index].skuId).then(() => {this.carts.splice(index,1);})

注意:后台成功响应后,要把页面的购物车中数据也删除

4.6.2.后台实现

Controller

@DeleteMapping("{skuId}")
public ResponseEntity<Void> deleteCart(@PathVariable("skuId") String skuId) {this.cartService.deleteCart(skuId);return ResponseEntity.ok().build();
}

Service

public void deleteCart(String skuId) {// 获取登录用户UserInfo user = LoginInterceptor.getLoginUser();String key = KEY_PREFIX + user.getId();BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);hashOps.delete(skuId);
}

5.登录后购物车合并(作业)

已完成,细节需要自己理解,注意细节:

当跳转到购物车页面,查询购物车列表前,需要判断用户登录状态,

  • 如果登录:

    • 首先检查用户的LocalStorage中是否有购物车信息,
    • 如果有,则提交到后台保存,
    • 清空LocalStorage
  • 如果未登录,直接查询即可

5.1 修改前台

5.2 修改后台

Controller

    /*** 合并购物车** @return*/@PutMapping("add")public ResponseEntity<Void> addCartToUser(@RequestBody Cart cart) {this.cartService.addCart(cart);return ResponseEntity.status(HttpStatus.CREATED).build();}

这里service实现方法直接调用添加购物车方法。

【javaWeb微服务架构项目——乐优商城day14】——购物车(实现未登录状态的购物车,实现登陆状态下的购物车,实现未登录状态的购物车合并到登录状态)相关推荐

  1. 【javaWeb微服务架构项目——乐优商城day15】——会调用订单系统接口,实现订单结算功能,实现微信支付功能

    0.学习目标 会调用订单系统接口 实现订单结算功能 实现微信支付功能 源码笔记及资料: 链接:https://pan.baidu.com/s/1_opfL63P1pzH3rzLnbFiNw 提取码:v ...

  2. 【javaWeb微服务架构项目——乐优商城day03】——(搭建后台管理前端,Vuetify框架,使用域名访问本地项目,实现商品分类查询,cors解决跨域,品牌的查询)

    乐优商城day03 0.学习目标 1.搭建后台管理前端 1.1.导入已有资源 1.2.安装依赖 1.3.运行一下看看 1.4.目录结构 1.5.调用关系 2.Vuetify框架 2.1.为什么要学习U ...

  3. 【javaWeb微服务架构项目——乐优商城day05】——商品规格参数管理(增、删、改,查已完成),SPU和SKU数据结构,商品查询

    乐优商城day05 0.学习目标 1.商品规格数据结构 1.1.SPU和SKU 1.2.数据库设计分析 1.2.1.思考并发现问题 1.2.2.分析规格参数 1.2.3.SKU的特有属性 1.2.4. ...

  4. 【javaWeb微服务架构项目——乐优商城day11】——利用RabbitMQ实现搜索和静态页的数据同步

    文章目录 0.学习目标 1.RabbitMQ 1.1.搜索与商品服务的问题 1.2.消息队列(MQ) 1.2.1.什么是消息队列 1.2.2.AMQP和JMS 1.2.3.常见MQ产品 1.2.4.R ...

  5. 【javaWeb微服务架构项目——乐优商城day07】——Elasticsearch介绍和安装及使用(安装kibana,安装ik分词器,Spring Data Elasticsearch,高级查询)

    文章目录 0.学习目标 1.Elasticsearch介绍和安装 1.1.简介 1.1.1.Elastic 1.1.2.Elasticsearch 1.1.3.版本 1.2.安装和配置 1.2.1.新 ...

  6. 终极对决!Dubbo 和 Spring Cloud 微服务架构到底孰优孰劣?

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

  7. blog微服务架构代码_DDD+微服务大型案例:Uber如何从复杂的RPC微服务转向面向业务领域的微服务架构DOMA? -优步工程博客...

    最近,围绕面向服务的体系结构,尤其是微服务体系结构的弊端进行了大量讨论.仅仅几年前,由于许多人宣传微服务架构的好处,例如独立部署形式的灵活性,明确的所有权,系统稳定性的改进以及更好的关注点分离,很多人 ...

  8. Java实战项目——乐优商城 常见错误集锦(一) ERROR com.zaxxer.hikari.pool.HikariPool:HikariPool-1-Exception during pool

    前言 错误信息:com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - 在初始化期间出现异常,具体异常信息如下: mysql连接出现问题?经过查阅资料,出 ...

  9. 《黑马头条》SpringBoot+SpringCloud+ Nacos等企业级微服务架构项目

    01环境搭建.SpringCloud微服务(注册发现.服务调用.网关) 1)课程对比 2)项目概述 2.1)能让你收获什么 2.2)项目课程大纲 2.3)项目概述 随着智能手机的普及,人们更加习惯于通 ...

  10. leyou商城项目搭建(1)-电商行业及乐优商城介绍

    leyou商城项目搭建(1)-电商行业介绍 1.了解电商行业 1.1.项目分类 1.1.1.传统项目 1.1.2.互联网项目 1.2.电商行业的发展 1.2.1.钱景 1.2.2.数据 1.2.3.技 ...

最新文章

  1. linux关于tcp协议ack的实现--发送端对ack的处理
  2. 【转】物料与客户主数据的税分类
  3. python小练习之一
  4. Windows下的函数
  5. [Luogu 1730]最小密度路径
  6. python获取浏览器cookie_python3实现读取chrome浏览器cookie
  7. FMEA软件之边界图(FMEAHunter)
  8. 环信WebIM 发送图片消息和显示图片 发送文件和显示文件 发送表情和显示表情
  9. ubuntu 18改MAC桌面
  10. POWERBUILDER12.6开发实验室管理系统[LIS](四),希森美康XN-350全自动血球计数仪接口
  11. 解决谷歌浏览器跨域问题
  12. 【Kernel】驱动开发学习之Platform平台总线模型
  13. linux更换进程执行码,第八节 进程的切换和系统的一般执行过程—— 20135203齐岳...
  14. MPLAB-IDE-C语言编程代码实例-分析
  15. crh寄存器_STM32的CRH、CRL、ODR和IDR寄存器的使用总结
  16. 游戏策划笔试题目-获取装备期望
  17. 【Raft】分布式一致性算法Raft和zab、paxos
  18. 测量三相永磁同步电机的交轴直轴电感
  19. 我用easyswoole v2做了一个http服务
  20. python:实现二进制补码算法(附完整源码)

热门文章

  1. 使用dd命令测试裸盘性能评测
  2. 发送ajax将浏览器卡死,jQuery Ajax同步参数致使浏览器假死怎么办
  3. CodeCademy | Python | 6. Pyglatin
  4. [随笔] flex 布局使用 space-between 尾行排版效果优化
  5. fNIRS | 非平稳波形的预处理方法
  6. 一款简洁的税后工资计算器(2019)
  7. python 存根_python - 内联类型注释与存根会导致不同的mypy行为 - SO中文参考 - www.soinside.com...
  8. 数据结构 严蔚敏 迷宫求解 代码
  9. WebSocket实现简单多人聊天
  10. 怎么开启2345加速浏览器的过滤弹窗广告