Flyway简介
平时我们写代码一般使用Git等工具来进行版本管理,而Flyway可以理解为是用来进行数据库的版本管理的,它的功能是比较强大的,可以帮忙我们自动执行SQL,确保各个环境(开发、测试等)数据表的同步等,详细内容可以参考文档,这里简单介绍一下常用的使用方法 基本maven使用 引入依赖 12345<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>7.0.0</version></dependency> 创建SQL脚本并执行 在src/resources下创建 db/migration目录,在其中创建对应的SQL文件,其中又分为不同的文件类型,基于约定由于配置的原则,通过文件命名方式进行区分 版本迁移以V开头,只会执行一次;回退迁移以U开头,一般不使用;可重复执行迁移以R开头,每次修改后都会重新执行 版本迁移类型 在db/migration目...
Guava EventBus
在我们日常开发中经常有这种类型的场景: 新建用户后,需要进行一些操作,如发送优惠券等(和创建用户本身无关的操作) 数据变更时,对应的展示表格等信息需要进行对应的更新 即当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 观察者模式(发布-订阅)就是这种情况下的一种解决方案,使用这种方式可以让解耦发布者和订阅者,互相不需要知道对方,之前一篇文档中简单介绍过Spring中的事件使用,这次介绍一种非Spring环境下Guava提供的EventBus的使用 使用 下面简单介绍一下EventBus的使用,使用起来其实是比较简单的,代码如下 创建事件类 1234// 一个简单的普通类public class UserCreateEvent { // 定义需要的属性} 定义监听者 12345678910111213141516171819// 定义一个发送短信通知的服务public class SendSmsService { // 使用 @Subscribe 标识此方法用来处理事件消息 @Subscribe // 方法...
记一次调用HTTPS接口证书问题排查
问题 发现系统调用HTTPS接口时出现异常,异常信息如下 123javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:unable to find valid certification path to requested target 排查 怀疑1: 接口提供方的证书过期了?(其实仔细看日志的话就可以排除这个可能) 操作: 通过本地浏览器打开对应url,浏览器显示正常的安全信息,证书也未过期,oracle的证书样例如下(例子中的根证书颁发机构为 DigiCert Global Root CA ),这时可以排除证书问题 **怀疑2: ** 接口换了证书,服务器没有对应的根证书? 操作: 通过浏览器访问,查询到接口提供方对应的根证书颁发机构为:DST Root CA X3 上网查询到 获取服务器(lin...
Spring事务基本原理
本文主要对基于XML和基于注解配置声明式事务的执行过程进行介绍,因为Spring的事务是基于AOP的,所以最好了解一些AOP相关的基础内容,下面我们就开始进入正文 配置使用 我们使用一个功能,首先就是需要配置,这里我们写一个基于Mybatis的配置,dataSource相关的配置都忽略,直接看事务相关的配置 123456<!-- 声明使用的事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="dataSource" /></bean><!-- 启用注解式声明事务 --><tx:annotation-driven transaction-manager="transactionManager" /> 这样配置后,在...
从源码看ThreadLocal
对于多线程并发对数据的修改的情况,其实除了使用锁或者CAS机制之外,有的情况我们完全可以为每一个线程分配单独的数据,这个数量只能在对应的线程下才能访问到,这样就能避免资源的争抢 或者对于单次请求全局的一些信息,比如当前请求对应的用户信息,可以不通过参数的方式依次传递,而是在全局的一个地方维护,比如当请求进来时,就将当前用户的信息存储进去,但是因为我们的服务是多线程的,同时可能有很多的请求,所以需要用户信息有线程隔离的能力,不能访问到或覆盖了别的线程的用户信息 JDK提供的对应功能的类就是ThreadLocal 使用 先来看下最简单的例子 12345678910111213141516171819202122private static ThreadLocal<String> nameThreadLocal = new ThreadLocal<>();private static ExecutorService executorService = Executors.newSingleThreadExecutor();public static void ...
Redis RDB与AOF
Redis的存储是基于内存的,这就有意味着,如果服务重启那么所有的数据都会丢失,这是我们不能接受的,为此,Redis提供了 RDB 与 AOF 两种持久化机制 简介 RDB: 对于RDB,我们可以把它理解一个定时的快照,就是每隔一段时间(或其他策略),它会创建一个当时所有数据的一个快照,默认存储到的文件为 dump.rdb AOF: 因为RDB创建的是所有数据的快照,这点就决定了它不可能进行高频率的执行,但是如果不经常性的执行,那么当出现如服务器宕机等情况时,会丢失从上次快照到当前的所有操作数据。为了解决这个问题,AOF应运而生,它会在每次执行操作的时候,将这个操作命令进行持久化存储,默认存储到的文件为 appendonly.aof,这样恢复的时候,可以将 aof文件中的所有命令重新执行一遍,即可恢复数据 配置及使用 RDB和AOF的配置都在redis的配置文件redis.conf中进行配置,我们看下主要的配置 RDB的主要配置如下 1234567rdbcompression yes # 是否使用 LZF算法 压缩字符串dbfilename dump.rdb # 持久...
Netty服务端使用及简介
最近因为工作原因,学习了一下Netty,这里写个笔记记录一下 Netty是什么呢?它是一款异步的事件驱动的网络应用程序框架,使用它可以快速的开发出可维护的高性能的面向协议的服务器和客户端—《Netty实战》 这是有两个关键词是异步和事件驱动,先来简单介绍一下 异步是指什么呢?就是发送消息和接收消息是异步的,如调用发送方法后,进行的异步发送,你不知道到底发送出去了没有,如果想要知道结果怎么办呢?这时候可以设置回调函数,发送结果会通过回调函数传回来,当然,其实也可以阻塞同步等待结果,不过那可能就会影响其他数据的处理了 事件驱动呢,我理解就是接收数据等的时候,如在数据可以到达可读取的时候,IO线程会通知调用我们相应的方法进行数据处理流程 好了,下面我们看一段来自Netty官网的服务端代码 12345678910111213141516171819202122232425262728293031323334353637public class DiscardServer { private int port; public DiscardServer(int po...
C语言实现的封装,继承,多态
提到面向对象编程,我们想到的就是封装、继承、多态,但是其实这几个特性并不是只有面向对象语言才能实现,面向过程的C语言也是可以支持实现这三个特性的,下面我们来具体看下 封装 1234// point.hstruct Point;struct Point* makePoint(double x, double y);double distance(struct Point *p1, struct Point *p2); 123456789101112131415161718192021// point.c#include "point.h"#include <stdlib.h>#include <math.h>struct Point { double x, y;};struct Point* makePoint(double x, double y) { struct Point* p = malloc(sizeof (struct Point)); p->x = x; p->y = y;...
Tomcat NioEndpoint浅析
NioEndpoint 是 Tomcat 中负责使用 NIO 方式进行网络通信功能的模块,它负责监听处理请求连接,并将解析出的字节流传递给 Processor 进行后续的处理 下面梳理一下主要的处理流程,如下图 创建Acceptor(默认1个),并启动在对应端口进行监听 创建Poller(多核下默认为2个)并启动,每个 Poller 在创建时会开启一个 Selector Acceptor 监听到连接后,将其转发注册到随机的一个 Poller 中 Poller 在获取到连接后,将其包装为 PollerEvent,并添加到其 events 列表中 Poller 在执行时,会循环获取 events,执行其 run方法 PollerEvent 执行时,会将其中的 SocketChannel 注册到selector中,监听对应事件 当有事件触发时,Poller 会将对应的连接转发给 Endpoint Endpoint 会创建对应的 SocketProcessor, 并将其提交到线程池中执行 SocketProcessor 会获取 Endpoint 中的 hanler进行处理 简化一...
Tomcat整体结构概览
这里主要介绍一下 Tomcat 的整体设计结构 整体结构 Tomcat 的整体结构如下 主要分为两大部分,连接器和容器 连接器 ProtocolHandler EndPoint EndPoint 负责进行 TCP 监听连接,解析之后将消息转发给Processor Processor Processor 进行应用层对应的解析,如HTTP1.1协议,为请求和响应生成对应的Tomcat 的 Request 和 Response 对象 Adapter Adapter 主要负责将 Tomcat 的 Request 和 Response对象转换为 Servlet 的 ServletRequest 和 ServletResponse 对象 容器 容器中也是分层的,从 Engine -> Host -> Context -> Wrapper,消息进行层层对位转发 Server.xml 下面看一个具体 Tomcat 的 serverl.xml配置信息对应一下 12345678910111213141516171819202122232425262728293031323334...
