慕课网《RabbitMQ消息中间件极速入门与实战》学习总结

  • 时间:2018年09月05日星期三
  • 说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com
  • 教学源码:无
  • 学习源码:https://github.com/zccodere/s...

第一章:RabbitMQ起步

1-1 课程导航

课程导航

  • RabbitMQ简介及AMQP协议
  • RabbitMQ安装与使用
  • RabbitMQ核心概念
  • 与SpringBoot整合
  • 保障100%的消息可靠性投递方案落地实现

1-2 RabbitMQ简介

初识RabbitMQ

  • RabbitMQ是一个开源的消息代理和队列服务器
  • 用来通过普通协议在完全不同的应用之间共享数据
  • RabbitMQ是使用Erlang语言来编写的
  • 并且RabbitMQ是基于AMQP协议的

RabbitMQ简介

  • 目前很多互联网大厂都在使用RabbitMQ
  • RabbitMQ底层采用Erlang语言进行编写
  • 开源、性能优秀,稳定性保障
  • 与SpringAMQP完美的整合、API丰富
  • 集群模式丰富,表达式配置,HA模式,镜像队列模型
  • 保证数据不丢失的前提做到高可靠性、可用性
  • AMQP全称:Advanced Message Queuing Protocol
  • AMQP翻译:高级消息队列协议

AMQP协议模型

1-3 RabbitMQ安装

学习笔记

0.安装准备
官网地址:http://www.rabbitmq.com/
安装Linux必要依赖包<Linux7>
下载RabbitMQ安装包
进行安装,修改相关配置文件
vim /etc/hostname
vim /etc/hosts1.安装Erlang
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get install erlang erlang-nox2.安装RabbitMQ
echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -
sudo apt-get install rabbitmq-server3.安装RabbitMQ web管理插件
sudo rabbitmq-plugins enable rabbitmq_management
sudo systemctl restart rabbitmq-server
访问:http://localhost:15672
默认用户名密码:guest/guest4.修改RabbitMQ配置
vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.5.7/ebin/rabbit.app
比如修改密码、配置等等;例如:loopback_users中的<<"guest">>,只保留guest
服务启动:rabbitmq-server start &
服务停止:rabbitmqctl app_stop

1-4 RabbitMQ概念

RabbitMQ的整体架构

RabbitMQ核心概念

  • Server:又称Broker,接受客户端的连接,实现AMQP实体服务
  • Connection:连接,应用程序与Broker的网络连接
  • Channel:网络信道

    几乎所有的操作都在Channel中进行
    Channel是进行消息读写的通道
    客户端可建立多个Channel
    每个Channel代表一个会话任务

  • Message:消息

    服务器和应用程序之间传送的数据,由Properties和Body组成
    Properties可以对消息进行修饰,比如消息的优先级、延迟等高级特性
    Body则就是消息体内容

  • Virtual host:虚拟机

    用于进行逻辑隔离,最上层的消息路由
    一个Virtual host里面可以有若干个Exchange和Queue
    同一个Virtual host里面不能有相同名称的Exchange或Queue

  • Exchange:交换机,接收消息,根据路由键转发消息到绑定的队列
  • Binding:Exchange和Queue之间的虚拟连接,binding中可以包含routing key
  • Routing key:一个路由规则,虚拟机可用它来确定如何路由一个特定消息
  • Queue:也称为Message Queue,消息队列,保存消息并将它们转发给消费者

RabbitMQ消息的流转过程

第二章:RabbitMQ使用

2-1 发送消息

SpringBoot与RabbitMQ集成

  • 引入相关依赖
  • 对application.properties进行配置

创建名为rabbitmq-producer的maven工程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>47-rabbitmq</artifactId><groupId>com.myimooc</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>rabbitmq-producer</artifactId><properties><spring.boot.version>2.0.4.RELEASE</spring.boot.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--RabbitMQ依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!--工具类依赖--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.36</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-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>

1.编写Order类

package com.myimooc.rabbitmq.entity;import java.io.Serializable;/*** <br>* 标题: 订单实体<br>* 描述: 订单实体<br>* 时间: 2018/09/06<br>** @author zc*/
public class Order implements Serializable{private static final long serialVersionUID = 6771608755338249746L;private String id;private String name;/*** 存储消息发送的唯一标识*/private String messageId;public Order() {}public Order(String id, String name, String messageId) {this.id = id;this.name = name;this.messageId = messageId;}@Overridepublic String toString() {return "Order{" +"id='" + id + ''' +", name='" + name + ''' +", messageId='" + messageId + ''' +'}';}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMessageId() {return messageId;}public void setMessageId(String messageId) {this.messageId = messageId;}
}

2.编写OrderSender类

package com.myimooc.rabbitmq.producer.producer;import com.myimooc.rabbitmq.entity.Order;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** <br>* 标题: 订单消息发送者<br>* 描述: 订单消息发送者<br>* 时间: 2018/09/06<br>** @author zc*/
@Component
public class OrderSender {private RabbitTemplate rabbitTemplate;@Autowiredpublic OrderSender(RabbitTemplate rabbitTemplate) {this.rabbitTemplate = rabbitTemplate;}/*** 发送订单** @param order 订单* @throws Exception 异常*/public void send(Order order) throws Exception {CorrelationData correlationData = new CorrelationData();correlationData.setId(order.getMessageId());// exchange:交换机// routingKey:路由键// message:消息体内容// correlationData:消息唯一IDthis.rabbitTemplate.convertAndSend("order-exchange", "order.a", order, correlationData);}}

3.编写application.properties类

# RabbitMQ配置
spring.rabbitmq.addresses=192.168.0.105:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000# Server配置
server.servlet.context-path=/
server.port=8080spring.http.encoding.charset=UTF-8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.default-property-inclusion=NON_NULL

4.编写Application类

package com.myimooc.rabbitmq.producer;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** <br>* 标题: 启动类<br>* 描述: 启动类<br>* 时间: 2018/09/06<br>** @author zc*/
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

5.编写OrderSenderTest类

package com.myimooc.rabbitmq.producer.producer;import com.myimooc.rabbitmq.entity.Order;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.UUID;/*** <br>* 标题: 订单消息发送者测试<br>* 描述: 订单消息发送者测试<br>* 时间: 2018/09/06<br>** @author zc*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderSenderTest {@Autowiredprivate OrderSender orderSender;@Testpublic void testSend1() throws Exception {Order order = new Order();order.setId("201809062009010001");order.setName("测试订单1");order.setMessageId(System.currentTimeMillis() + "$" + UUID.randomUUID().toString().replaceAll("-",""));this.orderSender.send(order);}
}

2-2 处理消息

创建名为rabbitmq-consumer的maven工程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>47-rabbitmq</artifactId><groupId>com.myimooc</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>rabbitmq-consumer</artifactId><properties><spring.boot.version>2.0.4.RELEASE</spring.boot.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--RabbitMQ依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!--工具类依赖--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.36</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-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>

1.编写Order类

package com.myimooc.rabbitmq.entity;import java.io.Serializable;/*** <br>* 标题: 订单实体<br>* 描述: 订单实体<br>* 时间: 2018/09/06<br>** @author zc*/
public class Order implements Serializable{private static final long serialVersionUID = 6771608755338249746L;private String id;private String name;/*** 存储消息发送的唯一标识*/private String messageId;public Order() {}public Order(String id, String name, String messageId) {this.id = id;this.name = name;this.messageId = messageId;}@Overridepublic String toString() {return "Order{" +"id='" + id + ''' +", name='" + name + ''' +", messageId='" + messageId + ''' +'}';}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMessageId() {return messageId;}public void setMessageId(String messageId) {this.messageId = messageId;}
}

2.编写OrderReceiver类

package com.myimooc.rabbitmq.consumer.consumer;import com.rabbitmq.client.Channel;
import com.myimooc.rabbitmq.entity.Order;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;import java.util.Map;/*** <br>* 标题: 订单接收者<br>* 描述: 订单接收者<br>* 时间: 2018/09/06<br>** @author zc*/
@Component
public class OrderReceiver {/*** 接收消息** @param order   消息体内容* @param headers 消息头内容* @param channel 网络信道* @throws Exception 异常*/@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "order-queue",durable = "true"),exchange = @Exchange(name = "order-exchange",type = "topic"),key = "order.*"))@RabbitHandlerpublic void onOrderMessage(@Payload Order order, @Headers Map<String, Object> headers, Channel channel) throws Exception {// 消费者操作System.out.println("收到消息:");System.out.println("订单信息:" + order.toString());// 手动签收消息Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);channel.basicAck(deliveryTag, false);}
}

3.编写application.properties类

# RabbitMQ连接配置
spring.rabbitmq.addresses=192.168.0.105:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000
# RabbitMQ消费配置
# 基本并发:5
spring.rabbitmq.listener.simple.concurrency=5
# 最大并发:10
spring.rabbitmq.listener.simple.max-concurrency=10
# 签收模式:手动签收
spring.rabbitmq.listener.simple.acknowledge-mode=manual
# 限流策略:同一时间只有1条消息发送过来消费
spring.rabbitmq.listener.simple.prefetch=1# Server配置
server.servlet.context-path=/
server.port=8082spring.http.encoding.charset=UTF-8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.default-property-inclusion=NON_NULL

4.编写Application类

package com.myimooc.rabbitmq.consumer;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** <br>* 标题: 启动类<br>* 描述: 启动类<br>* 时间: 2018/09/06<br>** @author zc*/
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

第三章:可靠性投递

3-1 设计方案

保障100%消息投递成功设计方案(一)

3-2 代码详解

因篇幅限制,源码请到github地址查看,这里仅展示核心关键类

1.编写OrderSender类

package com.myimooc.rabbitmq.ha.producer;import com.myimooc.rabbitmq.entity.Order;
import com.myimooc.rabbitmq.ha.constant.Constants;
import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper;
import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** <br>* 标题: 订单消息发送者<br>* 描述: 订单消息发送者<br>* 时间: 2018/09/06<br>** @author zc*/
@Component
public class OrderSender {@Autowiredprivate RabbitTemplate rabbitTemplate;@Autowiredprivate BrokerMessageLogMapper brokerMessageLogMapper;/*** 回调方法:confirm确认*/private final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.out.println("correlationData:" + correlationData);String messageId = correlationData.getId();if (ack) {// 如果confirm返回成功,则进行更新BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO();messageLogPO.setMessageId(messageId);messageLogPO.setStatus(Constants.OrderSendStatus.SEND_SUCCESS);brokerMessageLogMapper.changeBrokerMessageLogStatus(messageLogPO);} else {// 失败则进行具体的后续操作:重试或者补偿等System.out.println("异常处理...");}}};/*** 发送订单** @param order 订单*/public void send(Order order) {// 设置回调方法this.rabbitTemplate.setConfirmCallback(confirmCallback);// 消息IDCorrelationData correlationData = new CorrelationData(order.getMessageId());// 发送消息this.rabbitTemplate.convertAndSend("order-exchange", "order.a", order, correlationData);}
}

2.编写OrderService类

package com.myimooc.rabbitmq.ha.service;import com.myimooc.rabbitmq.entity.Order;
import com.myimooc.rabbitmq.ha.constant.Constants;
import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper;
import com.myimooc.rabbitmq.ha.dao.mapper.OrderMapper;
import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO;
import com.myimooc.rabbitmq.ha.producer.OrderSender;
import com.myimooc.rabbitmq.ha.util.FastJsonConvertUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;/*** <br>* 标题: 订单服务<br>* 描述: 订单服务<br>* 时间: 2018/09/07<br>** @author zc*/
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate BrokerMessageLogMapper brokerMessageLogMapper;@Autowiredprivate OrderSender orderSender;/*** 创建订单** @param order 订单*/public void create(Order order) {// 当前时间Date orderTime = new Date();// 业务数据入库this.orderMapper.insert(order);// 消息日志入库BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO();messageLogPO.setMessageId(order.getMessageId());messageLogPO.setMessage(FastJsonConvertUtils.convertObjectToJson(order));messageLogPO.setTryCount(0);messageLogPO.setStatus(Constants.OrderSendStatus.SENDING);messageLogPO.setNextRetry(DateUtils.addMinutes(orderTime, Constants.ORDER_TIMEOUT));this.brokerMessageLogMapper.insert(messageLogPO);// 发送消息this.orderSender.send(order);}
}

3.编写RetryMessageTask类

package com.myimooc.rabbitmq.ha.task;import com.myimooc.rabbitmq.entity.Order;
import com.myimooc.rabbitmq.ha.constant.Constants;
import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper;
import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO;
import com.myimooc.rabbitmq.ha.producer.OrderSender;
import com.myimooc.rabbitmq.ha.util.FastJsonConvertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.List;/*** <br>* 标题: 重发消息定时任务<br>* 描述: 重发消息定时任务<br>* 时间: 2018/09/07<br>** @author zc*/
@Component
public class RetryMessageTask {private Logger logger = LoggerFactory.getLogger(getClass());@Autowiredprivate OrderSender orderSender;@Autowiredprivate BrokerMessageLogMapper brokerMessageLogMapper;/*** 启动完成3秒后开始执行,每隔10秒执行一次*/@Scheduled(initialDelay = 3000, fixedDelay = 10000)public void retrySend() {logger.debug("重发消息定时任务开始");// 查询 status = 0 和 timeout 的消息日志List<BrokerMessageLogPO> pos = this.brokerMessageLogMapper.listSendFailureAndTimeoutMessage();for (BrokerMessageLogPO po : pos) {logger.debug("处理消息日志:{}",po);if (po.getTryCount() >= Constants.MAX_RETRY_COUNT) {// 更新状态为失败BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO();messageLogPO.setMessageId(po.getMessageId());messageLogPO.setStatus(Constants.OrderSendStatus.SEND_FAILURE);this.brokerMessageLogMapper.changeBrokerMessageLogStatus(messageLogPO);} else {// 进行重试,重试次数+1this.brokerMessageLogMapper.updateRetryCount(po);Order reSendOrder = FastJsonConvertUtils.convertJsonToObject(po.getMessage(), Order.class);try {this.orderSender.send(reSendOrder);} catch (Exception ex) {// 异常处理logger.error("消息发送异常:{}", ex);}}}logger.debug("重发消息定时任务结束");}
}

4.编写ApplicationTest类

package com.myimooc.rabbitmq.ha;import com.myimooc.rabbitmq.entity.Order;
import com.myimooc.rabbitmq.ha.service.OrderService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.UUID;/*** <br>* 标题: 订单创建测试<br>* 描述: 订单创建测试<br>* 时间: 2018/09/07<br>** @author zc*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {@Autowiredprivate OrderService orderService;@Testpublic void testCreateOrder(){Order order = new Order();order.setId(String.valueOf(System.currentTimeMillis()));order.setName("测试创建订单");order.setMessageId(System.currentTimeMillis() + "$" + UUID.randomUUID().toString().replaceAll("-",""));this.orderService.create(order);}}

慕课网_《RabbitMQ消息中间件极速入门与实战》学习总结相关推荐

  1. 慕课网_《微信授权登录》学习总结

    时间:2017年08月12日星期六 说明:本文部分内容均来自慕课网.@慕课网:http://www.imooc.com 教学源码:无 学习源码:https://github.com/zccodere/ ...

  2. 微信授权登录(微信订阅号使用测试账号)

    1.微信授权登录: 微信公众号测试登录: 准备: 1.1 花生壳! 下载地址:http://hsk.oray.com/download/ 1.2 微信公众号:https://mp.weixin.qq. ...

  3. 硅谷课堂 12_公众号消息和微信授权登录

    硅谷课堂第十二天-公众号消息和微信授权登录 文章目录 硅谷课堂第十二天-公众号消息和微信授权登录 一.公众号普通消息 1.实现目标 2.消息接入 2.1.公众号服务器配置 2.2.验证来自微信服务器消 ...

  4. uni app和php开发微信登录代码,uniapp如何实现微信授权登录

    uniapp实现微信授权登录的方法:首先获取对应的appid和appsecret:然后在uniapp项目的manifest.json中进行APP SDK配置和模块权限配置.最后实现编码. 本教程操作环 ...

  5. thinkphp 微信授权登录 以及微信实现分享

    <?php namespace app\wechat\controller; use think\Controller; use think\Request; /** * 微信授权登录类 * U ...

  6. code换取微信openid_微信授权登录开发的两种方式

    本文主要针对微信公众号(公众平台的开发) 首先理解一个概念:OAuth: OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表), ...

  7. Java版本微信授权登录(升级版)

    前面写了一遍文章<Java版本微信授权登录(测试版)>,可以当做入门的基础文章,这里继续做一点深入,主要解决的是,如何在本地开发中微信授权以后跳转到本地启动的项目中. 我们知道了微信公众平 ...

  8. android友盟微信授权登录清除,【转载】Android友盟SDK微信授权登录接入

    微信授权登录接入需要先到微信开放平台申请好应用的APPID,交纳300大洋费用得到授权登录权限后才能使用,此处不再赘述. 接入的两种方式 -- 微信SDK接入:使用微信官方SDK接入,需要分" ...

  9. uniapp开发h5微信授权登录(详细教程)

    uniapp开发h5微信授权登录 文章目录 uniapp开发h5微信授权登录 前言 一.前期准备--申请测试账号 二.正式开发--前端代码 三.打包发布 总结 前言 我也是第一次做h5授权微信登录,网 ...

  10. springboot微信授权登录

    水平有限!实现方法直接找的网上的以为大神所编写的api来实现,这里主要是记录一下自己实现的过程.具体方法请参考网址:https://github.com/liyiorg/weixin-popular, ...

最新文章

  1. python学习之第四课时--运算符
  2. Yii直接加载JS/CSS
  3. 算法学习之路|最小生成树——prime算法
  4. BZOJ1114 : [POI2008]鲁滨逊逃生Rob
  5. 弘辽科技:手淘推荐流量总是忽高忽低如何稳定获取
  6. 卫星地面站空间分集的必要性及解决方案
  7. 【数据结构与算法】详解什么是哈希表,并用代码手动实现一个哈希表
  8. 外贸人必收藏开发客户、找邮箱等高效工具
  9. Learning Sites
  10. Protocol(一)[概述]
  11. 一篇文章看懂Facebook和新浪微博的智能FEED
  12. (已更新)成语小秀才小程序V2.0.14完整安装包+小程序前端
  13. 优秀logo,最基础的设计技巧(四)
  14. 提取字符串中一个或多个空格隔开的字符串
  15. Vue中slot的使用(通俗易懂)
  16. 单目标优化:飞狐优化算法(Flying Foxes Optimization,FFO)求解cec2017(提供Matlab代码)
  17. wowza媒体所使用的端口
  18. 数据库管理工具DBeaver的下载以及安装
  19. C语言中fun的功能是将字符串,c语言程序设计请编写一个函数fun,它的功能是:将ss所指字符串中所.,c语言程序设计题 请编写一个函数fun,它的功能是:将ss所...
  20. WebLogic CVE-2019-2647、CVE-2019-2648、CVE-2019-2649

热门文章

  1. Solaris ALOM1.6 SC Password Reset
  2. show一下新模板(分享全套CSS和图片)
  3. Linux下获取毫秒级时间差
  4. UA MATH571A 一元线性回归III 方差分析与相关性分析
  5. python多线程的两种写法
  6. 播放图像有锯齿_反隔行操作
  7. Python 全栈开发:python字符串切片
  8. getparameter的使用
  9. MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments
  10. javaweb数据库操作