Thrift(二)-处理流程分析
之前介绍过thrift使用, 但是只知道使用总是不够满足,这次我们接着之前的代码,来看下这个具体的实现和处理流程,在介绍之前先看下几个重要的接口 传输层 TTransport : 负责数据传输(大部分场景为负责网络传输) 协议层 TProtocol: 负责进行数据结构的序列化与反序列化(依赖TTransport 进行数据传输及读取) 处理层 TProcessor : 使用协议和传输接口进行具体处理处理 server初始化 再次看下Server的初始化启动代码 123456789101112// 创建传输层ServerTransportTServerTransport serverTransport = new TServerSocket(12345);// 实例化接口实现类// 构造Server参数(TProcessor, TTransport, TProtocol-默认TBinaryProtocol)UserService.Processor<UserServiceImpl> processor = new UserService.Processor<&g...
Thrift(一)-快速入门
Thrift是facebook开发的一款轻量级的跨语言的RPC实现,它为数据传输、数据序列化和应用层的处理提供了清晰的抽象和实现。它的代码生成器使用简单的定义语言来生成跨语言的代码,来构建可互操作的RPC客户端和服务端。这篇文章主要简单介绍一下thrift的使用 使用 thrift的使用可以分为如下几个步骤 使用thrift的接口描述语言(IDL)定义好数据类型和服务接口 安装thrift代码生成工具,来生成对应语言的客户端和服务端代码 服务端需要对具体的服务接口实现逻辑进行编码实现 编写初始化代码进行服务端/客户端的启动或调用 下面我们来分别具体看一下 使用IDL定义数据类型和服务接口 因为要实现跨语言的通信,那么就不能使用任何一种语言来定义数据类型和接口,所以thrift提供了IDL来定义相关的信息,其中支持的信息包括 基本类型、结构体、容器、异常、服务接口 等 基本类型 bool byte i16 (有符号的16位整型) i32 (有符号的32位整型) i64 (有符号的64位整型) double (64位浮点数) string (字符串) 因为有的语言没有无符号...
Maven生命周期与插件笔记
工作中大部分Java项目都是基于maven来进行项目的构建等工作,但是对于maven这个高频用到的工具其实了解程度还不够,下面主要是学习《Maven实战》中记录的关于生命周期与插件相关的笔记 maven生命周期与插件 maven的生命周期是从大量项目和构建工作中总结抽象出来的对所有构建过程进行的抽象和统一,这个生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有构建步骤 虽然maven抽象出了生命周期的概念,但是它并没有对相关的功能进行实现,就像它是负责定义了接口,但是具体实现是由插件来完成,这样可以很好的保证自身的轻量和扩展性 而对于maven插件,还有个插件目标的概念,就是可以认为一个插件本身是可以提供很多种功能的,一种功能就是一个插件目标,比如对于 maven-dependency-plugin 这个插件,我们通过执行mvn dependency:help可以看到它有21个插件目标,截取部分内容如下,其中就包含我们平时分析依赖使用的mvn dependency:tree(其中冒号前面是插件前缀,冒号后面是该插件的目标) 123456...
定时任务实现原理浅析
如果我们有想固定间隔时间执行的任务等,自己实现的一种方式是可以新启动一个线程,在其中sleep固定的时间后执行,但是这种方式在任务多的时候肯定是不行的。现在已经有很多现成的工具我们可以直接使用,这里主要介绍一下JDK的ScheduledThreadPoolExecutor与Netty的HashedWheelTimer,看一下它们的实现原理 ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor是JDK自带的一个用于执行周期任务的线程池,用法大致如下 123456// 创建任务线程池ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);// 提交任务executor.schedule(() -> System.out.println("111"), 1, TimeUnit.SECONDS);executor.scheduleAtFixedRate(() -> System.out.println(&q...
transmittable-thread-local实现原理
之前简单介绍过 ThreadLocal,但是其中有个问题就是当一个请求中使用到线程池时,无法将主线程中ThreadLocal中的值传递进去,这次我们就看下怎么解决这个问题 比较直接的的方法就是包装一下Runnable或Callable,在创建的时候将主线程中ThreadLocal对应内容传递保存进去,之后执行的时候再取出来重新赋值到对应ThreadLocal中,使用之后再清理掉即可,大致样子如下 1234567891011121314151617181920212223242526272829303132public class SimpleThreadLocalTest { // 创建一个线程池及姓名的ThreadLocal private Executor executor = Executors.newSingleThreadExecutor(); public static ThreadLocal<String> USER_NAME_THREAD_LOCAL = new ThreadLocal<>(); @Test...
Java编译时注解处理器
Java注解大家都了解,平时我们使用最多的就是在运行时也有效的注解:@Retention(RetentionPolicy.RUNTIME),可以根据这类注解在运行时进行一些特殊的逻辑处理,如Spring中的AOP使用。但是除了这类在运行时存在的注解,还有两种会保留到源码@Retention(RetentionPolicy.SOURCE)和字节码@Retention(RetentionPolicy.CLASS)中的注解,这种注解有什么作用呢? 这里介绍一种比较常见的用法-Java注解处理器(Java Annotation Process),它可以在运行时获取注解信息,生成一些额外的文件信息,如我们常用的lombok或mapstruct都是使用这种技术 下面我们通过一个非常简单的例子来介绍一个它的用法:给前端提供接口时,后端在编写接口文档时,经常会需要将一个类的结构转成json结构并添加注解后提供给前端,这里我们通过注解,在编译时生成类的结构信息 定义注解 首先创建一个定义注解的模板,我们定义如下两个注解 123456// 用于类上面的描述使用@Target(ElementType...
一种动态添加外部Jar包中SpringBean的方式
我们在日常写代码的过程中,经常会有一个扩展点接口,同时会有多种实现,类似策略模式,在运行时动态获取具体的实现。 如果想在不需要重新部署项目的情况下,新增一种扩展点的实现并且能够生效使用,有什么方式呢? 先想个简单的例子来说明一下上面说的场景,比如价格计算。定义一个扩展点接口: 123public interface PriceCalculator { BigDecimal calc(GoodsDetail detail);} 这是应用内置的一种策略: 12345678910111213141516@Servicepublic class DirectReducePriceCalculator implements PriceCalculator { @Resource private ActivityService activityService; @Override public BigDecimal calc(GoodsDetail detail) { // 随便写的,只是为了稍微贴近一点实际...
SpringMVC自定义参数解析
我们日常开发过程中,入参出参基本都是与后端对应的类结构完全一致,SpringMVC自动帮我们处理了参数转换的过程,GET 和 POST 的几种常见传参方式如下 123456789101112131415161718192021222324// HTTP请求参数名需要与属性名userName相同@GetMapping("/listUser")public List<User> listUser(String userName) { return new ArrayList<>();}@GetMapping("/listUser")// HTTP请求参数名需要与注解中的名称username相同相同public List<User> listUser1(@RequestParam("username") String userName) { return new ArrayList<>();}@GetMapping("...
状态机简介
之前通过《状态模式》介绍了一下状态模式的使用,这次我们来介绍一下有限状态机 维基百科中是这样定义的:有限状态机(FSM)又称有限状态自动机(FSA),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型,在任何给定时间都可以恰好处于有限数量的状态之一 其实状态模式也可以算是状态机的一种实现,除了状态模式,还有一种实现方式就是创建一个描绘迁移的数据表,该表被一个处理事件的处理引擎解释。引擎查找与事件匹配的迁移,调用响应的动作并更改状态,这样状态机的逻辑全部集中在了一个地方 所以表驱动的状态机和状态模式的主要区别就是:状态模式对于状态相关的行为进行建模,而表驱动的方法着重于定义状态转换 这里我们介绍一下表驱动的状态机实现,虽然这方式叫基于表驱动的状态机,但是这个表不是说特指我们平时用的数据库的表,而是一种关系的记录 现在已经有了很多成熟开源的状态机可以使用,如 Spring Statemachine、Squirrel Statemachine和stateless4j,平时工作如果需要,直接使用就好而不需要自己再开发,这次就以最轻量级的 stateless4...
单元测试之Mock
单元测试是对我们写的代码的最小单元进行测试,一般来说就是对函数(方法)进行测试,大家都知道写单元测试的好处,但是具体要怎么写呢?被测试的类可能依赖外部的类或服务,这个依赖的外部接口如何Mock,依赖注入的类如何替换成自己Mock的类等等,下面就介绍一种常用的Mock方式 首先,既然是单元测试,那么要做的第一件事就是屏蔽掉对外部的依赖,不让它们对我们要测试的方法产生影响。屏蔽的方式一般就是通过Mock,将调用的真实方法替换为我们设置好的mock类,这里简单介绍一种Mock框架 Mockito 首先需要引入对应的依赖,如果使用Maven则需要在pom.xml中添加如下内容 123456<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.10.19</version> <!-- 可以替换最新的版本号 --> <scope>t...
