1.JDK1.8的新特性有哪些
速度更快 – 红黑树
代码更少 – Lambda
强大的Stream API – Stream
便于并行 – Parallel
最大化减少空指针异常 – Optional
1.Lambda表达式
2.新的日期API:发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作
原因:
- java.util.Date 是非线程安全的
- 时区处理麻烦
- 设计很差:java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期
3.Base64编码:
- base64是网络上最常见的用于传输8bit字节代码的编码方式之一。有时我们需要把二进制数据编码为适合放在URL中的形式。这时采用base64编码具有不可读性,即所编码的数据不会被人直接看出。
- 用于在http环境下传递较长的标识信息。
4.接口的默认方法和静态方法:
允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法
代码实现5.并行流:
- Fork/Join框架:
在必要的情况下,将一个大任务进行必要的拆分Fork成若干个小任务,再将小任务的运算结果进行Join汇总。- Fork/Join框架和传统线程池的区别:
采用“工作窃取”模式(Working-stealing),即当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中- 并行流将会充分使用多核的优势,多线程并行执行,基数越大,效果越明显。其底层还是Fork/Join框架
6.Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。
2.实现多线程的几种方法
- 1.继承Thread类
- 2.实现Runnable接口
- 3.直接在函数体使用(匿名内部类)
实现RunnabLe接口创建多线程程序的好处:
- 避免了单继承的局限性
一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
实现了RunnabLe接口,还可以继承其他的类,实现其他的接口- 增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用start方法:用来开启新线程
3.数据结构
4.MySQL数据库
5.SSM项目有什么大坑,怎么解决的
6.Spring的AOP一般用来干嘛
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
- 采用filter技术对字符集进行处理
- 日志记录
- 性能统计
- 安全控制
- 事务处理
- 异常处理
实现AOP的几种方式
1.方式一
<!--方式一:使用原生Spring API接口-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
<!--切入点 expression:表达式 ,execution(要执行的位置! * * * * )-->
<aop:pointcut id="pointcut" expression="execution(* com.whz.service.UserServiceImp.*(..))"/>
<!--执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
<!--注册bean-->
<bean id="userServiceImp" class="com.whz.service.UserServiceImp"></bean>
<bean id="log" class="com.whz.log.Log"></bean>
<bean id="afterLog" class="com.whz.log.AfterLog"></bean>
public class Log implements MethodBeforeAdvice {
/*method:要执行的目标对象的方法
args:参数
target:目标对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了 ");
}
}
public class AfterLog implements AfterReturningAdvice {
//
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue);
}
}
2.方式二
<!--方式二:自定义类-->
<bean id="diy" class="com.whz.diy.DiyPointCut"></bean>
<aop:config>
<!--自定义切面,ref要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImp.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
public class DiyPointCut {
public void before(){
System.out.println("==========之前=========");
}
public void after(){
System.out.println("==========之后=========");
}
}
3.方式三
<!--方式三:注解-->
<bean id="annotationPointCut" class="com.whz.diy.AnnotationPointCut"/>
//方式三:使用注解实现aop
@Aspect//标注这个类是个切面
public class AnnotationPointCut {
@Before("execution(* com.whz.service.UserServiceImp.*(..))")
public void before(){
System.out.println("++++++++++before++++++++++++");
}
@After("execution(* com.whz.service.UserServiceImp.*(..))")
public void after(){
System.out.println("++++++++++after++++++++++++");
}
}
4.Test
//测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口
UserService userService = (UserService) context.getBean("userServiceImp");
userService.delete();
userService.add();
}
}
7.MySQL的左外连接的执行顺序
左外连接和右外连接查询:
(1) 左外连接查询:是将左边表中所有数据都查询出来, 如果在右边表中没有对应的记录, 右边表显示为null即可。
以左侧表为主,不管on条件是否满足条件,左侧表的所有记录都会返回。
换句说:on and后面的条件对左侧表没有过滤作用,即使加上对左侧表的过滤,也不起作用
on后面的条件对右侧表的过滤起作用。where条件则对左连接后的临时表数据进行筛选。
(2) 右外连接查询:是将右边表中所有数据都查询出来, 如果在左边表中没有对应的记录, 左边表显示为null即可。
where和having都用于筛选过滤,但是:
(1) where用于在分组之前进行筛选, having用于在分组之后进行筛选
(2) 并且where中不能使用列别名, having中可以使用别名
(3) where子句中不能使用列别名(可以使用表别名), 因为where子句比select先执行
SQL语句的书写顺序和执行顺序:
SQL语句的书写顺序:
select…
from…
where…
group by…
order by…
…
SQL语句的执行顺序:
from… – 确定要查询的是哪张表 (定义表别名)
where… – 从整张表的数据中进行筛选过滤
group by… – 根据指定的列进行分组
select… – 确定要显示哪些列 (定义列别名)
order by… – 根据指定的列进行排序
8.JDK实现动态代理
1、为接口创建代理类的字节码文件
2、使用ClassLoader将字节码文件加载到JVM
3、创建代理类实例对象,执行对象的目标方法
结合源码分析,JDK如何实现动态代理
9.Spring 的事务及实现
事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性
事务有四个特性:ACID
- 原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
- 一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
- 隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
- 持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
10.Session和Cookie的区别
- cookie数据保存在客户端,session数据保存在服务器端
- 存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。- 存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。- 隐私策略不同
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。- 有效期上不同
开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。- 服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。- 浏览器支持不同
假如客户端浏览器不支持cookie:
cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
假如客户端支持cookie:
cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
session只能在本窗口以及子窗口内有效。- 跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问
11.常用的日志框架
- Log4J:日志大炮
Log4J 是 Apache 的一个日志开源框架,有多个分级(DEBUG/INFO/WARN/ERROR)记录级别,可以很好地将不同日志级别的日志分开记录,极大地方便了日志的查看。- LogBack:日志火箭
LogBack 其实可以说是 Log4J 的进化版,因为它们两个都是同一个人(Ceki Gülcü)设计的开源日志组件。LogBack 除了具备 Log4j 的所有优点之外,还解决了 Log4J 不能使用占位符的问题。
12.从输入URL到整个网页加载完毕及显示在屏幕上的整个流程
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互
10、客户端和服务器交互
11、ajax查询