java知识文章链接

** **
****

开发相关

1.EasyExcel 轻松灵活读取Excel内容:https://segmentfault.com/a/1190000020759658

Spring相关

1.Spring Boot 应用在启动阶段执行代码的几种方式:https://segmentfault.com/a/1190000021437254

2.Spring Aop实现原理https://blog.csdn.net/baomw/article/details/84262006
总结:通过BeanFactoryPostProcessor获取哪些bean拥有切面注解(BeanFactoryPostProcessor可以获取BeanDefination中的元数据),通过BeanPostProcessor(可以获取初始化前的bean对象)生成一个代理对象替换原来的bean对象,放入spring容器中,在生成的代理中会有相关的切面逻辑

3.Spring 是如何解决循环依赖的
https://blog.csdn.net/qq_36381855/article/details/79752689
https://blog.csdn.net/f641385712/article/details/92801300
总结:结合bean的生命周期,bean先通过构造函数实例化对象,然后填充bean里面对应的属性,然后调用相关的aware或者init方法初始化bean里对应的方法。spring容器里使用了三级缓存,一级缓存(完全实例化的bean对象,singletonObjects),二级缓存(提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性)earlySingletonObjects),三级缓存(通过构造函数实例化,singletonFactories),对于构造函数注入的循环依赖spring无法解决。A、B互相依赖,A实例化后会将实例化对象放入三级缓存中,在实例化其属性时发现B未创建,就会去创建B,B在实例化A的时候通过三级缓存找到了A,成功创建了bean,因此A的bean也得以创建

4.Spring 事务
https://www.cnblogs.com/mseddl/p/11577846.html

5.拦截器和过滤器什么区别
https://zhidao.baidu.com/question/583953960492530045.html
总结:
(1)拦截器是基于java的反射机制的,而过滤器是基于函数回调;
(2)拦截器不依赖与servlet容器(Filter为javax.servlet-api中的对象),过滤器(为spring中的对象,以spring为例)依赖与servlet容器;
(3)拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用;
(4)拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问;
(5)在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
拦截器的代码实现(以struts2为例)

6.spring bean生命周期
https://segmentfault.com/a/1190000019807818
在这里插入图片描述

SpringBoot相关

1.springboot统一异常拦截器https://www.cnblogs.com/zhangweizhong/p/12600220.html
总结:使用@ControllerAdvice和@ExceptionHandler注解

2.Spring Cloud 和dubbo比较链接1 链接2
总结:(1)服务调用方式 dubbo是RPC springcloud Rest Api,dubbo和服务接口的耦合度更强一些,rest接口更加灵活(2)注册中心,dubbo 是zookeeper springcloud是eureka,也可以是zookeeper(3)服务网关,dubbo本身没有实现,只能通过其他第三方技术整合,springcloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,springcloud支持断路器,与git完美集成配置文件支持版本控制,事物总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素。

3.SpringBoot自动配置原理
https://blog.csdn.net/u014745069/article/details/83820511
https://www.cnblogs.com/jiadp/p/9276826.html
https://blog.csdn.net/zjcjava/article/details/84028222
总结:@SpringBootApplication----->@EnableAutoConfiguration------>AutoConfigurationImportSelector------->导入META-INF/spring.factories下的所有配置的AutoConfiguration类,这些类中关联了一系列的配置属性(通常以Properties.class结尾),springboot将这些配置信息通过bean的方式加载到容器里供使用。其中上述链接中的自己实现方式实现的就是自定义一个AutoConfiguration类,及属性Properties,然后将其写入到META-INF/spring.factories的EnableAutoConfiguration键中

Redis相关

1.redis缓存雪崩、缓存穿透、缓存击穿解释
https://www.jianshu.com/p/e4afd294b867
https://www.jianshu.com/p/add7ce729662
总结:雪崩:redis挂掉,对数据库造成毁灭行访问,造成数据库崩溃,整个系统崩溃,或者redis大量失效,直接访问数据库; 穿透:redis总是没有存储相关数据,每次都是访问数据库,比如redis中未存储从数据库查出的空数据 ; 击穿:redis失效瞬间,大量请求访问到数据库

2.redis过期键删除策略
https://www.jianshu.com/p/3dc773c3b6e3(链接已被删)
https://www.jianshu.com/p/406edc497d75
总结:定时删除、惰性删除、定期删除;RDB定期删除策略(生成文件时,过期键不写入文件,从文件恢复时,主服务器不加载过期键,从服务器全部加载)、AOF删除策略(已过期的键会在文件中追加del操作,重写文件时,过期的键不会重写到新文件)、主从删除策略(过期键由主服务器控制,从服务器不主动删除过期键,主服务器将删除同步给从服务器)

3.redis的回收策略(淘汰策略)https://juejin.im/post/5dde7d6251882577d569f3cb
问题11(回收策略主要解决的问题是内存不足时如何删除键)

4.redis数据同步机制https://www.jianshu.com/p/41254dc5cb38
总结:
全量复制:从节点启动时向主节点发送全量同步命令,主节点收到命令后将rdb文件全量发送给从服务器,并且在主服务器发送过程中缓存期间的操作命令,从服务器在收到主服务器的rdb文件后,并且写入主服务器的缓存数据完成同步,此后,主服务器没写入一个命令 ,从服务器同步一次操作
增量复制:主从同步后因为网络断开重连后,从服务器向主服务器发送带有服务器编号的offset,主服务器通过编号判断是否是自己的,若是,并且对应的offset值在缓存区中则进行增量复制,否则进行全量复制
大文件复制需要注意配置文件中的复制超时,否则会复制失败
redis使用大小限制和持续性限制防止输出缓存区溢出,满足条件的会断开客户端连接

5.使用redis作异步队列https://juejin.im/post/5dde7d6251882577d569f3cb第39问
使用redis作延迟队列https://blog.csdn.net/mengqingming1/article/details/103196701
通过score参数往zset中添加元素,zset通过score排序,zadd:向zset中添加带评分的元素;zrangeByScore:取出zset中评分范围的数据,可指定offset和取出数量,但是不从zset中删除;zrem:移除zset中的数据

6.redis分布式锁https://www.jianshu.com/p/0e6d6d7b5411
总结:
原理:redis上键值的唯一性,一个客户端在redis上尝试设置键值,若该键值已存在,则表示锁已被其他客户端获得,若不存在则设置键值,获得锁
预防死锁:可设置键值的过期时间,过期时间应依据业务来进行设置,若客户端在获取锁处理共享数据后发生异常,锁到期后,客户端从异常中恢复,这时候如果直接释放锁,可能释放的是其他客户端持有的锁,因此在获取锁后,应当将客户端拥有的惟一值设置到锁的值中,表明谁持有锁,那么对于上面的客户端异常恢复时应该检查下锁中的值是否为该客户端持有。对于非持有锁的客户端可以设置超时或者重试次数获取锁
保证释放锁的原子性:释放锁时需要先获取值,检查是否自己设置的,然后删除键值,这是两个操作过程,为保证操作的原子性,可以使用redis的事务机制进行删除(watch,multi,Transaction,exec,unwatch),或者使用Lua脚本的方式,redis保证执行Lua脚本时不执行其他操作,从而保证原子性
若主从切换过程中锁失去了原子性:使用RedLock(Redis Distributed Lock)

7.怎么防止AOF文件越来越大https://blog.csdn.net/weixin_45154837/article/details/100568263
总结:redis rewrite机制,redis会fock一个进程重新生成aof文件,在重新生成aof文件之前不会删除原有的aof文件,生成成功后会替换aof文件,rewrite策略可以在redis.config中配置

JAVA基础

1、阻塞队列的实现原理https://www.jianshu.com/p/5f7979e8d21d
总结:ArrayBlockingQueue和LinkedBlockingQueue内部在put或者take时,在数据为空或者满时会进行阻塞,其是通过ReentrantLock里的newCondition生成Condition实现的,本质上就是线程的await和notifyAll,源码中对应notFull.await()和notFull.signal()操作。其中对于里面的存放和获取方法绝大多数使用了ReentrantLock保证线程安全的。其中ArrayBlockingQueue使用的是单锁而LinkedBlockingQueue使用的双锁。
问题引申为什么ArrayBlockingQueue不像LinkedBlockingQueue一样使用双锁机制呢?
其中一种解释为:ArrayBlockingQueue内部使用的是数组结构,对于数据的操作都是操作的整个数组对象,而LinkedBlockingQueue内部使用的是链表结构,数据是存储在链表中的节点中的,对于数据的操作操作的是某一个节点,因此使用双锁,分别锁住首尾两个节点有利于性能的提升

2、ReentrantLock原理
https://blog.csdn.net/fuyuwei2015/article/details/83719444
https://tech.souyunku.com/?p=31962

3、java内存https://www.cnblogs.com/czwbig/p/11127124.html

4、ConcurrentHashMap原理解析https://www.cnblogs.com/zerotomax/p/8687425.html
**总结:
(1):ConcurrentHashMap只在首次put的时候初始化数组,并且置SIZECTL为-1,其他线程在发现为-1时,表示有其他线程在初始;
(2)put操作 在这里插入图片描述
(3)多线程帮助扩容
在这里插入图片描述
(4)同步机制
在这里插入图片描述

**

5、垃圾回收
https://baijiahao.baidu.com/s?id=1636852721632353675&wfr=spider&for=pc
新生代:复制算法
老年代:标记整理算法
在这里插入图片描述
垃圾收集器使用

6、Sychronized原理
Synchronized的内部实现原理 https://www.jianshu.com/p/5c4f441bf142
Synchronized之管程 https://www.jianshu.com/p/32e1361817f0
总结:sychronized修饰的方法由ACC_SYNCHRONIZED标记,修饰的代码块由monitorenter和monitorexit修饰,两种都会去竞争monitor,其是一种数据结构,封装了同步操作,每个锁会对应其中的一条Monitor Record,每条monitor record 里包含当前锁归哪个线程所有(owner),owner线程获取锁的次数(count),以及阻塞队列等信息。那么对于每个对象在对象头里面都有个Mark Word字段,里面包含了锁的状态(解释了锁升级),以及指向monitor record的地址,那么多线程在竞争时通过对象头找到monitor record查看自己是否有权利获取资源。
轻量锁是在无竞争状态在使用CAS来代替互斥量,而偏向锁是在无竞争状态在把整个同步都消除掉,连CAS都省了。

7、ThreadLocal原理
https://www.jianshu.com/p/3c5d7f09dfbd
在这里插入图片描述

总结:
(1)数据是放在ThreadLocalMap结构中的,每个线程都会有ThreadLocalMap对象,ThreadLocal的set过程是将数据放到对应的Thread的ThreadLocalMap中,参看上面截图,其中key为ThreadLocal对象;
(2)对于某一ThreadLocal来讲,他的索引值i是确定的,在不同线程之间访问时访问的是不同的table数组的同一位置即都为table[i],只不过这个不同线程之间的table是独立的。
(3)对于同一线程的不同ThreadLocal来讲,这些ThreadLocal实例共享一个table数组,然后每个ThreadLocal实例在table中的索引i是不同的

应用举例:公司平台的操作日志,通过拦截器获取每次请求,将日志对象在拦截器前置方法中创建,在各自的业务中实现具体的日志内容,在请求结束后在拦截器完成方法中将日志写入到远程接口,问,那直接在具体的业务逻辑中实现日志写入不是更简单?可以在完成方法中使用线程方式写入数据,避免影响数据返回效率
问题引申:ThreadLocalMap会引起内存泄漏吗?为什么ThreadLocalMap的key使用弱引用?java是怎么解决内存泄漏问题的?弱引用会引起前面存入的数据,后面无法获取吗?
https://blog.csdn.net/thewindkee/article/details/89390145
ThreadLocalMap会引起内存泄漏,其key值为ThreadLocal对象,若其key值被垃圾回收了,那么key将会被置为null,而value值仍然存在,ThreadLocal在每次set或者get时会去检查是否有这些内存泄漏的值,进行清空,若不去调用这些方法,仍然会有内存泄漏问题,内存泄漏的前提是ThreadLocal对象被释放,那么只要正确操作ThreadLocal对象,ThreadLocal为强引用,其不会无缘无故置key为空。若key值采用强引用,那么当ThreadLocal不再需要后,比如是在其他方法中创建的,本质上应该回收ThreadLocal对象,但是由于线程Thread未结束,仍然会持有ThreadLocal引用,同样造成内存泄漏

8、==和equals区别
https://juejin.im/post/6844903954145345544#heading-0
==比较的是内存地址,equals在object中定义为也是比较内存地址,和等于等效,在基本数据类型中重写了equals,比较的是地址指向的值

		Map<String,String> map1=new HashMap<String,String>();		
		Map<String,String> map2=new HashMap<String,String>();		
		System.out.println(map1==map2);				//false
		System.out.println(map1.equals(map2));		//true
		map1.put("1", "2");
		map2.put("1", "3");
		System.out.println(map1.equals(map2));		//false

上面的代码比较了hashMap的equals方法,其继承自AbstractMap的equals,比较map中的所有元素是否一致

9、hashmap为什么每次扩容取2的n次方
https://blog.csdn.net/apeopl/article/details/88935422
总结:hashmap重新计算hash值时会与(n - 1) & hash相关,这里的n为新map容量,其中当容量取2的n次方时,能够使新生成的hash值尽量分散,避免hash冲突

10、子类继承父类
若父类只有有参构造函数,则子类在创建构造函数时,构造函数第一行必须调用父类的有参构造函数,否则报错,通常绝大多数父类有无参构造函数,编译器在子类中默认会调用父类的无参构造函数,因此很多场景未管父类的构造函数,本质上每个子类的构造函数第一行都要调用父类的构造函数
11、java栈和堆的区别https://blog.csdn.net/jianghao233/article/details/82777789
1.栈内存存储的是局部变量而堆内存存储的是实体
2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短
3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

12、List/Map快失败
https://blog.csdn.net/chewbee/article/details/78314661
https://www.cnblogs.com/czd-xi/p/10046585.html
1.使用迭代器进行变量移除不会发生ConcurrentModificationException异常
2、使用迭代器遍历中若直接对list或者map进行修改会发生ConcurrentModificationException异常

Mybatis

2、ReentrantLock原理https://tech.souyunku.com/?p=31962

Tomcat

1、tomcat是如何保证不同项目中相同的类互不干扰的
https://www.cnblogs.com/aspirant/p/8991830.html
https://www.cnblogs.com/xiezhengcai/archive/2012/02/26/2369179.html
https://www.jianshu.com/p/51b2c50c58eb
**总结:
(1)tomcat并没有遵循双亲委派机制,对于不同的工程是创建多个webappclassload进行加载的,若使用双亲委派机制进行加载,不同项目的相同包将使用同一份,有可能造成jar包冲突
(2)双亲委派以及多实现类加载器的好处:结构分层,避免重复加载类,比如若自定义的类和java自带的类重复了,那么若不按双亲委派,而使用独立的类加载器加载,有可能加载进虚拟机的是自己类,而不是java自带的,可能造成安全问题,那么双亲委派会优先通过启动类去加载java路径下的类,加载完了发现已加载时不会再加载同名的自定义的类
(3)在这里插入图片描述
(4)通过Tomcat的class加载的优先顺序一览 ,可以判断不同项目中的公用包可以提取出来共同使用,不过不建议https://www.cnblogs.com/penzz/p/3241870.html
**

设计模式(白话叙述理解)

https://blog.csdn.net/qq_39404258/article/details/81175421
1、建造者模式
对象中拥有多属性,持续对对象进行属性赋值,而不需每次都set一个值,形如objectDto.Build().name(name).year(year).build()
2、原型模式
通过拷贝原始对象生成新的对象,一般实现Cloneable接口,现在对于对象的拷贝,更多的是使用BeanUtils.copy
3、适配器模式
简言之就是原有的方法不能满足需求,需要在此基础上进行拓展,常举的什么电源适配,220V转5V,包括对第三方接口进行适配,比如已有的接口不能满足要求,对原有的接口进行包装下,如接口升级,保留老接口,重构新版本接口
4、模板模式
抽象出子类中的共性方法到父类中,细节由各个子类实现,如人、车数据都要发送,其有些共性的方法,将共性的方法抽取出来,在人、车特性的类中实现不一样的内容
5、代理模式
代理模式和装饰模式很像,都是对原有的方法进行扩展,细品装饰模式,FileInputStream是对InputStream的功能进行了加强,是为了能够更好的完成文件的处理,而代理模式,通常是获取到原有的方法,在方法前后进行处理,比如加日志这种,其目的不是为了增强原有的功能,而是为了获取到原有对象(。。。),功能上不一样,结构上很像
https://zhuanlan.zhihu.com/p/97499017
6、中介者模式
对象间的关系比较复杂,通过中间对象解决复杂关系。举例:房东和房客之间的关系很乱,房东将房源脱管给中介去处理。比如,消息中间件也属于这种模式,将消息发给mq,其他组件监听mq,比如通常为了加速线程处理,会把相应的任务信息发送到队列中,多线程从队列中取,类似于生产者和消费者这种
7、责任链模式
链式调用结构,一个处理完给下一个处理,通过获取next交给下一个对象处理,典型的过滤器,对于我自己来说还是没有if,else香,因为没有那么多的处理流程,若是像Servlet那样过滤器很多,当然是用责任链模式比较好
http://c.biancheng.net/view/1383.html
8、策略模式
策略模式和模板模式很像的,区别是模板模式中,是将公同的部分抽象出来到父类中,只在子类中实现细节,而策略模式中是为了实现某个功能将所有的功能整体封装在子类对象中
https://segmentfault.com/q/1010000003024759
9、门面模式
将复杂的对象调用包裹起来,对外提供简单的调用方式,而不去关心内部实现的细节,比如对外接口这种,外部调用者不管你里面具体怎么调用的,包括怎么调用其他子系统。区别于代理模式,代理的代理类和门面的门面类都是拿子模块的对象,但是代理模式是在拿到代理类前后实现一些自我逻辑,比如加日志,权限等,而门面模式则是对外提供一个简单的接口,而不是增加调用者的需求

Maven相关

1.maven jar包冲突
链接1
链接2
总结:
(1)第一声明者优先原则,先声明先使用
(2)路径近者优先原则
(3)排除依赖原则

2.maven 作用域
https://blog.csdn.net/u011191463/article/details/68066656
总结:
(1)compile(默认);(2)test;(3)runtime;(4)provided;(5)system

网络

1.csrf攻击原理

2.TCP/IP 协议模型
http://www.360doc.com/content/10/0730/16/2149364_42538187.shtml
https://zhidao.baidu.com/question/573470632.html
总结:OSI模型七层,TCP/IP协议四层或者五层都行,主要是上三层,其中
应用层:http、Telnet、ftp、DNS、SMTP
传输层:TCP、UDP、RTP
网络层:IP、ICMP、ARP、RARP

3.TCP/IP 三次握手四次挥手
https://www.cnblogs.com/bj-mr-li/p/11106390.html
总结:
为什么不能使用两次握手建立连接?
若客户端建立连接请求的报文因为延时到达服务端,若延时到达后原有的连接已经关闭,那么此时服务端将会认为客户端要建立连接,将会向客户端发送报文,1、若此时客户端实际没有连接服务端,将会扔掉所有从服务端来的报文;2、若此时客户端正好新建请求到服务端,收到服务端的回复后,以为建立了连接,实际上收到的是上次的连接恢复,那么在发送数据时,会造成数据错乱,因此发送数据都是有序号的

https://www.jianshu.com/p/4d39863e62ab

4.http响应码
https://www.runoob.com/http/http-status-codes.html

分类分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误
**(1)100 Continue 继续。客户端应继续其请求;
(2)101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
(3)400 Bad Request 客户端请求的语法错误,服务器无法理解,比如json格式错误
(4)401 Unauthorized 请求要求用户的身份认证
(5)403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
(6)405 Method Not Allowed 客户端请求中的方法被禁止
(7)501 Not Implemented 服务器不支持请求的功能,无法完成请求
(8)502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应**

数据库

1.pg数据库分表
https://www.cnblogs.com/yanshw/p/11445780.html
https://www.jianshu.com/p/705c359ed76e
触发器教程
**总结:
(1)创建子表并且继承父表
(2)为子表的数据插入添加限制
(3)创建触发器,实现在向父表插入时自动插入到子表中,在创建触发器之前需要先创建插入
函数 **

2.pg自定义函数并且调用

create or replace function f() returns void as $f$	--创建一个f()函数,返回void
declare 
	i int :=0;										--定义一个变量i,循环插入数据
begin
	while i<1000 loop
	insert into tbl_partition (date_key,hour_key,client_key,item_key,account,expense,id) values (to_date('2016-1-28 15:42:56','yyyy-mm-dd hh24:mi:ss'),1,1,1,1,1,i);
	i=i+1;
	end loop;
end
$f$
language plpgsql;

select f()											--函数调用

安装教程

1.ES安装
https://www.cnblogs.com/hualess/p/11540477.html
npm install -g grunt-cli无法安装
phantomjs无法下载
ES7.0版本参考中间会有错误信息混合使用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值