一到两年工作经验的看完这些面试轻松拿offer

Java基础面试题

1、面向对象的特征有哪些方面

面向对象的特征主要有以下几个方面:

  • 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

  • 封装:把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。

  • 继承:使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

    • 关于继承如下 3 点请记住:
      • 子类拥有父类非 private 的属性和方法。
      • 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
      • 子类可以用自己的方式实现父类的方法。(以后介绍)。
  • 多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

2、== 和 equals 的区别是什么
  • == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

  • equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

  • 情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

  • 情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

3、常用的集合有哪些?

Map接口和Collection接口是所有集合框架的父接口:

  • Collection接口的子接口包括:Set接口和List接口;

  • Map接口的实现类主要有:HashMap、ConcurrentHashMap、TreeMap、Hashtable以及Properties等;

  • Set接口的实现类主要有:HashSet、LinkedHashSet、TreeSet等;

  • List接口的实现类主要有:ArrayList、LinkedList、Stack、Vector等。

4、静态变量和成员变量的区别?
  • 所属不同: 静态变量属于类,所以也称为类变量;成员变量属于对象,所有也称为实例变量(对象变量);

  • 在内存中出现的时间不同: 静态变量只在类创建时加载一次,随着类的加载而加载随着类的消失而消失;成员变量随着对象(也叫实例)的创建而存在,随着对象的消失而消失;

  • 在内存中的位置不同: 静态变量存储于方法区里的静态区,成员变量属于对内存;

  • 调用方式不同: 静态变量可以通过类名调用,也可以通过对象调用;成员变量只能通过对象调用;

5、filter过滤器用过吗?一般用在什么地方?
  • 用过

  • 例如实现Servlet,Jsp或静态html等文件的拦截,从而实现一些特殊功能。

  • 例如实现URL级别的权限访问控制过滤敏感词汇、压缩响应信息等一些高级功能。

6、多线程一般用在什么地方?
  • 多线程的作用:充分利用CPU资源,提高CPU使用率,才用多线程的方式去同时完成几件事情而不相互干扰

  • 用在什么地方:大多情况下,用到多线程主要是需要处理大量的IO操作或处理需要耗费大量时间的操作等等。比如:读写文件等。

7、线程之间的可见性
  • 加入volatile可以实现线程之间的可见性

  • 加入了volatile关键字之后可以将值马上更新到变量中从而达到可见性

8、int和Integer的区别?
  • Integer是int的包装类,而int是Java的一种基本数据类型

  • Integer是类,必须实例化之后才能使用,而int变量不需要

  • Integer的默认值是null,而int的默认值是0

  • Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针只想此对象;而int是直接存储数据值

9、Jdk和Jre和JVM的区别
  • JDK

    • Jdk还包括了一些Jre之外的东西 ,就是这些东西帮我们编译Java代码的, 还有就是监控Jvm的一些工具
      Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等
  • JRE

    • Jre大部分都是 C 和 C++ 语言编写的,他是我们在编译java时所需要的基础的类库
      Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包
      如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
  • Jvm

    • 在倒数第二层 由他可以在(最后一层的)各种平台上运行
      Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。
10、Oracle JDK 和 OpenJDK 的对比
  • Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;

  • OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;

  • Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;

  • 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;

  • Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;

  • Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。

11、Java8的新特性
  • Lambda表达式

  • 函数式接口

  • 方法引用和构造器调用

  • Stream API

  • 接口中的默认方法和静态方法

  • 新时间日期API

12、http协议的三次握手
  • 三次握手:
    • 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据.
13、http协议的四次挥手
  • 四次挥手:
    • 第一次挥手:客户端A发送一个FIN.用来关闭客户A到服务器B的数据传送
    • 第二次挥手:服务器B收到这个FIN. 它发回一个ACK,确认序号为收到的序号+1。和SYN一样,一个FIN将占用一个序号
    • 第三次挥手:服务器B关闭与客户端A的连接,发送一个FIN给客户端A
    • 第四次挥手:客户端A发回ACK报文确认,并将确认序号设置为序号加1
14、http协议的三次握手为什么不是两次或者四次
  • 客户端要给服务器报告我要和你建立连接,顺便把我自己的一个发送能力发给服务器,让服务器知道
  • 服务器判断是否可以给你创建链接,把我的一个接受能力,
  • 只有三次握手才能保证双方的发送和接收能力达到我认为协商好的一个过程
  • 协议没有百分之百的安全,三次已经够了,即使是四次也不能保证协议百分之百可靠
15、http调用时候超时,超时怎么处理
  • 我使用的是捕获异常,重试,重试超过一定次数就报错,放弃重试,以防造成其他模块的阻塞
16、final 有什么用
  • 用于修饰类、属性和方法;
  • 被final修饰的类不可以被继承
  • 被final修饰的方法不可以被重写
  • 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的
17、&和&&的区别
  • &运算符有两种用法:(1)按位与;(2)逻辑与。
  • &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。
18、Java 有没有 goto
  • goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。
19、3.2E3F 里面的E/F分别表示什么?
  • E:科学计数法 3.2*10(3)
  • F:表示float类型
20、switch(参数) case的参数可以传哪些数据类型?
  • jdk1.0 char byte short int

    jdk5.0 enum(枚举)

    jdk7.0 String
21、do while 和while之间的区别?
  • do while 先执行 然后在判断 保证程序至少执行一次【先斩后奏】
  • while 先判断 符合条件在执行
22、list用过哪些?ArrayList如何排序?list和Set的区别?
  • 用过ArrayList、LinkedList、Vector
  • 排序:sort()

List和Set的区别:

  1. List,Set都是继承自Collection接口
  2. List特点:元素放入有顺序,元素可以重复。

    Set特点:元素放入无顺序,元素不可重复,重复元素会覆盖。
  3. Set和List对比:

    Set:检索元素效率低下,删除和插入效率高,删除和插入不会引起元素位置的改变。

    List:和数组类似,List可以动态增长,查找元素效率高,增删元素效率低,因为增删元素会引起其他元素位置的改变。
23、list集合去重(两种解决方案)
  • 把list变为set集合
  • 在jdk1.8中用到java8新特性stream流
  • list.stream().distinct(抵死听科特).collect(Collectors.toList());
24、异常包括什么 说一下什么是运行时异常、非运行时异常,举例说明
  • 异常是指程序运行过程当中出现的例外情况
    异常的体系结构:

    Throwable
    Error
    Exception
    RuntimeException

    异常包括:运行时异常和非运行时异常

  • 运行时异常(RuntimeException):指编译能通过,直到运行的时候才体现出来

  • 非运行时异常(Exception):指在编译的时候必须明确该如何处理,否则根本无法通过编译

  • Error:描述了Java运行时系统的内部错误或资源耗尽错误。大多数错误与代码编写无关,而表示代码运行时JVM出现的问题。应用程序不应该抛出这种类型的对象。
    常见的运行时异常(RuntimeException)有:

  • IndexOutOfBoundsException(下标越界异常)

  • NullPointerException(空指针异常)

  • NumberFormatException(String转换为指定的数字异常)

  • ArithmeticException(算术异常,如除数为0)

  • FileNotFoundException(文件未找到异常)

  • IOException(操作输入流和输出流时可能出现的异常,如磁盘损坏等)

25、jvm内存结构
  • 堆 程序计数器 方法区,虚拟机栈,本地方法栈
26、在jvm中锁住的是什么?
  • 锁住的是堆里这个字节码文件
27、线程的实现方式
  • 继承Thread类,重写run方法 (其实Thread类本身也实现了Runnable接口)
  • 实现Runnable接口, 重写run方法。(传入Thread类的构造方法中,由Thread的start启用线程)
  • 实现Callable接口,重写call方法(有抛出异常和有返回值)
    通过Callable和FutureTask创建线程,将Callable实现类传入FutureTask构造方法中,由FutureTask的start方法启用线程
  • 通过线程池创建线程
28、怎么处理异常
  • 抛还上级:throws
  • 自行处理:try catch finally
29、多态的实现机制

Java中实现多态的机制靠的是: 父类或接口定义的引用变量可以指向子类或具体的实现类的实例对象,而程序调的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

一句话:父类或接口引用指向具体的实例对象
多态的不同表现形式:方法的重写和重载就是Java多态的不同表现

  • 重写Overriding是父类与子类之间多态的一种表现
  • 重载OverLoding是一个类中多态的一种表现
30、Java简单运算面试题
short x = 1;
x = x + 1;//左边short = 右边int?
System.out.println(x);//报错

short y = 1;
y += 1;//y = (short)(y + 1); +=会自动转换
System.out.println(y);//2
31、StringBuffer和StringBuilder之间的区别?
  • StringBuffer和StringBuilder在创建对象的时候 都会多预留16块缓冲区
  1. StringBuffer 同一时间允许一个线程进行访问,效率较低,但是不会出现并发错误
  2. StringBuilder 同一时间允许多个线程进行访问,效率较高,但是可能会出现并发错误
32、为什么不把一个类所有的方法全部定义成静态的呢?
  • 静态方法里面只能直接的访问静态成员
  • 如果想要在静态方法里面访问非静态成员的话,需要先创建对象,拿着对象去调用
33、&和&&的区别
  • &和&&都可以作为逻辑运算符使用
  • &&有短路特性,当通过前面条件能够得知最终表达式结论的话,后面的条件会短路掉不做判断,所以效率更高
  • &没有短路特性,两边的条件都会进行判断。
    另外&还是按位运算符的按位与运算。当&左右两边连接的是整数类型的时候作为二进制按位与运算,也就是将两个数的二进制位都是1的结果写1。
34、final finally finalize区别
  • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
  • finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
  • finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
35、String和StringBuffer的区别

String和StringBuffer都是Java当中提供的字符串类型,其中String没有预留缓冲空间,而StringBuffer会在原先内容的基础上预留一部分的缓冲空间。

String: “a” + “b” 相当于创建了一个新对象,返回值是”ab"。

StringBuffer: sbuff.append(“b”)相当于还是在原先的对象上进行修改值。

36、访问修饰符 public,private,protected,以及不写(默认)时的区别
  • 定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  • 分类

    • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
    • default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
    • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
    • public : 对所有类可见。使用对象:类、接口、变量、方法
    37、请说出你所知道的线程同步的方法
  • synchronize修饰符
    修饰代码块

    修饰方法

  • java.util.concurrent.locks.ReentrantLock(并发包中的可重入锁)
    Lock lock = new ReentrantLock();

    其中lock.lock()用于上锁,lock.unLock()用于释放锁

    38、在Java中,如何跳出当前的多重循环
  1. break加循环标签,如:
    example_this:for(int x=0; x<10; x++) {
        if(...) {
            break example_this;//结束循环
        }
    }
    
  2. 使用return
  3. 使用System.exit(0);结束虚拟机
39、接口是否可以继承?抽象类时候可以实现接口?抽象类是否可以继承实体类?

接口可以继承接口,而且可以多继承,多个接口之间用,隔开;
抽象类可以实现接口,而且可以暂时不实现接口当中要求的抽象方法,因为抽象类中本身就可以有抽象方法留待子类具体实现;
抽象类可以继承实体类,如果继承的实体类没有默认的无参构造方法,需要写出抽象类的构造方法并在其构造方法的首行使用super()传参来明确指定调用父类的哪个构造方法。

40、抽象类是类 有构造方法 但是不能创建对象那么要构造方法的作用?
  • 给子类构造方法首行的super去调用的
41、怎么解决死锁?
  • wait(),notify(),notifyAll()
    使用 wait() 让当前线程(a)放弃锁标记进入等待池当中阻塞,从而成全另外的线程(b)能够成功获得它(b)需要的锁标记之后再调用 notify() 或者 notifyAll() 唤醒线程(a),让线程(a)从等待池进入锁池等待获得锁标记

[注意这三个方法都必须已经持有锁标记才能调用所以他们只能出现在synchronized代码块当中]

42、线程的生命周期

新生 就绪 运行 消亡 阻塞(等待池 锁池)

43、线程池
  • 可重用的线程池,方法的参数表示同一时间允许多少个线程并发执行,当线程执行完时,线程将被归还给线程池 Executors.newFixedThreadPool(2);
  • 带缓存机制的线城池,当线程执行完时,线程将被归还给线程池,如果一分钟之内没有其他线程被提交, 线程将会消亡 Executors.newCachedThreadPool();
  • 单一执行器:同一时间仅允许一条线程执行 Executors.newSingleThreadExcutor()
44、简述JDBC中Statement和PrepareStatement的区别
  • 两者同为接口 , PreparedStatement是Statement的子类
  • Statement 只能执行静态语句
    PreparedStatement存在一个强大缓存区,相同的sql语句执行相同语句结构仅仅编译一次,PreparedStatement仅对改动数据进行修改而不再进行编译,而Statement只要语句发生了改变,则必须重新进行编译
  • PreparedStatement支持对sql语句使用 ?占位符,杜绝了 sql注入安全隐患
  • 如果sql语句不需要多次执行,或者?过多,则效率可能较Statement低
45、简述 execute() executeUpdate() executeQuery() executeBatch()的使用场合,返回值?
返回类型使用场合
execute()boolean执行dql语句返回true,dml语句返回false
executeUpdate()int执行dml返回更改记录数,dql立刻报错
executeQuery()ResultSet执行dql语句返回结果集
executeBatch()int[]只能执行dml语句,返回更改的记录数的数组
46、Java当中如何实现数据共享
  • 使用静态变量完成数据共享
  • 使用参数传递完成数据共享
  • 使用内部类完成数据共享
47、为什么要使用内部类?
  • 内部类是Java当中 共享数据最最简单的方式之一
48、内部类都有哪几种?
  • 成员内部类、静态内部类、局部内部类、匿名内部类
49、如何自定义异常和如何主动制造异常出现的场景?
  • 自定义异常
    自己写一个类型继承Exception => 非运行时异常

    自己写一个类型继承RuntimeException => 运行时异常
  • 如何主动制造异常出现的场景
    throw new 异常的类型();
50、throw 和 throws 的区别?
  • throw 用在方法体当中
    在没有异常出现的情况下主动制造异常出现的场景
    [没事找事型]
  • throws 用在方法签名的最后
    表明本方法当中出现指定种类的异常 本方法不做处理
    抛还给调用的上级进行处理
    [有事甩锅型]
51、如何控制线程?
  1. setPriority(int) : 设置线程优先级别 可选范围 1-10 默认5
    优先级越高 代表抢到时间片的概率越高
  2. static sleep(long) : 让当前线程休眠指定的毫秒数
  3. static yield() : 让当前线程直接放弃时间片返回就绪
  4. join() : 当前线程邀请另一个线程优先执行
如何解决并发错误?
  • synchronized(临界资源){执行操作}
  • 可重入锁java.util.concurrent.locks.ReentrantLock
52、如何解决死锁?
  • 一块空间 : 等待池
  • 三个方法 :
    1. wait() : 让当前线程放弃已经持有的锁标记
      并且进入调用方法那个对象等待池当中
    2. notify() : 从调用方法的那个对象的等待池当中
      随机的唤醒一个线程
    3. notifyAll() : 从调用方法的那个对象的等待池当中
      唤醒所有线程

这三个方法不是线程类的 是Object类的

这三个方法必须在已经持有锁标记的前提下才能使用,否则不但失败 还会触发异常

53、锁池和等待池的区别
  1. 进入的时候是否需要释放锁标记
    • 锁池:不需要 所以可能会造成死锁
    • 等待池:需要 先释放锁标记才能进入等待池
  2. 离开的时候是否需要调用方法
    • 锁池:不需要 只要锁标记再度可用
    • 等待池:需要 必须要notify() 或 notifyAll()
  3. 离开之后去往何方:
    • 锁池:就绪
    • 等待池:锁池
54、流的分类
  • 按照方向分:输入流 输出流
    按照单位分:字节流 字符流
    按照功能分:节点流 处理流(过滤流、包装流)
55、接口和抽象类之间的区别?
  1. 分别表示的类型不同
    接口:interface

    抽象类:class
  2. 里面定义的属性修饰符不同
    接口:里面定义的属性默认都是静态的最终变量(public static final)

    抽象类:里面定义的属性默认是(default)
  3. 里面定义的方法不同
    接口:里面定义的方法默认都是抽象方法(public abstarct)

    从 jdk8.0开始 接口里面可以定义普通方法

    抽象类:里面既可以定义抽象方法 又可以定义普通方法
56、ArrayList和Vector之间的区别?
  • Vector:同一时间允许单个线程进行访问 效率较低,但是不会出现并发错误

    ArrayList:同一时间允许多个线程进行访问 效率较高,但是可能会出现并发错误
  • 从jdk5.0开始 集合的工具类里面提供一个方法(synchronizedList) 可以将线程不安全的ArrayList对象变成线程安全的集合对象,于是Vector渐渐被淘汰
57、ArrayList和LinkedList之间的区别?
  • ArrayList:底层基于数组实现的
    优点:随机访问 遍历查找效率高

    缺点:添加/删除元素
  • LinkedList:底层基于链表实现的
    优点:添加/删除元素效率高

    缺点:随机访问/遍历查找效率低
  • *:当正常开发的时候 尽量避免使用LinkedList里面的get(下标)方法
  • ArrayList 的查找性能绝对是一流的,无论查询的是哪个位置的元素。
  • ArrayList 除了尾部插入的性能较好外(位置越靠后性能越好),其他位置性能就不如人意了。
  • LinkedList 在头尾查找、插入性能都是很棒的,但是在中间位置进行操作的话,性能就差很远了,而且跟 ArrayList 完全不是一个量级的。
58、为什么Linkdlist查询慢
59、泛型中的通配符 T,E,K,V,?

本质上这些个都是通配符,没啥区别,换成 A-Z 之间的任何一个 字母都可以。

通常情况下,T,E,K,V,? 是这样约定的:

  • ? 表示不确定的 java 类型
  • T (type) 表示具体的一个java类型
  • K V (key value) 分别代表java键值中的Key Value
  • E (element) 代表Element

可参考:掘金

60、悲观锁与乐观锁?
  • 悲观锁: 在操作表时认为另外一个对表的操作会修改数据

    1.所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。

    2.java中synchronizedReentrantLock等独占锁就是悲观锁思想的实现。

    3.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
  • 乐观锁: 在操作表时认为别的操作不会对表有修改数据的操作

    1.所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制(原子类)和CAS算法实现。

    2.乐观锁适用于多读的应用类型,这样可以提高吞吐量。

产生死锁的条件:

1.互斥条件:进程对于分配的到的资源具有排它性,即一个资源只能被一个进程占用,直到释放
2.请求和保持
3.不剥夺条件
4.循环等待条件

解决方案:

避免死锁
加锁顺序
加锁时限
死锁检测
61、synchronized与Lock的区别
  • 首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
  • synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
  • synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
  • 用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
  • synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
  • Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
62、sychnize 什么情况情况是对象锁? 什么时候是全局锁为什么
  • synchronized 作用在普通方法上属于对象锁,作用在静态方法,类.class 上面,属于全局锁。对象锁只对同一个对象加锁,作用对象是同一个对象。而类锁是对类加锁,对整个类都有效。
  • 如果锁住的是一般方法就是对象锁,对象锁只会对同一个对象起作用,如果是锁住了static 方法则是全局锁,会对全局对象都管用,如果想在普通方法中使用全局锁需要锁住class对象。
63、什么是ThreadLocal,底层如何实现的?
  • ThreadLocal是一个解决线程并发问题的一个类,用于创建线程的本地变量,我们知道一个对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步的时候,我们可以选择ThreadLocal变量。
  • ThreadLocal是一个解决线程并发问题的一个类,用于创建线程的本地变量,我们知道一个对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步的时候,我们可以选择ThreadLocal变量。
64、Volatile的工作原理
  • 保证变量可见性
  • 禁止指令重排序
  • 保证Double、Long的原子性。
  • 线程修改完volatile变量后会将其存回主内存,其他线程如果想读取该变量必须重新从主内存中读取该变量。
65、CAS知道吗?如何实现的
  • CAS(Compare and Swap),即比较并替换,实现并发算法时常用到的一种技术。
  • CAS的思想很简单:三个参数,一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false。
  • CAS缺点
    • CAS存在一个很明显的问题,即ABA问题。
      • 问题:如果变量V初次读取的时候是A,并且在准备赋值的时候检查到它仍然是A,那能说明它的值没有被其他线程修改过了吗?
      • 如果在这段期间曾经被改成B,然后又改回A,那CAS操作就会误认为它从来没有被修改过。针对这种情况,java并发包中提供了一个带有标记的原子引用类AtomicStampedReference,它可以通过控制变量值的版本来保证CAS的正确性。
66、jvm内存模型
  • jvm内存主要分为五个部分:方法区,java堆,java栈,程序计数器,本地方法栈。
    • 方法区(永久代,线程共享):
    • 存储被虚拟机加载的类信息,常量,静态常量,静态方法,运行时常量池等。
      • (1)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
      • (2)Sun HotSpot虚拟机把方法区叫做永久代(Permanent Generation),方法区中最重要的部分是运行时常量池(运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时就会抛出OutOfMemoryError异常。)。
    • java堆(线程共享):
    • 存放所有new出来的东西。
      • (1)堆是java虚拟机所管理的内存区域中最大的一块,java堆是被所有线程共享的内存区域,在java虚拟机启动时创建,堆内存的唯一目的就是存放对象实例,几乎所有的对象实例都在堆内存分配空间。
      • (2)堆是GC管理的主要区域,从垃圾回收的角度看,由于现在的垃圾收集器都是采用的分代收集算法,因此java堆还可以初步细分为新生代和老年代。
      • (3)Java虚拟机规定,堆可以处于物理上不连续的内存空间中,只要逻辑上连续的即可。在实现上既可以是固定的,也可以是可动态扩展的。如果在堆内存没有完成实例分配,并且堆大小也无法扩展,就会抛出OutOfMemoryError异常。
    • java栈(线程私有方法级):
    • 为虚拟机执使用到的方法服务。每个方法被调用的时候都会创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。局部变量表存放的是:编译期可知的基本数据类型、对象引用类型。每个方法被调用直到执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
      • 在Java虚拟机规范中,对这个区域规定了两种异常情况:
      • (1) 如果线程请求的栈深度太深,超出了虚拟机所允许的深度,就会出现StackOverFlowError(比如无限递归。因为每一层栈帧都占用一定空间,而 Xss 规定了栈的最大空间,超出这个值就会报错)。
      • (2) 虚拟机栈可以动态扩展,如果扩展到无法申请足够的内存空间,会出现OOM。
    • 程序计数器(线程私有):
      • 保证线程切换后能恢复到原来的位置。在线程创建时创建,指向下一条指令的地址,执行本地方法时,其值为undefined。说的通俗一点,我们知道,Java是支持多线程的,程序先去执行A线程,执行到一半,然后就去执行B线程,然后又跑回来接着执行A线程,那程序是怎么记住A线程已经执行到哪里了呢?这就需要程序计数器了。因此,为了线程切换后能够恢复到正确的执行位置,每条线程都有一个独立的程序计数器,这块儿属于“线程私有”的内存。
    • 本地方法栈(线程私有):
    • 为虚拟机执使用到的Native方法服务。
      • (1)本地方法栈与java虚拟机栈作用非常类似,其区别是:java虚拟机栈是为虚拟机执行java方法服务的,而本地方法栈则为虚拟机执使用到的Native方法服务。
      • (2)Java虚拟机没有对本地方法栈的使用和数据结构做强制规定,Sun HotSpot虚拟机就把java虚拟机栈和本地方法栈合二为一。
      • (3)本地方法栈也会抛出StackOverFlowError和OutOfMemoryError。
67、重载和重写的区别,重载的方法能否根据返回类型进行区分
  • 方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
  • 重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
  • 重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
  • 重载对返回类型没有特殊的要求。
    • 方法重载的规则:
      • 1.方法名一致,参数列表中参数的顺序,类型,个数不同。
      • 2.重载与方法的返回值无关,存在于父类和子类,同类中。
      • 3.可以抛出不同的异常,可以有不同修饰符。
    • 方法重写的规则:
      • 1.参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一致。
      • 2.构造方法不能被重写,声明为final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次声明。
      • 3.访问权限不能比父类中被重写的方法的访问权限更低。
      • 4.重写的方法能够抛出任何非强制异常(UncheckedException,也叫非运行时异常),无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
68、什么是事务,有什么用
  • 事务的特性ACID
  • 事务提供了一种机制,可用来将一系列数据库更改归入一个逻辑操作。更改数据库后,所做的更改可以作为一个单元进行提交或取消。事务可确保遵循原子性、一致性、隔离性和持续性(ACID)这几种属性,以使数据能够正确地提交到数据库中。
    • 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作 要么都发生,要么都不发生。

    • 一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。

    • 隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时, 一个用户的 事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

    • 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

69、事务的并发会产生的问题有哪些
  • 脏读

    • 一个事务正在对数据进行更新操作,但是更新还未提交,另一个事务这时也来操作这组数据,并且读取了前一个事务还未提交的数据,而前一个事务如果操作失败进行了回滚,后一个事务读取的就是错误的数据,这样就造成了脏读
  • 不可重复读

    • 一个事务多次读取同一个数据,在该事务还未结束时,另一个事务也对该数据进行 了操作,而且在第一个事务两次读取之间,第二个事务对数据进行了更新,那么第一个 事务前后两个读取到的数据是不同的,这样就造成了不可重复读
  • 幻读

    • 第一个数据正在查询某一条数据,这时,另一个事务又插入了一条符合条件的数据,第一个事务在第二次查询符合同一条件的数据时,发现多了一条前一次查询时没有的数据,仿佛幻觉一样,这就是幻读
70、不可重复读和幻读的区别
  • 不可重复读是指在同一查询事务中多次进行,由于其他提交事务所做的修改和删除,每次返回不同的结果集,此时发生不可重复读
  • 幻读是指在同一查询事务中多次进行,由于其他提交的事务所做的插入操作,每次返回不同的结果集,此时发生幻读表面上看,区别就在于不可重复读能看见其他事务提交的修改和删除,而幻读能看见其他事务提交的插入
71、spring 事务隔离级别
  • default:(默认)
  • 默认隔离级别,使用数据库默认的事务隔离级别
  • read_uncommitted:(读未提交)
    • 这是事务最低的隔离级别,他允许另外一个事务可以看到这个事务未提交的数据,这种隔离级别会产生脏读,不可重复读和幻读
  • read_committed(读已提交)
    • 保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据.这种事务隔离级别可以避免脏读,但是可能会出现不可重复读和幻读
  • repeatable_read(可重复读)
    • 这种事务级别可以防止脏读,不可重复读.但是可能出现幻读.他除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读
  • Serializable 串行化
    • 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。防止了脏读、不可重复读、幻读
  • 总结:
脏读不可重复读幻读
读未提交
读已提交不会
可重复读不会
串行化不会
72、spring事务的传播行为
  • requierd
    • 如果有事务那么加入事务,没有的话新建一个
  • not_supported
    • 不开启事务
  • requires_new
    • 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完,继续执行老事务
  • mandatory
    • 必须在一个已有的事务中执行,否则抛出异常
  • never
    • 必须在一个没有的事务中执行,否则抛出异常
  • supports
    • 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务那就不用事务
  • PROPAGATION_NESTED
    • 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
73、Spring声明式事务的回滚机制
  • 在Spring 的事务框架中推荐的事务回滚方法是,在当前执行的事务上下文中抛出一个异常。如果异常未被处理,当抛出异常调用堆栈的时候,Spring 的事务框架代码将捕获任何未处理的异常,然后并决定是否将此事务标记为回滚。
  • 在默认配置中,Spring 的事务框架代码只会将出现runtime, unchecked 异常的事务标记为回滚;也就是说事务中抛出的异常时RuntimeException或者是其子类,这样事务才会回滚(默认情况下Error也会导致事务回滚)。在默认配置的情况下,所有的 checked 异常都不会引起事务回滚。如果有需要,可以通过rollback-for 和no-rollback-for进行指定。
74、分布式环境下如何处理事务

分布式事务处理是很难保证acid的。一般做法是牺牲一致性,满足可用性和分区容错。

  • 采用的方式可以是二阶段提交,由于二阶段提交存在着诸如同步阻塞、单点问题、数据不一致、宕机等缺陷,所以还可以采用TCC(补偿事务)的方式实现,
  • TCC核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段,本质也是2阶段提交,缺点也比较明显的,在确认和补偿时都有可能失败,一些业务流程可能用TCC不太好定义及处理。分布式事务还可以基于 mq(消息队列)/rpc(远程方法调用)实现最终一致性。
  • 还有Mycat可以通过用户会话Session中设置autocommit=false启动事务,通过设置ServerConnection中变量txInterrupted=true来控制是否事务异常需要回滚。
  • 在Mycat中的事务是一种二阶段提交事务方式,但是从实际应用场景出发这种出现故障的概率还是比较小的,因此这种实现方式可以满足很多应用需求,但如果出现问题,会很麻烦。
  • 但在分库分表,立即可见的应用上是不能满足业务需求的,所以分布式事务需要根据具体业务的需要权衡取舍的。
75、CAP 理论

在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)3 个要素最多只能同时满足两个,不可兼得。其中,分区容忍性又是不可或缺的。

HashMap

1、HashMap底层
  • 在1.7或者之前才用的是数组加链表 1.8后采用数组加链表加红黑树
  • 默认数组长度为16,当数组长度使用75%时进行扩容 扩容长度为2倍
  • 当阈值大于8时会自动转换红黑树在使用put添加元素时会进行hashcode方法计算hashcode值%16取余
  • 余数就是下标 如果在数组中有数据则去链表中添加
2、为什么不用二叉树
  • 因为二叉树当数据链大时会导致树干过高影响查询效率,所以采用1.8红黑树
3、为什么加入1.8红黑树
  • 时间复杂度
  • 加快查询效率
4、HashMap 是如何扩容的
  • HashMap 中有两个非常重要的变量,一个是 loadFactor ,一个是 threshold ,loadFactor 表示的就是负载因子,threshold 表示的是下一次要扩容的阈值,当 threshold = loadFactor * 数组长度时,数组长度扩大位原来的两倍,来重新调整 map 的大小,并将原来的对象放入新的 bucket 数组中。
5、HashMap 为什么线程不安全
  • HashMap 不是一个线程安全的容器,不安全性体现在多线程并发对 HashMap 进行 put 操作上。如果有两个线程 A 和 B ,首先 A 希望插入一个键值对到 HashMap 中,在决定好桶的位置进行 put 时,此时 A 的时间片正好用完了,轮到 B 运行,B 运行后执行和 A 一样的操作,只不过 B 成功把键值对插入进去了。如果 A 和 B 插入的位置(桶)是一样的,那么线程 A 继续执行后就会覆盖 B 的记录,造成了数据不一致问题。

  • 还有一点在于 HashMap 在扩容时,因 resize 方法会形成环,造成死循环,导致 CPU 飙高。

6、那个是线程安全的map
  • ConcurrentHashMap 是线程安全的 HashMap
7、那有什么方法解决线程安全
  • Hashtable
  • ConcurrentHashMap
  • Synchronized Map
8、HashMap和Hashtable之间的区别?
  1. 同步特性不同:
    • HashMap 同一时间允许多个线程进行访问 效率较高,但是可能会出现并发错误
    • Hashtable 同一时间允许一个线程进行访问 效率较低,但是不会出现并发错误
    • 从jdk5.0开始,集合的工具类里面提供一个方法(synchronizedList) 可以将线程不安全的HashMap对象变成线程安全的集合对象
  2. 对null的要求不同
    • HashMap无论主键还是值都可以存放null,但是由于主键唯一 所以主键只能添加一个null
    • Hashtable无论主键还是值都不能装null,一旦泛型里面装null 都会触发NullPointerException
  3. 底层分组不同:
    • HashMap底层数组大小默认为16,程序员可以随意的定义,但是最终一定是2的n次方数
    • Hashtable底层数组大小默认为11,程序员可以随意定义
  4. 出现的版本不同
    • Hashtable:since jdk1.0
    • HashMap:since jdk1.2
      :::
    9、HashMap HashTable和ConcurrentHashMap的区别
  • 最大的区别就是ConcurrentHashMap是底层采用分段的数组+链表实现所以线程安全的,hashMap不是线程安全的。
  • ConcurrentHashMap融合了hashtable和hashmap二者的优势。
  • 为什么线程安全呢:
    • ConcurrentHashMap代码中bai可以看出,它引入了一个“du分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
    • 在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中:
10、Synchronized容器和Concurrent容器有什么区别
  • 在Java语言中,多线程安全的容器主要分为两种:Synchronized和Concurrent,虽然它们都是线程安全的,但是它们在性能方面差距比较大。
  • Synchronized容器(同步容器)主要通过synchronized关键字来实现线程安全,在使用的时候会对所有的数据加锁。需要注意的是,由于同步容器将所有对容器状态的访问都串行化了,这样虽然保证了线程的安全性,但是这种方法的代价就是严重降低了并发性,当多个线程竞争容器时,吞吐量会严重降低。于是引入了Concurrent容器(并发容器),Concurrent容器采用了更加智能的方案,该方案不是对整个数据加锁,而是采取了更加细粒度的锁机制,因此,在大并发量的情况下,拥有更高的效率。
11、HashMap和TreeMap的区别
  • HashMap是通过hashcode()对其内容进行快速查找的;HashMap中的元素是没有顺序的;
  • TreeMap中所有的元素都是有某一固定顺序的,如果需要得到一个有序的结果,就应该使用TreeMap;
  • HashMap和TreeMap都不是线程安全的;
  • HashMap继承AbstractMap类;覆盖了hashcode() 和equals() 方法,以确保两个相等的映射返回相同的哈希值;
  • TreeMap继承SortedMap类;他保持键的有序顺序;
  • HashMap:基于hash表实现的;使用HashMap要求添加的键类明确定义了hashcode() 和equals() (可以重写该方法);为了优化HashMap的空间使用,可以调优初始容量和负载因子;
  • TreeMap:基于红黑树实现的;TreeMap就没有调优选项,因为红黑树总是处于平衡的状态;
  • HashMap:适用于Map插入,删除,定位元素;
  • TreeMap:适用于按自然顺序或自定义顺序遍历键(key);

MySQL

1、为什么要使用数据库
  • 数据保存在内存
    • 优点: 存取速度快
    • 缺点: 数据不能永久保存
  • 数据保存在文件
    • 优点: 数据永久保存
    • 缺点:
      • 1、速度比内存操作慢,频繁的IO操作。
      • 2、查询数据不方便
  • 数据保存在数据库
    • 数据永久保存
    • 使用SQL语句,查询方便效率高。
    • 管理数据方便
2、数据库经常使用的函数
  • count(*/column):返回行数
  • sum(column): 返回指定列中唯一值的和
  • max(column):返回指定列或表达式中的数值最大值
  • min(column):返回指定列或表达式中的数值最小值
  • avg(column):返回指定列或表达式中的数值平均值
  • date(Expression): 返回指定表达式代表的日期值
3、常用的存储引擎有
  • Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
  • MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键。
  • MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。
4、什么是索引
  • 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
  • 索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
  • 更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。索引是一个文件,它是要占据物理空间的。
5、索引有哪些优缺点
  • 索引的优点
    • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
    • 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
  • 索引的缺点
    • 时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
    • 空间方面:索引需要占物理空间。
6、怎么创建索引的,有什么好处,有哪些分类
  • 创建索引的语法:create index depe_unique_ide on depe(dept_no) tablespace idx_
  • 创建索引可以增加查询速度,唯一索引可以保证数据库列的一致性,可以确定表与表之间的连接
  • 索引的分类:
    • 逻辑分类:单列索引,复合索引,唯一索引,非唯一索引,函数索引
    • 物理分类:B数索引,反向键索引,位图索引
7、有哪些索引和作用
  • 唯一索引:不允许有俩行具有相同的值
  • 主键索引:为了保持数据库表与表之间的关系
  • 聚集索引:表中行的物理顺序与键值的逻辑(索引)顺序相同。
  • 非聚集索引:聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致
  • 复合索引:在创建索引时,并不是只能对一列进行创建索引,可以与主键一样,讲多个组合为索引
  • 全文索引: 全文索引为在字符串数据中进行复杂的词搜索提供有效支持
  • 覆盖索引: 覆盖索引可以减少回表次数,在MySQL5.6之后支持索引下推,把覆盖索引的一个字段进一步的进行筛选,减少回表次数
8、如果索引走不上因该考虑那些方面
  • 是不是本身SQL写的有问题,比如说对一些索引字段进行了函授操作
  • 进行链接查询时两表的字符编码不一样
  • 有没有可能是两表的字段类型不一样,比如一个表是String,另一个表是Interger
  • 是不是索引统计信息有问题,如果索引信息有问题可以去Analyze table重新统计所有信息
9、索引建的不好,导致索引速度慢
  • 使用force index,强制走一个索引,不推荐,建议作为一个应急预案,有可能迁移到别的数据库就不支持
  • 可以考虑用覆盖索引加最左原则,能不能把这个选错的索引删除
10、解决大批量数据更新
  • 可以把数据存在一个内存的临时表中,因为Innodb会维护一个buffer pool的,如果把大量的数据全部读取进去,可能会造成一个flush的操作,就是把脏页刷回MySQL,就是这么一个操作会造成我们线上的一个业务的阻塞
11、创建索引的三种方式
  • 第一种方式:在执行CREATE TABLE时创建索引
  • 第二种方式:使用ALTER TABLE命令去增加索引
  • 第三种方式:使用CREATE INDEX命令创建
12、如何删除索引
  • 根据索引名删除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名
  • 删除主键索引:alter table 表名 drop primary key(因为主键只有一个)。这里值得注意的是,如果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引)
    • 需要取消自增长再行删除
    • 但通常不会删除主键,因为设计主键一定与业务逻辑无关。
13、数据库建表3范式
  1. 关系型数据库

    表、字段、值 有相互关系
  2. 创建字段

    所有字段中必须有一个字段是唯一的
  3. 字段不能冗余
14、sql去重关键字
  • distinct 专业去重(支持多列)用于返回唯一不同的值select distinct salary,name from student;
  • group by 聚合统计
15、分页怎么实现的
  • Mysql分页使用limit:select 列名 from 表名 limit 10,10;
  • Oracle分页使用rownum:select a.* from (select rownum rw, 列名 from 表名 where 条件) a where a.rw>数字 and a.rw<=y;
16、sql语句优化
  • 合理使用索引
  • 用exists代替in,exists是直接判断存不存在,而in会挨个比较
  • 复杂的业务功能可以使用存储过程
  • 应尽量避免在 where 子句中使用!=<>orinnot in操作符,否则将引擎放弃使用索引而进行全表扫描
  • 能多表关联的尽量不写子查询
  • 避免%xxx式查询,前置%查询会导致查全表
  • 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
  • 应尽量避免在 where 子句中对字段进行 null 值判断,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默 认值。
  • 应尽量避免在 where 子句中使用!=或<>操作符, MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。
  • 应尽量避免在 where 子句中使用 or 来连接条件, 否则将导致引擎放弃使用索引而进行全表扫描, 可以 使用UNION合并查询
  • in 和 not in 也要慎用,否则会导致全表扫描,对于连续的数值,能用 between 就不要用 in
  • 如果在 where 子句中使用参数,也会导致全表扫描。
  • 应尽量避免在 where 子句中对字段进行表达式操作,应尽量避免在where子句中对字段进行函数操作
  • 索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,- 若太多则应考虑一些不常使用到的列上建的索引是否有必要。
  • 尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
  • 最好不要使用”“返回所有: select from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
  • 在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。
17、左外连接,右外连接,说一下?
  • 左外连接:from 原表 left join 新表 on 关联关系

    原表和新表能够关联的数据+无法通过关联关系关联到原表的数据

  • 右外连接:from 原表 right join 新表 on 关联关系

    原表和新表能够关联的数据+无法通过关联关系关联到新表的数据

18、sql语句中怎么判断一个字段是不是空

与空判断使用is null或者is not null

19、数据源、数据库连接池、DBCP三者的关系?
  1. 数据源:是连接数据库的一个标准
  2. 数据库:连接池是实现数据源的一种解决方案
  3. DBCP:是连接池的具体实现
20、jdbc怎样执行sql语句?
  1. 加载驱动
  2. 通过驱动管理对象获得连接
  3. 获得执行器对象编写SQL语句,JAVA中用String类型表示SQL
  4. 通过执行器执行SQL语句

    常用的执行SQL语句的方法有:
    execute() boolean (执行select语句时返回true,因为select能够返回一个查询结果 其他命令开头的语句返回false);
    executeUpdate() int;
    executeQuery() ResultSet
  5. 释放资源
21、索引用过吗?在什么情况下会导致索引失效?用索引还需要注意哪些问题呢?索引分为几种?
  • 用过;如果有索引的列空值比较多、重复数据比较多的话索引不起作用。
    通常索引用在查询较多而增删改较少的列,因为索引也会花时间自己维护会降低增删改的效率。

  • 常用的索引有普通索引、唯一性索引、位图索引,如果某个列上经常使用函数,还可以建一个函数索引。

22、like 用过吗?怎么用的?

like常用来实现模糊查询,与%和_匹配使用,如果需要匹配特殊字符,则需要使用escape逃离符。

例:搜索以“QA_”开头的数据:select code from 表 where code like 'QA/_%' escape '/'

23、union 和union all的区别
  • union取交集,union all取并集

例如:有{1,2,3}和{2,3,4}

union 能够去除重复数据 (做排序操作)(1,2,3,4)

union all 不会做去重操作 效率高 (1,2,2,3,3,4)

  • 多个查询语句必须有相同的列数

    多个查询语句中的列对应的数据类型必须一致

    如:select ename,job from emp01 union select ename,job from emp02;
24、事务的特性
  • 事务四大特性(简称ACID)
  1. 原子性(Atomicity): 事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
  2. 一致性(Consistency): 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  3. 隔离性(Isolation): 事务的执行不受其他事务的干扰。
  4. 持久性(Durability): 能够将提交的数据持久化到数据库中。
25、什么是事务?特征?JDBC如何控制事务?
  • 多条sql语句作为 一个执行单元,要么全部执行,要么全不执行

  • 四大特性:原子性,一致性,隔离性,持久性

  • JDBC控制事务:

    • 开始事务:connection.setAutoCommit(false);
    • 执行sql语句
    • 提交:connection.commit();
    • 回滚:Connection.rollback();
26、存储过程、视图、触发器
  • 存储过程 procedure: 在服务器端,能够被多个程序调用的一段SQL语句块。

    简单来说就是事先用数据库语言写好的一段功能,能够像函数一样被程序调用,但是存储过程本身没有返回值,是通过返回参数的形式返回数据。

  • 视图 View : 视图其实就是伪表,将编译后的SQL语句保存在数据库中,拿出只想让用户看见的字段,这就是视图。

    一般来讲视图不能创建索引(因为视图本身只是一个编译后的查询语句,索引只能创建在表的列上),但是Oracle提供了一种物化视图可以创建索引(物化视图:虽然叫视图但是实际类似于表,将数据暂时存储并在基表刷新或者提交数据时刷新本视图以便与基表数据保持一致)。

  • 触发器 trigger: 一种特殊的存储过程,不需要调用,在满足条件时触发。

    触发条件:在对某个表做insert 、 update 或delete操作之前或之后(取决于如何实现)自动执行

27、如果一个数组数据很多 如何求出最大值和最小值的差
  • array.max()求出最大值
  • min()求最小值
28、简述垃圾回收机制
  • 在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,
    在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,
    并将它们添加到要回收的集合中,进行回收。
29、MySQL存储引擎的选择
  • 在以读写为主的项目中使用MyiSAM
  • 在更新删除频率较高的使用InnoDB 高并发场景支持事务和外键
30、InnoDB四大特性
  • 插入缓冲(insert buffer)
  • 二次写(double write)
  • 自适应哈希索引(ahi)
  • 预读(read ahead)
31、如何调用存储过程?
  • JDBC中使用CallableStatement执行器对象,通过execute("{call 过程名(?,?)}")
    的方式来调用;
  • PL/SQL Developer工具中可以通过declare begin 过程名(参数); end;的方式调用;
32、备份数据
  • 第一种方式: 通过导入导出命令备份数据库中全部数据

    MySQL使用mysqldump命令备份数据
  • 第二种方式: 使用工具导出数据
33、in与exists的区别? 那个效率更高?

exists效率更高

  • in :需要通过条件比较结果中的所有数据
  • exists: 只关心子查询能够查询出数据
34、Hibernate中常见的主键增长策略?
  • Assigned:在调用save方法之前设置,自定义主键增长方式
  • Identity:建表语句必须支持auto_increment
  • Sequence:指定序列生成主键
  • Native:底层自动选择合适的策略
  • Increment:最大值+1的方式
  • Uuid:生成32为字符串
35、结构化查询语言都是什么?
  • DDL alter drop truncate create
  • DML insert delete update
  • DQL select
  • DCL grant revoke
  • TCL commit rollback savepoint
36、drop和truncate的区别?
  • drop:删除表结构和表数据(如果删除表空间的话需要+purge)
  • truncate:删除表数据和表空间,会保留表结构
37、组函数?多行函数?
  • sum()
  • avg()
  • count()
  • max()
  • min()
38、什么时候使用多表连接?什么时候使用子查询?
  • 如果需要查询的数据在多个表中,一定要使用多表连接
  • 不需要表A中的列,但是下需要表A中的条件,可以用子查询
  • 子查询中如果使用了in some any all这几个关键字,效率比较低,可以转换成多表关联
39、为什么要使用视图?
  • 节省编译时间,提高查询效率
  • 屏蔽原表中的字段,避免没有权限的用户查询到其他字段
  • 视图的数据能够动态的来源于原表
  • 简单的视图可以更新视图中的数据,复杂的视图无法更新
    create view 视图名 as select name from student;
40、为什么要给普通用户创建属于自己的表空间?
  • 项目中很有可能与其他项目使用同一个数据库,
    多个用户在使用用一个数据库时有可能访问同一个数据库文件,
    就会产生资源争用的问题。给不同的用户指定不同的表空间,
    就可以让他们使用不同的数据库文件,解决资源争用的问题
  • 给予用户部分权限
41、约束有哪几种?
  • 外键约束 foreign key references
  • 唯一约束 unique
  • 非空约束 not null
  • 主键约束 primary key
  • 检查约束 check
42、索引有哪几种?
  • 函数索引
  • 普通索引 normal
  • 唯一索引 unique
  • 位图索引 bitmap(适合在数据量比较大,基数比较小的列 如:男/女)
43、查询语句常见的关键字的优先级?
  • select 列名 优先级高于order by
  • from 表明 优先级最高
  • where 条件 优先级次高
  • group by条件 优先级次于where
  • having 条件 优先级一定在group by之后
  • order by分组 优先级最低
44、对MySQL的锁了解吗
  • 当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。

  • 就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用。

45、从锁的类别上分MySQL都有哪些锁呢

从锁的类别上来讲,有共享锁和排他锁。

  • 共享锁: 又叫做读锁。 当用户要进行数据的读取时,对数据加上共享锁。共享锁就是让多个线程同时获取一个锁。
  • 排他锁: 又叫做写锁。 当用户要进行数据的写入时,对数据加上排他锁。排它锁也称作独占锁,一个锁在某一时刻只能被一个线程占有,其它线程必须等待锁被释放之后才可能获取到锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。
45、数据库的乐观锁和悲观锁是什么,怎么实现的
  • 数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制
  • 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。
  • 两种锁的使用场景
    • 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
    • 但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
47、为什么mysql要选用B+树做索引的数据结构,而不用其他树?
  • 第一B树能减少树的层数,这就减少了磁盘IO查找的次数。
  • 第二B+树相比于B树,B+树所有data域数据都是存在叶子节点上的, 但是B-树的每个节点都有data域,这无疑增大了节点大小,也会增加了磁盘IO次数
  • mysql还对B+树做了一个优化,就是将所有叶子节点串起来,方便数据便利,毕竟遍历树拿到所有数据并不是那么方便

Spring

1、为什么使用Spring
  • 目的:解决企业应用开发的复杂性

  • 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

  • 范围:任何Java应用

  • 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

  • 1.轻量

    • 从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
  • 2.控制反转

    • Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它.
  • 3.面向切面

    • Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
  • 4.容器

    • Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
  • 框架

    • Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
  • 所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

2、Spring两大核心
  • IOC(控制翻转):
    • 控制翻转,也叫依赖注入,他就是不会直接创建对象,只是把对象声明出来,在代码 中不直接与对象和服务进行连接,但是在配置文件中描述了哪一项组件需要哪一项服 务,容器将他们组件起来。在一般的IOC场景中容器创建了所有的对象,并设置了必 要的属性将他们联系在一起,等到需要使用的时候才把他们声明出来,使用注解就跟 方便了,容器会自动根据注解把对象组合起来
  • AOP(面对切面编程)
    • 面对切面编程,这是一种编程模式,他允许程序员通过自定义的横切点进行模块 化,将那些影响多个类的行为封装到课重用的模块中。
      例子:比如日志输出,不使用AOP的话就需要把日志的输出语句放在所有类中,方法 中,但是有了AOP就可以把日志输出语句封装一个可重用模块,在以声明的方式将他 们放在类中,每次使用类就自动完成了日志输出。
3、spring有几种增强
  • 前置增强 before
  • 后置增强 after afterReturnning
  • 环绕增强 aroud
  • 异常增强 throws
4、spring 常用的注入方式有哪些?

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:

  • 构造方法注入
  • setter注入
  • 基于注解的注入
5、spring 事务实现方式有哪些?
  • 编程式事务管理对基于POJO的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
  • 基于 TransactionProxyFactoryBean 的声明式事务管理
  • 基于 @Transactional 的声明式事务管理
  • 基于 Aspectj AOP 配置事务
6、Spring的优缺点是什么
  • 优点:
    • 方便解耦,简化开发
      • Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护,交给Spring管理。
    • AOP编程的支持
      • Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
    • 声明式事务的支持
      • 只需要通过配置就可以完成对事务的管理,而无需手动编程。
    • 方便程序的测试
      • Spring对Junit4支持,可以通过注解方便的测试Spring程序。
    • 方便集成各种优秀框架
      • Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。
    • 降低JavaEE API的使用难度
      • Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
  • 缺点:
    • Spring明明一个很轻量级的框架,却给人感觉大而全
    • Spring依赖反射,反射影响性能
    • 使用门槛升高,入门Spring需要较长时间
7、Spring由哪些模块组成

Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。

  • 而这些组件被分别整合在核心容器:
  • Spring Core
    • 框架的最基础部分,提供 IoC 容器,对 bean 进行管理。
  • Spring Context
    • 基于 bean,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化、校验和调度等功能。
  • Spring DAO
    • 提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码,还提供了声明性事务管理方法。
  • Spring ORM
    • 提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate、MyBatis 等。
  • Spring AOP
    • 提供了符合AOP Alliance规范的面向方面的编程实现。
  • Spring Web
    • 提供了基础的 Web 开发的上下文信息,可与其他 web 进行集成。
  • Spring Web MVC
    • 提供了 Web 应用的 Model-View-Controller 全功能实现。
8、Spring 框架中都用到了哪些设计模式?
  • 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
  • 单例模式:Bean默认为单例模式。
  • 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
  • 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
  • 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
9、Spring 事务隔离级别
  • Required:支持当前事务,如果没有,还有Supports,如果没有事务就以非事务运行
  • Mandatory: 如果没有事务,就抛出异常
  • Not_Supported: 非事务运行,如果有事务则挂起
  • Never:非事务运行,如果有则抛出异常
  • Requires_New:支持一个内嵌事务的过程
10、spring 的事务隔离?
  • 未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
  • 已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生
  • 可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生.
  • 串行化的 (serializable) :避免以上所有读问题.
11、spring容器启动流程、配置
  • 配置spring.xml
  1. 初始化springIOC容器,加载spring.xml
  2. 扫描注解
  3. 配置spring加载数据源
  4. 配置spring整合mybatis
    • 注入数据源
    • 设置别名(包下所有类类名全部小写)
    • 加载 sql.xml映射文件
    • 加载 PageHelper等插件
  5. 配置扫描接口(sql.xml文件所在包)
    • 获得sqlSessionFactory(上一步的3以获得)
      sqlSessionFactoryBeanName
    • 实例化接口
      basePackage
  6. 配置事务管理器(只需注入数据源)
  7. 注解(在需要事务的方法上@Transactional)使用声明事务(底层我们用cglib动态代理)
    注意属性readOnly="true"为只读,在select时可以设置
12、spring Bean 声明周期
[spring Bean 声明周期](https://blog.csdn.net/admin9527_/article/details/78506135)
13、IOC控制反转到底反转了什么?
**创建对象的过程,形成对象与对象之间依赖关系的操作**<br/>
(Martin: 依赖对象的获得被反转了,本来应该是我们自己new, 现在是通过SpringIOC容器注入)
14、什么是AOP?
AOP即**面向切面编程**,关注的是`非核心业务的处理`<br/>
**用到的地方**:比如日志、网站的访问次数等<br/>
**主要目的**::核心业务和非核心业务之间的解耦<br/>
底层使用了**动态代理**模式<br/>
**要素**:advice(非核心业务的载体), pointcut(非核心业务的放置位置),
	advisor(建立advice和pointcut之间的联系)
15、反转之后的好处?
有助于类与类之间的**解耦**
16、IOC的好处?
  • 将对象的创建和属性的赋值完全转交给Spring,从而降低类与类之间的依赖关系,达到松散耦合的目的
17、ICO的核心?
  • IOC容器之所以叫IOC容器, 是因为其中的IOC指的是将主动new变成了被动注入
  • 从此角度出发, IOC的核心是DI依赖注入
18、DI是什么?
  • 依赖注入,指的是建立每个对象之间关系的方式,也就是对属性赋值的操作
19、Bean的属性都有?
***id***:(每个IOC容器对象的唯一标识),<br/>
***class***:(当前类对应的类型),<br/>
***scope***:(作用范围),<br/>
***lazy-init***:(是否 延迟加载),<br/>
***factory-method***:(指定返回返回该对象的方法名称),<br/>
***factory-bean***:(指定工厂实例),<br/>
***init-method***:(对象初始化调用的方法),<br/>
***destroy-method***
20、scope分别有几种情况?如何配置?
  • singleton,prototype,request,session,globalSession
  • 一般无状态的类的对象都配置成singleton,无状态的类一般指像Service和Dao层这样逻辑处理类
    有状态的类需要设置成prototype或request,一般指像Action一样存在多实例, 并且其中数据都不同
21、Spring创建对象的方式?
  • 构造方法创建(id+class);
  • 静态工厂创建(class+factory-method);
  • 实例工厂创建(factory-bean+factory-method)
22、完成注入的方式
  • setter注入 (Setter Injection)
  • 构造方法注入 (Constructor Injection)
  • 依赖注入分为接口注入(Interface Injection)
  • 其中接口注入由于在灵活性和易用性比较差,现在从Spring4开始已被废弃。
23、Schema是什么?优势?
  • 用来校验xml文件规范的xsd的文件
    • 基于xml语法
    • 扩充了数据类型
    • 支持命名空间
    • schema最重要的能力之一就是对数据类型的支持
24、复杂属性如何注入?
  • 数组/List/Set
    <property><array/list/set><value>value</value>
  • Map
    <map><entry key="" value=""/>
  • Properties
    <props><prop key="">vlaue</prop>
25、常用Spring注解?
  • @Component
  • @Repository
  • @Service
  • @Controller
  • @Autowired
  • @Qualifier
  • @Scope
  • @Value
  • @Aspect
  • @Pointcut
  • @Before
  • @After
  • @AfterReturning
  • @Around
  • @AfterThrowing
  • @Autowired
26、接收文件
  • @RequestParam(value=“file”) MultipartFile file
27、关于日期、时间
  • 映射类声明变量前,加入此注解:
    1. @DatetimeFormat是将String转换成Date,一般前台给后台传值时用(springmvc用)
    2. 将Date转换成String 一般后台传值给前台时设置响应方式为
      @JsonFormat(pattern=“yyyy-MM-dd”)
    3. @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”,timezone = “GMT+8”)
      只争对json响应式的处理(中国为东8区)
    4. @JsonIgnore json响应式忽略这个属性
      private Date hiredate;
28、使用注解完成IOC的流程
  • 添加context命名空间以及schemaLocation
  • 配置文件中添加上下文组件扫描<context:component-scan base-package=“com”/>
  • 给所有需要放入IOC容器中的组件添加注解@Component/@S…/@C…/@R…/@Scope
  • 给所有需要注入的属性添加注解@Autowired或@Resource
29、@Resource和@Autowired的区别
  • 来源不同

    @Autowired来自Spring类库中,@Resource是J2EE官方类库中的
  • 底层匹配机制不同

    @Autowired优先按照类型进行匹配,如果存在一个接口多个实现类, 再去按照属性名匹配,
    如果匹配不到,抛出异常NoUniqueBeanDefinitionException,
    此时,可通过 Qualifier(“对象名”) 指定注入对象

    @Resource优先按照属性名进行匹配,如果匹配不到,再去按照类型进行匹配,
    如果匹配到多个类型,抛出异常NoUniqueBeanDefinitionException
    此时,可通过 @Resource(name=“对象名”) 指定注入对象
30、反射涉及到哪些类?分别对应哪些方法
  • Class:太多, 比如getDeclaredConstructors(), c.newInstance()
  • Field: get(obj),set(obj,value)
  • Method: invoke(obj, a.class, b.class, …)
  • Constructor: newInstance(a.class, b.class …),setAccessible(true)
31、@RequestMapping注解用在类上面有什么作用
  • 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
32、怎么样把某个请求映射到特定的方法上面
  • 直接在方法上面加上注解@RequestMapping,并且在这个注解里面写上要拦截的路径。
33、如果在拦截请求中,我想拦截get方式提交的方法,怎么配置
  • 可以在@RequestMapping注解里面加上method=RequestMethod.GET
34、如果想在拦截的方法里面得到从前台传入的参数,怎么得到
  • 直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样
35、如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象
  • 直接在方法中声明这个对象,SpringMvc就自动会把属性赋值到这个对象里面。
36、怎么样把ModelMap里面的数据放入Session里面
  • 可以在类上面加上 @SessionAttributes 注解,里面包含的字符串就是要放入session里面的key。
37、当一个方法向AJAX返回特殊对象,譬如Object,List等,需要做什么处理
  • 要加上 @ResponseBody 注解。
38、IOC控制反转底层原理
  1. 自定义两个注解
    @Component:判断是否注入bean容器
    @Autowired:判断是否依赖注入
  2. 创建ApplicationContext容器类
    1. private ConcurrentHashMap<String, Object> beans = null; 存放bean的容器
    2. initBeans(); 根据注解@Component加载所有bean
      • 利用反射机制,遍历一个包下的所有类,判断类上有注解@Component就放入beans容器中,beans.put(beanId, newInstance);
    3. initEntryField(); 根据注解@Autowired加载所有依赖注入的对象
      • 所有bean初始化之后,判断bean的依赖注入关系
      • 遍历beans容器,利用反射机制,获取bean的所有属性并遍历判断有@Autowired注解的进行依赖注入(利用java反射set注入,private不用写set方法了)
39、spring 与springboot的区别
  • Spring 是一个“引擎”
    • Spring的全称是SpringFramework,它指的是一个框架,这个框架是模块化开发的其中有Spring Ioc、Spring AOP、Spring MVC等等的模块
  • Spring Boot 是基于 Spring4 的条件注册的一套快速开发整合包
    • Spring框架的开发团队Pivotal推出了一整套简化Spring框架的开发方式,称之为SpringBoot。所以说SpringBoot是用来简化Spring框架开发的。

Spring MVC

1、什么是Spring MVC?简单介绍下你对Spring MVC的理解
  • Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块,无需中间整合层来整合。 它和Struts2一样都属于表现层框架。在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。员之间的配合。
2、Springmvc的优点:
  • 它是基于组件技术的。全部的应用对象,无论控制器和视图,还是业务对象之类的都是 java组件,并且和Spring提供的其他基础结构紧密集成
  • 不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)
  • 可以任意使用各种视图技术,而不仅仅局限于JSP
  • 支持各种请求资源的映射策略
  • 它应是易于扩展的
3、Spring MVC的主要组件?
  • 前端控制器DispatcherServlet(不需要程序员开发)
    作用:接收请求、响应结果 相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
  • 处理器映射器HandlerMapping(不需要程序员开发)
    作用:根据请求的URL来查找Handler
  • 处理器适配器HandlerAdapter
    注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
  • 处理器Handler(需要程序员开发)
  • 视图解析器 ViewResolver(不需要程序员开发)
    作用:进行视图的解析 根据视图逻辑名解析成真正的视图(view)
  • 视图View(需要程序员开发jsp)
    View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
4、什么是DispatcherServlet
  • Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。
5、什么是Spring MVC框架的控制器
  • 控制器提供一个访问应用程序的行为,此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层,允许用户创建多种用途的控制器。
6、MVC是什么,MVC设计模式的好处有哪些
  • mvc是一种设计模式(设计模式就是日常开发中编写代码的一种好的方法和经验的总结)。模型(model)-视图(view)-控制器(controller),三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。
  • mvc设计模式的好处
    • 分层设计,实现了业务系统各个组件之间的解耦,有利于业务系统的可扩展性,可维护性。
    • 有利于系统的并行开发,提升开发效率。
7、Spring MVC常用的注解有哪些
  • @RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
  • @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
  • @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。
  • @Conntroller:控制器的注解,表示是表现层,不能用用别的注解代替
8、SpingMvc中的控制器的注解一般用哪个,有没有别的注解可以替代?
  • 一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外,一般不用别的注解代替。
9、Spring MVC与Struts2区别
  • 相同点
    • 都是基于mvc的表现层框架,都用于web项目的开发。
  • 不同点
    • 前端控制器不一样。Spring MVC的前端控制器是servlet:DispatcherServlet。struts2的前端控制器是filter:StrutsPreparedAndExcutorFilter。
    • 请求参数的接收方式不一样。Spring MVC是使用方法的形参接收请求的参数,基于方法的开发,线程安全,可以设计为单例或者多例的开发,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。struts2是通过类的成员变量接收请求的参数,是基于类的开发,线程不安全,只能设计为多例的开发。
    • Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,Spring MVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
    • 与spring整合不一样。Spring MVC是spring框架的一部分,不需要整合。在企业项目中,Spring MVC使用更多一些
10、Spring MVC的异常处理?
  • 可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。
11、springmvc提供的两种视图类型
  • ModelAndView
  • String
12、.springmvc和struts2的区别
  1. 入口

    struts2:web.xml filter元素,容器启动初始化

    mvc: web.xml servlet元素,第一次触发请求实例化对象
  2. 创建对象

    struts2: 基于类开发,发送请求时,每次都会创建对象,多例的

    mvc: 基于方法开发,一般设计为单例(默认)
  3. 接受请求参数

    struts2: 成员变量 依赖类存在

    mvc: 局部变量 依赖方法存在
    :::
    #### 13、springmvc组成部分
  • 自中央处理器 DispatcherServlet
  • 映射器 mvc:annotation-driven @RequestMappeing
  • 适配器 mvc:annotation-driven 执行方法
  • 处理器 @Controller
  • 视图解析器 InternalResourceViewResolver
  • 视图 我们看不见,底层动的
  • 异常处理器
  • 上传解析器
14、springmvc文件上传
有个类MultipartFile、方法transferTo
public String upload(@RequestParam(value="f") MultipartFile f,HttpSession session){
    //MultipartFile有transferTo()这么一个方法写出文件
    f.transferTo(new File(path,filenewname));
}
  • springmvc文件下载
    记得设置响应头信息
    response.setHeader("Content-Disposition","attachment;filename="+filename);
15、SpringMVC的流程?
  • 用户发送请求至前端控制器 DispatcherServlet
  • DispatcherServlet收到请求后,调用 HandlerMapping 处理器映射器,请求获取Handle;
  • 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
  • DispatcherServlet通过 HandlerAdapter 处理器适配器调用处理器;
  • 执行处理器(Handler,也叫后端控制器);
  • Handler执行完成返回ModelAndView
  • HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
  • DispatcherServlet将ModelAndView传给 ViewReslover 视图解析器进行解析;
  • ViewReslover解析后返回具体View;
  • DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
  • DispatcherServlet响应用户。
16、springMVC和struts2的区别有哪些?
  • 入口不同:springmvc的入口是一个servlet即前端控制器(DispatchServlet)
    struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。
  • 实现方式不同:springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例)
    struts2是基于类开发传递参数是通过类的属性,只能设计为多例
  • 参数解析不同:Struts采用值栈存储请求和响应的数据,通过OGNL存取数据
    springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将
  • ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
17、SpringMVC怎么样设定重定向和转发的?
  • 在返回值前面加"forward:“就可以让结果转发,譬如”forward:user.do?name=method4"
  • 在返回值前面加"redirect:“就可以让返回值重定向,譬如”redirect:http://www.baidu.com"
18、SpringMvc怎么和AJAX相互调用的?

通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :

  • 加入Jackson.jar
  • 在配置文件中配置json的映射
  • 在接受Ajax的方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。
19、SpringMvc里面拦截器是怎么写的

有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可:

<!-- 配置SpringMvc的拦截器 -->
<mvc:interceptors>
    <!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 -->
	<bean id="myInterceptor" class="com.abc.action.MyHandlerInterceptor"></bean>
    <!-- 只针对部分请求拦截 -->
	<mvc:interceptor>
    	<mvc:mapping path="/modelMap.do" />
		<bean class="com.abc.action.MyHandlerInterceptorAdapter" />
	</mvc:interceptor>
</mvc:interceptors>
20、Spring MVC的异常处理 ?

可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。

21、SpringMvc的核心入口类是什么,Struts1,Struts2的分别是什么:

SpringMvc的是DispatchServlet
Struts1的是ActionServlet
Struts2的是StrutsPrepareAndExecuteFilter

22、SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?

是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。

23、SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代?

一般用@Conntroller注解,表示是表现层,不能用用别的注解代替。

24、SpringMvc中函数的返回值是什么?

返回值可以有很多类型,有String, ModelAndView,但一般用String比较好。

25、SpringMvc用什么对象从后台向前台传递数据的?
  1. 使用Map、Model和ModelMap的方式
@RequestMapping("/test")
public String test(Map<String,Object> map,Model model,ModelMap modelMap,HttpServletRequest request){
    //1.放在map里  
    map.put("names", Arrays.asList("caoyc","zhh","cjx"));
    //2.放在model里 建议使用
    model.addAttribute("time", new Date());
    //3.放在request里  
    request.setAttribute("request", "requestValue");
    //4.放在modelMap中 
    modelMap.addAttribute("city", "ChengDu");
    modelMap.put("gender", "male");
    return "hello";
}

JSP写法:

time:${requestScope.time}
names:${requestScope.names }
city:${requestScope.city }
gender:${requestScope.gender }
request:${requestScope.request}
  1. 使用ModelAndView的方式:
@RequestMapping(value="/test2.do",method = RequestMethod.POST)  
public ModelAndView checknameIsExist2(@RequestParam("sid") String sid,Model model,HttpServletRequest request) {  
    ModelAndView mav = new ModelAndView();  
    mav.addObject("ModelAndView", "ModelAndViewValue");  
    //设置要跳转的页面,与返回值时String时返回success类似,以下跳转到/student/studentList.jsp  
    mav.setViewName("/student/studentList");  
    return mav;  
26、SpringMvc中有个类把视图和数据都合并的一起的,叫什么?

ModelAndView

27、读过springmvc源码?

Springmvc入口 请求 映射器 适配器

//前端控制器分派方法 
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 
    HttpServletRequest processedRequest = request; 
    HandlerExecutionChain mappedHandler = null; 
    int interceptorIndex = -1;
    try { 
      ModelAndView mv; 
      boolean errorView = false;  
      try { 
    //检查是否是请求是否是multipart(如文件上传),如果是将通过MultipartResolver解析 
        processedRequest = checkMultipart(request); 
     //步骤2、请求到处理器(页面控制器)的映射,通过HandlerMapping进行映射 
        mappedHandler = getHandler(processedRequest, false); 
        if (mappedHandler == null || mappedHandler.getHandler() == null) { 
          noHandlerFound(processedRequest, response);
          return; 
        } 
 //步骤3、处理器适配,即将我们的处理器包装成相应的适配器(从而支持多种类型的处理器) 
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 
        // 304 Not Modified缓存支持 
        //此处省略具体代码  
        // 执行处理器相关的拦截器的预处理(HandlerInterceptor.preHandle) 
        //此处省略具体代码  
        // 步骤4、由适配器执行处理器(调用处理器相应功能处理方法) 
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
        // Do we need view name translation? 
        if (mv != null && !mv.hasView()) { 
          mv.setViewName(getDefaultViewName(request)); 
        }  
        // 执行处理器相关的拦截器的后处理(HandlerInterceptor.postHandle) 
        //此处省略具体代码 
      } 
      catch (ModelAndViewDefiningException ex) { 
        logger.debug("ModelAndViewDefiningException encountered", ex); 
        mv = ex.getModelAndView(); 
      } 
      catch (Exception ex) { 
        Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 
        mv = processHandlerException(processedRequest, response, handler, ex); 
        errorView = (mv != null); 
      }  
//步骤5 步骤6、解析视图并进行视图的渲染 
//步骤5 由ViewResolver解析View(viewResolver.resolveViewName(viewName, locale)) 
步骤6 视图在渲染时会把Model传入(view.render(mv.getModelInternal(), request, response);if (mv != null && !mv.wasCleared()) { 
        render(mv, processedRequest, response); 
        if (errorView) { 
          WebUtils.clearErrorRequestAttributes(request); 
        } 
      } 
      else { 
        if (logger.isDebugEnabled()) { 
          logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + 
              "': assuming HandlerAdapter completed request handling"); 
        } 
      }
      // 执行处理器相关的拦截器的完成后处理(HandlerInterceptor.afterCompletion) 
      //此处省略具体代码  
    catch (Exception ex) { 
      // Trigger after-completion for thrown exception. 
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex)      throw ex; 
    } 
    catch (Error err) { 
      ServletException ex = new NestedServletException("Handler processing failed", err); 
      // Trigger after-completion for thrown exception. 
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); 
      throw ex; 
    }
    finally { 
      // Clean up any resources used by a multipart request. 
      if (processedRequest != request) {
        cleanupMultipart(processedRequest); 
      } 
    } 
  } 
28、Springmvc九大组件:

protected void initStrategies(ApplicationContext context) {
//用于处理上传请求。处理方法是将普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File.
initMultipartResolver(context);
//SpringMVC主要有两个地方用到了Locale:一是ViewResolver视图解析的时候;二是用到国际化资源或者主题的时候。
initLocaleResolver(context);
//用于解析主题。SpringMVC中一个主题对应一个properties文件,里面存放着跟当前主题相关的所有资源、
//如图片、css样式等。SpringMVC的主题也支持国际化,
initThemeResolver(context);
//用来查找Handler的。
initHandlerMappings(context);
//从名字上看,它就是一个适配器。Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。
//如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情
initHandlerAdapters(context);
//其它组件都是用来干活的。在干活的过程中难免会出现问题,出问题后怎么办呢?
//这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。
initHandlerExceptionResolvers(context);
//有的Handler处理完后并没有设置View也没有设置ViewName,这时就需要从request获取ViewName了,
//如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情了。
initRequestToViewNameTranslator(context);
//ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。
//View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。
initViewResolvers(context);
//用来管理FlashMap的,FlashMap主要用在redirect重定向中传递参数。
initFlashMapManager(context);

29、springmvc 提供2种 请求格式
  1. doaction
  2. 默认不加载静态资源 js css
  3. 默认不加载静态资源,要加载的话需要在spring配置文件中配置解析
    <!-- 静态servlet对象 针对/请求不加载静态资源 js css img  -->
    <mvc:default-servlet-handler />
    
    

MyBatis

1、MyBatis是什么?
  • Mybatis 是一个半自动 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高。
  • MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
2、Mybatis优缺点
  • 优点
    与传统的数据库访问技术相比,ORM有以下优点:
    • 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用
    • 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接
    • 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)
    • 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护
    • 能够与Spring很好的集成
  • 缺点
    • SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求
      SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
3、mybatis 和 hibernate 区别?
  • hibernate自动,mybatis半自动
  • 日志 hibernate自带
  • 移植性 hibernate:hql qbc面向对象,更换数据库,只更换方言即可
  • 优化 mybatis自己写sql灵活方便
  • 一级缓存

    hibernate底层是Hashtable 线程安全

    mybatis底层是HashMap 线程不安全
    -都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。
4、为什么说Mybatis是半自动ORM映射工具,它与全自动的区别在哪里
  • Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
  • 而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
5、JDBC编程有哪些不足之处,MyBatis是如何解决的
  • 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
    解决:在mybatis-config.xml中配置数据链接池,使用连接池管理数据库连接。
  • Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。-
    • 解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
  • 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    • 解决: Mybatis自动将java对象映射至sql语句。
  • 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
    • 解决:Mybatis自动将sql执行结果映射至java对象。
6、MyBatis的工作原理
  • 在学习 MyBatis 程序之前,需要了解一下 MyBatis 工作原理,以便于理解程序。MyBatis 的工作原理如下图
  • 读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
  • 加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
  • 构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
    创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
  • Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
  • MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
  • 输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
  • 输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
7、MyBatis和Hibernate的适用场景?
  • MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
  • 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

开发难易程度和学习成本

  • Hibernate 是重量级框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统
  • MyBatis 是轻量级框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务系统

总结

  • MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架,
  • Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。
8、MyBatis编程步骤是什么样的?
  • 创建SqlSessionFactory
  • 通过SqlSessionFactory创建SqlSession
  • 通过sqlsession执行数据库操作
  • 调用session.commit()提交事务
  • 调用session.close()关闭会话
9、MyBatis的工作原理
  • 读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
  • 加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
  • 构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
  • 创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
  • Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
  • MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
  • 输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 -preparedStatement 对象设置参数的过程。
  • 输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

Spring Boot

1、什么是 Spring Boot
  • Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,使开发者能快速上手。
2、为什么要用SpringBoot
  • 快速开发,快速整合,配置简化、内嵌服务容器
3、SpringBoot与SpringCloud 区别
  • SpringBoot是快速开发的Spring框架,SpringCloud是完整的微服务框架,SpringCloud依赖于SpringBoot。
4、Spring Boot 有哪些优点
  • Spring Boot 主要有如下优点:
    • 容易上手,提升开发效率,为 Spring 开发提供一个更快、更简单的开发框架。
    • 开箱即用,远离繁琐的配置。
    • 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
    • SpringBoot总结就是使编码变简单、配置变简单、部署变简单、监控变简单等等
5、SpringBoot的缺点
  • 我觉得是为难人,SpringBoot在目前我觉得没有什么缺点,非要找一个出来我觉得就是
    • 由于不用自己做的配置,报错时很难定位。
6、Spring Boot 核心注解
  • 启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
    • @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
    • @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,
    • @ComponentScan:Spring组件扫描。
      :::
7、SpringBoot Starter的工作原理
  • 我个人理解SpringBoot就是由各种Starter组合起来的,我们自己也可以开发Starter
  • 在sprinBoot启动时由@SpringBootApplication注解会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建spring容器中的bean,并且进行自动配置把bean注入SpringContext中 //(SpringContext是Spring的配置文件)
8、Spring Boot 有哪几种方式
  • 打包用命令或者放到容器中运行
  • 用 Maven/ Gradle 插件运行
  • 直接执行 main 方法运行
9、Spring boot 自动装配原理
  • 主要是Spring Boot的启动类注解springbootapplication主配置类,有了这个主配置类启动时就会为SpringBoot开启一个@EnableAutoConfiguration注解自动配置功能。
  • 在主类启动时就会为springBoot开启一个@EnableAutoConfiguration自动装配注解,有了这个EnableAutoConfiguration的话就会:
  • 从配置文件META_INF/Spring.factories加载可能用到的自动配置类去重
  • 并将exclude和excludeName属性携带的类排除过滤
  • 将满足条件(@Conditional)的自动配置类返回
10、Spring Boot 配置加载顺序
  • 在 Spring Boot 里面,可以使用以下几种方式来加载配置。
    • properties文件;
    • YAML文件;
    • 系统环境变量;
    • 命令行参数;
    • 等等……
11、Spring Boot 中如何解决跨域问题
  • 跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决方案并非 Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题
12、SpringBoot性能如何优化
  • 如果项目比较大,类比较多,不使用@SpringBootApplication,采用@Compoment指定扫包范围
  • 在项目启动时设置JVM初始内存和最大内存相同
  • 将springboot内置服务器由tomcat设置为undertow
13、您使用了哪些 starter maven 依赖项
  • 使用了下面的一些依赖项
    • spring-boot-starter-web 嵌入tomcat和web开发需要servlet与jsp支持
    • spring-boot-starter-data-jpa 数据库支持
    • spring-boot-starter-data-redis redis数据库支持
    • spring-boot-starter-data-solr solr支持
    • mybatis-spring-boot-starter 第三方的mybatis集成starter
14、Spring Boot 开发分布式微服务
  • 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
  • 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
  • 冗余-分布式系统中的冗余问题。
  • 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
  • 性能-问题 由于各种运营开销导致的性能问题。
15、使用 Spring Boot 开发分布式微服务时,我们面临什么问题
  • 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
  • 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
  • 冗余-分布式系统中的冗余问题。
  • 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
  • 性能-问题 由于各种运营开销导致的性能问题。

Spring Cloud

1、你用过springcloud,你知道它的实现原理吗

-我目前使用到的就是Eureka做注册中心,ribbon做负载均衡,feign做声明式服务调用(原先是使用restTemplate,太过混乱)Hystrix的熔断机制机制还没有使用,zuul做路由处理,比如一些token校验,客户端调用哪个服务都得经过该层。

2、什么是微服务架构
  • 微服务架构就是将单体的应用程序分成多个应用程序,这多个应用程序就成为微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言,不同数据库,以保证最低限度的集中式管理
3、什么是 spring cloud
  • spring cloud 是一系列框架的有序集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。
4、spring cloud 断路器的作用是什么
  • 在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。
5、Spring Cloud 核心组件
    • pring Cloud Eureka:服务注册与发现
    • Spring Cloud Zuul:服务网关
    • Spring Cloud Ribbon:客户端负载均衡
    • Spring Cloud Feign:声明性的Web服务客户端
    • Spring Cloud Hystrix:断路器
    • Spring Cloud Config:分布式统一配置管理
6、为什么需要使用Spring Cloud?
  • 首先springcloud基于spingboot的优雅简洁,可还记得我们被无数xml支配的恐惧?可还记得springmvc,mybatis错综复杂的配置,有了spingboot,这些东西都不需要了,spingboot好处不再赘诉,springcloud就基于SpringBoot把市场上优秀的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理
  • 什么叫做开箱即用?即使是当年的黄金搭档dubbo+zookeeper下载配置起来也是颇费心神的!而springcloud完成这些只需要一个jar的依赖就可以了!
  • springcloud大多数子模块都是直击痛点,像zuul解决的跨域,fegin解决的负载均衡,hystrix的熔断机制等等等等
7、Spring Cloud 是什么?
  • Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
  • Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
8、spring Cloud的优缺点
  • 优点:
    • 耦合度比较低。不会影响其他模块的开发。
    • 减轻团队的成本,可以并行开发,不用关注其他人怎么开发,先关注自己的开发。
    • 配置比较简单,基本用注解就能实现,不用使用过多的配置文件。
    • 微服务跨平台的,可以用任何一种语言开发。
    • 每个微服务可以有自己的独立的数据库也有用公共的数据库。
    • 直接写后端的代码,不用关注前端怎么开发,直接写自己的后端代码即可,然后暴露接口,通过组件进行服务通信。
  • 缺点:
    • 部署比较麻烦,给运维工程师带来一定的麻烦。
    • 针对数据的管理比麻烦,因为微服务可以每个微服务使用一个数据库。
    • 系统集成测试比较麻烦
    • 性能的监控比较麻烦。【最好开发一个大屏监控系统】
  • 总的来说优点大过于缺点,目前看来Spring Cloud是一套非常完善的分布式框架,目前很多企业开始用微服务、Spring Cloud的优势是显而易见的。
9、Spring Cloud与Spring Boot的区别
  • SpringBoot:SpringBoot专注于快速方便的开发单个个体微服务。
  • SpringCloud: SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,
    为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务
  • SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系
  • SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
10、Spring Cloud 和dubbo区别
  • 服务调用方式:dubbo是RPC springcloud Rest Api
  • 注册中心:dubbo 是zookeeper springcloud是eureka,也可以是zookeeper
  • 服务网关,dubbo本身没有实现,只能通过其他第三方技术整合,springcloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,springcloud支持断路器,与git完美集成配置文件支持版本控制,事物总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素。
11、Spring Cloud如何实现服务的注册
  • 服务发布时,指定对应的服务名,将服务注册到 注册中心(eureka zookeeper)
  • 注册中心加@EnableEurekaServer,服务用@EnableDiscoveryClient,然后用ribbon或feign进行服务直接的调用发现。
12、什么是 SpringCloudConfig
  • 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需 要分布式配置中心组件
  • 在 Spring Cloud 中,有分布式配置中心组件 spring cloud config , 它支持配置服务放在配置服务的内存中(即本地),也支持放在远程 Git 仓库中
  • 在 spring cloud config 组件中,分两个角色,一是 config server,二是 config client。

Redis

1、什么是Redis
  • Redis 是一个使用 C 语言写成的,开源的高性能key-value非关系缓存数据库。它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。Redis的数据都基于缓存的,所以很快,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。Redis也可以实现数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。
2、Redis有哪些优缺点
  • 优点

    • 读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
    • 支持数据持久化,支持AOF和RDB两种持久化方式。
    • 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
    • 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
    • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
  • 缺点

    • 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
    • Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
    • 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
    • Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
3、使用redis有哪些好处?
  • 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都很低
  • 支持丰富数据类型,支持string,list,set,sorted set,hash
  • 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
  • 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
4、为什么要用 Redis
  • 高性能:
    • 假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
  • 高并发:
    • 直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。
5、Redis里储存的数据和Mysql是一致的
  • 更新的时候,先删除缓存,然后再更新数据库。
  • 读的时候,先读缓存;如果没有的话,就读数据库,同时将数据放入缓存,并返回响应。
6、使用Redis带宽被打满怎么解决
  • 可以往其他的缓存方式去考虑一下
7、Redis为什么这么快
  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
  • 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  • 使用多路 I/O 复用模型,非阻塞 IO;
  • 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
8、Redis数据结构
  • String 字符串
  • hash 哈希
  • list 列表
  • set set集合
  • zset 有序集合
  • redis是否有事务,是否有事务回滚
    • 有事务 不支持回滚
9、redis什么时间使用
  • 用于并发量大的数据,并且不经常修改的数据
10、Redis主要消耗什么物理资源?
  • 内存。
11、Redis缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题
  • 缓存雪崩
    • 由于原有缓存失效,新缓存未到期间,所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
  • 解决办法:
    • 大多数系统设计者考虑用加锁,或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时是将缓存失效时间分散开。
  • 缓存穿透
    • 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
  • 解决办法:
    • 最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
    • 另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴
  • 缓存预热
    • 缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
  • 解决办法:
    • 直接写个缓存刷新页面,上线时手工操作下;
    • 数据量不大,可以在项目启动的时候自动进行加载;
    • 定时刷新缓存;
  • 缓存更新
    • 常见的策略有两种:
    • 定时去清理过期的缓存;
    • 当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。
      两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!
  • 缓存降级
    • 当访问量剧增、服务出现问题或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
      降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的
  • 解决办法:
    • 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
    • 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;
    • 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;
    • 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。
12、有没有尝试进行多机redis 的部署,如何保证数据一致的
  • 主从复制,读写分离
    • 一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。
13、Redis 常见性能问题和解决方案?
  • Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件
  • 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次
  • 为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内
  • 尽量避免在压力很大的主库上增加从库
  • 主从复制不要用图状结构,用单向链表结构更为稳定
14、Redis 持久化机制
  • Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
  • 实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
  • RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)
  • AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
  • 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
15、Redis使用场景
  • 计数器
    • 可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。
  • 缓存
    • 将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。
  • 会话缓存
    • 可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
  • 全页缓存(FPC)
    • 除基本的会话token之外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
  • 查找表
    • 例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。
  • 消息队列(发布/订阅功能)
    • List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。
  • 分布式锁实现
    • 在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。
  • 其它
    • Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有序性操作,从而实现排行榜等功能。
16、Redis如何做内存优化
  • 可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面

Ribbon

1. Ribbon自定义负载均衡策略
    1. 首先创建一个自定义负载均衡类 在负载均衡类内添加@Configuretion 因为他是一个配置类
    1. 配置类内添加一个方法 返回值是IRule 使用@Bean注解注入
    1. 创建负载均衡策略类 这个类需要继承 AbstractLoadBalancerRule(啊波斯踹可他 漏的白len斯 茹er)
      并且重写 choose 方法 方法内写我们的自定义负载均衡算法
    1. 在负载均衡类中把我们的自定义负载均衡策略类返回出去
    1. 在SpringBoot启动类中添加注解 @RibbonClient(name=“服务名”,configuration=负载均衡类.class)
      负载均衡类不能乱放,必须放在SpringBoot扫描不到的报下,否则所有的服务都会使用这个自定义负载均衡类

微服务

1、RPC原理
  • 服务端接口暴露出去,发布出去,我需要在这个服务端启动时,把这个接口发布到注册中心里
  • 客服端consumer在启动时,去注册中心中找到发布对应的接口的那个consumer服务里面相当于创建一个Start的一个代理对象
  • 把服务之间的通信变成了就是封装成了一个对象的一个调用,涉及到了网络通信,以及协议的转换

Hystrix熔断器

1、Hystrix特性
  • 断路器机制
    • 断路器很好理解, 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN) 避免发送大量无效请求影响系统吞吐量,并且断路器有自我检测并恢复的能力.
  • Fallback
    • Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.
  • 资源隔离
    • 在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池. 例如调用产品服务的Command放入A线程池, 调用账户服务的Command放入B线程池. 这样做的主要优点是运行环境被隔离开了. 这样就算调用服务的代码存在bug或者由于其他原因导致自己所在线程池被耗尽时, 不会对系统的其他服务造成影响. 但是带来的代价就是维护多个线程池会对系统带来额外的性能开销. 如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话, 可以使用Hystrix的信号模式(Semaphores)来隔离资源.
2、什么是Hystrix?
  • 防雪崩利器,具备服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)
  • 服务降级:
    • 优先核心服务,非核心服务不可用或弱可用。通过HystrixCommand注解指定。
    • fallbackMethod(回退函数)中具体实现降级逻辑。
3、熔断都有哪些状态
当一个服务调用另一个服务由于网络原因或自身原因出现问题,调用者就会等待被调用者的响应 当更多的服务请求到这些资源导致更多的请求等待,发生连锁效应(雪崩效应)
断路器有三种状态
打开状态:
  • 一段时间内 达到一定的次数无法调用 并且多次监测没有恢复的迹象 断路器完全打开 那么下次请求就不会请求到该服务
半开状态:
  • 短时间内 有恢复迹象 断路器会将部分请求发给该服务,正常调用时 断路器关闭
关闭状态:
  • 当服务一直处于正常状态 能正常调用
4、Hystrix熔断器四种防雪崩方式:
  • 服务降级:接口调用失败就调用本地的方法返回一个空
  • 服务熔断:接口调用失败就会进入调用接口提前定义好的一个熔断的方法,返回错误信息
  • 服务隔离:隔离服务之间相互影响
  • 服务监控:在服务发生调用时,会将每秒请求数、成功请求数等运行指标记录下来。
5、谈谈服务雪崩效应
  • 雪崩效应是在大型互联网项目中,当某个服务发生宕机时,调用这个服务的其他服务也会发生宕机,大型项目的微服务之间的调用是互通的,这样就会将服务的不可用逐步扩大到各个其他服务中,从而使整个项目的服务宕机崩溃.发生雪崩效应的原因有以下几点
  • 单个服务的代码存在bug. 2请求访问量激增导致服务发生崩溃(如大型商城的枪红包,秒杀功能). 3.服务器的硬件故障也会导致部分服务不可用.
6、服务雪崩效应产生的原因
  • 因为Tomcat默认情况下只有一个线程池来维护客户端发送的所有的请求,这时候某一接口在某一时刻被大量访问就会占据tomcat线程池中的所有线程,其他请求处于等待状态,无法连接到服务接口。

消息中间件MQ

1、什么是MQ
  • MQ就是消息队列。是软件和软件进行通信的中间件产品
2、什么是 ActiveMQ?
  • activeMQ 是一种开源的,实现了 JMS1.1 规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信
3、为什么使用MQ
  • 耦合
    • 在没有使用MQ是每次调用服务采用rpc方式远程调用 如果其中一个模块出现问题导致失败给用户不良体验 使用MQ后吧每次的数据放到MQ中不关心具体
  • 异步
    • 减少时间
  • 削峰
    • 秒杀系统 解决高并发 请求都放到MQ中每次只执行一部分请求从而缓解服务器压力
  • 日志处理
    • 解决大量日志传输。
  • 消息通讯
    • 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
3、MQ的缺点
  • 数据一致 一致性
  • 系统可用性降低: 解决方案双主双从 ,镜像集群
  • 系统复杂度提高
4、消息丢失的原因
  • 生产者没有成功发送消息到MQ Broker
  • 生产者发送给MQ Broker后Broker 宕机导致内存消息丢失
  • 消费者消费到消息 但是还没有处理完毕出现异常导致消息丢失
5、ActiveMQ 服务器宕机怎么办?
  • 这得从 ActiveMQ 的储存机制说起。在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的,它们的最大限制在配置文件的节点中配置。但是,在非持久化消息堆积到一定程度,内存告急的时候,ActiveMQ 会将内存中的非持久化消息写入临时文件中,以腾出内存。虽然都保存到了文件里,但它和持久化消息的区别是,重启后持久化消息会从文件中恢复,非持久化的临时文件会直接删除。
6、消息队列有什么缺点
  1. 系统可用性降低
  • 本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;
  1. 系统复杂度提高
  • 加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
  1. 一致性问题
  • A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
7、Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

image

  • 一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;
  • 后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;
  • 不过现在确实越来越多的公司会去用 RocketMQ,确实很不错,毕竟是阿里出品,但社区可能有突然黄掉的风险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。
  • 所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。
  • 如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。

Dubbo

1、为什么要用 Dubbo
  • 随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。就这样为分布式系统的服务治理框架就出现了,Dubbo 也就这样产生了。
2、Dubbo是什么
  • Dubbo 是一款高性能、轻量级的开源 RPC 框架,提供服务自动注册、自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成。
3、Dubbo 的使用场景有哪些
  • 透明化的远程方法调用:就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
  • 软负载均衡及容错机制:可在内网替代 F5 等硬件负载均衡器,降低成本,减少单点。
  • 服务自动注册与发现:不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
4、Dubbo 核心功能有哪些?
  • Remoting:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。
  • Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
  • Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
5、Dubbo 核心组件有哪些?
  • Provider:暴露服务的服务提供方
  • Consumer:调用远程服务消费方
  • Registry:服务注册与发现注册中心
  • Monitor:监控中心和访问调用统计
  • Container:服务运行容器
6、Dubbo 服务器注册与发现的流程?
  • 服务容器Container负责启动,加载,运行服务提供者。
  • 服务提供者Provider在启动时,向注册中心注册自己提供的服务。
  • 服务消费者Consumer在启动时,向注册中心订阅自己所需的服务。
  • 注册中心Registry返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  • 服务消费者Consumer,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 服务消费者Consumer和提供者Provider,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心Monitor。
7、Spring Cloud 和dubbo区别?
  • 服务调用方式:dubbo是RPC springcloud Rest Api
  • 注册中心:dubbo 是zookeeper springcloud是eureka,也可以是zookeeper
  • 服务网关,dubbo本身没有实现,只能通过其他第三方技术整合,springcloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,springcloud支持断路器,与git完美集成配置文件支持版本控制,事物总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素。
8、Dubbo 有哪些注册中心?
  • Multicast 注册中心:Multicast 注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现,基于网络中组播传输实现。
  • Zookeeper 注册中心:基于分布式协调系统 Zookeeper 实现,采用 Zookeeper 的 watch 机制实现数据变更。
  • Redis 注册中心:基于 Redis 实现,采用 key/map 存储,key 存储服务名和类型,map 中 key 存储服务 url,value 服务过期时间。基于 Redis 的发布/订阅模式通知数据变更。
  • Simple 注册中心。
  • 推荐使用 Zookeeper 作为注册中心
9、Dubbo的集群容错方案有哪些?
  • Failover Cluster:失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。
  • Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
    Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
  • Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
  • Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2″ 来设置最大并行数。
  • Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。
10、Dubbo 超时设置有两种方式:
  • 服务提供者端设置超时时间,在Dubbo的用户文档中,推荐如果能在服务端多配置就尽量多配置,因为服务提供者比消费者更清楚自己提供的服务特性。
  • 服务消费者端设置超时时间,如果在消费者端设置了超时时间,以消费者端为主,即优先级更高。因为服务调用方设置超时时间控制性更灵活。如果消费方超时,服务端线程不会定制,会产生警告。
11、服务调用超时会怎么样
  • dubbo 在调用服务不成功时,默认是会重试两次
12、Dubbo 支持分布式事务吗
  • 目前暂时不支持,可与通过 tcc-transaction 框架实现
  • 介绍:tcc-transaction 是开源的 TCC 补偿性分布式事务框架
  • TCC-Transaction 通过 Dubbo 隐式传参的功能,避免自己对业务代码的入侵。
13、Dubbo 可以对结果进行缓存吗
  • 为了提高数据访问的速度。Dubbo 提供了声明式缓存,以减少用户加缓存的工作量<dubbo:reference cache=“true” />
  • 其实比普通的配置文件就多了一个标签 cache=“true”
14、Dubbo 必须依赖的包有哪些
  • Dubbo 必须依赖 JDK,其他为可选。
15、Dubbo 支持哪些序列化方式
  • 默认使用 Hessian 序列化,还有 Duddo、FastJson、Java 自带序列化。
16 、Dubbo 在安全方面有哪些措施
  • Dubbo 通过 Token 令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。
  • Dubbo 还提供服务黑白名单,来控制服务所允许的调用方。

Eureka

1、什么是Eureka
  • Eureka作为SpringCloud的服务注册功能服务器,他是服务注册中心,系统中的其他服务使用Eureka的客户端将其连接到Eureka Service中,并且保持心跳
    这样工作人员可以通过Eureka Service来监控各个微服务是否运行正常。
2、Eureka包含的组件
  • Eureka Server
  • Eureka Clien
  • Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
  • Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
  • 在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
  • Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
3、Eureka工作原理
  • Eureka : 就是服务注册中心(可以是一个集群),对外暴露自己地址;
  • 提供者 : 启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者 : 向Eureka 订阅服务,Eureka会将对应服务的服务列表发送给消费者,并且定期更新
  • 心跳(续约): 提供者定期通过http方式向Eureka刷新自己的状态
4、什么是服务注册
  • 服务提供者在启动时,会向EurekaServer发起一次请求,将自己注册到Eureka注册中心中去
5、什么是服务续约
  • 在注册服务完成以后,服务提供者会维持一个心跳(每30s定时向EurekaServer 分发起请求)告诉EurekaServer “我还活着”
6、什么是失效剔除
  • 有时候,我们的服务提供方并不一定是正常下线,可能是内存溢出,网络故障等原因导致服务无法正常工作.EurekaServer会将这些失效的服务剔除服务列表.因此它会开启一个定时任务.每隔60秒会对失效的服务进行一次剔除
7、什么是自我保护
  • 当服务未按时进行心跳续约时,在生产环境下,因为网络原因,此时就把服务从服务列表中剔除并不妥当发,因为服务也有可能未宕机.Eureka就会把当前实例的注册信息保护起来,不允剔除.这种方式在生产环境下很有效,保证了大多数服务依然可用
8、怎么实现Eureka高可用
  • 集群
    • 注册多台Eureka,然后把SpringCloud服务互相注册,客户端从Eureka获取信息时,按照Eureka的顺序来访问。
9、Eureka和ZooKeeper的区别
ZooKeeper中的节点服务挂了就要选举
在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的,
选举就是改微服务做了集群,必须有一台主其他的都是从

Eureka各个节点是平等关系,服务器挂了没关系,只要有一台Eureka就可以保证服务可用,数据都是最新的。
如果查询到的数据并不是最新的,就是因为Eureka的自我保护模式导致的

Eureka本质上是一个工程,而ZooKeeper只是一个进程

Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper 一样使得整个注册系统瘫痪

ZooKeeper保证的是CP,Eureka保证的是AP
CAP:
C:一致性>Consistency;
取舍:(强一致性、单调一致性、会话一致性、最终一致性、弱一致性)
A:可用性>Availability;
P:分区容错性>Partition tolerance;
10、什么是 feigin?它的优点是什么?
  • feign 采用的是基于接口的注解
  • feign 整合了 ribbon,具有负载均衡的能力
  • 整合了 Hystrix,具有熔断的能力

Zull

1、什么是zuul
  • Zuul包含了对请求的路由和过滤两个最主要的功能:

    • 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础
    • Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得.
2、zuul用来做限流,但是为什么要限流?
  • 防止不需要频繁请求服务的请求恶意频繁请求服务,造成服务器资源浪费。
  • 防止不法分子恶意攻击系统,击穿系统盗取数据,防止数据安全隐患。
  • 防止系统高峰时期,对系统对频繁访问,给服务器带来巨大压力。
  • 限流策略
3、zuul的工作原理
  • 过滤器机制
    • zuul的核心是一系列的filters, 其作用可以类比Servlet框架的Filter,或者AOP。
    • zuul把Request route到 用户处理逻辑 的过程中,这些filter参与一些过滤处理,比如Authentication,Load Shedding等。
什么是网关以及网关的作用
  • 什么是网关:
    • 网关相当于一个网络服务架构的入口,所有网络请求必须通过网关转发到具体的服务。
  • 网关的作用:
    • 统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等
4、zuul 的作用

Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

  • 验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。
  • 审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。
  • 动态路由: 以动态方式根据需要将请求路由至不同后端集群处。
  • 压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。
  • 负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。
  • 静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。
  • 多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。
5、网关和过滤器的区别
  • 网关是对所有服务的请求进行分析过滤,过滤器是对单个服务而言。
6、常用的网关
  • Nginx
  • Zuul
  • Gateway
7、Zull和Nginx的区别
  • Zuul是java语言实现的,主要为java服务提供网关服务,尤其在微服务架构中可以更加灵活的对网关进行操作。
  • Nginx是使用C语言实现,性能高于Zuul,但是实现自定义操作需要熟悉lua语言,对程序员要求较高,可以使用Nginx做Zuul集群。
  • Zuul负载均衡实现:采用ribbon+eureka实现本地负载均衡
  • Nginx负载均衡实现:采用服务器实现负载均衡
  • Nginx相比zuul功能会更加强大,因为Nginx整合一些脚本语言(Nginx+lua)
  • Nginx适合于服务器端负载均衡
  • Zuul适合微服务中实现网关
8、ZuulFilter常用有那些方法
  • Run():过滤器的具体业务逻辑
  • shouldFilter():判断过滤器是否有效
  • filterOrder():过滤器执行顺序
  • filterType():过滤器拦截位置

Nginx

1、什么是Nginx
  • Nginx是一个 轻量级/高性能的反向代理Web服务器,他实现非常高效的反向代理、负载平衡,他可以处理2-3万并发连接数,官方监测能支持5万并发,现在中国使用nginx网站用户有很多,例如:新浪、网易、 腾讯等。
2、为什么要用Nginx
  • 跨平台、配置简单、方向代理、高并发连接:处理2-3万并发连接数,官方监测能支持5万并发,内存消耗小:开启10个nginx才占150M内存 ,nginx处理静态文件好,耗费内存少,
  • 而且Nginx内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上。
  • 使用Nginx的话还能:
    • 节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
    • 稳定性高:宕机的概率非常小
    • 接收用户请求是异步的
3、为什么Nginx性能这么高
  • 因为他的事件处理机制
  • 异步非阻塞事件处理机制
  • 运用了epoll模型,提供了一个队列,排队解决
4、Nginx怎么处理请求的?
  • nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,location就是实际地址
5、什么是正向代理和反向代理
  • 正向代理就是一个人发送一个请求直接就到达了目标的服务器
  • 反方代理就是请求统一被Nginx接收,nginx反向代理服务器接收到之后,按照一定的规 则分发给了后端的业务处理服务器进行处理了
6、使用“反向代理服务器的优点是什么
  • 反向代理服务器可以隐藏源服务器的存在和特征。它充当互联网云和web服务器之间的中间层。这对于安全方面来说是很好的,特别是当您使用web托管服务时。
7、Nginx的优缺点
  • 优点:
    • 占内存小,可实现高并发连接,处理响应快
    • 可实现http服务器、虚拟主机、方向代理、负载均衡
    • Nginx配置简单
    • 可以不暴露正式的服务器IP地址
  • 缺点:
    • 动态处理差:nginx处理静态文件好,耗费内存少,但是处理动态页面则很鸡肋,现在一般前端用nginx作为反向代理抗住压力,
8、Nginx应用场景
  • http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。
  • 虚拟主机。可以实现在一台服务器虚拟出多个网站,例如个人网站使用的虚拟机。
  • 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会应为某台服务器负载高宕机而某台服务器闲置的情况。
  • nginz 中也可以配置安全管理、比如可以使用Nginx搭建API接口网关,对每个接口服务进行拦截。
9、如何用Nginx解决前端跨域问题
  • 使用Nginx转发请求。把跨域的接口写成调本域的接口,然后将这些接口转发到真正的请求地址。
10、Nginx负载均衡的算法怎么实现的,策略有哪些
  • 为了避免服务器崩溃,大家会通过负载均衡的方式来分担服务器压力。将对台服务器组成一个集群,当用户访问时,先访问到一个转发服务器,再由转发服务器将访问分发到压力更小的服务器。
  • Nginx负载均衡实现的策略有以下五种:
    • 轮询(默认)
      • 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某个服务器宕机,能自动剔除故障系统。
    • 权重 weight
      • weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。其次是为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。
    • Ip_hash( IP绑定)
      • 每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题
    • fair(第三方插件)
      • 必须安装upstream_fair模块。
      • 对比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,响应时间短的优先分配。
    • url_hash(第三方插件)
      • 必须安装Nginx的hash软件包
      • 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。
11、Nginx配置高可用性怎么配置
  • 当上游服务器(真实访问服务器),一旦出现故障或者是没有及时相应的话,应该直接轮训到下一台服务器,保证服务器的高可用

Docker

1、什么Docker
  • Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在任何环境中无缝运行。
2、什么是Docker镜像

Docker镜像是Docker容器的源代码,Docker镜像用于创建容器。使用build命令创建镜像。

3、什么是Docker容器

Docker容器包括应用程序及其所有依赖项,作为操作系统的独立进程运行。

4、Docker容器有几种状态
  • 四种状态:运行、已暂停、重新启动、已退出。
5、Dockerfile中最常见的指令是什么
  • FROM:指定基础镜像
  • EXPOSE:暴露端口
  • RUN:运行指定的命令
  • CMD:容器启动时要运行的命令
6、Dockerfile中的命令COPY和ADD命令有什么区别
  • COPY与ADD的区别COPY的SRC只能是本地文件,其他用法一致
7、docker常用命令
  • docker pull 拉取或者更新指定镜像
  • docker push 将镜像推送至远程仓库
  • docker rm 删除容器
  • docker rmi 删除镜像
  • docker images 列出所有镜像
8、容器与主机之间的数据拷贝命令
  • docker cp 命令用于容器与主机之间的数据拷贝
    • 主机到容器:
      • docker cp /www 96f7f14e99ab:/www/
    • 容器到主机:
      • docker cp 96f7f14e99ab:/www /tmp/
9、解释一下dockerfile的ONBUILD指令
  • 当镜像用作另一个镜像构建的基础时,ONBUILD指令向镜像添加将在稍后执行的触发指令。如果要构建将用作构建其他镜像的基础的镜像,这将非常有用。
10、什么是Docker Swarm
  • Docker Swarm是Docker的本机群集。它将Docker主机池转变为单个虚拟Docker主机。Docker Swarm提供标准的Docker API,任何已经与Docker守护进程通信的工具都可以使用Swarm透明地扩展到多个主机。
11、Docker Image和Layer有什么区别
  • Image:Docker镜像是由一系列只读层构建的
  • Layer:每个层代表Dockerfile中的指令。
12、Docker使用流程
  • 创建Dockerfile后,您可以构建它以创建容器的镜像
  • 推送或拉取镜像。

分布式

分布式消息队列

1.分布式消息队列基础知识

消息

  • 要想弄清楚分布式消息队列的具体意义,首先得从什么是消息入手。
    消息即是信息的载体。为了让消息发送者和消息接收者都能够明白消息所承载的
    信息(消息发送者需要知道如何构造消息;消息接收者需要知道如何解析消息),
    它们就需要按照一种统一的格式描述消息,这种统一的格式称乊为消息协议。所
    以,有效的消息一定具有某一种格式;而没有格式的消息是没有意义的。
2.消息通信
  • 而消息从发送者到接收者的方式也有两种。一种我们可以称为即时消息通讯,也
    就是说消息从一端发出后(消息发送者)立即就可以达到另一端(消息接收者),
    这种方式的具体实现就是我们已经介绍过的 RPC(当然单纯的 http 通讯也满足
    这个定义);另一种方式称为延迟消息通讯,即消息从某一端发出后,首先迚入
    一个容器迚行临时存储,当达到某种条件后,再由这个容器发送给另一端。 这
    个容器的一种具体实现就是消息队列。
3.消息中间件
  • 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流
    量削锋、消息通讯等问题。实现高性能,高可用,可伸缩和最终一致性架构。是
    大型分布式系统丌可缺少的中间件。
    目前在生产环境,使用较多的消息队列有 ActiveMQ,RabbitMQ,ZeroMQ,
    Kafka,MetaMQ,RocketMQ 等

分布式ID

1、分布式唯一 ID 有哪些特性或要求呢
  • 唯一性:生成的 ID 全局唯一,在特定范围内冲突概率极小。
  • 有序性:生成的 ID 按某种规则有序,便于数据库插入及排序。
  • 可用性:可保证高并发下的可用性, 确保任何时候都能正确的生成 ID。 ④ 自主性:分布式环境下不依赖中心认证即可自行生成 ID。
  • 安全性:不暴露系统和业务的信息, 如:订单数,用户数等
2、分布式唯一 ID 有哪些生成方法呢
  • 总的来说,大概有三大类方法,分别是:数据库自增 ID、UUID 生成、snowflake雪花算法
  • 数据库自增 ID
    • 核心思想:使用数据库的 id 自增策略(如: Mysql 的 auto_increment)。
      • 优点:
        • 简单,天然有序。
      • 缺点:
        • 并发性不好。
        • 数据库写压力大。
        • 数据库故障后不可使用。
        • 存在数量泄露风险
  • UUID 生成
    • 核心思想:结合机器的网卡(基于名字空间/名字的散列值 MD5/SHA1)、当地时间(基于时间戳&时钟序列)、一个随记数来生成 UUID。
      • 优点:
        • 本地生成,没有网络消耗,生成简单,没有高可用风险。
      • 缺点:
        • 不易于存储:UUID 太长,16 字节 128 位,通常以 36 长度的字符串表示,很多场景不适用。
        • 信息不安全:基于 MAC 地址生成 UUID 的算法可能会造成 MAC 地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。
        • 无序查询效率低:由于生成的 UUID 是无序不可读的字符串,所以其查询效率低。
  • 雪花算法
    • 核心思想:把 64-bit 分别划分成多段,分开来标示机器、时间、某一并发序列等,从而使每台机器及同一机器生成的 ID 都是互不相同。
      • 优点:
        • 生成有顺序的id,提高数据库的性能,现在大部分都不用uuid作为主键
      • 缺点:
        • 时钟回拨:最常见的问题就是时钟回拨导致的ID重复问题,在SnowFlake算法中并没有什么有效的解法,仅是抛出异常。时钟回拨涉及两种情况①实例停机→时钟回拨→实例重启→计算ID ②实例运行中→时钟回拨→计算ID
        • 手动配置:另一个就是workerId(机器ID)是需要部署时手动配置,而workerId又不能重复。几台实例还好,一旦实例达到一定量级,管理workerId将是一个复杂的操作。

设计模式

1. 什么是设计模式
所谓设计模式,就是面向对象编程中的各种现成套路,也是众多前辈程序员经过长期积累和实践从而总结出的解决方案
----------------------------
面对不同的需求场景,选择合适的设计模式,可以提高代码的可读性,增加代码的可重用性,保证代码的可扩展性
----------------------------
设计模式只是在面向对象编程语言之间通用。至于面向过程语言、函数式编程语言,谈困设计模式是没有意义的
2. 设计模式的分类
设计模式一共有23种,这23中设计模式又可以根据设计的目的分为三大类型。
1.创建型模式
  这一类设计模式的目的是用于创建对象。
2.结构型模式
  这一类设计模式的目的是优化不同类、对象、接口之间的结构关系。
3.行为型模式
  这一类设计模式的目的是更好地实现类与类之间的交互以及算法的执行。

总结图
总结图

人事

1、两年工作经验最大的收获是什么

如何了解快速上手,公司所接手的项目,首先可以去看一下业务上下流的关系,比如这个服务器是服务于那些服务的,哪些业务的,我们的服务又提供给那些服务的调用
邮箱的沟通,进入企业写代码可能跟沟通六四开,也有可能是五五开

2、怎么理解业务跟技术之间的关系

我以前觉得我是一个做技术的,可能技术更重要一点,但是我发现业务也是很重要的,技术是服务于业务的,因为我们去给别人去给企业做这个东西,企业是希望盈利的,而他盈利的东西是这个业务去盈利,那么我们如何把我们的这个技术做好,能够真正的去服务业务,让那些业务运行的更好,我觉得业务跟技术同等重要

3、你有什么想问我的(面试官)

我能问下您对我今天的面试感觉怎么样,或者觉得我可以在哪些方面做得更好,,,,,,,,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值