文章目录
- 一、JavaSE基础
- 1. 谈谈对OOP的理解
- 2. String底层使用什么实现的?为什么不可变?
- 3. Int和Integer的区别,在使用时有什么区别?
- 4. 重写,重载
- 5. ==与equals()
- 6. 接口与抽象类
- 7. 格式化日期用的什么?
- 二、集合
- 三、多线程
- 1. 创建线程有哪些方法(4种)?
- 2. Runnable和Callable有什么不同?
- 3. start()和run()方法有什么区别?
- 4. 线程池有哪些参数
- 5. 线程池有几种(5种)?拒绝策略有几种(4种)?阻塞队列有几种(3种)?
- 6. 如何检测死锁?
- 7. volatile底层是怎么实现的?
- 8. volatile与synchronized有什么区别?
- 四、MySql
- 1. sql优化
- 2. 什么是索引
- 3. 如何判断一条sql语句是否使用了索引(执行计划)
- 4. 存储引擎
- 5. 如何选择合适的存储引擎
- 6. Innodb有哪些特性?
- 7. Innodb的事务锁有哪些?(4种)
- 8. 使用什么工具创建表?
- 9. 表结构是怎么设计的?
- 10. Mysql事务的隔离级别
- 11. 什么是脏读?什么是幻读?
- 12. MySQL 服务占用 cpu 100%,如何排查问题?
- 13. 数据库集群是怎么同步的?
- 五、Redis
- 六、Linux
- 七、Spring
- 八、SpringMVC
- 九、MyBatis
- 十、SpringBoot
- 十一、RabbitMQ
- 十二、其它
2020年3月份一些中小型互联网或计算机软件公司的社招题目。
一、JavaSE基础
1. 谈谈对OOP的理解
- 首先面向对象是一种编程思想
- 万物皆对象。我的电脑是一个对象,我的手机是一个对象等等,OOP可以理解为使用代码来模拟现实生活
- 三大特性:封装、继承和多态
- 封装就是隐藏类的内部信息,不允许外部程序直接访问,而是通过getter(获取)和setter(设置)方法完成,提高数据的安全性
- 继承是指:父类的基本特征和行为,子类也会有,子类也可以改变这些特征和行为。
- 多态就是多个对象调用同一个方法,可能会得到的是不同的结果。
2. String底层使用什么实现的?为什么不可变?
String
的底层使用的是char
数组。这个char
数组和String
这个类都是final
修饰的,所以不可变。
3. Int和Integer的区别,在使用时有什么区别?
Integer
是int
的包装类,int
则是java
的一种基本数据类型Integer
变量必须实例化后才能使用,而int
变量不需要Integer
实际是对象的引用,当new
一个Integer
时,实际上是生成一个指针指向此对象;而int
则是直接存储数据值Integer
的默认值是null
,int
的默认值是0
4. 重写,重载
- 方法重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同
- 方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型
- 子类中不能重写父类中的
final
方法 - 子类中必须重写父类中的
abstract
方法
- 子类中不能重写父类中的
5. ==与equals()
==
号在比较基本数据类型时比较的是值,而用==
号比较两个对象时比较的是两个对象的地址值equals()
方法存在于Object
类中,其底层依赖的是==
号,如果类没有重写Object
中的equals()
方法的类中,则调用equals()
方法其实和使用==
号的效果一样
6. 接口与抽象类
相同点:
- 都不能被实例化
- 接口的实现类或抽象类的子类都只有实现了抽象方法后才能实例化。
不同点:
- 意义不同:接口是功能的封装,解决对象能干什么;抽象类是事物的抽象,解决对象到底是什么。
- 内容不同:接口中的内容只能有:抽象方法(
public abstract
修饰),常量(public static final
修饰),在JDK8中,接口还可以定义static
静态方法和default
方法;而抽象类可以有普通类的所有内容和抽象方法。 - 接口支持多继承,类只允许单继承
7. 格式化日期用的什么?
使用的是 SimpleDateFormat
。
- 把日期转换为指定格式的字符串
//使用SimpleDateFormat类,在构造方法中指定日期的格式:y年,M月,d日,H小时,m分钟,s秒 SimpleDateFormat sdf = new SimpleDateFormat("yyy y-MM-dd HH:mm:ss"); //调用SimpleDateFormat实例方法format(Date)可以把日期转换为字符串 String text = sdf.format(date);
- 把字符串转换为日期
text = "2068年5月12日 8:28:58"; //先创建SimpleDateFormat对象, 指定的格式串要与字符串匹配 SimpleDateFormat anotherSdf = new SimpleDateFormat("yyyy年M月dd日 H:mm:ss"); //调用SimpleDateFormat的实例方法parse(String)可以把字符串转换为日期对象, 如果格式串与字符串不匹配就会产生异常 date2 = anotherSdf.parse(text);
二、集合
1. List,Set,Map区别(扩容过程)
(1)List集合
存储特点:有序,可重复。存储顺序与添加顺序一致,可以存储重复的数据
ArrayList
底层数据结构是数组,访问快,添加,删除慢
初始化容量:10
扩容:1.5倍Vector
底层数据结构是数组,它是线程安全的,ArrayList
不是线程安全的
初始化容量:10
扩容:2倍LinkedList
底层是双向链表,访问慢,添加和删除效率高
(2)Set集合
存储特点:无序,不可重复。存储顺序与添加顺序可能不一样;不能存储重复(通过equals()
方法来判断)的数据
HashSet
- 底层是
HashMap
- 向
HashSet
添加元素就是把元素作为键添加到底层的HashMap
中
- 底层是
TreeSet
TreeSet
实现了SortedSet
接口,可以根据元素自然排序,要求集合中的元素必须是可比较的(Comparator
与Comparable
)TreeSet
底层是TreeMap
- 向
TreeSet
添加元素就是把元素作为键添加到底层的TreeMap
中
(3)Map
Map
是按<键,值>
对的形式存储数据,Map的key不允许重复
-
HashMap
- 底层是数组+链表,键与值都可以为
null
,线程不安全 - JDK8中,当链表长度超过
8
时,链表转换为红黑树;插入时,新增的结点插入到链表的尾部 - 初始化容量为
16
- 加载因子:
0.75
,当键值对的数量 > 容量*加载因子时,按2倍大小扩容 - 在创建时可以指定初始化容量,
HashMap
会把初始化容量自动调整为2
的幂次方
- 底层是数组+链表,键与值都可以为
-
CurrentHashMap
- 底层采用数组+链表+红黑树,利用
CAS+Synchronized
来保证线程安全
- 底层采用数组+链表+红黑树,利用
-
HashTable
- 底层数组+链表,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化
- 初始容量为
11
,扩容:2倍+1
2. HashMap遍历怎么遍历?
两种方式遍历:使用EntrySet遍历;使用KeySet 遍历
3. 平时什么情况下使用HashMap?
比如说读取系统参数,在服务之间传递一些键值对时使用。
4. 简单说一下什么是hash碰撞?怎么解决的?
首先根据键的哈希码,经过hash函数计算hash值,然后根据hash值计算数组下标,当下标相同时,就会出现hash碰撞。
HashMap采用链表法,将数组下标相同的键值对用链表存起来,解决了hash碰撞。
三、多线程
1. 创建线程有哪些方法(4种)?
- 继承
Thread
类,重写run
方法(其实Thread类本身也实现了Runnable接口) - 实现
Runnable
接口,重写run
方法 - 实现
Callable
接口,重写call
方法(有返回值) - 使用线程池(有返回值)
2. Runnable和Callable有什么不同?
- 最大的不同点:实现
Callable
接口的任务线程能返回执行结果;而实现Runnable
接口的任务线程不能返回结果; Callable
接口的call()
方法允许抛出异常;而Runnable
接口的run()
方法的异常只能在内部消化,不能继续上抛;Callable
接口支持返回执行结果,此时需要调用FutureTask.get()
方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
3. start()和run()方法有什么区别?
start()
方法来启动线程,而启动后的线程运行的是run()
方法中的代码。run()
方法当作普通方法的方式调用时,并不会开启新的线程。
4. 线程池有哪些参数
最常用的三个参数:
corePoolSize
:核心线程数queueCapacity
:任务队列容量(阻塞队列)maxPoolSize
:最大线程数
三个参数的作用:
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满
- 若线程数小于最大线程数,创建线程
- 若线程数等于最大线程数,抛出异常,拒绝任务
5. 线程池有几种(5种)?拒绝策略有几种(4种)?阻塞队列有几种(3种)?
五种线程池:
ExecutorService threadPool = null;
threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
threadPool = Executors.newScheduledThreadPool(2);//一个能实现定时、周期性任务的线程池
threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多
四种拒绝策略:
RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务
三种阻塞队列:
BlockingQueue<Runnable> workQueue = null;
workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界
workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,无界
workQueue = new SynchronousQueue<>();//无缓冲的等待队列,无界
6. 如何检测死锁?
利用Java自带工具JConsole
Java线程死锁查看分析方法
7. volatile底层是怎么实现的?
当一个变量定义为volatile
后,它将具备两种特性:1. 可见性,2. 禁止指令重排序。
可见性:编译器为了加快程序运行速度,对一些变量的写操作会现在寄存器或CPU缓存上进行,最后写入内存。而在这个过程中,变量的新值对其它线程是不可见的。当对volatile
标记的变量进行修改时,先当前处理器缓存行的数据写回到系统内存,然后这个写回内存的操作会使其他CPU里缓存了该内存地址的数据无效。
处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致。如果一个正在共享的状态的地址被嗅探到其他处理器打算写内存地址,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充。
8. volatile与synchronized有什么区别?
- volatile仅能使用在变量上,synchronized则可以使用在方法、类、同步代码块等等。
- volatile只能保证可见性和有序性,不能保证原子性。而synchronized都可以保证。
- volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
四、MySql
1. sql优化
- sql优化主要是对查询进行优化,应尽量避免全表扫描,首先应考虑在
where
及order by
涉及的列上建立索引 - 任何地方都不要使用
select * from t
,用具体的字段列表代替“*
”,不要返回用不到的任何字段。 - 避免在 where 子句中使用
!=
或<>
操作符,否则将引擎放弃使用索引而进行全表扫描,可以在null
上设置默认值,确保表中没有null
值。 - 复合索必须指定索引中第一个字段作为检索条件,否则不使用索引
in
和not in
也要慎用,否则会导致全表扫描。对于连续的数值,能用 between 就不要用 in 了。- 模糊查询时,以"%"开头,会导致全表扫描
2. 什么是索引
索引(Index)是帮助MySQL高效获取数据的数据结构,可以理解为一本字典的目录,提高程序的检索 和查询效率
3. 如何判断一条sql语句是否使用了索引(执行计划)
通过执行计划,可以判断本次查询中对于数据行定位是否是从索引获取的
EXPLAIN 查询语句
对于查询的评级由好到坏:const > primary(主键) > ref > range > index > all
- 平时进行SQL优化时,最低要求达到range级别,尽可能达到ref级别
4. 存储引擎
-
MyIsam:
-
使用三个文件表示每个表:
- 格式文件 — 存储表的结构(mytable.frm)
- 数据文件 — 存储表的数据(mytable.MYD)
- 索引文件 — 存储表的索引(mytable.MYI)
-
对表文件中数据行查询提速,有很大帮助。
-
灵活的
AUTO_INCREMENT
字段处理 -
可被转换为压缩、只读表来节省空间
-
但是MyIsam不支持事务,因此在进行数据行添加,修改,删除时,无法保证数据安全性
-
-
INNODB:MySQL数据库的默认引擎;
- 每个
InnoDB
表在数据库目录中以.frm
格式文件表示 InnoDB
表空间tablespace
被用于存储表的内容- 提供一组用来记录事务性活动的日志文件
- 支持事务处理
- 提供全
ACID
兼容 - 在
MySQL
服务器崩溃后提供自动恢复 - 多版本(
MVCC
)和行级锁定 - 支持外键及引用的完整性,包括级联更新和删除
- 每个
-
MEMORY:其数据存储在内存中,且行的长度固定,这两个特点使得MEMORY存储引擎非常快;
- 在数据库目录内,每个表均以
.frm
格式文件表示; - 表数据及索引被存储在内存中;
- 表级锁机制;
- 不能包含TEXT或BLOB字段;
- 在数据库目录内,每个表均以
5. 如何选择合适的存储引擎
MyISAM
表最适合于大量的数据读而少量数据更新的混合操作。MyISAM表的另一种适用情形是使用压缩的中读表。- 如果查询中包含较多的数据更新操作,应使用
InnoDB
。其行级锁机制和多版本的支持为数据读取和更新的混合提供了良好的并发机制。 - 可使用
MEMORY
存储引擎存储非永久需要的数据,或者是能够从基于磁盘的表中重新生成的数据。
6. Innodb有哪些特性?
- 插入缓冲
- 二次写
- 自适应哈希
- 预读
7. Innodb的事务锁有哪些?(4种)
行级锁:
- 共享锁(S Lock) : 允许事务读一行数据
- 排它锁(X Lock) : 允许事务删除或更新一行数据
表级锁:
- 意向共享锁(IS Lock):事务想要获得一张表中某几行的共享锁
- 意向排它锁(IX Lock):事务想要获得一张表中某几行的排它锁
由于Innodb引擎支持的均为行锁,所以意向锁其实不会阻塞除全表扫描之外的任何请求
8. 使用什么工具创建表?
使用Power Designer
来创建表
9. 表结构是怎么设计的?
- 首先,表结构的设计尽量要满足数据库三范式
- 但是还是根据实际需求进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需求。
第一范式:要求有主键,数据库中不能出现重复记录,每一个字段是原子性不能再分;
第二范式:第二范式是建立在第一范式基础之上,要求数据库中所有非主键字段完全依赖主键,不能产生部分依赖;
第三范式:建立在第二范式基础之上,要求非主键字段不能产生传递依赖于主键字段
10. Mysql事务的隔离级别
事务隔离级别 | 说明 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
读未提交(read-uncommitted) | 读取数据的事务对象,可以读取到另一个事务对象尚未提交的数据 | 是 | 是 | 是 |
不可重复读(read-committed) | 读取数据的事务对象,只能读取另一个事务对象提交过后的数据 | 否 | 是 | 是 |
可重复读(repeatable-read) (默认) |
读取数据的事务对象,在另一个事务对象提交前后读取的内容要保持一致 | 否 | 否 | 是 |
串行化(serializable) | 串行读取 | 否 | 否 | 否 |
11. 什么是脏读?什么是幻读?
-
脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
-
不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
-
幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
总结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
12. MySQL 服务占用 cpu 100%,如何排查问题?
- 一般情况下,mysql占用过高多是有慢查询,打开慢查询日志,找到执行较慢的语句。另一种方法:也可以在mysql命令行中调用
show processlist;
,查看当前 mysql 使用频繁的 sql 语句。 - 分析查询效率低的原因,一般是因为没有使用索引,要么sql优化,要么给字段加上索引。
13. 数据库集群是怎么同步的?
- 当 master 主服务器上的数据发生改变时,则将其改变写入二进制事件日志文件中
- salve 从服务器会在一定时间间隔内对 master 主服务器上的二进制日志进行探测,探测其是否发生过改变,如果探测到 master 主服务器的二进制事件日志发生了改变,则开始一个 I/O Thread 请求 master 二进制事件日志
- 同时 master 主服务器为每个 I/O Thread 启动一个dump Thread,用于向其发送二进制事件日志
- slave 从服务器将接收到的二进制事件日志保存至自己本地的中继日志文件中
- salve 从服务器将启动 SQL Thread 从中继日志中读取二进制日志,在本地重放,使得其数据和主服务器保持一致;
- 最后 I/O Thread 和 SQL Thread 将进入睡眠状态,等待下一次被唤醒
五、Redis
1. 有几种数据类型(5种)?分别是哪几种?
有5种数据类型,分别是:字符串类型,哈希类型,list,set,zset
2. 你用到了哪些数据类型?在哪儿用到的?
String类型:
- 计数:由于Redis单线程的特点,我们不用考虑并发造成计数不准的问题,通过 incrby 命令,我们可以正确的得到我们想要的结果。
- 限制次数:比如登录次数校验,错误超过三次5分钟内就不让登录了,每次登录设置key自增一次,并设置该key的过期时间为5分钟后,每次登录检查一下该key的值来进行限制登录。
Hash类型:
- 缓存一些信息
List类型:
- 可以用作栈,队列等等
Set类型:
- 利用集合的交并集特性,比如在社交领域,我们可以很方便的求出多个用户的共同好友,共同感兴趣的领域等。
Zset类型:
- 和set数据结构一样,zset也可以用于社交领域的相关业务,并且还可以利用zset 的有序特性,还可以做类似排行榜的业务。
3. redis的过期策略有哪些?
定期删除+惰性删除。
定期删除:redis
默认是每隔 100ms
就随机抽取一些设置了过期时间的 key
,检查其是否过期,如果过期就删除。定期删除可能会导致很多过期 key
到了时间并没有被删除掉,所以就使用惰性删除。
惰性删除:获取 key
的时候,如果此时 key
已经过期,就删除,不会返回任何东西。
4. 持久化
(1)RDB
Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是 dump.rdb
。 RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用。 RDB
恢复数据时比其他 AOF
速度快。
- 优点:由于存储的是数据快照文件,恢复数据很方便,也比较快
- 缺点:
- 会丢失最后一次快照以后更改的数据。 如果你的应用能容忍一定数据的丢失,那么使用 rdb 是不错的选择; 如果你不能容忍一定数据的丢失,使用 rdb 就不是一个很好的选择。
- 由于需要经常操作磁盘, RDB 会分出一个子进程。如果你的 redis 数据库很大的话,子进程占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别),如果你的数据库超级大并且你的服务器 CPU 比较弱,有可能是会达到一秒。
(2)AOF
Append-only File(AOF), Redis
每次接收到一条改变数据的命令时,它将把该命令写到一个 AOF
文件中(只记录写操作,读操作不记录),当 Redis
重启时,它通过执行 AOF
文件中所有的命令来恢复数据。
- append-only 文件是另一个可以提供完全数据保障的方案;
- AOF 文件会在操作过程中变得越来越大。比如,如果你做一百次加法计算,最后你只会在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录对最终的结果是无用的;但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小
- 可以同时使用这两种方式,redis默认优先加载 aof文件(aof数据最完整);
六、Linux
1. 什么是管道?
管道就是用“|
”连接两个命令,将前面一个命令的输出作为后面命令的输入,用于把管道左边的输出作为右边的输入。
七、Spring
1. IoC
IoC 就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI 依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖 IoC 容器来动态注入对象需要的外部资源。
2. Aop
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为 “切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。AOP 实现的关键在于 代理模式.
3. Aop在项目中用在什么地方?
Aop一般用来处理权限控制,日志记录,加载事务等非主要业务逻辑的事情。底层是采用cglib和jdk的动态代理实现的。
4. IoC和Aop有什么作用?
- IoC 这个指的就是我们获取对象的方式进行反转了。不使用IoC时,对象是需要手动new出来的,是我们主动获取的。使用IoC之后,是将这个获取的过程交给spring来管理,我们只需要告诉spring你需要什么就行了,它就会把东西给你。
- Aop 就是用来增强功能,在执行主业务的时可以顺带执行其他业务。
Sring 的AOP和IoC都是为了解决系统代码耦合度过高的问题。使代码重用度高、易于维护。
5. AspectJ的Aop和Spring的Aop有什么区别?
-
Spring AOP采用的是动态织入(运行时织入),而Aspectj是静态织入(编译时期就织入),通过修改代码来实现。
织入是指把增强应用到目标对象来创建新的代理对象的过程。
-
AspectJ由于是在编译时期就织入,故性能更优。
-
Spring AOP的通知是基于该对象是SpringBean对象才可以,而AspectJ可以在任何Java对象上应用通知。
-
Spring AOP仅支持方法切入点,而AspectJ支持所有切入点
八、SpringMVC
1. SpringMVC执行流程
- 浏览器提交请求到中央调度器
- 中央调度器直接将请求转给处理器映射器。
- 处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
- 中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
- 处理器适配器调用执行处理器。
- 处理器将处理结果及要跳转的视图封装到一个对象
ModelAndView
中,并将其返回给处理器适配器。 - 处理器适配器直接将结果返回给中央调度器。
- 中央调度器调用视图解析器,将
ModelAndView
中的视图名称封装为视图对象。 - 视图解析器将封装了的视图对象返回给中央调度器
- 中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,成响应对象。
- 中央调度器响应浏览器。
2. @RequestParam和@PathVariable
@RequestParam
:将请求参数绑定到控制器的方法参数上,同时可以给参数一些限定,比如说指定参数的默认值,是否允许参数为空等等。@PathVariable
:是将Rest
风格的请求中{}
中的值取出来
3. @ResponseBody和@RequestBody
@ResponseBody
:作用在方法上,表示该方法的返回结果直接写入响应体中,如果不使用@ResponseBody
,则返回值会解析为跳转路径。@RequestBody
:作用在形参列表上,用于将前台发送过来固定格式的数据【xml
格式或者json
等】封装为对应的JavaBean
对象,封装时使用到的一个对象是系统默认配置的HttpMessageConverter
进行解析,然后封装到形参上。
九、MyBatis
1. #{}和${}都用过吗?有什么区别?
-
#
:占位符,告诉 mybatis 使用实际的参数值代替。并使用PreparedStatement
对象执行 sql 语句,#{…}
代替sql
语句的“?
”。 可以避免SQL注入,这样做更安全,更迅速,通常也是首选做法。 -
$
:字符串替换, 告诉 mybatis 使用$
包含的“字符串
”替换所在位置。使用Statement
把sql
语句和${…}
的内容连接起来(相当于是String字符串中的+号),有SQL注入的风险。主要用在替换表名,列名,不同列排序等操作。
2. 模糊查询怎么使用?
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select * from student where name like "%" #{name} "%"
</select>
3. 动态查询的sql怎么写?
十、SpringBoot
1. SpringBoot配置文件加载顺序
相同目录下,application.properties
文件的优先级大于application.yml
。
不同目录下的配置文件优先级从高到低顺序:(高优先级配置会覆盖低优先级配置,多个配置文件互补)
file:./config/
- 优先级最高(项目根路径下的config)file:./
- 优先级第二 -(项目根路径下)classpath:/config/
- 优先级第三(项目resources/config下)classpath:/
- 优先级第四(项目resources根目录)
十一、RabbitMQ
1. RabbitMQ使用场景
- 服务间异步通信
- 请求削峰
- 解耦
十二、其它
1. 简单说一下http请求四次挥手的过程?
2. maven配置文件有哪些主要的元素?
3. 了解哪些设计模式?具体说说其中的某个?
自我介绍+项目介绍(你用了那些技术,项目用了哪些技术)
还有什么想问的
- 工作地点
- 岗位职责
- 多久会有回复