爬取前准备
网页查看
建立mysql数据库及表
建立数据库
建立表
1 | python复制代码CREATE TABLE `51job` ( |
完整代码及代码分析
1 | python复制代码from selenium import webdriver |
图片辅助分析
图1
图2
图3
图4
图5
运行结果
博主会持续更新,有兴趣的小伙伴可以点赞、关注和收藏下哦,你们的支持就是我创作最大的动力!
本文转载自: 掘金
开发者博客 – 科技是第一生产力
建立数据库
建立表
1 | python复制代码CREATE TABLE `51job` ( |
1 | python复制代码from selenium import webdriver |
图1
图2
图3
图4
图5
博主会持续更新,有兴趣的小伙伴可以点赞、关注和收藏下哦,你们的支持就是我创作最大的动力!
本文转载自: 掘金
有关阿里云OSS有关图片上传设置过期时间的问题,困扰了我几个小时的时间,之前也不是没用过阿里OSS,但此次开发中发现原来的方法上传不了,经百度得到的代码上传之后,图片又有过期时间,这tm确实迷惑了我。
经过我仔细对比之前使用阿里OSS发现,我的Bucket设置的读写权限为==私有==
修改回==公共读==后就不需要设置过期时间了
希望各位小伙伴别再遇到我这样的问题了!
1 | xml复制代码 <!--阿里云OSS--> |
Bucket的读写权限要设置为==私有==
1 | java复制代码@Service |
Bucket的读写权限要设置为==公共读==
1 | java复制代码@Service |
本篇博文到此结束,觉得不错的小伙伴可以一键三连哦!,感谢支持!!!
本文转载自: 掘金
==Glidedsky==这关的==JS解密==不同于我之前见到的,希望大家好好看,好好学!
==温馨提示==:保护好头发!
既然是JS加密过的,那么数据肯定不是静态的,如下
直接请求该页面,或取到的html代码粘贴到html文件打开是没有数字的
打开控制台查看XHR
这里有个问题,我之前查看是可以查看到数据的,但不知道为什么又看不到数据了,有知道的小伙伴麻烦在评论区告诉我下,谢谢。
网上查的说什么==网页可以感应用户打开了控制台==,咱也不知道,咱也不敢问,还有这么吊的操作
如何还有不明白的小伙伴,可以参考我这篇JS解密文章 Python爬虫JS解密详解,写的很详细,这玩意搞多了就有经验了
不说了,咱们接着看
往下翻可以看见,该请求带了3个参数
按住Ctrl+Shift+f 进行搜索,输入==sign==,可见有6个匹配的
有兴趣的小伙伴可以点进去再次搜索==sign==,都是些跟下图一样==牛头不对马嘴==的匹配
按我之前的JS解密经验,不应该是直接匹配到,然后搞个什么函数加密的嘛 o(╥﹏╥)o
都看到这份上了,接直接放弃也不是我个性格,耐着性子接着研究研究。。。。
然后发现个新办法,现在教给大家——就是打XHR断点,如下
复制部分URL就好了,不用全部复制
==现在进入最关键步骤——使用python代码得到上面的数据==
==获取t值==
==获取sign值==
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA),SHA1比MD5的安全性更强。对于长度小于2^ 64位的消息,SHA1会产生一个160位的消息摘要。
不要慌,python中提供了hashlib库解决,真是厉害啊!
==成功了,老铁们可以来波点赞嘛!(*^▽^*)==
==拼接URL请求,注意:返回数据为json格式==
完美
1 | python复制代码import requests |
闯关成功,解密成功!!!
==注意填上Cookie,我提供的代码没有填上Cookie值==
博主会持续更新,有兴趣的小伙伴可以==点赞==、==关注==和==收藏==下哦,你们的支持就是我创作最大的动力!
博主开源Python爬虫教程目录索引(宝藏教程,你值得拥有!)
本文转载自: 掘金
掘金的小伙伴们,大家好,我是沉默王二。最近我在狂补计算机基础知识,感觉有点上瘾!以前觉得很枯燥的知识,现在竟然有点香!不知道为什么。
我算是科班出身,大学的专业就是计算机网络,不过老实说,在实际的开发中,大学的很多课程,要么“用处”不大,要么可以换个方式,更高效的学习。
其中的原因,一方面是实际开发更关注知识的“实用”,另外一方面,大学的教学确实和产业有些脱钩。所以我就从实际应用的角度出发,重新来梳理一下计算机基础方面的知识。
毫无疑问,数据结构对一名程序员来说非常重要,还是那句话程序=数据结构+算法,这种说法无论放在什么时候都是成立的。
大部分的数据结构课程,关注的重点都在如何从数学上实现一个数据结构,但在实际开发中,大部分主流语言都已经内置了常见的数据结构,比如说 Java。也就是说,对于大部分程序员来说,实际开发中,很难有需求要从零开始实现一个数据结构。因此我们只需要做到下面几点。
1、熟悉常见数据结构的概念,比如说数组、堆栈、链表、哈希表等。
2、了解常用数据结构之间的差异,比如说 ArrayList 和 LinkedList,我在之前的文章中有详细说明过,可以点击链接去查看下。
3、关注常用数据结构的外围算法,比如说如何对 List 和 Map 进行查找。
4、关注数据结构使用中容易出错的地方,比如说线程是否安全等。
…
B 站上浙江大学的一个数据结构的课还不错,很系统很经典,适合小白入门。
视频地址如下。
以我接触的领域来说,大部分普通的业务系统都不会涉及到太复杂的算法,因此我没有在算法上投入过多时间。
但如果你在一些特殊的领域,如果算法跟不上,可以说是“寸步难行”,比如说图形处理领域,无论是图像的变化还是增强,无一例外都要用到矩阵变换,因此就必然涉及到线性代数的内容,再往深处学的话,必然会牵扯出更多的知识。
所以学习算法要视情况而定,如果想走算法岗,那么《算法第4版》、《算法导论》、《数学之美》、《编程珠玑》、《剑指offer》这些书都要耐着性子啃一啃。电子书可以在下面这个 GitHub 仓库上找得到。
顺带再推荐一份阿里大佬的算法刷题笔记吧,在 GitHub 上已经有 13.3k 的 star 了。里面的每道题都写了解题思路,是通过 GO 语言实现的,每道题都 runtime beats 100% 了。
在线阅读地址如下所示:
我认为设计模式是初中级程序员迈向高级程序员的必经之路。有不少程序员,前期冲劲十足,但后继乏力,都是吃了设计模式的亏。
在工作的前几年,大部分程序员都处于熟悉编程语言的阶段,也就是处于“技”的阶段,随后就要进入“术”的阶段了。在编程领域,“术”的典型代表就是“设计模式”。
我自己推荐的一本书是《设计模式之禅》,代码是用 Java 实现的,读起来比较轻松,也更符合国内程序员的阅读习惯。
另外就是我上次推荐的 Refactoring Guru 网站,里面附带的图片非常精美,阅读起来的视觉效果会比较丰富。
在线阅读地址如下所示:
离线版可以通过下面这个链接下载(无套路,不需要解压密码):
实现一个软件系统的过程,不仅只有编码,还涉及到项目安排,团队协调等一系列非技术因素,如果想从一名程序员走向管理岗,成为 team leader 或者开发经理,软件工程方面的知识就必须得跟得上。
这里我推荐几本不错的经典书,其中有一本邹欣老师的书,他刚出任 CSDN 副总裁,希望 CSDN 能在他的入驻后变得更好一些。他这本书的书名叫做《构建之法》,我看过,还是很不错的。
另外还有两本必读,就是《人月神话》和《人件》,虽然有了岁月的痕迹,但依然值得深读。当然,关于软件工程,最好的学习方法是观察,观察你所在的团队是如何处理工程问题的,然后思考,最终形成自己的方法观。
电子书可以在下面这个 GitHub 仓库上找得到。
要想写出一个好而美的程序,需要经过三个阶段。
第一阶段,有扎实的基本功,简单点说,就是要做到语法熟练、框架熟练,成为一名能够完成开发任务的“码农”。
第二阶段,从“码农”到“工程师”,在局部上,不仅要能够实现功能,还能关注功能之外的维度,比如健壮性、低耦合、可扩展等指标。
第三阶段,从“工程师”到“架构师”,不仅在局部上追求一个模块的好坏,而且还要从整个系统层面去掌控,合理安排资源的优先级,保证整个系统不会出现腐败等等。
要想成为一名优秀的架构师,除了自身的努力,也需要一点点运气,但靠读书可能不够,但这些经典书籍还是要阅读的,能给日常的工作带来巨大的帮助。
电子书可以在下面这个 GitHub 仓库上找得到。
技术这条道路并不好走,不仅要学习很多新技术、新框架,还要及时补充必要的计算机基础知识,底子硬的同时还要学会拥抱变化。
学习的过程,就好像登山一样,大概有 80% 的人在这个过程中会掉队。那么请相信我,只要目标明确,努力加上坚持,再加上一点点好运气,你就能登顶!
好了,我是沉默王二,希望这篇文章能够帮到你!下期见。
本文转载自: 掘金
计算机做加法是对人做加法的模拟。那么人是怎么做加法的呢?让我们来考察一下。
从一般的情况出发,比如怎么计算“24+35”呢?
我们把个位与个位相加,4+5=9,再把十位与十位相加,2+3=5,再合起来得到 59。
这就是所谓的 分而治之(divide and conque) 了,用打仗的话来说,也可以说是各个击破。
显然,会做两个多位数加法的基础是会做两个一位数加法。那么,问题又来了,如何做两个一位数的加法呢?
其实,你靠的是记忆!我们会在后面再去深入探讨这一问题。
目前,我们考虑的是如何构造多位加法器,重点是如何去模拟多位加法器的工作过程。
对于两个一位数加法的问题,我们暂且认为:经过反复学习,在我们的大脑中形成了一个关于一位数加法的神经网络,它的功能可由以下的一个抽象接口模型来描述:
它能接受两个一位数,并快速给出相加的结果。以此为基础,多位数的加法可以分解成多次一位数的加法,并把结果合并起来。
先不考虑一位加法器的实现细节,相反,假定它已经有了我们想要的功能,我们现在先考虑如何用它构建高级的多位加法器。
这种思路我们称之为“自顶向下(top down)”,先把目光聚焦在高层的结构上。
一位加法器是为多位加法器服务的,从服务对象考虑起能让我们更好地确定底层接口的规范。
假定底层已有我们想要的功能,这种思路又称为“wishful thinking(按愿望思维)”。它避免了我们过早地纠结在底层实现的细节上去。
有人可能会想,人做加法是用十进制,计算机或者说电路做加法是用二进制,这样去类比可行吗?是不是应该先讲讲二进制的知识先呢?
进制差异自然会带来影响,特别越到底层,影响越显著。
不过,我们将看到,进制的选择暂时不会影响高层的结构。对于我们而言,十进制更加自然,到后面,会逐步转到二进制上去讨论。
至于数字的表示问题,10 进制的一大麻烦就是要表示的状态太多了,既然要用电路来实现,首先很容易想到用电压来表示数字。
比如数字 1 就用 1V 的电压来表示,同理,数字 9 就用 9V 来表示。
自然,这种表示不是唯一的,你也可以用 0.1V 来表示 1,那么相应地用 0.9V 来表示 9,关键或许在于保持这种比率关系。
考虑前面人做加法的例子:24+35
一种策略就是只用一个一位数加法器,分成多次,每一次把同一位上的两个数扔给这个一位加法器去运算:
比如先把个位的 4 和 5 扔进去,得出一个结果 9,存起来;
再把十位上的 2 和 3 扔进去…
当然,这种方式的挑战在于如何存储中间结果,如何依次地把数据送进去,另外还有速度的问题等等。
打造出一个如此的加法器几乎相当于一个初级计算机的雏形了。
显然,人做多位加法的过程也是串行式的。
那么,一种更加简单粗暴的策略就是把几个一位加法器拼接起来,同时进行计算,一方面无需关注存储,依次送入数据等问题,另外速度上也更快了。
24+35,按照我们的习惯,左边是高位(十位),右边是低位(个位)。
如果需要更多的位数,那么简单放置更多的一位加法器就完了。这种方式需要更多的硬件,但我们也因此得到了好处。
当然了,无限的并行下去也是不行的,最终我们要的是一种中庸之道,平衡之术,盲目推崇或排斥某种方式往往都是不可取的。
比如一个 32 位机如何做 64 位的加法呢?最终还是靠串行做 2 次 32 位加法来实现。
当然,有一个很重要的问题被有意无意地忽略了,那就是进位。
考虑以下多位数的加法:“256+128”, 那么,通过组合三个一位数加法器,分别处理个位,十位与百位数字的相加,结果如下:
显然,3714 不是我们想要的结果,因为没有考虑到进位的影响。正确的结果应该是 384。
到目前为止,我们关于一位加法器的构想还是很粗糙的。首先,从最终结果的表示层面而言,按前面约定的表示,输出应该限制在 0V-9V 的区间。
如果是 0V,按电路上一般的约定,可用一个接地符号来表示:
对于上述个位数加法而言,那么就是输入一个 6V 和一个 8V 的电压,结果输出的 14V 电压,这不是我们想要的结果。
显然,上述例子中,个位中只需要输出 4V 即可,而不是 14V,14 需要拆分成 1 和 4。
现在需要修正一位加法器的原型。首先至少要两个输出,一个是 加位(sum,S) 的输出,一个 进位(carry,C) 的输出:
其次,进位 的输出还要参与到下一级的输入中去,也即要有三个输入,输出则只要显示 加位 的结果即可:
对于右边最低位,不存在进位,使用一个接地符号表示输入为 0V。
其余的进位输入则来自低位的进位输出。
图中红色的线表示产生了进位。对于中间的十位数加法,实际是 5+2+1=8。
经过这样的调整,多位加法器就能正常工作了,但这样一来,模型也复杂多了。
综合进位及显示的需要,那么,一个具有普遍性的一位加法器至少要三个输入,其中有一个进位输入(Carry In);以及两个输出(其中,CO 指 Carry out,进位输出):
这样的一个东西,我们称之为全加器(Full Adder,FA)。如果你是计算机或相关专业科班出身,你就知道为何这么叫了,我也不想引入新的叫法。
前面说到,如果从高层考虑起,能让我们更好地确定底层接口的规范,我们现在的确得到了一个更明确的接口。
如果一开始就一头猛扎进去实现最初设想的一位加法器原型,恐怕到构建多位加法器时又不得不返工了。
现在尽管我们不知道怎么去实现它,但我们却更清楚它应该是怎样的。
你心中有个 Big Picture(大图景),你更加不容易走偏。
然后,以此为基础,把三个一位加法器封装在一起,把同一个数的三个位放在一起,得到以下一个三位加法器的原型:
走线就有点随意了,我也不是什么专业绘电路图的,大家能看明白原理就行了。
执行上述加法的过程如下:
通过梳理线路的走向,就无须像前面那般两个数字交叉在一起很不直观。
线未必非得要走到一块,有种说法是“接口要对用户友好”,无论你是设计硬件还是软件的接口,都应该记住这一点。
明白了它的内部实现,之后,再提到它时,只需要一个简化的接口模型:
那么,这就是搞软件的人口中所谓的抽象呀,封装呀,提供接口呀,隐藏实现呀,blah, blah…
以它为基础,我们又可以构建比如一个 6 位加法器,在它里面封装了两个三位加法器:
如果想呈现全部的细节,那么就像下面这样了,线很多,但道理还是一样的:
当然也可以跳过三位加法器,直接构建在 6 个全加器基础上。本质上还是一样,不过少了层封装。
自然,按照同样的思路,你还可以打造 12 位加法器。当然你也可以先造个 2 位的加法器,然后再一层一层弄出 4 位,8 位的等等。
你甚至可用一个 2 位加一个 3 位来造一个 5 位的加法器,有何不可呢?随便你怎么去组合。
搞软件的同学是不是又想到了什么分层次呀,模块化呀,然后又是一大堆理论,大道理,blabla…
这些原则其实是软硬通吃的。
当然,以上这些最终都建立在全加器功能的基础上。
而后面我们将看到,全加器它又是建立在半加器等的基础之上。
构造一层又一层的抽象,这就是我们应付复杂性的重要手段。
当不知道全加器是如何工作时,我们可能会觉得不够踏实,似乎一切建立在无源之水,无本之木之上一样。
我们将在下一篇再探讨如何去构建全加器。见计算机是如何做加法的?(2)——构建一位加法器
本文转载自: 掘金
日常 Coding 过程中,设计模式三板斧:模版、构建者、策略,今天来说下第三板斧 策略设计模式
策略模式还是比较简单并且使用较多的,平常我们多运用策略模式用来消除 if-else、switch 等多重判断的代码,消除 if-else、switch 多重判断 可以有效应对代码的复杂性
如果分支判断会不断变化(增、删、改),那么可以使用别的技巧让其满足开闭原则,提高代码的扩展性 (策略模式场景主要负责解耦,开闭原则需要额外支持)
下文中会详细列举如何使用设计模式做个 Demo 、模式的真实场景以及策略模式的好处
策略设计模式大纲如下:
- 什么是策略模式
- Spring 项目中真实的应用场景
- 框架源码底层如何玩耍策略模式
- 策略模式总结
策略模式在 GoF 的《设计模式》一书中,是这样定义的:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
定义一组算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化,客户端代指使用算法的代码
看到上面的介绍可能不太明白策略模式具体为何物,这里会从最基本的代码说起,一步一步彻底掌握此模式。下述代码可能大家都能联想出对应的业务,根据对应的优惠类型,对价格作出相应的优惠
这段代码是能够满足项目中业务需求的,而且很多已上线生产环境的代码也有这类代码。但是,这一段代码存在存在两个弊端
如何运用策略模式优化上述代码,使程序设计看着简约、可扩展等特性
将上述代码块改造为策略设计模式,大致需要三个步骤
目前把抽象策略接口、具体的策略实现类以及策略工厂都已经创建了,现在可以看一下客户端需要如何调用,又是如何对客户端屏蔽具体实现细节的
根据代码块图片得知,具体策略类是从策略工厂中获取,确实是取消了 if-else 设计,在工厂中使用 Map 存储策略实现。获取到策略类后执行具体的优惠策略方法就可以获取优惠后的金额
通过分析大家得知,目前这种设计确实将应用代码的复杂性降低了。如果新增一个优惠策略,只需要新增一个策略算法实现类即可。但是,添加一个策略算法实现,意味着需要改动策略工厂中的代码,还是不符合开闭原则
如何完整实现符合开闭原则的策略模式,需要借助 Spring 的帮助,详细案例请继续往下看
最近项目中设计的一个功能用到了策略模式,分为两类角色,笔者负责定义抽象策略接口以及策略工厂,不同的策略算法需要各个业务方去实现,可以联想到上文中的优惠券功能。因为是 Spring 项目,所以都是按照 Spring 的方式进行处理,话不多说,上代码
可以看到,比对上面的示例代码,有两处明显的变化
小贴士:为了阅读方便,mark() 返回直接使用字符串替代,读者朋友在返回标示时最好使用枚举定义
接下来继续查看抽象策略工厂如何改造,才能满足开闭原则
和之前责任链模式相同 (TODO 添加链接),都是通过 InitializingBean 接口实现中调用 IOC 容器查找对应策略实现,随后将策略实现 mark() 方法返回值作为 key, 策略实现本身作为 value 添加到 Map 容器中等待客户端的调用
这里使用的 SpringBoot 测试类,注入策略工厂 Bean,通过策略工厂选择出具体的策略算法类,继而通过算法获取到优惠后的价格。小插曲:如果不想把策略工厂注入 Spring 也可以,实现方法有很多
总结下本小节,我们通过和 Spring 结合的方式,通过策略设计模式对文初的代码块进行了两块优化:应对代码的复杂性,让其满足开闭原则。更具体一些呢就是 通过抽象策略算法类减少代码的复杂性,继而通过 Spring 的一些特性同时满足了开闭原则,现在来了新需求只要添加新的策略类即可,健壮易扩展
自己用肯定觉得不够,必要时候还得看看设计开源框架源码的大佬们如何在代码中运用策略模式的
在作者了解中,JDK、Spring、SpringMvc、Mybatis、Dubbo 等等都运用了策略设计模式,这里就以 Mybatis 举例说明
Mybatis 中 Executor 代表执行器,负责增删改查的具体操作。其中用到了两种设计模式,模版方法以及策略模式
Executor 代表了抽象策略接口,刚才说到的模版方法模式源自 BaseExecutor
Configuration 代表策略工厂,负责创建具体的策略算法实现类
SimpleExecuto、ReuseExecutor… 表示封装了具体的策略算法实现类
上述代码块发生在 Configuration 类中创建执行器 Executor,通过 executorType 判断创建不同的策略算法。
上述代码块并没有彻底消除 if-else,因为 Mybatis 中执行器策略基本是固定的,也就是说它只会有这些 if-else 判断,基本不会新增或修改。如果非要消除 if-else,可以这么搞,这里写一下伪代码
这种方式叫做 “查表法”,通过策略工厂实现消除 if-else 分支。最后,Mybatis 太过详细的设计这里不再赘述,有兴趣的小伙伴可以去把源码下载啃一啃
到了这里可能有读者看出了问题,策略模式就算消除了 if-else 但是如果添加新的策略类,不还是会违反开闭原则么?
没错,因为 Mybatis 本身没有引入 Spring 依赖,所以没有办法借助 IOC 容器实现开闭原则。Spring 是一种开闭原则解决方式,那还有没有别的解决方式?
解决方式有很多,开闭原则核心就是 对原有代码修改关闭,对新增代码开放。可以通过扫描指定包下的自定义注解亦或者通过 instanceof 判断是否继承自某接口都可以。不过, 项目如果用了 Spring 还是消停的吧
文章中图文并茂的方式介绍策略模式,通过价格优惠的场景,进而引用本文的重点:策略设计模式,相信小伙伴看完后都会有一定的收获
策略模式的本质依然是对代码设计解耦合,通过三类角色贯穿整个策略模式:抽象策略接口、策略工厂以及具体的策略实现类。通过细粒度的策略实现类避免了主体代码量过多,减少了设计中的复杂性
作者听到过很多小伙伴觉得自己做的都是 CRUD 工作,没有挑战性没意思。其实,我想说的是:业务代码一样牛逼,一样能体现程序员的水平。不一定非要高并发、大数据等场景。颇有一屋不扫何以扫天下的意思
最后抛出一个问题:出现 if-else 的代码,一定要使用策略模式优化么
如果 if-else 判断分支不多并且是固定的,后续不会出现新的分支,那我们完全 可以通过抽函数的方式降低程序复杂性;不要想法设法去除 if-else 语句,存在即合理。而且,使用策略模式会导致类增多,没有必要为了少量的判断分支引入策略模式
关于策略设计模式本文就讲到这里,后面会陆续输出工厂、原型、享元等模式;如果文章对你有帮助那就点个关注支持下吧,祝好。
参考文章
微信搜索【源码兴趣圈】,关注公众号后回复 123 领取内容涵盖 GO、Netty、Seata、SpringCloud Alibaba、开发规范、面试宝典、数据结构等学习资料!
本文转载自: 掘金
道哥的第 022 篇原创
在上一篇文章中物联网网关开发:基于MQTT消息总线的设计过程(上),我们聊了在一个物联网系统的网关中,如何利用 MQTT 消息总线,在嵌入式系统内部实现多个进程之间的相互通信问题。
这个通信模型的最大几个优点是:
- 模块之间解耦合;
- 各模块之间可以并行开发;
- 把 TCP 链接和粘包问题交给消息总线处理,我们只需要处理业务层的东西;
- 调试方便;
以上只是描述了在一个嵌入式系统内部,进程之间的通信方式,那么网关如何与云平台进行交互呢?
在上一篇文章中已经提到过:网关与云平台之间的通信方式一般都是客户指定的,就那么几种(阿里云、华为云、腾讯云、亚马逊AWS平台)。一般都要求网关与云平台之间处于长连接的状态,这样云端的各种指令就可以随时发送到网关。
这一篇文章,我们就来聊一聊这部分内容。
在公众号回复:mqtt,获取示例代码的网盘地址。
目前的几大物联网云平台,都提供了不同的接入方式。对于网关来说,应用最多的就是 MQTT 接入。
我们知道,MQTT 只是一个协议而已,不同的编程语言中都有实现,在 C 语言中也有好几个实现。
在网关内部,运行着一个后台 deamon: MQTT Broker,其实就是 mosquitto 这个可执行程序,它充当着消息总线的功能。这里请大家注意:因为这个消息总线是运行在嵌入式系统的内部,接入总线的客户端就是需要相互通信的那些进程。这些进程的数量是有限的,即使是一个比较复杂的系统,最多十几个进程也就差不多了。因此,mosquitto 这个实现是完全可以支撑系统负载的。
那么,如果在云端部署一个 MQTT Broker,理论上是可以直接使用 mosquitto 这个实现来作为消息总线的,但是你要评估接入的客户端(也就是网关)在一个什么样的数量级,考虑到并发的问题,一定要做压力测试。
对于后台开发,我的经验不多,不敢(也不能)多言,误导大家就罪过了。不过,对于一般的学习和测试来说,在云端直接部署 mosquitto 作为消息总线,是没有问题的。
下面这张图,说明了 Proc_Bridge 进程在这个模型中的作用:
- 从云平台消息总线接收到的消息,需要转发到内部的消息总线;
- 从内部消息总线接收到的消息,需要转发到云平台的消息总线;
如果用 mosquitto 来实现,应该如何来实现呢?
mosquitto 这个实现是基于回调函数的机制来运行的,例如:
1 | scss复制代码// 连接成功时的回调函数 |
以上代码就是一个 mosquitto 客户端的最简代码了,使用回调函数的机制,让程序的开发非常简单。
mosquitto 把底层的细节问题都帮助我们处理了,只要我们注册的函数被调用了,就说明发生了我们感兴趣的事件。
这样的回调机制在各种开源软件中使用的比较多,比如:glib 里的定时器、libevent通讯处理、libmodbus 里的数据处理、linux 内核中的驱动开发和定时器,都是这个套路,一通百通!
在网关中的每个进程,只需要添加上面这部分代码,就可以挂载到消息总线上,从而可以与其它进程进行收发数据了。
上面的实例仅仅是连接到一个消息总线上,对于一个普通的进程来说,达到了通信的目的。
但是对于 Proc_Bridge 进程来说,还没有达到目的,因为这个进程处于桥接的位置,需要同时连接到远程和本地这两个消息总线上。那么应该如何实现呢?
看一下 mosquitto_new 这个函数的签名:
1 | c复制代码/* |
最后一个参数的作用是:可以设置一个用户自己的数据(作为指针传入),那么 mosquitto 在回调我们的注册的任何一个函数时,都会把这个指针传入。因此,我们可以利用这个参数来区分这个连接是远程连接?还是本地连接。
所以,我们可以定义一个结构体变量,把一个 MQTT 连接的所有信息都记录在这里,然后注册给 mosquitto。当 mosquitto 回调函数时,把这个结构体变量的指针回传给我们,这样就拿到了这个连接的所有数据,在某种程度上来说,这也是一种面向对象的思想。
1 | arduino复制代码// 从来表示一个 MQTT 连接的结构体 |
完整的代码已经放到网盘里了,为了让你先从原理上看明白,我把关键几个地方的代码贴在这里:
1 | c复制代码// 分配结构体变量 |
另外一个问题:不知道你是否注意到示例中的 mosquitto_loop() 这个函数?这个函数需要放在 while 死循环中不停的调用,才能出发 mosuiqtto 内部的事件。(其实在 mosuiqtto 中,还提供了另一个简化的函数 mosquitto_loop_forever)。
也就是说:在每个连接中,需要持续的触发 mosquitto 底层的事件,才能让消息系统顺利的收发。因此,在示例代码中,使用两个线程分别连接到云平台的总线和内部的总线。
经过这两篇文章,基本上把一个物联网系统的网关中,最基本的通信模型聊完了,相当于是一个程序的骨架吧,剩下的事情就是处理业务层的细节问题了。
万里长征,这才是第一步!
对于一个网关来说,还有其他更多的问题需要处理,比如:MQTT 连接的鉴权(用户名+密码,证书)、通信数据的序列化和反序列化、加密和解密等等,以后慢慢聊吧,希望我们一路前行!
在公众号回复:mqtt,获取示例代码的网盘地址。
【原创声明】
转载:欢迎转载,但未经作者同意,必须保留此段声明,必须在文章中给出原文连接。
不吹嘘,不炒作,不浮夸,认真写好每一篇文章!
欢迎转发、分享给身边的技术朋友,道哥在此表示衷心的感谢!
利用C语言中的setjmp和longjmp,来实现异常捕获和协程
本文转载自: 掘金
摘要:这些场景,你是怎么写的代码?
if-else,这是个再正常不过的coding习惯,当我们代码量小的时候用来做条件判断是再简单不过的了。但对于优秀程序员来说,这却不是好代码。
不信你往下看…
假设有如下代码
通过对判断条件取反,代码在逻辑表达上会更加清晰
2.1 简化1级判空
假设有如下代码
使用Optional后
2.2 简化多级判空
假设有如下代码
使用Optional后
对于没有else的场景,使用ifPresent即可
假设有如下代码:
这就是不要根据不同的参数类型走不同的代码逻辑,这种场景很常见,他还会以switch-case的方式出现:
不同的代码逻辑就代表了不同的策略,我们可以通过如下几个方式改写。
3.1 多态
具体的策略对象可以放在一个Map中,优化后的实现类似如下
关于如何存放到Map中也两个可以参考的方式。
3.1.1 静态表
3.1.2 Spring托管下的动态注册
定义一个注册中心用于接受注册信息
将每个Strategy交由Spring管理,并在构造后注册
使用方式就变成了
3.2 枚举
采用多态会额外产生很多策略类,如果我们已经预先将petType定义成了枚举,就会发现可以把Strategy中的invoke()方法放到枚举中,从而完成了一种映射关系。
这样在调用时的代码就类似如下:
3.3 函数式简化策略
同样面对多态会额外产生很多策略类的问题,除了枚举我们还可以使用函数式的方式来改写,这里有个前提最好是策略的内容不会过于复杂,不然在代码的可读性上会比较差
同样我们会有一个map静态表,不过map里面存放的是lambda
使用方式则变成了
本文分享自华为云社区《改写if-else的几个思路》,原文作者:技术火炬手。
本文转载自: 掘金
在上一篇Spring Security 实战干货:OAuth2授权回调的核心认证流程中,我们讲了当第三方同意授权后会调用redirectUri发送回执给我们的服务器。我们的服务器拿到一个中间授信凭据会再次进行认证,目的是为了获取Token。而这个逻辑由OAuth2LoginAuthenticationProvider负责,经过上一文的分析后我们发现获取Token的具体逻辑由OAuth2AuthorizationCodeAuthenticationProvider来完成,今天就把它的流程搞清楚,来看看Spring Security OAuth2 认证授权获取Token的具体步骤。
注意:本Spring Security干货系列教程的OAuth2相关部分是在Spring Security 5.x版本的。
该类是AuthenticationProvider针对OAuth 2.0中Authorization Code Grant模式的实现。关于AuthenticationProvider有必要简单强调一下,它已经多次在Spring Security干货系列中出现,十分重要!一定要去看看相关的分析和使用,它是你根据业务扩展认证方式渠道的重要入口。
在该实现中包含了一个OAuth2AccessTokenResponseClient成员变量,它抽象了通过tokenUri端点从认证服务器获取Token的细节。你可以根据OAuth 2.0常用的四种模式来进行实现它, 以达到根据不同的策略来获取Token的能力。
在Spring Security 5中OAuth 2.0登录的配置中默认使用DefaultAuthorizationCodeTokenResponseClient。如果你想使用自定义实现的话可以通过HttpSecurity来配置:
1 | java复制代码 @Override |
接下来我们看看DefaultAuthorizationCodeTokenResponseClient实现的获取Token的逻辑:
1 | java复制代码@Override |
这里的方式跟我另一个开源项目Payment Spring Boot的请求方式异曲同工,都是三个步骤:
RequestEntity。RestOperations发起请求。ResponseEntity组织返回值。如果有些的OAuth 2.0认证服务器获取Token的方式比较特殊你可以自行实现OAuth2AccessTokenResponseClient。
OAuth2AccessTokenResponseClient是OAuth2AuthorizationCodeAuthenticationProvider的核心要点。搞清楚它的作用和机制就可以了。这里我们总结一下OAuth2AuthorizationCodeAuthenticationProvider的认证过程:
OAuth2AuthorizationCodeAuthenticationToken的状态是否合法。OAuth2AccessTokenResponseClient请求OAuth 2.0认证服务器获取Token等信息。OAuth2AuthorizationCodeAuthenticationToken返回。到此OAuth 2.0的登录流程就搞清楚了,读者可通过系列文章进行学习批判。我是:码农小胖哥,多多关注,获取实用的编程干货。
关注公众号:Felordcn获取更多资讯
本文转载自: 掘金
本文使用两种方法介绍 Spring Boot WebFlux 使用 R2DBC 连接 MySQL:
相关技术点:WebFlux、R2DBC 等技术请自行了解。
Spring Boot WebFlux 使用 R2DBC 技术连接 MySQL,首先需要在 WebFlux 项目的基础上导入以下两个依赖:
1 | xml复制代码<dependency> |
在 Spring Boot WebFlux 项目中创建目录 config,添加以下两个配置 Java 类即可。
ConnectionFactoryConfiguration.java 配置类,用来配置 MySQL 的连接信息。如下:
1 | java复制代码package com.codergeshu.webfluxr2dbc.config; |
R2dbcConfiguration.java 配置类,用来启用 R2DBC 技术连接 MySQL。代码如下:
1 | java复制代码package com.codergeshu.webfluxr2dbc.config; |
至此使用配置类方式就完成了使用 R2DBC 连接 MySQL,之后就可以使用 ReactiveCrudRepository 进行相关数据库操作了。
除了使用上述两个配置 Java 类外,我们还可以使用 application.yml 文件进行 R2DBC 连接 MySQL 的配置,内容如下:
1 | java复制代码spring: |
其配置信息类似于 ConnectionFactoryConfiguration.java 和 R2dbcConfiguration.java 的结合体。
以上两种方法都能够使 WebFlux 项目使用 R2DBC 连接到 MySQL,选择其中一种方法即可,推荐选择 application.yml 配置文件,毕竟比较清晰且容易管理。
大家好,我是 CoderGeshu,一个热爱生活的程序员,如果这篇文章对您有所帮助,还请大家给点个赞哦 👍👍👍
另外,欢迎大家关注本人同名公众号:CoderGeshu,一个致力于分享编程技术知识的公众号!!
一个人可以走的很快,而一群人可以走的很远……
本文转载自: 掘金