0%

什么是过滤器?

Filter 也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如JSP,Servlet,静态图片文件或静态HTML文件进行拦截,从而实现一些特殊功能。例如实现 URL级别的权限控制 、 过滤敏感词汇 、 压缩响应信息 等一些高级功能。

阅读全文 »

Spring MVC中的拦截器( Interceptor )类似于Servlet中的过滤器( Filter ),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

阅读全文 »

基础知识

一把锁

synchronized

两个并(并发、并行)

并发:

  • 是在同一实体上的多个事件
  • 是在一合处理器上“同时”处理多个任务
  • 同一时刻,其实是只有一个事件在发生

并行:

  • 是在不同实体上的多个事件
  • 是在多台处理器上同时处理多个任务
  • 同一时刻,大家真的都在做事情

三个程(进程、线程、管程)

进程:简单的说,在系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源。

线程:也被称为轻量级进程,在同一个进程内会有1个或多个线程,是大多数操作系统进行时序调度的基本单元。

管程:Monitor(监视器),也就是我们平时所说的锁,Monitor其实是一种同步机制,他的义务是保证(同一时间)只有一个线程可以访问被保护的数据和代码。JVM中同步是基于进入和退出监视器对象(Monitor,管程对象)来实现的,每个对象实例都会有一个Monitor对象。Monitor对象会和Java对象一同创建并销毁。

阅读全文 »

灰度组件功能需求整理

灰度规则的格式和存储方式

我们希望支持不同格式(JSON、YAML、XML 等)、不同存储方式(本地配置文件、Redis、Zookeeper、或者自研配置中心等)的灰度规则配置方式。实际上,这一点跟之前的限流框架中限流规则的格式和存储方式完全一致,代码实现也是相同的

灰度规则的语法格式

我们支持三种灰度规则语法格式:具体值(比如 893)、区间值(比如 1020-1120)、比例值(比如 %30)。除此之外,对于更加复杂的灰度规则,比如只对 30 天内购买过某某商品并且退货次数少于 10 次的用户进行灰度,我们通过编程的方式来实现。

灰度规则的内存组织方式

类似于限流框架中的限流规则,我们需要把灰度规则组织成支持快速查找的数据结构,能够快速判定某个灰度对象(darkTarget,比如用户 ID),是否落在灰度规则设定的范围内。

灰度规则热更新

修改了灰度规则之后,我们希望不重新部署和重启系统,新的灰度规则就能生效,所以,我们需要支持灰度规则热更新。

在 V1 版本中,对于第一点灰度规则的格式和存储方式,我们只支持 YAML 格式本地文件的配置存储方式。对于剩下的三点,我们都要进行实现。考虑到 V1 版本要实现的内容比较多,我们分两步来实现代码,第一步先将大的流程、框架搭建好,第二步再进一步添加、丰富、优化功能。

阅读全文 »

分析

需求场景

我们先来看下幂等框架的需求场景。

为了复用代码,我们把通用的功能设计成了公共服务平台。公司内部的其他金融产品的后台系统,会调用公共服务平台的服务,不需要完全从零开始开发。公共服务平台提供的是 RESTful 接口。为了简化开发,调用方一般使用 Feign 框架(一个 HTTP 框架)来访问公共服务平台的接口。

调用方访问公共服务平台的接口,会有三种可能的结果:成功、失败和超时。前两种结果非常明确,调用方可以自己决定收到结果之后如何处理。结果为“成功”,万事大吉。结果为“失败”,一般情况下,调用方会将失败的结果,反馈给用户(移动端 App),让用户自行决定是否重试。

但是,当接口请求超时时,处理起来就没那么容易了。有可能业务逻辑已经执行成功了,只是公共服务平台返回结果给调用方的时候超时了,但也有可能业务逻辑没有执行成功,比如,因为数据库当时存在集中写入,导致部分数据写入超时。总之,超时对应的执行结果是未决的。那调用方调用接口超时时(基于 Feign 框架开发的话,一般是收到 Timeout 异常),该如何处理呢?

阅读全文 »

分析

项目背景

公司成立初期,团队人少。公司集中精力开发一个金融理财产品(我们把这个项目叫做 X 项目)。整个项目只做了简单的前后端分离,后端的所有代码都在一个 GitHub 仓库中,整个后端作为一个应用来部署,没有划分微服务。

遇到了行业风口,公司发展得不错,公司开始招更多人,开发更多的金融产品,比如专注房贷的理财产品、专注供应链的产品、专注消费贷的借款端产品等等。在产品形态上,每个金融产品都做成了独立的 App。

对于不同的金融产品,尽管移动端长得不一样,但是后端的很多功能、代码都是可以复用的。为了快速上线,针对每个应用,公司都成立一个新的团队,然后拷贝 X 项目的代码,在此基础之上修改、添加新的功能。

这样成立新团队,拷贝老代码,改改就能上线一个新产品的开发模式,在一开始很受欢迎。产品上线快,也给公司赢得了竞争上的优势。但时间一长,这样的开发模式暴露出来的问题就越来越多了。而且随着公司的发展,公司也过了急速扩张期,人招得太多,公司开始考虑研发效率问题了。

因为所有的项目的代码都是从 X 项目拷贝来的,多个团队同时维护相似的代码,显然是重复劳动,协作起来也非常麻烦。任何团队发现代码的 bug,都要同步到其他团队做相同的修改。而且,各个团队对代码独立迭代,改得面目全非,即便要添加一个通用的功能,每个团队也都要基于自己的代码再重复开发。

除此之外,公司成立初期,各个方面条件有限,只能招到开发水平一般的员工,而且追求快速上线,所以,X 项目的代码质量很差,结构混乱、命名不规范、到处是临时解决方案、埋了很多坑,在烂代码之上不停地堆砌烂代码,时间长了,代码的可读性越来越差、维护成本越来越高,甚至高过了重新开发的成本。

阅读全文 »

实际上,Spring 框架中用到的设计模式非常多,不下十几种。我们今天就总结罗列一下它们。

适配器模式在 Spring 中的应用

在 Spring MVC 中,定义一个 Controller 最常用的方式是,通过 @Controller 注解来标记某个类是 Controller 类,通过 @RequesMapping 注解来标记函数对应的 URL。不过,定义一个 Controller 远不止这一种方法。我们还可以通过让类实现 Controller 接口或者 Servlet 接口,来定义一个 Controller。针对这三种定义方式,我写了三段示例代码,如下所示:

阅读全文 »

常用来实现扩展特性的设计模式有:观察者模式、模板模式、职责链模式、策略模式等。今天,我们再剖析 Spring 框架为了支持可扩展特性用的 2 种设计模式:观察者模式和模板模式。

观察者模式在 Spring 中的应用

Java、Google Guava 都提供了观察者模式的实现框架。Java 提供的框架比较简单,只包含 java.util.Observable 和 java.util.Observer 两个类。Google Guava 提供的框架功能比较完善和强大:通过 EventBus 事件总线来实现观察者模式。实际上,Spring 也提供了观察者模式的实现框架。

Spring 中实现的观察者模式包含三部分:Event 事件(相当于消息)、Listener 监听者(相当于观察者)、Publisher 发送者(相当于被观察者)。

阅读全文 »

我们常说的 Spring 框架,是指 Spring Framework 基础框架。Spring Framework 是整个 Spring 生态(也被称作 Spring 全家桶)的基石。除了 Spring Framework,Spring 全家桶中还有更多基于 Spring Framework 开发出来的、整合更多功能的框架,比如 Spring Boot、Spring Cloud。

在 Spring 全家桶中,Spring Framework 是最基础、最底层的一部分。它提供了最基础、最核心的 IOC 和 AOP 功能。当然,它包含的功能还不仅如此,还有其他比如事务管理(Transactions)、MVC 框架(Spring MVC)等很多功能。

阅读全文 »

Google Guava 是 Google 公司内部 Java 开发工具库的开源版本。Google 内部的很多 Java 项目都在使用它。它提供了一些 JDK 没有提供的功能,以及对 JDK 已有功能的增强功能。其中就包括:集合(Collections)、缓存(Caching)、原生类型支持(Primitives Support)、并发库(Concurrency Libraries)、通用注解(Common Annotation)、字符串处理(Strings Processing)、数学计算(Math)、I/O、事件总线(EventBus)等等。

做业务开发也会涉及很多非业务功能的开发。我们要有善于发现、善于抽象的能力,并且具有扎实的设计、开发能力,能够发现这些非业务的、可复用的功能点,并且从业务逻辑中将其解耦抽象出来,设计并开发成独立的功能模块,比如类库、框架、功能组件。

实际上,不管是类库、框架还是功能组件,这些通用功能模块最大的两个特点就是复用和业务无关。如果你开发的这块代码,业务无关并且可能会被复用,那就可以考虑将它独立出来,开发成类库、框架、功能组件等。

阅读全文 »