2017 该有个总结

内心独白

转眼间来到了2018年,这是我参加工作的第四个年头,时光如梭,又来到了新的一年。不知不觉中一年的时间不再那么漫长,一年的时间不再那么难熬,而是转眼间一年就过去了。心中懵然,生活就是如此,把握好每一天,不误好时光。

回忆是人世间最值得品味的,新的一年对过去一个总结,对未来一个期望。

阅读全文

微信开发之初体验

微信号区别

  1. 企业号

    • 微信企业号只有企业通信录成员才能关注
    • 同一个微信企业号可配置多个类似服务号的应用,发送信息条数无限制
    • 旨在通过微信连接企业应用,为企业提供移动端办公入口
  2. 服务号

    • 微信的服务号,顾名思义,是提供服务的,用于向粉丝提供服务的一种公众号, 它比订阅号的功能更全。
    • 服务号也分为两种,认证服务号与未认证服务号,但是认证方式只可以是公司认证,并且也只有公司才能申请
  3. 订阅号

    • 订阅号用于媒体、政府等新闻发布平台,时下非常流行的自媒体概念一般都是使用订阅号
    • 订阅号适合推送消息
  4. 小程序

    • 在没有网络连接的情况下,微信公众号的功能无法使用
    • 小程序本身无需联网的工作,它能够在离线的情况下发挥作用
    • 小程序更像H5的应用,在微信平台体现可扩展的Native应用

微信用户信息区别

  1. openid

    • openid 普通用户的标识,对公众号帐号唯一
    • 一个openid只对应一个公众号
    • 同一个用户关注不同的公众号会有不同的openid
  2. unionid

    • unionid 微信用户统一标识
    • 针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的
    • 对于拥有多个账号的企业来说,unionid可以帮助识别不同公众账号下的用户是否是同一个人
    • 网页应用,二维码等需要记录用户的unionid,因为他们的openid是立即生成的,unionid表示唯一用户

如何获取用户UnionId

  1. 开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(https://open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

  2. 获取公众号openid列表

    1
    2
    3
    http请求方式: GET(请使用https协议)
    https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
  3. 获取公众号openid对应的unionid信息

    1
    2
    3
    接口调用请求说明
    http请求方式: GET https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

注意事项

  1. 批量获取用户openid的列表时,注意accesstoken是否已失效,一次获取的accesstoken的最长有效期是7200s,注意批量获取时,判断accesstoken的失效时间。
  2. 批量获取用户unionid时,一般是脚本多线程跑数据,因为提供的批量一次传入100个openid,所以要注意accesstoken过期时间和接口调用sleep,防止被墙报异常。

Redis Cluster FlushAll失败

问题背景

Flush是一个极少用到的操作,不过既然碰到过诡异的现象,也记录在此。

问题场景是在Reids Cluster中使用主从模式,向主节点发送flush命令,预期主从节点都会清空数据库。但是诡异的现象出现了,我们得到的结果是主从节点发生了切换,并且数据并没有被清空。

问题分析

分析以上case,Redis采用单线程模型,flush操作执行的时候会阻塞所有其它操作,包括集群间心跳包。当Redis中有大量数据的时候,flush操作会消耗较长时间。所以该节点较长时间不能跟集群通信,当达到一定阈值的时候,集群会判定该节点为fail,并且会切换主从状态。

Redis采用异步的方式进行主从同步,flush操作在主节点执行完成之后,才会将命令同步到从节点。此时老的从节点变为了主节点,它不会再接受来自老的主节点的删除数据的操作。

当老的主节点flush完成的时候,它恢复与集群中其它节点的通讯,得知自己被变成了从节点,所又会把数据同步过来。最终造成了主从节点发生了切换,并且数据没有被清空的现象。

解决方案

解决方式:临时调大集群中所有节点的cluster-node-timeout参数

1
2
3
4
5
port 7000 //7000-7005
cluster-enabled yes //开启集群
cluster-config-file nodes.conf //保存节点配置,自动创建,自动更新
cluster-node-timeout 5000 //集群超时时间,节点超过这个时间没反应就断定是宕机
appendonly yes //存储方式,aof,将写操作记录保存到日志中

MyBatis Mapper变量引用方式#{}与${}差别

前言

众所周知,SQL存在注入的风险,所以mybatis 在默认情况下会使用预编译的方式,并会设置PreparedStatement参数,并进行了必要的安全检查和字符的转义。

PreparedStatement预编译

1. Mapper配置,默认是预编译

1
<select id="getList" resultType="Map" >select * from A where age = #{age} ORDER BY #{age}</select>

2. SQL举例

1
select * from A where age = #{age}

3. 解释

参数:age=>5
解析后执行的SQL:select * from A where age = ?
然后在SQL的执行中进行值的替换。

Statement直接拼接

1. Mapper配置 statementType

1
<select id="getList" resultType="Map" statementType="STATEMENT">select * from A where age = ${age} ORDER BY ${age}</select>

2. SQL举例

1
select * from B where age = ${age}

3. 解释

参数:age传入值为:5
解析后执行的SQL:select * from B where age =5

总结

1. ${}方式会引发SQL注入的问题、同时也会影响SQL语句的预编译,所以从安全性和性能的角度出发,能使用#{}的情况下就不要使用${}。

2. 可能需要直接插入一个不做任何修改的字符串到SQL语句中,这时候应该使用${}语法更加灵活方便,但是不能有外部sql的进入,防止sql注入。