对于javaSE的理解
是整个JAVA的基础和核心,是刚接触java要学习的基础知识
1.1 控制数据的流向,将前台传过来的数据包起来,而后一个一个地插入数据库永久保存。
1.2 从数据库中用jdbc取出数据,而后包起来,最终传递到前台页面进行公开展览
where、having之间的区别和用法
聚合函数是比较where、having 的关键。
若须引入聚合函数来对group by 结果进行过滤 则只能用having
select sum(score) from student where sex='man' group by name having sum(score)>210
where 后不能跟聚合函数,由于where执行顺序大于聚合函数
dubbo
调用关系说明:
0. 服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册本身提供的服务。 --写入本身的URL地址。
2. 服务消费者在启动时,向注册中心订阅本身所需的服务。 --订阅提供者的URL地址,并写入本身的URL地址。
3. 注册中心返回服务提供者地址列表给消费者,若是有变动,注册中心将基于长链接推送变动数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,若是调用失败,再选另外一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo建议使用Zookeeper做为服务的注册中心。
Dubbo的将注册中心进行抽象,是得它能够外接不一样的存储媒介给注册中心提供服务,有ZooKeeper,Redis等
首先是负载均衡,单注册中心的承载能力是有限的,在流量达到必定程度的时 候就须要分流,负载均衡就是为了分流而存在的,一个ZooKeeper群配合相应的Web应用就能够很容易达到负载均衡;资源同步,单单有负载均衡还不够,节点之间的数据和资源须要同步
负载均衡策略
RandomLoadBalance:随机负载均衡算法,Dubbo默认的负载均衡策略
按权重设置随机几率。在一个截面上碰撞的几率较高,但调用越大分布越均匀
RoundRobinLoadBalance:轮询负载均衡算法,按公约后的权重设置轮循比率
这种模式下,在权重设置不合理的状况下,会致使某些节点没法负载请求,另外,若是有些机器性能比较低,会存在请求阻塞的状况
ConsistentHashLoadBalance: 一致性Hash,相同参数的请求老是发到同一提供者。
当某一台提供者挂时,本来发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引发剧烈变更。
Zookeeper的做用:
zookeeper用来注册服务和进行负载均衡,哪个服务由哪个机器来提供必需让调用者知道,简单来讲就是ip地址和服务名称的对应关系。固然也能够 经过硬编码的方式把这种对应关系在调用方业务代码中实现,可是若是提供服务的机器挂掉调用者没法知晓,若是不更改代码会继续请求挂掉的机器提供服务。 zookeeper经过心跳机制能够检测挂掉的机器并将挂掉机器的ip和服务对应关系从列表中删除。
java小例子: int a=2,b=2;
硬编码:if(a==2) return false;
非硬编码 if(a==b) return true; (就是把数值写成常数而不是变量 )
一个简单的版本:如求圆的面积 的问题 PI(3.14)
那么3.14*r*r 就是硬编码,而PI*r*r 就不是硬编码。
ZooKeeper的特性引进来。
首先是负载均衡,单注册中心的承载能力是有限的,在流量达到必定程度的时 候就须要分流,负载均衡就是为了分流而存在的,一个ZooKeeper群配合相应的Web应用就能够很容易达到负载均衡
资源同步 节点之间的数据和资源须要同步,ZooKeeper集群就自然具有有这样的功能
Zookeeper作了什么?
配置管理 若是程序分散部署在多台机器上,要逐个改变配置就变得困难。如今把这些配置所有放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,而后全部相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每一个应用程序就会收到 Zookeeper 的通知
集群管理 是否有机器退出和加入、选举master。
分布式锁 一个是保持独占,另外一个是控制时序。
dubbo协议
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多(并发量高),单一消费者没法压满提供者,尽可能不要用dubbo协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
一、dubbo默认采用dubbo协议,dubbo协议采用单一长链接和NIO异步通信,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的状况
二、他不适合传送大数据量的服务,好比传文件,传视频等,除非请求量很低。
三、Dubbo协议缺省每服务每提供者每消费者使用单一长链接,若是数据量较大,可使用多个链接。
四、为防止被大量链接撑挂,可在服务提供方限制大接收链接数,以实现服务提供方自我保护
为何采用异步单一长链接?
由于服务的现状大都是服务提供者少,一般只有几台机器,而服务的消费者多,可能整个网站都在访问该服务,好比Morgan的提供者只有6台提供者,却有上百台消费者,天天有1.5亿次调用,若是采用常规的hessian服务,服务提供者很容易就被压跨,经过单一链接,保证单一消费者不会压死提供者,长链接,减小链接握手验证等
何时用长链接,短链接?
长链接多用于操做频繁,点对点的通信,并且链接数不能太多状况。每一个TCP链接都须要三步握手,这须要时间,若是每一个操做都是先链接,再操做的话那么处理速度会下降不少,因此每一个操做完后都不断开,次处理时直接发送数据包就OK了,不用创建TCP链接。例如:数据库的链接用长链接,若是用短链接频繁的通讯会形成socket错误,并且频繁的socket 建立也是对资源的浪费。
而像WEB网站的http服务通常都用短连接,由于长链接对于服务端来讲会耗费必定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的链接用短链接会更省一些资源,若是用长链接,并且同时有成千上万的用户,若是每一个用户都占用一个链接的话,那可想而知吧。因此并发量大,但每一个用户无需频繁操做状况下需用短连好。
短链接:通讯双方有数据交互时,就创建一个TCP链接,数据发送完成后,则断开此TCP链接
单例模式:确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例
枚举(单例模式)
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
// 饿汉式单例
public class Singleton1 {
// 私有构造
private Singleton1() {}
private static Singleton1 single = new Singleton1();
// 静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
应用刚启动的时候,无论外部有没有调用该类的实例方法,该类的实例就已经建立好了。以空间换时间
写法简单,在多线程下也能保证单例实例的惟一性,不用同步,运行效率高。
当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的惟一实例将被建立。
懒汉式:
应用刚启动的时候,并不建立实例,当外部调用该类的实例或者该类实例方法的时候,才建立该类的实例。是以时间换空间。
实例在被使用的时候才被建立,能够节省系统资源,体现了延迟加载的思想。html
/**
* 饱汉式(懒汉式)----就是有钱,豪,用的时候再new(线程不安全)
* <p>
* Created by lxk on 2017/3/23
*/
public class SingletonPattern2 {
private static SingletonPattern2 singletonInstance;
private SingletonPattern2() {
}
public static SingletonPattern2 getSingletonInstance() {
if (singletonInstance == null) {
singletonInstance = new SingletonPattern2();
}
return singletonInstance;
}
///**
// * 为了应对上述的不安全,能够简单的以下操做给方法添加[synchronized],使之成为同步函数。
// * 可是:
// * 在不少线程的状况下,就每一个线程访问都得判断锁,效率就是问题。因此,才有后面的[双重锁形式]
// */
//public static synchronized SingletonPattern2 getSingletonInstance() {
// if (singletonInstance == null) {
// singletonInstance = new SingletonPattern2();
// }
// return singletonInstance;
//}
在任何须要生成复杂对象的地方,均可以使用工厂方法模式(好比 计算器的加减乘除)
步骤 1
建立一个接口:
Shape.java
public interface Shape { void draw(); }
步骤 2
建立实现接口的实体类。
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
步骤 3
建立一个工厂,生成基于给定信息的实体类的对象。
ShapeFactory.java
public class ShapeFactory { //使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){ return null; }
if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
步骤 4
使用该工厂,经过传递类型信息来获取实体类的对象。
FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory(); //获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE"); //调用 Circle 的 draw 方法 shape1.draw(); //获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw(); //获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE"); //调用 Square 的 draw 方法 shape3.draw();
}
}
步骤 5
执行程序,输出结果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
sql优化
SELECT子句中避免使用‘*’;
表设计--合理的增长冗余的字段(减小表的联接查询);
在业务密集的SQL当中尽可能不采用IN操做符,用EXISTS替代IN、用NOT EXISTS替代NOT IN;
用UNION-ALL 替换UNION /or( 若是有可能的话);
最左匹配原则
两个字段(name,age)创建联合索引,若是where age=12这样的话,是没有利用到索引的,这里咱们能够简单的理解为先是对name字段的值排序,而后对age的数据排序,若是直接查age的话,这时就没有利用到索引了,查询条件where name=’xxx’ and age=xx 这时的话,就利用到索引了
失效条件
条件是or,若是还想让or条件生效,给or每一个字段加个索引
避免在索引列上使用计算。WHERE子句中,若是索引列是函数的一部分。优化器将不使用索引而使用全表扫描;
低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000; 高效: SELECT … FROM DEPT WHERE SAL > 25000/12;
模糊查询like 关键词%yue%,因为yue前面用到了“%”,所以该查询必然走全表扫描,除非必要,不然不要在关键词前加%;
注意:like ‘…%’,是会使用索引的;左模糊like
考虑索引重建场合
索引最大的好处是提升查询速度,
缺点是更新数据时效率低,由于要同时更新索引
对数据进行频繁查询进创建索引,若是要频繁更改数据不建议使用索引。
表上频繁发生update,delete操做。
表上发生了alter table ..move操做(move操做致使了rowid变化)
为何要分库分表,主从复制,读写分离
针对大数据量而且访问频繁的表,将其分为若干个表
当一张表的数据达到几千万时,你查询一次所花的时间会变多,若是有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减少数据库的负担,缩短查询时间;
主从结构,一主多备,读写分离,读从库,写主库
在实际的应用中,绝大部分状况都是读远大于写。Mysql提供了读写分离的机制,全部的写操做都必须对应到Master,读操做能够在 Master和Slave机器上进行,Slave与Master的结构彻底同样,
全部的写操做都是先在Master上操做,而后同步更新到Slave上,因此从Master同步到Slave机器有必定的延迟
提升数据库的吞吐量
非关系型数据库中,咱们查询一条数据,结果出来一个数组,关系型数据库中,查询一条数据结果是一个对象。
关系型数据库
SQLite、Oracle、mysql
特性:关系型数据库的最大特色就是事务的一致性;
优势:通用的SQL语言使得操做关系型数据库很是方便,大大减低了数据冗余和数据不一致的几率;
缺点:为了维护一致性所付出的巨大代价就是其读写性能比较差,海量数据的高效率读写;
非关系型数据库
MongoDb、redis、HBase
特性:使用键值对存储数据;严格上不是一种数据库,应该是一种数据结构化存储方法的集合
优势:无需通过sql层的解析,读写性能很高,nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。
缺点:不提供sql支持,学习和使用成本较高,无事务处理,附加功能bi和报表等支持也很差
数据库事务必须具有ACID特性,ACID是Atomic原子性,Consistency一致性,Isolation隔离性,Durability持久性
事务的四大特性
原子性--事务包含的全部操做要么所有成功,要么所有失败回滚
一致性--事务必须使数据库从一个一致性状态变换到另外一个一致性状态,也就是说一个事务执行以前和执行以后都必须处于一致性状态。
拿转帐来讲,假设用户A和用户B二者的钱加起来一共是5000,那么无论A和B之间如何转帐,转几回帐,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
隔离性--多个用户并发访问数据库时,好比操做同一张表时,数据库为每个用户开启的事务,不能被其余事务的操做所干扰,多个并发事务之间要相互隔离.
持久性--一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即使是在数据库系统遇到故障的状况下也不会丢失提交事务的操做。
脏读:事务B读取事务A尚未提交的数据
不可重复读:两次事务读的数据不一致
幻读:事务A修改了数据,事务B也修改了数据,这时在事务A看来,明明修改了数据,昨不同,
隔离级别
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何状况都没法保证。
Spring 框架前端
spring管理的bean在默认状况下是会在服务器启动的时候初始化的。
bean设置了scope为prototype(原型)以后,会每次使用时生产一个
bean设置了lazy-init=”true”后,启动服务器不会立刻实例化,而是在用到的时候被实例化
具体来讲Spring是一个轻量级的容器,用于管理业务相关对象的。核心功能主要为:IOC,AOP,MVC。
Spring 的基础是ioc和 aop,ioc 提供了依赖注入的容器, aop解决了面向横切面的编程
控制反转IoC(Inversion of Control)
是说建立对象的控制权进行转移,之前建立对象的主动权和建立时机是由本身把控的,而如今这种权力转移到第三方,好比转移交给了IoC容器,它就是一个专门用来建立对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,经过IoC容器来创建它们之间的关系,让容器管理对象的生命周期如建立,初始化,销毁等。
DI(依赖注入)其实就是IOC的另一种说法
Spring MVC提供了一种轻度耦合的方式来开发web应用。它是Spring的一个模块,是一个web框架。经过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易
SpringBoot实现了自动配置,下降了项目搭建的复杂度。它主要是为了解决使用Spring框架须要进行大量的配置太麻烦的问题,因此它并非用来替代Spring的解决方案,而是和Spring框架紧密结合用于提高Spring开发者体验的工具
spring-colud是一种云端分布式架构解决方案,基于spring boot,在spring boot作较少的配置,即可成为 spring cloud 中的一个微服务。
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
Spring AOP的核心实现原理就是采用的动态代理,根据被代理对象是否实现了所要被代理的接口这个条件,动态代理会选择不一样的实现方案。
java中最多见的动态代理模式:jdk原生动态代理和cgLlb动态代理
JDK原生:不须要任何外部依赖,但只能基于接口进行代理,实现一个InvocationHandler,方法调用会被转发到该类的invoke()方法,在须要使用对象实例的时候,经过JDK动态代理获取实例的代理对象
cgLlb:经过继承的方式实现,不管目标对象有没有实现接口均可以代理,可是没法处理final的状况
其实最核心的仍是java的反射机制,经过获取对象实例,调用对应的方法,前者经过接口来作桥梁,后者经过中间类转发,都只是形式而已
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程当中的步骤进行抽象,,从而得到步骤之间的逻辑划分。
aop框架具备的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
SpringMVC工做流程
一、用户发送请求至前端控制器DispatcherServlet
二、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
三、处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(若是有则生成)一并返回给DispatcherServlet。
四、DispatcherServlet调用HandlerAdapter处理器适配器
五、HandlerAdapter通过适配调用具体的处理器(Controller,也叫后端控制器)。
六、Controller执行完成返回ModelAndView
七、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
八、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
九、ViewReslover解析后返回具体View
十、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
十一、DispatcherServlet响应用户
简单:系统启动的时候根据配置文件建立spring的容器, 首先是发送http请求到核心控制器DispatcherServlet,spring容器经过映射器去寻找业务控制器,
使用适配器找到相应的业务类,在进业务类时进行数据封装,在封装前可能会涉及到类型转换,执行完业务类后使用ModelAndView进行视图转发,
数据放在model中,用map传递数据进行页面显示。
值传递和引用传递的区别
值传递仅仅传递的是值。
引用传递,传递的是内存地址,修改后会改变内存地址对应储存的值。
用数组来举例就最清楚了,例如咱们定义一个数组a[]={1,2};那么a[0]=1, a[1=2].
若是咱们把数组a里的元素值做为参数传递,实际上只是进行了值传递,对数组自己没有影响
若是咱们把 数组a的指针做为参数传递,那么假如处理的函数就能够直接修改数组a里的值。
== 和equals区别?
当“==”运算符的两个操做数都是包装器类型的引用,则是比较执行的是不是同于个对象,而若是二者比较中有一个操做数是表达式(含运算符)则比较的是数值(会自动触发拆箱的过程)
equals 用于判断两个变量是不是对同一个对象的引用
Session和Cookie的区别?
session是存放在服务器端的,cookie是存放在客户端的,cookie的安全性不高,虽然它已经加了密,可是仍是能够伪造的。
死锁产生发生:
线程死锁是指因为两个或者多个线程互相持有对方所须要的资源,致使这些线程处于等待状态,没法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其余线程将不能进入该代码块。当线程互相持有对方所须要的资源时,会互相等待对方释放资源,若是线程都不主动释放所占有的资源,将产生死锁。
如何避免:
一、加锁顺序:
二、加锁时限:
解决方案:简单粗暴 找到进程号,kill 进程
String,StringBuffer和StringBuilder的区别
一、运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String。
二、线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。
适用场景分析:
String:适用于少许的字符串操做的状况
StringBuilder:适用于单线程下在字符缓冲区进行大量操做的状况
StringBuffer:适用多线程下在字符缓冲区进行大量操做的状况
mybatis如何处理结果集
MyBatis的结果集是经过反射来实现的
MyBatis里面的核心处理类叫作SqlSession
MyBatis(IBatis)的好处是什么
把sql语句从Java源程序中独立出来,放在单独的XML文件中编写,给程序的维护带来了很大便利。
封装了底层JDBC API的调用细节,并能自动将结果集转换成JavaBean对象,大大简化了Java数据库编程的重复工做
须要程序员本身去编写sql语句,程序员能够结合数据库自身的特色灵活控制sql语句,更高的查询效率
#{}与${}的区别
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #{user_id},若是传入的值是111,那么解析成sql时的值为order by “111”, 若是传入的值是id,则解析成的sql为order by “id”.
2. $将传入的数据直接显示生成在sql中。如:order by ${user_id},若是传入的值是111,那么解析成sql时的值为order by 111, 若是传入的值是id,则解析成的sql为order by id.
${}方式会引起SQL注入的问题、同时也会影响SQL语句的预编译,因此从安全性和性能的角度出发,能使用#{}的状况下就不要使用${}。
在mapper中如何传递多个参数
第一种:使用 @param 注解 第二种:多个参数封装成map
分布式锁通常有三种实现方式:(乐观锁,本身实现,经过版本号 )
1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁
首先,为了确保分布式锁可用,咱们至少要确保锁的实现同时知足如下四个条件:
互斥性。在任意时刻,只有一个客户端能持有锁。
不会发生死锁。即便有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其余客户端能加锁。
具备容错性。只要大部分的Redis节点正常运行,客户端就能够加锁和解锁。
解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端本身不能把别人加的锁给解了。java
加锁
1. 当前没有锁(key不存在),那么就进行加锁操做,并对锁设置个有效期,同时value表示加锁的客户端。mysql
2. 已有锁存在,不作任何操做。
解锁
首先获取锁对应的value值,检查是否与requestId相等,若是相等则删除锁(解锁)
深刻探索SpringApplication执行流程
若是咱们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要建立一个SpringApplication对象实例,而后调用这个建立好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提早作几件事情:
根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该建立一个为Web应用使用的ApplicationContext类型。
使用SpringFactoriesLoader在应用的classpath中查找并加载全部可用的ApplicationContextInitializer。实现了这个接口的这些实例将在上下文初始化的时候prepareContext被使用。
使用SpringFactoriesLoader在应用的classpath中查找并加载全部可用的ApplicationListener。这个接口表示这个接口将监听对应的ApplicationEvent事件
推断并设置main方法的定义类。
Spring 框架中的单例 Beans 是线程安全的么?
Spring 框架并无对单例 bean 进行任何多线程的封装处理。关于单例 bean 的线程安全和并
发问题须要开发者自行去搞定。但实际上,大部分的 Spring bean 并无可变的状态(好比
Serview类和DAO类),因此在某种程度上说Spring的单例bean是线程安全的。若是你的bean
有多种状态的话(好比 View Model 对象),就须要自行保证线程安全。
最浅显的解决办法就是将多态 bean 的做用域由“singleton”变动为“prototype”。
spring开发web 时要注意,默认Controller、Dao、Service都是单例的
@SpringBootApplication是一个复合注解,包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration。
@Autowired和@Resource(java原生)开启基于注解的自动装配
@Autowired是Spring的注解,@Resource是J2EE的注解
@Component是全部受Spring 管理组件的通用形式,@Component注解能够放在类的头上,@Component不推荐使用。
@Service对应的是业务层Bean
@Controller对应表现层的Bean
@RequestMapping 代表全部的请求路径都要基于该路径
Java集合类
(1)List 支持null元素和重复元素的动态扩容列表,jdk提供的实现类有:ArrayList, LinkedList, Stack,CopyOnWriteArrayList、Vector
(2)Set 不支持重复元素的动态扩容列表,jdk提供的实现类有:EnumSet, TreeSet, HashSet, LinkedHashSet、 NavigableSet、ConcurrentSkipListSet、CopyOnWriteArraySet
(3)map 是存储键/值对的映射集,jdk提供的实现类有:HashMap, TreeMap,LinkedHashMap、ConcurrentHashMap、HashTable、ConcurrentSkipListMap
(4)queue/deque queue是在集合尾部添加元素,在头部删除元素的队列,deque是可在头部和尾部添加或者删除元素的双端队列
List 线程不安全的子类:ArrayList, LinkedList,
ArrayList:是一个容量动态扩张的集合,实现了RandomAccess接口,支持随机访问,能够经过List list = Collections.synchronizedList(new ArrayList(...))把它转成线程安全的集合,固然只是封装了对ArrayList的操做,保存同步而已,性能不是很高,全部的修改操做都要一个个同步。
LinkedList:内部是链表结果,非线程安全,添加元素的方法只是新增一个节点而后改变尾部节点和新增节点的引用连接,因此新增和删除操做比较快,可是不支持随机访问,同时实现List和Deque接口,因此便可以当一个双端队列使用,也能够当List使用
set 线程不安全的子类:EnumSet, TreeSet, HashSet, LinkedHashSet、 NavigableSet
treeSet是有序集合,内部经过TreeMap来存储元素,把元素存储在map的key里,经过TreeMap存储Key的有序性和无重复性来实现本身的有序性和Set的的元素无重复性
HashSet不是线程安全的
map 线程不安全的子类:HashMap, TreeMap,LinkedHashMap,键值对、键惟1、值不惟一
HashMap是线程不安全的提供全部Map操做的集合容器,支持Null为key或者value,而且是无序的。nginx
HashMap是线程不安全的,不要在并发的环境中同时操做HashMap,建议使用ConcurrentHashMap。
jdk1.8后HashMap的存储结构,由于和1.7以前都不太同样,性能也不同。
jdk1.8以前,hashMap的存储结构是数组+链表,也就是发生hash冲突后的元素后插入到链表里,而不是存储在数组,这样的的话若是对于hash冲突比较严重的数据时,hashMap的查询速度就不是o(1)了,而是o('n');
jdk1.8后,HashMap的存储结构是数组+链表or平衡树,由于平衡树的时间复杂度是o(log('n')),是1.8后HashMap的查询复杂度是O(1)~O(log('n' ))。
loadFactor是触发HashMap扩容的负载因子,默认是0.75,扩容是很是耗时的事情,因此这个负载因子很重要,0.75是性能比较好的一个数
若是你常常会使用索引来对容器中的元素进行访问,那么 List 是你的正确的选择。若是你已经知道索引了的话,那么 List 的实现类好比 ArrayList 能够提供更快速的访问,若是常常添加删除元素的,那么确定要选择LinkedList。
若是你想容器中的元素可以按照它们插入的次序进行有序存储,那么仍是 List,由于 List 是一个有序容器,它按照插入顺序进行存储。
若是你想保证插入元素的惟一性,也就是你不想有重复值的出现,那么能够选择一个 Set 的实现类,好比 HashSet、LinkedHashSet 或者 TreeSet。全部 Set 的实现类都遵循了统一约束好比惟一性,并且还提供了额外的特性好比 TreeSet 仍是一个 SortedSet,全部存储于 TreeSet 中的元素可使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
若是你以键和值的形式进行数据存储那么 Map 是你正确的选择。你能够根据你的后续须要从 Hashtable、HashMap、TreeMap 中进行选择。
Comparable和Comparator区别比较
Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,咱们若须要控制某个类的次序,能够创建一个“该类的比较器”来进行排序。
Comparable至关于“内部比较器”,而Comparator至关于“外部比较器”。
两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个能够比较的对象,可是须要修改源代码。 用Comparator 的好处是不须要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象须要做比较的时候,把比较器和对象一块儿传递过去就能够比大小了, 而且在Comparator 里面用户能够本身实现复杂的能够通用的逻辑,使其能够匹配一些比较简单的对象,那样就能够节省不少重复劳动了。
jdk1.8 lambam表达式
// 之前的循环方式
for (String player : players) {
System.out.print(player + "; ");
}
// 使用 lambda 表达式以及函数操做(functional operation)
players.forEach((player) -> System.out.print(player + "; "));
使用Lambdas排序集合
// 1.3 也能够采用以下形式:
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
readExcelList.stream().forEach(p->{ xxx });
java经过Stream对list集合分组
CompleteDtos.stream().collect(Collectors.groupingBy(CompleteRateDto::getIdKey)).values().forEach(p->{ xxx });
kafaka
Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和重复的日志服务。
nginx程序员
在正向代理中,Proxy和Client同属于一个LAN(图中方框内),隐藏了客户端信息;web
在反向代理中,Proxy和Server同属于一个LAN(图中方框内),隐藏了服务端信息;redis
负载均衡调度算法:算法
weight轮询(默认):接收到的请求按照顺序逐一分配到不一样的后端服务器,即便在使用过程当中,某一台后端服务器宕机,Nginx会自动将该服务器剔除出队列,请求受理状况不会受到任何影响。spring
ip_hash:每一个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器
(1)保证内网的安全,一般将反向代理做为公网访问地址,Web服务器是内网
(2)负载均衡,经过反向代理服务器来优化网站的负载
Tomcat在高并发环境下处理动态请求时性能很低,而在处理静态页面更加脆弱,可是经过Nginx来处理静态页面要比经过Tomcat处理在性能方面好不少
Nginx能够经过两种方式来实现与Tomcat的耦合。
将静态页面请求交给Nginx,动态请求交给后端Tomcat处理。
将全部请求都交给后端的Tomcat服务器处理,同时利用Nginx自身的负载均衡功能,进行多台Tomcat服务器的负载均衡。
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
①Web服务器首先检查是否已经装载并建立了该Servlet的实例对象。若是是,则直接执行第④步,不然,执行第②步。
②装载并建立该Servlet的一个实例对象。
③调用Servlet实例对象的init()方法。
④建立一个用于封装HTTP请求消息的HttpServletRequest对象和一个表明HTTP响应消息的HttpServletResponse对象,而后调用Servlet的service()方法并将请求和响应对象做为参数传递进去。
⑤WEB应用程序被中止或从新启动以前,Servlet引擎将卸载Servlet,并在卸载以前调用Servlet的destroy()方法。
Servlet是一个供其余Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行彻底由Servlet引擎来控制和调度。
针对客户端的屡次Servlet请求,一般状况下,服务器只会建立一个Servlet实例对象,也就是说Servlet实例对象一旦建立,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
ConcurentHashMap原理?
线程不安全的HashMap-- 由于多线程环境下,使用Hashmap进行put操做会引发死循环,致使CPU利用率接近100%,因此在并发状况下不能使用HashMap。 底层数组+链表实现,线程不安全
效率低下的HashTable容器 -- HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的状况下HashTable的效率很是低下。由于当一个线程访问HashTable的同步方法时,其余线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态
底层数组+链表实现 线程安全
ConcurrentHashMap --底层采用分段的数组+链表实现,线程安全,jdk 1.8后 变动为table数组+单向链表+红黑树的结构,负载因子恒定为0.75
经过把整个Map分为N个Segment,能够提供相同的线程安全,可是效率提高N倍,默认提高16倍。
锁分段技术:首先将数据分红一段一段的存储,而后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其余段的数据也能被其余线程访问。
ConcurrentHashMap提供了与Hashtable和SynchronizedMap不一样的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操做;而ConcurrentHashMap中则是一次锁住一个桶。
诸如get、put、remove等经常使用操做只锁住当前须要用到的桶。这样,原来只能一个线程进入,如今却能同时有16个写线程执行,并发性能的提高是显而易见的
spring事务和jdbc事务的优缺点
Spring提供了对事务的声明式事务管理,只须要在配置文件中作一些配置,便可把操做归入到事务管理当中,解除了和代码的耦合。
Spring声明式事务管理,核心实现就是基于Aop。
Spring声明式事务管理是粗粒度的事务控制,只能给整个方法应用事务,不能够对方法的某几行应用事务。
1.xml方式声明事务 2.注解方式声明事务
JDBC事务
JDBC的一切行为包括事务是基于一个Connection
的,在JDBC中是经过Connection
对象进行事务管理。在JDBC中,经常使用的和事务相关的方法是: setAutoCommit
、commit
、rollback
等。
JDBC为使用Java进行数据库的事务操做提供了最基本的支持。经过JDBC事务,咱们能够将多个SQL语句放到同一个事务中,保证其ACID特性。JDBC事务的主要优势就是API比较简单,能够实现最基本的事务操做,性能也相对较好。
可是,JDBC事务有一个局限:一个 JDBC 事务不能跨越多个数据库
http原理
HTTP的工做过程
一次HTTP操做称为一个事务,其工做过程可分为四步:
1)首先客户机与服务器须要创建链接。只要单击某个超级连接,HTTP的工做开始。
2)创建链接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。
3)服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
4)客户端接收服务器所返回的信息经过浏览器显示在用户的显示屏上,而后客户机与服务器断开链接。
若是在以上过程当中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来讲,这些过程是由HTTP本身完成的,用户只要用鼠标点击,等待信息显示就能够了。
设计模式分哪几种
整体来讲设计模式分为三大类:
建立型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
Socket并发解决方案?
多线程同步实现?
synchronized和volatile的使用区别?
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰以后,那么就具有了两层语义:
1)保证了不一样线程对这个变量进行操做时的可见性,即一个线程修改了某个变量的值,这新值对其余线程来讲是
当即可见的。
2)禁止进行指令重排序。
volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取;
synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。
1.volatile仅能使用在变量级别;
synchronized则可使用在变量、方法、和类级别的
2.volatile仅能实现变量的修改可见性,并不能保证原子性;
synchronized则能够保证变量的修改可见性和原子性
3.volatile不会形成线程的阻塞;
synchronized可能会形成线程的阻塞。
mybatis和hibernate的优缺点
Hibernate的优势:
一、hibernate是全自动,hibernate彻底能够经过对象关系模型实现对数据库的操做,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。
二、数据库移植性良好。
Hibernate的缺点:
一、学习门槛高,精通门槛更高,程序员如何设计O/R映射,在性能和对象模型之间如何取得平衡,以及怎样用好Hibernate方面须要的经验和能力都很强才行
二、hibernate的sql不少都是自动生成的,没法直接维护sql;虽然有hql查询,但功能仍是不及sql强大,见到报表等变态需求时,hql查询要虚,也就是说hql查询是有局限的;hibernate虽然也支持原生sql查询,但开发模式上却与orm不一样,须要转换思惟,所以使用上有些不方便。总之写sql的灵活度上hibernate不及mybatis。
Mybatis的优势:
一、易于上手和掌握,提供了数据库查询的自动对象绑定功能,并且延续了很好的SQL使用经验,对于没有那么高的对象模型要求的项目来讲,至关完美。
二、sql写在xml里,便于统一管理和优化, 解除sql与程序代码的耦合。
三、提供xml标签,支持编写动态sql。
四、速度相对于Hibernate的速度较快
Mybatis的缺点:
一、关联表多时,字段多的时候,sql工做量很大。
二、sql依赖于数据库,致使数据库移植性差。
三、对象关系映射标签和字段映射标签仅仅是对映射关系的描述,具体实现仍然依赖于sql。
四、编写动态sql时,不方便调试,尤为逻辑复杂时。
java线程池有哪些?线程池的原理,什么场景下不适用线程池
ThreadLocal的理解
向ThreadLocal里面存东西就是向它里面的Map存东西的,而后ThreadLocal把这个Map挂到当前的线程底下,这样Map就仅仅属于这个线程了。
mysql和oracle的区别
最重要的区别
MySQL是轻量型数据库,而且免费,没有服务恢复数据。
Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。
对事务的提交
MySQL默认是自动提交,而Oracle默认不自动提交,须要用户手动提交,须要在写commit;指令或者点击commit按钮
分页查询
MySQL是直接在SQL语句中写"select... from ...where...limit x, y",有limit就能够实现分页;而Oracle则是须要用到伪列ROWNUM和嵌套查询
JVM
类加载的几个过程
加载、验证、准备、解析、初始化。而后是使用和卸载了
堆里面的分区:Eden,survival (from+ to),老年代,各自的特色?
堆里面分为新生代和老生代(java8取消了永久代,采用了Metaspace),新生代包含Eden+Survivor区,survivor区里面分为from和to区,内存回收时,若是用的是复制算法,从from复制到to,当通过一次或者屡次GC以后,存活下来的对象会被移动到老年区,当JVM内存不够用的时候,会触发Full GC,清理JVM老年区
当新生区满了以后会触发YGC,先把存活的对象放到其中一个Survice
区,而后进行垃圾清理。由于若是仅仅清理须要删除的对象,这样会致使内存碎
片,所以通常会把Eden 进行彻底的清理,而后整理内存。那么下次GC 的时候,
就会使用下一个Survive,这样循环使用。若是有特别大的对象,新生代放不下,
就会使用老年代的担保,直接放到老年代里面。由于JVM 认为,通常大对象的存
活时间通常比较久远。
容器
HashMap 底层实现。
HashMap的底层经过位桶实现,位桶里面存的是链表(1.7之前)或者红黑树(有序,1.8开始) ,其实就是数组加链表(或者红黑树)的格式,经过判断hashCode定位位桶中的下标,经过equals定位目标值在链表中的位置,,当添加一个元素(key-value)时,就首先计算元素key的hash值,以此肯定插入数组中的位置,可是可能存在同一hash值的元素已经被放在数组同一位置了,这时就添加到同一hash值的元素的后面,他们在数组的同一位置,可是造成了链表,同一各链表上的Hash值是相同的,因此说数组存放的是链表。而当链表长度太长时,链表就转换为红黑树,这样大大提升了查找的效率。
当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的搬移到新的数组中。
HasMap的扩容机制resize()?
构造hash表时,若是不指明初始大小,默认大小为16(即Node数组大小16),若是Node[]数组中的元素达到(填充比*Node.length)从新调整HashMap大小 变为原来2倍大小,扩容很耗时
何时扩容:当向容器添加元素的时候,会判断当前容器的元素个数,若是大于等于阈值---即当前数组的长度乘以加载因子的值的时候,就要自动扩容啦。
扩容(resize)就是从新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组没法装载更多的元素时,对象就须要扩大数组的长度,以便能装入更多的元素。方法是使用一个新的数组代替已有的容量小的数组,就像咱们用一个小桶装水,若是想装更多的水,就得换大水桶。
Linux系统查看当前运行java的进程?
在Linux下查看全部java进程命令:ps -ef | grep java
中止特定java进程命令:kill -9 java进程序号
中止全部java进程命令:pkill - 9 java
HashSet类是如何实现添加元素保证不重复的?---哈希码的原理
当你利用HashSet建立一个对象时,在HashSet的构造方法中,先用hashCode方法计算出该对象的哈希码。
比较顺序以及原理
(1).若是该对象哈希码与集合已存在对象的哈希码不一致,则该对象没有与其余对象重复,添加到集合中!
(2).若是存在于该对象相同的哈希码,那么经过equals方法判断两个哈希码相同的对象是否为同一对象(判断的标准是:属性是否相同)
1>.相同对象,不添加!
2>.不一样对象,添加!
final finally finalize区别
一、final修饰符(关键字)。被final修饰的类,就意味着不能再派生出新的子类,不能做为父类而被子类继承
二、finally是在异常处理时提供finally块来执行任何清除操做。无论有没有异常被抛出、捕获,finally块都会被执行
三、finalize是方法名。在垃圾收集器删除对象以前对这个对象调用的,将对象从内存中清除出去以前作必要的清理工做。
一 反射机制的概念:
指在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法,对于任意一个对象,都能调用它的任意一个方法.这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制.
二 反射机制的应用:
生成动态代理,面向切片编程(在调用方法的先后各加栈帧).
三 反射机制的原理:
1 首先明确的概念: 一切皆对象----类也是对象.
2 而后知道类中的内容 :modifier constructor field method.
3 其次明白加载: 当Animal.class在硬盘中时,是一个文件,当载入到内存中,能够认为是一个对象,是java.lang.class的对象.
Hash冲突?
因为哈希算法被计算的数据是无限的,而计算后的结果范围有限,所以总会存在不一样的数据通过计算后获得的值相同,这就是哈希冲突
Spring框架分为哪七大模块以及各模块的主要功能做用?
1. Spring Core: Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的须要,并真正地容许你从程序逻辑中分离出依赖关系和配置。2.Spring Context: 构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明建立,好比说经过Servlet容器。3.Spring DAO: DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 而且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不只仅是实现了特定接口,并且对全部的POJOs(plain old Java objects)都适用。4.Spring ORM: ORM 封装包提供了经常使用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,能够混合使用全部Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。5.Spring AOP: Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你能够定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。并且,利用source-level的元数据功能,还能够将各类行为信息合并到你的代码中。6.Spring Web: Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一块儿使用Spring时,这个包使Spring可与其余框架结合。7.Spring Web MVC: Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并非仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。而且,还能够借助Spring框架的其余特性。