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注解来完成,如下:

 

@Component    
@Aspect    
public class TestAspect {    
    @Pointcut(value="execution(* *(..))")    
    private void pointcut() {}    
    @Before(value="pointcut()")    
    public void before() {    
        System.out.println("=======before");    
    }    
}   

 

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>  

 

 

配置事务特征

  1. <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的配置文件如:

 

<context-parm>  
  <param-name>contextConfigLocation</param-name>  
  <param-name>classpath:applicationContext.xml</param-name>  
</context-parm>  

 

启动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面试题集的主要内容,如果未能解决你的问题,请参考以下文章

Java面试题集

面试阿里,字节跳动90%会被问到的Java异常面试题集,史上最全系列!

凭借这份Java面试题集,java验证码生成

凭借这份Java面试题集,java验证码生成

java面试笔试题代码,先收藏了

Android - Android 面试题集