2019java后端面试看这篇就够了(二)

Java面试最值得收藏的文章(共4部分):

2019java后端面试集合篇最值得收藏的(一)

2019java后端面试集合篇最值得收藏的(二)

2019java后端面试集合篇最值得收藏的(三)

2019java后端面试集合篇最值得收藏的(四)

Junit单元测试:

我在编写完自己的功能模块后,为了保证代码的准确性,一般都会使用junit进行单元测试,

当时使用的是junit4这种基于注解的方式来进行单元测试。为了和spring集成获取配置的bean,

通常使用 @RunWith来加载springjunit这个核心类,使用 @ContextConfiguration来加载

相关的配置的文件,通过 @Resource按名字来注入具体的bean,最后在需要测试的方法上面加上

@Test 来进行单元测试。并且在编写单元测试的时候还要遵守一定的原则如:

源代码和测试代码需要分开;测试类和目标源代码的类应该位于同一个包下面,即它们的包名应该一样;

测试的类名之前或之后加上@Test,测试的方法名通常也以test开头。

@RunWith(SpringJUnit4ClassRunner.class)//运行spring相关环境 相当于spring监听功能

@ContextConfiguration(locations={"classpath:spring-common.xml","classpath:spring-datasource.xml"})//读取spring配置文件 不识别* 只能识别具体文件 多个配置文件使用string数据传递

public class TestSpring {

  //注入Service层

private @Resource UserService userService;

@Test

public void testFind(){

List userList = userService.findAllUserInfo();

for (User user : userList) {

System.err.println(user.toString());

}

}

}

SSM整合的流程【问到SSI整合流程就说我们通常用的是SSM,我就给您说下SSM的流程吧】

在项目中通过在web.xml配置springMVC的核心控制器DispatcherServlet并加载Spring-mvc-controller.xml,并且通过配置Spring的监听器contextLoaderListener加载spring-common.xml,之后新建控制层并在类上加入@Controller和@RequestMapping注解,并通过@Resouce注入service层,在

service的实现类上加入@Service注解并通过@Autowired注入dao层,dao层只有接口并没有实现类,是通过在mybatis中对应的含有sql语句的xml文件中来通过namespace指明要实现的dao层的接口,并使sql语句的id和dao层接口中的方法名一致从而明确调用指定dao层接口时要执行的sql语句。并且在spring-mvc-controller.xml中配置了component-scan对controller进行扫描从而使控制层的注解生效还配置了内部视图解析器从而在控制层进行页面跳转时加上指定的前缀和后缀,在spring-common.xml中配置了dbcp数据库连接池以及sqlSession来加载mapper下所有的xml并对所有的mapper层进行扫描也就是对dao层的扫描,

还通过Aop中的切点表达式对service层进行事务控制,并且对service层进行扫描使其注解生效。

 

SSH整合的流程

在项目中首先是通过在web.xml中配置strtus2的前端控制器filterDispatcher加载struts.xml配置文件并对指定的后缀名进行拦截,并且通过配置spring的监听器contextLoadListener加载spring的相关配置文件如

spring-service.xml,spring-dao.xml,spring-common.xml,之后新建控制层的类继承于BaseAction,而BaseAction继承于ActionSupport,在BaseAction中封装了常用的方法如getRealPath(),outJson()等,

之后控制层注入service层,service层注入dao,dao层继承于HibernateDaoSupport并注入spring-common.xml中配置的sessionFactory,sessionFactory注入dataSource连接数据库,注入hibernate.cfg.xml从而加载hbm.xml文件,除此之外还通过Spring中的Aop配置了事务并且通过切点表达式对Servcie层代码进行控制。

 

SQL语句的执行顺序:

查询中用到的关键词主要包含六个,并且他们的顺序依次为 

select--from--where--group by--having--order by 

 

其中select和from是必须的,其他关键词是可选的,这六个关键词的执行顺序 

与sql语句的书写顺序并不是一样的,而是按照下面的顺序来执行 

from--where--group by--having--select--order by, 

from:需要从哪个数据表检索数据 

where:过滤表中数据的条件 

group by:如何将上面过滤出的数据分组 

having:对上面已经分组的数据进行过滤的条件  

select:查看结果集中的哪个列,或列的计算结果 

order by :按照什么样的顺序来查看返回的数据 

 

HashMap的底层代码/原理【http://zhangshixi.iteye.com/blog/672697

HashMap底层就是一个数组结构,数组中的每一项又是一个链表。

当新建一个HashMap的时候,就会初始化一个数组。

 

Entry就是数组中的元素,每个 Entry 其实就是一个key-value对,

它持有一个指向下一个元素的引用,这就构成了链表。

 

 

HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。

HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,

当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,

再根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,

也会根据hash算法找到其在数组中的存储位置,

再根据equals方法从该位置上的链表中取出该Entry。

 

默认是构建一个初始容量为 16,负载因子为 0.75 的 HashMap。

 

也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过16*0.75=12的时候,

就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,

而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,

那么预设元素的个数能够有效的提高HashMap的性能。

 

 

Http协议原理:

HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,

是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。

 

http的工作流程:

当发送一个http请求时,首先客户机和服务器会建立连接,

之后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),

以及要传递的参数和头信息,服务器接到请求后会进行响应,

包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收

到请求后将其展示到浏览器上然后断开和服务器端的连接。

 

简单说就是:建立连接--》发送请求--》响应--》断开连接

 

 

GET和POST的区别:


1、GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.jsp?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中。
2、GET提交的数据大小有限制,最多只能有1024字节(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
3、通常用Post进行文件上传而get是不支持的。
4、GET方式没有POST方式安全

 

 

什么是长连接、短连接?

在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,

但任务结束就中断连接。

 

从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:

Connection:keep-alive 

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,

如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。

Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。

实现长连接要客户端和服务端都支持长连接。

 

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

 

Hashtable与HashMap的区别

HashMap不是线程安全的,HashTable是线程安全。

HashMap允许空(null)的键和值(key),HashTable则不允许。

HashMap性能优于Hashtable。

 

Map

1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和HashTable.

2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.

3.HashMap允许键或值为空,而HashTable不允许键或值为空

 

说说你对缓存的理解

通常情况下缓存是为了提高应用程序的性能,减少数据库的访问次数,缓存的存储介质可以

内存或者硬盘,通常将数据存储在内存里,确切的说是jvm的内存中,缓存是

基于Map这种思想构建的,以键值对的方式进行存取,之所以还可以将

缓存的数据存储在硬盘中,是因为内存资源相当有限和宝贵,所以当内存资源

不足的时候,就可以将其存储到硬盘中,虽然硬盘的存取速度比内存要慢,但是

因为减少了网络通信量,所以还是提高程序的性能。缓存可以分为客户端缓存和

服务器端缓存,所谓的客户端缓存通常指的是IE浏览器的缓存,服务器端缓存指

的web服务器的缓存,通常可以通过第三方组件实现,如oscache或者redis

 

我们通常将那些频繁访问但是又不是经常改变的数据进行缓存。为了保证缓存数据的

有效性,在数据发生改变的时候,我们要刷新缓存,避免脏数据的出现。刷新缓存的

策略有两种,一种是定时刷新,一种手动刷新。

缓存的层次如下:jsp-->action-->service(通常放置在service)-->dao,

缓存越靠前对性能的提升越大

 

缓存的策略:(缓存空间不足需要进行清理的时候使用)

LRU:最近最少使用原则.(理解:存储书)

FIFO:先进先出的缓存策略.(理解:排队)

 

你对Maven是怎么理解的

maven是一个项目管理工具,其核心特点就是通过

maven可以进行包的依赖管理,保证jar包版本的一致性,以及可以使多个项目共享

jar包,从而能够在开发大型j2ee应用的时候,减小项目的大小, 

maven根据“约定优于配置”的特性,对其项目的编译打包部署进行了

更为抽象的封装,直接使用系统预定好的mvn clean,compile,test,package等命令进行项目的操作。

为了保证团队中的成员能够节省下载jar包所需要的时间,

于是我就采用nexus搭建了在局域网内的maven私服,然后通过配置settings.xml中

建立mirror镜像,将所有下载jar包的请求都转发到maven私服上,之后通过在pom.xml

即(project object model)中配置项目所依赖的jar包,从而达到在构建项目的时候,

先从本地仓库中查找,如果不存在从内部私服查找,如果不存在最后再从外网central

服务器查找的机制,达到了节省下载带宽,提高开发效率,以及jar包重用的目的。

 

Spring MVC中的注解你都用过哪些

SpringMVC中用到过的注解有@RequestParam它的作用是接受前台传递的参数并且可以通过defaultValue属性对其设置默认值;在SpringMVC进行文件上传的时候也会通过@RequestParam和MultipartFile结合使用。@Autowired注解和@Resource注解的作用都是为了进行属性注入,但@Autowired默认是按照类型进行匹配,它是Spring提供的注解,@Resource默认是按照名字进行匹配,它是java提供的注解。在进行restful接口编程的时候我们还会用到@pathvariable注解从路径中获取参数信息以及用到@ResponseBody注解将实体类自动转换为指定的json格式,@RequestBody将前台传递过来的json格式的数据转换为对应的javabean。除此之外还有@Controller,@Service,@Repository分别在控制层,业务逻辑层和持久层的实现类型添加。最后还有@RequestMapping注解在控制层的方法上添加从而将指定url和方法对应起来。

 

SpringMVC的运行原理是:

整个处理过程从一个HTTP请求开始:

1.Tomcat在启动时加载解析web.xml,找到spring mvc的前端总控制器DispatcherServlet,并且通过DispatcherServlet来加载相关的配置文件信息。

2.DispatcherServlet接收到客户端请求,找到对应HandlerMapping,根据映射规则,找到对应的处理器(Handler)。

3.调用相应处理器中的处理方法,处理该请求后,会返回一个ModelAndView。

4.DispatcherServlet根据得到的ModelAndView中的视图对象,找到一个合适的ViewResolver(视图解析器),根据视图解析器的配置,DispatcherServlet将要显示的数据传给对应的视图,最后显示给用户。

 

谈谈你对Spring的理解

Spring就相当于一个粘合剂,有两个核心,一个核心是IOC (控制反转),它是基于工厂设计模式,所谓控制反转就是将自己手工完成对象创建(new)的这种任务交给spring容器去完成。和控制反转配套使用的还有一个DI也就是依赖注入。我们可以进行构造函数注入,属性注入等,最常用的还是属性注入。可以注入各种类型Map,List,properties

注入可以通过ByType和ByName分别按照类型和名字进行自动注入。

Spring中的Bean支持单例和原型两种方式,默认是单例的。

可以通过singleton=true/false来进行配置或者通过

scope="singleton",scope="prototype"来配置。

所谓单例:即至始至终在jvm中都只有一个该类的实例。

所谓原型:也叫多例,就每次都会创建一个新的对象实例。

 

另一个核心是AOP(面向切面编程/面向方面编程), AOP是OOP(面向对象编程)的延续,主要应用于日志记录,性能统计,安全控制,事务处理等方面。它是基于代理设计模式,而代理设计模式又分为静态代理和动态代理,静态代理比较简单就是一个接口,分别有一个真实实现和一个代理实现,而动态代理分为基于接口的jdk的动态代理和基于类的cglib的动态代理,Aop默认使用的是基于接口的jdk的动态代理。所谓动态代理,即通过代理类的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联。Jdk的动态代理要实现InvocationHandler接口并重写其中的invoke方法。

 

AOP的核心概念:

 

 

概念解释:

切面(Aspect): 有切点(PointCut)和通知(Advice)组成,它既包括横切逻辑的定义,也包括了连接点的定义。

切点(Pointcut):一个切点定位多个类中的多个方法。

通知也叫增强(Advice):由方位和横切逻辑构成,所谓的方位指的是前置通知,后置通知,返回后通知,环绕通知,抛出异常后通知

连接点(JoinPoint):由切点和方位构成,用来描述在在哪些类的指定方法之前或之后执行

所谓的方位包括:

前置通知(Before advice):在连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。

 

返回后通知(After returning advice): 在连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。

 

抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知

 

后置通知(After (finally) advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)

 

环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行

 

 

 

AOP在项目中的应用/后台的日志管理模块?[必说]

后台的日志管理模块是为了让开发人员根据记录的日志信息及时找到系统产生的错误以及知道当前系统在整个运行过程中都执行了哪些类的哪些方法。考虑到对日志的统一处理我就采用了AOP这项技术。

AOP的核心是切面,而切面中包含了切点和通知,切点是为了对指定类的指定方法进行拦截,通知中包含方位和横切逻辑,所谓方位指的是前置通知,后置通知,环绕通知等,横切逻辑指的是公共部分的代码如日志,事务等。

在项目中我们通常使用AOP进行事务方面的控制和日志的统一处理。在事务控制方面是通过Spring自带的事务管理器,配置切点表达式,对service层指定的方法如增删该进行事务控制,对查询进行只读事务控制从而提高性能。在日志的统一处理方面,我首先配置log4j.properties并指定日志级别为info,将日志输入到控制台以及指定的日志文件中。接着自己写一个日志的切面类LogAspect,并通过ProceedingJoinPoint【连接点】获取目标类名以及执行的方法名,通过调用LOG.info方法记录进入方法时的日志信息。为了记录出现异常时的错误日志,通过对proceed方法进行trycatch捕获,在catch中用LOG.error记录异常信息。在spring-mvc-controller.xml中配置aop-config,并通过aop-pointcut的切点表达式对所有的Controller和里面的方法进行拦截,最后通过aop-around配置环绕通知,并通过里面的method属性指明要调用切面类中的方法名。

 

#定义LOG输出级别

log4j.rootLogger=INFO,Console,File#定义日志输出目的地为控制台

log4j.appender.Console=org.apache.log4j.ConsoleAppender

log4j.appender.Console.Target=System.out#可以灵活地指定日志输出格式,下面一行是指定具体的格式

log4j.appender.Console.layout = org.apache.log4j.PatternLayout

log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n

#文件大小到达指定尺寸的时候产生一个新的文件

log4j.appender.File = org.apache.log4j.RollingFileAppender#指定输出目录

log4j.appender.File.File = logs/ssm.log#定义文件最大大小

log4j.appender.File.MaxFileSize = 10MB# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志

log4j.appender.File.Threshold = ALL

log4j.appender.File.layout = org.apache.log4j.PatternLayout

log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n

 

前台的日志管理模块:【15k及其以上必说】

前台的日志模块的核心价值是为了统计用户的行为,方便进行用户行为分析。 考虑到对日志的统一处理以及前台访问量巨大导致的大并发和大数据量的问题。 当时是结合AOP和Mongodb来完成了这项功能。

 

存日志的时候是通过SpringAOP写了个切面类,之后在切面类可以获取用户使用的

浏览器的类型如是IE还是谷歌,还是火狐;

以及用户使用的设备类型如是手机,

还是说是平板,还是说是PC;包括用户浏览过的商品信息,用户购买的商品信息等。将这些信息通过封装好的

MongodbUtil将其插入到mongodb数据库中方便其他系统后续对其进行分析。

考虑到mongodb的高可用性我们搭建了3台mongodb数据库来实现副本集,这样

不仅可以达到故障自动转移的特性而且也可以通过读写分离提高性能,即便

主服务器宕机了,还会通过投票选举出下一个主服务器继续提供服务。考虑到

后续数据量的不断增加,为了方便扩容我们还建立了3个分片。

图片管理模块:【15k及其以上必说】

考虑到我们的项目最后要部署到多台tomcat通过nginx来实现负载均衡,

为了对项目中的文件以及图片进行统一的管理,我们就用mongodb来充当文件服务器。

对于大部分的单张图片和单个文件来说小于16M,所以我们就以常规的方式来将

文件转换为二进制的字节数组进行保存。考虑到高可用性以及为了应对后期随着文件数量的不断

增加而能够方便进行扩容,我们建立了3个分片并将分片和副本集做了整合,每个分片都是一个副本集,这样

不仅满足了大数据量的存储也避免了分片中单台机器导致的单点故障问题。考虑到可能要处理

大于16M的文件,所以又增加了支持大文件存储的gridfs,这样即便再大的文件也会被gridfs分解为多个

chunk进行存储。

 

Restful的概述以及项目中应用?【必说的】

近期开发的项目有一部分是需要给前端提供接口,本来是想通过webservice的形式来提供接口进行数据的

输出,但项目经理要求用restful这种ROA面向资源编程的形式开发接口进行数据的提供,所以我就到网上

查阅了相关的资料,因为我们的项目是基于SpringMVC的,所以最终我就采用了基于SpringMVC进行restful

接口的开发。用到的注解有 @RestController @PathVariable @RequestBody 这些,其中 @RestController

就相当于 @Controller 和 @ResponseBody的组合体,这样就可以避免在各个方法上加入 @ResponseBody注解了,@PathVariable是为了从路径中获取参数信息, @RequestBody 起到的作用就是将前端提交过来的json数据根据相关的配置文件利用jackson这个工具自动转换为对应的javabean实体。

 

再者restful是基于HTTP协议现有的Get动作进行查询,Post动作进行增加,Put动作进行修改,Delete动作进行删除。返回结果我们采用JSON格式的数据,其中用code表示状态码,用message表示提示信息,用data表示返回的数据。

 

最后我们为了保证restful接口的安全性,采用了基于token的认证方式,它的流程是

用户用密码登录成功后,服务器返回token给客户端,客户端将token保存在本地,发起后续的相关请求时,

将token发回给服务器,服务器检查token的有效性,有效则返回数据,若无效,分两种情况

一种是token错误,这时需要用户重新登录,获取正确的token;一种是token过期,

这时客户端需要再发起一次认证请求,获取新的token。我们的token是通过uuid来保证唯一性,并且将其

存入redis中保证性能,通过uuid来充当key,通过userName来充当值。

 

 

Set,List,Collection,Collections的区别

1.List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。

 

2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。

 

StringBuffer StringBuilder String 区别

String       字符串常量   不可变  使用字符串拼接时是不同的2个空间

StringBuffer  字符串变量   可变   线程安全  字符串拼接直接在字符串后追加

StringBuilder 字符串变量   可变   非线程安全  字符串拼接直接在字符串后追加

 

1.StringBuilder执行效率高于StringBuffer高于String.

2.String是一个常量,是不可变的,所以对于每一次+=赋值都会创建一个新的对象,StringBuffer和StringBuilder都是可变的,当进行字符串拼接时采用append方法,在原来的基础上进行追加,所以性能比String要高,又因为StringBuffer  是 线程安全的而StringBuilder是线程非安全的,所以StringBuilder的效率高于StringBuffer.

3.对于大数据量的字符串的拼接,采用StringBuffer,StringBuilder.

 

抽象类与接口的区别

1.一个类只能进行单继承,但可以实现多个接口。

2.有抽象方法的类一定是抽象类,但是抽象类里面不一定有抽象方法;

  接口里面所有的方法的默认修饰符为public abstract,接口里的成员变量默认的修饰符为  pulbic static final。

关系:

接口和接口      继承

接口和抽象类    抽象类实现接口

类和抽象类      类继承抽象类

类和类          继承

 

你对jquery的理解

Jquery是一个js框架,拥有跨浏览器的特性,可以兼容各种浏览器,

可以使用它的append方法、remove方法、insertAfter方法操作文档对象、

通过id选择器$("#id")以及类选择器$(".class")还有标签选择器$("标签名")

可以选择DOM元素、通过fadeIn In以及fadeOut制作淡入淡出的动画效果、

通过bind来对指定元素绑定事件、通过$.get,$.post以及$.ajax发送ajax

异步请求提高了性能。

 

你对Aajax的理解

AJAX 全称: 异步JavaScript及 XML。

Ajax的核心是JavaScript中的XmlHttpRequest(XHR)。

使用ajax可以提高用户的体验度,进行异步数据传输从而

提高性能。ajax不能跨域。

 dataType:'jsonp',可以通过设置动态的

你可能感兴趣的:(java面试开箱即用)