java面试题整合(持续更新)


Redis是如何实现list存储的

 List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样 ,我们可以在其头部(lf)和尾部(right)添加新的元素。

在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。

SpringMVC的优势、基本原理以及大概的流程

   springmvc是一个轻量级IOC容器框架,拥有一致的事务管理和面向切面工程。

   1.Spring其他框架无缝结合,是其他web框架所不具备的

   2.可适配,通过HandlerAdapter可以支持任意的类作为处理器

   3.利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;

   4.强大的JSP标签库,使Jsp编写更容易。

 ①. Springmvc将所有的请求都提交给 中央调度器Dispatcherservlet

   ②. Dispatcherservlet收到请求调用 Handl ermapping处理映射器

   ③.处理映射器找到具体的处理器,生成处理器对象返回给 Dispatcherservlet

   ④. Dispatcherservlet调用 Handl eradapter处理器适配器

   ⑤. Handl eradapter经过适配调用具体的处理器 Controller

   6. Controller进行业务逻辑处理后,会返回一个 Modelandview

   ⑦. Handl eradapter将 Controller执行结果 Modelandview返回给 Dispatcherservlet

   ⑧. Dispatcherservlet将 Modelandview传给Viewresolver视图解析器

   ⑨. Viewresolver解析后返回具体的View

   ⑩ Dispatcherservlet根据View进行渲染视图并响应用户

 

JSP和servlet 的区别

   (1).jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)

   (2).jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.

   (3).Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象, HttpServletResponse对象以及HttpServlet对象得到.

 

Java中是 怎么解析xml的

  (1) DOM(JAXP Crimson解析器)

DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。

由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。

   (2)SAX  

SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。

   (3)JDOM

    JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。

   (4)DOM4J 

它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。

 

MySQL数据库的索引有哪几种?有什么区别?

  (1)普通索引。最基本的索引,它没有任何限制,用于加速查询。

  (2)唯一索引。索引列的值必须唯一,但允许有空值。

  (3)主键索引。是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般 是在建表的时候同时创建主键索引。

  (4)组合索引。指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。

  (5)全文索引。主要用来查找文本中的关键字,而不是直接与索引中的值相比较。

 

class.forName是什么意思

   返回与给定的字符串名称相关联类或接口的Class对象。

   是一个静 态方法,同样可以用来加载类。该方法有两种形式:Class.forName(String name, boolean initialize, ClassLoader loader)和 Class.forName(String className)。

  第一种形式的参数 name表示的是类的全名;initialize表示是否初始化类;loader表示加载时使用的类加载器。

  第 二种形式则相当于设置了参数 initialize的值为 true,loader的值为当前类的类加载器。

几种造线程池的方法,区别

   (1)newFixedThreadPool

定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程

   (2)newCachedThreadPool

可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制

   (3)newScheduledThreadPool

定长线程池,可执行周期性的任务

   (4)newSingleThreadExecutor

单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行

   (5)newSingleThreadScheduledExecutor

单线程可执行周期性任务的线程池

   (6)newWorkStealingPool

任务窃取线程池,不保证执行顺序,适合任务耗时差异较大。默认创建的并行 level 是 CPU 的核数。主线程结束,即使线程池有任务也会立即停止。

 

面向服务通过什么样的方式实现?

   面向服务SOP)是一种体系结构,目标是在软件代理交互中获得松散耦合。一个服务是一个服务提供者为一个服务消费者获得其想要的最终结果的一个工作单元

   Web Service是面向服务编程的方式之一

https://blog.csdn.net/hu_zhiting/article/details/50594633

   原理:

     (1)Web Service采用SOAP协议实现跨编程语言和跨操作系统平台。

     (2)Web Service采用HTTP协议传输数据,采用XML格式封装数据(即说明调用什么方法,传递什么参数,返回结果是什么)。

    (3)Web Service通过HTTP协议发送请求和接收结果时,发送的请求内容和结果都采用XML格式封装,并增加一些特定的HTTP消息头,说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式便是SOAP协议(即HTTP协议+XML数据格式)。

 

消息中间件 acitveMQ 的作用、原理?几种模式,每种的特点及使用问题?MQ 发送消息失败怎么办?

   作用:消除高并发访问高峰,加快网站的响应速度。

   消息中间件的两种消息传递模式

    (1)点对点消息通信型:也称为队列模式,一条特定的消息只给一个特定的消费者,消费完成之后就从持久化存储中删除该数据,生产者将消息发送到指定的队列(queue)中,此时对于消费者来说,获取消息有两种方式.分别是pull和push,其中push方式是activeMQ接收到消息之后去调用消费者的新消息通知接口,相当于activeMQ去通知消费者,但是这样会浪费activeMQ的宝贵线程资源.而pull方式,是消费者循环调用activeMQ的api去获取消息,这样不会消耗activeMQ的线程资源,并且消费者更加主动.push方式由于过多占用activeMQ的线程资源而难以应对高并发,所以并不适用.

    (2)发布/订阅模式:也称为主题模式,特定的一条消息可以被多个消费者接收,只要消费者订阅了某个主题.消息的生产者会将消息发布到名称为topic的虚拟通道里面去,topic是可以被多个消费者订阅的.这个模式类似于广播模式,但是要求消费者在线监听,如果消费者离线,再次上线是无法获取该消息的,发布/订阅模式采用的是pull方式把消息发送给消费者.

Tomcat 集群中怎么实现共享

1) 请求精确定位

        例如基于访问IP地址的Hash策略,即当前用户的请求都集中定位到一台服务器中,这样单台服务器就会保存用户的Session登录信息。

        但是如果宕机,则等同于单点故障,保存用户的Session登录信息就会丢失,会话不复制。

2) Session复制共享

        例如Tomcat自带Session共享,主要是指集群环境下多台应用服务器之间同步Session,使Session保持一致,对外则是保持透明。

        如果其中一台服务器发生故障,根据负载均衡的原理,调度器会遍历寻找可用节点来分发请求。由于Session已同步,所以能够保证用户的Session信息不会丢失,也就是所谓的会话复制。

 

在数据库怎么复制表数据和表结构?

   (1)复制表结构及数据到新表

         CREATE TABLE 新表 SELECT * FROM 旧表

   (2)只复制表结构到新表

        CREATE TABLE 新表 SELECT * FROM 旧表 WHERE 1=2或CREATE    TABLE 新表  LIKE 旧表

   (3)复制旧表的数据到新表(假设两个表结构一样)

        INSERT INTO 新表 SELECT * FROM 旧表

   (4)复制旧表的数据到新表(假设两个表结构不一样)

        INSERT INTO 新表(字段1,字段2,.......) SELECT 字段1,字段2,...... FROM 旧表

From表单提交的方法、属性,数据量大的时候用什么方法提交?

   GET

提交的数据格式跟元素的method属性有关。该属性指定了提交数据的 HTTP 方法。

如果是 GET 方法,所有键值对会以 URL 的查询字符串形式,提交到服务器,比如/handling-page?user_name=张三&user_passwd=123&submit_button=提交。

POST

如果是 POST 方法,所有键值对会连接成一行,作为 HTTP 请求的数据体发送到服务器,比如user_name=张三&user_passwd=123&submit_button=提交。

FormData(XMLHttpRequest.sendf方法)

表单数据以键值对的形式向服务器发送,这个过程是浏览器自动完成的。但是有时候,我们希望通过脚本完成过程,构造和编辑表单键值对,然后通过XMLHttpRequest.send()方法发送。浏览器原生提供了 FormData 对象来完成这项工作。

数据量大

form中添加属性enctype="multipart/form-data"使用文件上传的方式,不过这样后台取表单数据的方法就需要修改.

只能循环fileItemList去取出表单数据.

  1. Java多线程中哪种方式不会使线程进入阻塞状态

   yield会是线程进入就绪状态

  1. shiro的工作流程?怎么认证?怎么授权?

   (1)shiro中获取subject主体

        SecurityUtils.getSubject();

   (2)判断当前用户是否认证过了,如果认证过了就放行了

         subject.isAuthenticated()

   (3)如果没有认证过,就把前台传递的账号密码封装为一个UserNamePasswordToken对象,

          new UsernamePasswordToken(username, password);

   4)UserNamePasswordToken对象传入,进行登录操作

        subject.login(usernamepasswordtoken);

   (5)我们配置的安全管理器中实现了doGetAuthenticationInfo方法,从数据库查询用户数据,加密加盐后进行shiro的认证

   (6)如果认证成功,进行权限赋于。

   (7)根据配置shiro的真实过滤器跳转至登录成功页面或登录失败的页面。

     认证过程

     授权

服务器宕机如何处理?全部宕机如何处理?

服务器宕机

    (1)对于服务器频繁出现宕机情况就要注意了检查服务器是否存在负载量过大,服务器散热存在问题等等情况。再针对这样的情况一项一项来解决,这样才能保证服务器尽可能长时间正常运       行。

   (2)对于一般服务器宕机,我们可以采用重启服务器的方式来解决。正常重启服务器可以清除内存碎片,重新优化应用软件,中断无用的端口,缓解CPU压力,加快服务器运行速度等等。

   (3)对于服务器租用用户来说,服务器宕机是非常值得重视的问题,如果租用的服务器经常出现宕机情况的话,一定要及时通知服务商,让服务器查明具体情况,问题过于严重甚至可以要求跟换服务器或者更换服务器供应商。

     做好防范准备。可以同时运行两个网站空间,存放相同的内容,当一个出现问题时,立即启用另一个即可。

 java多线程有几种实现方法?都是什么?它们的区别?

   两种

   继承 Thread 类:多个任务由多个线程来完成,互相不干扰,各玩各的,多个线程分别完成自己的任务

   实现 Runnable 接口:一个任务由多个线程来共同完成

具体实现如下:

 多个线程输出https://blog.csdn.net/kanglix1an/article/details/46006093

JDO是 什么?说说你 对JDO的 理解

   JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。

这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)。

JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。

如何在Jsp中把div或table隐藏起来?

   Table的隐藏




Div的隐藏

1.display:none;

2.visibility:hidden;

TCP和UDP的区别?

   TCP 是面向连接的,UDP 是面向无连接的

   UDP程序结构较简单

   TCP 是面向字节流的,UDP 是基于数据报的

   TCP 保证数据正确性,UDP 可能丢包

   TCP 保证数据顺序,UDP 不保证

Servelet在多个请求时存在线程安全问题,请讲一下在servelet编程中要注意什么问题?

   (1)实现 SingleThreadModel 接口

    确保servlet每次只处理一项请求。接口不含方法。

    如果servlet实现了该接口,会确保不会有两个线程同时执行servlet的service方法。 servlet容器通过同步化访问servlet的单实例来保证,也可以通过维持servlet的实例池,对于新的请求会分配给一个空闲的servlet。

2同步对共享数据的操作

使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。

3避免使用实例变量

只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。

小结

Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。

Quartz怎么配置啊?

  Quartz有三要素:

Scheduler:调度器。所有的调度都是由它控制。

Trigger: 定义触发的条件。例子中,它的类型是SimpleTrigger,每隔1秒中执行一次(什么是SimpleTrigger下面会有详述)。

JobDetail & Job: JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中,例子中是HelloQuartz。 为什么设计成JobDetail + Job,不直接使用Job?这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

服务器集群和session的同步方法及优点?

   (1)客户端cookie加密

简单,高效。比较好的方法是自己采用cookie机制来实现一个session,在应用中使用此session实现。

问题:session中数据不能太多,最好只有个用户id。

(2) application server的session复制

可能大部分应用服务器都提供了session复制的功能来实现集群,tomcat,jboss,was都提供了这样的功能。

问题:

性能随着服务器增加急剧下降,而且容易引起广播风暴;

session数据需要序列化,影响性能。

(3)使用数据库保存session

使用数据库来保存session,就算服务器宕机了也没事,session照样在。

问题:

程序需要定制;

每次请求都进行数据库读写开销不小(使用内存数据库可以提高性能,宕机就会丢失数据。可供选择的内存数据库有BerkeleyDB,MySQL的内存表);

数据库是一个单点,当然可以做数据库的ha来解决这个问题。

(5)使用共享存储来保存session

和数据库类似,就算服务器宕机了也没事,session照样在。使用nfs或windows文件共享都可以,或者专用的共享存储设备。

问题:

程序需要定制;

频繁的进行数据的序列化和反序列化,性能是否有影响;

共享存储是一个单点,这个可以通过raid来解决。

(5)使用memcached来保存session

这种方式跟数据库类似,不过因为是内存存取的,性能自然要比数据库好多了。

问题:

程序需要定制,增加了工作量;

存入memcached中的数据都需要序列化,效率较低;

memcached服务器一死,所有session全丢。

(6)使用terracotta来保存session

memcached类似,但是数据不需要序列化,并且是Find-Grained Changes,性能更好。

配置对原来的应用完全透明,原有程序几乎不用做任何修改。而且terracotta本身支持HA。

 tomcat端口(当一台电脑上有两个tomcat 端口一样 怎么去修改 让两个tomcat一起运行)

   当第一个tomcat启动后,后面tomcat的server.xml中的端口不管怎么改,仍然会报端口冲突。后来在dos下运行才发现所有的tomcat都会去找CATALINA_HOME和CATALINA_BASE这两个环境变量,因此步骤如下:  

(1)使用压缩版的tomcat不能使用安装版的。  

(2)第一个tomcat的配置不变。  

(3)增加环境变量CATALINA_HOME2,值为新的tomcat的地址;增加环境变量CATALINA_BASE2,值为新的tomcat的地址。  

(4)修改新的tomcat中的startup.bat,把其中的CATALINA_HOME改为CATALINA_HOME2。  

(5)修改新的tomcat中的catalina.bat,把其中的CATALINA_HOME改为CATALINA_HOME2,CATALINA_BASE改为CATALINA_BASE2。  

(6)修改conf/server.xml文件:  

6.1 把端口改为没有是使用的端口。  

6.2

  maxThreads="150" minSpareThreads="25" maxSpareThreads="75"  

  enableLookups="false" redirectPort="8443" acceptCount="100"  

  connectionTimeout="20000" disableUploadTimeout="true" /> 把端口改为没有是使用的端口。  

6.3

  enableLookups="false" redirectPort="8443" protocol="AJP/1.3" /> 把端口改为没有是使用的端口。  

(7)成功!

Linux的基本命令

   ls  显示文件夹

   cd  进入目录

   mkdir  创建文件夹

   rm   删除文件或目录


线程池使用过哪些?原理是什么?

   CachedThreadPool 

这类线程池的特点就是里面没有核心线程,全是非核心线程,其maximumPoolSize设置为Integer.MAX_VALUE,线程可以无限创建,当线程池中的线程都处于活动状态的时候,线程池会创建新的线程来处理新任务,否则会用空闲的线程来处理新任务,这类线程池的空闲线程都是有超时机制的,keepAliveTime在这里是有效的,时长为60秒,超过60秒的空闲线程就会被回收,当线程池都处于闲置状态时,线程池中的线程都会因为超时而被回收,所以几乎不会占用什么系统资源。任务队列采用的是SynchronousQueue,这个队列是无法插入任务的,一有任务立即执行,所以CachedThreadPool比较适合任务量大但耗时少的任务。

FixedThreadPool

这类线程池的特点就是里面全是核心线程,没有非核心线程,也没有超时机制,任务大小也是没有限制的,数量固定,即使是空闲状态,线程不会被回收,除非线程池被关闭,从构造方法也可以看出来,只有两个参数,一个是指定的核心线程数,一个是线程工厂,keepAliveTime无效。任务队列采用了无界的阻塞队列LinkedBlockingQueue,执行execute方法的时候,运行的线程没有达到corePoolSize就创建核心线程执行任务,否则就阻塞在任务队列中,有空闲线程的时候去取任务执行。由于该线程池线程数固定,且不被回收,线程与线程池的生命周期同步,所以适用于任务量比较固定但耗时长的任务。

ScheduledThreadPool

这类线程池核心线程数量是固定的,好像和FixThreadPool有点像,但是它的非核心线程是没有限制的,并且非核心线程一闲置就会被回收,keepAliveTime同样无效,因为核心线程是不会回收的,当运行的线程数没有达到corePoolSize的时候,就新建线程去DelayedWorkQueue中取ScheduledFutureTask然后才去执行任务,否则就把任务添加到DelayedWorkQueue,DelayedWorkQueue会将任务排序,按新建一个非核心线程顺序执行,执行完线程就回收,然后循环。任务队列采用的DelayedWorkQueue是个无界的队列,延时执行队列任务。综合来说,这类线程池适用于执行定时任务和具体固定周期的重复任务。

SingleThreadPool

这类线程池顾名思义就是一个只有一个核心线程的线程池,从构造方法来看,它可以单独执行,也可以与周期线程池结合用。其任务队列是LinkedBlockingQueue,这是个无界的阻塞队列,因为线程池里只有一个线程,就确保所有的任务都在同一个线程中顺序执行,这样就不需要处理线程同步的问题。这类线程池适用于多个任务顺序执行的场景。

你最常用的设计模式是什么?优缺点?

   单例模式:保证被创建一次,节省系统开销。

工厂模式(简单工厂、抽象工厂):解耦代码。

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。

模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

 

shiro是什么?shiro用来干什么的?shiro怎么用的?

   Shiro是一个非常强大的、易于使用的、开源的、权限框架。它包括了权限校验、权限授予、会话管理、安全加密等组件。

   Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单

(注意:记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可)

   Shiro使用步骤。

1.先把账号密码传入Shiro里面的UsernamePasswordToken对象里面。

UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");

2.创建Subject对象。

Subject subject = SecurityUtils.getSubject();

3.调用 Subject.login()进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功。

try{
Subject.login(token)//调用安全管理器,安全管理器调用自定义Realm
User user = (User) subject.getPrincipal();//登陆成功后就可以通过安全管理器获得用户对象。
}catch (UnknownAccountException e) {  
        error = "用户名/密码错误";  
} catch (IncorrectCredentialsException e) {  
        error = "用户名/密码错误";  
} catch (ExcessiveAttemptsException e) {  
         // TODO: handle exception  
         error = "登录失败多次,账户锁定10分钟";  
} catch (AuthenticationException e) {  
         // 其他错误,比如锁定,如果想单独处理请单独catch处理  
         error = "其他错误:" + e.getMessage();  
}  

if (error != null) {// 出错了,返回登录页面  
         request.setAttribute("error", error);  
         return "failure";  
} else {// 登录成功  
         return "success";  
}  

4.最后调用 Subject.logout 进行退出操作

5.自定义Realm去写登陆的判断

public class UserRealm extends AuthorizingRealm {
    private UserService userService = new UserServiceImpl();

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//用户授权

        String username = (String)principals.getPrimaryPrincipal();//获取用户名

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

       authorizationInfo.setRoles(userService.findRoles(username));

  authorizationInfo.setStringPermissions(userService.findPermissions(username));//根据用户名查询权限集合
        return authorizationInfo;
    }

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//用户认证
        String username = (String)token.getPrincipal();
        User user = userService.findByUsername(username);
        if(user == null) {
            throw new UnknownAccountException();//没找到帐号
        }
        if(Boolean.TRUE.equals(user.getLocked())) {
            throw new LockedAccountException(); //帐号锁定
        }
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以在此判断或自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), //用户名
                user.getPassword(), //密码
                ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
                this.getClass().getName()  //realm name
        );
        return authenticationInfo;
    }
}

   tomcat 与?nginx,apache的区别是什么?Nginx和Apache各有什么优缺点?

   (1)Apache

Apache HTTP服务器是一个模块化的服务器,可以运行在几乎所有广泛使用的计算机平台上。其属于应用服务器。Apache支持支持模块多,性能稳定,Apache本身是静态解析,适合静态HTML、图片等,但可以通过扩展脚本、模块等支持动态页面等。

(Apche可以支持PHP ,cgi(外部应用程序与Web服务器之间的接口), perl,但是要使用Java的话,你需要Tomcat在Apache后台支撑,将Java请求由Apache转发给Tomcat处理。) 缺点:配置相对复杂,自身不支持动态页面。

(2)Tomcat:

Tomcat是应用(Java)服务器,它只是一个Servlet(JSP也翻译成Servlet)容器(这里什么是Servlet和JSP可以参考后续文章),可以认为是Apache的扩展,但是可以独立于Apache运行。

(3)   Nginx

Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”,是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP (这三个是什么可以参考我的这篇文章 )代理服务器。

Nginx和Apache两者优缺点比较

Nginx 配置简洁, Apache 复杂 ;

Nginx 静态处理性能比 Apache 高 3倍以上 ;

Apache 对 PHP 支持比较简单,Nginx 需要配合其他后端用;Apache 的组件比 Nginx 多

apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程;

nginx处理静态文件好,耗费内存少;

动态请求由apache去做,nginx只适合静态和反向;

Nginx适合做前端服务器,负载性能很好;

Nginx本身就是一个反向代理服务器 ,且支持负载均衡

mysql性能优化举例

   (1)选择正确的存储引擎  

   (2)用Not Exists 代替Not In

   (3)对操作符的优化 尽量不采用不利用索引的操作符

   (4)mysql分库分表:

https://jingyan.baidu.com/article/03b2f78c2ec6035ea337ae7f.html

IO流了解吗?它们的区别是什么?

   Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。

   区别:

      1) 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;

       (2)字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。

Spring boot 自带的定时任务与Quartz定时任务的区别

   spring3.0以后自带的scheduletask任务调度,可以实现quartz的大部分功能,不需要额外引用jar,也不需要另外配置。而且支持注解和配置文件两种。

Quartz 定时任务,这是一个功能很强大的开源的专门用于定时任务调度的框架,也很好的和springboot整合,缺点:配置复杂,需要花费一定的时间去了解和研究,选择quartz任务Tigger能够被持久化,这样即使在发布后,任务依然能够执行,不需要重新设定,能够轻松暂停恢复触发器(即下次不会被调度)。

 

正则表达式以及常用String类方法

  常用的正则表达式:https://blog.csdn.net/ZYC88888/article/details/98479629

   string类方法:

   (1)获取字符串的长度 方法:public int length()

(2)返回字符串中指定位置的字符;public char charAt(int index)

(3)查找字符串在字符串中的位置 方法:public int indexOf(String str)

(4)截取字符串的方法:public String substring(int beginIndex, int endIndex)

(5)字符串比较方法:

该方法是对字符串内容按字典顺序进行大小比较,通过返回的整数值指明当前字符串与参数字符串的大小关系。若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。

public int compareTo(String anotherString)

(6)对字符串中的字符进行大小写转换方法:

转换成大写

public String toUpperCase()

转换成小写

public String toLowerCase()

https://jingyan.baidu.com/article/3ea5148995320b52e71bba40.html

多线程同步机制

   一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁);

  如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池 等待队列中)。

  取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中 等待的某个线程就可以拿到锁执行同步代码了。

  这样就保证了同步代码在统一时刻只有一个线程在执行。

众所周知,在Java多线程编程中,一个非常重要的方面就是线程的同步问题。

关于线程的同步,一般有以下解决方法:

1)在需要同步的方法的方法签名中加入synchronized关键字。

(2) 使用synchronized块对需要进行同步的代码段进行同步。

(3)使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。

https://blog.csdn.net/hanghangaidoudou/article/details/81606223

IO流中的设计模式

IO流涉及的装饰者设计模式:

FileInputStream inputStream=new FileInputStream(file);

//把inputStream装饰成BufferedReader来成为具备缓冲能力的reader
BufferedReader reader=new BufferedReader(inputStreamReader);

IO流涉及的适配器设计模式:

FileInputStream fileInput=new FileInputStream(file);

//把fileInput文件字节流,通过适配器(InputStreamReader转换流)变为字符流
InputStreamReader input=new InputStreamReader(fileInput);

装饰者模式:

  给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例(各种字符流键装饰,各种字节流间装饰)。

适配器模式

        有时候我们需要实现一个接口,但那个接口可能有很多抽象方法,我们只需要其中一个或多个方法。这时候我们可以创建一个类(适配器)实现接口,并重写接口中所有方法(空方法,有方法体,但方法体中无内容)。

       当我们需要接口中的某个方法时,只需继承类似于适配器的类 ,然后重写对应的方法即可。  将某个类的接口转换成我们期望的另一个接口表示,目的是消除由于接口不匹配所造成类的不兼容问题(字符流与字节流间互相适配)。

jbos与tomcat区别与优缺点

     1. TomcatApache鼎力支持的Java Web应用服务器(注:servlet容器)

         由于它优秀的稳定性以及丰富的文档资料,广泛的使用人群,从而在开源领域受到最广泛的青睐。

 

      2. Jboss作为Java EE应用服务器,它不但是Servlet容器,而且是EJB容器

    从而受到企业级开发人员的欢迎,从而弥补了Tomcat只是一个Servlet容器的缺憾。

 为什么需要装箱和拆箱?

把一个基本类型包装成一个类,一个是可以使这个类型具有很多可以调用的方法。
二个是Java向面像对象语言的靠近。其实Java还不算是很纯的面向对象的语言。
真正的面向对象,是没有基本数据类型的。它只有一种类型,就是对象。
三个是在泛型中,基本类型是不可以做泛型参数的。
如:List list = new ArrayList ();这是不合法的。
你只能这个样写List list = new ArrayList ();也就是要用int型的包装类类型来解决基本类型不可以做泛型参数的问题.
拆箱装箱示例代码:

 讲一下JAVA中的集合

List 接口

List接口是有序的集合,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素和空元素

  • ArrayList
    是以一种类似数组的形式进行存储,因此它的随机访问速度极快,能在遍历和随机访问时提供更好的性能。该类是非同步的,在多线程环境下需要自己手动管理线程的同步问题。
  • LinkedList
    是以一种基于链表数据结构的集合类,适用于需要进行频繁的插入、删除操作的数据集。该类是非同步的,可以通过List list = Collections.synchronizedList(new LinkedList(...))构造一个同步的List集合。
    PS:Collections是一个很好用的集合工具类哦。

Set接口

Set 接口是无序的集合,Set 不保存重复的元素。

  • HashSet
    该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个,并且存放到HashSet中的对象需要实现hashCode()方法。
  • TreeSet
    该类实现了Set接口,将放入其中的元素按序排放,可以实现排序等功能,这就要求你放入其中的对象是可排序的,需要使用到集合框架提供的另外两个实用类ComparableComparator

Map接口

Map是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。

  • HashMap
    HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。该类根据键的hashcode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
  • TreeMap 
  • 该类继承自AbstractMap,将放入其中的元素对键按序排放

线程的实现方式?怎么启动线程?怎么区分线程?

实现方式:

   继承 Thread 类:多个任务由多个线程来完成,互相不干扰,各玩各的,多个线程分别完成自己的任务

   实现 Runnable 接口:一个任务由多个线程来共同完成

具体实现如下:

 两种方式线程输出https://blog.csdn.net/kanglix1an/article/details/46006093

启动线程:

thread.start();

启动线程使用start方法,而启动了以后执行的是run方法。

怎么区分线程:

thread.setName("设置一个线程名称");这是一种规范,在创建线程完成后,都需要设置名称。

 

线程并发库和线程池的作用

dk1.5后,java.util.current包提供了很多关于线程并发的类

java通过Executor提供的四个静态方法进行创建4种线程池

使用线程池的作用:

1.限制线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃

2.节约了资源,免去了不停的去创建线程销毁线程的过程

 

线程池的好处?

java通过Executors提供了四个静态方法创建线程池,分别是:

       newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

      newFixedThreadPool :创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

      newScheduledThreadPool: 创建一个定长线程池,支持定时及周期性任务执行。

      newSingleThreadExecutor: 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

1、线程池的重用

        线程的创建和销毁的开销是巨大的,而通过线程池的重用大大减少了这些不必要的开销,当然既然少了这么多消费内存的开销,其线程执行速度也是突飞猛进的提升。

2、控制线程池的并发数

并发:在某个时间段内,多个程序都处在执行和执行完毕之间;但在一个时间点上只有一个程序在运行。头脑风暴:老鹰妈妈喂小雏鹰食物,小雏鹰很多,而老鹰只有一张嘴,她需要一个个喂过去,到最后每个小雏鹰都可以吃到,但是在一个时间点里只能有一个小雏鹰可以吃到美味的食物。

并行:在某个时间段里,每个程序按照自己独立异步的速度执行,程序之间互不干扰。头脑风暴:这就好似老鹰妈妈决定这样喂食太费劲于是为每个小雏鹰请了个保姆,这样子在一个时间点里,每个小雏鹰都可以同时吃到食物,而且互相不干扰。

        回到线程池,控制线程池的并发数可以有效的避免大量的线程池争夺CPU资源而造成堵塞。头脑风暴:还是拿老鹰的例子来讲,妈妈只有一个,要这么一个个喂下去,一些饿坏的小雏鹰等不下去了就要破坏规则,抢在靠前喂食的雏鹰面前,而前面的雏鹰也不是吃软饭的,于是打起来了,场面混乱。老鹰生气了,这么不懂事,谁也别吃了,于是造成了最后谁也没食吃的局面。

3、线程池可以对线程进行管理

        线程池可以提供定时、定期、单线程、并发数控制等功能。比如通过ScheduledThreadPool线程池来执行S秒后,每隔N秒执行一次的任务。

 

分库与分表带来的分布式困境与应对之策

连续分表有可能存在数据热点的问题,有些表可能会被频繁地查询从而造成较大压力,热数据的表就成为了整个库的瓶颈,而有些表可能存的是历史数据,很少需要被查询到。连续分表的另外一个好处在于比较容易,不需要考虑迁移旧的数据,只需要添加分表就可以自动扩容。随机分表的数据相对比较均匀,不容易出现热点和并发访问的瓶颈。但是,分表扩展需要迁移旧的数据。

针对于水平分表的设计至关重要,需要评估中短期内业务的增长速度,对当前的数据量进行容量规划,综合成本因素,推算出大概需要多少分片。对于数据迁移的问题,一般做法是通过程序先读出数据,然后按照指定的分表策略再将数据写入到各个分表中。

表关联问题

在单库单表的情况下,联合查询是非常容易的。但是,随着分库与分表的演变,联合查询就遇到跨库关联和跨表关系问题。在设计之初就应该尽量避免联合查询,可以通过程序中进行拼装,或者通过反范式化设计进行规避。

分页与排序问题

一般情况下,列表分页时需要按照指定字段进行排序。在单库单表的情况下,分页和排序也是非常容易的。但是,随着分库与分表的演变,也会遇到跨库排序和跨表排序问题。为了最终结果的准确性,需要在不同的分表中将数据进行排序并返回,并将不同分表返回的结果集进行汇总和再次排序,最后再返回给用户。

分布式事务问题

随着分库与分表的演变,一定会遇到分布式事务问题,那么如何保证数据的一致性就成为一个必须面对的问题。目前,分布式事务并没有很好的解决方案,难以满足数据强一致性,一般情况下,使存储数据尽可能达到用户一致,保证系统经过一段较短的时间的自我恢复和修正,数据最终达到一致。

分布式全局唯一 ID

在单库单表的情况下,直接使用数据库自增特性来生成主键ID,这样确实比较简单。在分库分表的环境中,数据分布在不同的分表上,不能再借助数据库自增长特性。需要使用全局唯一 ID,例如 UUID、GUID等。关于如何选择合适的全局唯一 ID,我会在后面的章节中进行介绍。

 

数据库索引的原理?

1.1

B+树索引的构造类似于二叉树,根据键值快速找到数据。但是B+树种的B不是代表二叉,而是代表平衡。注意:B+树索引能找到的只是被查找数据行所在的页。然后数据库通过把页读入内存,再在内存中进行查找,最后查到数据。

1.2

二叉查找树

数字代表每个节点的键值,二叉查找树中,左子树的键值总是小于跟的键值,右子树的键值总是大于跟的键值。通过中序遍历得到键值:2、3、5、6、7、8。

1.3

定义:符合二叉查找树的定义,其次必须满足任何节点的左右两个子树的高度最大差为1。

平衡二叉树虽然查找速度非常快但是维护一颗平衡二叉树的代价是非常大,通常需要1次或多次左旋和右旋来得到插入或更新后树的平衡性。

1.4

B+树的特性:

 

所有记录都在叶节点,并且是顺序存放,各个叶节点(页为单位)都是逻辑的连续存放,是一个双向循环链表。

B+树插入必须保证插入后叶节点中的记录依然排序,所以在插入时必须考虑以下三种情况:

B+树索引在数据库中有一个特点就是其高扇出性,因此在数据库中,B+树高度一般在2-3层,也就是寻找某一键值的行记录,最多2-3次IO,而一般的磁盘每秒至少可以做100次IO,2-3次的意味着查询时间只需0.02-0.03秒。

二、 聚集索引、非聚集索引

聚集索引与非聚集索引的区别是:页节点是否存放一整行记录

2.1 聚集索引

InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放。而聚集索引就是按照每张表的主键构造一颗B+树,并且叶节点中存放着整张表的行记录数据,因此也让聚集索引的叶节点成为数据页。聚集索引的这个特性决定了索引组织表中的数据也是索引一部分。同时B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。

实际数据也只能按照一颗B+树进行排序,因此每张表只能拥有一个聚集索引。在许多情况下,查询优化器非常倾向于采用聚集索引,因为聚集索引能够让我们在索引的叶节点直接找到数据。此外,由于定义了数据的逻辑顺序,聚集索引能够快速地访问针对范围值得到查询。查询优化器能够快速发现某一段范围的数据需要扫描。注意每一个页中的记录也是双向链表维护的。

2.2 非聚集索引

也称辅助索引,页级别不包含行的全部数据。页节点除了包含键值以外,每个页级别中的索引中还包含了一个书签,该书签用来告诉InnoDB存储引擎,哪里可以找到与索引相对应的行数据。因为InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引书签就是相应行数据的聚集索引键。下图是聚集索引和辅助索引的关系:

当通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键,然后再通过主键索引来找到了一个完整的行记录。

举例来说:一颗高度为3的辅助索引树中查找数据,那么需要对这颗辅助索引遍历3次找到指定主键;如果聚集索引树的高度同样为3,那么还需要对聚集索引进行三次查找,才能查找一个完整的行数据所在的页,因此需要6次的逻辑Io来访问最终的一个数据页。

https://cloud.tencent.com/developer/article/1338726

 

一个线程运行时发生异常会怎样?

Java中Throwable分为Exception和Error:

出现Error的情况下,程序会停止运行。

Exception分为RuntimeException和非运行时异常。

非运行时异常必须处理,比如thread中sleep()时,必须处理InterruptedException异常,才能通过编译。

而RuntimeException可以处理也可以不处理,因为编译并不能检测该类异常,比如NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException等。

简单说:

① 如果该异常被捕获或抛出,则程序继续运行。

② 如果异常没有被捕获该线程将会停止执行。

 

如何在两个线程间共享数据?

将数据抽象成一个类,并将对这个数据的操作作为这个类的方法,这么设计可以和容易做到同步,只要在方法上加”synchronized“

将Runnable对象作为一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个 Runnable 对象调用外部类的这些方法。

 

Java中什么是竞态条件? 举个例子说明。

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。

导致竞态条件发生的代码区称作临界区。

在临界区中使用适当的同步就可以避免竞态条件。

临界区实现方法有两种,一种是用synchronized,一种是用Lock显式锁实现。

class Counter {

protected long count = 0;

public void add(long value) {

this.count = this.count + value;

}

}

观察线程A和B交错执行会发生什么,两个线程分别加了2和3到count变量上,两个线程执行结束后count变量的值应该等于5。

然而由于两个线程是交叉执行的,两个线程从内存中读出的初始值都是0。然后各自加了2和3,并分别写回内存。

最终的值并不是期望的5,而是最后写回内存的那个线程的值,上面例子中最后写回内存的是线程A,但实际中也可能是线程B。

如果没有采用合适的同步机制,线程间的交叉执行情况就无法预料。

add()方法就是一个临界区,它会产生竞态条件。

 

Java内存模型是什么?

自动集成了以及多处理器技术,这种集成程度比以前诞生的计算机语言要厉害很多,该语言针对多种异构平台的平台独立性而使用的技术支持也是具有开拓性的一面,有时候在开发Java同步和要求很严格的程序时,往往容易混淆的一个概念就是内存模型。究竟什么是内存模型?内存模型描述了程中各个变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,这点没有错,但是编译器、运行库、处理器或者可以有特权在变量指定内存位置存储或者取出变量的值。【JMM】(Java Memory Model的缩写)允许编译器和缓存以数据在处理器特定的缓存(或寄存器)和主存之间移动的次序拥有重要的特权,除非使用了volatile或明确请求了某些可见性的保证

 

ribbon和feign的区别?

pring cloud的Netflix中提供了两个组件实现软负载均衡调用:ribbon和feign。

Ribbon 

是一个基于 HTTP 和 TCP 客户端的负载均衡器 

它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载。

Feign 

Spring Cloud Netflix 的微服务都是以 HTTP 接口的形式暴露的,所以可以用 Apache 的 HttpClient 或 Spring 的 RestTemplate 去调用,而 Feign 是一个使用起来更加方便的 HTTP 客戶端,使用起来就像是调用自身工程的方法,而感觉不到是调用远程方法。

 

Spring Cloud的断路器的作用?

当一个服务调用另一个服务由于网络原因或者自身原因出现问题时 调用者就会等待被调用者的响应 当更多的服务请求到这些资源时

 导致更多的请求等待 这样就会发生连锁效应(雪崩效应) 断路器就是解决这一问题

断路器有完全打开状态

 一定时间内 达到一定的次数无法调用 并且多次检测没有恢复的迹象 断路器完全打开,那么下次请求就不会请求到该服务

 半开

        短时间内 有恢复迹象 断路器会将部分请求发给该服务 当能正常调用时 断路器关闭

关闭

         当服务一直处于正常状态 能正常调用 断路器关闭

 

Eureka和zookeeper区别?

eureka基于AP zookeeper基于CP 由于作为注册中心可用性的需求要高于一致性,所以eureka貌似要比zookeeper更合理一些

https://www.cnblogs.com/a164266729/p/5278509.html

jQuery是什么有什么用?

jQuery本身是一个基于插件的JavaScript库,它的各种功能可以通过新的插件进行增强。

jQueryWeb编程提供了一个抽象的层,使得它可以兼容于任何浏览器,并且大大简化了原先用JavaScript做的工作,总而言之, jQuery可以完成如下所示的工作。

·快速获取文档元素jQuery的选择机制构建于Css的选择器,它提供了快速查询DOM文档中元素的能力,而且大大强化了JavaScript中获取页面元素的方式。

·提供漂亮的页面动态效果: JQuery中内置了一系列的动画效果,可以开发出非常漂亮的网页,目前许多知名的网站都使用了jQuery的内置的效果,比如淡入淡出,元素移除等动态特效。

·创建Ajax无刷新网页: Ajax是异步的JavaScriptXML的简称,可以开发出非常灵敏无刷新的网页,特别是开发服务器端网页时,比如PHP网站,需要往返地与服务器沟通,如果不使用Ajax,每次数据更新不得不重新刷新网页,而使用了Ajax特效后,可以对页面进行局部刷新,提供非常动态的效果。

·提供对JavaScript语言的增强: JQuery提供了对基本JavaScript结构的增强,比如元素选代和数组处理等操作。

·增强的事件处理: jQuery提供了各种页面事件,它可以避免程序员在HTML中添加太多事件处理代码,最重要的是,它的事件处理器消除了各种浏览器兼容性问题。

·更改网页内容JQuery可以修改网页中的内容,比如更改网页的文本、插入或转网页图像, jQuery简化了原本使用JavaScript代码需要处理的方式。如果想系统学习jQuery,请关注黑马程序员web前端课程

 

dubbo服务开发流程,运行流程?zookeeper注册中心的作用?

1、要在系统中使用dubbo,要先搭建一个注册中心,推荐使用Zookeeper.

2、有了注册中心然后是发布服务,发布服务需要使用spring容器和dubbo标签来发布服务,并且发布服务时需要指定注册中心的位置。

3、服务发布之后就是调用服务。一般调用服务也是使用spring容器和dubbo标签来引用服务,这就可以在客户端的容器中生成一个服务的代理对象,在action或者controller中直接调用service的方法即可。

 

可以集群

什么是MyBatis的接口绑定?有哪些实现方式?

接口绑定:就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。

 student user = (student) session.selectOne("test.studentMapper.selectUserByID", 1);

接口绑定有两种实现方式:

注解绑定:就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;

//这种方式不用写mapper.xml
@Select("select * from `tb_Teacher` where id = #{id}")
    public teacher  selectTeacherByID(int id);

Sql绑定:在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。

<select id="selectUserByID" parameterType="int" resultType="test.student">
        select id,name,age,stuCountry stu_country from `tb_Student` where id = #{id}
    select>

当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。

使用MyBatis的mapper接口调用时有哪些要求?

1) Mapper接口方法名和Mapper.xml中定义的每个SQL的id相同;

2)  2) Mapper接口方法的输入参数类型和mapper.xml中定义的每个sqlparameterType类型相同

3) Mapper接口方法的输入输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

4) Mapper.xml文件中的namespace,就是接口的类路径。

简述Mybatis的插件运行原理,以及如何编写一个插件

Mybatis仅可以编写针对ParameterHandlerResultSetHandlerStatementHandlerExecutor4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandlerinvoke()方法,当然,只会拦截那些你指定需要拦截的方法。

实现MybatisInterceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

mybatis面试题:https://www.cnblogs.com/huajiezh/p/6415388.html

spring在项目中如何充当粘合剂

1、在项目中利用spring的IOC(控制反转或依赖注入),明确地定义组件接口(比如UserDAO),开发者可以独立开发各个组件, 然后根据组件间的依赖关系组装(UserAction依赖于UserBiz:业务逻辑层,UserBiz依赖于UserDAO)运行,很好的把Struts(Action)和hibernate(DAO的实现)结合起来了。


2、spring的事务管理把hibernate对数据库的操作进行了事务配置。

Jquery异步获取数据的方式有几种?有何区别?

个是$.getJSON方法,一个是$.ajax方法。

使用$.getJSON方法和$.ajax方法都能达到相同的效果,但是,如果想对异步获取的过程有更细节的控制,推荐使用$.ajax方法。

set怎么保证不重复(HashMap怎么保证key值不重复)

 首先set实现元素唯一有两种方法
equals()和hascode()
当set添加一个新数据时我们先调用一个hashcode方法去比对hashcode值,如果不一制就调用equals()方法进行第二次判断,如果一致就不用进行第二次判断。

谢谢观看!博主会不定时的更新题目