Git Product home page Git Product logo

ghiblog's Introduction

Highlighted projects:

  • visitor-badge, a visitor count badge generator service for your Github Markdown files

我还在维护一个科技周刊, 每周分享 10 个有趣的链接, 欢迎关注.

views since 2023/06/14

ghiblog's People

Contributors

jwenjian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ghiblog's Issues

我给GitHub的README做了个访客数量统计功能

readme-visitor-badge

这是什么

一个统计README页面被打开多少次的badge生成服务, 其实原理上可以应用在任何可以显示svg的markdown/issue/html上, 当你每次打开这些页面, 浏览器就会向服务器发送一个请求, 将对应的访问数量加1, 之后生成最新的svg返回给浏览器.

技术点

  1. badge的生成, 直接使用了google的开源项目pybadges, 非常简单
  2. 利用Flask写了非常简单的web服务, 接受请求, 缓存访问量, 生成svg并返回

遇到的问题

  1. 缓存

Github使用了camo作为图片的代理服务器, 当你审查README上的图片元素时, 你会发现所有的图片都不是指向真实的服务器地址, 而是一串https://camo.githubusercontent.com/xxxxxxxxxxxxxxxxxxxxxxxxx/yyyyyyyyyyyyyyy/zzzzzzzzzzzzzzzz.jpg的网址, 如下:
image

而camo的服务器会对被代理的图片进行缓存, 使得当第一次刷新页面时, camo会像badge生成服务发起请求, camo记录访问次数为1, 之后再次刷新页面, camo会缓存这个badge图片, 从而无法达到我们想要的效果.

经过一番搜索和研究发现, 在badge生成服务返回的http响应的header中, 需要动一些小手脚:

  1. Cache-Control
    设置Cache-Control的内容为no-cache,max-age=0, 告诉camo服务器在使用缓存之前进行验证

  2. Expires
    这里我手动将资源的过期时间设置成了当前时间减去10分钟

这样的话, 当用户打开README页面之后, camo服务器在返回缓存内容之前, 会像源服务器发起请求, badge生成服务收到请求之后会将访问量加1并生成相应的svg内容同时携带以上2个header信息返回.

而正是由于这两个header的设置, camo服务器发现缓存的资源在10分钟之前已经过期, 于是就将最新的svg返回给了浏览器.

使用方法

在你的README里面, 添加一个图片:

![Total visitor](https://visitor-count-badge.herokuapp.com/total.svg?repo_id=${这里放你的repo对应的唯一的字符串, 如用你的github用户名+仓库名, 总之保持唯一就好了})

如 ![Total visitor](https://visitor-count-badge.herokuapp.com/total.svg?repo_id=jwenjian.ghiblog.issue.43)就会统计当前issue的总访客数量, 如下图, 刷新下这个页面试试?

Total visitor

下一步计划

  1. 当前方案没有对这些访问量进行持久化, 下一步是研究如何使用heroku的数据库来进行持久化

所以如果你哪天发现你的访问量突然从0开始了, 还请见谅 :(

  1. 新增生成当天访问量的badge
  2. 新增生成最近7天/30天访问量折线图的badge

青岛之行随拍

📅 6.28-6.30
📍 青岛

❗️ 多图预警 ❗️

第一天

  • 北京 -> 青岛
  • 第三海水浴场, 团建
    IMG_3189
    IMG_3191
    IMG_3199
    IMG_3200
    IMG_3201
    IMG_3205

第二天

  • 崂山上清宫
  • 崂山太清宫
    IMG_3221
    IMG_3228
    IMG_3246
    IMG_3256
    IMG_3258
    IMG_3283
    IMG_3286
    IMG_3291
    IMG_3312
    IMG_3319

第三天

  • 青岛奥帆中心
  • 八大关
  • 第二海水浴场
  • 青岛 -> 北京
    IMG_3347
    IMG_3349
    IMG_3352
    IMG_3357

IMG_3375
FullSizeRender
IMG_3383
IMG_3396
IMG_3401

How to add custom properties to manifest file with spring boot

  1. Add maven-jar-plugin or maven-war-plugin into your pom.xml depending on your packaging type, will use maven-jar-plugin for example.
  2. Config the maven-jar-plugin as below:
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Checkpoint>${buildNumber}</Checkpoint>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
  1. Thus will add new property Checkpoint to MANIFEST.MF

Refer to https://stackoverflow.com/questions/26865851/adding-properties-to-manifest-file-with-spring-boot

2019年的第一次旅行

文章迁移自Hexo

2019.1.12

离职后的第一天, 和同学一起坐城铁从郑州到焦作, 看下4年后的理工大.

👉👉👉

出发

飞猪上买了城铁票, 1车无座, 结果上车之后发现1车只有很小的一个地方可以站人, 没有座位, 很奇怪. 乘务员说后面的车厢全是空的, 随便坐.
我们就走到2车, 上去后发现是一等座, 一个人都没有, 开心.

有了城铁之后, 郑州到焦作真的方便太多了, 34分钟, 28块钱.

到达

到了焦作火车站之后, 查了下公交线路(4年多过去了, 早就忘了哪路车是从火车站到学校的了😂), 结果发现43路车是一小时一班!!!

见下图👇👇👇

image

时间宝贵, 还是打了个🚕, 车费10块钱.

吃饭

到了学校西门外的商城区, 下车就往过桥米线店里走, 点了一份菌类过桥米线加燕饺, 17块钱(好便宜), 量足, 味道也很好😂.

下图绿色画笔圈出来的就是过桥米线的店👇👇👇

image

进入学校

本来想和外出的学生一起混进去的, 结果还是被门卫喊住要看学生证, 只好实话实说:

学生证呢?

去学校干嘛?

回学校看看

以前毕业的学生是吧?

哪一届的?

10届

(摆摆手)进去吧进去吧...

✌✌✌

多图预警❗❗❗

  • 小白车

image

  • 馨月湖

image

  • 图书馆

image

  • 运动场
    image

  • 快递中心

image

  • 餐厅

image

  • 六子裹凉皮

image

  • 西门

image

  • 皇家理工荞麦面

image
image

  • 洗浴中心

image

还有很多图就不一一贴了, 主要因为iPhone8拍出来的图, 一个都10Mb多, 太大了, 估计会影响网页加载....

回程

回程的时候还是只能买到无座票, 结果上车还是到2车的一等座, 开心😂.

今天这趟旅程, 是从北京回来之后最轻松的一次旅行(好像是唯一的一次🤣), 辞职之后真的是一身轻松.

[From Instapaper] : **为什么不搞多党竞争甚至一些党员干部都不知怎么回答

**为什么不搞多党竞争?甚至一些党员干部都不知怎么回答

“ **政治文化传统决定了,如果**的执政党也像西方政党那样只代表部分人的利益的话,这个政党将被人民抛弃。 ” 7月1日晚,在东方卫视《这就是**》第24期节目中,主讲人、复旦大学**研究院院长张维为教授讲述了如何从历史传承和国际比较中读懂**共产党,并提出了政治制度竞争的三条标准。 张维为:…



July 9, 2019 at 03:19PM

via Instapaper https://ift.tt/2S7KLWn

Python操作剪贴板

安装依赖

pip install pyperclip

示例代码

import pyperclip

def copy_to_clipboard(command: str):
    pyperclip.copy(str(command))

if __name__ == '__main__':
    copy_to_clipboard("Hello, world!")
    copied_str = pyperclip.paste()
    print(copied_str) # Hello, world!

gist
pyperclip

C++: 引用和指针

C++ 引用 vs 指针
引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

对于第二个不同点, 网上举了很多例子, 比如:
image

最开始被例子中的注释// error,引用不能换了给误导, 以为这样写的话, 编译器就会报错而无法运行, 其实不然.

引用不能指向另外一个对象的意思是, 如果一个引用初始化时指向对象a, 那么对该引用再次赋值成对象b就相当于给对象a再次赋值, 其值为对象b的地址对应的值, 而不是将该引用指向对象b

int var_a = 1;
int& ref_var_a = var_a;
int var_b = 2;

此时执行ref_var_a = var_b;, 相当于执行var_a = var_b; 通过下面这段代码和output会更加明显.

#include <iostream>

int main()
{
	int var_a = 1;
	int& ref_var_a = var_a;
	int var_b = 2;


	std::cout << "var_a = " << var_a << std::endl;
	std::cout << "var_a's address = " << &var_a << std::endl;
	std::cout << "ref_var_a = " << ref_var_a << std::endl;
	std::cout << "ref_var_a's address = " << &ref_var_a << std::endl;
	std::cout << "var_b = " << var_b << std::endl;
	std::cout << "var_b's address = " << &var_b << std::endl;

	ref_var_a = var_b;

	std::cout << "========== ref_var_a = var_b =======" << std::endl;

	std::cout << "var_a = " << var_a << std::endl;
	std::cout << "var_a's address = " << &var_a << std::endl;
	std::cout << "ref_var_a = " << ref_var_a << std::endl;
	std::cout << "ref_var_a's address = " << &ref_var_a << std::endl;
	std::cout << "var_b = " << var_b << std::endl;
	std::cout << "var_b's address = " << &var_b << std::endl;

}

对应的output如下:

image

可以看出:

  1. ref_var_a的地址在执行ref_var_a = var_b前后始终没变: 0015F8A8
  2. var_a的地址对应的值在ref_var_a = var_b之后变成了var_b的地址对应的值: 2
  3. 由于var_a的值发生了变化, 而ref_var_a指向var_a, 所以之后ref_var_a的值也变成了2

bye 2018

文章迁移自Hexo

又到年底了.

现在是2018年12月31日22时13分.

又到跨年了, 今天下午去看了场电影, <来电狂响>, **版的完美陌生人, 总体来说还算可以, 剧情基本上是按照原来的套路发展的, 好像是比原著多了些感人的场景比如饿了么外卖员的送餐, 也算对得起豆瓣的评分了.

说到这个电影, 又要忍不住开始吐槽了, 这种电影竟然还有家长带孩子过来看的, 真的是搞不懂.

👉👉👉

最近特别享受看完电影之后从电影院走到家的一段路程. 厚厚的羽绒服帽子, 带上耳机, 音量开到80%左右, 打开网易云音乐, 不慌不乱的慢慢走回去, 一边回忆电影剧情, 一边胡思乱想, 让**神游.

2018年, 不, 2017年底, 我做出了一个决定, 不是艰难的决定, 当时做决定时并没有太多犹豫.

2017年圣诞节, 2018元旦, 跟随着这个决定, 我从北京回来了.

在郑州的这一年, 感受就是一个字: 累

从最开始的加班赶项目, 到后来的开始带后台+接口开发, 简单梳理一下大致的工作内容:

  1. 将原来的bootstrap+vuejs的后台管理页面迁移到vuejs+element-ui
  2. springboot单应用拆分dubbo分布式
  3. druid数据源(动态切换)
  4. gitlab平台搭建及相关git规范建立
  5. 基于BlockingQueue的1v1视频聊天匹配
  6. ELK日志平台搭建
  7. 数据库表结构设计
  8. 基于redis的分布式锁解决高并发问题
  9. 基于rocketmq对后台业务进行解耦拆分
  10. 短网址生成&还原&跳转
  11. 双向SSL的生成及与移动端联调
  12. 基于NGINX的负载均衡配置
  13. 谷歌支付本地验证
  14. 接口查询优化
  15. nodejs工程实现直播间机器人进直播间及发送预定义发言内容
  16. 基于quartz的定时任务实现指定时间(年月日时分秒)执行任务, 实现如活动结束后自动发奖及通知等类似功能
  17. 基于腾讯IM的系统小助手(类公众号)的设计及开发
  18. 极光推送
  19. monit实现进程监控
  20. gitlab持续集成实现vuejs工程代码格式化检查和打包
  21. gitlab+sonarqube实现持续代码质量检查
  22. 自定义springboot starter开发
  23. springboot+vuejs+webuploader实现大文件分片上传
  24. ... ...

一年的时间, 而已.

另外对于自己这部分, 大体上没有做太多事情, 主要是因为工作上的事情太忙:

  1. 重新拾起来了我的github pages, 之后会陆续的补一下这一年里遇到的一些技术或者碰见的问题等.

  2. 尝试了使用typecho进行博客网站搭建

  3. 了解flutter

  4. 写了一个谷歌浏览器插件(还未发布到应用商店)

  5. 尝试建立一个基于印象笔记的博客生成系统, 主要想法是利用印象笔记的客户端(安卓/IOS/PC/浏览器插件/微博集成)进行日常工作&生活中的记录和存储, 然后注册印象笔记的开发者, 基于webhook触发请求, 同步所有印象笔记, 动态生成hexo博客内容并发布到github pages, 这样以后写博客就可以不用把仓库克隆到本地, 直接使用印象笔记就可以了. 如果这个真的实现了, 真的挺好的, 但是实现的过程中遇到了几个问题:

    a. 由于政策原因, 印象笔记不允许外链分享

    b. 通过印象笔记sdk获取的印象笔记内容是一个自定义的xhtml的页面, 而且里面的图片/附件等内容没有外链, 这样会导致生成的博文不正确

    c. 申请印象笔记开发者邮件没有得到回复, 无法继续.

总的来说, 这一年倒不算浪费, 至少有机会去接触到以前没有用到的技术.

但是还是要离开, 最主要是郑州的公司, 大部分, 不, 绝大部分都没有一个规范的软件开发流程, 包括文档, 需求分析, 架构设计, 缺陷管理, 代码质量控制, 服务器监控及运维等等.

开发需要兼职:

  • 数据库表设计
  • 代码架构设计
  • 服务器运维
  • 服务部署
  • 需求分析
  • ... ...

而且还不止这些.

种种不合乎规范的事情集中到一起, 最终的结果就是做出来的东西虽然表面看起来可以用, 但是开发人员自己知道这项目到底质量如何, 奇怪的郑州的老板都不关心这些.

神奇.

不说这些了, 让所有的不愉快留在2018年吧.

听首歌, 准备迎接新的一年!!!

未完待2019年续.

智能屏幕护眼软件: f.lux

f.lux

image

下载安装之后, 需要输入所在位置的zip code或者经纬度, 这个软件会根据所在地的日出日落时间调整屏幕的色温, 比如现在(北京, 22:44)的显示如下图:

image

zip code应该是对应国内的邮政编码

CSS隐藏元素滚动条

最近在用vuejs+element-ui搭建一个后台管理系统,UI布局定的是左侧导航栏和顶部导航栏相结合。

左侧导航栏css:

.side-bar {
  position: fixed;
  left: 0;
  top: 0;
  width: 200px;
  height: 100%;
  overflow-y: hidden;
}

结果由于模块太多, 左侧导航栏高度超过了屏幕高度,之前overflow-y设置成了hidden,就导致了超出屏幕高度的部分无法显示.

解决办法是将overflow-y设为auto, 这样的话, 如果左侧导航栏的高度超过了屏幕高度, 则在导航栏右侧显示一个滚动条。

功能上满足了, 但是这个滚动条也太丑了点吧 💔

一番google之后, 找到了解决方案:

添加下面的css代码, 既可以隐藏.side-bar的滚动条,又不影响滚动效果, 完美解决 👍️

.side-bar::-webkit-scrollbar{
  display: none;
}

不过据说是只有在webkit内核的浏览器内有效,非webkit内核浏览器未测试。

Maven: mvn clean install --fail-at-end

--fail-at-end - if a particular module build fails, continue the rest of the reactor and report all failed modules at the end instead

https://maven.apache.org/guides/mini/guide-multiple-modules.html

For example, you have a project with 1 parent pom and several modules:

projects/

  • module_a/
    • pom.xml
  • module_b/
    • pom.xml
  • module_c/
    • pom.xml
  • pom.xml

Let's assume that the module_a is missing a.jar, module_c is missing c.jar.

When you execute command mvn clean install in the project folder, you will failed and know that module_a is missing a.jar.

You will not know that module_c has dependency issue because maven stoped continue building, so you fix the module_a's issue, run the command again, the module_c's issue is waiting for you, suprize!


With the command line option --fail-at-end, maven will continue the rest of the reactor and report all failed modules at the end, so that you can know that module_a and module_c both have dependency issue, module_a missing a.jar and module_c missing c.jar.

It's helpful!

But no suprize anymore, it's up to you 😈

Windows截图工具-Snipaste

Snipaste

Snipaste 是一个简单但强大的截图工具,也可以让你将截图贴回到屏幕上!

以前一直用onenote的截图工具, 打开之后按下Win+S键就直接可以截图, 但是软件升级到16001之后找不到截图工具了, 据说是没有了 👉 Win10自带的OneNote如何截图

Snipaste:

  • 免费
  • 无广告
  • 小巧
  • 功能丰富

唯一一点是修改截图快捷键的时候, 没有办法设置成Win+S, 一按Win键, 就弹出系统菜单了, 猜测是软件没有(无法?)捕获Win键?

我们的生活多愉快~

image

点击 ⬆️ 图感受生活的愉快.

🎵
大姐姐你呀赶快来,
小弟弟你也莫躲开,
手拉这手啊唱起那歌啊,
我们的生活多愉快,
娃哈哈啊娃哈哈啊
我们的生活多愉快~

😄 😄 😄

insshot: 自动截屏保存ins用户的最新post

insshot

这个项目的触发点是 -> 林志玲宣布婚讯, 微博上有人贴出了林志玲ins的po文, 但是由于众所周知的原因, 没办法上ins上看看原po.

经过了大概3天的头脑风暴+coding, 才有了现在的这个项目.

What

insshot的功能:

  1. 从github读取label列表, 我把label当成了数据库了, 这样每次想增加一个ins用户不需要手动提交了
  2. 借助puppeteer, 对每个用户的ins主页进行解析, 获取到最新的post链接
  3. 打开最新的post页面, 选取图片和文字区域, 截图到本地
  4. 调用阿里云oss的api, 将截图保存到阿里云oss中, 以便之后在手机上访问

总体思路是, 借助circle-ci的运行环境(主要是网络环境), 访问instagram, 截图保存成文件, 将文件保存至本地网络可以访问的阿里云oss上, 绕了(GFW)一圈.

How

主要的几个关键点:

  1. 在github上创建了一个token, 用token访问github的api
  2. 借助puppeteer, 解析instagram的网页, 找到需要截图的区域, 截图保存至本地
  3. 创建阿里云oss的bucket, 调用阿里云oss的api, 将截图文件发送到oss, 供本地访问
  4. 创建一个快捷指令, 用于在手机上快速查看用户的最新ins的po文

实现过程中遇到的问题:

  1. Instagram的post详情页面, 如果用户处于未登录状态, 则右侧文本区域只显示最新的评论, 而不是po主发文时输入的文字, 解决方案是模拟页面滚动, 将po主的文本滚动到可视区域之后, 再进行截图操作
  2. 阿里云的oss选择香港节点, 否则circle-ci在调用时会一直超时

其他

快捷指令

获取快捷指令 -> InsShot

使用方法, 点击设置之后, 见第一条注释.

使用截图:
image

image

供学习, 参考

pydice: Python的GUI应用 - 课堂点名工具

pydice

先上截图:

pydice

心血来潮花费2个晚上制作的一个小公举工具, 使用方法如下:

  1. 选择一个包含多个图片的文件夹
  2. 点击开始, 程序会快速的把文件夹中的图片读取并渲染在canvas上, 同时下方显示图片的文件名
  3. 点击停止, 程序会显示停止这一刻的图片及其文件名

基于此, 可应用到课堂点名, 抽奖等业务场景中.

比如课堂点名, 首先将所有学生的照片以各自的姓名命名放到同一个文件夹内, 打开程序, 选择该文件夹, 点击开始, 屏幕上会快速显示每个学生的照片及其姓名, 点击停止, 则当前屏幕的照片及学生姓名即被选中.


  • 项目依赖pillow库来处理.jpg的图片格式: pip install pillow
  • 界面布局依赖 PAGE

书单

文学

  • [√] 摆渡人
  • [√] 三体
  • [√] 那些古怪又让人忧心的问题what if?
  • [√] 本书书名无法描述书本内容: 一场逗你玩的哲学探险
  • [√] 如何培养逻辑脑: 聪明人都在玩的逻辑游戏
  • [√] 如果世界上不再有猫
  • [√] 白夜行
  • [√] 孤独深处(收录郝景芳雨果奖作品: 北京折叠)
  • [√] 有狐: 给我来个小和尚
  • [√] 幻夜
  • [√] 放学后
  • [√] 解忧杂货店
  • [-] 神秘岛
  • [√] 最璀璨的银河: 刘慈欣经典作品合集
  • [√] 十一字杀人
  • [√] 民调局异闻录
  • [√] 虚无的十字架
  • [√] 信
  • [√] 恶意
  • [√] 时间移民
  • [√] 梦幻花
  • [√] 时间简史
  • [√] 赡养人类

计算机

  • [√] Effecttive Java中文版(第2版)
  • [√] 写给大忙人看的Java SE 8
  • [√] 小程序 巧应用: 微信小程序开发实战
  • [√] 图解HTTP
  • [-] 深入理解Java虚拟机: JVM高级特性与最佳实践(第2版)
  • [-] 图解TCP/IP
  • [] 图解网络硬件
  • [-] 鸟哥的Linux私房菜(基础学习篇 第三版)

转载-浅谈 Python 的 with 语句

with 语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from future import with_statement 导入后才可以使用),从 2.6 版本开始缺省可用(参考 What's new in Python 2.6? 中 with 语句相关部分介绍)。with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

摘自: 浅谈 Python 的 with 语句

关于浏览器自动填充

先回顾个新闻: W3C将与WHATWG合作制定最新HTML和DOM规范

接下来再贴一个谷歌浏览器的issue, Issue 468153: autocomplete=off is ignored on non-login INPUT elements

W3C关于autocomplete属性的定义:

定义和用法

autocomplete 属性规定输入字段是否应该启用自动完成功能。

自动完成允许浏览器预测对字段的输入。当用户在字段开始键入时,浏览器基于之前键入过的值,应该显示出在字段中填写的选项。

注释:autocomplete 属性适用于

,以及下面的 类型:text, search, url, telephone, email, password, datepickers, range 以及 color。

语法

<input autocomplete="value">

取值

描述
on 默认。规定启用自动完成功能。
off 规定禁用自动完成功能。

按照W3C的标准, 对于input等标签来说, 默认启用了自动完成, 浏览器就可以在你点击这些标签的时候给你推荐之前输入的值.

如果你不想让浏览器在某些输入框上启动自动完成, 比如登录界面的验证码输入框, 由于每一次验证码都不一样, 所以让浏览器推荐之前输入的验证码的值是无意义的, 这个时候可以通过设置autocomplete=off来告诉浏览器.

但是.

在上面贴出的谷歌浏览器的issue中, 有人发现谷歌浏览器无视了页面元素中autocomplete=off的设置, 仍然对这些元素进行自动填充和输入提示.

开发者对这个issue的回复如下:

bu fan yi le

First off, thanks for everyone's feedback on this. I apologize for our delay in clarifying our stance. We've been working to finalize our policy regarding Autofill and the autocomplete attribute, and we've been making changes to this over the past few months (as some of you have noticed).

First and foremost, Autofill in Chrome exists to help our everyday users get through common forms (address forms, contact forms, checkout forms, etc) across the web. This has become especially important on mobile devices, where typing on virtual keyboards is both difficult and annoying. Autofill tries to make this experience better, and it's used millions of times per day by Chrome users.

The tricky part here is that somewhere along the journey of the web autocomplete=off become a default for many form fields, without any real thought being given as to whether or not that was good for users. This doesn't mean there aren't very valid cases where you don't want the browser autofilling data (e.g. on CRM systems), but by and large, we see those as the minority cases. And as a result, we started ignoring autocomplete=off for Chrome Autofill data [1].

We don't just ignore the autocomplete attribute, however. In the WHATWG standard, we defined a series of new autocomplete values that developers can use to better inform the browser about what a particular field is, and we encourage developers to use those types. [2]

In cases where you really want to disable autofill, our suggestion at this point is to utilize the autocomplete attribute to give valid, semantic meaning to your fields. If we encounter an autocomplete attribute that we don't recognize, we won't try and fill it.

As an example, if you have an address input field in your CRM tool that you don't want Chrome to Autofill, you can give it semantic meaning that makes sense relative to what you're asking for: e.g. autocomplete="new-user-street-address". If Chrome encounters that, it won't try and autofill the field.

We encourage developers to take advantage of Autofill. We announced during the Chrome Dev Summit in 2015 that when Autofill is enabled we see 25% more forms submitted than when it's disabled [3]. Users find high value in Autofill, and we want to encourage users and developers to continue to take advantage.

着重看下上面我加粗的部分.

所以, 如果你想在谷歌浏览器中让你的HTML标签禁止自动填充和自动完成, 那么就给这些标签的autocomplete属性设置一个有意义的值, 如: captcha-for-login, user-address, do-not-autocomplete-this-one等等.

另外, 如果你发现你的网站的页面没有显式的禁用自动填充和自动完成, 但是在谷歌浏览器中这个功能一直不生效, 很有可能是因为谷歌浏览器认为你的网站不够安全. 具体参照谷歌浏览器的帮助文档:

Chrome doesn't suggest my saved info
If you don't get suggestions when you fill in a form, either:

  • The website might not be secure enough to get this info from Chrome. If the website is secure, learn how to fix issues with saved info.
  • Chrome might not detect certain fields in the form.

参考

https://support.google.com/chrome/answer/142893?hl=en-GB
https://bugs.chromium.org/p/chromium/issues/detail?id=468153#c164
http://www.w3school.com.cn/tags/att_input_autocomplete.asp
https://gist.github.com/niksumeiko/360164708c3b326bd1c8

**色-收集**传统颜色的网站

设计UI时,配色占了很大一部分的工作,如果你不是专业的UI设计师, 很难对色彩具有很高的敏感度, 经常不知道哪个颜色更受大多数人欢迎。

**色,是一个非常漂亮且实用的网站,包含了非常多的**传统颜色,如玫瑰红,朱红,天青,胭脂,深竹月... ...

每个颜色都会提供RGB和CMYK值

名字好听,颜色也好看,列几个截图养养眼。

image

image

image

传送门

**色-**传统颜色

C++: Ignore warnings C4996

C4996 occurs when the compiler encounters a function or variable that is marked as deprecated by using a __declspec(deprecated) modifier, or when you attempt to access a function, class member or typedef that has the C++14 [[deprecated]] attribute.

To ignore the warnings, do in below ways:

  1. In cpp file
#pragma warning(disable : 4996)
  1. In Commond line:
    Using the /wd4996 command line option.

  2. In Visual Studio:

  • Open the Property Pages dialog for your project. For information on how to use the Property Pages dialog, see Property Pages.
  • Select the Configuration Properties, C/C++, Advanced page.
  • Edit the Disable Specific Warnings property to add 4996. Choose OK to apply your changes.

Refer to : https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2019

HSTS

前几天用谷歌浏览器访问一个网站, 浏览器提示您的连接不是私密连接, 原因是网站的证书过期了.

本想着要忽略掉这个错误继续访问的, 结果点击高级按钮之后, 并没有一个仍然访问的链接可以点击, 于是花了点时间研究了一下提示信息, 见下图

👇👇👇

image

图中最后一段话提到了您目前无法访问...... 因为此网站使用了HSTS.

那么HSTS是个啥❓ , 为什么使用了之后只要证书过期就无法访问❓

带着这个问题, 我跑到图书馆借了一本关于HTTPS的专业书Google了一下, 终于找到了答案.

🎉🎉🎉

HSTS, 全称: HTTP Strict Transport Security, 是国际互联网工程组织IETF正在推行一种新的Web安全协议, 它的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。

采用HSTS协议的网站将保证浏览器始终连接到该网站的HTTPS加密版本,不需要用户手动在URL地址栏中输入加密地址。

该协议将帮助网站采用全局加密,用户看到的就是该网站的安全版本。

HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。

非加密传输时设置的HSTS字段无效!!!

比如,https://xxx 的响应头含有Strict-Transport-Security: max-age=31536000; includeSubDomains
这意味着两点:

  1. 在接下来的一年(即31536000秒)中,浏览器只要向xxx或其子域名发送HTTP请求时,必须采用HTTPS来发起连接。比如,用户点击超链接或在地址栏输入 http://xxx/ ,浏览器应当自动将 http 转写成 https,然后直接向 https://xxx/ 发送请求。
  2. 在接下来的一年中,如果 xxx 服务器发送的TLS证书无效(如证书过期/证书中域名与实际访问域名不匹配等),用户不能忽略浏览器警告继续访问网站。

同时为了防止用户首次安装浏览器或者手动清除了本地关于HSTS网站的状态导致的安全问题, Chrome同时维护了一个叫做HSTS Preload List的网站列表, 访问这个列表中的网站默认使用HSTS规则, 如:

  • Google
  • Paypal
  • Twitter
  • Simple
  • Linode
  • Stripe
  • Lastpass

如果你自己的网站也开启了HSTS的支持并且希望将自己的网站放入这个列表中, 可以在这里提交申请.

HSTS目前已经被主流浏览器(Chrome, Firefox, Safari, Opera, Edge, IE)支持, 如果你的网站是HTTPS的, 不妨试着开启HSTS的支持, 强制客户端与服务器使用https协议进行数据的交换来提高安全性.

参考链接:

Nginx代理Oracle数据库连接

image

Nginx在1.9.0版本之后(当前最新版本为1.16.0)可以通过stream模块代理TCP连接.

基于这个功能, 可以将nginx用作数据库连接的反向代理服务器, 对外暴露端口的同时隐藏真实数据库服务器的IP地址.

步骤:

  1. 在代理服务器上安装Nginx, 这里假设代理服务器IP为192.168.1.80 各个版本的安装指南参见 -> 这里
  2. 配置stream模块, 这里假设真实服务器IP地址为192.168.1.100, 端口号为1521:
stream{
    server {
        listen 10521;
        proxy_connect_timeout 1s;
        proxy_timeout: 3s;
        proxy_pass: 192.168.1.100:1521;
    }
}

其中, listen指定代理服务器监听的端口号, proxy_pass指向真实数据库地址

  1. 启动Nginx
  2. 使用SQLPLUS/SQLDevelpoer连接代理服务器: 192.168.1.80:10521即可

代理MySQL服务器同理.

Python: 对数组进行选择排序

image

算法导论 第二章

Python实现

arr = [5, 2, 4, 6, 1, 3]

idx = 0
for i in range(0, len(arr)):
    idx = i
    for j in range(i + 1, len(arr)):
        if arr[j] < arr[idx]:
            idx = j

    arr[i], arr[idx] = arr[idx], arr[i]
    print(arr)

print(arr) # [1, 2, 3, 4, 5, 6]

中间结果如下:

[1, 2, 4, 6, 5, 3]
[1, 2, 4, 6, 5, 3]
[1, 2, 3, 6, 5, 4]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]

配置SpringBoot定时任务线程池

文章迁移自Hexo

在SpringBoot中可以通过@Scheduled 注解来定义一个定时任务, 下面这段代码定义了一个每隔十秒钟执行一次的定时任务:

@Component
public class ScheduledTaskDemo {
    private static final Logger logger = LoggerFactory.getLogger(ScheduledTaskDemo.class);

    @Scheduled(cron = "0/10 * * * * *")
    public void execute() {
        logger.info("Scheduled task is running... ...");
    }
}

此时启动SpringBoot应用, 可以在控制台看到这个定时任务每隔10秒钟打印一条log

2017-12-21 22:20:20.832 INFO 7424 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8000 (http)
2017-12-21 22:20:20.859 INFO 7424 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 12.134 seconds (JVM running for 14.156)
2017-12-21 22:20:30.002 INFO 7424 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : Scheduled task is running... ...
2017-12-21 22:20:40.001 INFO 7424 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : Scheduled task is running... ...
2017-12-21 22:20:50.002 INFO 7424 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : Scheduled task is running... ...

但是, 一切还没结束.

如果没有相关log显示, 检查是否在入口类或者Configuration类上添加了@EnableScheduling注解

在上面的相关代码中, 我们使用cron表达式来指定定时任务的执行时间点, 即从0秒开始, 每隔10秒钟执行一次, 现在我们再加一个定时任务:

@Component
public class SecondScheduledTaskDemo {
    private static final Logger logger = LoggerFactory.getLogger(ScheduledTaskDemo.class);

    @Scheduled(cron = "0/10 * * * * *")
    public void first() {
        logger.info("Second scheduled task is starting... ...");
        logger.info("Second scheduled task is ending... ...");
    }

}

现在再启动SpringBoot应用, 再看log:

2017-12-21 23:12:20.007 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is starting... ...
2017-12-21 23:12:35.013 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is ending... ...
2017-12-21 23:12:35.016 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.SecondScheduledTaskDemo : Second scheduled task is starting... ...
2017-12-21 23:12:35.016 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.SecondScheduledTaskDemo : Second scheduled task is ending... ...
2017-12-21 23:12:40.000 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is starting... ...
2017-12-21 23:12:55.001 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is ending... ...
2017-12-21 23:12:55.002 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.SecondScheduledTaskDemo : Second scheduled task is starting... ...
2017-12-21 23:12:55.002 INFO 13208 --- [pool-1-thread-1] c.e.demo.scheduled.SecondScheduledTaskDemo : Second scheduled task is ending... ...

注意log中定时任务执行的时间点, 第二个定时任务原本应该每隔10秒钟执行一次, 但是从23:12:20到23:13:55, 本该执行4次, 确只执行了2次.

难道是cron表达式不对?

No.

为了找到原因, 我们从@Scheduled注解的源码开始找:

 *
 * <p>Processing of {@code @Scheduled} annotations is performed by
 * registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
 * done manually or, more conveniently, through the {@code <task:annotation-driven/>}
 * element or @{@link EnableScheduling} annotation.
 *

划重点, 每一个有@Scheduled注解的方法都会被注册为一个ScheduledAnnotationBeanPostProcessor, 再接着往下看ScheduledAnnotationBeanPostProcessor:

	/**
	 * Set the {@link org.springframework.scheduling.TaskScheduler} that will invoke
	 * the scheduled methods, or a {@link java.util.concurrent.ScheduledExecutorService}
	 * to be wrapped as a TaskScheduler.
	 * <p>If not specified, default scheduler resolution will apply: searching for a
	 * unique {@link TaskScheduler} bean in the context, or for a {@link TaskScheduler}
	 * bean named "taskScheduler" otherwise; the same lookup will also be performed for
	 * a {@link ScheduledExecutorService} bean. If neither of the two is resolvable,
	 * a local single-threaded default scheduler will be created within the registrar.
	 * @see #DEFAULT_TASK_SCHEDULER_BEAN_NAME
	 */
	public void setScheduler(Object scheduler) {
		this.scheduler = scheduler;
	}

重点来了, 注意这句话:

If neither of the two is resolvable, a local single-threaded default scheduler will be created within the registrar.

这句话意味着, 如果我们不主动配置我们需要的TaskScheduler, SpringBoot会默认使用一个单线程的scheduler来处理我们用@Scheduled注解实现的定时任务, 到此我们刚才的问题就可以理解了:

23:12:20, 第一个定时任务在线程pool-1-thread-1开始执行, 由于我们没有配置scheduler, 目前这个线程池pool-1里只有一个线程, 在打印了starting日志之后, 这个线程开始sleep;第二个定时任务也准备执行, 但是线程池已经没有多余线程了, 只能等待.

23:12:30, 第一个定时任务还在sleep, 第二个定时任务还在等待.

23:12:35, 第一个定时任务sleep结束, 打印ending日志并结束, 此时线程池空闲, 第二个定时任务从等待状态直接开始执行, 执行结束之后, 线程池空闲.

23:12:40, 线程池空闲, 第一个定时任务执行, 打印starting日志, 开始sleep.

注意, 这里也有可能执行第二个定时任务, 看CPU了.

... ...

搞清楚这个流程之后, 解决这个问题就很简单了.

根据刚才注释的描述, 我们只需要提供一个满足我们需要的TaskScheduler并注册到context中就可以了.

@Configuration
public class ScheduledTaskConfiguration implements SchedulingConfigurer {

    /**
     * Callback allowing a {@link TaskScheduler
     * TaskScheduler} and specific {@link Task Task}
     * instances to be registered against the given the {@link ScheduledTaskRegistrar}
     *
     * @param taskRegistrar the registrar to be configured.
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(2);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }
}

上面的代码提供了一个线程池大小为2的taskScheduler, 现在再启动下SpringBoot看看效果.

2017-12-21 23:28:30.001 INFO 7972 --- [TaskScheduler-1] c.e.demo.scheduled.ScheduledTaskDemo : Second scheduled task is starting... ...
2017-12-21 23:28:30.001 INFO 7972 --- [TaskScheduler-2] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is starting... ...
2017-12-21 23:28:30.002 INFO 7972 --- [TaskScheduler-1] c.e.demo.scheduled.ScheduledTaskDemo : Second scheduled task is ending... ...
2017-12-21 23:28:40.001 INFO 7972 --- [TaskScheduler-1] c.e.demo.scheduled.ScheduledTaskDemo : Second scheduled task is starting... ...
2017-12-21 23:28:40.001 INFO 7972 --- [TaskScheduler-1] c.e.demo.scheduled.ScheduledTaskDemo : Second scheduled task is ending... ...
2017-12-21 23:28:45.002 INFO 7972 --- [TaskScheduler-2] c.e.demo.scheduled.ScheduledTaskDemo : First scheduled task is ending... ...

可以看到, 当线程池里有两个线程的时候, 这两个定时任务各自按照预定的时间进行触发, 互不影响了.

Eclipse网络代理配置

使用Eclipse时,尤其是在安装插件(Mercurial插件等)的时候,都需要从Eclipse market place去下载,而大多数朋友的网络直连eclipse market place会非常慢, 而且非常有可能会失败。

这个时候就需要配置Eclipse的网络代理,但是, 一定要注意:

不要配置socks代理!

如果你不小心配置了socks代理之后发现代理没有起作用, 就一定要清空socks代理, 然后重启eclipse。

stackoverflow链接:eclipse-kepler-not-connecting-to-internet-via-proxy

谷歌浏览器原生支持触控板快速前进后退

今天刷github trending时, 用触控板在trending repositories上左右滑来滑去, 突然发现屏幕左侧/右侧中间出现圆形的向左/向右箭头, 此时松开触控板, 浏览器会执行后退/前进动作, 见下图:

chrome

C++: jni.h: no such file or directory

C++代码中:

#include <jni.h>

Visual studio运行报错:

Cannot open include file: 'jni.h': No such file or directory

解决步骤(Visual Studio 2019):

  1. Project -> Properties -> VC++ Directories
    image

  2. 修改Include Didrectories, 添加本地${JAVA_HOME}/include${JAVA_HOME}/include/win32目录:
    image

基于Github Action自动生成并更新GitHub Issue博客的ReadMe

Why

现在很多人, 包括我, 在折腾了一堆个人博客的系统之后, 放弃了花哨的页面效果, 回过头来用Github Issue写博客.

但头疼的一点就是:
如果让其他人直接点到自己仓库的issues页面来看自己的文章的话, 只会看到issue的列表, 没有突出内容, 没有分类, 没有about me, 只有一条条的issue.

如果想解决上述的问题, 就要手动在发布issue之后, 手动更新README, 并且push到仓库, 那么你需要:

  • 一台电脑
  • 安装git
  • clone仓库
  • 修改README
  • push

很麻烦, 感觉慢慢没有了更新的动力 😢

How it works

利用Github Action提供的工作流, 结合GitHub的API来实现:

  1. 通过Github API获取当前仓库的信息, 如
  • 总issue数量
  • 总label数量
  • 每个label下的issues列表
  • 最新更新(创建)的是哪些issue
  1. 将这些信息组装出自己满意的README页面
  2. 更新仓库的README.md文件
  3. 提交README.md的变更到远程仓库, 到这里, 我们的痛点就解决了一半, 剩下就是将步骤1-4在创建issue, 修改issue, 删除issue, 为issue新增label, 从删除label等等的动作之后触发了。
  4. 集成Github Action, 设置触发条件为: on: [issues, issue_comment], 完成!

于是, 你只需要写Issue就好了, 剩下的交给Github Action 🎉

You want too?

如果你也想有一个自动更新的GitHub Issue博客, 那么参考以下步骤:

  1. fork此仓库到你的账号下
  2. 修改 .github/workflow/main.yml 的第 20, 25, 26, 30, 34行内容,具体改成什么你应该懂得。
  3. 在你的仓库中建以下几个label:

这些label目前是必须存在的,所以一定要先创建。

  • :+1:置顶
  • :framed_picture:封面
  • 开源
  1. 创建一个issue试试?

至此, 如果不出意外, 你的ghiblog的自动更新就完成了.

功能说明

置顶

只需要给你的issue打上 :+1:置顶 的标签即可。

封面图片

新建一个issue, 并给这个issue打上 :framed_picture:封面 标签,(最好只给一个issue打上此标签。)
这个issue中的所有评论内容都要遵循下面的格式:

图片
---
标题

如:

![致命女人 00_28_49 20191026-155316](https://user-images.githubusercontent.com/25657798/67616241-0132a080-f809-11e9-8bd9-319b65f6e3f0.png)
---
[ Why Women Kill ]

开源项目展示

这里只适用于展示自己的开源项目, 即自己账号下拥有的开源项目。

新建一个issue并设置label为: 开源, issue的标题为你的开源项目的仓库名称, issue的内容为你的开源项目的介绍。

如我的开源项目: jwenjian/gallery

那么issue的标题为gallery, issue的内容为: 基于Github issue的相册网站

调整Typora显示宽度

文章迁移自Hexo

吐槽Ubuntu下的typora:

  1. 命令行安装太慢, 太,慢,开了lantern还是很慢(不过这好像也怪不到别人...😓)
  2. 手动下载安装包, 启动, 不能自动的把软件图标添加到favorite, 所以, 是的, 我现在在用vscode写markdown。

Typora作为一款跨平台、有颜值的markdown编辑器, 除了上方被我吐槽的这两点, 基本上是一款非常令人满意的软件。

但是,就在昨天我用Typora来记录kafka的相关配置选项的时候发现了另外一个不太人性的地方, 默认展示渲染结果的宽度太窄了(github主题的最大宽度是860px, 你敢信💔?)。

#write{
    max-width: 860px;
    margin: 0 auto;
    padding: 20px 30px 40px 30px;
    padding-top: 20px;
    padding-bottom: 100px;
}

github.css

这种情况在你想贴一段代码, 或者加一个很多列的表格的时候尤为明显,导致本该一行显示的代码变成了两行显示或者表格区域下方多了一个x方向的滚动条,丑。 但是你翻遍Typora的配置项也找不到任何一个地方可以修改的地方。

PS.缩放字体也不行, 该丑的, 它还是丑。

不过好在Typora是用electron技术栈开发的软件,意味着你可以按下F12显示最熟悉的chrome控制台, 审查元素之后你就会发现(以github white主题为例), css文件中指定了最大宽度, 而且, 还是860px。

虽然不太懂为什么要这么做, 但是接下来就是我们要做的事情。

  1. 搜索安装目录下的github.css文件

linux下: ${TYPORA_HOME}/resources/app/style/themes/github.css

  1. 修改#white下的max-width为你想要的宽度, 像素值或者百分比, 建议80%.

重启Typora即可。

TKinter教程

先说点题外话, 我觉得学习任何语言或者新技术, 一定要有实际的问题或痛点驱动, 否则很难坚持下去.

最近在学习python, 今天突发奇想准备做一个小工具来解决工作中遇到的问题, Tkinter作为python内置的GUI库, 就这样被内定了.

正在看的教程在这里 👉 https://tkdocs.com/tutorial/onepage.html

教程里有一段是讲Geometry Management, 提到grid, 是这么说的:

Tk's "grid" is without a doubt one of the absolute best

接下来, ☕ 语言躺枪:

A poor geometry manager... well, all the Java programmers who have suffered through "GridBagLayout" please raise their hands.

🙌 🙌 🙌

😄

How to prevent XXE injection when convert xml to object in java

About XXE

According to OWASP, “An XML External Entity attack is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.”

Prevent XXE injection in Java using JAXB

        JAXBContext jaxbContext = JAXBContext.newInstance(AppConfig.class);

        // Prevent XXE
        XMLInputFactory xif = XMLInputFactory.newFactory();
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        XMLStreamReader xmlStreamReader = xif.createXMLStreamReader(Demo.class.getResourceAsStream("appconfig.xml"));

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

        AppConfig appConfig = (AppConfig) unmarshaller.unmarshal(xmlStreamReader);

        System.out.println(appConfig.toString());

References:

Maven: maven-dependency-plugin:get 通过命令行下载jar包到本地仓库 无需pom文件

Apache Maven Dependency Plugin

dependency:get resolves a single artifact, eventually transitively, from a specified remote repository.

根据上述文档, 我们可以用下面的命令来实现在命令行中下载指定的依赖包到本地仓库, 无需pom文件.

mvn -DgroupId=commons-io -DartifactId=commons-io -Dversion=1.4 dependency:get

如果执行成功, 命令行会输出如下信息:

[INFO] Resolving commons-io:commons-io:jar:1.4 with transitive dependencies
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  04:09 min
[INFO] Finished at: 2019-06-24T13:44:49+08:00
[INFO] ------------------------------------------------------------------------

参数:

  • artifact

按固定格式groupId:artifactId:version[:packaging[:classifier]]组成的依赖信息
所以上述示例也可以写成: mvn -Dartifact=commons-io:commons-io:1.4 dependency:get

  • artifactId
  • classifier
  • groupId
  • packaging
  • remoteRepositories

逗号分隔的远程仓库地址, 可选, 如果不填会用settings.xml中配置的信息

  • transitive

是否同时依赖包的所有依赖, 默认为是

  • version

Python: 对数组进行插入排序

image

算法导论 第二章

Python实现:

arr = [5, 2, 4, 6, 1, 3]

for i in range(1, len(arr) + 1):
    for j in reversed(range(1, i)):
        if arr[j - 1] > arr[j]:
            arr[j - 1], arr[j] = arr[j], arr[j - 1]

print(arr) # [1, 2, 3, 4, 5, 6]

上述命令输出:

before =      [5, 2, 4, 6, 1, 3]
after =       [2, 5, 4, 6, 1, 3]

before =      [2, 5, 4, 6, 1, 3]
after =       [2, 4, 5, 6, 1, 3]

before =      [2, 4, 5, 6, 1, 3]
after =       [2, 4, 5, 1, 6, 3]

before =      [2, 4, 5, 1, 6, 3]
after =       [2, 4, 1, 5, 6, 3]

before =      [2, 4, 1, 5, 6, 3]
after =       [2, 1, 4, 5, 6, 3]

before =      [2, 1, 4, 5, 6, 3]
after =       [1, 2, 4, 5, 6, 3]

before =      [1, 2, 4, 5, 6, 3]
after =       [1, 2, 4, 5, 3, 6]

before =      [1, 2, 4, 5, 3, 6]
after =       [1, 2, 4, 3, 5, 6]

before =      [1, 2, 4, 3, 5, 6]
after =       [1, 2, 3, 4, 5, 6]

[1, 2, 3, 4, 5, 6]

排序过程:

image


Gist中还有另外一种实现: arr-sort.py

C语言-位运算符

位运算符

摘自: 摘自: http://www.runoob.com/cprogramming/c-operators.html

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:

A = 0011 1100

B = 0000 1101


A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

下表显示了 C 语言支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:

运算符 描述 实例
& 按位与操作,按二进制位进行"与"运算。运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; (A & B) 将得到 12,即为 0000 1100
| 按位或运算符,按二进制位进行"或"运算。运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1; (A | B) 将得到 61,即为 0011 1101
^ 异或运算符,按二进制位进行"异或"运算。运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0; (A ^ B) 将得到 49,即为 0011 0001
~ 取反运算符,按二进制位进行"取反"运算。运算规则:~1=0; ~0=1; (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<< 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000
>> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111

参考:
按位与

按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位都为1时,结果位才为1。参与运算的两个数均以补码出现。

按位或

按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。当参与运算的是负数时,参与两个数均以补码出现。

取反

取反,是Java使用补码来表示二进制数,在补码表示中,最高位为符号位,正数的符号位为0,负数为1。

异或

如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0

左移运算符

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

右移运算符

将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位或者一律补0,或者补符号位,这由不同的机器而定。

使用淘宝镜像安装puppeteer

  1. 在用户目录下新建文件.npmrc
  2. 粘贴下面的配置
registry=https://registry.npm.taobao.org
chromedriver_cdnurl=http://npm.taobao.org/mirrors/chromedriver
phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs
electron_mirror=https://npm.taobao.org/mirrors/electron/
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
puppeteer_download_host=https://cdn.npm.taobao.org/dist
  1. 执行npm install puppeteer --verbose

Linux命令在线查询手册

LinuxCool

真正好用的Linux命令在线查询手册

  • 根据命令快速搜索
  • 提供命令语法格式, 常用参数, 参考实例

截图:

  • 命令搜索
    image

  • 命令详解

image

端午节随拍

0606 - 八达岭长城

话说长城离住的地方真的挺远的, 🚇 15 -> 🚇 13 -> 🚆 S2, 路上花了大概2.5个小时.
游览路线: 上南城 -> 下南城 -> 上北城 -> 下北城
一天下来, 走了27000多步, 好多蚂蚁森林能量...

微信图片_20190608234406
微信图片_201906082343131
微信图片_201906082343132
微信图片_201906082343133
微信图片_201906082343136
微信图片_201906082343138
微信图片_201906082343139
微信图片_201906082344064
微信图片_201906082344065
微信图片_201906082344067
微信图片_201906082344068
微信图片_2019060823440610
微信图片_2019060823440611
微信图片_2019060823440612
微信图片_2019060823440613
微信图片_2019060823440615
微信图片_2019060823440616
微信图片_2019060823440617

0607 - 北京随拍

微信图片_20190608235109
微信图片_201906082351092
微信图片_201906082351093
微信图片_201906082351461

微信图片_201906082351465
微信图片_201906082351466
微信图片_201906082351467
微信图片_201906082351468

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.