学习更多的知识,整理不易,拒绝白嫖,记得三连哦
关注公众号:java星星 获取全套课件资料

1. 支付

订单搞定之后就是支付了,首先搭建支付工程。

1.1. 搭建环境

pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu</groupId><artifactId>gmall-1010</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.atguigu</groupId><artifactId>gmall-payment</artifactId><version>0.0.1-SNAPSHOT</version><name>gmall-payment</name><description>谷粒商城支付系统</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>com.atguigu</groupId><artifactId>gmall-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.atguigu</groupId><artifactId>gmall-oms-interface</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></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>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</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-zipkin</artifactId></dependency><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.10.0.ALL</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

bootstrap.yml:

spring:application:name: payment-servicecloud:nacos:config:server-addr: 127.0.0.1:8848

application.yml:

server:port: 18092
spring:cloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8080port: 8179zipkin:base-url: http://localhost:9411/sender:type: webdiscovery-client-enabled: falsesleuth:sampler:probability: 1redis:host: 172.16.116.100rabbitmq:host: 172.16.116.100virtual-host: /fenggeusername: fenggepassword: fenggelistener:simple:acknowledge-mode: manualprefetch: 1thymeleaf:cache: falsedatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://172.16.116.100:3306/guli_paymentusername: rootpassword: root
feign:sentinel:enabled: true
mybatis-plus:global-config:db-config:id-type: auto

启动类:

@SpringBootApplication
@EnableFeignClients
@MapperScan("com.atguigu.gmall.payment.mapper")
public class GmallPaymentApplication {public static void main(String[] args) {SpringApplication.run(GmallPaymentApplication.class, args);}}

网关配置:

nginx配置:加入payment.gmall.com

server {listen       80;server_name  api.gmall.com search.gmall.com www.gmall.com item.gmall.com sso.gmall.com cart.gmall.com order.gmall.com payment.gmall.com;proxy_set_header Host $host;location / {proxy_pass   http://192.168.221.1:8888;}
}

重新加载nginx配置:nginx -s reload

在hosts中添加payment.gmall.com:

1.2. 支付流程

支付流程如下:

  1. 点击提交订单按钮,完成订单创建后,跳转到支付选择页

  2. 选择支付渠道,点击立即支付。跳转到具体的支付页

  3. 用户扫码支付跳转到支付成功页

1.3. 选择支付方式

下单成功后,请求路径:http://payment.gmall.com/pay.html?orderToken=202006041844036401268493714385424386

已知条件是订单编号,而支付可能需要订单金额等一些订单信息。所以订单工程应该提供一个根据订单编号查询订单的数据接口。

1.3.1. 根据订单编号查询订单

在gmall-oms工程中的OrderController中添加根据订单编号查询订单的接口方法:

@GetMapping("token/{orderSn}")
public ResponseVo<OrderEntity> queryOrderByOrderSn(@PathVariable("orderSn")String orderSn){OrderEntity orderEntity = this.orderService.getOne(new QueryWrapper<OrderEntity>().eq("order_sn", orderSn));return ResponseVo.ok(orderEntity);
}

在gmall-oms-interface工程中的GmallOmsApi添加接口方法:

@GetMapping("oms/order/token/{orderSn}")
public ResponseVo<OrderEntity> queryOrderByOrderSn(@PathVariable("orderSn")String orderSn);

1.3.2. 跳转到支付渠道选择页

在gmall-payment工程中实现页面跳转。

PaymentController:

@Controller
public class PaymentController {@Autowiredprivate PaymentService paymentService;@GetMapping("pay.html")public String toPay(@RequestParam("orderToken") String orderToken, Model model){OrderEntity orderEntity = this.paymentService.queryOrderByOrderToken(orderToken);model.addAttribute("orderEntity", orderEntity);return "pay";}
}

PaymentService:

@Service
public class PaymentService {@Autowiredprivate GmallOmsClient omsClient;public OrderEntity queryOrderByOrderToken(String orderToken) {ResponseVo<OrderEntity> orderEntityResponseVo = this.omsClient.queryOrderByOrderSn(orderToken);return orderEntityResponseVo.getData();}
}

GmallOmsClient:

@FeignClient("oms-service")
public interface GmallOmsClient extends GmallOmsApi {}

1.3.3. 页面渲染

1.4. 完成支付功能

这里支付已支付宝为例,支付宝的支付流程如下:

调用顺序如下:

  1. 商户系统请求支付宝接口 alipay.trade.page.pay,支付宝对商户请求参数进行校验,而后重新定向至用户登录页面。
  2. 用户确认支付后,支付宝通过 get 请求 returnUrl(商户入参传入),返回同步返回参数。
  3. 交易成功后,支付宝通过 post 请求 notifyUrl(商户入参传入),返回异步通知参数。
  4. 若由于网络等问题异步通知没有到达,商户可自行调用交易查询接口 alipay.trade.query 进行查询,根据查询接口获取交易以及支付信息(商户也可以直接调用查询接口,不需要依赖异步通知)。

注意

  • 由于同步返回的不可靠性,支付结果必须以异步通知或查询接口返回为准,不能依赖同步跳转。
  • 商户系统接收到异步通知以后,必须通过验签(验证通知中的 sign 参数)来确保支付通知是由支付宝发送的。详细验签规则参考异步通知验签。
  • 接收到异步通知并验签通过后,一定要检查通知内容,包括通知中的 app_id、out_trade_no、total_amount 是否与请求中的一致,并根据 trade_status 进行后续业务处理。
  • 在支付宝端,partnerId 与 out_trade_no 唯一对应一笔单据,商户端保证不同次支付 out_trade_no 不可重复;若重复,支付宝会关联到原单据,基本信息一致的情况下会以原单据为准进行支付。

1.4.1. 内网穿透

支付异步通知需要独立ip使阿里支付成功后可以回调我们的接口,所以前提条件就是内网穿透。

哲西云:https://cloud.zhexi.tech

哲西云浏览器客户端配置隧道,映射网关的8888端口:

具体配置如下:

测试内网穿透:访问品牌列表

使用内网穿透后,外网无法通过payment.gmall.com访问支付系统了。只能通过内网穿透提供的地址访问,那么我们的网关也就无法通过域名转发请求,只能通过路径转发,于是在网关中配置路径路由:

1.4.2. 表、实体类及Mapper接口

将支付数据保存到数据库,以便跟支付宝进行对账。

创建guli_payment数据库,导入一下sql:

CREATE TABLE `payment_info` (`id` bigint(20) NOT NULL COMMENT '商户订单号',`out_trade_no` varchar(64) DEFAULT NULL,`payment_type` tinyint(4) DEFAULT NULL COMMENT '支付类型(微信与支付宝)',`trade_no` varchar(64) DEFAULT NULL COMMENT '支付宝交易凭证号',`total_amount` decimal(18,4) DEFAULT NULL COMMENT '订单金额。订单中获取',`subject` varchar(100) DEFAULT NULL COMMENT '交易内容。利用商品名称拼接。',`payment_status` tinyint(4) DEFAULT NULL COMMENT '支付状态,默认值0-未支付,1-已支付。',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`callback_time` datetime DEFAULT NULL COMMENT '回调时间,初始为空,支付宝异步回调时记录',`callback_content` text COMMENT '回调信息,初始为空,支付宝异步回调时记录',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='支付对账表';

对应的实体类如下:

@Data
@TableName("payment_info")
public class PaymentInfoEntity {@Idprivate Long id;private String outTradeNo;private Integer paymentType;private String tradeNo;private BigDecimal totalAmount;private String subject;private Integer paymentStatus;private Date createTime;private Date callbackTime;private String callbackContent;
}

mapper接口:

public interface PaymentInfoMapper extends BaseMapper<PaymentInfoEntity> {}

项目结构:

1.4.3. 整合阿里支付

继续改造gmall-order工程

在pom.xml中,引入阿里支付的依赖:

<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.10.0.ALL</version>
</dependency>

在application.yml中添加阿里支付的配置:

alipay:app_id: 2021001163617452gatewayUrl: https://openapi.alipay.com/gateway.domerchant_private_key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQalipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkWsnotify_url: http://9glldacce2.52http.net/pay/successreturn_url: http://9glldacce2.52http.net/pay/ok

app_id、私钥、公钥参照资料中的《支付宝秘钥.txt》

把课前资料中封装的阿里支付工具类及PayVo对象copy到工程中:

1.4.4. 跳转到支付

修改提交订单的gmall-order中OrderController方法,如下:

@GetMapping("alipay.html")
@ResponseBody
public String alipay(@RequestParam("orderToken") String orderToken){try {// 校验订单状态OrderEntity orderEntity = this.paymentService.queryOrderByOrderToken(orderToken);if (orderEntity.getStatus() != 0){throw new OrderException("此订单无法支付,可能已经过期!");}// 调用支付宝接口获取支付表单PayVo payVo = new PayVo();payVo.setOut_trade_no(orderEntity.getOrderSn());// payVo.setTotal_amount(orderEntity.getPayAmount().toString());payVo.setTotal_amount("0.01");payVo.setSubject("谷粒商城支付平台");// 把支付信息保存到数据库Long payId = this.paymentService.save(orderEntity, 1);payVo.setPassback_params(payId.toString());String form = alipayTemplate.pay(payVo);// 跳转到支付页return form;} catch (AlipayApiException e) {e.printStackTrace();throw new OrderException("支付出错,请刷新后重试!");}
}

PaymentService:

@Service
public class PaymentService {@Autowiredprivate GmallOmsClient omsClient;@Autowiredprivate PaymentInfoMapper paymentInfoMapper;public OrderEntity queryOrderByOrderToken(String orderToken) {ResponseVo<OrderEntity> orderEntityResponseVo = this.omsClient.queryOrderByOrderSn(orderToken);return orderEntityResponseVo.getData();}public Long save(OrderEntity orderEntity, Integer payType){// 查看支付记录,是否已存在。PaymentInfoEntity paymentInfoEntity = this.paymentInfoMapper.selectOne(new QueryWrapper<PaymentInfoEntity>().eq("out_trade_no", orderEntity.getOrderSn()));// 如果存在,直接结束if (paymentInfoEntity != null) {return paymentInfoEntity.getId();}// 否则,新增支付记录paymentInfoEntity = new PaymentInfoEntity();paymentInfoEntity.setOutTradeNo(orderEntity.getOrderSn());paymentInfoEntity.setPaymentType(payType);paymentInfoEntity.setSubject("谷粒商城支付平台");// paymentInfoEntity.setTotalAmount(orderEntity.getPayAmount());paymentInfoEntity.setTotalAmount(new BigDecimal(0.01));paymentInfoEntity.setPaymentStatus(0);paymentInfoEntity.setCreateTime(new Date());this.paymentInfoMapper.insert(paymentInfoEntity);return paymentInfoEntity.getId();}
}

测试效果:

1.4.5. 异步回调

由于同步返回的不可靠性,支付结果必须以异步通知或查询接口返回为准,不能依赖同步跳转。

接收到回调要做的事情:

  1. 验签:验证回调信息的真伪
  2. 检查通知内容:通知中的 app_id、out_trade_no、total_amount 是否与请求中的一致
  3. 验证用户付款的成功与否:根据 trade_status 进行后续业务处理(TRADE_SUCCESS)
  4. 把支付状态写入支付信息表payment_info中。
  5. 更新订单状态并减库存。
  6. 给支付宝返回回执。成功:success 失败:failure

1.4.5.1. 实现异步回调方法

请求方式:Post请求

请求路径:/pay/success

请求参数:PayAsyncVo

返回值:success/failure

给PaymentController新增支付成功后的回调方法:

@PostMapping("pay/success")
@ResponseBody
public String paySuccess(PayAsyncVo payAsyncVo){// 1.验签Boolean flag = this.alipayTemplate.verifySignature(payAsyncVo);if (!flag) {//TODO:验签失败则记录异常日志return "failure"; // 支付失败}// 2.验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验String payId = payAsyncVo.getPassback_params();if (StringUtils.isBlank(payId)){return "failure";}PaymentInfoEntity paymentInfoEntity = this.paymentService.queryPayMentById(Long.valueOf(payId));if (paymentInfoEntity == null|| !StringUtils.equals(payAsyncVo.getApp_id(), this.alipayTemplate.getApp_id())|| !StringUtils.equals(payAsyncVo.getOut_trade_no(), paymentInfoEntity.getOutTradeNo())|| paymentInfoEntity.getTotalAmount().compareTo(new BigDecimal(payAsyncVo.getBuyer_pay_amount())) != 0){return "failure";}// 3.校验支付状态。根据 trade_status 进行后续业务处理  TRADE_SUCCESSif (!StringUtils.equals("TRADE_SUCCESS", payAsyncVo.getTrade_status())) {return "failure";}// 4.正常的支付成功,记录支付记录方便对账paymentService.paySuccess(payAsyncVo);// 5.发送消息更新订单状态,并减库存this.rabbitTemplate.convertAndSend("order-exchange", "order.pay", payAsyncVo.getOut_trade_no());// 6.给支付宝成功回执return "success";
}

给PaymentService添加方法:

/*** 根据id查询支付信息* @param id* @return*/
public PaymentInfoEntity queryPayMentById(Long id) {return this.paymentInfoMapper.selectById(id);
}/*** 更新支付状态* @param payAsyncVo*/
public void paySuccess(PayAsyncVo payAsyncVo){PaymentInfoEntity paymentInfoEntity = new PaymentInfoEntity();paymentInfoEntity.setCallbackTime(new Date());paymentInfoEntity.setPaymentStatus(1);paymentInfoEntity.setCallbackContent(JSON.toJSONString(payAsyncVo));this.paymentInfoMapper.update(paymentInfoEntity, new UpdateWrapper<PaymentInfoEntity>().eq("out_trade_no", payAsyncVo.getOut_trade_no()));
}

1.4.5.2. oms更新订单状态

给gmall-oms中的OrderListener添加修改订单状态为支付成功(待发货)的消息监听方法:

@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "ORDER-PAY-QUEUE", durable = "true"),exchange = @Exchange(value = "ORDER-EXCHANGE", ignoreDeclarationExceptions = "true"),key = {"order.pay"}
))
public void successOrder(String orderToken, Channel channel, Message message) throws IOException {if (this.orderMapper.successOrder(orderToken) == 1){// 如果订单支付成功,真正的减库存this.rabbitTemplate.convertAndSend("ORDER-EXCHANGE", "stock.minus", orderToken);// 给用户添加积分信息OrderEntity orderEntity = this.orderService.getOne(new QueryWrapper<OrderEntity>().eq("order_sn", orderToken));UserBoundVO userBoundVO = new UserBoundVO();userBoundVO.setUserId(orderEntity.getUserId());userBoundVO.setIntegration(orderEntity.getIntegration());userBoundVO.setGrowth(orderEntity.getGrowth());this.rabbitTemplate.convertAndSend("ORDER-EXCHANGE", "bound.plus", userBoundVO);channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}
}

给gmall-oms工程的OrderMapper接口及实现类添加successOrder方法:

int successOrder(String orderToken);
<update id="successOrder">update oms_order set `status`=1 where order_sn=#{orderToken} and `status`=0
</update>

给gmall-oms-interface工程添加UserBoundVO

内容:

@Data
public class UserBoundVO {private Long userId;private Integer integration;private Integer growth;
}

1.4.5.3. wms减库存

给gmall-wms的StockListener添加减库存的监听器方法:

@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "STOCK-MINUS-QUEUE", durable = "true"),exchange = @Exchange(value = "ORDER-EXCHANGE", ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),key = {"stock.minus"}
))
public void minusStock(String orderToken, Channel channel, Message message) throws IOException {try {// 获取redis中该订单的锁定库存信息String json = this.redisTemplate.opsForValue().get(KEY_PREFIX + orderToken);if (StringUtils.isNotBlank(json)){// 反序列化获取库存的锁定信息List<SkuLockVo> skuLockVos = JSON.parseArray(json, SkuLockVo.class);// 遍历并解锁库存信息skuLockVos.forEach(skuLockVo -> {this.wareSkuMapper.minus(skuLockVo.getWareSkuId(), skuLockVo.getCount());});// 删除redis中库存锁定信息this.redisTemplate.delete(KEY_PREFIX + orderToken);}channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);} catch (Exception e) {e.printStackTrace();if (message.getMessageProperties().getRedelivered()){channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);} else {channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);}}
}

给gmall-wms的WareSkuMapper添加方法:

void minus(@Param("id") Long wareSkuId, @Param("count") Integer count);

给gmall-wms的WareSkuMapper.xml添加映射

<update id="minus">update wms_ware_sku set stock_locked = stock_locked - #{count}, stock = stock - #{count}, sales = sales + #{count} where id = #{id}
</update>

gmall-ums中加积分的监听器略。。。。。。

1.4.6. 同步回调

用户扫描支付成功后,我们可以通过同步回调,跳转到商户的支付成功页。

请求方式:GET

请求路径:/pay/ok

请求参数:参照异步请求(比异步请求略少)

返回视图名称

@GetMapping("pay/ok")
public String payOk(PayAsyncVo payAsyncVo){// 查询订单数据展示在支付成功页面// String orderToken = payAsyncVo.getOut_trade_no();// TODO:查询并通过model响应给页面return "paysuccess";
}

2. 秒杀

秒杀具有瞬间高并发的特点,针对这一特点,必须要做限流 + 异步 + 缓存 (+ 页面静态化)。

限流方式:

  1. 前端限流,一些高并发的网站直接在前端页面开始限流,例如:小米的验证码设计
  2. nginx限流,直接负载部分请求到错误的静态页面:令牌算法 漏斗算法
  3. 网关限流,限流的过滤器。或者使用专业的限流组件sentinel
  4. 代码中使用分布式信号量
  5. rabbitmq限流(能者多劳:chanel.basicQos(1)),保证发挥所有服务器的性能。
@Autowired
private StringRedisTemplate redisTemplate;@Autowired
private RabbitTemplate rabbitTemplate;@Autowired
private RedissonClient redissonClient;/*** 分布式并发工具类,快速的腾出服务器的资源来处理其他请求;* @param skuId* @return*/
@GetMapping("/miaosha/{skuId}")
public ResponseVo<Object> kill(@PathVariable("skuId") Long skuId){Long userId = LoginInterceptor.getUserInfo().getUserId();if(userId!=null){// 查询库存String stock = this.redisTemplate.opsForValue().get("sec:stock:" + skuId);if (StringUtils.isEmpty(stock)){return ResponseVo.fail("秒杀结束!");}// 通过信号量,获取秒杀库存RSemaphore semaphore = this.redissonClient.getSemaphore("sec:semaphore:" + skuId);semaphore.trySetPermits(Integer.valueOf(stock));//0.1sboolean b = semaphore.tryAcquire();if(b){//创建订单String orderSn = IdWorker.getTimeId();SkuLockVO lockVO = new SkuLockVO();lockVO.setOrderToken(orderSn);lockVO.setCount(1);lockVO.setSkuId(skuId);//准备闭锁信息RCountDownLatch latch = this.redissonClient.getCountDownLatch("sec:countdown:" + orderSn);latch.trySetCount(1);this.rabbitTemplate.convertAndSend("ORDER-EXCHANGE", "sec.kill", lockVO);return ResponseVo.ok("秒杀成功,订单号:" + orderSn);}else {return ResponseVo.fail("秒杀失败,欢迎再次秒杀!");}}return ResponseVo.fail("请登录后再试!");
}@GetMapping("/miaosha/pay")
public String payKillOrder(String orderSn) throws InterruptedException {RCountDownLatch latch = this.redissonClient.getCountDownLatch("sec:countdown:" + orderSn);latch.await();// 查询订单信息return "";
}

d();

        SkuLockVO lockVO = new SkuLockVO();lockVO.setOrderToken(orderSn);lockVO.setCount(1);lockVO.setSkuId(skuId);//准备闭锁信息RCountDownLatch latch = this.redissonClient.getCountDownLatch("sec:countdown:" + orderSn);latch.trySetCount(1);this.rabbitTemplate.convertAndSend("ORDER-EXCHANGE", "sec.kill", lockVO);return ResponseVo.ok("秒杀成功,订单号:" + orderSn);}else {return ResponseVo.fail("秒杀失败,欢迎再次秒杀!");}
}
return ResponseVo.fail("请登录后再试!");

}

@GetMapping("/miaosha/pay")
public String payKillOrder(String orderSn) throws InterruptedException {

RCountDownLatch latch = this.redissonClient.getCountDownLatch("sec:countdown:" + orderSn);latch.await();// 查询订单信息return "";

}

尚硅谷2020微服务分布式电商项目《谷粒商城》-支付、秒杀相关推荐

  1. 尚硅谷2020微服务分布式电商项目《谷粒商城》学习笔记

    尚硅谷2020微服务分布式电商项目<谷粒商城> 项目简介 资料 百度云 链接:https://pan.baidu.com/s/1eGCTi6pLtKbDCwBs-zCOzQ 提取码:1pm ...

  2. 尚硅谷2020微服务分布式电商项目《谷粒商城》-单点登录(jwt)

    学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 用户管理提供数据接口 1.1. 数据验证功能 根据接口文档知: 请求方式:GET 请求路径:check ...

  3. 尚硅谷2020微服务分布式电商项目《谷粒商城》-商品搜索

    关注公众号:java星星 获取全套课件资料 1. 导入商品数据 1.1. 搭建搜索工程 pom.xml内容如下: <?xml version="1.0" encoding=& ...

  4. 谷粒商城 - 微服务分布式电商项目

    谷粒商城 1.项目背景 谷粒商城项目是尚硅谷研究院最新推出的完整大型分布式架构电商平台,技术全面.业务深入,全网无出其右.技术涵盖:微服务架构 + 分布式 + 全栈 + 集群 + 部署 + 自动化运维 ...

  5. 微服务分布式电商项目《谷粒商城》学习笔记

    文章目录 一.基本架构图 二.配置 三.项目搭建 四.数据库 1.开启虚拟机,在windows下通过navicat连接上 2.人人开源:https://gitee.com/renrenio 五.微服务 ...

  6. 分布式电商项目 谷粒商城 学习笔记<2>

    文章目录 六.三级分类 1.按照父子类的结构获取所有分类 2.跨域问题的解决 1.使用nginx部署为同一域 2.让服务器告诉预检请求能跨域 3.过滤器优先级问题 4.删除 5.增加修改拖拽 七.品牌 ...

  7. 基于微服务的电商系统架构

    分层 微服务设计 微服务微内核 基于微服务的电商系统架构 转载于:https://www.cnblogs.com/davidwang456/articles/9221369.html

  8. JavaEE大型分布式电商项目 上海淘淘商城 29期

    上海29期_张志君老师_淘淘商城_大型分布式电商项目 JavaEE大型分布式电商项目 淘淘商城 29期 需要的加qq:350226234,备注:程序员学习视频 ==================== ...

  9. 分布式电商项目五:使用人人开源搭建前后分离的后台管理系统

    分布式电商项目五:使用人人开源搭建前后分离的后台管理系统 现在我们开始搭建一个后台管理系统,使用的是码云上面的开源项目:人人开源 需要使用两个开源项目:fast和fast-vue. 使用git把需要的 ...

最新文章

  1. 人工智能深度学习Caffe框架介绍,优秀的深度学习架构
  2. C++ Primer 5th笔记(chap 18 大型程序工具)noexcept
  3. laytpl遍历实体列表_Layui数据表格之获取表格中所有的数据方法
  4. android 返回图标,在Toolbar中添加一个返回图标
  5. ASP.NET MVC ActionFilter自定义过滤器异常过滤器过滤器用法
  6. [转]项目失败的经验
  7. svn汉化插件安装步骤
  8. 对Python的深度学习库Theano的介绍
  9. 制作u盘winpe启动盘_老毛桃U盘启动盘制作
  10. Chosen.1 翁克 回忆 怪事
  11. VMware上传超过4GB文件失败
  12. 微软宣布Windows更新计划,Win10将在2025年停止服务支持
  13. 某头部证券机构云化与信创双转型深度解析|信创专题
  14. java使用poi操作excel删除一整行
  15. jQuery 如何通过 ID 选择器 获取动态ID
  16. KB,Kb单位换算,网络带宽中的Kbps和KB/s到底是什么意思?
  17. 7-4 BCD解密 (10分)
  18. 迅雷的工作原理 [揭密迅雷]
  19. 二、PyQtGragh模块安装以及上手体验
  20. 产品经理懂点技术:几种常用的系统开发方法

热门文章

  1. C语言无符号整型运算
  2. TOTALCMD 小计
  3. 搜狐三季度财报发布!张朝阳的三驾马车已经形成了?
  4. GNURadio RTL-SDR之FM接收
  5. 数字设计基础——卡诺图的应用
  6. gitlab-ci运行参数
  7. 笔记本电脑跌到地上,硬盘不认盘咔咔响数据恢复
  8. Good-Turning Smothing 学习
  9. 【信息收集自动化工具】
  10. 安川机器人之MotoPlus编程