第三次面试

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的区别

  1. cookie数据保存在客户端,session数据保存在服务器端
  2. 存储容量不同
    单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
    对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
  3. 存储方式不同
    cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
    session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
  4. 隐私策略不同
    cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
    session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
  5. 有效期上不同
    开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
    session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。
  6. 服务器压力不同
    cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
    session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
  7. 浏览器支持不同
    假如客户端浏览器不支持cookie:
    cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
    运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
    假如客户端支持cookie:
    cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
    session只能在本窗口以及子窗口内有效。
  8. 跨域支持上不同
    cookie支持跨域名访问。
    session不支持跨域名访问

用cookie和session实现登录功能

11.常用的日志框架

  1. Log4J:日志大炮
    Log4J 是 Apache 的一个日志开源框架,有多个分级(DEBUG/INFO/WARN/ERROR)记录级别,可以很好地将不同日志级别的日志分开记录,极大地方便了日志的查看。
  2. 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查询

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值