Java面試題(实用性高)
Posted 一怒成仙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面試題(实用性高)相关的知识,希望对你有一定的参考价值。
3.Spring MVC中的注解你都用过哪些,SpringMVC的运行原理是什么?
@Controller:使其普通的java类充当控制层的作用。
@RequestMapping:有两个参数 url 代表要访问的路径 method请求方式
@Service::使其java类充当service层。
@Repository::使其java类充当持久层。
@Resource:默认按照名字注入指定的bean。
@Autowired:默认按照类型进行注入可以结合@Qualifier("bean的的名字 名字")使使其按照名字进行注入。他是 其按照名字进行注入。他是Spring中的注解。
@RespsonceBody:将controller的方法返回的对象通过适当的转换器转换为指定个时候将其输出(通常适用于返回json/xml)
@RequestParam
作用:1.在文件上传时注解 @requestParam 后跟multilpartFile属性
2.接收指定参数名的参数并对方法中的参数赋值并且可以设置默认值
我们通常使用Spring MVC来充当我们项目中的控制层,我们控制层的作用就是接受前台传递的参数,调用业务逻辑层进行业务处理以及将返回的结果集返回前台进行展示,首先我们要在web.xml中配置Spring MVC的前端总控制器DispatcherServlet并加载Spring MVC的配置文件,我们在Controller层上加上@Controller注解,使其充当控制层,并且要在Spring mvc的配置文件中通过component-scan对Controller层进行扫描从而使类中的@Controller注解生效,Spring mvc用方法来接收参数,所以我们说Spring mvc是基于方法的设计,我们也可以通过@PathVariable从路径中获取信息,我们通常通过@Resource这个注解来进行Bean注入,他是java中的注解,而不是Spring中的,默认是按照属性名进行注入,我们也可以通过设置name属性的值,让其只能按照属性名进行注入,我们也可以用@Autowired注解来进行Bean的注入,他默认是按照类型进行注入,如果要按属性名进行注入我们需要结合@Qualifier注解使其按照名字进行注入,我们可以将返回值的类型改为ModelAndView并在配置文件中配置视图解析器的前缀和后缀,以此来给我们前台页面传递数据,也可以在方法中通过ModelMap进行返回数据。也可以通过@ResponseBody将返回的实体类或者实体类的集合转换为指定的格式进行前台页面交互。并且要在配置文件中进行相关的配置。@RequestMapping是将Url映射到具体的方法上。文件上传时我们通过@RequestParam来接收前台上传的文件。以上就是我对Spring MVC的理解和运用。
4.SSH整合的流程/SSI整合的流程/SSM整合的流程?
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层代码进行控制。
======================================================================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层进行扫描使其注解生效。
5.谈谈你对Spring的理解?
Spring 是完全面向接口的设计,降低程序耦合性,主要是事务控制并创建bean实例对象。在ssh整合时,充当黏合剂的作用。IOC(Inversion of Control) 控制反转/依赖注入,又称DI(Dependency Injection) (依赖注入)
IOC的作用:产生对象实例,所以它是基于工厂设计模式的
Spring IOC的注入
通过属性进行注入,通过构造函数进行注入,
注入对象数组 注入List集合
注入Map集合 注入Properties类型
Spring IOC 自动绑定模式:
可以设置autowire按以下方式进行绑定
按byType只要类型一致会自动寻找,
按byName自动按属性名称进行自动查找匹配.
AOP 面向方面(切面)编程
AOP是OOP的延续,是Aspect Oriented Programming的缩写,
意思是面向方面(切面)编程。
注:OOP(Object-Oriented Programming ) 面向对象编程
AOP 主要应用于日志记录,性能统计,安全控制,事务处理(项目中使用的)等方面。
Spring中实现AOP技术:
在Spring中可以通过代理模式来实现AOP
代理模式分为
静态代理:一个接口,分别有一个真实实现和一个代理实现。
动态代理:通过代理类的代理,接口和实现类之间可以不直接发生联系,而 可以在运行期(Runtime)实现动态关联。
动态代理有两种实现方式,可以通过jdk的动态代理实现也可以通过cglib
来实现而AOP默认是通过jdk的动态代理来实现的。jdk的动态代理必须要有
接口的支持,而cglib不需要,它是基于类的。
Spring AOP事务的描述:
在spring-common.xml里通过<aop:config>里面先设定一个表达式,设定对service里那些方法 如:对add* ,delete*,update*等开头的方法进行事务拦截。我们需要配置事务的传播(propagation="REQUIRED")特性,通常把增,删,改以外的操作需要配置成只读事务(read-only="true").只读事务可以提高性能。之后引入tx:advice,在tx:advice引用transactionManager(事务管理),在事务管理里再引入sessionFactory,sessionFactory注入 dataSource,最后通过<aop:config>引入txAdvice。
Spring实现ioc控制反转描述:
原来需要我们自己进行bean的创建以及注入,而现在交给
spring容器去完成bean的创建以及注入。
所谓的“控制反转”就是 对象控制权的转移,
从程序代码本身转移到了外部容器。
官方解释:
控制反转即IoC (Inversion of Control),
它把传统上由程序代码直接操控的对象的调用权交给容器,
通过容器来实现对象组件的装配和管理。
所谓的“控制反转”概念就是对组件对象控制权的转移,
从程序代码本身转移到了外部容器。
6.HashMap和HashTable的区别?
1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和HashTable.
2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.
3.HashMap允许键或值为空,而HashTable不允许键或值为空.
7.HashMap的底层原理?(源代码)
HashMap底层就是一个数组结构,数组中的每一项又是一个链表。
当新建一个HashMap的时候,就会初始化一个数组。
Entry就是数组中的元素,每个 Entry 其实就是一个key-value对,
它持有一个指向下一个元素的引用,这就构成了链表。
HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。
HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,
当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,
再根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,
也会根据hash算法找到其在数组中的存储位置,
再根据equals方法从该位置上的链表中取出该Entry。
8.jre,jdk,jvm的区别?
Jdk【Java Development ToolKit】就是java开发工具箱, JDK是整个JAVA的核心里边包含了jre,它除了包含jre之外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此之外,里边还包含了java源生的API,java.lang.integer在rt的jar包里边【可以在项目中看到】,通过rt这个jar包来调用我们的这些io流写入写出等
JDK有以下三种版本:
J2SE,standard edition,标准版,是我们通常用的一个版本
J2EE,enterpsise edtion,企业版,使用这种JDK开发J2EE应用程序
J2ME,micro edtion,主要用于移动设备、嵌入式设备上的java应用程序
Jre【Java Runtime Enviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序能够运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,所有的Java程序都要在JRE下才能运行。
包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。
Jre里边包含jvm
Jvm:【Java Virtual Mechinal】因为jre是java运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之所以有跨平台的作用,就是因为我们的jvm
关系:
J2se是基于jdk和jre,
JDK是整个JAVA的核心里边包含了jre,
Jre里边包含jvm
9.Set,List,Collection,Collections的区别?
1.List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。
2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。
10.系统管理的描述?
我负责项目中的系统管理模块,其中包含用户管理,菜单管理以及给用户赋角色,给角色赋权限;涉及到的表有用户表,角色表,用户角色关联表,菜单表,角色菜单关联表。在菜单管理模块采用ztree进行菜单的增删改查操作,为了将权限控制到按钮级别我们在进行菜单管理时会设置该菜单是属于按钮级别还是普通菜单,通过在数据库中增加一个type类型的字段来实现,如type为1则是普通菜单,type为2则是按钮菜单。
这样用户在登录的时候根据用户名和密码到用户表验证信息是否合法,如果合法则获取用户信息,之后根据用户id再到用户角色关联表中得到相关联的角色id集合,之后根据角色id集合再到角色权限关联表中获取该角色所拥有的权限id集合,然后再根据权限id集合到权限表(菜单表)中获取具体的菜单,展现给当前登录用户,从而达到不同用户看到不同的菜单权限。
为了防止用户不登录而直接访问后台资源我通过在项目中加入LoginInterceptor拦截器对未经认证的用户进行拦截,如果未经认证则跳转到登录页面使用户再次登录,除此之外还加入了PermissionInterceptor拦截器来对用户无权访问的资源进行拦截,如果无访问权限则跳转到没有访问权限的页面。
再者考虑到性能将用户登录后所拥有的资源权限通过OScache结合单例设计模式将数据存储到了缓存中,这样可以避免每次操作都需要重新进行查询的代价,减少和数据库的交互次数,提高系统性能。考虑到单例的设计模式在多线程中会出现线程安全的问题,所以就给单例加了双重判断锁,从而避免该问题的发生。
11.抽象类和接口的区别?
共同点:
- 都可以写抽象方法
- 都不能被实例化对象
- 类继承抽象类需要重写抽象方法,类实现接口也必须重写抽象方法
不同点
- 类和接口是两个不同的概念,抽象类是由abstract修饰的类;接口不是类,用interface定义
- 接口中只能有抽象方法,抽象类中既可以有抽象方法,又可以有普通方法
- 类是单继承多实现,实现一个抽象类,需要继承.实现接口需要implements
- 接口定义的变量默认是public static final的,而抽象类没有这个限制
12.Get和Post的区别?
1.get是从服务器上获取数据,post是向服务器传送数据,
2.get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。
3.get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
4.在进行文件上传时只能使用post而不能是get。
5.不明确是post请求的都是get请求
13.Redirect和Forward的区别?
1、从数据共享上
Forword是一个请求的延续,可以共享request的数据
Redirect开启一个新的请求,不可以共享request的数据
2、从地址栏
Forword转发地址栏不发生变化
Redirect转发地址栏发生变化
14.Http协议的理解?
HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,
是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。
http的工作流程:
当发送一个http请求时,首先客户机和服务器会建立连接,
之后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),
以及要传递的参数和头信息,服务器接到请求后会进行响应,
包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收
到请求后将其展示到浏览器上然后断开和服务器端的连接。
简单说就是:建立连接--》发送请求--》响应--》断开连接
15.长连接和短连接?
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,
但任务结束就中断连接。
从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,
如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
实现长连接要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
16.你对jquery的理解?
jquery是一个轻量级的js框架,具有跨浏览器的特性,兼容性好,
并且封装了很多工具,方便使用。
常用的有: 选择器 ,dom操作 ,ajax(ajax不能跨域) ,特效,工具类
17.事务的概述?
在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交。
判断事务是否配置成功的关键点在于出现异常时事务是否会回滚
事务的ACID属性
1. 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,
要么都不发生。
2. 一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
3. 隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰.
4. 持久性(Durability)
持久性是指一个事务一旦被提交,
它对数据库中数据的改变就是永久性的.即使系统重启也不会丢失.
在JDBC中,
事务默认是自动提交的,
每次执行一个 SQL 语句时,如果执行成功,
就会向数据库自动提交,而不能回滚
为了让多个 SQL 语句作为一个事务执行:
(1)执行语句前调用 Connection 对象的 setAutoCommit(false);
以取消自动提交事务
(2)在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
(3)在出现异常时,调用 rollback(); 方法回滚事务。
18.索引的概述?
1、索引的概念
索引就是为了提高数据的检索速度。
数据库的索引类似于书籍的索引。
在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。
在数据库中,索引也允许数据库程序迅速地找到表中的数据,
而不必扫描整个数据库.
2、索引的优点
1.创建唯一性索引,保证数据库表中每一行数据的唯一性
2.大大加快数据的检索速度,这也是创建索引的最主要的原因
3.减少磁盘IO(向字典一样可以直接定位)
3、索引的缺点
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
2.索引需要占用额外的物理空间
3.当对表中的数据进行增加、删除和修改的时候,
索引也要动态的维护,降低了数据的维护速度
4、索引的分类
1.普通索引和唯一性索引
普通索引:CREATE INDEX mycolumn_index ON mytable (myclumn)
唯一性索引:保证在索引列中的全部数据是唯一的
CREATE unique INDEX mycolumn_index ON mytable (myclumn)
2. 单个索引和复合索引
单个索引:对单个字段建立索引
复合索引:又叫组合索引,在索引建立语句中同时包含多个字段名,
最多16个字段
CREATE INDEX name_index ON userInfo(firstname,lastname)
3.顺序索引,散列索引,位图索引
19.三层分页的SQL语句?(手写)
首先不考虑查询条件 先写分页语句 在写条件
1.例如:河北省不满18周岁的男的4,5,6条信息
select * from
(select t.* ,rownum rn from
(select id,name, age,sex from t_student where name="河北" and age<18 and sex="男") t
where rownum <= 6)
where rn >=4
2.女生年龄从高到低排序 每页3条 查询第3条
select * from
(select t.*,rownum rn from
(select id,name,age from t_student order by age desc) t
where rownum <= 9)
where rn>=7
20.数据库三范式?
第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。
第二范式(2NF): 首先是满足第一范式,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不是部分依赖。
第三范式(3NF): 首先满足第二范式,非主键列直接依赖于主键,消除传递依赖。
21.id,rowid,rownum的区别?
rowid物理位置的唯一标识。
而id是逻辑上的唯一标识,所以rowid查找速度要快于id,是目前最快的
定位一条记录的方式
rowid和rownum都是"伪数列"
所谓“伪数列”也就是默认隐藏的一个数列。
rownum用于标记结果集中结果顺序的一个字段,
它的特点是按顺序标记,而且是连续的,
换句话说就是只有有rownum=1的记录,才可能有rownum=2的记录。
rownum关键字只能和<或者<=直接关联
如果是>或者=则需要给他0起个别名
22.单例设计模式?(手写)
单例就是该类只能返回一个实例(实例只会创建一次)
单例所具备的特点:
1.私有的构造函数
2.私有的静态的全局变量
3.公共的静态的方法
双重锁定式
public class Singleton {
private Singleton(){};
private static Singleton single;
public static Singleton getInstance(){
if(null ==single){
Synchronized(single){
if(null == single){
single = new Singleton();
}
}
}
return single;
}
}
23.主键和唯一索引的区别?
在创建主键的同时会生成对应的唯一索引,主键在保证数据唯一性的同时不允许为 空,而唯一可以有一个为空数据项,一个表中只能有一个主键,但是一个主键可以 有多个字段,一个表中可以有多个唯一索引。
24.数据库连接池运行原理?
数据库连接池的优点运行原理:
在我们不使用数据库连接池的时候,每次访问数据库都需要创建连接,
使用完成之后需要释放关闭连接,而这样是很耗费资源的。当我们使用
数据库连接池的时候,在tomcat启动的时候就创建了指定数量的连接,
之后当我们程序使用的时候就直接从连接池里面取,而不需要创建,同理,
当我们使用完的时候也不需要关闭连接,而是将连接返回到连接池中,供
其他请求继续使用。
DBCP:比较稳定。
C3P0: 性能比较高。
25.jdbc,ibatis,hibernate的区别?
Hibernate属于全自动, Ibatis属于半自动,Jdbc属于手动,从开发效率上讲hibernate较高,ibatis居中,jdbc较低,从执行效率上讲hibernate较低,ibatis居中,jdbc较高,因为jdbc是手工写sql语句,程序员对sql的控制能力更大,可以根据业务需要进行优化,而ibatis虽然也可以对sql进行优化,但是他里面将resultset封装为实体的过程中采用了反射机制所以一定程度上影响了性能,而hibernate因为高度封装所以开发效率相对较高,但正因为这个原因,所以程序员在对sql语句的控制和优化方面相对比较弱,而且在将resultset封装成实体的过程中也采用了反射机制,所以在性能方面较低
26.SQL优化?
外键必须加索引。
避免在 where 子句中对有索引的字段进行运算,这会导致索引失效,从而进行全表扫描。
在 where 及 order by 涉及的列上建立索引,要尽量避免全表扫描。
在设计表时要避免表中字段出现null的情况,通常要为其设置默认值。
避免在查找时放弃使用索引而进行全表扫描。
SELECT语句中避免使用\'*’,只查询需要返回的字段 ,这样可以减少oracle解析sql语句的时间。
用NOT EXISTS 替换 NOT IN 操作符,用 EXISTS 替换 IN
27.Java代码优化?
解析大文件的xml数据使用sax替代dom4j,使用分段批量提交来完成大数据量的插入。
对于大批量字符串的拼接使用stringbuffer或者stringbuilder代替string进行+拼接。
根据业务情况使用缓存减少对数据库的访问。
单线程应尽量使用 HashMap, ArrayList,因为HashTable,Vector使用了同步机制,降低了性能。
在finally块中关闭流,断开连接,释放资源。
避免在循环条件中使用复杂表达式 。
28.Hibernate优化?
3.Hibernate优化:
在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数 据量的,可以使用session. clear()或者session. evict(Object) ,在处理过程中,清除全部的缓存或者清除某个对象。
通过使用Hibernate的一级缓存,二级缓存,查询缓存等来提高性能 (必须)
Hibernate可以通过设置hibernate.jdbc.fetch_size,hibernate.jdbc.batch_size等属性,对Hibernate进行优化。
Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,Batch Size越大和数据库交互的次数就越少,速度就越快, 但也不要无限的大下去,通常选择一个合适的值,如100条;其次我们在进行大批量数据的导入操作时,可以结合batchsize进行分段批量提交,从而达到最优效果。
29.数据库优化?(被动说)
数据库优化:作为开发人员最主要是从sql语句的优化方面考虑的,对于数据库底层的优化,是由DBA完成的。
在我们公司里面做项目的时候,在开发过程中最主要是由程序员对java代码以及sql语句这方面进行优化,至于数据库 底层的优化,则由DBA在项目基本结尾进行压力测试的时候参与进来,通过对数据库的分析,确定影响性能的sql语句以及相关的表,通过和我们进行交流然后对其进行适当的改进。
30.MySQL优化?【慢日志,分表,sql执行计划】
慢日志就是在我们设置的时间内执行慢的语句可以在慢日志看到!
2.分表:
时间划分 地区划分
水平划分 垂直划分(把平常经常使用的提取出来加上索引)
3.在mysql中通过explain查看执行计划
31.Freemarker静态化?
在做XX电商项目的时候,考虑到提高网站前台的性能,承受更大的并发,我们将网站首页和很多文章页面都进行了静态化。当时采用的方式是通过freemarker模板引擎和spring定时器来结合完成的。前台美工通过网站管理后台用freemarker编写首页模板以及相关的样式,之后将模板信息存入模板表,我负责编写spring定时器在每晚的凌晨从数据库中的模板表中取出各种类型的模板并和相关的数据结合起来生成静态的html页面。并且考虑到减少前台美工编写freemarker标签的难度,我将经常用到的一些功能像分页,列表展示等通过#macro编写为freemarker的宏命令,方便前台美工直接使用。对于及时性要求比较高的特别热门的频道,则在用户点击发布时直接调用编写的接口通过freemarker和数据结合生成html静态页面。
32.Redis分布式缓存?
redis是一个基于key,value的支持多种数据类型(String,List,Set,zSet,Hash)的可进行持久化的内存数据库。我们在项目中通常使用redis来充当缓存服务器来缓存分类列表,品牌列表,热销商品,推荐商品以及该商品的关联商品等等。以前做项目的时候,我们是把商品的信息存放在redis里面,redis支持多种数据类型,有两种方法存储对象:1,可以把对象序列化进行存储,然后反序列化取出。2.用hash结构存储,最后发现,还是用hash存取比较快
当时我们就是在redis中设置maxmemory【最大内存】,把maxmemory-policy【数据清除策略】设置为allkeys-lru。为了保证redis不会因为占用内存过大而导致系统宕机,也会设置最大内存和数据清除策略。使用了jedis作为客户端,并考虑到性能问题使用了jedis连接池。考虑到redis服务器的高可用性,我们做了redis的主从复制,刚开始配置redis的时候,我是关闭它的保护模式,虽然实现了功能,但是不安全,最后是在redis.conf配置文件中绑定具体的ip地址,这样只有该ip地址才能访问redis服务器,并且设置长度为20位左右的密码,从而保证只有进行了密码授权才能进行相关的操作,为了信息安全,我们配置了redis的主从复制,在从服务器的配置文件中通过配置slaveof绑定主服务器的ip地址和端口号,
当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库
快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。
哨兵要监视 Redis 服务器,就必须连接 Redis 服务器。启动哨兵的时候需要指定一个配置文件,程序初始化的时候会读取这个配置文件,获取被监视 Redis 服务器的 IP 地址和端口等信息。
哨兵连接redis服务器发送两个连接一个是普通连接,另一个是订阅发布专用连接。哨兵在初始化订阅发布连接的时候,做了两个工作:一是,向 Redis 服务器发送 SUBSCRIBE SENTINEL_HELLO_CHANNEL命令;二是,注册了回调函数 sentinelReceiveHelloMessages()。
哨兵会向 hello 频道发送包括:哨兵自己的IP 地址和端口,runid,当前的配置版本;其所监视主机的 IP 地址,端口,当前的配置版本。【这里要说清楚,什么是 runid 和配置版本】虽然未知的信息很多,但我们可以得知,当一个哨兵新加入到一个 Redis 集群中时,就能通过 hello 频道,发现其他更多的哨兵,而它自己也能够被其他的哨兵发现,哨兵向与 Redis 服务器的命令连接通道上,发送了一个INFO 命令(字符串);并注册了回调函数sentinelInfoReplyCallback()。Redis 服务器需要对 INFO 命令作出相应,能在 redis.c 主文件中找到 INFO 命令的处理函数:当 Redis 服务器收到INFO命令时候,会向该哨兵回传数据,包括:
关于该 Redis 服务器的细节信息,rRedis 软件版本,与其所连接的客户端信息,内存占用情况,数据落地(持久化)情况,各种各样的状态,主从复制信息,所有从机的信息,CPU 使用情况,存储的键值对数量等。
由此得到最值得关注的信息,所有从机的信息都在这个时候曝光给了哨兵,哨兵由此就可以监视此从机了。
Redis 服务器收集了这些信息回传给了哨兵,刚才所说哨兵的回调函数 sentinelInfoReplyCallback()会被调用,它的主要工作就是着手监视未被监视的从机;完成一些故障修复(failover)的工作。连同上面的一节,就是Redis 的 auto discover 的全貌了。
在哨兵的定时程序中,哨兵会向所有的服务器,包括哨兵服务器,发送 PING 心跳,而哨兵收到来自 Redis 服务器的回应后,也会更新相应的时间点或者执行其他操作,哨兵不仅仅凭借自己的信息,还依据其他哨兵提供的信息判断 Redis 服务器是否下线的方法称为客观方法,即通过所有其他哨兵报告的主机在线状态来判定某主机是否下线。
一个 Redis 集群难免遇到主机宕机断电的时候,哨兵如果检测主机被大多数的哨兵判定为下线,就很可能会执行故障修复,重新选出一个主机。一般在 Redis 服务器集群中,只有主机同时肩负读请求和写请求的两个功能,而从机只负责读请求,从机的数据更新都是由之前所提到的主从复制上获取的。因此,当出现意外情况的时候,很有必要新选出一个新的主机。
优选选择优先级高的从机
优先选择主从复制偏移量高的从机,即从机从主机复制的数据越多
优先选择有 runid 的从机
如果上面条件都一样,那么将 runid 按字典顺序排序
并且通过加入哨兵来使redis主服务器宕机时,从服务器自动转换为主服务器继续提供服务。
33.jdbc操作数据库的步骤?
①加载数据库驱动程序(Class.forName("数据库驱动类");)
②连接数据库(Connection con = DriverManager.getConnection();)
③操作数据库(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
④关闭数据库,释放连接(con.close();)
34.悲观锁,乐观锁?
悲观锁/乐观锁:
悲观锁(Pessimistic Lock), 每次去查询数据的时候都认为别人会修改,
所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
传统的关系型数据库里边就用到了这种锁机制,比如通过select ....for update进行数据锁定。
乐观锁(Optimistic Lock), 每次去查询数据的时候都认为别人不会修改,
所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,
可以使用版本号,时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
35.Spring中事务的隔离级别,传播特性?
spring中事务的传播特性好像有5个左右,
我做项目的时候使用最多的就是PROPAGATION_REQUIRED,
它所代表的意思支持当前事务,如果当前没有事务,就新建一个事务。
spring中事务的隔离级别有5个,默认使用的是ISOLATION_DEFAULT,
它代表使用数据库默认的事务隔离级别,也是我们项目中最常使用的。
除此之外还有
读未提交:
它充许另外一个事务可以看到这个事务未提交的数据,
这种隔离级别会产生脏读,不可重复读和幻像读。
读提交:
保证一个事务修改的数据提交后才能被另外一个事务读取,
也是大多数数据库的默认值。可以避免脏读,但会产生不可重复读和幻像读。
重复读:
在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
串行化:
顺序执行事务。除了防止脏读,不可重复读外,还避免了幻像读。
并发性也最低,但最安全。
不可重复读的重点是修改 :
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了 。
幻读的重点在于新增或者删除 :
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样。
36.MongoDB概述?
mongodb是一个nosql数据库,我们在项目中通常用它来存储评论信息,
【评论id,商品id,标题,评分,内容,评论人信息,评论的发布时间】
因为每个商品都会有评论信息,而且某些热门商品的评论信息可能是数千条,
mongodb正好适用于这种大数据量、高并发、弱事务的互联网应用。考虑
到mongodb的高可用性我们搭建了3台mongodb数据库来实现副本集,这样
不仅可以达到故障自动转移的特性而且也可以通过读写分离提高性能,即便
主服务器宕机了,还会通过投票选举出下一个主服务器继续提供服务。
再者考虑到我们的项目最后要部署到多台tomcat通过nginx来实现负载均衡,
为了对项目中的文件以及图片进行统一的管理,我们就用mongodb来充当文件服务器。
对于大部分的单张图片和单个文件来说小于16M,所以我们就以常规的方式来将
文件转换为二进制的字节数组进行保存。考虑到高可用性以及为了应对后期随着文件数量的不断
增加而能够方便进行扩容,我们建立了3个分片并将分片和副本集做了整合,每个分片都是一个副本集,这样
不仅满足了大数据量的存储也避免了分片中单台机器导致的单点故障问题。考虑到可能要处理
大于16M的文件,所以又增加了支持大文件存储的gridfs,这样即便再大的文件也会被gridfs分解为多个
chunk进行存储。
37.Easyui概述?
我们在项目中通常用EasyUI来充当展示层,因为它是一个RIA富客户端框架,
自身提供了很多功能强大的插件,可以提高用户的体验度而且也有助于我们
开发人员直接使用,提高开发效率。我们在项目中使用到的EasyUI插件有Layout布局,
EasyUI的tree,Tab页面,datagrid,form表单,Dialog对话框,Messager提示信息还有
Accordion手风琴效果,progress进度条等。
EasyUI的tree的生成方式有两种,一种是通过一条sql语句查询所有的菜单信息,
然后在java中通过递归的方式将其拼装成符合指定json格式的数据,这种适用
于数据量比较小的情况,通过减少数据库的访问次数提高性能,另一种是通过
ajax异步加载的方式,每点击一下树节点就向后台发送一次请求,从而来获取
该节点下的子节点,这种适用于数据量比较大的情况。这时候如果采用取出全
部数据递归拼装的话就有可能出现内存溢出。
我们当时在项目中是通过Easyui的tree来生成菜单,考虑到菜单的
数据量也不是特别的大,所以就采用了第一种取出所有数据并递归将其
拼装成指定Json的方式来提高性能,再者考虑到每个用户的菜单信息并
不是经常改变,所以又结合oscache缓存以及带有双重判定锁的单例模式
将其缓存到内存中,从而再次提高了性能。
在点击树形菜单,动态添加tab页的时候一定要注意,为了避免每次点击
都添加一个新的tab页,我们的做法是当点击事件发生时,先判断当前
选中的菜单所对应的tab页是否已经存在,如果存在就将其激活选中,否则
再添加新的。多个tab页出现的另一个问题就是不同tab页间的数据可能不
同步,所以我们会在每个tab页上面都增加一个刷新按钮,可以通过点击
该按钮给该tab页所对应的iframe的src属性重新赋值,来起到刷新的作用。
datagrid也是我们在项目中经常使用到的,在使用datagrid时应该注意的是
在拼装好的json数据中,需要有total和rows这两个属性,其中total用来
指明数据的总条数,rows用来指明当前页的数据列表;在前台页面中要保证
columns中的field和rows中的属性名相对应,否则数据就展现不出来,而且
对于图片等制定格式数据的展示需要结合formatter对其进行格式化才能进行
正确的显示。最后就是在datagrid和form表单结合进行数据查询时调用的是
load方法,进行增删改后刷新datagrid调用的是reload方法。
38.BootStrap概述?
Bootstrap是一个支持响应式的Css框架它提供了很多组件,
如导航条,面板,菜单,form表单,还有栅格,
而且他们这些都是支持响应式的,可以在各种
设备上进行完美的展现。这里面我感觉最有价值的就是
bootstrap提供的栅格系统,这个栅格系统将
整个页面分为12列,而且可以根据屏幕的宽窄进行自动
调节,这也是响应式的关键所在。在使用栅格系统的时候
要注意最外层样式是Container,里面是row,row里面包含
的是列,列里面可以用来填充各种各样的组件。
我在项目中使用bootstrap完成的情况大概是这个样子,
首先我使用了bootstrap的导航条,并将其固定在顶部,
使其在拖拉滚动条的时候不至于看不到,
之后在导航条的下面采用了bootstrap的栅格系统将其分为左右两部分,
左边使用bootstrap的Treeview组件,将菜单展现出来,当点击treeview
上的菜单节点时结合一个第三方的tab组件,将需要展示的内容放到tab页内,
并进行上下切分,上面使用了bootstrap的form组件,
下面使用了它的响应式表格以及分页组件,在进行增加修改时,
使用了第三方的bootbox弹出框。
39.Innodb和MyISAM的区别?
基本来说MyISAM类型不支持事务处理而InnoDB类型支持。
MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快,
但是不提供事务支持,而InnoDB提供事务支持以及外键。
MySQL主从复制 读写分离【主动】
我们在项目中的关系型数据库采用的是MySQL,考虑到对事务的支持使用的是InnoDB引擎,
为了保证数据库数据的安全,达到高可用性,以及分担服务器压力我们对MySQL进行了主从复制
的配置并结合MyCat这个数据库中间件进行读写分离。我们项目 目前采用的是一主带2或者3从的架构。
因为互联网项目一般都是读的多,写的少,所以通过这种一主多从的架构分担了单台数据库的压力
并且在一台服务器宕机的情况下也能保证项目的基本运行。
主从复制的配置步骤:【被动】
主从复制的配置比较简单,最主要是开启主服务器的二进制日志并指明一个唯一的
标识,从服务器也要指明一个唯一的标识,并且在主服务器上创建账号,开启复制权限;
在主服务器上运行show master status查看主服务器的状态,之后在从服务器上用刚才
建立的账号连接指定的的主服务器,并指明要复制的二进制文件以及起始位置,
最后运行start slave就可以了,然后通常运行show slave status查看从服务器的状态,
如果slave_io和slave_sql为yes,就证明配置成功了。
主从复制的运行原理:【被动】
最主要就是主服务器上的二进制日志以及从服务器上的IO线程,SQL线程,以及中继日志。
主服务器将其自身的改变存入到二进制日志中去,从服务器连接主服务器并通过IO线程读取
主服务器上的二进制日志,将读取的内容存入自身的中继日志,之后SQL线程会读取中继日志
中的sql语句对其进行执行,这样就保证了从服务和主服务器的一致性。MySQL的主从复制默认
是基于sql语句进行的。
40.你上家公司在哪?你在哪住?你去公司怎么坐车?
北京市海定区阜外亮甲1号中关注联网创意产业园27号楼 (丰台区)
海淀区蓝靛厂 晨月园小区 远大路公交站上车 355/79/118线都能到 坐六站(定慧北桥下车)走大概5分钟就到了
公司附近 在那边有一个丰台科技原生态主题公园
晨月园附近有个巨人学校
从育新坐606路公交到成府路南口下车然后在步行到公司
41.你期望薪资多少?你上家工资多少?税后拿到手的有多少?扣了多少钱的税?
15K 14K 13K 1000
42.你哪个学校毕业的?学的什么专业?你们学校校长叫什么名字?你们学校还有啥其他专业吗?你大学都学了什么?
郑州理工专修学院 计算机科学与技术 刘信古
有,还有,酒店服务管理 建筑工程 行政管理 轨道交通运营 等等。。。
计算机原理 计算机网络 高级语言 编程语言 操作系统 数据结构
43.你今年多大了?属相是啥?
26 马
44.你为啥从上家公司离职?
合同到期,想换一个新的环境,公司这边也挽留我,但是在公司也呆了,2.3年了,
想换一个新的平台,来不断提升充实自己。
45.你交社保了吗?为啥没交?
在上家公司的时候,人事说咱们公司的五险一金如果要上的话都是从自己工资里面扣的,
当时感觉没啥必要也就没上。
46.你的优缺点是啥?
这几年做程序,因为要不断的对代码进行验证确认,所有感觉自己现在有点强迫症。
47.你的五年规划是啥?
前2,3年继续加强自己的技术功底,然后朝着项目经理(技术经理,产品经理)方面发展
48.你啥时候上的大学?哪年毕业的?从火车站怎么到你们学校?你们学校周围都有啥?
2008年9月 2012年6月 下了火车打个车10来块钱
(吹牛逼的活) 有一些卖衣服的 卖吃的 小超市 酒店什么的....
49.你知道五险一金都是啥吗?
养老保险,医疗保险,失业保险,工伤保险,生育险 住房公积金
50.你们公司有多少人?你们公司有哪几个部门?
60人左右 技术部 销售部 行政部 人力资源部 财务部
51.你对ajax是怎么理解的(融入ajax跨域的解决方案)?
ajax全称是异步javascript及xml;
ajax的核心JavaScript中的xmlHttpRequest(XHR);
使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域,所谓不能跨域就是不能跨多个网站(多个域名),不能跨多个项目可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的
52.Ajax超时、Ajax同步异步、原生的Ajax
Ajax是默认没有超时时间,如果我们想要ajax超时在ajax中有一个timeout这个属性设置它的时间是根据秒来设置
Ajax 异步是跳转页面加载一部分数据当点击按钮的时候加载另一部分数据这样的使用于大数据量的加载
Ajax同步 是跳转页面一下子执行了说有的ajax请求加载了所有的数据这样的如果在大量数据中页面会卡
Ajax中有async属性 async =”true”是同步flase是异步 默认的是异步
原生的ajax是xmlhttprequest
53.你对webservice是怎么理解的?
(主动说)
webservice是SOA(面向服务编程)的一种实现,
主要是用来实现异构平台通信也就
是不同平台不同项目之间的数据传输,从而避免了信息孤岛的问题,
它之所以能够
进行异构平台通信是因为它是完全基于xml的,
所以说,webService是跨平台,
跨语言,跨框架的,在java中通常有三种技术框架分别是xfire,cxf,axis2。
我们为了保证
webservice的安全性,采用了基于
WS-Security标准的安全验证(使用回调函数)。
(没必要主动说)
webservice的三要素分别是:
wsdl(webservice description language)
用来描述发布的接口(服务)
soap(simple object access protocol)
是xml和http的结合,是webservice数据通信的协议
uddi 用来管理,查询webService的服务
(没必要主动说)
webservice的具体三种实现方式(框架)或者三种实现框架的区别
1. Axis2:可以用多种语言开发,
是一个重量级框架,功能非常强大,
但是它的性能比较低。
2. Xfire:它相比Axis2来说是一个轻量级框架,
它的性能要比Axis2高。
3. cxf:是Xfire的升级版,就好比是,
struts2是webwork的升级,
然后cxf和spring集成起来非常方便,简易,
性能方面也要比Xfire高。
【注】jdk6 自带的webservice jws
(主动说)
业务场景
我在以前做项目的时候,其中遇到一个功能,
需要进行两个项目之间的数据的传输,
项目经理让我去完成这个任务,我根据以往的项目经验,
想到两种解决方案,第一种
就是开放另外一个项目的数据库的权限给我,
然后我直接通过访问另外一个项目的数据
库,来得到需要的信息,但后来我分析了下,觉的这种方式不安全,
而且因为当时
这个项目是另外一家公司负责在做,所以数据库里面的表结构,
以及以后牵涉
到的责任问题都很多,所以我就采用了第二种方案,
即通过webservices的方式,进行
异构系统之间数据信息的传递,webservices的具体实现,
有xfire,cxf,axis2,
我根据以往的项目经验,了解到cxf是xfire的升级版本,适用于java语言,
xfire/cxf 性能比axis2要高,并且和spring整合起来也比较方便,
而axis2支持更多的语言,
性能相对于cxf要低,通过上面分析,
结合我们目前的两个项目都是基于java
语言的,所以我采用cxf这种方式实现了两个项目之间数据的传递,
我们为了保证
webservice的安全性我们采用了基于
WS-Security标准的安全验证(使用CXF回调函数)。
(没必要主动说)
webservice服务端配置流程
首先在web.xml中引入cxfServlet核心类,
指定对以/cxf开头的url路径提供webservice服务,
之后我们在要发布成webservice接口上添加@Webservice 注解,
而且还要在实现类上添加同样的webservice注解并且要说明实现了哪个接口,
之后在spring-webservice.xml中发布webservice服务,
通过jaxws:endpoint这个标签,
并且在标签配置implementor和address来表明实现服务的类,
以及发布的地址,
最后在浏览器中输入相关的webservice地址?wsdl来验证服务是否发布成功。
(没必要主动说)
webservice客户端的配置
首先通过wsdl2java根据发布的webservice服务端地址的wsdl
生成客户端调用的中间桥梁java类,
将生成的java类拷贝到客户端项目中,
配置spring-client.xml文件,
通过jaxws:client定义一个bean,
并通过address属性指明要访问的webservice的服务地址,
通过serviceClass指明充当中间桥梁的服务类,之后获取该bean,
就可以通过它来访问发布的webservice接口中的方法。
54.你对负载均衡这块有认识吗?
负载均衡:
(了解)
我们在做这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增加硬件的配置提高其性能,但这样做比较耗费资金,而且服务器内存空间也是有限的;所以后来就使用横向扩展来达到这一目的.
(主动说)
当时我们使用nginx(n g 个 s)+3个tomcat进行负载均衡,在我们不进行负载均衡之前,那所有的请求都由一台tomcat进行处理,这样会使我们的tomcat所承受的压力增大,而我们进行负载均衡之后,同样数量的请求经过nginx将其分发到多台tomcat进行处理,从而降低每台tomcat所承受的压力,而且当其中一台机器宕机时,其他机器还可以继续提供服务,保证服务不间断。
当时项目在部署完成后,遇到这么个问题,用户登录输入验证码的时候,明明验证码输入的正确,但总是提醒说验证码不正确从而不能正常登录,经过分析后发现有可能第一次
请求被发送到t1上,那么放在session中的验证码就被放到了t1上,当用户输入验证码点击登录时,新发送的请求有可能被发送到t2上面,这样在进行对比时就肯定会不一致从
而提示验证码输入错误,后来我就考虑使用ip_hash这种负载均衡策略来代替默认的轮询策略,虽然解决了验证码错误问题,但是在后续的测试中发现如果用户在使用过程中
突然一台服务器宕机了,那么因为session在这台服务器上存储着,所以就会提示用户重新登录,这样使用户的体验度非常不好,最后就通过将session信息保存到redis服务器中从而在
多台web服务器中实现session共享,这样就解决了上面所说的那些问题。
怎么避免nginx产生单点故障(被动说)
同时我们为了避免nginx的单点故障,达到高可用性,就在nginx的前面又加了一个F5,从而将请求分配给多个nginx,再通过nginx分配给多个不同的Tomcat。这样大大的提高了服务的有效性,并且进一步提高了性能。
55.你在linux上怎么部署项目?
1.Linux下常见的分支:
CentOS:服务端【纯开源】
RedHat:服务器端【收费】
Ubantu:个人电脑
2.访问方式:通过SSH/Putty客户端连接服务器
3.如何使用:
1.虚拟机的好处?
可以在虚拟机中随意操作系统,不怕影响或损害电脑;
2.克隆(备份):快速创建当前系统的备份,快速创建另外一个虚拟系统;
在manage 下的clone中
linked(链接克隆) 软克隆 优点:速度快,生成文件小;
full(完整克隆) 硬克隆 优点:文件大,速度比较慢;
选择桥接模式;
只查出四行 ping Ip -c 4
3.快照:可以将当前的虚拟系统快速还原到某一时刻;都是一个虚拟系统。
快照 Snapshot 下的 Take Snapshot
快照的好处:埋下几个点,方便还原
4.命令:
注意:
rpm是Linux下一种软件安转包的后缀名。如*。rpm ,等同于windows中的exe.rpm是一个命令,用来进行和软件安装相关的操作。(安转,卸载,查找)
linux下没有盘符的概念,它是通过相关的目录来管理资源的。我们通常在/home中创建文件夹来存放需要安转的软件
tab键自动补全 *代表当前目录下的所有文件
JDK默认安装在 usr/java中
设置jdk的环境变量:
修改/etc/profile文件
用文本编辑器打开 /etc/profile
在profile文件末尾加入:
export JAVA_HOME = /usr/java/jdk.1.7.0_79
export PATH = $JAVA_HOME/binL$PATH
source /etc/profile 使修改立即生效
echo $PATH 查看PATH值
56.你对linux中的常用命令都了解哪些?
1.ifconfig:查看IP地址
2.java -version :查jdk的版本
3.rpm -qa | grep 软件的名称 :查找和指定名称相关的软件
4.rpm -e --nodeps 软件的名称 :卸载指定的软件
5.rpm -ivh 软件名称 :安装指定的软件
6.uname -a 查看Linux系统的基本信息(计算机名,操作位数,版本号)
7.LL 查看文件夹下的文件
8.mkdir
以上是关于Java面試題(实用性高)的主要内容,如果未能解决你的问题,请参考以下文章