Java面试题集
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试题集相关的知识,希望对你有一定的参考价值。
三、开源框架
什么是mybaties?
Mybaties是支持普通sql查询,存储过程和高级映射的优秀持久层框架。Mybaties消除了几乎所有的jdbc代码和参数的手工设置以及结果集的检索。Mybaties使用简单的xml或注解用于配置和原始映射,将接口和Java的pojos(Plan Old Java Objects 普通的Java对象)映射成数据库中的记录。
Mybaties的动态sql语句是基于ognl表达式的,可以方便的在sql语句中实现某些逻辑,总体来说mybaties动态sql语句主要有以下几类:
1:if语句(简单的条件判断)
2:choose(when otherwise),相当于Java语言中的switch与jstl中的choose很类似。
3:trim(where,set,对包含的内容加上prexif或者suffix等,前缀后缀)
4:where(主要是用来简化sql语句中where条件判断,能只能的处理and ,or,不必担心多余导致语法报错)
5:set(主要用于更新操作)
6:foreach 主要用在构建in条件中,它可以在sql语句中进行迭代一个集合。Foreach元素的属性主要有item,index,collector,open,separator,close.
Item表示集合中每一个元素进行迭代时的别名;
Index指定一个名字,用于表示在迭代过程中,每次迭代到的位置;
Open表示该语句以什么开始;
Separator表示在每次进行迭代之间以什么符号作为分隔符;
Close表示该语句以什么结束。
注意:collector 若是list则为list,若为数组则为array,默认为map
Mybaties与hibernate的区别?
相对于hibernate的O/R而言,mybaties是一种“sql mapping”的ORM实现。
Hibernate对数据库结构提供了较为完整的封装,hibernate的o/r mapping实现了pojo和数据库之间的映射,以及sql的自动生成和执行。程序员往往只需定义好pojo到数据库表的映射关系,即可通过hibernate提供的办法完成持久层操作。程序员甚至不需要对sql熟练掌握,hibernate会根据制定的存储逻辑,自动生成对应的sql并调用jdbc接口加以执行。
而mybaties着力点则在于pojo与sql之间的映射关系。也就是说mybaties并不会为程序员在运行期间自动执行生成sql执行,具体的sql语句需要程序员自己写,然后通过映射配置文件,将sql所需的参数以及返回的结果字段映射到指定pojo。
Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句,而mybatis 需要我们自己在xml配置文件中写sql语句,hibernate要比ibatis功能负责和强大很多。因为hibernate自动生成sql语句,我们 无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成,但是对于特别复杂的查 询,hibernate就很难适应了,这时候用mybatis就是不错的选择,因为mybatis还是由我们自己写sql语句。
springMVC工作原理(重点)
在整个springMVC框架中,dispatcherServlet处于核心位置,负责协调和组织不同组件以完成请求处理并返回响应工作
1.客户端发送一个请求匹配dispatcherServlet的请求映射路径(web.xml),web容器将该请求转交给dispatcherServlet处理。
2.dispatcherServlet接收到请求后,将请求信息(包括url,http,请求头,请求参数,cook等)以及HandlerMapping的配置找到处理请求的处理器Handler
3.dispatcherServlet根据HandlerMapping得到对应请求的Handler后,通过HandlerAdapter对Handler进行封装,再以统一的适配器接口调用Handler。
4.处理器完成业务逻辑的处理后将返回一个ModelAndView给dispatcherServlet,ModelAndView包含视图逻辑名和模型数据信息。
5.dispatcherServlet借助ViewResoler完成逻辑视图名到真实视图对象的解析。
6.得到真实视图对象后,dispatcherServlet使用这个view对ModelAndView中的模型数据进行视图渲染。
SpringMVC注解
[email protected](value="url请求地址")写在类的上面,表示该类的url请求地址
[email protected](value="请求路径",method={RequestMethod.GET})写在方法的上面,方法的路径。
[email protected] 绑定单个请求数据,可以是url中的数据,表单提交的数据或者上传的文件。
[email protected] 用来返回数据给客户端。例如:
@ResponseBody
@RequestMapping(value = "/getGoodsByType", method = RequestMethod.POST)
public ResultModel<Goods> getGoodsByType(@RequestParam int typeId) {
return “modelresult”
}
[email protected] 用来处理Content-type不是application/x-www-form-urlencoded编码的内容,例如application/json ,application/xml等。
[email protected] 绑定url模板变量值,@PathVariable(value="id")Integer id这里value值必须和请求参数一致。
[email protected] 绑定数据到Model
[email protected] 绑定数据到session
[email protected] 绑定multipart/data数据,并可以根据类型进行对象转换。
[email protected] 绑定请求头数据
[email protected] 绑定Cookie数据
Springmvc常用标签?
首先在jsp页面引入springmvc标签标识符
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
form标签:<form:form modelAttribute=”contentModel” method=”post”>
input标签:<form:input path=”username”>
password标签:<form:password path=”password”>
checkbox标签:
<form:checkbox path=”selectArray” value=${contentModel.testArray}>
SpringMVC与Struts2比较(重点)
1.springmvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,一个方法对应一个request上下文,而方法同时又跟一个url对应,而struts2是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入,struts2中一个Action对象对应一个request上下文,struts2中action一个方法对应一个url,但是其类的属性被所有方法所共享。
2.springmvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,方法之间不共享变量。而struts2虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码读程序时带来麻烦。
3.springmvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便只需一个注解@ResponseBody然后直接返回响应文本即可,如下:
@RequestMapping(value=“/whitelists”) public String index(ModelMap map) { Account account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId()); List groupList = groupManager.findAllGroup(account.getId()); map.put(“account”, account); map.put(“groupList”, groupList); return “/group/group-index”; } // @ResponseBody ajax响应,处理Ajax请求也很方便
Spring最核心的2点:IOC和AOP(重点)
Spring是一个轻量级的控制反转和面向切面的容器框架。
IOC(控制反转也称为 DI依赖注入):一个对象依赖的其对象通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象,spring容器初始化时就将依赖传递给对象。
IOC(控制反转):获得依赖对象被反转,即获得依赖对象的过程由自身管理变为由IOC容器主动注入。依赖注入就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象中。
一个对象依赖的其他对象通过被动的方式传递过来,而不是这个对象自己创建或者查找依赖对象,容器在对象初始化时不等对象请求就主动将依赖传递给它。
AOP:面向方面编程。能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例持久化管理,事务管理、日志管理、权限控制,调试管理等封装起来,便于减少系统的重复代码,降低模块间的耦合度,提高开发和调试效率
Spring的目的就是让对象与对象之间的关系没有通过代码来关联,都是通过配置类说明管理的(spring根据配置,内部通过反射去动态组装对象)。
项目中如何体现spring的AOP和IOC的?
项目中体现AOP:
主要是横切一个关注点,将一个关注点模块化成一个切面,在切面上声明一个通知(Advice)和切入点。通知中定义了要插入的方法,切入点内容是一个表达式,以描述需要在哪些对象的哪些方法上插入通知定义的方法。
项目中用到的spring中的切面编程最多的地方是声明式事务管理。
1.定义一个事务管理
2.配置事务特性(相当于声明通知,一般在业务层的类的一些方法上定义事务)
3.配置哪些类的哪些方法需要配置事务(相当于切入点,一般在业务类的方法上)
例如:
1.注解方式配置事务
@AspectJ风格的切面可以通过@Compenent注解标识其为Spring管理Bean,而@Aspect注解不能被Spring自动识别并注册为Bean,
必须通过@Component注解来完成,如下:
2.拦截方式配置事务(在spring-hibernate.xml中配置)
Spring的声明式事务配置:
首先配置sessionfactory
<bean id=”sessionFactory” class=”org.springframework.orm.hibernate4.LocalSessionFactoryBean”>
<property name=”configLocation”>
<value>/WEB/INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
然后配置事务管理器
<bean id=”transactionManager” class=”org.springframework.orm.hibernate4.HibernateTransactionManager”>
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
配置事务特征
-
<tx:advice id=”txAdvice” transaction-manager=”transactionManager”> <tx:attributes> <tx:method:nametx:method:name=”add.*” progagation=”REQUIRED”> <tx:method:nametx:method:name=”update.*” progagation=”SUPPORTS”> <tx:method name="delete*" rollback-for="Exception" /> </tx:attributes> </tx:advice>
配置哪些类的哪些方法配置事务
<aop:config> <aop:pointcut id=”transactionPoitcut”expression=”execution(*.com.ftsc.service.impl.*.*(..))”/> <aop:advisor advice-ref=”txAdvice”pointcut-ref=”transactiomPointcut”> </aop:config>
Spring的传播机制:progagation定义了7个事务传播机制。
REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务
SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行,但是对于事务同步的事务管理器,supports与不使用有少许不同。
REQUIRES_NEW:总是开启一个新的事务如果一个事务已经存在,则将当前事务挂起
NOT_SUPPORTED:总是非事务执行,并挂起任务存在的事务
NEVER:总是非事务的执行,如果存在一个活动事务,则抛出异常
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动事务,则按
TransactionDefinition.PROPAGATION_REQUIRED属性执行
注:嵌套事务一个非常的概念及时内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
项目中体现IOC:
例如spring整合struts,让spring的IOC容器管理struts2的action
首先在web.xml中引入struts配置文件如struts的过滤器,spring的配置文件如:
启动IOC容器的listener:
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
spring整合struts的插件struts-spring-plugin,该插件包的作用是:覆盖struts的objectFactory来增强核心框架对象的创建,当创建一个对象的时候,它会用struts配置文件的class属性去和spring配置文件中的id属性进行关联,如果能找到,则由spring创建,否则由struts框架自身创建,然后由spring来装配
接着在spring的配置文件中配置struts的action实例,(注意需要配置scope属性为prototype,因为struts的action是单例,这是为了解决线程安全问题。)在struts配置文件中配置action,但其class属性不再指向该action的实现类,而是指向spring容器中action实例的ID
Spring依赖注入方式?
spring注入有3中方法:属性名称,setter方法,构造方法
开发中主要使用spring的什么技术?
1.IOC容器管理各层组件
2.使用aop配置事务
3.整合其他框架
Spring注解?
@Component:通用注解,可用于任何bean
@Repository:通常用于注解dao类,即持久层
@Service:通常用于注解service类,即服务层。
@Controller:通常用于controller类,即控制层(MVC)
在声明action时,需要指定为多例,解决线程安全问题。
Spring过滤器和拦截器区别?
Spring的拦截器与servlet的filter有相似之处,比如二者都是AOP编程思想的体现,都能实现权限检查,日志记录等。
区别:
1.使用范围不同:filter是servlet规范规定的,只能用于web程序中,而拦截器既可以用于web程序,也可以用于application,swing程序中;
2.规范不同:filter是在servlet规范中定义的,是servlet容器支持的,而拦截器是在spring容器内的,是spring框架支持的;
3.使用资源不同:同其他的代码块一样,拦截器也是一个spring的组件,归spring管理,配置在spring文件中,因此能使用spring里的任何资源,对象。例如service对象,数据源,事务管理等,通过ioc注入到拦截器即可,而过滤器则不能;
4.深度不同:filter只在servlet前后起作用,而拦截器能够深入到方法前后,异常抛出前后等,因此拦截器的使用具有更大的弹性,所以在spring框架的程序中,要优先使用拦截器。
案例:在web.xml中使用filter如字符集编码
Struts2工作原理?
1.客户端发送一个请求给strtusPrepareAndExecueFilter(在web.xml中),
2.strutsPrepareAndExecuteFilter询问ActionMapper:该请求是否是一个strtus2的请求,
3.若actionMapper认为该请求是一个strtus请求,则strutsPrepareAndExecuteFilter把请求的处理交给actionProxy,
4.ActionProxy通过ConfigurationManager询问框架的配置文件,确定需要调用action类及action方法,
5.actionProxy创建一个actionInvocation的实例,并进行初始化,
6.actionInvocation实例在调用action过程前后,涉及到相关拦截器(Intercepter)的调用,
7.Action执行完毕,actionInvocation负责根据strtus.xml找到对应的返回结果。调用结果的execute方法,渲染结果,在渲染的过程中可以使用strtus2框架的标签,
8.执行各个拦截器invocation.invoke()之后的代码
9.把结果发送给客户端
Struts2:注意在页面中展示的数据,都一视同仁的成为字符串在页面上展现出来。
Struts2常用标签?
首先在jsp页面中引入strtus2标签库<%@taglib prefix=”s”uri=”/struts-tags”>
1.往action传值:<input name=”userName” type=”text” >
2.显示标签property用于输出指定值:<s:property value=”userName”>
3.用于从页面往action中(user)的对象传值:
<s:text name=”user.userName”id=”userName”>
4.迭代<s:iterator>用于将list,Map,ArrayList等集合数据循环遍历
<s:iterator id=”user”status=”u”value=”userList”>
<s:property value=”userName”>
</s:iterator>
5.Set标签用于将某个值放入指定范围内如application,session
<s:set name=”user”value=”userName” scope=”request”>
El表达式:如
<s:set name=”name” value=”<%=request.getParamter(“name”)%>”/>
拦截器和过滤器的区别?
1.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
2.Struts2拦截器只能对action请求起作用,而过滤器则对所有请求起作用。
3.拦截器可以访问action的上下文,值栈里的对象,而过滤器不能。
4.在action的生命周期中,拦截器可以调用多次,而过滤器只能在容器初始化时被调用一次。
谈谈你对MVC的理解?
MVC即Model-View-Controller的缩写
Model:表示业务数据和业务处理,相当于Javabean,一个模型为多个视图提供数据
View:用户看到并与之交互的页面,向用户显示相关数据,并接受用户的输入,如jsp
Controller:接受用户请求并调用相应模型去处理请求,然后根据处理的结果调用相应的视图来显示处理的结果如servlet,struts2
MVC处理过程:首先控制器接受用户的请求,并决定应该调用哪个模型来进行处理;然后根据用户请求进行相应的业务逻辑处理,并返回数据;最后控制器调用相应的视图格式化返回的数据,并通过视图呈现给用户。
Action 是单例还是多例?为什么?
Action是单例,当多个用户访问一个请求时候,服务器内存中只有一个与之对应的 action类对象。因为当服务器第一次加载struts的配置文件时,创建一个action后,每发送一个请求,服务器都会去检索相应的范围是否存在这 样一个action实例,如果存在,则使用这个实例,否则创建一个action实例。
Hibernate的缓存机制:一级缓存session缓存和二级缓存sessionfactory缓存?
hibernate:一个基于元数据的轻量级(占用资源少,没有浸入性)orm(对象关系数据库映射)框架。
Session是一级缓存,它是属于事务范围的缓存,由Hibernate管理,无需进行干预。
SessionFactory是二级缓存,它是属于进程范围或群集范围的缓存,可以进行配置和更改.
一级缓存又叫session缓存,轻量级的,创建和销毁不需要消耗太多资源,但是它是线程不安全的,要避免多个线程共享一个session实例。我们框架使用的get,load,save,update,delete等都支持一级缓存的。
二级缓存又叫sessionfactory缓存,重量级的,创建和销毁需要消耗太多资源,它是线程安全的,一个实例可以被应用的多个线程共享。
需要在配置文件中启用二级缓存
<!--启用二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
缓存的操作数据原理:
查询数据时,会首先从一级缓存中取数据,如果取上,则直接使用,否则到二级缓存中取,如果取到则直接使用,否则,就会发送语句查询数据库。这样利用一级和二级缓存会提高访问效率。
lazy(Hibernate的延迟加载功能):表示查询当前对象或关联对象数据时,不真正访问数据库,当使用对象非主键属性时,才真正发送查询语句,访问数据库。
Hibernate工作原理?
1.读取并解析配置文件
2.读取并解析映射信息,创建sessionfantory
3.打开session
4.创建事务transaction
5.持久化操作
6.提交事务
7.关闭session
8.关闭sessionfactory
Hibernate的核心接口有5个:session,sessionFactory,transaction,query,configuration?
Session接口:负责进行被持久化对象的crud操作。Session是一级缓存,轻量级的,线程不安全的。
SessionFactory接口:负责初始化Hibernate,它充当数据存储源的代理,并负责创建session对象,这里用到工厂模式,sessionFactory是二级缓存,重量级的。
Configuration接口:负责配置并启动Hibernate,创建sessionFactory对象。在Hibernate启动过程中,configuration类的实例首先定义映射文件位置,读取配置,然后创建sessionFactory对象。
Transact接口:负责相关事务相关的操作。
Query和criteria接口:负责各种数据库查询,用sql或者hql语句表达方式。
Hibernate中Java对象的状态有哪些?
1.临时态(transient)不处于session缓存中。Oid为null或等于id的unsaved-value属性值
2.持久态(persistent)加入session缓存中
3.游离态(detached)已经被持久化,但不再处于session的缓存中
Session的清理和清空有什么区别?
清理缓存调用的是session.flush()方法,而清空调用的是session.clean()方法。
Session清理缓存是指按照缓存中对象的状态变化来同步更新数据库,但不清空缓存。而清空则是把session的缓存置空,不同步更新到数据库。
Hibernate的load()方法与get()方法的区别?
Get加载数据不支持延迟加载,若没有oid对象则返回的是null,而load加载数据支持延迟加载,返回的是一个代理对象
Hibernate优缺点?
优点:
1.对JDBC访问数据库的代码做了封装,简化了数据访问层繁琐的重复性代码
2.映射的灵活性, 它支持各种关系数据库,从一对一到多对多的各种复杂关系.
3.非侵入性、移植性会好
4.缓存机制: 提供一级缓存和二级缓存。
缺点:
1.无法对 SQL 进行优化
2.框架中使用 ORM 原则, 导致配置过于复杂
3.执行效率和原生的JDBC相比偏差: 特别是在批量数据处理的时候
4.不支持批量修改、删除
Hibernate的openSessionView问题?
用于解决懒加载异常问题,主要功能就是把hibernate session和一个请求的线程绑定在一起,直到页面完整输出,这样就可以保证页面读取数据的时候session一直处于开启状态,如果去获取延迟加载对象也不会报错。
注意配置filter要放在strtus2过滤器的前面,因为它要页面显示完后再退出。
Hibernate的getCurrentSession()和openSession()的区别?
1.getCurrentSession()它会先检查当前线程中是否绑定了session如果有则直接返回,没有再创建,而openSession()则是直接new一个新的session并返回。
2.使用ThreadLocal来实现线程session的隔离。
3.getCurrentSession()在事务提交的时候会自动关闭session,而openSession()要手动关闭。
项目中为什么使用SSH?
1.使用struts2是因为struts2是基于MVC设计模式,很好的将应用程序进行分层,使开发者更关注业务逻辑实现,其次struts有丰富的taglib,灵活运用,大大提高开发效率。
2.使用hibernate是因为它是基于orm模式的轻量级框架。
3.使用spring是因为基于IOC和AOP架构多层j2ee框架,采用IOC使得很容易实现bean的装配,采用AOP实现事务管理。
Hibernate的update()和saveOrUpdate()的区别?
Update()和saveOrUpdate()是用来对跨session的po进行状态管理的。
Update()方法操作的对象必须是持久化的对象,如果此对象在数据库中不存在的话,就不能使用update()方法。
saveOrUpdate()方法操作的对象即可以是持久化的,也可以是未持久化的对象,如果该对象是已经持久化的则调用该方法会更新数据库对象,如果该对象是未持久化的则调用该方法会save到数据库。
什么是hibernate的并发机制?怎么去处理并发问题?
Hibernate的并发机制:1.hibernate的session对象是非线程安全的,对于单个请求,单个会话,单个工作单元,它通常只使用一次然后就丢弃。如果一个session实例会话允许共享的话,那些支持并发运行的,例如http request,session bean将会导致出现资源争用。如果在http session中hibernate的session话,就可能出现同步访问http session,只要用户足够快点击浏览器的“刷新”。2.多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。
解决方案:
1.设置事务隔离级别
Serializable串行化。隔离级别最高
Repeatable read:可重复读
Read committed:已提交数据读
Read uncommitted:未提交数据读。隔离级别最差
设置锁:乐观锁和悲观锁。
乐观锁:使用版本号或者时间戳检测更新丢失,在<class>映射中设置optimistic-lock=“all”可以在没有版本或者时间戳属性映射的情况下实现版本检查,此时hibernate将比较一行记录的每个字段的状态行。
悲观锁:hibernate总是使用数据库的锁定机制,从不在内存中锁定对象,只要为jdbc连接指定一下隔离级别,然后让数据库去搞定一切就够了。类LockMode定义了hibernate所需的不同的锁定级别:
LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ
以上是关于Java面试题集的主要内容,如果未能解决你的问题,请参考以下文章