博客主页

解决segmentfault等网站的登录复制限制

不知道从什么时候开始segmentfault也启用了需登录才能复制的限制,其实我很反感这种限制。尤其是作为一个技术社区,这样的限制又怎么能真的对技术人员有用?下面开始贴代码解决这烦人的限制。

对于这类禁止复制的,大多都是通过监听dom的copy事件实现的,segmentfault也一样。我们只需要把原本的eventlistener移除即可。

(function() {
  let arr = Array.from(document.querySelectorAll("article.article"));
  if (arr && arr.length <= 0) { return; } 
  let articleContent = arr[0];
  let eventHolder = getEventListeners(articleContent);
  if (!eventHolder || !eventHolder.copy) { return; }
  eventHolder.copy.forEach(e => {
    articleContent.removeEventListener('copy',e.listener)
  })
})();

当然还有个有点搞笑的办法,观察segmentfault的console输出,每次选中有一段log,点进去发现会查找一个SFUserId的dom节点获取用户ID,只需要几行代码就能解决了。

/assets/images/sf/sf_log_pos.png

/assets/images/sf/sf_login_func.png

(function () {
	const span = document.createElement("span");
  span.id = 'SFUserId';
  span.innerText = '123321'
  document.body.appendChild(span);
})();

希望决策者不要把程序员当傻子,稍微有点经验的程序员解决这种问题易如反掌,再不济在浏览器把你js禁用了你也无可奈何。还是把心思放在产品上吧,别想这种歪点子。

Read more

深入理解Spring事务: 物理事务和逻辑事务

Spring事务模块的文档中有描述了两个专业术语,分别是物理事务(physical transaciton)逻辑事务(logic transaction)。读者可能会一头雾水,因为Spring文档中并没有对这两个术语进行过多的介绍。

In Spring-managed transactions, be aware of the difference between physical and logical transactions, and how the propagation setting applies to this difference.

Ref: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/data-access.html#tx-propagation

Read more

深入理解Spring事务: Spring如何实现挂起事务

我们在看Spring的事务传播行为(Propagation)时会发现在某些条件下,线程会被挂起(suspend),接着去执行其他事务。比如Propagation.REQUIRES_NEW有一段这样的描述:

Create a new transaction, and suspend the current transaction if one exists.

这个挂起要怎么去理解呢?

事务和线程的关系

要理解事务挂起必须先了解事务和线程的关系。Oracle的文档中有个描述。

When a transaction is created, it is associated with the thread that created it. As long as the transaction is associated with the thread, no other transaction can be created for that thread.

Ref: https://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s1204transactionsuspension01.html

spring-tx的Propagation其实就是参考了EJB的Transaction设计。作为参考者,这方面和Oracle的设计是一致的。

当事务创建时,就会被绑定到一个线程上。该线程会伴随着事务整个生命周期,直到事务提交、回滚或挂起(临时解绑)。线程和事务的关系是1:1,当线程绑定了一个事务后,其他事务不可以再绑定该线程,反之亦然。

Read more

给gitalk添加匿名评论功能

gitalk是一个基于github issue的评论系统,这个想法是非常具有创意的。不过一直以来这个项目都存在一些问题。

  1. 整个OAuth流程放在前端,暴露了client_id和client_secret
  2. github权限粒度较高,用户授权时会把仓库所有的权限授权出去,容易被人恶意利用
  3. 获取access_token是通过第三方api代理获取,有被恶意利用的可能

这几个重要缺陷一直是我的心头刺,因此我Fork了一份代码自己把这两个问题fix了。首先我把授权流程放到了server端,解决第一个和第三个问题。然后我新增了一个匿名评论功能,来打消访客的安全疑虑,同时匿名评论也能增加游客评论欲望。本文着重讲一下怎样实现匿名评论的功能。

Read more

用JS解决Github Pages图片加载慢的问题

GitHub Pages的服务器不在国内,也没有CDN,因此在国内的访问速度本身就不快,如果文章还包含了自己上传到github pages的图片,那加载速度会更惨不忍睹。

对于图片加载慢的问题,唯一的解决办法就是不要把图片上传到github pages,另外寻找图床把图片地址引用到文章中。不过图床有个很大的问题就是稳定性,一旦第三方服务取消支持外链(比如微博2019年启用防盗链,大量图片无法显示),文章将会出现一大堆无法显示的图。

因此最好的办法还是有双管齐下,一份放在图床,另外一份上传到自己的gihub pages 仓库,当图床不可用时,自动替换为我们备份的地址(慢一点总比显示不了强)。

要实现这功能其实并不难,我们都是知道dom的img标签有个onerror事件,当图片加载出错,就会回调这个function。基于这一点,只需要给我们文章的图片都加上onerror事件即可。思路如下:

Read more

谈谈Spring中的InstantiationAwareBeanPostProcessor

熟悉Spring的朋友应该都知道InstantiationAwareBeanPostProcessor这个接口。从它的继承结构可以看出它是一个BeanPostProcessor,不过它是一个非常特殊的BeanPostProcessor,因为它的贯穿了bean创建的每一个周期。

Bean创建流程

/assets/images/bean/spring-iiap-class.png

上面展示了InstantiationAwareBeanPostProcessor3个主要的方法,它们都会在Bean的创建周期中被回调,用以实现拦截或其他的自定义处理。前三个方法分别是实例化之前阶段、实例化后阶段、赋值阶段。因为第四个已经被废弃,这里也不在赘述。

上面提到的三个方法,其实正好是对应了Spring Bean创建周期,对于一个普通的Spring Bean,当它被请求创建时,会经历下面的流程

/assets/images/bean/bean-creation.jpg

Read more

Spring和SpringBoot自动装配原理

“自动装配”这个概念Spring官方提到的不多,仅在SpringBoot中有大概的介绍。根据功能对他总结,可以把自动装配理解为: 通过注解或者特定的配置,能实现自动加载一整个模块的功能,不需要开发者做太多的配置。

在Spring Boot的时代,这功能非常常见,我们所使用的所有Spring Boot Starter都实现了自动装配。不过这个功能并不是Spring Boot的专利,实际上Spring Framework早就实现了这个功能。

要解释Spring的自动装配,先要了解一下Spring配置的历史。

Read more