首页 > 技术交流 > 【万字】携程后台开发面经分类汇总

【万字】携程后台开发面经分类汇总

头像
Mkbk
编辑于 2021-04-16 15:10:37 APP内打开
赞 50 | 收藏 325 | 回复7 | 浏览4239

面试携程之前,把之前的携程的后台开发相关的面经收集了一下了,做了汇总分类。现在分享给大家,希望对大家有帮助!

目录:


1. Object下都有什么方法? [2s]

Object类是所有类的父类,所有类都默认继承了Object类。

Object类实现的方法:

  1. getClass 方法
    final修饰,用于返回当前运行时对象的class对象。
  2. hashCode 方法
    用于返回对象的哈希码,主要使用在哈希表中,如 JDK中的HashMap。
  3. equals 方法
    用于比较两个对象的内存地址是否相等;
    但一般都是使用重写后的equals方法,用于比较两个对象的值是否相等。
  4. clone 方法
    用于创建并返回对象的一份拷贝(浅复制);
    调用clone方法前需要先实现Cloneable接口并重写clone方法,否则会报CloneNotSupportedException异常。
  5. toString 方法
    会返回 类的名字@实例的哈希码的16进制 的字符串;
    一般都是使用重写后的toString方法。
  6. notify 方法
    final修饰,用于唤醒在该对象上等待的线程,如果有多个线程在等待,则随机唤醒其中一个。
  7. notifyAll 方法
    final修饰,用于唤醒在该对象上等待的所有线程。·
  8. wait 方法 (3种)
    final修饰,用于暂停线程的执行,相比sleep方法,wait方***释放锁;
    8.1 wait() 方***一直暂停线程执行;
    8.2 wait(long timeout) 方***暂停线程,timeout 是超时时间(毫秒);
    8.3 wait(long timeout,int nanos) 方法和 wait(long timeout) 一样,但是超时时间要加上nanos(毫微秒);
  9. finalize 方法
    实例被垃圾回收器回收的时候触发的操作

2. 深拷贝和浅拷贝是什么?区别? 如果是Clone接口,那通过克隆出来的对象是浅拷贝还是深拷贝?用 Java 实现一下。 [2s]

  1. 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
  2. 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

Clone接口默认是浅拷贝。

如果要用clone实现深拷贝类A的实例话

1.类A的引用类型属性也要实现cloneable方法;

2.在类A的clone方法中,单独set,clone这个鞋应用类型的属性。

   @Override
    protected Object clone() throws CloneNotSupportedException {
        //浅拷贝
        //return super.clone();

        //深拷贝
        Student student = (Student) super.clone();
        // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
        student.setTeacher((Teacher) this.teacher.clone());
        return student;

    }

使用序列化实现深拷贝,参考:https://www.cnblogs.com/xinruyi/p/11537963.html

参考:https://www.cnblogs.com/xinruyi/p/11537963.html

3. wait() 和 notify(), 具体使用场景

  1. notify 方法
    final修饰,用于唤醒在该对象上等待的线程,如果有多个线程在等待,则随机唤醒其中一个。
  2. notifyAll 方法
    final修饰,用于唤醒在该对象上等待的所有线程。·
  3. wait 方法 (3种)
    final修饰,用于暂停线程的执行,相比sleep方法,wait方***释放锁;
    3.1 wait() 方***一直暂停线程执行;
    3.2 wait(long timeout) 方***暂停线程,timeout 是超时时间(毫秒);
    3.3 wait(long timeout,int nanos) 方法和 wait(long timeout) 一样,但是超时时间要加上nanos(毫微秒);

使用场景:

  1. 线程间的通信
  2. 实现 生产者-消费者模式

4. equals() 和 hashcode() [2s]

5. 面向对象的特点?面向对象和面向过程的区别? [2s]

  • 封装:将事物封装成一个类,减少耦合,隐藏细节。保留特定的接口与外界联系,当接口内部发生改变时,不会影响外部调用方。

  • 继承:从一个已知的类中派生出一个新的类,新类可以拥有已知类的行为和属性,并且可以通过覆盖/重写来增强已知类的能力。

  • 多态:

    多态的本质就是

    一个程序中存在多个同名的不同方法

    主要通过三种方式来实现:

    • 通过子类对父类的覆盖来实现
    • 通过在一个类中对方法的重载来实现
    • 通过将子类对象作为父类对象使用来实现

区别:

  • 面向过程面向过程性能比面向对象高。 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发。但是,面向过程没有面向对象易维护、易复用、易扩展。
  • 面向对象面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低

6. 如何实现多态?并以面向对象的思想设计一个猫吃鱼的例子(写代码)

主要通过三种方式来实现:

  • 通过子类对父类的覆盖来实现
  • 通过在一个类中对方法的重载来实现
  • 通过将子类对象作为父类对象使用来实现

类、抽象类、接口的区别

7. 死锁是什么?死锁是怎么造成的?死锁的几个条件?如何避免死锁? [3s]

两个线程或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。

死锁产生必须满足的四个条件:

  1. 资源互斥:该资源任意一个时刻只由一个线程占用。

  2. 不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。

  3. 请求与保持状态:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁:

上面说了产生死锁的四个必要条件,为了避免死锁,我们只要破坏产生死锁的四个条件中的其中一个就可以了。

  1. 破坏互斥条件 :这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。
  2. 破坏请求与保持条件 :一次性申请所有的资源。
  3. 破坏不剥夺条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
  4. 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

8. synchronized 相关 [3S]

8.1 synchronized关键字加在静态方法和非静态方法上有何区别?

  1. 修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁

  2. 修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁

  3. 修饰代码块 :指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁

总结:

  • synchronized 关键字加到 static 静态方法和 synchronized(class) 代码块上都是是给 Class 类上锁。
  • synchronized 关键字加到实例方法上是给对象实例上锁。
  • 尽量不要使用 synchronized(String a) 因为 JVM 中,字符串常量池具有缓存功能!

8.2 synchronized是用来干嘛的?

synchronized 关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

8.3 jvm是怎么实现synchroinzed的? (synchroinzed 的底层实现。)

synchronized 关键字底层原理属于 JVM 层面。

public class SynchronizedDemo {
    public void method() {
        synchronized (this) {
            System.out.println("synchronized 代码块");
        }
    }
}

从上面我们可以看出:

synchronized 同步语句块的实现使用的是 monitorentermonitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。

当执行 monitorenter 指令时,线程试图获取锁也就是获取 对象监视器 monitor 的持有权。

在 Java 虚拟机(HotSpot)中,Monitor 是基于 C++实现的,由ObjectMonitor实现的。每个对象中都内置了一个 ObjectMonitor对象。

另外,wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

在执行monitorenter时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。

在执行 monitorexit 指令后,将锁计数器设为 0,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。

synchronized 修饰方法的的情况

public class SynchronizedDemo2 {
    public synchronized void method() {
        System.out.println("synchronized 方法");
    }
}

synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法。JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

总结

synchronized 同步语句块的实现使用的是 monitorentermonitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。

synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法。

不过两者的本质都是对对象监视器 monitor 的获取。

8.4 synchronized(Main.class) 和 synchronized(object)的区别?

同步synchronized(.class)代码块的作用其实和synchronized static方法作用一样:也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 *当前 class 的锁**。

8.5 volatile和synchronized的区别?

synchronized 关键字和 volatile 关键字是两个互补的存在,而不是对立的存在!

  • volatile 关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile 关键字只能用于变量而 synchronized 关键字可以修饰方法以及代码块
  • volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。
  • volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。

9.volatile 相关 [2s]

volatile有什么作用?

指令重排是什么意思?

JMM模型?

volatile 底层实现原理?

volatile的底层是通过lock前缀指令、内存屏障来实现的。

10. 线程相关 [5s]img

多线程

10.1 线程有哪些基本状态? 状态切换图画出来。

10.2 线程的可见性。

10.3 进程和线程的区别

10.4 Java如何实现线程安全

同步代码块 synchronized

同步方法 synchronized

lock锁

10.5 static 关键字 修饰的方法是否有线程安全问题

静态方法如果没有使用静态变量,则没有线程安全问题。

如果在静态方法里使用了静态变量,这就会有线程安全问题!

因为静态方法内声明的变量,每个线程调用时,都会新创建一份,而不会共用一个存储单元。比如这里的tmp,每个线程都会创建自己的一份,因此不会有线程安全问题。
注意:静态变量,由于是在类加载时占用一个存储区,每个线程都是共用这个存储区的,所以如果在静态方法里使用了静态变量,这就会有线程安全问题!

10.6 ThreadLocal 了解么?

11. 集合相关

11.1 集合概述(用过哪些集合?)

11.2 ArrayList 相关

ArrayList & LinkedList的区别,

线程不安全的list会导致什么问题 ? 哪些线程安全的list,

ArrayList 扩容机制

默认的空参构造函数,底层会先创建一个空的数组,当第一次开始向数组中添加数据时才会真正分配容量,默认第一次是扩容成10;

扩容过程的话,是先通过 ensureCapacityInternal 得到最小扩容量,然后通过 ensureExplicitCapacity 方法判断是否需要扩容,也就是用当前总共所需的容量-现有容量是否 大于 0, 如果大于0,说明容量不够了,就会调用一个 grow 方法来进行扩容。

grow方法是先将数组扩容到成当前容量的1.5倍,直至容量足够,或者直至扩容至Integer.MAX_VALUE - 8。

然后使用 elementData = Arrays.copyOf(elementData, newCapacity); 将旧数据放到扩容后的新数组中,并将原来的数组引用指向新数组,然后在新数组上添加新数据。

通过运行结果,我们可以看出向 ArrayList 添加大量元素之前最好先使用ensureCapacity 方法,以减少增量重新分配的次数。

11.3 HashMap相关

HashMap底层原理?在key相同的情况下怎么处理?

HashMap扩容机制?扩容会新建一个数组吗

HashMap 为什么后面链表 会 转化为红黑树

HashMap线程安全吗?与ConcurrentHashMap的区别?分段锁在Java8后有什么变化?

HashTable & ConcurrentHashmap & ConcurrentHashMap的原理

12. JVM

媒体\文章\1. Java\1.4 JVM)

jvm的内存模型?

看了哪本关于jvm的书?

JVM中一个对象从创建到被回收所经历的整个过程

垃圾收集算法
老年代中有对象依赖年轻代中对象,怎么判断年轻代中的对象是否需要被回收。

jvm调优的方法

13. MySQL 及数据库相关

13.1 事务的特性是什么? 并发可能带来的问题?事务隔离级别有哪些? 默认的是哪个?

13.2 MySQL怎么实现隔离的?

就只有锁吗?(我又回答了MVCC)

13.3 MVCC相关

MVCC是怎么解决幻读问题的?

在可重复读隔离级别下,通过多版本并发控制(MVCC)+ Next-Key Locking 防止幻影读

MVCC具体是怎么实现隔离的

而InnoDB实现MVCC的方式是:

  • 事务以排他锁的形式修改原始数据
  • 把修改前的数据存放于undo log,通过回滚指针与主数据关联
  • 修改成功(commit)啥都不做,失败则恢复undo log中的数据(rollback)****

MVCC参考1

MVCC参考2

13.4 MySQL锁 相关

锁有行锁,段锁和表锁,insert一行数据的时候加的是什么锁?为什么?

MyISAM和InnoDB存储引擎使用的锁:

  • MyISAM采用表级锁(table-level locking)。

  • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

MySQL数据库的锁分为表级锁和行级锁。从数据库的角度看,行级锁又可以分为独占锁和共享锁

13.5 MySQL存储引擎是什么? 及区别。

MySQL5.5版本及以前默认是MyIsam;

MySQL5.6及以后默认是Innodb。

  • MyISAM采用表级锁(table-level locking)。
  • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

13.6 关系型数据库与非关系型数据库的区别?非关系型数据库在什么场景下使用?

关系型数据库:最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织。

非关系型数据库:是一种数据结构化存储方法的集合,可以是文档或者键值对等。

关系型数据库优缺点

优点:

1、易于维护:都是使用表结构,格式一致
2、使用方便SQL语言通用,可用于复杂查询;
3、复杂操作支持SQL,可用于一个表以及多个表之间非常复杂的查询。

缺点:

1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表结构,灵活度稍欠
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈

非关系型数据库优缺点

优点:
1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
3、高扩展性;

缺点:
1、不提供sql支持,学习和使用成本较高;
3、数据结构相对复杂,复杂查询方面稍欠。

项目用的数据库是?

13.7 索引

什么是索引?索引的优缺点点是什么?什么场景下使用索引、什么场景下不使用? 建立索引要注意什么?索引失效的场景?

索引:是一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。 简单来说就是:索引是一种排好序的快速查找数据结构

优点:

  1. 类似于大学图书馆建书目索引,提高数据检索的效率,降低数据库的 IO 成本
  2. 通过索引列对数据进行排序,降低数据排序的成本,降低了 CPU 的消耗。

缺点:

  1. 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。
  2. 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加的索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
  3. 索引只是提高效率的一个因素,如果我们的MySQL有大数据量的表,我们就需要花时间研究建立最优秀的索引,或优化查询语句。

使用场景

需要创建索引的情况:

  1. 主键自动建立唯一索引。
  2. 频繁作为查询条件的字段可以创建索引;
  3. 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度。
  4. 查询中统计或者分组字段
  5. 单值与复合索引,在高并发下倾向于创建复合索引
  6. 查询中与其他表关联的字段,外键关系可以创建索引

不需要创建索引的情况:

  1. 表记录太少
  2. 经常增删改的表
    因为虽然提高了查询速度,但同时却会降低更新表的速度,比如对表进行 INSERT、UPDATE、DELETE。
    因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
  3. 数据重复且分布平均的表字段。
    因此应该只为最经常查询和最经常排序的数据建立索引。
    注意:如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
  4. 频繁更新的字段不适合创建索引。
    因为每次更新不单单是更新了记录还会更新索引,加重了IO负担。
  5. Where 条件里用不到的字段不适合创建索引。

索引使用注意以及失效情况:

优化总结口诀
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE百分写最右,覆盖索引不写星:
不等空值还有or,索引失效要少用;
VAR引号不可丢,SQL高级soeasy!

MySQL都有哪些索引?

从逻辑角度:

  1. 单值索引: 即一个索引只包含单个列,一个列可以有多个单列索引。
  2. 唯一索引:索引列的值必须唯一,但允许有空值。
  3. 复合索引:即一个索引包含多个列
  4. 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引:
  5. 全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较;是所以全文索引更像是一个搜索引擎。

从物理存储角度:

  1. 聚集索引(clustered index):其索引树的叶子节点中存的是整行数据,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序
  2. 非聚集索引(non-clustered index):叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值

非聚簇索引一定会回表查询吗?
不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。

从数据结构角度:

  1. B+树索引(O(log(n)))
  2. hash索引
  3. FULLTEXT索引
  4. R-Tree索引

索引是怎么实现的?

在数据库中维护一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。 简单来说就是:一种排好序的快速查找数据结构

具体的常见实现有:B+树索引,hash 索引。

索引底层数据结构是, 为什么不用二叉树

索引的底层数据结构一般选用 B+ 树索引。

比如,二叉搜索树,有可能退化成链表,查找时间复杂度会从 O(logn) 变成O(n),性能不够稳定,并且二叉搜索树,树高会非常高,磁盘IO次数会特别多,也就是会特别消耗性能。并且二叉搜索树的范围查询性能也很差。

B+树作为索引的结构比其他数据结构好在哪,比如二叉树哈希表、数组,B树。

数组:插入的效率太低了!每次插入要将插入位置后面的元素全部复制后移!效率太低。

哈希表哈希表的增删改以及普通查询的效率都是O(1),速度很快。但是对于范围查询的时候,需要遍历整个哈希表,非常耗时。 哈希表比较适合NOSQL数据库,比如Redis。

二叉树:可能退化成链表,查找性能降低为O(n),并且二叉搜索树等一个节点最多两个子节点,会使树高非常高,也就是会使磁盘IO非常多,而磁盘IO是非常耗时的。

B树索引:B-Tree 的特点是无论叶子结点和非叶子结点,它都存有索引值和数据;B+Tree 的特点是只有叶子结点才会存放索引值和数据,非叶子结点只会存放索引值本身。因此对于非叶子结点,一个结点中,B+Tree 存放的索引值数量会远远大于 B-Tree。 也就是说,B树比B+树更瘦高,磁盘IO次数会更多,所以B+树相比B树更适合作为索引。并且B+树的叶子节点之间用指针按顺序连接起来了,大幅提高了范围查询的速度。

B+树原理是什么?

B+树最左匹配原则

B+树的优点

B树和B+树的区别

B树:B树可以在内部节点同时存储键和值

B+树: B+树的内部节点只存放键,不存放值。值只存放在叶子节点,并且用指针按序连接。

  • B树只适合随机检索,而B+树同时支持随机检索和顺序检索;
  • B+树空间利用率更高,可减少I/O次数,磁盘读写代价更低。一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗。B+树的内部结点并没有指向关键字具体信息的指针,只是作为索引使用,其内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了。而IO读写次数是影响索引检索效率的最大因素;
  • B+树的查询效率更加稳定。B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找。而在B+树中,顺序检索比较明显,随机检索时,任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当。
  • B-树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题
  • B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作。
  • 增删文件(节点)时,效率更高。因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率。

sql题考察对B+树的理解

连接数据库的操作怎么做的

mysql分页查询的实现以及对于limit 10000,100000000000000查询缓慢的解决办法

SQL语句,查询全班每门课程的及格率

14. SSM等框架相关

14.1 解释一下SQL注入

 sql注入解释:是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者)

 SQL注入,大家都不陌生,是一种常见的攻击方式。攻击者在界面的表单信息或URL上输入一些奇怪的SQL片段(例如“or ‘1’=’1’”这样的语句)

#{}是经过预编译的,是安全的

${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入

14.2 spring的bean和java的bean有哪些区别? 创建bean有几种方式?bean的生命周期(Singleton等)?

传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处不在,任何组件都可以被称为bean。

传统javabean作为值对象,要求每个属性都提供getter和setter方法;但spring中的bean只需为接受设值注入的属性提供setter方法。

生命周期不同:传统javabean作为值对象传递,不接受任何容器管理其生命周期;spring中的bean有spring管理其生命周期行为。

创建bean的方式:

  1. 使用构造器实例化Bean
  2. 使用静态工厂方式实例化Bean
  3. 使用实例工厂方法实例化Bean
  4. 用 setter 方式

Spring的AOP自调用问题。

Spring的循环依赖问题原理。

Spring IOC

Spring隔离级别

如果Controller层想返回的数据是JSON格式的,怎么办。

@Controller 返回一个页面

@RestController ,会返回JSON 或 XML 形式数据。

@RestController只返回对象,对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中,这种情况属于 RESTful Web服务,这也是目前日常开发所接触的最常用的情况(前后端分离)。

如果指定的方法为POST请求,怎么处理。

@PostMaping

或者

@RequestMapping(value="/users",method=RequestMethod.POST)

15. 网络相关

解释一下IO阻塞?

TCP相关

TCP如何保证可靠传输?

  1. 应用数据被分割成 TCP 认为最适合发送的数据块。
  2. TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
  3. 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  4. TCP 的接收端会丢弃重复的数据。
  5. 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
  6. 拥塞控制: 当网络拥塞时,减少数据的发送。
  7. ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
  8. 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

TCP三次握手?

TCP四次挥手

TCP建立连接后,服务端出现故障,怎么处理?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

HTTP协议,HTTP1.0,HTTP1.1, HTTP2.0的特性,以及区别

HTTP协议:超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个请求-响应协议,它通常运行在TCP之上。指定了客户端和服务器之间消息请求和响应的格式。

HTTP报文格式:

请求报文(Request):

  1. 请求行:
    请求行包含:请求方法、URL和HTTP协议版本。 比如:POST /login.html HTTP/1.1 。

    HTTP 协议有 7 种请求方式,常用的两种是:GET 和 POST。

  2. 请求头:客户端浏览器告诉服务器一些信息。

  3. 请求空行:用于分割 POST 请求的请求头和请求体。

  4. 请求体:用于封装 POST 请求消息的请求参数。

响应报文(Response):

  1. 响应头
    包含多个以键值对存储的信息,“属性名:属性值”。
    比如:
    Cache-Control:private //缓存控制
    Connection:Keep-Alive //是否保证连接
    Content-Encoding:gzip //编码格式
    Content-Type:text/html //服务器告诉客户端本次响应体数据格式
    Accept: //告诉浏览器,它所支持的数据类型
    Accept-Encoding: //支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
    Accept-Language: //告诉浏览器,它的语言环境
    Cache-Control: //缓存控制
    Connection: //告诉浏览器,请求完成是断开还是保持连接
    HOST: //主机
    Refresh: //告诉客户端,多久刷新一次;
    Location: //让网页重新定位;
  2. 响应空行:一个空行用于分割 响应头和响应体。
  3. 响应体:响应回的数据。

常见的HTTP Code有哪些,常见HTTP协议的状态码

  • 200(成功)
  • 301 (永久性重定向)
  • 302 (临时性重定向):请求重定向到指定网页
  • 304(未修改):自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容
  • 401(未授权):请求要求身份验证
  • 403(禁止):服务器拒绝请求(比如死循环了,一直访问)
  • 404(未找到):服务器找不到请求的网页
  • 405 (方法禁用):Post请求当成了Get请求直接访问
  • 500 (服务器内部错误):有bug导致程序嗝屁了
  • 502 (错误网关):服务器从上游接到了无效响应
  • 504 ( 网关超时):nginx请求超时,请求一直没有返回

项目是处理HTTP请求的,那么301状态码和302有什么区别了解吗?

使用@RequestMapping()处理HTTP请求。

比如:@RequestMapping(value="/users",method=RequestMethod.POST)

或者使用对应HTTP请求类型的的xxxMapping注解

@GetMapping("users")

@PostMapping("users")

@PutMapping("/users/{userId}")

@DeleteMapping("/users/{userId}")

@RestController

16. 设计模式

单列模式定义: 确保一个类只有一个实例,并提供该实例的全局访问点。

这样做的好处是:有些实例,全局只需要一个就够了,使用单例模式就可以避免一个全局使用的类,频繁的创建与销毁,耗费系统资源。

单例模式的设计要素

  • 一个私有构造函数 (确保只能单例类自己创建实例)
  • 一个私有静态变量 (确保只有一个实例)
  • 一个公有静态函数 (给使用者提供调用方法)

简单来说就是,单例类的构造方法不让其他人修改和使用;并且单例类自己只创建一个实例,这个实例,其他人也无法修改和直接使用;然后单例类提供一个调用方法,想用这个实例,只能调用。这样就确保了全局只创建了一次实例。

饿汉式

public class Singleton{
    private static Singleton uniqueInstance = new Singleton();

    private Singleton() {

    }

    public static Single getUniqueInstance() {
        return uniqueInstance;
    } 

}

懒汉式(线程不安全)

public class Singleton{
    private static Singleton uniqueInstance;

    private Singleton() {

    }

    public Singleton getUniqueInstance() {
        if(uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

}

懒汉式(线程安全)

public class Singleton{
    private static Singleton uniqueInstance;

    private Singleton() {

    }

    public static synchronized Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }



}

双重校验锁

public class Singleton{
    private static volatile Singleton uniqueInstance;

    private Singleton() {

    }

    public static  Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized(Singleton.class) {
                if (uniqueInstance == null) {
                     uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }



}

静态内部类

public class Singleton{
    private Singleton() {

    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }


}

枚举类

public enum Sinleton {
    INSTANCE;

    //Do something else...
}

Redis

redis和rabbitMQ,他们的区别,各自的使用场景,本地缓存和redis的区别。

redis、消息队列,怎么保证可靠性、重复消费,为什么用消息队列,如果用rpc会怎样?

redis对于缓存击穿的解决方案

为什么项目要用消息队列呢?

数据结构与算法

数据结构:

你了解的数据结构

你说到了树结构,讲一下你了解的树结构

二叉搜索树应用场景

红黑树的性质和操作

二叉树

B+树最左匹配原则

算法

n皇后

八皇后

重构二叉树

寻找重复数

逆波兰式

给个单链表,找到中间元素 快慢指针

二分查找

string to int

数组中的数字去重

写一个前缀树,要实现的方法包括put、search、startWith。

一个很大的无序数组,找出其中最小的k个数。时间复杂度。(只需要说思路,我具体说了用快速排序里面的那种思想)

写你认为最快的排序算法

如何实现一个栈

如何实现最小栈

如何实现数组奇数顺序排前面偶数顺序排后面

将一个数组中正数放左边,零放中间,负数放右边。利用快排思想排两次

一个是给定一个n值,求n以内不含4和7的个数

给定一个包含大小写字母的字符串,求出字符串中的所有最大元素(按照ANSCII码),例如aabzbbzc,输出aabz(max)bbz(max)c。

项目

.项目登录注册的安全性问题如何解决

项目经历

项目做了什么?

项目是处理HTTP请求的,那么301状态码和302有什么区别了解吗?

为什么项目要用消息队列呢?

特殊问题

为什么选择携程

你的优点是什么

如何学习

最近学啥

最有成就感 + 比较挫败的时候

平时自己是怎么学习的

对于自己的职业生涯规划怎么想的

代码风格

代码优化

反问

更新的一些:

wait() notify() 底层了解过吗

想让两个线程顺序输出,有哪几种方法,哪种最好?

了解注解吗?自己的项目使用到了自定义注解。注解怎么实现的?通过反射实现。反射中获取class对象的三种方式?通过object类的getClass方法,类的class属性,class类的forName方法。

b+树的缺点

.共享变量放在哪个区(元数据),哪static修饰的变量放在哪

7条回帖

回帖
加载中...
话题 回帖

相关热帖

技术交流近期热帖

近期精华帖

热门推荐