1、 解决跨域的几种方案?
Spring Boot 中给我们提供了一个注解 @CrossOrigin 来实现跨域
这里可以通过实现 WebMvcConfigurer 接口中的 addCorsMappings() 方法来实现跨域。
Nginx 配置解决跨域问题
crosFIlter
2、上万个用户请求,服务器如何区分.
①当浏览器首次访问服务器时,服务器会为客户端创建一个session(每个用户独有的房间,用来存放这个对象的相关信息和内容),并通过特殊算法算出一个sessionID(类似于双方都知道的唯一暗号),用来标识该session对象。
②当浏览器再次(session还在有效时间内)向服务器请求资源的时候,浏览器将sessionID和请求内容一起发送到服务端。服务端通过对比自身存储的sessionId来判断用户之前是否存在,并返回对应的内容给不同用户。
③因为标识符存在内存里,所以当浏览器关闭时,浏览器保存的sessionId就会消失。服务器将匹配失败,默认为此请求是新用户提出的,如上文顺序,重新创建一个session容器,和相应的唯一sessionId,返回给浏览器。
事务的四大特性?
原子性:要么都成功,要么都失败
一致性:一个事务在执行之前和执行之后,数据库都必须处以一致性状态
隔离性:一个事务的执行不能被其它事务干扰。
持久性:事务的持久性是指事务一旦提交后,数据库中的数据必须被永久的保存下来
3. 事务的隔离级别详解?
读未提交(read uncommitted): 一个事务还没有提交时,它做的变更就能被别的事务看到。
解释:(一个事务在写数据时,不允许另外一个事务进行写操作,但允许读操作。这样避免了更新丢失,却可能出现脏读,也就是说(事务A读到了事务B未提交的数据, 事务B修改了内容后,又进行了回滚,那么此时事务A读取到的数据就成为了脏数据)。)
读已提交(read committed): 执行两次同意的查询却有不同的结果,也叫不可重复读。
解释:(写事务提交之前不允许其他事务的读操作,可以解决脏读问题。但会出现一个事务范围内两个相同的查询却返回了不同数据(事务A,读取了数据后,事务B修改了数据并进行了提交,那么此时事务A再次读取时,就会出现数据不一致的情况),这就是不可重复读。)
可重复读(repeatable read):能确保同一事务多次读取同一数据的结果是一致的
解释:(在开始读取数据(事务开启)时,不再允许修改操作,这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,但是有时可能会出现幻读。
(事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。)
可串行化(Serializable):是最高的隔离级别。强制事务串行执行,会在读取的每一行数据上加锁,这样虽然能避免幻读的问题,但也可能导致大量的超时和锁争用的问题。很少会应用到这种级别,只有在非常需要确保数据的一致性且可以接受没有并发的应用场景下才会考虑。.
解释:(幻读:幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。
4、Cookie和Session区别:
2.1)存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端
2.2)安全性:Cookie不安全,Session安全
2.3)数据大小:Cookie最大3KB,Session无大小限制
2.4)存储时间:Cookie可以长期存储,Session默认30分钟
2.5)服务器性能:Cookie不占服务器资源,Session占用服务器资源
5、TCP和UDP的区别?
tcp是面向连接的,udp是无连接的,即发送数据之前不需要建立连接
tcp传输数据是无差错、不丢失、不重复,且按顺序到达,
udp尽最大努力的传输,可能会造成数据的丢失
BS:浏览器和服务器
CS:客户端和服务器
6、#和$的区别
#{}是预编译处理 是占位符,${}字符串的替换,拼接符
7、&和&&的区别?
&&只要有一个条件不一样就是不满足,如果第一个条件就是不满足就不判断后面的条件。
而&要对所有的条件都进行判断。 概念的不同
8、== 和 equals 的区别是什么?
1、equals():用来检测两个对象是否相等,即两个对象的内容是否相等。
2、==:用于比较引用和比较基本数据类型时具有不同的功能
(1)、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
(2)、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
9、springboot的两个核心配置文件
1.bootstrap (.yml或.properties)
2.application(.yml或.properties)
bootstrap 加载优先于 applicaton
10、springboot的核心注解
1.@SpringBootApplication用来开启 Spring Boot 的各项能力
2.@EnableAutoConfiguration允许 Spring Boot 自动配置注解,
3.@SpringBootConfiguration修饰是 Spring Boot 配置而已
4.@Configuration定义配置类
5.@ComponentScan包扫描
6.@Component实例化
11、AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。
12、ArrayList,LinkedList和Vector都继承自List接口。ArrayList和Vector的底层是动态数组查询效率高,LinkedList的底层是双向链表插入删除的效率高
ArrayList和Vector的区别就是ArrayList是线程不安全的,Vector是线程安全的,Vector中的方法都是同步方法(synchronized),所以ArrayList的执行效率要高于Vector,
13、StringBuffer和StringBuilder 区别简述
StringBuffer线程安全,因为StringBuffer类中的办法都增加了synchronized关键字
StringBuilder 线程不安全
14、线程安全?
在多个线程去访问某个方法或对象的时候,不管通过任何的方式的调用或者线程如何交替执行,在程序中不做任何同步干预的情况
这个方法或者对象的执行或者修改,都能按照预期的结果来反馈,那么这个类我们认为它是线程安全的。线程安全问题的具体表现有三个方面,原子性、有序性、可见性
原子性:一个不可再被分割的颗粒。原子性指的是一个或多个操作要么全部执行成功要么全部执行失败。
有序性: 程序执行的顺序按照代码的先后顺序执行。(处理器可能会对指令进行重排序)
可见性: 一个县城对共享变量的修改,另一个线程能够立刻看到。
15、导致线程不安全的原因
1.线程争抢,抢占式执行。
2.多个线程同时修改了同一个变量。
3.操作非原子性操作。
4.内存可见性问题。
5.指令重排序。
16、解决线程安全问题的方法
1.volatile解决指令重排序问题和内存可见性问题
2.使用锁解决线程安全问题
内置锁synchroned
(1)修饰静态方法
(2)修饰普通方法
(3)修饰代码块
lock()锁
1、首先二者的关键字不同,sync是关键字,lock是接口。
2,sync会主动释放锁,lock不会,而且容易产生死锁。
3,sync默认是非公平锁,悲观锁。Lock用的是乐观锁方式,乐观锁实现的机制就是CAS操作
17、单例模式
饿汉式(线程安全)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
懒汉式(线程不安全)
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
18、shiro认证流程
首先通过前端页面的账号密码提交,在Controller
请求处理层获取了前端的账号密码,然后获取当前用户的Subject对象,执行了Subject的login方法进行登录操作,
并将账号密码封装进Token对象,作为参数传入。而后面设置了认证需要的Realm类,该Realm类继承了AuthenticatingRealm父类,
实现了doGetAuthenticationInfo方法,在doGetAuthenticationInfo方法中获取用户的账号密码,在做完一些校验后,
传递给了SimpleAuthenticationInfo,并返回出去:
优化后:
(获取前端传入的账号和密码,并封装成token,传入subject.login(token) 提交给security manage。security manage
会把它委托给Authenticator,然后通过modularRealmAuthenticator进行身份验证,Authenticator会把相应的token传入
relam,获取身份验证的信息,如果没有返回或抛出异常,表示身份验证失败。
)
19、数组转为list:Arrays.asList(arr)
list转为数组:list.toArray()
数组转为字符串:1、new strBuilder().append() 2、stringutils.join
20、springmvc的流程
用户发送请求到前端控制器中,前端控制器根据用户请求的controller找到对应的rquestMapper,将处理后的数据返回给前端控制器,前端控制器把数据返回给视图层,视图层通过渲染后,返回给前端控制器
前端控制器在响应给用户。
21、java8的新特性
接口支持定义默认实现方法
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
22、jvm运行过程:
我们都知道Java源文件,通过编译器,能够生产相应的.Class文件,也就是字节码文件,而字节码文件又通过Java虚拟机中的解释器编译成特定机器上的机器码 。
23、java多线程的实现的四种方式.
1.继承Thread类,重写run方法
2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
3.通过Callable和FutureTask重写call方法
4.通过线程池创建线程
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
24、start() 和run()的区别?
1.start() 可以创建一个新线程,run()不能
2.start()不能被重复调用,run()可以
3.start()中的run代码可以不执行完就继续执行下面的代码,即进行了线程切换。直接调用run方法必须等待其代码全部执行完才能继续执行下面的代码。
4.start() 实现了多线程,run()没有实现多线程。
25、多线程的特性
原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
可见性:是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
有序性:即程序执行的顺序按照代码的先后顺序执行。
26、springcloud的组件
我们这个因为服务有很多个,那么有可能随时增加,这个时候我们需要一个注册中心eureka,把它管理起来。然后通过注册中心可以找到这些东西,然后我们怎么去调用又会用到feign,然后要去做负载均衡又会用到ribbon,最后服务可能会崩,就需要做服务熔断、降级隔离的东西这些东西又会用到hytrix。对配置文件的统一管理就会用到这个configsever
27、Token的定义?
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。
28、spring的好处?
1)方便解耦,简化开发
Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理。
2)方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持。
3)降低 Java EE API 的使用难度
Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。
4)方便程序的测试
Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序。
5)AOP 编程的支持
Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。
6)声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无须手动编程。
29、@Autowired由Spring提供,只按照byType注入
@Resource,默认按照名称进行装配,当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
30、redis为什么快?
1、redis 基于内存,所以速度比较快。
2、使用单线程可以省去多线程时CPU上下文会切换的时间,也不用去考虑各种锁的问题,不存在加锁释放锁操作,没有死锁问题导致的性能消耗。对于内存系统来说,多次读写都是在一个CPU上,没有上下文切换效率就是最高的
3、多路I/O复用技术可以让单个线程高效的处理多个连接请求
31、产生死锁的必要条件:
互斥条件: 进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
请求和保持条件: 当进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件: 进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
环路等待条件: 在发生死锁时,必然存在一个进程–资源的环形链。
32、hashmap
hashmap1.7 底层是数组+链表,1.8之后是数组+链表+红黑树
hashmap的扩容机制是2n ,hashtable是2n+1
hashmap的不安全的,concurrenthashmap是安全的,hashtable是安全的
当前链表长度超过8并且数组长度超过64才会转红黑树,如果数组长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树,以减少搜索时间。
33、mybatis的缓存
一级缓存是SqlSession级别的缓存:不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的(默认是开启的)。
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存的作用范围更大(cache)。
34、RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的,消息中间件;
可以用它来:解耦、异步、削峰。
35、Mybaits的优点:
(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响, SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态 SQL语句,并可重用。
(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的 数据库MyBatis都支持)。
(4)能够与Spring很好的集成;
(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
MyBatis框架的缺点:
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功 底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
MyBatis框架适用场合:
(1)MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
(2)对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选 择。
36、#{}是预编译处理,$ {}是字符串替换。
37、mybatis 一对一关联查询需要在resultmap里面配置association,一对多关联查询需要在resultmap 里面配置conllention节点
38、Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指 的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用 延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
39、Mybatis 提供了 9 种动态 sql 标签:
trim|where|set|foreach|if|choose|when|otherwise|bind。
Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。
40、MyBatis 是如何进行分页的?分页插件的原理是什 么?
mybatis是使用分页插件PageHelper进行分页的, 其原理就是底层通过拦截器,进行拦截,然后根据传入的参数拼接sql中的limit,达到分页的效果。
41、SQL优化
1、查询语句中不要使用select *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union
all会更好)
5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫
描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null
值,然后这样查询: select id from t where num=0
42、索引分类
主键索引、唯一索引、普通索引、联合索引、全文索引
43、 简述MyISAM和InnoDB储存引擎的区别
MyISAM:不支持事务;支持表锁;支持全文索引;count()有变量存储,无需查全表;非聚簇索引
InnoDB:支持事务;支持行级锁;聚簇索引;
44、索引失效
查询条件包含or,可能导致索引失效
如何字段类型是字符串,where时一定用引号括起来,否则索引失效
like通配符可能导致索引失效。
联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
在索引列上使用mysql的内置函数,索引失效。
对索引列运算(如,+、-、*、/),索引失效。
索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
索引字段上使用is null, is not null,可能导致索引失效。