JAVA面试题整理2020

一、JAVA SE部分

1、java跨平台原理

程序运行需要将我们的java代码编译成对应的字节码文件,但是各种操作系统(Windows、Linux)的指令并不完全一致,要实现一份字节码文件能在多种系统上都能正常运行,就需要在各平台安装对应系统的JVM(Java Virtual Machine),这是由sun公司提供的,只要按照统一的API接口开发,部署到不同的操作平台时,JVM会屏蔽掉各平台之间的差异,实现同一份代码跨平台运行

2、java基本数据类型

整数类型: 默认类型 int字节数位数取值范围
byte1字节8bit[-128,127] -2^7 ~ 2^7-1
short2字节16bit-2^15 ~ 2^15-1
int4字节32bit-2^31 ~ 2^31-1
long8字节64bit-2^63 2^63-1
小数类型:默认类型 double
float4字节32bit-
double8字节64bit-
布尔类型:true/false
boolean-1bit-
字符类型
char2字节16bit[0,65535]

3、面向对象特征

  1. 封装:把对象封装成一个高度自治且相对封闭的个体,通过其自己提供的方法来对象的属性。例如domain的一个实体类,需要通过get、set方法来进行赋值取值。(封装步骤:1、类用public修饰;2、私有化成员变量;3、提供get、set方法;4提供一个无参构造)
  2. 抽象:把一些事物的共性抽象成一个类,忽略与当前目标和主体无关的部分,值关注与目标有关的属性。即把有一些共性的多个对象抽象为一个类,例如现实生活中的人类、车类,都有部分相同的属性。
  3. 继承:在定义一个类的时候,可以通过extend在一个已经存在的类Parent的基础上进行,就能把已经存在的类Parent中的内容做为自己的内容,并且可以加入其他新的内容,如果有些Parent中的内容有所差异,可以通过重写方法满足自己的特性。(继承特点:1、单继承;2、多重继承;3所有类都隐式继承Object)
  4. 多态:在程序中定义引用变量指向的具体类型在编译时并不确定,而是在程序运行时,通过该变量调用的方法 确定引用哪个类的实例对象。例如接口,可以有多个实现类,UserDao userDao = new UserDaoJdbcImpl(); UserDao userDao = new UserDaoHibernateImpl();通过接口来定义变量,当程序运行时才进行绑定,指向具体的实体类。

4、基本数据类型与包装类

每个基本数据类型都对对应一个包装类,例如:int—Integer;包装类型是一个引用类型,可以存放null,扩展性更强
二者之间的转换通过装箱和拆箱完成;
Integer i = 1,会通过Integer.valueOf(1)方法自动装箱,将基本数据类型转换成对应的包装类型
int j = i,就会通过intValue(i)方法自动拆箱,将包装类型转换成对应的基本类型

5、"=="和equals区别

  1. “= =” 是比较两个变量的值是否相等,变量可以是基本数据类型和引用类型;基本数据类型是存放在栈中,"= ="比较的是基本数据的值是否相等,而引用类型创建后是保存在堆中,生成一个在堆中的地址,将这个地址赋值给变量,用==比较两个变量的时候比较的是他们的地址是否为同一个;
  2. equals只能比较引用类型,是比较两个对象具体的内容是否相同;
    例如String s1=“abc”;String s2 = new String(“abc”);如果通过==进行比较,创建了两个字符串变量,这两个变量指向堆中的地址不一样,就是不相等的,但是如果用equals就是比较他们的具体内容是否相同,结果就是true

6、String、StringBuffer和StringBuilder区别

这三个类都是用来声明和操作字符串
String底层是一个长度不可变final修饰的char字符数组,一旦声明长度就固定,常用来表示长度固定的内容;
StringBuffer和StringBuilder底层都是长度可变的字符数组,创建时默认长度都为16,用来声明需要经常增删改的字符串,通过append()方法进行字符串拼接,效率很高。而这二者的区别是StringBuffer是线程安全,效率相对于线程不安全的StringBuilder相对低一些。
StringBuffer和StringBuilder扩容机制:当要添加的字符串大于 > 当前字符数组的长度的时候扩容,扩容是: 原来长度*2+2 的方式扩容

7、java中的数据结构、集合Collection

  1. java中的数据结构:
    List 存入取出有序可重复的集合
    Set 存入取出无序,不可重复的集合
    Map 键值对集合
    Queue(队列 FIFO) 订单排队等
    Tree树状结构 菜单子菜单,上下级关系,包括:1、二叉树:红黑树(自平衡机制,为了提高查询效率);2、多叉树
  2. 集合Collection:
    集合主要包括List和Set
    1、List:存入取出有序,元素可重复,可以存放null
    ArrayList:基于数组,数组在内存中是连续的,要增删改都需要移动内存,增删改效率低,而查询效率高;
    LinkedList:底层维护了链表,在内存中是不要求连续的,当前元素存放了下一个或上一个元素的地址;如果要查询就必须从第一个元素一个一个找,效率很低;但是对于增删插,并不需要移动内存,只需要修改元素保存的引用地址就可以,所以增删插效率高;
    Vector:线程安全的ArrayList,有线程安全要求的时候使用;
    2、Set:存入取出无序,元素不可重复,可以存放null
    HashSet:基于HashMap,而HashMap又是基于HashCode,非线程安全,没有任何排序要求的时候使用,效率非常高
    HashMap底层是键值对数组+链表+红黑树,它判断重复的机制是先判断HashCode,如果HashCode相同再通过equals进行比较,当两个结果都相等就判定为同一个元素
    TreeSet:基于TreeMap,TreeMap底层又是基于红黑树;可以满足一定的排序要求
    排序方式有两种:
    1、自然排序:实现Comparable接口,重写compareTo方法
    2、定制排序:在创建TreeSet对象的时候传入一个Comparator接口的实现类对象,在实现类重重写compare方法

8、HashMap和HashTable的比较

HashMap和HashTable都是Map接口下的的,Map接口是一个独立体系,与Collection毫无关系
HashMap:基于HashCode,底层是Entry键值对数组,默认长度是16,可以存放null值和null键,线程不安全,效率高;
HashMap在通过put方法保存元素时,会用添加的key对应的HashCode去模数组的长度,来获取下标,然后进行保存。当键值对元素获取到的下标和原有的元素相等时,就会发生Hash冲突(Hash碰撞),这时候就会在对key进行equals比较,当结果为true时,就会用新添加的键值对覆盖掉原有的,而结果为false时,就会在该下标出原有的键值对后面形成一个链表,当链表长度达到8个时,就会形成红黑树,当键值对的数量删除到小于等于6个时,又会将红黑树退化为链表;
HashMap扩容机制:创建是默认长度为16,扩容因子0.75,存放临界值为长度*扩容因子,当存放达到临界值(大于等于)的时候底层通过resize()方法进行扩容,长度扩容为原来的2倍;

HashTable:是一个线程安全的HashMap,效率低,不能存放null值和null键;例如Properties配置文件(.xml、.yml、.properties等)就是HashTable的一个子类,只是键值都是String类型;在JDK8及以后,如果既要保证线程安全又要提高效率,使用ConcurrentHashMap来代替HashTable,理论上效率是HashTable的16倍;

9、线程及线程同步

线程的使用:
方式1:写一个线程类继承Thread类,重新run()方法,通过线程对象.start()启动线程;
方式2:写一个业务类实现Runnable接口,重写run()方法,测试先创建业务类对象,将其作为线程对象的构造方法参数创建线程对象,再.start()启动线程;
注意:run()方法只是执行方法,而线程的启动必须是通过start();

线程的状态
1、new 新建;2、Runnable 就绪,可执行状态;3、Running 运行状态;4、Blocked 阻塞状态;5、死亡Dead;
wait和sleep的区别:
wait:Object方法,使线程等待,直到被notify或者notifyall唤醒,会放弃锁资源;
sleep:Thread的方法,强制使线程睡眠,直到时间结束继续运行,不会放弃锁资源;

线程同步:
1. 同步代码块(悲观锁)
语法:

Synchronized(同步对象){//必须是几个线程对象锁共享的 => static
						有线程安全问题的代码
					}	
					同步对象可以是:static修饰的对象、字节码、this(实现Runnable接口)	
2. 同步方法(悲观锁)
	用Synchronized关键字修饰方法即可,在修饰符位置,返回值前面
		如果方法是static修饰的:同步的是: 当前类.class 
		如果方法是非static修饰的:同步的是: this 
3. 锁机制(乐观锁)
	通过Lock接口的实现类ReentrantLock对象进行上锁lock()和释放锁unlock()

乐观锁(锁机制)效率高,功能强大,悲观锁在读锁和写锁的时候都会进行上锁,就容易堵塞。而乐观锁只有在写锁的时候才会上锁,效率大大提高;

10、线程池

作用:
1、管理多个线程,限定线程个数,防止线程过多导致系统缓慢或崩溃;
2、线程复用,节约资源,提高响应速度,不用每运行一个程序都去创建和销毁线程;
线程池核心参数:
最大线程数,最小线程数,闲置时间,线程工厂,阻塞策略,拒绝策略

11、IO流

1、分类
字节流:包括InputStream输入流和OutputStream输出流,用来处理除文本文字相关的所有流;如果用字节流处理文本相关的东西会遇到乱码问题,因为不同的字符集转换成字节流对应的字节数是不一致的,GBK:中文2字节,英文和数字1字节;UTF-8:中文3~6字节,英文和数字1字节;如果要解决则需要用到转换流,设置字符集,将字节流进行包装;
字符流:包括Reader输入流和Writer输出流,只用于处理文本文字相关的东西;
2、字节流特点
字节流在读取的时候可以将字节数组存储到缓冲区,所以拷贝文件使用字节流;

12、设计模式了解及分类

设计模式就是将前人写代码的优秀经验总结下来应用到开发中,增强代码可读性,使代码更加优美高效;
分类:

  1. 创建型模式:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式五种;
  2. 结构性模式:适配器模式、代理模式、装饰器模式、外观模式、桥接模式、组合模式、享元模式七种;
  3. 行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式十一种;
    装饰器模式:通过对原类文件继承,对原有方法功能的基础上,增强新的功能
    适配器模式:不同的类需要配合完成功能
    简单工厂模式:将生产和消费分离(解耦),即创建对象和使用对象的功能分离,便于管理;但是扩展性弱,有新产品就要修改工厂方法

***Spring底层使用的就是简单工厂模式+Map缓存的单例+反射实现的

13、单例模式

一个类只能创建一个对象

1、饿汉模式
设计步骤:1)私有化构造方法
2)类中创建一个对象,并且用private、static、final进行修饰(private为了避免在外部直接访问当前对象;static是为了在静态方法中可以返回当前类中的对象;final:可加可不加,加了可以保证不可修改,且提高获取效率)
3)提供一个public获取实例的方法,以供外部使用对象

public class Singleton {
	 // 1. 私有化构造方
	private Singleton(){}
	
	/**
	 * 2. 在类中创建一个对象,并且用private、static、final修饰
	 *			private为了避免在外部直接访问当前对象
	 *			static是为了在静态方法中可以返回当前类中的对象
	 *			final:可加可不加,加了可以保证不可修改,且提供获取效率
	 */
	private static final Singleton instance = new Singleton();
	
	/**
	 * 3. 提供一个public修饰的静态方法getInstance给外部返回一个对象
	 * @return
	 */
	public static Singleton getInstance() {
		//返回创建好的对象的
		return instance;
	}
}

2、懒汉模式
需要使用时再创建对象
2.1 简单加锁

public class Singleton {
	private Singleton(){}
	private static Singleton INSTANCE= null;
	public static synchronized Singleton getInstance() {
		if (INSTANCE==null){
            INSTANCE = new Singleton();
        }
        return INSTANCE;
	}
}

2.2 双重判断加锁

public class Singleton {
	private Singleton(){}
	private static Singleton INSTANCE= null;
	public static Singleton getInstance() {
		if (INSTANCE==null){
            synchronized (Singleton.class){
                if (INSTANCE==null)
                 INSTANCE = new Singleton();
            }
        }
        return INSTANCE;
	}
}

3、枚举

public enum Singleton{
	INSTANCE;
}			

14、代理模式

客户端不直接调用实际对象,而是通过一个代理对象来间接调用;可以在代理对象调用之前和之后加入自己的逻辑;
分为静态代理和动态代理,常用动态代理,因为它可以根据代理的对象动态创建代理类;
Spring中AOP就是通过动态代理实现的:如果代理的类有接口,就使用JDK自带的动态代理模式,如果没有接口就使用CGLIB的动态代理模式;

15、四大元注解

1、@Target 用来限制被修饰注解的使用范围,即注解可以在类的哪些成员上使用;
2、@Retention 限制注解的作用时间;注解的生命周期和三个阶段有关:源文件有效SOURCE、源文件和字节码文件中有效CLASS、运行时(包括源文件和字节码)有效RUNTIME;
3、@Documented 文档注解,可以使用javadoc生成文档注释
4、@Inherited 从该类的子类上可以继承父类的注解

二、JAVA_Web部分

1、TCP和UDP

  1. TCP :Transmisson Control Protocol传输控制协议,需要连接后才能进行数据传输,安全,但效率低;点对点传输,首部开销20字节;
    传输前需要"三次握手"建立连接:1)客户端向服务器发送TCP报文,请求建立连接;2)服务器反馈一段报文表示正常接收到客户端数据并同意建立连接;3)客户端向服务器发送确认接收到第二段报文的信息;"三次握手"完成之后才能进行数据的传输;
  2. UDP :User Datagram Protocol用户数据报协议,不需要连接就能传输,不安全,但是效率高;支持一对一、一对多、多对一和多对多通信,首部开销8字节;

2、TCP协议与HTTP协议区别

TCP是传输层协议,用来传输数据,HTTP是应用层协议,用来包装数据

3、MVC分层思想

M:Model模型层,包括Service业务层和Dao层,Service业务层专门进行业务判断,满足条件后调用Dao层来操作数据库
V:View视图层,页面展示
C:Controller控制层,获取前端数据,调用对应的Service处理数据,完成业务
MVC流程图如下:
在这里插入图片描述

4、Java Web项目结构

—| 根目录:一般命名为webapps或webcontent,下面存放公开可直接访问的资源文件和一个名为WEB-INF的文件夹;
—| WEB-INF下有:
—| 1、lib文件夹,放项目要用到的jar包;
—| 2、classes文件夹,存放项目编译后的字节码文件;
—| 3、不能被直接访问的其他资源,例如html和jsp等;

5、Get请求与Post请求的区别

Get请求会将参数保存到地址栏,多个参数用&连接,大小上限为2KB,不安全;
Post请求会生成数据包在请求体中,没有大小限制且安全;表单提交必须用Post

6、Servlet生命周期

在第一次调用构造方法和init方法时自动创建对象(单例模式),然后一直存在,创建后再次调用service方法都不需要再次创建对象,且正常关闭服务器的时候,该对象依然能调用从HttpServlet继承的destroy方法,只是调用方法,并未销毁该对象

7、Servlet三大职责

1、匹配请求,获取请求中的参数;
2、调用service业务代码处理请求;
3、响应请求;

8、请求转发Forward和重定向Redirect的区别

重定向是两次或多次请求,地址栏会发生变化,不能共享一次请求中的数据,可以定向到外部应用;
转发是一次请求,所以地址栏不会发生变化,可以共享一次请求中的数据,不能定向到外部应用;

9、JSP和Servlet区别

JSP相当于一个Servlet,Servlet是用来编写后台代码,JSP主要用来展示数据,JSP运行的时候,Tomcat会自动将其转换为一个Servlet,将其中的数据以流的形式进行输出

10、JSP九大内置对象

输入输出对象: response; out;
四大作用域对象:pageContext(仅当前页面有效); request(也是输入对象,一次请求有效);session(一次会话有效,可包含多次请求); application(全局对象);
servlet对象:config; page;
异常对象:exception
注意:四大作用域对象使用同一API,都不能跨域取值,都有setAtrribute(“name”, “value”); getAtrribute(“name”); removeAtrribute(“name”, “value”)三个方法;

11、JSP动态包含与静态包含的区别

动态包含标签:<jsp:include page=“xxx”></jsp:include >,先编译后包含,会生成多个.java文件,每个包含文件都会有一个,包含动态页面jsp的时候使用;
静态包含:<%@ include file=“error.jsp” %>,先包含后编译,只有一个.java文件,包含静态页面html的时候使用;

12、session和cookie的区别

session和cookie都是会话跟踪技术,cookie是通过客户端记录的信息确认用户身份,而session是通过服务端记录的信息来确认用户身份,但是session的实现是依赖于cookie和sessionId,区别如下:

  1. cookie数据存放在浏览器,而session的数据存放在服务器上;
  2. cookie不安全,可以通过解析存放在本地的cookie进行cookie欺骗;
  3. 由于session数据保存在服务器上,会占用性能,故一般登录等重要信息使用session,购物车等其他信息使用cookie;
  4. 单个cookie保存的数据不能超过4K,且大部分浏览器都限制一个站点最多保存20个cookie;

13、事务四大特性

  1. 原子性:一个事务内部的所有操作是一个整体,不可分割;
  2. 一致性:一个事务既然是一个整体,内部所有操作要么都成功,要么都失败,失败就进行事务回滚;
  3. 隔离性:每个事务是独立的,不能受到其他事务的干扰;
  4. 持续性:事务开始就不能中途停止;

三、数据存储部分

1、Mybatis认识

Mybatis(iBatis)是一个ORM的数据库持久化框架,Mybatis的底层就是一个别人写好的JDBC代码,但是相对于JDBC,它有以下几大优势:

  1. 代替了JDBC的繁琐代码,消除了JDBC中需要手动设置参数和转换结果集的问题;
  2. 将sql语句放在了xml配置文件中,和代码分离,便于维护;
  3. 通过简单的API就可以操作数据库,提高开发效率;
  4. 还支持编写动态sql,代替编写逻辑代码;

2、ORM认识

ORM即Object Relational Mapping 对象关系映射,可以解决面向对象和面向关系之间的不匹配问题,使我们在查询数据库的的时候,数据库中的数据会自动转换成java对象,可以直接用面向对象的思维进行数据库操作;
ORM映射方式分为完整映射和半映射:
完整映射:不用写sql语句,例如JPA、Hibernate
半映射/sql映射:需要自己写sql语句,例如Mybatis,但是功能更齐全,灵活性高

3、Mybatis中#与$区别

#在sql映射执行的时候会自动转换成一个占位符,通过PreparedStatement执行,避免了sql注入问题;
$在映射执行的时候会进行拼接,是Statement方式执行,会有sql注入的问题,基本只在order by + limit的时候使用;

4、数据库类型

关系型数据库:Mysql、Oracle、SqlServer等
非关系型数据库:Redis、Memcached、MongoDB等

5、数据库的存储过程的优点

  1. 存储过程只在创建的时候编译一次,以后每次执行存储过程都不用再进行编译,而一般的SQL语句每执行一次就会编译一次,故使用数据库存储过程可以大大提高执行效率;
  2. 在执行复杂业务逻辑时,可能需要执行多条SQL语句,这些语句都要分别从客户端发送到服务器,产生大量网络传输,而如果将这些操作都放在一个存储过程中,就可以减少网络传输,降低网络负载;
  3. 存储过程可以重复使用,减少数据库开发人员工作量;
  4. 安全性高,屏蔽了对底层数据库对象的直接访问,只需通过EXCUTE调用存储过程,不需要有底层数据库的访问权限;

6、数据库连接池作用

1、在数据库连接池中有一定数量的连接对象,每次需要访问数据库就从中取一个,使用完毕后重新返回给连接池,不需要每次访问数据库都去创建和销毁连接对象,提高响应速度;
2、限制了同一时间连接数据库的数量,防止高并发导致系统缓慢或崩溃;

7、Redis认识

Redis是一种数据结构化存储方法的集合,数据以Key-Value形式保存在内存中,不遵循sql标准;理论上一个Redis中可以存放2^32个key,约2亿五千万个keys;
优势:
1、数据存储在内存中,存取速度快,并发能力强;
2、value支持多种数据类型,如:String、List、Set、Map等;(Memcached的value只支持String类型)
3、支持多种客户端语言;
4、还支持持久化和存储过期;(Memcached不支持持久化)
5、支持集群,解决高并发;

8、Redis淘汰策略

常用:
1、volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰;
2、volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰;
3、allkeys-lru:从所有数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰;
不建议:
4、volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰;
5、allkeys-random:从所有数据集(server.db[i].dict)中任意选择数据淘汰;
6、no-enviction(驱逐):禁止驱逐数据;

9、Redis持久化策略

Redis有两种级别的持久化方式:RDB和AOF,通过redis.conf进行配置
RDB:可以在指定的时间间隔内修改次数进行持久化,默认开启;例如# save 900 1;就是在900秒内至少有一次改变进行持久化;
AOF:记录服务器执行的所有操作命令,保存在AOF日志文件中,服务器启动时重新执行这些命令还原数据集,默认关闭;通过appendonly yes开启;
Redis为了考虑效率,保存数据在内存中,并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中,在加载时,把两个数据做一个并集;

10、Redis集群方案

集群原因:解决单点故障;实现高并发;处理海量数据;
方案思路:

  1. 主从同步,读写分离,主备切换:只能解决高并发,但处理不了海量数据,如Twemproxy;
  2. 哨兵模式:基于主从模式,每个哨兵会以固定频率监控集群中的Master,当主服务器宕机可以自动提升从为新的Master,解决了单点故障及高并发,没处理海量数据;
  3. Redis cluster:无中心结构,不需要中间代理层,互相监控,都是Master,每个节点r会有备用节点,总共16384个槽,会根据节点数量计算槽slot,每个节点对应一个范围;每个key计算出hash槽到对应节点,存取的时候如果是在当前节点的槽值范围就执行,如果不是则会自动重定向到相应的节点完成操作;且有容错机制,集群中所有Master如果有半数以上与某个节点通信超时就会认为其故障,会自动提升其备用节点升级为主节点;此方案解决了集群三大原因;如果集群中某个主节点故障且没有对应的备用节点,整个集群就不可用;

1、twemproxy,类似于集群,设置好其管理的多个Redis实例,通过twemproxy代理身份来接收请求,并且通过一致性Hash算法连接到具体的Redis;这种方式代理单端口压力大,且一致性Hash算法如果Redis节点数量改变,导致计算值改变,数据无法自动迁移到新的节点;
2、codis,目前使用最广泛,和twemproxy类似,但是支持节点改变后旧数据自动迁移到新节点;
3、Redis cluster3.0自带集群,使用的是Hash槽而不是一致性Hash算法,自身支持节点设置从节点;
4、业务层代码实现,多个无关联的Redis实例,通过在代码中对key进行Hash计算然后确定连接具体的redis实例进行操作;
集群支持的最大节点数:16384个;集群后数据库都默认在下标为0的数据库中,且目前无法选择使用哪个数据库;

11、分布式Redis是前期做还是后期规模上来了再做好

Redis非常轻量,单个实例只使用1M内存,为了便于以后扩容,最好是在一开始就使用分布式;虽然前期分布式操作起来相对麻烦一点,但是长远看来,一旦数据量增加到一定程度需要更多Redis服务器时优势就体现出来了,这是只需要将一半Redis实例迁移到另一台服务器就可以,而不需要考虑重新分区的问题;

12. Redis缓存击穿和雪崩

  1. 击穿/穿透:单个key在缓存中查不到,需要去数据库查询,就是缓存穿透;并发不高问题不大,但是如果数据库数据量很大并发又高,大量的去数据库查询就是缓存击穿,容易造成数据库崩溃;
    解决:1)从数据库查询结果为空也进行缓存,避免每次都去DB查询;2)使用布隆过滤器(通过一种高效的数据结构和算法判断DB中是否存在key的数据),但是会增加复杂性和误判性;
  2. 雪崩:在同一时间,缓存中大量的key同时失效,又有大量的请求进来,所有流量全部达到DB中,导致DB不可用;解决方案:1)给key的过期时间添加一个随机值,避免同一时间大量失效;2)将热点数据设置永不过期;

13. Redis支持的Java客户端

包括:Redisson、Jedis、Lettuce,官方推荐Redisson;

  1. Jedis:API提供了全面的操作Redis命令;
  2. Redisson:实现分布式和可扩展的Java数据结构,相比于Jedis功能简单,不支持字符串操作,不支持事务、排序、管道、分区等Redis特性;

14. Mybatis一级缓存和二级缓存

  1. 一级缓存(本地缓存):默认开启,只针对同一个SqlSession有效,即使用同一个SqlSession对象调用同一个mapper方法,SQL语句执行一次后,Mybatis会将其放在缓存中,再次查询如果未申明需要刷新且缓存未过期,会直接获取缓存的数据而不会去数据库查询;
    生命周期:
    A、Mybatis开启数据库会话 => 创建SqlSession对象(此对象包含一个新的Executor对象,而Executor对象又持有新的PrepetualCache对象) => 会话结束 => 释放SqlSession及其内部的Executor和PrepetualCache对象;
    B、如果SqlSession调用close()方法,会释放一级缓存的PrepetualCache对象,缓存不可用;
    C、如果SqlSession调用clearCache()方法,会清空PrepetualCache对象的数据,但该对象仍然可用;
    D、SqlSession对象执行任何增删改的方法,都会清空PrepetualCache对象的数据,但该对象仍然可用;
    如何判断两次是完全相同的查询
    四个条件必须全相同:传入的statementId;结果集的范围;查询要传给JDBC的SQL语句;参数;

  2. 二级缓存(全局缓存):默认关闭,Application级别;开启要求实现二级缓存的POJO(简单Java对象)必须实现Serializable序列化接口,然后在xml映射文件中配置开启;

15. 关系型数据库优化原因及思路

优化原因:

  1. 提高高并发读写效率;
  2. 提高海量数据读写效率;
  3. 避免单点故障及支持动态扩展;
    优化思路:
  4. 定位慢sql:一般在开发者自验、测试、项目上线的一段时间开启定位慢查询记录到日志文件中;
  5. 分析慢sql:explain定位到的慢查询;
  6. 进行优化:单机优化、多机优化等;
    定位慢查询步骤:1) 关闭原来的mysql;2) 以支持慢sql记录的方式启动mysql;3) 设置慢查询时间阀值;4) 日志文件中查看慢sql(data.dir)

**针对数据库优化,优先选择垂直分库分表,还不能满足就进行集群、缓存等优化技术,水平分表分库是最后的选择;

16. 数据库单机优化 - 3范式NF

设计时首先满足1NF,然后满足2NF,最后满足3NF;
1NF:原子性,表中的列不可分割;
2NF:唯一性,表中信息不可重复,一般通过主键约束;
3NF:表中字段能通过其他表推导出来就不设计冗余字段,一般通过外键关联实现;
反3NF:在一些场合为提高查询效率,可以违反第3NF,在表中添加冗余字段;例如订单、订单明细;

17. 数据库单机优化 - 存储引擎&触发器

触发器:create trigger创建触发器,满足条件就能执行;

存储引擎:mysql中常见的有MyIsam、Innodb、memory;
MyIsam与Innodb的区别:
MyIsam:不支持事务,支持全文索引,查询添加速度快,不支持外键约束,锁机制是表锁;对事务要求不高使用;
Innodb:支持事务,不支持全文索引,查询添加速度慢,支持外键约束,锁机制是行锁;对事务要求高使用;

18. 数据库单机优化 - 索引

把全文查找变为索引查找,mysql存储引擎的支持的索引类型是B+Tree,通过索引算法减少查询次数而提高效率,但实际是以空间换时间;
Mysql索引分类:

  1. 普通索引:允许重复值,任何字段可以添加;
  2. 唯一索引:值不能重复的字段,可以为null(可以多个),例如邮箱、手机号等;
  3. 主键索引:把某个列设为主键,例如id;
  4. 全文索引:MyIsam可以用,但默认只支持英文,一般我们用ES、lucene;

创建索引会有B+Tree结构维护的文件,占用磁盘空间;对DML操作有影响,因为要维护索引;
设置索引的字段条件:1) 查询频繁的字段(where或order by后面的);2) 修改少;3) 唯一性高;

19. 数据库单机优化 - SQL优化

DDL批量插入:1) 变多次索引维护为一次索引维护;2) 变多次唯一校验为一次;3) 变多次事务提交为一次或固定多少数量提交;
DML批量插入:变多次事务提交为一次或固定多少数量提交;
DQL:order by通过索引排序;or两边字段都要能使用索引才能使用,都做索引判断;
SQL优化方式有很多,简单列举一个常用的:1) 避免全表扫描,使用索引;2) 在where中尽量避免用or连接条件;3) 能用between就不要用in;4) 尽量同varchar代替char;5) 不要用select *等······

22. 多机优化 - CAP理论

Consistency一致性:写操作后可以读取最新数据,主节点写入后会锁定节点,知道从节点同步完成,同步失败会返回错误信息,且一定不会返回旧数据,性能较低;
Avalability可用性:任何操作都可以响应结果,同步时不会锁定节点,未同步完毕返回旧数据;
Partition tolerance分区容忍性:添加多个节点,异步操作取代同步,避免网络故障及单点故障;

分布式系统CAP智能满足其中两种进行组合:
CA组合:单个Mysql服务器;
CP组合:满足一致性和分区容忍性,例如Redis、Zookeeper、Consol等;
AP组合:并发可能读写不同步(常用),如Mysql主从同步、Eureka;

21. 多机优化 - BASE理论

Basecalliy Available基本可用、Soft state软状态、Eventually consistent最终一致性;一般为保证分布式系统的可用性,我们会使用AP组合,牺牲了强一致性,所以扩展BASE理论:确保分布式系统出现故障允许损失部分功能而保证核心功能可用;允许系统存在中间状态(如支付中···);实现最终一致性,在经过一段时间后所有节点数据达到一致;

22. 多机优化 - 集群

在分布式系统中,要实现高可用及避免单点故障,我们通常对数据库进行集群,分为master和slave,主从同步+读写分离;
主从同步使用Mysql就能实现,读写分离需要使用其他组件,如Sharding-jdbc、MysqlProxy、Mycat,主负责写操作,从负责读操作;

23. 水平分表分库

要实现水平分表分库,需要使用到中间组件,一般选择Sharding-sphere中的Sharding-jdbc(只支持Java),以jar包形式依赖即可使用;id可使用雪花算法,引入了时间戳,永远不会重复且保持了升序;

四、Spring和SpringMVC

1、框架

框架是指为解决开放性问题而设计的具有一定约束性的支撑结构;

  1. 框架本身并不能完整到解决特定问题,但是可以帮助我们快速解决特定问题;
  2. 框架中为后续的扩展提供了很多的辅助性、支撑性的实用工具类;

2、Spring认识

Spring是一个轻量级开源的IOC和AOP容器框架;它可以用来帮我们管理对象(创建、保存、初始化和销毁),管理对象的前提是必须有无参构造;

3、Spring两大核心:IOC和AOP

IOC:Inversion Of Controll,控制反转,将对象的创建和依赖关系的维护的权力交给Spring,所有对象都是由Spring来帮助我们管理,不需要我们自己来控制,就是控制反转;其中最常用的就是DI (Dependency Injection)依赖注入;
AOP:Aspect Oreinted Programming,面向切面编程,将通用的逻辑抽取出来集中管理,提高代码复用,比如登录拦截,日志管理和事务管理等都可以通过AOP来做;

4、DI (Dependency Injection)依赖注入

DI (Dependency Injection)依赖注入:IOC是一种思想,在系统运行中动态的向某个对象提供它所需要的其他的对象,而DI就是来实现这种动态赋值思想的;可以通过xml或者注解两种注入方式实现;

  1. xml注入:又叫属性注入,字段类型和被注入的对象类型必须一致;必须有Setter方法;底层是通过反射和调用Setter方法复制的;
  2. 注解注入:将注解写在字段或者Setter方法上,写在字段上可以不要Setter方法;注解有@Autowired和@Resource两种;

5、SpringMVC认识

SpringMVC是一个优秀的web层或表现层框架,底层对Servlet进行了封装,可以用Mybatis取代原生的JDBC,且同样具有实现Servlet三大职责的能力:匹配请求并接收请求参数;调用业务层处理请求;响应处理结果;

6、SpringMVC执行流程

参考流程图:
SpringMVC执行流程图

五、SpringBoot

1、SpringBoot认识

Spring随着功能的增加变得越来越复杂,如果要启动一个新的Spring项目,我们就必须添加构建路径或者Maven依赖关系,配置应用程序服务器,添加Spring配置,从头做一系列的样板代码和配置;而Spring Boot就是基于Spring框架,使用Spring启动,解决了这些问题;
具有以下优点:

  1. 统一管理Maven依赖,避免大量引入导致版本冲突;
  2. 内置了Tomcat、Jetty等容器,不需要再独立运行容器;
  3. 使用Java Config配置,不再需要web.xml配置,简化配置,且可以自动配置;
  4. 提供应用监控的能力;
  5. SpringBoot应用中可以创建独立运行的项目;

2、SpringBoot核心配置文件

SpringBoot有两大核心配置文件:bootstrap和application;这两个都是SpringBoot的配置文件,bootstrap的加载顺序是在application之前;
application配置文件通常用于项目自动化配置;
而bootstrap一般在使用Spring Cloud Config配置中心统一管理application配置文件的时候,在bootstrap配置文件中添加链接到配置中心的属性来加载Spring Cloud Config中存放的配置文件;一些固定不能被覆盖的属性;加解密场景;

配置文件有两种格式:

  1. .properties文件:属性格式是spring.application.name = xxx;
  2. .yml文件:不支持@PropertySource注解导入配置,属性格式严格,例如:
spring:
	application:
		name: xxx

3、SpringBoot核心注解

SpringBoot核心注解是@SpringBootApplication,加载项目启动的主配置类上,它包含了以下三个注解及功能:

  1. @SpringBootConfiguration:组合了@Configuration,实现配置文件的功能;
  2. @EnableAutoConfiguration:打开自动配置的功能;
  3. @ComponentScan:Spring扫描组件的功能;

六、SpringCloud微服务治理框架

1、负载均衡

概念:应用在做了集群之后,需要有一个组件来统一将客户端的请求相对平均的分发到这些应用节点上,这种功能就是负载均衡,比如Nginx就是一个负载均衡器;
负载均衡算法:
1、轮询(round robin):将请求一个个一次分发给各个后台服务器,即所谓的雨露均沾,默认方式;
2、权重(weight):给每台服务器设置一个权重值,根据权重来分发请求,权重越大分配的比例越高;
3、IP_HASH:根据hash算法计算ip地址,同一个ip的请求会分配到同一台服务器;
4、url_hash :计算请求url的hash值来分配服务器;
5、Fair:根据每台服务器响应时间分发请求,响应速度越快分发的请求越多;

2、微服务认识

概念:
微服务架构类似于SOA架构,是一个分布式系统,一个项目会有多个服务,将这些服务拆分开,各自独立,一个服务只做自己的特有业务且有独立的数据库,各服务直接使用HTTP通信协同工作来实现整个系统的所有功能;
优点:
1、单个业务逻辑简单,便于维护;
2、各服务之间相互独立,无耦合,升级维护互不影响;
3、使用轻量级HTTP通信,不同服务可以使用不同的编程语言;
4、扩展能力强,业务量大的业务可以集群或拆分服务,提高系统负载能力;
5、开发效率高,敏捷开发;
缺点:
1、分布式事务,服务之间进行通信的机制增加了事务的复杂性;
2、服务器多,部署麻烦;技术架构复杂,技术成本高;
3、服务之间通信会对性能有一定损耗;

3、SpringCloud概念及常用组件

概念:SpringCloud是基于SpringBoot实现的微服务治理工具包,用来管理和协调微服务;
常用组件:

  1. Netflix Eureka
    Eureka是用来管理微服务通信地址清单,将微服务通过ip地址注册到统一的Eureka服务器,可以通过服务名来实现服务之间的调用;
  2. Netflix Zuul:服务网关
    微服务的网关,所有请求都要经过Zuul才能到达目标服务,还能处理一些公共的事情,例如用户鉴权;
  3. Netflix Ribbon\Feign:负载均衡
    Ribbon和Feign都是客户端的负载均衡器,分发请求和解决服务之间的通信问题;
  4. Netflix Hystrix:熔断器
    有些请求需要多个服务共同完成,一旦某个服务器出现故障会导致整个调用链上的微服务全部出现异常,Hystrix就是用来解决微服务故障的;
  5. Spring Cloud Config:分布式配置
    每个服务都有各自的配置文件,每次修改配置和重启服务实例很麻烦。通过config作为分布式配置管理中心来统一管理服务的配置文件;
  6. Spring Cloud Bus : 消息总线
    在微服务中给各个服务广播消息的组件,消息总线发起消息后,接入的微服务都可以接收并且消费消息;
  7. Spring Cloud sleuth :微服务链路追踪
    最终一个请求调用那些服务,请求时间和是否异常等;

4、微服务通信协议RPC和HTTP

RPC:Remote ProcedureCall,远程调用协议,自定义数据格式,基于TCP通信,Dubbo框架使用的RPC通信;
HTTP:基于TCP的网络传输协议,规定了数据格式,消息臃肿,SpringCloud使用的就是HTTP协议;

5、Dubbo了解

Dubbo是阿里巴巴提供的一个服务治理和调用的框架,现在是Apache的顶级项目,只是一个RPC框架,相比于SpringCloud缺少很多功能模块,例如网关、链路追踪等,使用时通常结合zookeeper作为注册中心;
与SpringCloud对比如下:
在这里插入图片描述

6、Eureka认识

微服务会有很多的服务,服务之间要进行网络通信,就需要通信地址,通过Eureka进行统一管理,拥有服务注册与发现的功能;
组成:EurekaServer服务端(注册中心);EurekaClient客户端;
EurekaServer是一个独立的服务,所有的EurekaClient需要将自己的通信地址注册到服务端(使用ip、端口等),在EurekaServer就会形成一个微服务的通信地址列表
服务发现: 注册到EurekaServer的客户端会定期(RegistryFetchIntervalSeconds:默认30s)从服务端拉取一份微服务通信地址列表缓存到本地,当需要调用其他服务时就会在本地缓存列表中通过服务名找到通信地址发起HTTP请求;
服务续约: 正常运行的Eureka客户端会定期(LeaseRenewalIntervalInSeconds:默认30s)向EurekaServer服务端发送一次“心跳”请求进行续约,证明自己正常,不要 将自己从通信地址列表中剔除;默认情况EurekaServer接收到的服务续约“心跳”失败比例在15分钟内低于85%就不会剔除服务;

***为避免单个EurekaServer服务器负担过大及解决单点故障问题,可以进行EurekaServer集群;

7、Eureka调优

  1. 保留下线服务数据处理:
    A) EurekaServer自我保护导致,开发阶段可以eureka.server.enable-self-preservation=false关闭自我保护,生成环境还是建议打开,避免网络波动导致误删;
    B) 客户端未正常下线导致,可以通过 eureka.server.eviction-interval-timer-in-ms=5000 来指定Eureka Server定时清除过期数据的频率(默认是60/s)
    C) 缓存问题,通过 eureka.server.use-read-only-response-cache=false关闭缓存
  2. 设置剔除服务时间,服务端每次收到客户端心跳续约请求后,默认等90S,如果没有下一次续约请求就会剔除服务,可以通过
    eureka.instance.lease-expiration-duration-in-seconds=90修改服务剔除时间;
  3. EurekaClient获取服务慢:客户端默认间隔30S向服务端获取一次服务注册列表,可以修改eureka.client.registry-fetch-interval-seconds=10更快发现服务;
  4. EurekaClient续约频率:客户端默认每30秒发送一次心跳请求进行服务续约,当3次续约失败就会剔除。可以通过
    eureka.instance.lease-renewal-interval-in-seconds=10s 来修改心跳续约时间。

8、负载均衡Ribbon&Feign

微服务中为了解决服务单点故障的问题,往往会对微服务进行集群,而集群之同一个服务就会有多个通信地址,此时就需要用到负载均衡器来帮助我们自动分发请求到服务器中;在微服务项目中可以用Ribbon或者Feign来完成负载均衡的工作;

  1. Ribbon:服务调用时,Ribbon会根据服务的多个通信地址根据负载均衡算法(默认轮询)分发请求;要开启负载均衡,就需要在RestTemplate的Bean方法上添加一个@LoadBalanced注解,赋予RestTemplate负载均衡的能力;对于Ribbon可以通过配置超时时间、重试以及饥饿加载进行调优;缺点:发送HTTP请求如果有参数需要在url地址后面一个一个拼接参数;
  2. Feign:基于Ribbon进行了封装,解决了Ribbon做负载均衡通过RestTemplate调用其他服务时需要在url中拼接参数的问题;Feign整合了Ribbon和SpringMVC的注解,这样使得Feign的客户端就很像Controller,它提供了HTTP请求的模板,我们只需要通过编写简单的接口并像Controller那样插入注解,就可以定义好HTTP请求的url、参数和格式等信息;使用只需要注入Feign接口调用方法即可,而且整合了Hystrix,可以实现服务熔断,通过Fallback或者FallbackFactory实现服务降级;
  3. Feign流程及原理:1)导入依赖,主配置类@EnableFeignClients开启Feign;2)Feign客户端接口中@EnableFeign(value=“服务名”,callback/callbackFactory),交给Spring管理,value指定服务名,后面定义降级方法(需要在配置文件中开启 Hystrix),降级工厂中可以打印异常信息;

9、Zuul概念

在微服务项目中,很多需要登录和权限才能访问,但不可能每个服务都去写一套登录认证授权的逻辑,代码重复量太大,故使用Zuul作为微服务的大门,所有请求都要经过Zuul,通过Zuul来将请求分发到其他微服务中,只需要在Zuul中做一次认证授权就行了;
Zuul是netflix开源的一个API Gateway服务器,本质上是一个web servlet(filter)引用;它是一个独立的服务,集成了Ribbon和Hystrix,实现负载均衡和服务熔断,同样Zuul也需要注册到EurekaServer中才能获取到正常运行的下游服务通信地址,发起调用;

10、Zuul工作原理

Zuul底层是通过各种的Filter来实现的,按照执行顺序依次为:"pre"前置,"routing"路由,"post"后置,"error"异常;一般自定义Filter都是前置过滤器;
正常执行流程:请求到前置过滤器(可能还有自定义的前置Filter),然后到路由过滤器,路由中去服务提供这执行业务,正常执行后再到后置过滤器,最终返回结果;
异常执行流程:

  1. 前置或路由过滤器中发生异常:直接进入erro过滤器,处理后再经后置响应结果;
  2. erro出现异常:也是进入post后返回结果;
  3. post出现异常:进入error后就返回,不会再次进入post
    在这里插入图片描述

七、SpringSecurity认证与授权

1. 什么是RBAC

RBAC:Role-Based Access Control,角色访问控制,将权限与角色进行关联,不同的角色对应多个不同的权限,再将角色赋予给用户,从而使用户拥有对应的权限,简化了系统中对用户权限的统一管理;
实质上就是Who、What、How的关系,即Who操作What,如何操作How;Who:权限的主体,用户;What:要操作的资源;How:权限;

2. 认证流程

传统的认证流程:
在这里插入图片描述使用SpringSecurity的认证流程:
在这里插入图片描述

3. SpringSecurity中的授权

  1. Web授权:在Security的配置类中通过HttpSecurity.authorizeRequests()对资源指定访问权限;常用的API如下:
    anyRequest(): 任何请求;
    antMatchers(“/path”) :匹配某个资源路径;
    authenticationed() : 保护URL需要登录访问;
    permitAll(): 指定url无需保护(放行)一般用户静态资源;
    hasAuthority(String authority): 某个资源需要用户拥有什么样的权限才能访问;
    hasAnyAuthority(String … authorities): 某个资源拥有指定权限中的一个就能访问;
    ----------在项目中有权限表,每个访问资源对应所需要的权限,可以全部查询直接添加到授权中;

  2. 方法授权:通过方法上注解来标记需要什么样的权限才能访问;使用时需要在Security配置类中@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled= true)开启方法授权的支持,通常在方法上使用注解@PreAuthorize(“hasAuthority(‘…’)”) 在进入方法之前进行权限验证;(@PostAuthorize是方法执行后验证,基本不会用)

4. OAuth2协议授权模式

OAuth协议是一个用户资源授权的安全开放简单的标准,使用该协议进行授权不会触及到第三方账号的用户名和密码等账号信息;
OAuth2授权模式:

  1. 授权码模式(authorization code):用户访问客户端 => 导向到认证服务器(携带重定向url) => 用户确认是否授权 => 如果确认授权,到重定向url,附上一个授权码code => 客户端通过授权码向认证服务器申请令牌token(携带前面的重定向url) => 认证服务器核对url和授权码,无误后发放令牌;
  2. 简化模式(implicit grant type):跳过授权码流程,请求过来直接向认证服务器申请令牌且不需要认证;
  3. 密码模式(Resource Owner Password Credentials Grant):用户向客户端提供用户名和密码,客户端通过这两个信息向“服务提供商”获取授权;
  4. 客户端模式(Client Credentials Grant):客户端以自己的名义向“服务提供商”进行认证,其实不存在授权问题;

八、全文检索Lucene&ElasticSearch

1. Lucene认识

Lucene是Apache的一个开源的全文检索引擎工具包,方便开发人员在系统中实现全文检索的功能;Lucene适用于小型项目,它仅仅是一个库,要想适用就必须集成到项目中;Lucene的两大核心是索引创建和索引搜索;
索引创建:将结构化或非结构化的数据信息提取,创建索引;(分词、规则排序、合并相同单词)
索引搜索:搜索时通过关键词进行检索,获取到对应的索引,最终是通过索引直接获取到数据取的结果;

2. ElasticSearch认识

Lucene作为目前性能最好、功能最全最先进的搜索引擎库,但由于它只是一个库,要使用就必须用Java作为开发语言并集成到项目中,而且配置复杂,就诞生了在Lucene基础上的ElasticSearch;
ElasticSearch解决了原生Lucene的不足并优化调用方式的同时,还实现了高可用的分布式集群的搜索方案;
ES除了实现全文检索功能外,还具有以下特点:

  1. 分布式的实时文件存储,并且将每个字段都编入索引,使其可以被搜索;
  2. 分布式的实时分析搜索引擎;
  3. 可以扩展到上百台服务器,且可以处理PB级别的结构化或非结构化数据;
  4. 高度集成化服务,通过简单的Restful API进行使用,支持多语言;
    ---------------------------------------------------------------------------类似框架扩展---------------------------------------------------------------------------------------
    与ES类似的框架:
    Solr(重量级对手):最流行的企业级搜索引擎,利用Zookeeper进行分布式管理,支持更多格式数据的管理,官方很多传统搜索应用表修比ES好,但是Solr的实时搜索效率低;
    Kata:基于Lucene,支持分布式,可扩展,有容错功能,“开箱即用”,但只是搜索方案,需要自己创建索引;
    HadoopContrib:分布式创建索引,只是创建索引方案,不包括搜索实现,可以和Kata配合使用;

3. ES在并发情况如何保证读写一致

  1. 通过版本号使用乐观并发控制,确保新版本不会被旧版本覆盖,在应用层处理具体的冲突;
  2. 写操作,一致性级别支持quorum(默认)/one/all,只有当大多数分片可用的时候才支持写操作;但是可能因为网络问题导致写入副本失败,这样该副本会被认为是故障的,分片就会在一个不同的节点上重建;
  3. 读操作,可以设置replication为sync(默认),就可以使操作在主分片和副本分片都完成后才返回;也可以在搜索时设置请求参数_preference为primary来查询主分片,确保查询到的是最新版本;

4. 在Linux部署ElasticSearch如何优化

  1. 内存,64G最佳,32G和16G也可以;
  2. 核心处理器数量多更好;
  3. SSD固态硬盘,提升查询和索引的性能;
  4. 避免集群跨越多个数据中心,杜绝集群跨越远距离;
  5. 确保应用程序和服务器JVM完全一样;
  6. 通过设置gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟。
  7. ES默认使用单播发现,以防止节点无意中加入集群,只有在同一台机器上运行的节点才会加入集群;
  8. 不要随意修改垃圾回收器(CMS)和各线程池的大小;
  9. 内存分配一半或少于一半给Lucene,不能超过32GB;

5. ElasticSearch中DSL查询和DSL过滤常用标签

  1. DSL查询
    Query 查询上下文
  2. DSL过滤 Filter
标签作用
match匹配 要分词处理使用
term精确匹配 不分词
range范围查询
bool过滤,用于需要多个过滤条件组合查询,必须包含must、must_not、should中的一个或多个
must相当于and
should相当于or
must_not相当于not

6. ES索引创建

ElasticSearch -> 创建索引库Indices -> 类型Types -> 文档Documents -> 字段Fields;
ES集群中可以包含多个索引库(相当于数据库),而每个索引库 又可以包含多种类型(相当于数据库中的表),每个类型包含多个文档(相当于表中的一行),每个字段又可以包含多个字段(相当于表中的列);

7. ES索引数据过多如何调优

前期就要做好规划,设计先行,编码在后,主要可以从以下三个方面进行调优:

  1. 动态索引:基于模板+时间+rollover api滚动创建索引,通过时间戳每天递增数据,避免单个索引数据量过大;
  2. 存储分离:冷热数据分离存储,例如一周内访问高为热数据,其余为冷数据,冷数据不会写入新数据;
  3. 部署:ES自身支持动态扩展,动态新增机器,如果前期节点规划合理,不需要重启集群也能动态新增;

8.ES集群

Shard分片:单台机器无法存储海量数据,可以将一个索引中的数据切分成多个shard,分布在多台服务器进行存储;
Replica副本:每个服务器都可能故障,造成shard丢失,为每个Shard创建多个replica放在其他服务器备用;建立索引时默认5个primary shard分片(建立索引一次设置),每个分片一个replica(可以随时修改);
ES状态:green(全部shard和replica可用);yellow(主分片正常,至少缺失一个replica);red(至少一个shard及其replica缺失,有数据缺失);

9. ES节点Node类型

Master Node:主节点,只负责维护集群及索引库的操作;
Data Node:数据节点,只处理CRUD;
Client Node:只负责处理请求的匹配与分发;
默认每个节点都有成为主节点的资格,可以存数据和处理请求,需要设置node.master与node.data状态分门别类;

九、部署方面Linux&Docker&k8s

1. 为什么使用Linux部署项目

Linux是一套性能稳定的多用户网络操作系统,由于其具有开源免费、安全稳定、硬件配置要低、性能高的优点,当应用开发完成之后要部署到硬件服务器上,就选择Linux作为硬件服务器的操作系统;
Linux常见版本有:

  1. Rpm系列,做服务器:Redhat(收费,完善稳定强大安全)、Fedora(免费,适合个人使用)、Centos(免费,稳定安全,常用);
  2. Dpkg系列,做个人用户:Debian(很多公司用,基于Ubuntu)、Ubuntu(适合个人用户)等;

2. Linux系统常用操作命令

命令作用
systemctl stop firewalld.servicestop关闭防火墙(status是查看防火墙状态;start开启防火墙)
ifconfig查看本机ip地址
su - 用户名切换登录用户及环境,不加-只切换用户不切换环境
ls - l列表查看当前文件夹内容
cd /usr/local进入目录
cd …/返回上一级,多级可以加
cd ~返回根目录
mkdir 目录名创建文件夹
rm -rf 目录名递归删除文件或文件夹
mv 目录1 目录2目录2存在将目录1移动到2;目录2不存在则将目录1改名为目录2
touch 文件名创建一个文件
vim 文件名编辑文件文本,按i后开始编辑,编辑完后Esc,然后:wq保存并退出编辑
cat 文件名查看文件文本内容
tar -zxvf xxx.tar解压tar包
unzip xxx.zip解压zip包
ps -ef丨grep xxx查看xxx进程,例如Tomcat
kill -9 进程号杀进程
tail -f xxx.log查看实时日志

3. 使用Nginx部署前端项目

在前后端分离的项目中,前端项目也需要进行部署,但是如果npm dun build拷贝到Tomcat的部署的话,静态页面处理的效率低下,而Nginx作为一个专门的Http服务器,处理效率更高,同时拥有负载均衡的功能;
部署npm管理的vuecli项目,npm run build打包到Nginx进行部署;对于传统的css+div项目直接拷贝部署即可;

4. Docker简介

Docker是一个开源的应用容器引擎,开发者可以打包应用及依赖包到一个可移植的镜像中,然后发布到Linux或windows机器上,也可以实现虚拟化;Docker可以帮我们构建后部署容器,只需要把打包好的程序放进容器即可,而容器又是基于镜像启动的,容器启动后就可以登录到容器安装自己需要的软件和服务;

5. Docker常用命令

命令作用
systemctl start docker启动Docker(停止stop、重启restart)
docker images查看docker下的所有镜像
docker pull centos:7拉取centos:7镜像
docker rmi $IMAGE_ID删除指定镜像
docker ps查看正在运行的容器(后面加 -a查看所有容器)
docker run -it --name=mycentos centos:7 /bin/bash创建交互式容器,退出后容器就停止
docker run -di --name=mycentos2 centos:7创建守护式容器,退出后容器保持运行
docker exec -it container_name (或者 container_id) /bin/bash登录守护式容器
docker cp 需要拷贝的文件或目录 容器名称:容器目录将文件拷贝到docker容器中

6. Docker Compose容器编排

Docker Compos是Docker官方编排项目之一,用来快速部署分布式应用,避免了自己一个一个创建和启动容器;

7. K8s概述

Kubernetes,是一个管理云平台多个主机上的容器化的开源的应用,即跨主机容器化编排工具,主要功能:基于容器的应用部署、维护和滚动升级;自我修复;负载均衡和服务发现;跨机器和跨地区的集群调度等;
k8s架构是基于Cluster集群,由Master和Node组成;Master负责提供、管理、调度k8s的资源对象以及对其进行持久化;而Node负责pod对应的容器创建与启动等,与Master密切协作,与k8s Service通信等;

8. K8s中的Pod及其控制器

Pod:在k8s中的最小部署单元,可以包含一个或多个容器,每个Pod有独立IP,且可以指定一组共享存储卷volumes;
管理Pod的控制器:ReplicaSet(副本集)、StatefulSet(有状态副本集)等···;
ReplicaSet(副本集)一般不直接使用,通常用Deployment声明式控制器来管理;

9. K8s资源清单

k8s中所有内容都被抽象为资源,资源实例化之后为对象;
资源分类

  1. 名称空间级:仅当前命名空间有效;系统组件是默认放在kube-system空间下;如:1) 工作负载型资源:Pod、ReplicaSet、Deployment等;2) 服务发现及负载均衡性资源:Service、Ingress(暴露服务);3) 配置与存储型资源:Volume存储卷;4) 特殊型存储卷:ConfigMap(一般配置文件)、Secret(存敏感数据)等;
  2. 集群级:不管任何命名空间下都有效,例如:Namespace【名称空间】、Node【节点】、Role【角色】、ClusterRole、RoleBinding、ClusterRoleBinding;
  3. 元空间级:根据一些指标操作的,例如:HPA、PodTemplate【pod模板】、LimitRange【资源限制】;

10. K8s中服务发现及负载均衡Service

Service与Pod是通过Label串联起来,同一个Service下的所有Pod通过kube-proxy实现负载均衡,每个Service都会有全局唯一的虚拟IP;
现在的Service都使用的ipvs的代理模式,客户端请求到达内核空间时,会直接根据ipvs规则分发到各个Pod上,效率远远高于以往的iptables和userspace两种代理模式;

11. K8s服务暴露

通过Service将服务暴露到外部网络有以下四种方式:

  1. ClusterIP:默认。集群内可达,可用于微服务项目中服务与服务之间的调用;
  2. NodePort:构建在ClusterIP之上,局域网范围可访问;
  3. LoadBanlancer:构建在NodePort之上,使用运营商负载均衡器;
  4. ExternalName:将Service映射至由ExternalName指定的主机名来暴露服务,此主机名需要被DNS解析到CNAME类型的记录;

12. K8s中Ingress

Ingress是HTTP(S)负载均衡器,应用层调度,支持多种后端健康状态检查而Service是TCP负载均衡器,传输层调度,不支持健康检查;
Ingress是一组基于DNS域名或URL路径将请求转发到指定Service资源的规则,简单的可以理解为Service的Service,来统一管理集群内的所有服务;
可以使用Ingress来代替SpringCloud微服务中的Zuul网关;

13. K8s存储卷Volume

分类:

  1. 本地存储:节点级存储,如:emptyDir(不具备持久化,声明周期与Pod相同)、hostPath(使用的Pod被调度至其他节点则无法使用之前的数据);
  2. 网络存储系统:集群级存储,管理员配置PV存储系统,用户通过PVC申请使用;
  3. Secret:存储敏感信息;
  4. ConfigMap:用于像Pod注入非敏感数据;可以代替SpringCloud微服务中的Config配置中心;

十、 其他技术

1. RabbitMQ了解与使用场景

MQ(Message Queue)消息队列,是用erlang语言开发,基于AMQP协议实现的消息队列,主要有以下特点:

  1. 提高系统响应速度:任务异步处理,消费消息并不需要确保提供方的存在;
  2. 提高稳定性:支持持久化,即使系统挂了也能将消息保存下来;
  3. 服务解耦:消费者和生产者之间的解耦;
  4. 消除峰值:异步下单,队列机制FIFO,将并行变为串行;

2. RabbitMQ如何确保消息正确发送以及消息接收方消费了消息

  1. 发送方确认模式:将通道设置成confirm模式,所有消息就会有唯一ID,通道会发送确认给生产者,如果RabbitMQ发生内部错误就会发生送一条nack消息;
  2. 接收方确认:消费者每接收到一条消息进行确认后才能从消息队列中删除消息;

3. 如何确保消息不丢失

RabbitMQ中交换机和队列默认都是非持久化的,在服务器宕机或重启之后都不会存在,所以要确保消息不丢失,首先要通过交换机和队列的durable属性进行持久化,然后对消息也要进行持久化;(当然持久化的消息会被写入磁盘,比写入内存慢很多,要进行需求和性能之间的平衡考虑)

4. RabbitMQ组成及工作流程

Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue;
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑;
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方;
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ;
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息;

  1. 发送消息流程:生产者和Broker建立TCP连接 => 二者之间建立通道Channel => 生产者通过通道将消息交给Broker的交换机 => 交换机将消息转发到指定的队列;
  2. 接收消息流程:消费者和Broker建立TCP连接 => 二者之间建立通道Channel => 消费者监听指定的队列 => 当消息到达队列,Broker默认将消息推送给消费者 => 消费者接收到消息;

5. 订阅模式类型

  1. 广播模式Fanout:消息发送给所有绑定到交换机的队列;
  2. 定向模式Direct:消息发送给指定routing key的队列;
  3. 通配符模式Topic:把消息发送给符合routing pattern(路由模式)的队列;

6. 数据结构

数据结构是一种用来装数据及数据之间关系的一种集合;

  1. 逻辑结构
    指数据与数据之间的联系,分为:
  1. 集合:元素除同属一个集合外别无联系,如:List、Set;
  2. 线性关系:元素之间一对一,如数组、线性表、栈、队列、串;
  3. 树形结构:一对多,如二叉树(包括:平衡二叉树、二叉排序树、红黑树等)、多叉树(B+树、B-树··);
  4. 图形结构:多对多;
  1. 物理结构
    数据的逻辑结构在计算机空间中的存放形式就是物理结构;
    分为:
  1. 顺序型:逻辑相邻的节点存储在物理位置相邻的存储单元中,如数组,存储空间连续;
  2. 链接存储:如链表,存储空间不要求连续;
  3. 索引存储:通过索引号确定节点存储地址,类似Lucene;
  4. 散列存储(hash存储):将元素存储位置与关键字之间建立确定的对应关系;

7. 算法简单了解

算法是解决问题步骤的有限集合,通常用某一种计算机语言进行伪码描述;
算法复杂度分为时间复杂度(执行算法所需时间长短)和空间复杂度(所需要的存储空间大小);
通常理论上以时间复杂度判别算法优劣:时间频度,即一个算法中语句执行的次数,算法所需时间与之成正比;
常见算法:递归、排序(冒泡排序)、散列算法(hash算法)、查找(二分查找、hash查找···)等;

8. 红黑树

Red-Black Tree,是一种自平衡的二叉树,每个节点都有颜色(红或黑);
根节点及所有的叶子节点都是黑色;
如果一个节点是红色,则其子节点必然为黑色;
从根节点到每个叶子节点NIL所经过的黑色节点个数是一样的(接近平衡);
通过左旋、右旋及变色保证自平衡;

9. FastDFS分布式文件系统

FastDFS是一个开源的分布式文件系统,用来对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。我们在maven工程中使用是导入了fastdfs-client-java包,并在fdfs_client.conf文件中配置了tracker-server服务器,由于多个地方会使用到fastDfs,专门抽取了一个文件上传下载的工具类,需要使用的时候直接调用相应方法即可。需要注意的是由于可以集群,在配置时每个tracker要进行正确配置。

10. 线程池原理

核心线程、非核心线程、等待队列、拒绝策略

  1. 有空闲线程直接使用,没有空闲线程且数量未达到核心线程数,则新建一个核心线程执行任务;
  2. 线程数量达到核心线程数corePoolSize,任务先放入等待队列等待执行;
  3. 如果等待队列也满了,创建非核心线程处理;
  4. 队列满了且达到了线程总数(核心+非核心),执行拒绝策略;
  5. 非核心线程如果闲置会根据策略被销毁,核心线程不会销毁;
    拒绝策略:1) 抛弃新任务并抛异常;2) 抛弃新任务但不抛异常;3) 抛弃一个等待队列的最前面任务尝试执行新任务;4) 新开线程执行任务;

11. 线程池类型

  1. CachedThreadPool可缓存线程池:没有核心线程,来任务没空闲就创建,到闲置时间就清理,适宜短期执行任务场景;
  2. FixedThreadPool定长线程池:核心线程数与最大线程数相等,任务进来会先创建核心线程达到总数后才会开始进行线程复用,适用长期执行任务场景;
  3. SingleThreadExcecutor单线程:核心线程和最大线程数都为1;
  4. ScheduledThreadPool可调度线程池:核心线程数小于最大线程,即原理中的包括核心和非核心的,最常用;

理论上最大线程数:(N为CPU核数)CPU密集型:N+1;IO密集型:2N+1;

12. JVM优化原因及组成

为什么优化:根据硬件及场景,合理配置JVM的参数,使JVM运行程序效率最佳;保证在高并发情况下程序能平稳顺畅运行;
JVM组成

  1. 类加载器子系统;
  2. 运行时数据区:方法区、堆、虚拟机栈、本地方法栈、程序计数器;
  3. 执行引擎:即时编译器、垃圾收集(Garbage Collection);
  4. 本地库接口;
    在这里插入图片描述程序计数器:每个线程独享一块很小的空间,主要用来确定指令的执行顺序;
    Java虚拟机栈:执行的是Java方法,线程私有的,每个线程分配一个栈,每个方法会创建一个栈桢,局部变量存放在栈桢中;可能出现的相关错误:栈深度溢出、栈内存溢出;
    本地方法栈:执行的是本地引入的方法;
    堆内存:主要存放对象和数组,Java管理最大的一块内存,所有线程共享;GC垃圾回收的主要区域,也分为新生代和老生代,新生代又包括Eden、From Survivor和To Survivor;
    元空间:在JDK1.8中引入,取代了1.6、1.7中的方法区,使用本地内存,几乎避免了元空间内存溢出的问题;
    JIT编译器:将字节码文件编译成机器码;

13. JVM类加载器

分为4种:

  1. 启动类加载器:加载JAVA_HOME中/lib下的;
  2. 扩展类加载器:加载JAVA_HOME中/lib/ext下的;
  3. 应用程序类加载器:加载我们classpath下的程序和引入的jar包;
    4:自定义类加载器(不用);

14. 应用程序类加载器流程之双亲委派机制

双亲委派机制:
我们的程序是使用应用程序类加载器,但不会第一时间就使用它,而是先委托给它的父类扩展类加载器,再由父类委托给启动类加载器,所以是最优先使用启动类加载器加载,加载不到再由父类扩展类加载器加载,当父类也加载不到最终才会使用应用程序类加载器进行加载,如果都加载不到类就会报ClassNotFoundException;过程中一旦有一级加载到就不会继续加载;

为何使用双亲委派机制:1) 不让我们轻易覆盖系统功能;2) 使我们也能扩展功能;

15. JVM内存溢出

  1. 堆内存溢出
    错误信息Java Heap Space,堆存放对象和数组,一次加载过多数据、集合引用过多对象且使用后未清空或者代码中死循环产生过多对象等原因造成;
  2. 栈内存溢出
    StackOverflowError:栈深度是一定的,当某个线程请求超过虚拟机允许的深度时就会抛出此深度溢出异常,例如递归方法没有出口;可以加大栈深度;
    OutOfMemoryError(unable to create new native thread):当不断创建线程到无法发扩展栈时抛出内存溢出异常;可以减小栈深度以增加可容纳线程数;

16. GC垃圾回收流程

  1. 判断是否对象已死:
  2. 选择垃圾回收算法:
  3. 选择垃圾回收时间
  4. 选择适当的垃圾回收器清理垃圾;

17. GC中如何判断对象已死

  1. 引用计数算法:每个对象添加一个引用计数器,当计数器为0失去引用,对象已死;但是无法判断两个对象相互引用却已死的情况;
  2. 可达性分析算法:通过一个对象到垃圾回收起点GC Roots没有任何引用引用链到达时则对象已死,可做GC Roots的有虚拟机栈本地变量表中引用的对象、方法区静态属性引用的对象、方法区常量引用的对象、本地方法栈中JNI引用的对象;

18. GC常用垃圾回收算法

  1. 标记-清除算法:先标记再清除,效率不高,且会产生大量不连续的内存碎片;
  2. 复制算法:将内存一分为二,每次只使用其中一块,这块用完了就将存活对象复制到另一块,然后全部清理这一块,如此循环使用,但是可使用内存永远只有一半;
  3. 标记-整理算法:先将可用对象标记并移动到一块连续内存,然后清理可用区以外的内存;
  4. 分代收集算法:新生代对象都是死亡快,只有少量存活,采用复制算法,只需要复制少量存活对象就可完成GC;老年代对象都是存活率高,使用标记-清除或标记-整理进行回收;

19. 常见垃圾收集器

新生代收集器:ParNew、Serial(淘汰)Parallel Scavenge(JDK1.8使用)
老生代收集器:CMS、Serial Old(淘汰)Parallel Old(JDK1.8使用)
堆内存收集器:G1(JDK1.9默认使用)

20. JVM优化

调优工具:jVisualvm、jConsole;
主要就是调整JVM的内存及GC等相关参数到最适合当前硬件状态;

  1. 集成开发中:eclipse修改eclipse.ini文件,Idea修改idea64.exe.vmoptions文件JVM参数;
  2. Tomcat启动:在catalina.bat修改JVM参数;
  3. SpringBoot项目:Idea中启动类设置VM options;打包后启动时java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC newframe-1.0.0.jar;

21. 分布式锁

在同一时间,一个代码块同时只能由一个线程可以执行,要实现就需要在某个地方做标记让使线程同步;
单体项目中,属于单进程可以有多线程,只需要用synchronize或Lock就能实现同步;
分布式系统中,是多个进程,要实现某个方法在同一时间只能被某个进程的某一线程执行,就需要使用到分布式锁;
分布式锁需要满足的特点:1) 是可重入锁,避免死锁;2) 高可用的获取锁和释放锁;3) 最好是阻塞锁;4) 最好是公平锁;
常见的分布式锁:基于数据库;基于缓存;基于Zookeeper;数据库的基本不用,另外两种根据实际情况选择

22. 分布式锁 - 基于数据库mysql

Innodb行锁
S Lock共享锁:允许事务读取一行数据,Mysql查询默认使用,即同时可以多个来查询,要改成排他锁在SQL语句后加for update即可;
X Lock排他锁:删除或更新,即一次只能一个操作改行,要获取锁需要等占用的事务释放锁;

数据库分布式锁可以使用X锁,但是性能低下,查询都要上锁;也可以不上锁,使用乐观版本控制,每次提交时才检测数据是否冲突;还可以通过唯一性(主键或唯一索引),使多个请求同时提交到数据库只有一个可以操作成功;

23. 分布式锁 - 基于缓存Redis

使用Redis中的Redisson自己集成的分布式锁,只需要导包获取即可,RedissionUtils.getInstance().getRLock(redisson, “goods” + goodsId);
当然也可以通过redis命令及redis lua支持的原子性自己实现分布式;

24. 分布式锁 - 基于Zookeeper

Zookeeper会维护一个有层级的树状数据结构,树状结构的节点分为:持久无序节点、持久顺序节点、临时无序节点、临时有序节点;
要实现分布式锁,主要使用临时有序节点+watch来完成:多某一个方法实现分布式锁,创建一个该方法对应的持久节点,每个线程进来先判断是否有前面节点,没有就创建一个临时有序的节点并直接获取锁,如果有前面节点存在,同样创建一个临时有序的节点但同时监听最末的一个节点,持续获取锁资源,当监听节点执行完释放后就能拿到锁执行方法;

25. 分布式事务

本地事务:一个数据源,只操作一个数据库;
分布式事务:多个数据源,同时操作多个数据库;比如微服务系统中,一个服务中的某个事务需要调用其他服务的事务;
常用解决方案:2PC、TCC、可靠消息最终一致性、最大努力通知···

  1. 2PC:将事务分为准备阶段和提交阶段,常用Seata、XA等;是阻塞机制,只适用于执行周期短的场景;
    Seata:需要部署TC事务协调器来维护全局事务,由事务管理器TM向TC申请全局事务,再由事务分支控制RM来进行全局管辖,接收TC指令,进行提交或回滚;使用搭建好后加@GlobalTransactional即可;
  2. 可靠消息最终一致性:事务发起方在本地事务完成后,发送一条可靠消息给事务参与方(需要被调用的服务),参与方一定能接收到消息并处理事务成功,保证最终事务一致,使用中间件RocketMQ,事务原子性+ACK接收机制+方法幂等性校验防止消息重复;适用于执行周期长,实时性要求不高的场景,如转账、退货等;
  3. TCC:补偿性事务AP系统一种,弱一致性,事务开始时向事务协调器注册事务,然后业务调用所有服务的try接口,根据返回情况决定使用confirm或者cancel,难度大,对应用侵入性高;
  4. 最大努力通知:调用参与者,参与者执行成功后尽最大努力通知我,根据结构进行操作,但是不保证消息一定能通知到调用方,例如微信支付和支付宝支付接口就是最大努力通知;

十一、前端部分

1. CS&BS了解

  1. CS:Client+Server客户端与服务器架构,CS架构的软件需要单独安装客户端才能进行访问,需要维护升级,面向的使用人群是固定的,使用的服务器是专用的,相对稳定安全;
  2. BS:Browser+webServer浏览器与服务器架构,以浏览器代替客户端,通过浏览器就能进行访问,面向人群更加广泛,但是稳定性和安全性相对于CS较低;

2. HTML、css、js在网页开发中的定位

  1. HTML:Hyper Text Marked Language,超文本标记语言,定义网页的页面结构;
  2. css:Cascading Style Sheet,层叠样式表,给页面添加样式,渲染页面;常用选择器:1)元素选择器:元素名;2)class类选择器:.属性名;3)id选择器:#id;4)通用选择器:*;
  3. js:JavaScript,是一种解释性脚本语言,由浏览器解释执行,常用来做表单验证,事件监听,页面跳转,局部刷新(Ajax)等,动态交互;主要包括ECMAScript(核心)、BOM(浏览器对象模型)、DOM(文档对象模型);

3. js中的boolean类型

和Java中一样,只有true和false两种取值,但是在JS语法中,表示false的有6个值:0; NaN; undefined; 空字符串; false; null;

4. Ajax认识

Asynchronous Javascript And XML异步JS和XML,是网页开发中改善用户体验的异步刷新技术;
传统的浏览器与服务器交互是同步请求,即使只修改页面中一小部分的数据,也要销毁整个页面,浪费网络传输;
而使用Ajax交互是异步请求,不刷新页面,只提交和更新局部数据,在发送请求的同时还可以继续操作页面,互不干扰,节约网络资源,减少不必要的数据传输;

5. jQuery框架

jQuery是一个开源的js框架,封装了js的属性和代码,优化了使用;它的核心特点是:支持链式编程;功能强大,支持更多类型的选择器;兼容各种主流浏览器;
常用的选择器:
id选择器:#id;
类选择器:.class属性;
层级选择器:儿子选择器 > 获取下面的子元素; 后代选择器 空格 获取下面后代;
标签选择器:标签名;
属性选择器:[attribute] 或[attribute=value] ;

6. window.onload与$(function(){})区别

window.onload是指页面加载完毕,包括所有的图片、视频等资源都加载完毕后才会执行;
$(function(){})是 $(document).ready(function(){})方法的简写,在页面结构加载完毕后就就会执行,执行时间在window.onload之前;

7. html5和css3新功能

  1. html5:相比于html4,增加了一些标签,以及画板、声音、视频、web存储等功能;但是过于强调语义,选择标签比较困难;
  2. css3:提供了一些css2难实现的功能,如:盒子圆角边框、盒子和文字阴影、渐变移动缩放旋转等;但是需要根据不同的浏览器处理兼容性问题;

8. Bootstrap框架

Bootstrap是一个移动设备优先的前端框架,封装了很多现成的js和css,是web开发更加迅速简单,支持响应式布局;常用的有表单、表格、模态框、布局、栅格系统等;

9. Vue是什么

Vue是一套用于构建用户界面的渐进式框架,可以自底向上逐层应用,只关注视图层;
主要有以下特性:

  1. 轻量:体积小,不依赖其他基础;
  2. 数据绑定:交互多的界面数据双向绑定很简单;
  3. 指令:内置指令v-xxx,通过对应表达式变化就能修改DOM;
  4. 插件化:虽然不包含Router、Ajax、表单验证等功能,但需要使用时可以很简单的添加插件即可;
  5. 组件化:支持自定义标签;

10. Vue实例挂载及常用属性

每个Vue实例需要通过el进行挂载到标签,可以通过id或class进行挂载,使用模板及常用属性例如:

<div id="myApp">
	<h1>{{message}}</h1>
</div>
<script type="text/javascript">
  		//创建vue是需要给他传递一个对象
        new Vue({
            el:"#myApp", //id在hmtl模板中要对应
            data:{ 
            	//数据模型
            },
            methods:{
                //挂载标签中的方法;无缓存,需要事件才能调用;
            },
      		watch:{
      			//监听Vue数据变化,从而做出反应
      		},
      		computed:{
      			//专门用来做计算的属性,必须有返回结果,有缓存,数据未发生变化则不会调用
      		},
      		created(){
          		//钩子函数,在Vue实例构建后执行
      		},
      		mounted(){
      			//钩子函数,在Vue实例构建并挂载完成后执行
      		}
        })
    </script>

11. Vue组件component

组件就是一个完成特定功能的HTML标签;

  1. 全局组件:在所有Vue实例中有效,可以在任何被挂载的标签中使用;
<div id="app">
    <mycomponent1></mycomponent1>
</div>

<div id="app1">
    <mycomponent1></mycomponent1>
</div>
//定义第一个全局组件,挂载标签中都能使用
Vue.component("mycomponent1",{
	template : "<h1>这是第一个全局组件</h1>"
})
var app = new Vue({
	el: "#app",
	data: {
	}
});
var app1 = new Vue({
	el: "#app1",
	data: {
	}
});
  1. 局部组件:在自己的Vue实例中有效,只能在其挂载的标签中使用;
<div id="app">
    <mycomponent></mycomponent>
</div>
var app = new Vue({
    el: "#app", //只能在挂载的app标签中使用
    data: {},
    components : {
        "局部组件的名字1" : {组件的配置对象},
        "局部组件的名字2" : {组件的配置对象}
    }
  });

12. 路由Router

路由就是负责将进入浏览器的请求映射到特定组件中,指定由哪个组件来响应请求,简单来说就是url地址和对应资源之间的映射;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值