整理一下自己所经历的高频面试题目。对于一个初级java开发人员的面试,面试时间一般为30~40分钟,有短点的,先写一张笔试卷子,然后面试20分钟,也有长一些的,我最长的一次面试将近2个小时,最后一轮纯技术面,看见面试官在一张纸上记上一个个知识点,问的很细。也有的公司会机试,但很少。像这样很仔细的面试官,会提前在纸上写上各个知识点,挨个问,然后根据你的情况在后面打勾或叉(这一般是稍大一点的公司,一个面试官一早上要面试很多人的那种)。所以要想面试顺利,是需要每点知识都会一些的,而且很多题目都很固定,如果你已经没有时间去梳理各个知识点,刷一下面试题也是可以突击一下的。
说具体的问题,知识点:Java基础,面向对象,IO流,集合,多线程,Servlet,JSP,框架,数据库,都会涉及一点。HTML,CSS,js,jQuery,jdk,服务器,开发工具,这几个较少但也会出现,我在下面都会介绍到。先来个高频的,基本每次都会出现其中一个,经常问的生命周期,运行流程之类(特别注意,很高频!)
- Servlet的运行原理
- JDBC连接数据库的步骤
- Hibernate的运行原理(可从读取hibernate.cfg.xml文件说起)
- Spring中bean的生命周期
- struts2或Spring MVC的工作原理
- 线程的生命周期(从线程创建,进入线程池,等等等到最后死亡。)
参考:
1.Servlet的运行原理,这里分为三个阶段来说
初始化阶段:servlet容器接收到客户端的Http请求后,会创建一个HttpRequest对象和HttpResponse对象并将请求参数封装到request对象中,然后servlert容器由请求url中的地址通过web.xml中servlet的配置查找该请求对应的servlet类,如果该servlet还没有被实例化过,servlet容器就实例化该servlet调用它的init()方法(servlet是单例,这个过程只有一次)。
响应请求阶段:初始化后,servlet容器调用这个servlet的service()方法,并将之前的request对象和response对象作为参数传入来处理请求,并将处理好的结果封装到response对象中返回给客户端。
销毁阶段:当这个servlet的所有service()方法都结束时,servlet容器就会调用它的destroy()方法来销毁这个servlet,释放它所占用的资源。
2.JDBC连接数据库的步骤(这里说一下连接mysql数据库)
a.加载驱动程序。Class.forName("com.mysql.jdbc.Driver")。
b.建立数据库连接。通过DriverManager类的getConnection方法获取连接对象,同时要传入连接路径作参数,路径里包括我的数据库名称“myTest”,用户名,密码还有编码。
c.创建数据库操作对象Statement,用连接对象的createStatement()方法。servlet容器就会调用它的destroy()方法来销毁这个servlet,释放它所占用的资源。
d.调用statement执行sql。
e.关闭资源,关闭连接。
//加载驱动类
Class.forName("com.mysql.jdbc.Driver");
//连接路径
String url="jdbc:mysql://localhost:3306/myTest?user=root&password=root&useUnicod=true&characterEcoding=UTF8";
connection= (Connection) DriverManager.getConnection(url);
//创建数据库操作对象Statement
statement = connection.createStatement();
//调用Statement对象执行对应的sql语句
String sql="select * from a_student";
rs = statement.executeQuery(sql);
//关闭结果对象rs,关闭数据库操作对象,关闭连接
3.Hibernate的运行原理
a.创建Configuration对象,读取并解析Hibernate.cfg.xml配置文件,并根据配置中的mapping配置读取并解析实体类相对应的映射
Configuration config = new Configuration().configure();
b.创建SessionFactory对象
SessionFactory sf = config.buildSessionFactory();
c.打开Session
Session session = sf.openSession();
d.创建并启动事务
Transaction tx = session.beginTransaction();
e.持久化操作
f.提交事务
tx.commit();
g.关闭Session,关闭SessionFactory
4.Spring中bean的生命周期(scope=singleton)
a. Spring对bean进行实例化
b. bean的属性注入
c. 若bean实现了一些接口。
spring将调用它们的方法。BeanNameAware接口,调用setBeanName(String beanId),beanId是bean的id。如BeanFactoryAware接口,可以获取Spring容器,获得其它bean。ApplicationContextAware这个接口,和上一个接口功能类似,可以获得其它bean。如果想对bean再进行一些修改,实现BeanPostProcessor接口,它的两个函数postProcessBeforeInitialzation( Object bean, String beanName ) 和 postProcessAfterInitialzation( Object bean, String beanName ) 分别是在InitialzationBean接口之前和之后执行,所以又叫做bean的前置处理和后置处理。前置处理后 InitializingBean这个接口,执行afterPropertiesSet函数。
d.如果这个bean配置了init-method属性,那么调用它所对应配置的初始化方法
e.如c,若实现了postProcessBeforeInitialzation接口,执行它的后置处理
f.以上一个完整可用的singleton的bean生成,直到它不再被需要,待清理的时候,如果它实现了DisposableBean接口, spring将调用它实现的destroy()方法。如果该bean配置了destroy-method元素,则调用该元素所对应配置的方法,这 两种功能其实一样。
5.struts2的工作原理
a.客户端发来一个Http请求
b.通过web.xml配置执行一系列过滤器和核心过滤器StrutsPrepareAndExecuteFilter(struts2版本不同,核心过滤器不同,struts的版本>= 2.1.3都用这个,低于这个版本用FilterDiapatcher)
c.核心过滤器询问ActionMapper来决定这个请求是否需要调用某个Action,若决定调用某个Action,核心过滤器将请求交给ActionProxy
d.ActionProxy通过配置文件获取Action类,然后ActionProxy创建一个Actionvocation实例。
e.ActionInvocation完成请求的拦截和相应的Action中方法的执行,并根据struts.xml中的配置返回结果到相应的jsp页面或Action。
6.线程的生命周期:为了更好的描述线程的生命周期普遍把线程分为几个状态:线程的创建,等待,运行,阻塞和死亡(和官方源码上的状态稍有不同)
创建:new一个Thread类或者它的子类,创建一个新线程
等待就绪:新的线程调用它的start()方法启动线程进入等待队列,但是CPU对线程的调度是随机的,所以此时线程处于等待状态,等待系统对其分配CPU。不能对已经启动的线程再调用start()方法,否则将抛出IllegalThreadStateException。
运行:等待状态的线程获得了CPU的使用权进入运行状态,线程就会执行run方法中的任务,但是此刻的线程稍较复杂,它可以再进入等待队列或变成阻塞状态或死亡。比如该线程失去了CPU的使用权,那么它就会再进入等待队列,等待系统的调度。也可以在运行时调用了sleep()方法,那么它将变为阻塞状态。当线程的run()方法执行完或者被强制的终止,那么线程进入死亡状态。
阻塞:运行中的线程出现下列几种情况是进入阻塞状态,该状态线程停止运行且不能进入等待队列。
a.该线程调用了sleep()方法,该方法执行完后,即睡眠时间到后,线程又可进入等待队列
b.Object对象调用了wait()方法,该方法执行后,只有其它线程中的对象调用了notify/notifyAll方法后,该线程才可进入等待队列
c.线程加入——join()方法,比如将B线程作为参数传入A线程,启动A线程,并调用A线程的join()方法a.join(),则A线程进入阻塞状态,当B线程运行完或一定时间后A再进入可执行状态。(这个实现的原理其实就是b中所述,启动A线程并调用join()方法时相当于在A线程中调用了wait方法,当到达一定时间或着B执行完后会自动调用自身的notify方法唤醒A线程)
死亡:线程的run()方法执行完,线程自然死亡,不能复生。
一.基础
1.Java的几种数据类型