算法:递归
算法:递归递归算法主要寻找: 终止条件:递归的尽头 单级递归的行为:在一次递归里要做的事情 返回值:每次迭代要return的东西 例如 首先,假定方法是已经实现的 终止条件为:当当前节点(传了空节点)或下一节点(传了单节点)为空,则无需反转返回当前节点 递归行为:假定之后的节点均已实现反转,则需要将已经反转的尾部的next变为当前节点,而当前节点由于是第一个节点,其next为null 此处注意在反转前需要先留存反转后的尾部; 返回值:返回反转后的头结点
![算法:递归]()
2020-06-24鱼鱼
[Quick Start]使用RedisTemplate操作Redis
[Quick Start]使用RedisTemplate操作RedisRedisTemplate现在作为使用率最高的redis三方类库,隶属Spring技术栈,此篇文章意在指引RedisTemplate的快速上手 在实践前,请确保已经有一个可连接的Redis服务 Redis有五大基本数据类型:string、hash、list、set和zset string即是最单纯的k-v存储方式,使用set、get等指令 hash是哈希表的存储方式,比较适合用来存储对象,每一条value相当于Java的一个Map,使用hmset、hget等指令 list是简单的有序列表,每一条value相当于Java的一个List,使用lpush、lpop、rpush、rpop等指令
![[Quick Start]使用RedisTemplate操作Redis](/blog_cover/20200220/cdd943f261664778a1c746b93930db3a.png)
2020-02-23鱼鱼
ES快速入门(2)——Tokenizer、Reindex
ES快速入门(2)——Tokenizer、Reindex本篇介绍es提供的几种分词分析器和常用的开源分词分析器 es默认的分词器,中规中矩的按照 Unicode Standard Annex #29分词,一般的小写符号会忽略,对于中文等字符会逐字分割,参数max_token_length表示最大的字符长度,再切分后会继续按此切分 譬如: 会分词为: 一个无视语义,按照字符尽量收集全索引的分词方式,会前后叠加的按符号位分词,参数: 会分词为: nGram的分词很全面,但如此夸张的方式用不好会导致索引doc过大,同时使查询效率偏低 分词规则很简单,无其余规则的按空格分词: 会分词为: 在standard的基础上能够有效拆分出邮箱和url地址的格式,同样有max_token_length这一参数:
![ES快速入门(2)——Tokenizer、Reindex]()
2020-09-05鱼鱼
Springboot源码原理:从启动方法看配置加载
Springboot源码原理:从启动方法看配置加载首先看一个springboot项目的配置,我们可以定义一个application.yml,对于不同的环境有时也通过profile配置项指定不同的配置文件(譬如application-dev.yml),也可以通过命令行覆写具体的VM options配置项(举个栗子,启动时执行 java -jar xxx.jar --server.port=8080),此文讲解这些配制的读取原理 整体配置项的优先级从高到低为: 命令行配置; 系统属性(System.getProperties()) 系统环境变量 jar包外的主配置文件(带有) jar包内的主配置文件 jar包外的次要配置文件(由spring.profile指定的)

2021-03-09鱼鱼
网络协议面面观:TCP/IP协议组,TCP与UDP
网络协议面面观:TCP/IP协议组,TCP与UDP日常中的网站应用交互绝大部分都是基于TCP/IP协议栈构建的,而TCP/IP就是通信常见的protocol(协议)组,是一类协议的简称,利用这篇文章总结一些常见的TCP/IP网络协议簇以及着重一下两个常见的传输层协议TCP和UDP,扫一下盲 OSI参考模型是ISO(国际标准化组织)指定的网络互联七层模型,与此对比的还有互联网界针对TCP/IP协议簇提出的四层模型 相比之下,OSI七层模型的应用面很窄,且是一种理论模型,TCP/IP则是一种实施标准 一般使用四层模型来表达协议归属,所以此处不详细介绍七层模型的内容,只是简单的与四层协议做对比,两者对比: 应用层 通过这个TCP/IP模型,整体的数据流向是发送方自顶向下然后在接收方自底向上的,即:

2020-03-03鱼鱼
扫盲——加密那些事
扫盲——加密那些事扫盲加密解密算法 日常开发中我们经常接触MD5算法,以此进行简单的文件完整性校验或者是后台密码验证,MD5是最常见也是最简单快捷的散列算法,常用于参数或文件完整性校验,譬如网络请求发起方与接收方分别对参数做MD5编码,一旦不一致便判断请求被篡改从而拒绝该请求,从而保证信息安全,编码后的字符串是编码前文本的一个简要梗概,因此它也被称作是信息摘要算法 这个算法的特点就是不可逆,只用于信息准确性和防篡改的校验,当然,MD5作为老牌的散列算法,很多经典的编码已经可以被反向解码出来(依靠正向的暴力穷举)以及被碰撞模仿(王小云院士团队的"破解"能够根据MD5编码后串码模拟原始消息,即使它可能与原信息不同),类似的还有SHA1,因此衍生了SHA224、SHA256、SHA512等更多安全的散列算法

2021-05-14鱼鱼
项目异常问题解决
项目异常问题解决这天 程序抛出了一个WARN日志: createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [43,844] milliseconds. 这意味着SHA1PRNG算法导致项目启动多花费了43秒,这是基于SHA-1算法实现且保密性较强的伪随机数生成器 1.从tomcat层面上解决: 在catalina.sh中加入这么一行:-Djava.security.egd=file:/dev/./urandom 2.从java层面解决 打开$JAVA_PATH/jre/lib/security/java.security这个文件,将下面的内容:

2019-02-28鱼鱼
ELK全家桶基本使用(I)文件收集Filebeat
ELK全家桶基本使用(I)文件收集FilebeatFilebeat是Elastic中的轻量文件收集系统,相比于功能更强悍的Logstash,当我们需求很单一,读取文件内容且对文件内容没有过多复杂处理时,最好使用FileBeat取代Logstash,以免造成不必要的内存开销 文档链接 Filebeat负责收集文件并发送给下游服务 核心行为包含输入、处理过滤和输出 当然也有集成好配置的模块,通过模块与Es和Kibana链接可以直接在Kibana上看到组件的可视化 同时不难看出Filebeat其实对数据库的支持不是很健壮 截止7.6版本,开源的Filebeat可支持以下几种消息输入类型: log 用得最多的输入类型; stdin 标准的输入,从process或是piepline读取(可理解为脚本运行通道直接输入),一旦配置了这种input方式,其他 input将不再生效文档地址;

2020-03-16鱼鱼
Spring源码解析(3) IoC容器配置读取和容器refresh
Spring源码解析(3) IoC容器配置读取和容器refresh在文章Spring源码解析(I) 基于SSM看Spring的使用和Spring启动监听中,讲述了web容器启动后会触发的方法实现中生成Context的部分,回顾下核心方法: 我们已经分析到了0.处,他对我们生成的容器做了一个判断,对于web.xml监听初始化的Context,其生成的WebApplicationContext都是ConfigurableWebApplicationContext的子类,所以必然会进入if分支 首先通过loadParentContext先加载了父容器,默认是null 然后调用了configureAndRefreshWebApplicationContext方法进行初始化和配置项的读取

2020-08-09鱼鱼
多线程应用提高(III) 并发编程的艺术
多线程应用提高(III) 并发编程的艺术《并发编程的艺术》p36:JMM不保证64位的long型和double型变量的写操作具有原子性 面试中可能经常会被问到HashMap和HashTable的区别,其中最重要的就是前者并不是线程安全的,但其实在高并发的情形下,后者的效率低的不像话甚至不可用,所以在jdk7之后出现了线程高效且安全的ConcurrentHashMap 当并发严重时,某线程若是调用了同步方法,另外的线程将进入阻塞/轮询状态,既不能put也不能get,但ConcurrentHashMap是不同的,它采用了锁的分段技术,将数据分段存储,不同的数据持有不同的锁,这样可用性会大大高于HashTable,所以在实际开发中我们都用ConcurrentHashMap取代HashTable
![多线程应用提高(III) 并发编程的艺术]()
2019-06-18鱼鱼
Spring MVC源码和设计思想2 HandlerMapping
Spring MVC源码和设计思想2 HandlerMapping系列传送门Spring MVC源码和设计思想1 DispatcherServlet-鱼鱼的博客 此篇篇幅很长,且慢慢道来 在之前一篇中,DispatchServlet的doDispatch()方法中有这么几行: 其中getHandler方法: handlerMappings是一个初始化过的List
,通过它获取HandlerExecutionChain HandlerExecutionChain存储了一个Object(其实就是HandleAdapter)和一个拦截器(HandlerInterceptor)数组,在doDispatch方法中执行了applyPreHandle和applyPostHandle方法,方法就是分别迭代调用了拦截器数组的postHandle和preHandle,同样地,发生异常时的triggerAfterCompletion也映射到了afterCompletion方法
2019-06-12鱼鱼
多线程应用提高(I) 多线程常见问题、常用方法和关键字
多线程应用提高(I) 多线程常见问题、常用方法和关键字我们一般熟识的创建多线程方式即为继承Thread类或是实现Runnable接口,重写run()方法,还有创建线程池实现 手动定义一个线程任务(作为内部类)的方法现在已经不被提倡,所以遇到可能存在并发的复杂任务时,一般采用线程池来实现 一些设计并发常用并且容易被混淆的方法们: static sleep() : Thread类的静态方法,阻塞当前正在线程,不释放锁; wait() : 当前线程暂停,并释放锁且暂时无法重新获得锁,必须绑定当前对象内容锁(如使用Synchronized的同步块),知道其他线程调用notify()/notifyAll()才有机会获得锁继续执行; yield() : 当前线程暂停,此时时间片分配给其他线程,但是不会分配给优先级更低的线程;
2019-12-07鱼鱼