参考答案:
首先,Java与C/C++相比。Java语言是一种完全的面向对象语言,虽然它的底层(运行时库)是用C语言开发的,可是并不依赖于C。因为Java的运行是在运行时库的支持下 进行的,所以运行效率比起可以更接近底层的C/C+ +来说效率会有所影响,,不过Java的类库采用很好的设计理念,非常好用,也非常实用,已经成为业界的一种标准开发语言。它的跨平台的特性受到开发者的青睐,只需要开发一次就能在所有安装了Java运行时库的环境 上运行。
其次,Java与C#相比。C#是微软开发的一种编程语言,语法类似Java,几乎就是Java 的翻版。运行原理和Java也类似,也是通过运行时库的支持运行。不过支持的平台还很有限。Java几乎被所有平台支持,而C #目前只被Windows和linux支持,Windows下的支持当然是由微软自己开发的,而Linux下的支持则有mono支持。实际上,mono也是把C #应用转化为Java应用而已,所以本质上,C #仍然只是被微软自己的操作系统支持。 应用平台受到限制,是它最大的缺占
参考答案:
JVM:Java虚拟机,Java Virtual Machine的缩写。是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构, 如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码) ,就可以在多种平台上不加修改地运行。
JDK:Java开发工具包,Java Development Kit的缩写。JDK是整个Java的核心, 包括了Java运行环境、Java工具和Java基础类库。
JRE:Java运行环境,Java Runtime Environment的缩写。运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。
JavaSE : Java Standard Edition,标准版,是我们常用的一个版本,从JDK5.0开始, 改名为Java SE,主要用于桌面应用软件的编程。
JavaEE:Java Enterprise Edition,企业版。JavaEE是J2EE的一个新的名称,主要
用于分布式的网络程序的开发。
JavaME :Java Micro Edition 为机顶盒、 移动电话和PDA之类嵌入式消费电子设备提供Java语言平台,包括虚拟机和一系列标准化的Java API
GC:垃圾回收,Garbage Collection的缩写。当Java虚拟机发觉内存资源紧张时,则会自动地去清理无用对象(没有被引用到的对象)所占用的内存空间。
参考答案:
每个Java程序对应于一个JVM实例,当一个Java程序运行时就创建一个JVM实例, 因此JVM实例的个数取决于同时执行的程序个数。
参考答案:
Java是利用JVM ( Java虚拟机)实现跨平台的。
Java源代码(java)经过Java编译器编译成Java字节码(.class),执行Java字节码,Java字节码经过JVM解释为具体平台的具体指令,并执行。不同平台有不同的JVM, 主流平台都提供了JVM,所以Java字节码可以在主流平台上能够解释执行。在这个意义上 Java是跨平台的,也就是说:Java的字节码是跨平台的。
参考答案:
TCP/UDP协议的区别如下表所示。
TCP/UDP协议比较
比较项 | TCP | UDP |
---|---|---|
是否可连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠的 | 不可靠的 |
应用场合 | 传输大量的数据 | 少量数据 |
速度 | 慢 | 快 |
参考答案:
在Java中,类的命名、方法的命名、变量的命名、包名的命名以及常量的命名首先必须符合Java标识符的命名规则,规则如下:
可以以字母、数字、"_“和” $ "符组成,
首字符不能以数字开头;
中文可以作为变量名,但不提倡使用;
Java大小写敏感,命名变量时需要注意;
不能使用Java保留字(一些Java语言规定好的,有特殊含义的字符) ,如:int、 if、for、 break等。
其次,类的命名、方法的命名、变量的命名、包名的命名以及常量的命名,建议符合如下规范:
类命名规范:首字母大写,如果由多个单词合成一个类名,要求每个单词的首字母也要大写,如:HelloWorld
方法命名规范:首字母小写,中间的每个单词的首字母都要大写,如getName
变量的命名规范:变量的命名规范和方法一样,首字母小写,中间的每个单词的首字母都要大写,如:studentName
包的命名规范:Java包的名字都是由小写单词组成。但是由于Java面向对象编程的特性,每一名Java程序员都可以编写属于自己的Java包,为了保障每个Java包命名的唯一性,在最新的Java编程规范中,要求程序员在自己定义的包的名称之前加上唯一的前缀。由于互联网上的域名是不会重复的,所以程序员一般采用自己在互联网上的域名称作为自己程序包的唯一前缀。例如." com.sun.swt"一般公司命名会以" com.公司名.项目名.模块名"开头,所以会长一点,如com.land.oa.emp.struts.actiono
常量的命名规范:基本数据类型的常量名为全大写,如果是由多个单词构成,可以用下划线隔开,如:WEEK_OF_MONTH
参考答案:
在Java中有三种注释类型:
单行注释符号是"// ",只能注释一行
块注释符号是" /* */ ",可以跨多行。
Javadoc注释符号是/** */,可以跨多行,而且生成javadoc时,这样的注释会被生成标准的Java API注释。
参考答案:
为了增加代码的清晰度和可观性,常用的方式如下:
1)给代码添加注释。
2)类名包名等命名规范化。
3)缩进排版规范。
添加异常的处理。
使用测试类和测试方法。
参考答案:
&和&&都可以执行关系判断。二者的区别是:&运算是把逻辑表达式全部计算完,而&&运算具有短路计算功能。所谓短路计算,是指系统从左至右进行逻辑表达式的计算, 一旦出现计算结果已经确定的情况,则计算过程立即被终止。
参考答案:
Java中8种基本类型及其字节长度如下表所示:
Java中的8种原始类型介绍
类型名称 | 字节长度 | 说明 |
---|---|---|
byte | 1字节(8位) | 存储1个字节数据 |
short | 2字节(16位) | 兼容性考虑,一般不用 |
Int | 4字节(32位) | 存储整数(常用) |
long | 8字节(64位) | 存储长整数(常用) |
float | 4字节(32位) | 存储浮点数 |
double | 8字节(64位) | 存储双精度浮点数(常用) |
char | 2字节(16位) | 存储一个字符 |
boolean | 1字节(8位) | 存储逻辑变量(true、false) |
参考答案:
JVM中类的装载是由ClassLoader和它的子类来实现的Java ClassLoader是—个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
参考答案:
进程是操作系统结构的基础,是一个计算机中正在运行的程序实例。可以分配给处理器并由处理器执行的一个实体,由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
参考答案:
各问题的参考答案如下:
第一问:垃圾回收(GC)是Java语言的一个重要特性,作用是释放不再被使用的内存。
第二问:垃圾回收由系统进行管理。在系统认为需要的时候自动启动一个线程进行处理。
第三问:尽量减少垃圾内存,也就是新建对象的数量,可以降低垃圾回收的频率。
第四问:垃圾回收机制无法保证有足够的内存。
参考答案:
会出现内存泄漏。
一般来说内存泄漏有两种情况。一是在堆中分配的内存,在没有将其释放掉的时候,就 将所有能访问这块内存的方式都删掉;另一种情况则是在内存对象已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用了第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。
下面给出了一个简单的内存泄漏的例子。在这个例子中,我们循环申请Object对象,并将申请的对象放入一个List中,如果我们仅仅释放引用本身,那么List仍然引用该对象,所以这个对象对GC来说是不可回收的。代码如下:
List list = new ArrayList(10);
for (int i = 1;i<100;i++)
{
Object o = new Object();
list.add(o);
o=null;
}
此时,所有的Object对象都没有被释放,因为变量list引用这些对象。
参考答案:
一个Java源文件中可以包含多个类每个源文件中至多有一个public类如果有的话, 那么源文件的名字必须与之相同。如果源文件中没有public类,则源文件用什么名字都可以,但最好还是具有特定的意义,免得自己都不记得里面写的是什么了。一般建议一个源文件中只写一个Java类。
参考答案:
常用的JDK包如下:
1 · java.lang包:这个包中包含了JDK提供的基础类,比如String等都是这里面的, 这个包是唯一 一个可以不用导入就可以使用的包,
2 · java.io包:这个包中包含了与输入输出相关的类,比如文件操作等;
3.java.net包:这个包中包含了与网络有关的类,比如URL,URLConnection等,
4 · java.util包:这个是系统辅助类,特别是集合类Collection,List,Map等
5 · java.sql包:这个是数据库操作的类,Connection, Statememt,ResultSet等。
参考答案:
1. 递归做为一种算法在程序 设计语言中广泛应用,是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象
2. 递归算法一般用于解决三类问题:
a) 数据的定义是按递归定义的(斐波那契函数)
b) 问题解决按递归算法实现(回溯)
c) 数据的结构形式是按递归定义(树的遍历,图的搜索)
3. 下面是使用递归算法实现计算某个整数 在二进制中的个数,代码如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIGMaKQt-1615101859298)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps2.jpg)]
参考答案:
参考答案的代码如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNv1dFoE-1615101859300)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps3.jpg)]
参考答案:
参考答案的代码如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4g5Czg4r-1615101859301)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps4.jpg)]
参考答案:
下列代码中使用二分搜索算法实现了从数组a[1000]中,查找两个相同的数,代码如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-umgiA7Gi-1615101859303)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps5.jpg)]
参考答案:
OOAD(Object Orient Analysis Design,面向对象的分析与设计)是现代软件企业广为采用的一项有效技术。OOAD方法要求在设计中要映射现实世界中指定问题域中的对象和实体,例如:顾客、汽车和销售人员等。这就需要设计要尽可能地接近现实世界,即以最自然的方式表述实体。
使用UML建模语言创建系统的分析模型与设计模型是OOAD实现的主要手段。
参考答案:
总共有五种创建模式,分别是单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,其中工厂方法模式是类创建模式,其余四种是对象创建模式。下面是对各个模式 的介绍。
单例模式(Singleton,对象创建模式):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
工厂方法模式(Factory Method,类创建模式):核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类 必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
抽象工厂模式(Abstract Factory,对象创建模式):抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。简单来说是创建一组相关或相互依赖的复杂对象。
建造模式(Builder,对象创建模式):将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
原型模式(Prototype,对象创建模式):通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等吉构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
参考答案:
在改写equals方法的时候总是要改写hashCode方法。如果不这样的话,就会违反 Object类的hashCode方法的通用约定,导致这个类无法与所有基于散列值的集合类结合在一起正常工作,包括HashMap,HashSet和Hashtable。
参考答案:
Java的继承是子类对象继承父类对象的成员属性和成员方法,只允许单继承。
在继承的过程中可以实现方法的重写(也称为覆盖) ,即子类定义一个方法覆盖从父类那里继承来的同名的方法。每当子类对象调用该方法时都是子类自己定义的方法,只有使用super关键字或父类名为前缀时,才会调用父类原来的方法。方法覆盖时,子类应与父类有完全相同的方法名,返回值类型和参数列表,子类中的覆盖方法不能使用比父类中被覆盖的方法更严格的访问权限。
方法重载要求是有两个或多个方法名相同,只是方法参数列表不同的方法,它对返回值大型没有限定。
参考答案:
修饰符的控制范围:
本类中 | 同包类中 | 子类中 | 其他类中 | |
---|---|---|---|---|
Public(公共的) | 可以 | 可以 | 可以 | 可以 |
Protected(受保护的) | 可以 | 可以 | 可以 | 不可以 |
默认 | 可以 | 可以 | 同包子类可以 | 不可以 |
Private(私有) | 可以 | 不可以 | 不可以 | 不可以 |
参考答案:
abstract class 和interface的区别如下:
首先,从语法角度来说。abstract class方法中可以有自己的数据成员,也可以有非 a bstract的成员方法,并赋予方法的默认行为,而在interface方式中一般不定义成员数据变量,所有的方法都是abstract,方法不能拥有默认的行为。
然后,从编程的角度来说。abstract class在Java语言中表示的是一种继承关系, 一个类只能使用一次继承关系,而一个类可以实现多个interface。
最后,从问题域角度来说。abstract class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在" is a "关系,即父类和派生类在概念本质上应该是相同的。对于interface来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。
参考答案:
\1. 所谓封装,也就是把客观事物抽象封装成类。封装是面向对象的特征之一。
\1. 简单的说,一个类就是一个封装了数据以及操作这些数据的算法。
\2. 对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
\2. 所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。
\1. 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
\2. 子类是对父类功能的扩展
\3. 实际开发中父类往往是从子类泛化而来,父类中的属性和方法是从子类中抽象来的。
\3. 所谓多态就是指一个父类具体子类实例的相同方法执行出不同表现。
\1. 多态机制使具有不同对象可以共享相同的外部接口方法。
\2. 这意味着,可以通过相同的方式调用具体对象功能不同方法。
参考答案:
子类subclass实例可以直接调用父类superclass未被重写的方法;若子类重写父类方法,可以在子类内通过"super.方法名()"的形式调用父类方法,例如:super.myMethod();
创建子类实例时默认调用父类无参的构造方法,若调用父类有参的构造方法可以在子类构造方法第一行通过"super(函数)"形式调用。
参考答案:
String类是final类,故不可以继承。
参考答案:
1)修饰成员变量。用static修饰的成员变量不属于对象的数据结构;static变量是属于类的变量,通常可以通过类名来引用static成员,static成员变量和类的信息一起存储在方法区,而不是在堆中,一个类的static成员变量只有"一份",无论该类创建了多少对象。
2)修饰成员方法。static修饰的方法则不需要针对某些对象进行操作,其运行结果仅仅与输入的参数有关,调用时直接用类名引用。由于static在调用时没有具体的对象,因此在static方法中不能对非static成员(对象成员)进行访问。static方法的作用在于提供一些"工具方法"和"工厂方法"等。
3)static块:属于类的代码块,在类加载期间执行的代码块,只执行一次,可以用来在软件中加载静态资源。
1) abstract
2) extends
3) final / finally
4) implements
5) import
6) instanceof
7) synchronized
8) throw/throws
参考答案:
1)abstract:抽象,修饰类和方法。含有abstract方法的类是abstract类,abstract 方法主要是为了让子类继承实现。
2)extends:继承,子类通过继承父类来添加变量或方法,或者覆盖父类的方法;子接口继承父接口来添加方法。
3)final / finally:final用于定义常量。finally是java异常处理机制的一个字句,用来执行一段代码,不管在前面定义的try语句中是否有异常或运行时错误发生都会执行该段代码。
4)implements:在类的声明中是可选的,用来指明当前类实现的接口。
5)import:在源文件的开始部分指明后面将要引用的一个类或整个包。
instanceof:判断其指向对象的实际类型。
synchronized:修饰方法或方法块。防止多个线程同时访问这个类中的 synchronized块。
throw/throws:throw允许用户抛出一个exception对象或者任何实现 throwable的对象。throws用在方法的声明中来说明哪些异常这个方法是不处理的,而是提交到程序的更高一层。
参考答案:
静态变量也称为类变量,归全类共有,它不依赖于某个对象,可通过类名直接访问,而 实例变量必须依存于某一实例,只能通过对象才能访问到它。
参考答案:
GC是垃圾收集的意思(Gabage Collection ) ,内存处理是编程人员容出现问题的地 方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的。Java程序员编程的时候不用考虑变量不用时释放内存,Java虚拟机可以自动判断出并收集到垃圾。
参考答案:
Java语言中一个显著的特点就是引入了垃圾回收机制,使c ++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
列举两种垃圾回收机制如下:
1)增量收集器
增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。
2)分代收集器
这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。JVM生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。
参考答案:
栈(stack)与堆(heap)都是Java用来在内存中存放数据的地方,二者区别在于:
\1. 栈存放基本类型变量和对象引用,当超过作用域后释放;堆存放new出来的对象和数组。
2.堆可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。 栈的存取速度比堆要快,仅次于直接位于CPU中的寄存器。堆由于要在运行时动态分配内存,存取速度较慢。
\3. 栈数据可以共享,如字面量3等;堆不可以。
\4. 栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进先出的方式进行处理;堆地址是不连续的,可随机访问。
参考答案:
Java语言是一个面向对象的语言,但是Java中的基本数据类型却不是面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(wrapper Class) Java语言提供两种不同的类型:引用类型和基本数据类型;int是Java语言中的原始数据类型,Integer是Java为int提供的包装类。Java为每一个基本数据类型提供了封装类,其中,基本数据类型包括byte、short、int、long、float、double, char、boolean这八个基本数据类型,这八个基本数据类型对应的封装类为Byte、Short、Integer、Long、 Float、Double、Character、Booleano
在这八个类名中,除了Integer和Character类以外,其它六个类的类名和基本数据类 型一致,只是类名的第一个字母大写即可。对于包装类说,这些类的用途主要包含两种:
1)作为和基本数据类型对应的类类型存在,方便涉及到对象的操作;
2)包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
参考答案:
在Java语言中,可以使用throw关键字来引发异常。
对异常处理的两条途径为:
1)使用throws抛出异常。
2)使用try-catch语句捕获异常。
参考答案:
异常"(Exception)分为两类:运行时异常和非运行时异常。
运行时异常和非运行时异常的区别是运行时异常(RuntimeException)又被称为非检查异常,非运行时异常指的是检查异常。运行时异常是指直接或间接继承 RuntimeException的异常。非运行时异常是指除了RuntimeException以外的其它异常,
是你的程序有逻辑错误,程序员应该积极避免其出现的异常。Java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
常见的运行时异常:
1.NullPointerException(空指针异常):当操作一个空引用时会出现此异常。
2.NumberFormatException(数字格式化异常):试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
3.ClassCastException(类型转换异常):强制类型转换类型不匹配时出现此异常。
4.ArrayIndexOutOfBoundsException(数组下标越界异常):当使用一个不存在的数组下标时出现此异常。
5.ArithmeticException(数学异常):当出现异常的运算条件时出现此异常常见的非运行时异常:
1)SQLException.提供关于数据库访问错的异常。
一IOException:当发生某种I/O异常时,抛出此异常。
3)ClassNotFoundException 当应用程序试图使用Class类中的forName方法、 loadClass方法时,抛出该异常。
参考答案:
当Java程序违反了Java的语义规则时,Java虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况,一种是Java类库内置的语义检查,例如:数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerExceptiono 另一种情况是Java允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。
参考答案:
Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含了异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、 throw、throws和finally
try用来指定一块预防所有"异常"的程序;catch子句紧跟在try块后面,用来指定你想要捕捉的"异常"的类型;
throw语句用来明确地抛出一个"异常"
throws用来标明一个成员方法可能抛出的各种“异常”
finally为确保一段代码不管发生什么"异常"都被执行一段代码;
可以在一个成员方法调用的外面写一个try语句,在这个成员方法内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常"的框架就放到堆栈上面,直到所有的try 语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到有处理这种"异常"的try语句。
参考答案:
Collection是 java.util下的接口,它是各种集合的父接口,继承于它的接口主要有Set 和List;Collections是个java.util下的类,是针对集合的帮助类,提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
参考答案:
1)HashMap是基于哈希表的Map接口的非同步实现。在 Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用) ,所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个"链表的数组"的数据结构,每个元素存放链表头结点的数组,即数组和链表的结合体。Hash Map底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。Entry就是数组中的元素,每个Map.Entry其实就是一个key-value对,它持有一个指向下一个元素的引用,这就构成了链表。
2)HashMap的存储。当我们往HashMap中put元素的时候,先根据key的 hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
3)HashMap的读取。从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。
4)HashMap的resize(rehash)当HashMap中的元素越来越多的时候,hash 冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对 Hash Ma p的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去这就是resize。那么HashMap什么时候进行扩容呢?当HashMap中的元素个数超过数组大小* loadFactor时,就会进行数组扩容,loadFactor 的默认值为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小为16,那么当 HashMap中元素个数超过16 * 0 .75=12(这个值就是代码中的threshold值,也叫做临界值)的时候,就把数组的大小扩展为2 * 16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知Hash Map中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。
参考答案:
Hashtable原理:Hashtable是基于哈希表的实现。通过使用put(Object key,Object value方法把两个对象进行关联,需要时用get(Object key)取得与key关联的值对象。还可以查询某个对象的索引值等等。这里的get方法查找一个对象时与vector中的get方法在内部实现时有很大不同,在一个Hashtable中查找一个键对象要比在一个Vector中快的多。这是因为Hashtable使用了一种哈希表的技术,在Java中每个对象缺省都有一个通过 Object的hashCode()方法获得的哈希码,Hashtable就是利用这个哈希实现快速查找键对象的。
二者都实现了Map接口,是将唯一键映射到特定的值上;主要区别在于:
1.HashMap没有排序,允许一个null键和多个null值,而Hashtable不允许;
2.HashMap把Hashtable的contains方法去掉了,改成containsvalue和 containskey,因为contains方法容易让人引起误解;
3.Hashtable继承自Dictionary类,HashMap E JavaI.2引进的Map接口的实
\4. Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问 Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法大致一样,所以性能不会有很大的差
参考答案:
List,Set继承自Collection接口,而Map没有继承自Collection接口。
参考答案
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全) ,通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
参考答案:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码;如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
参考答案:
多线程就象是人体一样,一直在并行的做许多工作,例如,人可以同时呼吸,血液循环, 消化食物的。多线程可以将一个程序划分成多个任务,他们彼此独立的工作,以方便有效的使用处理器和用户的时间。
参考答案:
启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
参考答案:
实现同步的方法为使用synchronized关键字,实现方式:
1)同步方法。可以是静态和非静态方法,不可以是抽象和接口方法。当一个线程调用这个对象的同步方法,则这个对象的其他所有同步方法将被锁定,不能调用,但可以调用非同步方法。非静态同步方法锁定的是方法所属的主体对象自身。静态同步方法锁定的是主体类对应的Class类型的对象,所以静态同步方法只跟所属类的其他静态同步方法相互制约。
2)同步块。锁定一个指定的对象,来对同步块中的代码进行同步。
参考答案:
如果数据将在线程间共享,使用同步编程。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,则使用异步编程,在很多情况下采用异步途径往往更有效率,比如发送短信。
参考答案:
一个程序中若创建大量线程,并在任务结束后销毁,会给系统带来过度消耗资源,以及过度切换线程的危险,从而可能导致系统崩溃。为此我们应使用线程池来解决这个问题。
首先创建一些线程,它们的集合称为线程池,当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务结束后不关闭该线程,而是将该线程还回到线程池中。在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程 池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
参考答案:
序列化就是一种用来处理对象流的机制,而胃对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题;序列化的实现:将需要被序列化的类实现 Serializable接口,该接口没有需实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的 writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
参考答案:
Java中有字节流、字符流。
字节输入流的父类为InputStream、字节输出流的父类为OutputStream;字符输入 流的父类为Reader、字符输出流的父类为Writer。
参考答案:
字节流与字符流主要的区别是他们的处理方式。字节流是最基本的,所有的 In putStream和OutputStream的子类用于处理二进制数据,它是按字节来处理的。而字符流是以字符为单位读写数据的。
参考答案:
String的长度是不可变的;StringBuffer的长度是可变的,如果对字符串中的内容经常进行操作,特别是内容要修改时,则使用StringBuffer ,如果最后需要String,那么使用 StringBuffer的toString()方法转换成String类型的数据;
StringBuffer 是线程安全的;StringBuilder是从JDK 5开始,为StringBuffer该类补充了一个单个线程使用的等价类;通常应该优先使用StringBuiIder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
java的原始数据类型,也可以叫java的基本数据类型,一共就8个,分别是:byte、short、int、long、boolean、char、float、double
byte 1个字节
boolean 1个字节
char 2个字节
short 2个字节
int 4个字节
long 8个字节
float 4个字节
double 8个字节
break和continue都是用来控制循环结构的。
\1. break:提前终止循环可以使用break来完成。break完全结束一个循环,跳出循环体执行循环后面的语句。
\2. continue:理解为continue是跳过当次循环中剩下的语句,执行下一次循环。
\3. 区别:continue只终止本次循环,break则完全终止循环
\1. i++ 理解为:先用i值后加1, 比如int j=i++; 如果i的初值是1,那么表达式i++的整体值就是1,然后,i的值就变成了2,最后执行赋值运算,将i++整体的值1,赋值给j,j为1。
\2. ++i 理解为:先加1后用i值,比如int j=++i;如果i的初值是1,首先i增加1为2,然后用i的值2最为++i整体表达式的值,最后进行赋值运算,将++i表达式的值2赋值给j,j为2。
注意:这两个表达式在计算时,=号赋值计算,都是最后发生的,是非常常见的考点。
\1. 在语法定义上的区别:
o静态变量前要加static 关键字,而实例变量前则不加。
\2. 在程序运行时的区别:
\1. 实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。
\2. 静态变量不属于某个实例对象,而是属于类,所以也称为类变量。
\3. 实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
\1. 重写必须继承,重载不用。
\2. 重写的方法名,参数数目相同,参数类型兼容,重载的方法名相同,参数列表不同。
\3. 重写的方法修饰符大于等于父类的方法,重载和修饰符无关。
\4. 重写不可以抛出父类没有抛出的一般异常,可以抛出运行时异常
重写和重载。向上造型
\1. 含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。
\2. abstract class类中定义抽象方法必须在具体子类中实现。
\3. 如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
\4. 接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
\1. 接口可以继承接口,可以继承多个接口
\2. 抽象类可以实现接口,可以实现多个接口
\3. 抽象类可以继承具体类,但只能继承一个类
\1. GC是垃圾收集的意思
\2. Java提供的GC功能可以自动监测回收不被引用的对象,释放其占用的内存,
\3. 垃圾收集器会自动进行管理。
\4. 如果要请求垃圾收集,可以调用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),这些方法会通知GC尽快进行内存垃圾回收。
\5. 在对象使用以后要及时释放其引用,有利于垃圾回收,可以有效的防止内存泄露。
\1. ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,优点是索引读取快,从最后插入和删除元素速度快,但是头部插入和删除慢。
\2. LinkedList使用双向循环链表方式存储数据,所以头尾插入或读取插入的速度快,而中部插入和读取慢.
\1. 历史原因:Hashtable 是陈旧API,HashMap 是Java 1.2 引进的Map 接口的一个实现
\2. 同步性:Hashtable 是线程安全的,也就是说是同步的,而HashMap 是线程序不安全的,不是同步的。由于同步检查所以Hashtable性能稍慢。
\3. 值:HashMap 可以插入一个null的key-value
\1. List特点:元素有顺序,元素可重复
\2. Set特点:元素无顺序,元素不可重复(注意:元素虽然无顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
\3. Map特点:元素按键值对存储,无顺序
\1. 队列(Queue)是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
\2. 栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。
\3. 队列先进先出(FIFO),栈先进后出(FILO)。
\1. String是不可变的,StringBuffer是可变的;StringBuffer是线程安全的,StringBuilder是非线程安全的。
\2. 由于字符串链接会自动创建StringBuilder对象,为了避免复杂字符串拼接时候大量创建StringBuilder对象,可以利用StringBuilder优化字符串链接操作。
\3. StringBuilder是jdk5之后新增的,其用法与StringBuffer完全一致,但它是线程不安全的,在单线程中最佳,因为其不需要维护线程的安全,因此是最快的。
不能被继承,因为String类是final类,final修饰的类是不能被继承
\1. 是值比较,对于引用类型变量是判断引用的值是否是同一个对象地址值,如果是相同对象其内容也一定是相同的
\2. equals方法判断的是对象的内容是否相同,由于其默认方法采用的==进行引用比较,所以需要重写为按照对象内容比较是否相同。
\1. HashMap :实现Map接口;使用hash算法,里面的数据是无序的;并且存储的是键值对;
\2. HashSet :实现了Set接口;内部封装了HashMap,故也是无序的;HashSet本质就是HashMap,数据存储到HashSet的Key部分,Value部分被屏蔽不使用了。
\1. 栈的数据结构是,先进后出(FILO),也可以说是后进先出
\2. 队列的数据结构是,先进先出(FIFO)
\1. Comparable接口
\1. 实现Comparable接口类表示这个类型的对象可以进行比较大小的。 这种可以比较大小的对象可以进行自然排序。
\2. Comparator接口
\1. 比较器用于实现对象任意属性进行比较大小。
\2. 在排序时候可以通过指定属性比较器实现任意属性排序。
\3. 在排序时候Comparable接口用于进行自然排序,而Comparator接口进行自定义排序,自定义排序更加灵活方便而常用。
\4. 设计上Comparable不推荐使用,因为对程序本身具有侵入性。
\1. Java异常是一个消息传播机制,如果不被处理将继续传播并且打断当前程序的执行。
\2. Java使用面向对象的方式来传播异常消息,发生的每个异常被封装到一个异常对象,该对象中包含有异常的信息。
\3. Java中使用try catch finally 语法捕获处理异常消息。
在应用开发中有三种方式可以用来创建线程:
\1. 继承Thread类,并且创建对象。
\2. 实现Runnable接口,将Runnable接口的具体对象作为参数创建Thread对象。
\3. 另外也可以使用Executer创建并重用线程
可以进入其他非synchronized的方法,synchronized的方法不可以的!
\1. Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor)
\2. 当一个线程访问对象的synchronized方法时,将在对象上锁,方法不能并发执行。
\3. 此时其他任何线程都得阻塞等待到当前线程方法执行结束后,才能有机会执行方法。
\4. 也就是说线程排到一个接着一个执行 synchronized的方法。
TCP是传送控制协议
\1. 是面向连接的可靠数据传输协议,TCP会确保数据会可靠的传输到对方.
\2. 使用步骤:先建立可靠连接—利用连接中的双向通讯流传输数据-----通讯结束以后,需要关闭连接.
\3. java利用Socket和ServerSocketAPI封装了TCP通讯过程,利用这两个类即可实现TCP通讯。
\4. HTTP通讯的底层是TCP协议。
\1. Java中并发运行多个流程的能力。每一个流程称为一个线程。
\2. Java的Thread API封装了线程控制过程。
\3. 创建线程对象后调用start方法就可以将线程提交到操作系统执行。
\4. 线程最终是由操作系统调度执行的。
\1. 一个线程是进程的一个顺序执行流程。一个进程中的全部线程共享同一个堆空间。线程本身有一个供程序执行时的栈,一个进程中可以包含多个线程。
\2. 新建、就绪、运行状态、阻塞状态、死亡状态
\3. 新建状态:利用NEW运算创建了线程对象,此时线程状态为新建状态,调用了新建状态线程的start()方法,将线程提交给操作系统,准备执行,线程将进入到就绪状态。
\4. 就绪状态:由操作系统调度的一个线程,没有被系统分配到处理器上执行,一旦处理器有空闲,操作系统会将它放入处理器中执行,此时线程从就绪状态切换到运行时状态。
\5. 运行状态:线程正在运行的过程中,碰到调用Sleep()方法,或者等待IO完成,或等待其他同步方法完成时,线程将会从运行状态,进入到阻塞状态。
\6. 死亡状态:线程一旦脱离阻塞状态时,将重新回到就绪状态,重新向下执行,最终进入到死亡状态。一旦线程对象是死亡状态,就只能被GC回收,不能再被调用。
常见的有SAX,DOM,DOM4J
\1. SAX:SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。
\2. DOM:DOM的利用SAX进行读取的,读取以后缓存到内存中成为DOM对象,处理大型文件时内存耗用较高。
\3. DOM4J:由于DOM API使用过于繁琐,JAVA的开源组织开发了DOM4J,底层封装了DOM,提供JAVA Bean风格的API,使用非常简洁。
\1. 节点流:有明确的数据源,从数据源读取基础的字节数据,或向数据源写入字节数据。
\2. 过滤流:依赖于其他流,不能单独使用,并且都提供了高级功能,使用起来更加方便。
\3. FileInputStream FileOutputStram
\4. BufferedInputStream BufferedOutputStream
\5. ObjectInputStream ObjectOutputStream
\1. BufferedReader只能连接在其他字符流上,所以属于字符流,其底层需要依赖于其他的字符流,或者字节流。
\2. BufferedReader提供了字符缓冲功能,能够一定程度上的提升IO性能。
\3. 提供了经典的方法readLine()方法,可以从目标流中,读取一行文本。
\1. JAVA中最基本的流是字节流,任何流的底层都是字节流。
\2. 字符流是以字符为单位进行读写的流,大部分的实现类是高级流,其底层一定基于字节流,字符流在字节流基础之上,扩展了字符编码解码功能。
\3. 字节流的抽象父类:InputStream OutputStream
\4. 字符流的抽象父类:Reader Writer
\1. 对象序列化,将对象中的数据编码为字节序列的过程。
\2. 反序列化;将对象的编码字节重新反向解码为对象的过程。
\3. JAVA提供了API实现了对象的序列化和反序列化的功能,使用这些API时需要遵守如下约定。
\1. 被序列化的对象类型需要实现序列化接口,此接口是标志接口,没有声明任何的抽象方法,JAVA编译器识别这个接口,自动的为这个类添加序列化和反序列化方法。
\2. 为了保持序列化过程的稳定,建议在类中添加序列化版本号。
\3. 不想让字段放在硬盘上就加transient
\1. HashMap是面向查询优化的数据结构,查询性能优异。
\2. 在其内部利用数组存储数据。
\3. 插入数据时,先根据Key的HashCode计算出数组的下标位置,再利用Key的equals()方法检查是否以存在重复的Key,如果不重复直接存储到数组中,如果重复就作为链表存储到散列桶中。
\4. 插入的数据和数组容量的比值大于加载因子则进行数组扩容,并重新散列,默认的加载因子为“0.75”。
\5. 查询时,先根据Key的HashCode计算出数组的下标位置,再利用Key的equals()方法检查到Key的位置,如果找到返回Key对应的Value,否则返回Null。
\6. 由于利用Key的HashCode直接计算出数据的存储位置,由于直接确定数据的存储位置,相对于其他查找方式,查询效率非常高。
Java 动态执行机制,可以实现动态执行功能:
\1. 反射提供了在运行时判断任意一个对象所属的类型,并可以检查解析类型的内部结构。
\2. 反射可以动态加载类型,并能够动态创建对象
\3. 反射可以动态访问对象的属性。
\4. 反射可以动态执行对象的方法。
\5. 利用反射API还可以动态的访问,不可见的属性和方法
\1. JDBC中,利用反射动态加载了数据库驱动程序。
\2. Web服务器中利用反射调用了Sevlet的服务方法。
\3. Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
\4. 很多框架都用到反射机制,注入属性,调用方法,如Hibernate、Struts2、Spring。
\1. 优点:可以动态执行!在运行期间根据业务功能动态执行方法、访问属性,最大限度发挥了java的灵活性。
\2. 缺点:对性能有影响,这类操作总是慢于直接执行java代码。
参考答案:
由关系、数据、数据之间的约束三者所组成的数据模型则称为RDBM S,即关系型数据库管理系统。
参考答案:
主流的数据库及其厂商如下:
Oracle数据库是著名的Oracle(甲骨文)公司的数据库产品,Oracle数据库是世界上第一个商品化的关系型数据库管理系统;OracIe数据库采用标准SQL(结构化查询语言),支持多种数据类型,提供面向对象的数据支持,具有第四代语言开发工具,支持UNIX、WINDOWS、OS/2等多种平台;Oracle公司的产品丰富,包括Oracle服务器、Oracle 开发工具和Oracle应用软件,其中最著名的就是Oracle数据库。
2)DB2是IBM公司的关系型数据库管理系统。DB2有很多不同的版本,可以运行在 从掌上产品到大型机不同的终端机器上;DB2 Universal Database Personal Edition和 DB2 Universal Database Workgroup Edition分别是单用户和多用户系统,可以运行在 OS/2和Windows上;DB2是Oracle的主要竞争对手。
3)Sybase是美国Sybase公司的关系型数据库系统。Sybase是较早采用C/S技术的数据库厂商;典型的UNIX或Windows NT平台上客户机/服务器环境下的大型数据库系统; Sybase通常与Sybase SQL Anywhere用于客户机/服务器环境,前者作为服务器数据库,后者为客户机数据库,采用该公司研制的PowerBuiIder为开发工具,在国内大中型系统中 具有广泛的应用;Sybase公司2010年被SAP收购。
4)Microsoft SQL Server是微软的产品,运行在Windows NT服务器上。Microsoft SQL Server的最初版本适用于中小企业,但是应用范围不断扩展,已经触及到大型、跨国企业的数据库管理。
5)MySQL是开放源码的小型关系型数据库管理系统。广泛应用在中小型网站中,成 本低、规模较Oracle和DB2小;2008年1月16日,Sun收购MySQL。 2009年4月 20日,SUN被Oracle公司收购,所以MySQL现在属于Oracle公司。
参考答案:
结构化旬语言(SQL)可分为:
1.数据定义语言(DDL):Data Definition Language
2.操纵语言(DML ) : Data Manipulation Language
3.事务控制语言(TCL):Transaction Control Language
4.数据查询语言(DQL):Data Query Language
5.数据控制语言(DCL):Data Control Language
参考答案:
事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度。两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:
1.幻读:事务TI读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次旬,结果集中可以看到T2插入的记录,这条新纪录则是幻读记录。
2·不可重复读取:事务TI读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次旬,发现与第一次读取的记录不同,这称为不可重复读。
3·脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2读取的行就无效,也就是脏数据。
为了处理这些问题,SQL标准定义了以下几种事务隔离级别:
1)READ UNCOMMITTED幻读、不可重复读和脏读都允许。
2)READ COMMITTED允许幻读、不可重复读,不允许脏读
3)REPEATABLE READ允许幻读,不允许不可重复读和脏读
4)SERIALIZABLE幻读、不可重复读和脏读都不允许
Oracle数据库支持READ COMMITTED和SERIALIZABLE这两种事务隔离级别。所以Oracle不支持脏读。SQL标准所定义的默认事务隔离级别是SERIALIZABLE但是Oracle 默认使用的是READ COMMITTEDe
参考答案:
1.为经常出现在WHERE语句中的列创建索引;为经常出现在ORDER BY、DISTINCT 后面的字段建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致;为经常作为表的连接条件的列上创建索引。
\2. 减少表之间的关联
\3. 优化sql,尽量让sql很快定位数据,不要让sql做做全表旬,应该走索引,把数据量大的表排在前面。
\4. 简化查询字段,没用的字段不要,对返回的结果进行控制,尽量返回少量数据。
参考答案:
索引的优点如下:
1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
\2. 可以大大加快数据的检索速度,这也是创建索引的最主要的原因;
\3. 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义.
\4. 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
\5. 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。
索引的缺点如下:
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加;
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大;
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度;
4.如果给不适合创建索引的列创建了索引,不会提高性能。
参考答案:
\1. 主键是为了标识数据库记录唯一性,不允许记录重复,且键值不能为空,主键也是一个特殊索引;
\2. 数据表中只允许有一个主键,但是可以有多个索引,
\3. 使用主数据库会自动创建主索引,也可以在非主键上创建索引,提高查询效率.
\4. 索引可以提高查询速度,它就相当于字典的目录,可以通过它很快查询到想要的结果,而不需要进行全表扫描
\5. 主键也可以由多个字段组成,组成复合主键,同时主键肯定也是唯一索引;
\6. 唯一索引则表示该索引值唯一,可以由一个或几个字段组成,一个表可以有多个唯一索引。
参考答案:
事务,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。
事务的特性四个特性ACID,分别表示·
原子性(atomicity):一个事务或者完全发生、或者完全不发生;
一致性(consistency):事务把数据库从一个一致状态转变到另一个状态;
隔离性(isolation):在事务提交之前,其他事务觉察不到事务的影响;
持久性(durability):一旦事务提交,它是永久的。
参考答案:
两种形式DTD和Schema,二者区别如下.
\1. Schema是标准的XML文件,而DTD则使用自己的特殊语法,因此,只需要知道XML 的语法规则就可以编写Schema了,不需要再学习其它语法规则。
\2. Schema利用命名空间将文件中特殊的节点与Schema说明相联系,一个XML文件可以有多个对应的Schema;而一个XML文件只能有一个相对应的DTD文件。
\3. Schema的内容模型是开放的,可以随意扩充,而DTD则无法解读扩充的内容。DTD 只能把文件类型定义为一个字符串,而XML Schema却允许把文件类型定义为整数,浮点数,字符串,布尔值或其他各数据类型,而无须重新定义。
参考答案:
Java中常用的XML解析技术有DOM、SAX两种方式,这两种方式的区别如下:
DOM解析处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档载入内存,适合对XML的随机访问。
SAX解析不同于DOM ,SAX是事件驱动型的XM L解析方法。它顺序读取XM L文件, 不需要一次全部装载整个文件。当遇到像文档开头,文档结束,或者标签开头与标签结束时, 它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XM L文件,适合对XM L的顺序序访问。
参考答案:
一个网页从请求到最终显示的完整过程一般可分为如下7个步骤:
\1. 在浏览器中输入网址;
\2. 发送至DNS服务器并获得域名对应的WEB服务器的IP地址,
\3. 与WEB服务器建立TCP连接;
\4. 浏览器向WEB服务器的IP地址发送相应的HTTP请求;
\5. WEB服务器响应请求并返回指定URL的数据,或错误信息,如果设定重定向,则重新发起请求重定向到新的URL地址。
\6. 浏览器下载数据后解析HTM L源文件,解析的过程中实现对页面的排版,解析完成 后在浏览器中显示基础页面。
\7. 分析页面中的超链接并下载图片、js等资源显示到当前页面,重复以上过程直至无超链接需要发送,完成全部显示。
\8. 断开TCP请求,结束请求过程。
参考答案:
HTML5是用于取代1999年所制定的HTML 4 .01和XHTML 1.0标准的HTML标准版本,现在仍处于发展阶段,但大部分浏览器已经支持某些HTML5技术。HTML 5有两大特点:首先,强化了web网页的表现性能。其次,追加了本地数据库等web应用的功能。广义论及HTML5时,实际指的是包括HTML、CSS和JavaScript在内的一套技术的组合,HTML5有如下几种特性:
语义特性(Semantic):HTML5赋予网页更好的意义和结构。更加丰富的标签将随着对RDFa、微数据、微格式等方面的支持,构建对程序、对用户都更有价值的数据驱动的 Web。
本地存储特性(OFFLINE & STORAGE):基于HTML5开发的网页APP拥有更短的启动时间,更快的联网速度,这些全得益于HTML5 APP Cache,以及本地存储功能。Indexed DB(html5本地存储最重要的技术之一)和API说明文档。
设备兼容特性(DEVICE ACCESS):从地理位置的API文档公开以来,HTML5为网页 应用开发者们提供了更多功能上的优化选择,带来了更多体验功能的优势。HTML5提供了前所未有的数据与应用接入开放接口。使外部应用可以直接与浏览器内部的数据直接相连,例如视频影音可直接与麦克风及摄像头相联。
连接特性(CON N ECTIVITY):更有效的连接工作效率,使得基于页面的实时聊天, 更快速的网页游戏体验,更优化的在线交流得到了实现。HTM L5拥有更有效的服务器推送技术,Server-Sent Event和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据"推送"到客户端的功能。
网页多媒体特性(MULTIMEDIA):支持网页端的Audio、Video等多媒体功能,与网站自带的APPS,摄像头,影音功能相得益彰。
5) 三维、图形及特效特性(3D, Graphics & Effects):基于SVG、Canvas、WebGL 及CSS3的3D功能,用户会惊叹于在浏览器中,所呈现的惊人视觉效果。
性能与集成特性(Class: Performance & Integration):没有用户会永远等待你的 Loading HTML5会通过XMLHttpRequest2等技术,帮助您的Web应用和网站在多样化的环境中更快速的工作。
CSS3是CSS技术的升级版本,CSS3语言开发是朝着模块化发展的。以前的规范作为一个模块实在是太庞大而且比较复杂,所以,把它分解为一些小的模块,更多新的模块也被加入进来。这些模块包括:盒子模型、列表模块、超链接方式、语言模块、背景和边框、文字特效、多栏布局等。
CSS3有如下几个特性·
CSS3圆角表格:圆角表格,对应属性:border-radiuse
以往对网页上的文字加特效只能用filter这个属性,这次CSS3中专门制订了一个加文字特效的属性,而目不止加阴影这种效果。对应属性:font-effecto
丰富了对链接下划线的样式,以往的下划线都是直线,这次可不一样了,有波浪线、点线、虚线等等,更可对下划线的颜色和位置进行任意改变。(还有对应顶线和中横线 的样式,效果与下划线类似)对应属性:text-underline-style,text-underline-color, text-underline-mode,text-underline-positione
在文字下点几个点或打个圈以示重点,CSS3也开始加入了这项功能,这应该在某些特定网页上很有用。对应属性:font-emphasize-style和font-emphasize-positione
参考答案:
块级元素的前后都会自动换行,如同存在换行符一样。默认情况下,块级元素会独占一行。例如,
、、
行内元素可以和其他行内元素位于同一行,在浏览器中显示时不会换行。例如,< a >、 等。
我们可以这样理解:如果元素是块级的,则总是在新行上显示,好比是书中的一个新段落;而元素如果是行内的,那么只能在当前行中显示,就像是段落中的一个单词。
因此,块级元素常用来构建网页上比较大的结构,用于包含其他块级元素、行内元素和文本;而行内元素一般只能包含其他行内元素和文本。
参考答案:
innerHTML outerHTML innerText之间的区别如下
innerHTML设置或获取位于对象起始和结束标签内的HTML;
outerHTML设置或获取对象及其内容的HTML形式
innerText设置或获取位于对象起始和结束标签内的文本
innerHTML与outerHTML在设置对象的内容时包含的HTML会被解析,而 innerText与outerText则不会。
在设置时,innerHTML与innerText仅设置标签内的文本,而outerHTML与 outerText设置包括标签在内的文本。
innerHTML符合W3C标准的属性,而innerText只适用于IE浏览器,因此,尽可能地去使用innerHTML,而少用innerText,如果要输出不含HTML标签的内容,可以使用innerHTML取得包含HTML标签的内容后,再用正则表达式去除HTML标签。
参考答案:
HTML页面有三种使用CSS样式表的方式:
\1. 内联样式表:样式规定在单个的元素中,写在元素的style属性里;
\2. 内部样式表:样式定义在HTML页面的头元素中;
\3. 外部样式表:将样式定义在一个外部的CSS文件中,然后由HTML页面引用样式表文件。
参考答案:
CSS使用层叠(Cascade)的原则来考虑继承、层叠次序和优先级等重要特征,从而判断相互冲突的规则中哪个规则应该起作用。
继承性是指,许多CSS的样式规则不但影响选择器所定义的元素,而且会被这些元素的后代继承。
层叠性是指,当一个web页面使用多个样式表,多个样式表中的样式可层叠为一个。
在多个样式表之间所定义的样式没有冲突的时候,浏览器会显示所有的样式。
优先级是指,当发生样式定义冲突时,浏览器首先会按照不同样式规则的优先级来应用样式。CSS样式的优先级如下所示(其中数字3拥有最高的优先权):
\1. 浏览器缺省设置;
\2. 外部样式表(.css文件)或者内部样式表(位于元素内部);
\3. 内联样式(作为某个元素的style属性的值)
同等优先级下,以最后定义的样式为准。
参考答案:
元素选择器是最常见的CSS选择器,即,文档的元素就是最基本的选择器。选择器通常是某个HTML元素,比如
、< h1 >、、< a >等,甚至可以是元素本身。
类选择器用于将样式规则与附带class属性的元素匹配,其中该class属性的值为类选择器中指定的值。使用类选择器时,首先需要定义样式类,其语法为: .className()
所有能够附带class属性的元素都可以使用此样式声明。只需要将class属性的值设置为"className",则可以将类选择器的样式与元素关联。
在实际使用时,如果需要为某种元素定义样式,则往往使用元素选择器;如果要应用样 式而不考虑具体设计的元素,最常用的方法就是使用类选择器。
参考答案:
Prototype是一个非常优雅的JS库,定义了JS的面向对象扩展,DOM操作API ,事件等等,以prototype为核心,形成了一个外围的各种各样的扩展库,是相当有前途的 JS底层框架,值得推荐。
jQuery是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持, 使我们写js变得更加方便,并目语法简洁和效率高一直是jQuery追求的目标。它注重简洁和高效,js效果有yui-ext的选择,因为yui-ext重用了很多jQuery的函数。
moo.fx—个超级轻量级的javascript特效库,能够与prototype.js或mootools 框架一起使用。它非常快、易于使用、跨浏览器、符合标准,提供控制和修改任何HTML 元素的CSS属性,包括颜色。它内置检查器能够防止用户通过多次或疯狂点击来破坏效果。
moo.fx整体采用模块化设计,所以可以在它的基础上开发你需要的任何特效。
参考答案:
JavaScript与Java是两个公司开发的不同的两个产品。Java是SUN公司推出的新一代面向对象的程序设计语言,特别适合于Internet应用程序开发;而JavaScript是 Netscape公司的产品,其目的是为了扩展Netscape Navigator功能,而开发的一种可以嵌入Web页面中的基于对象和事件驱动的解释性语言,它的前身是Live Script;而Java的前身是Oak语言。下面对两种语言间的异同作如下比较:
基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序 必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object Based)和事件驱动(Event Driver)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用,
解释和编译:Java的源代码在执行之前,必须经过编译;JavaScript是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
强类型变量和弱类型变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量声明,采用弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型,
参考答案:
JavaScript的数据类型可以分为三类:基本类型、特殊类型和复杂类型。
基本类型有string、number和boolean三种。其中,字符串是使用一对单引号或 者一对双引号括起来的任意文本;而数值类型都采用64位浮点格式存储,不区分整数和小数;布尔(逻辑)只能有两个值:true或falseo
特殊类型有null、undefined两种。其中,Undefined这个值表示变量不含有值, 即声明了变量但从未赋值;null在程序中代表"无值"或者"无对象",因此,可以通过将变量的值设置为null来清空里。
复杂类型指其他对象,如Array、Date、Object等。
参考答案:
JavaScript中常用的全局函数,及其作用如下:
parselnt:解析一个字符串并返回一个整数,
parseFloat:解析一个字符串并返回一个浮点数,
isNaN:检查某个值是否是数字,返回true或者false;
encodeURI:把字符串作为URI进行编码;
decodeURI ·对encodeURI()函数编码过的URI进行解码;
eval:计算某个字符串,以得到结果,或者用于执行其中的JavaScript代码
参考答案:
1)200 OK:请求已成功,请求所希望的响应头或数据体将随此响应返回。
2)302 Found:请求的资源现在临时从不同的URI响应应请求。
3)404 Not Fou nd:请求失败,请求所希望得到的资源未被在服务器上发现。
4)500 1nternal Server Error:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
5)400 Bad Request
当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求
参考答案:
B/S是Browser/Server的缩写,客户机上只要安装一个浏览器(Browser)如Netscape Navigator或Internet Explorer,服务器安装Oracle、Sybase、Informix或SQL Server 等数据库。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现。浏览器涌过Web Server同数据库进行数据交互。 C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、Informix或SQL Servero客户端需要安装专用的客户端软件。
参考答案:
J2EE是Sun公司提出的多层(multi-diered)、分布式(distributed)、基于组件 (component-base)的企业级应用模型(enterprise application model)o在这样的一个应 用系统中,可按照功能划分为不同的组件这些组件又可在不同计算机上,并且处于相应的 层次(tier)中。所属层次包括客户层@ient tier)组件、web层组件、Business层组件以及企业信息系统(EIS)层。
参考答案:
web容器给处于其中的应用程序组JSP、SERVLET供一个环境使JSP、SERVLET 直接跟容器中的环境变量接口交互,不必关注其它系统问题。例如:TOM CAT、WEBLOGIC、 WEBSPHERE等都为web容器。
参考答案:
Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTTP服务器上的数据库或应用程序)的中间层。与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java 虚拟机。
参考答案:
Servlet是运行在Servlet容器中的,由Servlet容器来负责Servlet实例的查找、创建以及整个生命周期的管理,Servlet整个生命周期可以分为四个阶段:类装载及实例创建阶段、实例初始化阶段、服务阶段以及实例销毁阶段。
类装载及实例创建阶段
默认情况下,ServIet实例是在接受到第一个请求时进行创建并且以后的请求进行复用,如果有Servlet实例需要进行一些复杂的操作,需要在初始化时就完成,比如打开文件、初始化网络连接等,可以配置在服务器启动时就创建实例,具体配置方法为在声明serviet标 签中添加l
初始化init(ServletConfig config).
一旦Servlet实例被创建,将会调用Servlet的init方法,同时传入ServletConfig实例,传入Servlet的相关配置信息,init方法在整个Servlet生命周期中只会调用一次。
服务service():
为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请 求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性。
销毁destory() ·
当Servlet容器将决定结束某个Servlet时,将会调用destory0方法,在destory方 法中进行资源释放,一旦destory方法被调用,Servlet容器将不会再发送可请求给这个 实例,若Servlet容器需再次使用该Servlet,需重新再实例化该Servlet实例。
参考答案:
GET和POST的区别如下:
从提交的数据量上来说,get方式会将请求参数及参数值放在请求资源路径里面,携带的数据大小有限制,不适合提交大量的数据;post方式会将请求参数及参数值放在实 体内容里面,理论上没有限制,适合大量数据的提交。
从安全上来讲,post方式相对安全(因为请求参数及值存放在实体内容里面,而 get方式会将请求参数及值显示在浏览器的地址栏)。但是要注意,post方式并没有将数据加密。
参考答案:
服务器向浏览器发送一个302状态码及一个Location消息头(该消息头的值是一个地址,称之为重定向地址) ,浏览器收到后会立即向重定向地址发出请求。
参考答案:
Servlet存在线程安全问题。容器收到请求之后,会启动一个线程来进行相应的处理。
默认情况下,容器只会为某个Servlet创建一个实例,如果同时有多个请求同时访问某个Servlet则肯定会有多个线程访问同一个Servlet实例。如果这些线程要修改Servlet实例的某个属性,就有可能发生线程安全问题。
可以使用synchronized对代码加锁来解决Servlet的安全问题。
参考答案:
转发和重定向的区别有以下几点:
重定向是浏览器发送请求并收到响应以后再次向一个新地址发请求,转发是服务器收到清求后为了完成响应转到一个新的地址。
重定向中有两次请求,不共享数据,转发只产生一次请求,且在组件间共享数据。
重定向后地址栏地址改变,而转发则不会。
重定向的新地址可以是任意地址,转发到的新地址必须是同个应用内的某地址。
参考答案:
Request对象:提供了当客户端请求一个页面或者传递一个窗体时,客户端提供的全部信息。这包括能指明浏览器和用户的HTTP变量在这个域名下存放在浏览器中的cookie
可作为团旬字符串而附于URL后面的字符串或页面的< FORM >段中的HTML控件的值。 也提供使用Secure Socket Layer(SSL)或其他加密通信协议的授权访问,及有助于对连接进行管理的属性。
Response对象:用来访问服务器端所创建的并发回到客户端的响应信息。提供HTTP 变量,指明服务器和服务器的功能和关于发回浏览器的内容的信息,以及倒可将为这个域而存放在浏览器里新的cookieo它也提供了一系列的方法用来创建输出,例如无处不在的 Response.write方法。
参考答案:
request的生命周期是一次请求。可以用于JSP表单提交数据;
session可以设置它的时间,tomcat中的默认时间为30分钟,当你关闭浏览器,
结束本次会话。Session对象的典型应用是用来对用户的身份进行验证,进而进行权限设置;
cookie存放的载体在客户端的浏览器中,生命周期默认是根据服务器返回的Set-Cookie头设置的。有2大类·
1)cookie:浏览器一关就没了;
2)有过期时间:超过设定的过期时间才消失。Cookie能使用户在不入密码和用户 名的情况下进入曾经浏览过的一些站点。
application生命周期在整个应用程序中。生命周期为应用程序启动到停止。 a pplication对象的最常见的应用是用来统计页面的访问人数或者是记录网站的在线人数。
参考答案:
过滤器是Servlet2.3规范中定义的一种小型的、可插入的Web组件。用来拦截Servlet 容器的请求和响应过程,以便查看、提取客户端和服务器之间正在交换的数据。过滤器通常是封装了一些功能的Web组件,这些功能很重要,但对于处理客户端请求或发送响应来说不是决定性的。典型的应用包括记录请求和响应的数据、管理会话属性等。
参考答案:
JSP在执行前先被转译成.Java文件(servlet),再编译成.class文件。每个JSP实例都有个jspservice方法,而这个jspservice方法将动态数据解释成以html标记的内容,然后再用JspWriter对象将一段一段地内容写向服务器,之后刷新JspWriter对象和关闭它,最后客户端所得到的就是html内容了。
参考答案:
JSP的四种范围如下·
page是代表与一个页面相关的对象和属性。一个页面由一个编译好的Java servlet 类表示。这既包括servlet又包括被编译成servlet的JSP页面;
request是代表与web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;
session是代表与用于某个Web客户机的一个用户体验相关的对象和属性。一个 web会话可以也经常会跨越多个客户机请求;
application是代表与整个Web应用程序相关的对象和属性。这实质上是跨越整个 web应用程序,包括多个页面、请求以及会话的一个全局作用域。
参考答案:
AJAXE Asynchronous JavaScript and Xml异步的JavaScript和Xml。它一种用来改善用户体验的技术,其实质是使用XMLHttpRequest对象异步地向服务器发请求。
服务器返回部分数据,而不是一个完整的页面,以页面无刷新的效果更改页面中的局部内容。
参考答案:
ajax设置同异步语句是:XMLHttpRequest.open(“Post”,url,true);其中第3个参数是设同步或者异步,true表示为异步。Ajax同步模式与异步模式的区别如下:
同步:提交请求一>等待服务器处理一>处理完毕返回。这个期间客户端浏览器不能做任何事。
异步:请求通过事件触发一>服务器处理(这时浏览器仍然可以做其他事情)一>处理完毕。
在同步的情况下,js会等待请求返回,获取status。不需要onreadystatechange事件处理函数。而异步则需要onreadystatechange事件处理,且值为4再处理下面的内容。
如果想获得返回值必须用同步,因为异步无法得到返回值。
ajax主要功能就是提供与服务器的异步交互,比如需要输入一个用户名,在输送完毕之后,没有确认提交,ajax可以通过异步提交来实现仅仅将输入的用户名发送到服务器数据库进行检测,然后回复是否重复。而同步提交就像注册完毕,将信息存储到数据库后提示注册成功。
参考答案:
JSON ( JavaScript Object Notation)是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式。
JSON最常见的用法之一,是从web服务器上读取JSON数据,将JSON数据转换为 JavaScript对象,然后在网页中使用该数据。
参考答案:
Spring框架的作用和优点如下·
\1. Spring是一个开源的轻量级的应用开发框架,其目的是用于简化企业级应用程序开发,减少侵入;
\2. Spring提供的IOC和AOP应用,可以将组件的耦合度降至最低,即解耦,便于系统日后的维护和升级;
\3. Spring为系统提供了一个整体的解决方案一开发者可以利用它本身提供的功能外, 也可以与第三方框架和技术整合应用,可以自由选择采用哪种技术进行开发。
参考答案:
可以通过< bean >定义的scope属性指定Bean对象的作用域或者使用注解
@Scope指定Bean对象的作用域。
默认Bean对象的作用域为singleton。
@Component、@Repository @Service、 @Scope、 @Autowired、 @lnject、 @Value
参考答案:
@Component为通用注解。
@Repository为持久层组件注解。
@Service为业务层组件注解。
@Scope为Bean的作用域注解。
@Autowired、@lnject为指定Bean之间依赖关系的注解。
@Value为注入Spring表达式值的注解。
参考答案:
Spring Web MVC的工作流程如下:
1.浏览器发出spring mvc请求,请求交给前端控制器DispatcherServlet处理。
\2. 控制器通过HandlerMapping维护的请求和Controller映射信息,找到相应的 Controller组件处理请求。
\3. 执行Controller组件约定方法处理请求,在约定方法中可以调用Service和DAO 等组件完成数据库操作。约定方法可以返回一个ModelAndView对象,封装了模型数据和视图名称信息。
\4. 控制器接收ModelAndView之后,调用ViewResolver组件,定位View的JSP并传递Model信息,生成响应界面结果。
参考答案:
IOC:控制反转,是一种设计模式。一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制;第二层是依赖注入:将相互互依赖的对象分离,在Spring配置文 件中描述他们的依赖关系。他们的依赖关系只在使用的时候才建立。
AOP:面向切面,是一种编思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。
Spring的AOP和IOC在项目中都是为了解决系统代码耦合度过高的问题。使代码重用度高、易于维护。比如事务、日志和安全等。
参考答案:
Spring的Bean有以下五种作用域:
\1. singleton:Springloc容器只会创建该Bean的唯一实例;
\2. prototype:每次请求都创建一个实例,
3.request:每次HTTP请求都会产生一个新的bean。需要注意的是,该作用域仅在基于Web的Spring ApplicationContext情形下有效,以下的session和global Session也是如此;
4.session:每次会话创建一个实例;
5.global session全局的HttpSession中,容器会返回该bean的同一个实例。
参考答案:
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交 互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。
参考答案:
低耦合是通过spring框架的IOC和AOP实现的。
将基于实现类的耦合变成基于接口的耦合,可以避免硬编码而造成的过度程序耦合,而 接下来需要解决的问题就是,如何确定该接口的实现类。IOC控制反转,就是将某一接口的具体实现类的控制从调用类中移除,转交给第三方,即Spring容器。
在业务系统里除了要实现业务功能之外,还要实现如权限拦截、性能监控、事务管理等非业务功能。通常的作法是非业务的代码穿插在业务代码中,从而导致了业务组件与非业务组件的耦合。AOP面向切面编程,就是将这些分散在各个业务逻辑代码中的非业务代码, 通过横向切割的方式抽取到一个独立的模块中,从而实现业务组件与非业务组件的解耦。
参考答案:
MyBatis最早源自Apache基金会的一个开源项目iBatis 2010年这个项目由 Apache software foundation迁移到了google code,并且改名为MyBatis;MyBatis 是支持普通SQL旬,存储过程和高级映射的优秀持久层框架。MyBatis封装了几乎所有 的JDBC代码和参数的手工设置以及结果集的检索;MyBatis使用简单的XML或注解做配置和定义映射关系,将Java的POJO(Plain Old Java Objects)映射成数据库中的记录。
参考答案:
MyBatis体系结构主要由以下几个关键部分:
1.加载配置
配置有两种形式,一种是XML配置文件,另一种是Java代码的注解。MyBatis将SQL 的配置信息加载成为一个个的MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),并将其存储在内存中
2.SQL解析
当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型) ,Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的 SQL语句和参数。
3.SQL执行
将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
4. 结果映射
将操作数据库的结果按照映射的配置进行转换,可以转换成Hash Map、JavaBean或 者基本数据类型,并将最终结果返回。
参考答案:
hibernate与MyBatis的对比·
MyBatis非常简单学,Hibernate相对较复杂,门槛较高;
二者都是比较优秀的开源产品;
当系统属于二次开发,无法对数据库结构亻故到控制和修改,那MyBatis的灵活性将比hibernate更适合;
系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的sql语句(或存储过程)才能达到系统性能设计指标。在这种情况下MyBatis会有更好的可控性和表现;
MyBatis需要手写sql语句也可以生成一部分,Hibernate则基本上可以自动生成, 偶尔会写一些hql同样的需求,MyBatis的工作量比Hibernate要大很多。类似的,如果涉及到数据库字段的修改Hibernate修改的地方很少,而MyBatis要把那些sql mapping 的地方一一修改;
MyBatis以数据库字段一一对应映射得到的po和Hibernte这种对象化映射得到的四是截然不同的,本质区别在于这种po是扁平化的,不像hibernate映射的po是可以表达立体的对象继承,聚合等等关系的这将会直接影响到你的整个软件系统的设计思路.
Hibernate现在已经是主流OR Mapping框架,从文档的丰富性,产品的完善性,版本的开发速度都要强于MyBatis
参考答案:
优点如下:
简化了项目依赖管理:
易于上手,对于新手可能一个"mvn clean package"命令就可能满足他的工作
便于与持续集成工具(jenkins)整合
便于项目升级,无论是项目本身升级还是项目使用的依赖升级。
有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,而不用自己去编译。
maven有很多插件,便于功能扩展,比如生产站点,自动发布版本等
缺点如下:
maven是一个庞大的构建系统,学习难度大
maven采用约定优于配置的策略(convention over configuration),虽然上手容易,但是一旦出了问题,难于调试。
当依赖很多时,m2eclipse 老是搞得Eclipse很卡。
中国的网络环境差,很多repository无法访问,比如google code, jboss 仓库无法访问等。
参考答案:
1.使用缓存的目的:
提高应用程序的性能,减少到数据库的访问次数
缓存的介质(缓存的存储位置)
内存:临时性存储空间 存取数据快 减少网络通信量
硬盘:永久性存储空间 存取速度慢
2.缓存的分类
客户端缓存:浏览器
服务器缓存:oscache,redis,memcache
3.缓存什么样的数据?
经常访问,又不经常修改的数据
4.缓存的有效性
为了避免脏数据的产生,要刷新缓存
5.脏数据
如果缓存中的数据和数据库中的数据不一致,那么缓存中的数据就被称之为脏数据
6.刷新缓存的方式
手动刷新:写程序的时候调用指定的代码清除缓存数据
定时刷新:当到达缓存过期时间后,会自动刷新数据
7.缓存的层次(一般我们将缓存加载service中)
jsp–>action–>service–>dao
缓存越靠前对性能的提高越大
8.缓存的清除策略:(缓存空间不足需要进行清理的时候使用)
LRU:最近最少使用原则.(理解:存储书)
FIFO:先进先出的缓存策略.(理解:排队)
9.什么时候使用缓存的清除策略?
当缓存中的数据已满,又有新的数据进来时,执行缓存的清除策略
参考答案:
索引的优点
创建唯一性索引,保证数据库表中每一行数据的唯一性
大大加快数据的检索速度,这也是创建索引的最主要的原因
减少磁盘IO(向字典一样可以直接定位)
索引的缺点
创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
索引需要占用额外的物理空间
当对表中的数据进行增加、删除和修改的时候,
索引也要动态的维护,降低了数据的维护速度
参考答案
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.顺序索引,散列索引,位图索引
参考答案:
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 服务器集群中,只有主机同时肩负读请求和写请求的两个功能,而从机只负责读请求,从机的数据更新都是由之前所提到的主从复制上获取的。因此,当出现意外情况的时候,很有必要新选出一个新的主机。
1.优选选择优先级高的从机
2.优先选择主从复制偏移量高的从机,即从机从主机复制的数据越多
3.优先选择有 runid 的从机
如果上面条件都一样,那么将 runid 按字典顺序排序并且通过加入哨兵来使redis主服务器宕机时,从服务器自动转换为主服务器继续提供服务
参考答案:
我们在项目中通常用EasyUI来充当展示层,因为它是一个RIA富客户端框架,
自身提供了很多功能强大的插件,可以提高用户的体验度而且也有助于我们
开发人员直接使用,提高开发效率。我们在项目中使用到的EasyUI插件有Layout布局,
EasyUI的tree,Tab页面,datagrid,form表单,Dialog对话框,Messager提示信息还有
Accordion手风琴效果,progress进度条等。
EasyUI的tree的生成方式有两种,一种是通过一条sql语句查询所有的菜单信息,
然后在java中通过递归的方式将其拼装成符合指定json格式的数据,这种适用
于数据量比较小的情况,通过减少数据库的访问次数提高性能,另一种是通过
ajax异步加载的方式,每点击一下树节点就向后台发送一次请求,从而来获取
该节点下的子节点,这种适用于数据量比较大的情况。这时候如果采用取出全
部数据递归拼装的话就有可能出现内存溢出。
我们当时在项目中是通过Easyui的tree来生成菜单,考虑到菜单的
数据量也不是特别的大,所以就采用了第一种取出所有数据并递归将其
拼装成指定Json的方式来提高性能,再者考虑到每个用户的菜单信息并
不是经常改变,所以又结合oscache缓存以及带有双重判定锁的单例模式
将其缓存到内存中,从而再次提高了性能。
参考答案:
基本来说MyISAM类型不支持事务处理而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外键。
参考答案:
ajax全称是异步JavaScript及xml;
ajax的核心JavaScript中的xmlHttpRequest(XHR);
使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域,所谓不能跨域就是不能跨多个网站(多个域名),不能跨多个项目可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的
参考答案:
负载均衡:
(了解)我们在做这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增加硬件的配置提高其性能,但这样做比较耗费资金,而且服务器内存空间也是有限的;所以后来就使用横向扩展来达到这一目的.
(主动说)当时我们使用nginx+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。这样大大的提高了服务的有效性,并且进一步提高了性能。
参考答案:
目前很多网站或应用在设计之初都会为高并发的数据请求做负载均衡,不差钱的土豪用户一般会直接买F5硬件设备作为其负载均衡器,原因不用多说,其功能强大,不仅包含负载均衡还包括应用交换、会话交换、状态监控、智能网络地址转换、通用持续性、响应错误处理、IPv6网关、高级路由、智能端口镜像、SSL加速、智能HTTP压缩、TCP优化、第7层速率整形、内容缓冲、内容转换、连接加速、高速缓存、Cookie加密、选择性内容加密、应用攻击过滤、拒绝服务(DoS)攻击和SYN Flood保护、防火墙过滤等功能,是不是很强大?当然价格也是让人很“心动”。而一些预算并不高,正在初期发展的网站来说,Nginx这种软负载也能
参考答案:
Nginx:高性能的 HTTP和反向代理服务器,同时支持作为IMAP/POP3/SMTP代理服务器。目前被很多网站应用为其HTTP软负载均衡器。高效的性能、良好的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗正逐渐被大型互联网公司所青睐。例如腾讯、淘宝、新浪等大型门户及商业网站都采用Nginx进行HTTP网站的数据分流。
参考答案:
Nginx采用的是反向代理技术,代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理,从而达到负载均衡的目的。
具体是怎么运行的呢?其实当Nginx启动后,其工作进程是由配置文件对其进行初始化的,主进程处理配置文件中的读取、端口绑定等特权操作,之后创建一小组子进程,由这些子进程进行请求的处理,同时缓存加载器加载硬盘中缓存到内存中,接着退出,保证资源开销始终保持着较低的状态。
Nginx推荐的配置是,一个工作进程对应一个CPU内核,确保硬件资源的有效利用。
一旦NGINX服务起来,仅有工作进程在忙,每个工作进程采用非阻塞地方式处理多个连接,降低上下文切换的次数。
每个工作进程都是单线程且独立运行,负责获取新连接并进行处理。进程之间通过共享内存进行通信,诸如缓存数据,会话持续化数据(ession persistence data),以及其他共享资源。
参考答案:
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 创建文件夹
9.vi文件名: 对指定的文件名进行编译。
按i进入编辑模式,
按ESC键进入命令模式
:wq! 强制保存并退出
:q!强制退出(!是强制的意思)
10.pwd :查看当前目录的完整路径
11.unzip 文件名.zip :解压后缀名为zip的压缩文件
zip 文件名.zip 要压缩的文件
12.mv 源文件 目标文件名(mv可以移动/重命名)
13.rm -rf 文件夹名 :递归强制删除文件夹及其下的文件
14.service iptables stop 禁用防火墙
15.chmod +x *.sh :使所有的后缀名为sh的文件,拥有可执行的权限
16.在bin目录下 ./startup.sh 启动tomcat
17.在bin目录下通过tail -f …/logs/catalina.out 来查看启动日志 tail -n 300 …/logs/catalina.out 查看最后三百行的信息
18.cat 文件名:查看整个文件内容
\19. ps -ef | grep 进程名:查看指定进程是否启动
20.kill -9 进程号 :强制杀死进程
killall -9 进程名
\21. find / -name 文件名 -print :查看指定文件的路径
vi 在命令模式下 yy复制当前光标所在行
p粘贴
dd 删除当前行
vi /etc/sysconfig/iptables 更改防火墙的配置文件,开放新的端口号
重启防火墙 service iptables restart
查看当前防火墙的状态 service iptables status
export JAVA_HOME = /usr/java/jdk.1.7.0_79
export PATH = J A V A H O M E / b i n L JAVA_HOME/binL JAVAHOME/binLPATH
source /etc/profile 使修改立即生效
echo $PATH 查看PATH值
参考答案:
我们在项目中的关系型数据库采用的是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语句进行的
参考答案:
1.需求分析
2.概要设计
3.详细设计(用例图,流程图,类图)
4.数据库设计(powerdesigner)
5.代码开发(编写)
6.单元测试(junit 白盒测试)(开发人员)
svn版本管理工具(提交,更新代码,文档)
7.集成测试 (黑盒测试,loadrunner(编写测试脚本)(高级测试))
8.上线试运行 (用户自己体验)
9.压力测试(loadrunner)
10.正式上线
11.维护
参考答案:
a) synchronized 方法
b) synchronized 块(同步代码块)
避免使用全局变量
使用ThreadLocal(参考:http://blog.csdn.net/drifterj/article/details/7782706)
a) 为多线程并发的互斥控制提供了另一种全新的解决思路
b) 通过ThreadLocal为其他模块的API传递参数
参考答案:
HttpClient是Apache Jakarta Common下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
参考答案:
SSO(Single Sign On)流行的业务整合解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
参考答案:
设置cookie不能在两个系统中。我们都知道cookie是跟随域名的。万一域名或者IP地址不同就会造成cookieA域名写的B域名是无法读取的。具体体现在两个不同的子系统。
例如:不能在sso中设置cookie,然后在前台读取,这样可能因为域名的不同而造成无法读取cookie的值。必须在前台中设置,前台中读取。当然设置的点是不同的。如设置是前台发起登录,到后台验证登录会,返回前台调用,然后前台调用写cookie。另外用户登录,然后查询cookie,然后获取数据。两个流程是分开的,各走各的。
参考答案:
会保留下来。因为cookie跟浏览器相关,cookie信息是保存在本地的。跟后台访问到哪个tomcat是没有关系的。这样就可以形成前端web服务的集群,就形成了一个单点登录系统。
参考答案:
RabbitMQ是一个开源的,RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
支持主流的操作系统Linux、Windows、MacOX等。
多种开发语言支持java、Python、Ruby、.NET、PHP、C/C++、node.js等。
参考答案:
RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
Redis是一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。
具体对比
序号 | 对比项 | Redis | RabbitMQ |
---|---|---|---|
1 | 可靠消费 | 没有相应的机制保证消息的消费,当消费者消费失败的时候,消息体丢失,需要手动处理 | 具有消息消费确认,即使消费者消费失败,也会自动使消息体返回原队列,同时可全程持久化,保证消息体被正确消费 |
2 | 可靠发布 | 不提供,需自行实现 | 具有发布确认功能,保证消息被发布到服务器 |
3 | 高可用 | 采用主从模式,读写分离,但是故障转移还没有非常完善的官方解决方案 | 集群采用磁盘、内存节点,任意单点故障都不会影响整个队列的操作 |
4 | 持久化 | 将整个Redis实例持久化到磁盘 | 队列,消息,都可以选择是否持久化 |
5 | 消费者负载均衡 | 不提供,需自行实现 | 根据消费者情况,进行消息的均衡分发 |
6 | 队列监控 | 不提供,需自行实现 | 后台可以监控某个队列的所有信息,(内存,磁盘,消费者,生产者,速率等) |
7 | 流量控制 | 不提供,需自行实现 | 服务器过载的情况,对生产者速率会进行限制,保证服务可靠性 |
8 | 应用场景分析 | 轻量级,高并发,延迟敏感 即时数据分析、秒杀计数器、缓存等 | 重量级,高并发,异步 批量数据异步处理、并行任务串行化,高负载任务的负载均衡等 |
参考答案:
目前成熟的消息队列产品有很多,著名的例如rabbitmq。它使用起来相对还是比较简单的,功能也相对比较丰富,一般场合下是完全够用的。但是有个很烦人的就是它不支持优先级。
例如一个发邮件的任务,某些特权用户希望它的邮件能够更加及时的发送出去,至少比普通用户要优先对待。默认情况下rabbitmq是无法处理掉的,扔给rabbitmq的任务都是FIFO先进先出。但是我们可以使用一些变通的技巧来支持这些优先级。创建多个队列,并为rabbitmq的消费者设置相应的路由规则。
例如默认情况下有这样一个队列,我们拿list来模拟 [task1, task2, task3],消费者轮流按照FIFO的原则一个个拿出task来处理掉。如果有高优先级的任务进来,它也只能跟在最后被处理[task1, task2, task3, higitask1]. 但是如果使用两个队列,一个高优先级队列,一个普通优先级队列。 普通优先级[task1, task2, task3], 高优先级[hightask1 ] 然后我们设置消费者的路由让消费者随机从任意队列中取数据即可。
并且我们可以定义一个专门处理高优先级队列的消费者,它空闲的时候也不处理低优先级队列的数据。这类似银行的VIP柜台,普通客户在银行取号排队,一个VIP来了他虽然没有从取号机里拿出一个排在普通会员前面的票,但是他还是可以更快地直接走VIP通道。
参考答案:
Lucene始于2000年,是一套用于全文检索和搜索的的开源程序库,由Apache软件基金会支持和提供。它提供了一个简单却强大的应用程序接口,能够做全文检索和搜寻,在Java开发环境里Lucene是一个成熟的免费开源的代码工具。
参考答案:
计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
全文数据的搜索主要有两种: 1.顺序扫描法 2.全文检索法
1.顺序扫描法在系统里面就有体现,windows当中的搜索功能就有搜索文件,或者搜索文件内容的选项;如果是按照搜索文件当中的内容时,那么windows就会顺序扫描计算机当中的每一个文件,去查找包含指定内容的文件。不用多说,会非常慢。
2.全文检索接触过数据库之后,针对数据库当中的结构化数据的搜索速度是很快的,而将非结构化的数据转换成结构化的数据,然后再进行搜索,这就是全文检索的基本思路了。
这种先建立索引,然后再对索引进行搜索的过程叫做全文检索。
参考答案:
庖丁解牛分词包,
LingPipe,开源自然语言处理的Java开源工具包。
参考答案:
Store:是否存储到索引库,如果不存储,搜索结果不会返回。
Index:是否通过该字段搜索,
例如:
ID: 存储、索引、不分词(用户输入完整ID)
标题: 存储、索引、分词(用户输入部分标题)
图片: 存储(用户没有查询要求)
价格: 存储、不索引、不分词
参考答案:
Solr是基于Lucene技术实现的一个搜索服务,它提供了基于HTTP方式的访问接口,其API接口支持多种数据格式(包括JSON、XML),所以各种语言都可以方便地调用Solr的搜索服务。
Solr支持集群技术、利用Solr云,使用者可以透明地对索引数据进行分片和复制,提高整个系统的高负荷量和高可用性。
相比之下,Lucene仅仅是它的核心搜索技术的实现,Lucene仅支持java语言的客户端使用者(Lucene有基于.net的移植项目,但已经商业化不支持开源)
lucene是全文检索的API,solr是全文检索的服务。
Solr是基于Lucene的全文搜索服务器。
Solr提供标准的REST API,任何编程语言都可以使用。
Solr提供分布式索引、负载均衡的查询、自动故障转移和恢复等功能。
参考答案:
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
分布式高并发断点续爬-爬虫
自行实现
多线程
线程池
AKKA框架
利用消息队列RabbitMQ,异步分布式高并发爬虫。
使用竞争的work模式,各个消费者都连接到一个消息队列中,形成一起抢任务。
设置为手工消息应答模式:当处理业务的节点宕机,此消息不会被移除。当RabbitMQ节点当前,RabbitMQ支持消息持久化,重启后消息不会丢失。继续执行。
答案:
事务:事务是一系列操作组成的工作单元,该工作单元内的操作是不可分割的,即要么所有操作都做,要么所有操作都不做。从数据库的角度来说,就是一组SQL语句。
事务具有4个特性,缺一不可,即:ACID(原子性、一致性、隔离性和持久性)
原子性:事务是不可分割的最小单元,事务内的操作要么全部都做,要么全部都不做。
一致性:事务执行时,是从一个一致状态变成另一个一致状态。
隔离性:一个事务的执行,不受其他事务(进程)的干扰。
持久性:事务一旦提交,对数据库的改变是持久的。
Spring框架提供了基于编程式事务管理和基于声明式事务管理。
答案:
ContextLoaderListener是一个ServletContextListener, 它在你的web应用启动的时候初始化。缺省情况下, 它会在WEB-INF/applicationContext.xml文件找Spring的配置。 你可以通过定义一个元素名字为”contextConfigLocation”来改变Spring配置文件的位置。示例如下:
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
/WEB-INF/xyz.xml
答案:
1.BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
2.ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问:Resource rs = ctx. getResource(”classpath:config.properties”)
c. 事件传递:通过实现ApplicationContextAware接口
**难度等级:**简单
答案:
1.低侵入式设计,代码污染极低
2.独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
3.Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦
4.Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
5.Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
6.Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
**难度等级:**简单
答案:
用setter方式注入:
1)与传统的JavaBean的写法更相似,程序开发人员更容易理解、接受。通过setter方法设定依赖关系显得更加直观、自然。
2)对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因而导致性能下降。而是用设置注入可以避免这些问题。
3)尤其在某些属性可选的情况下,多参数的构造器更加笨重。
用构造方式注入:
1)与传统的JavaBean的写法更相似,程序开发人员更容易理解、接受。通过setter方法设定依赖关系显得更加直观、自然。
2)对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因而导致性能下降。而是用设置注入可以避免这些问题。
3)尤其在某些属性可选的情况下,多参数的构造器更加笨重。
采用setter注入为主,构造注入为辅的注入策略。对于依赖关系无需变化的注入,尽量采用构造注入;而其它的依赖关系的注入,则考虑设值注入。
**难度等级:**简单
答案:
虽然两种模式都是将对象的创建从应用的逻辑中分离,但是依赖注入比工厂模式更清晰。通过依赖注入,你的类就是 POJO,它只知道依赖而不关心它们怎么获取。使用工厂模式,你的类需要通过工厂来获取
**难度等级:**简单
答案:
实施spring mvc项目的步骤:
1.添加jar包的依赖(maven,zip的开发包手动导入)
spring mvc必备jar包
spring-web
spring-webmvc
spring mvc辅助jar(处理json数据controller–》页面)
jackson-core com.fasterxml.jackson.core.jackson-core
jackson-databind com.fasterxml.jackson.core.jackson-databind
spring容器的必备jar包
spring-context
2.添加配置文件
spring.xml 除了springmvc和mybatis之外的spring配置项
spring_mvc.xml spring mvc相关的配置项
web.xml
contextConfigLocation
classpath:conf/spring.xml
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/*
dispatcher
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:conf/spring_mvc.xml
1
dispatcher
*.do
org.springframework.web.context.ContextLoaderListener
3.建立Controller类 ,spring mvc controller类不需要
继承任何类,所以说springmvc是轻量级框架(没有任何
侵入性和耦合性或依赖性)
a.在类上添加@Controller注解(特别注意,不能写@Component)
如果在类上添加@RequestMapping("/user"),/user相当于一个
命名空间,区分和管url
如果有@Controller注解需要spring的组件扫描
b.在当前controller类里添加一个方法,方法名任意
方法的参数跟客户端js发送json字符串中的key是一样
方法的返回值类型就是响应数据会客户端js的对象类型
(需要借助第三方工具jackson)
c.在controller类里的当前方法前面添加两个注解
@RequestMapping(value=“login1.do”,method=RequestMethod.GET)
value:请求的url的实际地址,当客户端请求此实际地址
那么springmvc就调用此注解修饰的方法,方法定位
method:指的是请求的方法(get,pot,put,delete)
@ResponseBody 此注解是指定当前方法返回的对象可以是
一个对象,并可以借助第三方工具jackson
工具转换json字符串响应给客户端的js
d.程序员就只需要关注业务的实现
4 启动tomcat服务器,初始化tomcat容器,spring容器
spring mvc容器
**难度等级:**简单
答案:
1.构造方法注入;
2.设置属性注入;
3.接口注入。
**难度等级:**简单
答案:
1.前置通知
2.后置通知
3.异常通知
4.最终通知
5.环绕通知
**难度等级:**简单
答案:
特点:
1.方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
2.AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
3.声明事物的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6.降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
7.Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
用到了,javase的相关技术:集合,io,xml读写等
**难度等级:**简单
答案:
在spring的配置文件中的bean节点中的property节点的name属性,对应的类中没有setter方法时会报NotWritablePropertyException
applicationContext.xml的路径放置错误,读取不到这个文件时会报Could not open path resource[ApplicationContext.xml]
**难度等级:**简单
答案:
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
**难度等级:**简单
答案:
lazy-init属性的作用和优缺点:
一个设置为lazy-init属性的bean,就意味要延迟加载,也就是IoC 容器将第一次被用到时才开始实例化。
bean的默认lazy-init=false,不需要延迟加载,IoC 容器将在服务器启动的时候,会解读ApplicationContext.xml文件,不管你是不是要使用该bean,都会先进行实例化。这会造成启动的时候,特别的慢。但是,也是最保险的方法。
描述init-method和destory-method属性的作用:
init-method和destroy-method方法来实现Bean的初始化和销毁时附加的操作
factory-method属性的作用:
用静态工厂的方式实例化
id:指定要实例化的对象名称
class:是一个普通的java类,在此类中有一个静态的方法
getObject,在此方法中return出一个UserDaoMySql
的对象
factory-method:是一个静态方法的方法名
**难度等级:**简单
答案:
在spring中定义了5中不同的事务隔离级别:
说明 :Oracle数据库缺省的事物隔离级别已经保证了避免脏读和不可重复读。但可能会幻读,避免幻读需要加表级锁,Oracle缺省行级锁。在基于Spring的事物配置中一定要慎重使用ISOLATION_SERIALIZABLE的事物隔离级别。这种配置会使用表级锁,对性能影响巨大。一般没有特殊需要的话,配置为使用数据库缺省的事物隔离级别便可。
**难度等级:**简单
答案:
spring 的优点?
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部
什么是DI机制?
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者
因此也称为依赖注入。
spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
Spring的事务管理机制实现的原理,就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的。
**难度等级:**简单
S****pring主线内容:
解耦和减少侵入
S****pring 核心 IOC DI
S****pring aop
**轻量:**Spring 是轻量的
**控制反转:**Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
**面向切面的编程(AOP):**Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
**容器:**Spring 包含并管理应用中对象的生命周期和配置。
MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
**事务管理:**Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
**异常处理:**Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
IOC 或 依赖注入把应用的代码量降到最低。最小的代价和最小的侵入性使松散耦合得以实现。IOC容器支持加载服务时的饿汉式初始化和懒加载。
**FileSystemXmlApplicationContext :**此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
**ClassPathXmlApplicationContext:**此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
**WebXmlApplicationContext:**此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。
AnnotationConfigApplicationContext:解析带有注解的
\1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
\2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
c. 事件传递:通过实现ApplicationContextAware接口
Application contexts提供一种方法处理文本消息,一个通常的做法是加载文件资源(比如镜像),它们可以向注册为监听器的 bean发布事件。另外,在容器或容器内的对象上执行的那些不得不由bean工厂以程序化方式处理的操作,可以在 Application contexts中以声明的方式处理。Application contexts实现了MessageSource接口,该接口 的实现以可插拔的方式提供获取本地化消息的方法。
依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
**构造器依赖注入:**构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
**Setter方法注入:**Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
你两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。
Spring Beans
S****pring bean就是一个对象,既然有的对象.考虑对象的生命周期
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中 的形式定义。
Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为 TRUE,bean 就是单件,否则就是一个 prototype bean。默认是TRUE,所以所有在Spring框架中的beans 缺省都是单件。
一个Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。
这里有三种重要的方法给Spring 容器提供配置元数据。
XML配置文件。
基于注解的配置。
基于java的配置。
当定义一个 在Spring里,我们还能给这个bean声明一个作用域。它可以通过bean 定义中的scope属性来定 义。如,当Spring要在需要的时候每次生产一个新的bean实例,bean的scope属性被指定为prototype。另一方面,一个bean每次 使用的时候必须返回同一个实例,这个bean的scope 属性 必须设为 singleton。
Spring框架支持以下五种bean的作用域:
singleton : bean在每个Spring ioc 容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
缺省的Spring bean 的作用域是Singleton.
不,Spring框架中的单例bean不是线程安全的。
初始: 单例,在spring容器加载的时候就生命周期开始
中间: init_method=****”init”
消亡: 在spring容器消亡的时候 destroy_method=****”destroy”
"Spring容器 从XML 文件中读取bean的定义,并实例化bean。
Spring根据bean的定义填充所有的属性。
如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
如果bean实现了 DisposableBean,它将调用destroy()方法。
Init_method=”任意方法名称” destroy_method=****”任意方法名称”
有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。
The bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。
当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML 的 配置元数据中,可以在 或 元素内使用 元素,内部bean通常是匿名的,它们的Scope一般是prototype。
Spring提供以下几种集合的配置元素:
类型用于注入一列值,允许有相同的值。
类型用于注入一组值,不允许有相同的值。
类型用于注入一组键值对,键和值都可以为任意类型。
类型用于注入一组键值对,键和值都只能为String类型。
有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。
no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
**byName:**通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
**byType::**通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
**autodetect:**首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。
可以提高开发效率,但是降低了程序的可读性
自动装配的局限性是:
重写: 你仍需用 和 配置来定义依赖,意味着总要重写自动装配。
基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。
**模糊特性:**自动装配不如显式装配精确,如果有可能,建议使用显式装配。
Spring注解
实例化对象:
@Controller @Service @ Repository @Component
context:component-scan
注入:
@Resource @Autowired @Qualifier @Inject @Named
context:component-scan
基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。
以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。
注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 context:annotation-config/元素。
context:component-scan
修饰在setter方法上,要求setter方法必须存储数据
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。
@Autowired @Qualifier
P****rivate UserDao userDao;
@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。
当有多个相同类型的bean却只有一个需要自动装配时,将@Qualifier 注解和@Autowire 注解结合使用以消除这种混淆,指定需要装配的确切的bean。
Spring数据访问
S****pringjdbc把常规的代码都封装起来,使用的时候就直接调用
S****pring jdbc中有一个JdbcTemplate
使用SpringJDBC 框架,资源管理和错误处理的代价都会被减轻。所以开发者只需写statements 和 queries从数据存取数据,JDBC也可以在Spring框架提供的模板类的帮助下更有效地被使用,这个模板叫JdbcTemplate (例子见这里here)
JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理。
Spring对数据访问对象(DAO)的支持旨在简化它和数据访问技术如JDBC,Hibernate or JDO 结合使用。这使我们可以方便切换持久层。编码时也不用担心会捕获每种技术特有的异常。
Spring支持以下ORM:
Hibernate
iBatis
JPA (Java Persistence API)
TopLink
JDO (Java Data Objects)
OJB
Spring支持两种类型的事务管理:
编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
**声明式事务管理:**这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
它为不同的事务API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式。
它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API如
它支持声明式事务管理。
它和Spring各种数据访问抽象层很好得集成。
大多数Spring框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理,虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵活性。
OOP面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。
AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
(1)AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
(2)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:
①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
(3)静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最终生成的代理实例; method 是被代理目标实例的某个具体方法; args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。
异常管理
性能管理
事务管理 @Transaction
权限管理 @Privilege(name=””)
SpringMVC是一个前端控制框架,主要用来接收用户提交的参数,和响应数据…SpringMVC是Spring家族的一大组件.
Spring是一个父级容器,
SpringMVC是一个子级容器.子级容器中的某写特定用法,不能用到Spring中
1.每编写一个Servlet都需要编写8行配置文件.
2.每个Servlet的入口;方法只有一个,只能处理一个业务.如果处理多个业务必须编写多个Servlet.这样的设计模式,太繁琐.
3.servlet获取参数时,必须一个一个的获取.并且参数类型必须手动转化.
3.1前端控制器(DispatcherServlet) 功能:转发request和response
3.2处理器映射器 根据用户提交的url.找到能够处理的Controller
3.3处理器适配器 根据特定的规则执行用户的请求.
3.4视图解析器 将用户返回的页面名称,自动拼接为具体页面路径.
Url:localhost:8090/项目名/hello.action
服务端接收到请求后,servlet-sevice-dao(handler).给用户一个响应.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8iIpB6w-1615101859307)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps6.jpg)]
步骤:
1.客户端发送请求:localhost:8090/项目名/hello.action,发送给前端控制器
2.前端控制请求处理器映射器,查询能够处理该请求的Controller
3.将找到的Controller路径返回给前端控制器.
4.请求处理器适配器找到合适的处理器.处理请求.
5.处理器适配器找到合适的处理器.执行请求代码.(controller-service-dao)
6.将处理后的结果和响应页面封装到ModelAndView对象中,返回给处理器适配器.
7.将ModelAndView对象返回给前端控制器.
8.请求视图解析器帮助解析View对象,到底是哪个页面.
9.视图解析器内部拼接.将页面名称拼接成真实的页面路径,返回给前端控制器.View=hello /WEB-INF/hello.jsp 拼接前缀和后缀
10.将数据填充到页面中(request域中)该过程叫做视图渲染.之后返回给用户进行展现.
答: 是 P r o p e r t i e s 文 件 中 的 变 量 占 位 符 , 它 可 以 用 于 标 签 属 性 值 和 s q l 内 部 , 属 于 静 态 文 本 替 换 , 比 如 {}是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如 是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如{driver}会被静态替换为com.mysql.jdbc.Driver。#{}是sql的参数占位符,Mybatis会将sql中的#{}替换为?号,在sql执行前会使用PreparedStatement的参数设置方法,按序给sql的?号占位符设置参数值,比如ps.setInt(0, parameterValue),#{item.name}的取值方式为使用反射从参数对象中获取item对象的name属性值,相当于param.getItem().getName()。
答:还有很多其他的标签,、、、、,加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。
答:Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个、、、标签,都会被解析为一个MappedStatement对象。
Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
答:Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10
答:Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
答:能,JDBC都能,Mybatis当然也能。
答:Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind。
其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
结果集的列名字跟实体的中的setter和getter匹配
比如结果集列名字为 username -> Username ->setUsername
->getUsername
答:第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
答:能,Mybatis不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把selectOne()修改为selectList()即可;多对多查询,其实就是一对多查询,只需要把selectOne()修改为selectList()即可。
关联对象查询,有两种实现方式,一种是单独发送一个sql去查询关联对象,赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用join查询,一部分列是A对象的属性值,另外一部分列是关联对象B的属性值,好处是只发一个sql查询,就可以把主对象和其关联对象查出来。
那么问题来了,join查询出来100条记录,如何确定主对象是5个,而不是100个?其去重复的原理是标签内的子标签,指定了唯一确定一条记录的id列,Mybatis根据列值来完成100条记录的去重复功能,可以有多个,代表了联合主键的语意。
同样主对象的关联对象,也是根据这个原理去重复的,尽管一般情况下,只有主对象会有重复记录,关联对象一般不会重复。
举例:下面join查询出来6条记录,一、二列是Teacher对象列,第三列为Student对象列,Mybatis去重复处理后,结果为1个老师6个学生,而不是6个老师6个学生。
t_id t_name s_id
| 1 | teacher | 38 |
| 1 | teacher | 39 |
| 1 | teacher | 40 |
| 1 | teacher | 41 |
| 1 | teacher | 42 |
| 1 | teacher | 43 |
答:Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
答:不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;毕竟namespace不是必须的,只是最佳实践而已。
原因就是namespace+id是作为Map
答:使用BatchExecutor完成批处理。
答:Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
**SimpleExecutor:**每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
**ReuseExecutor:**执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map
**BatchExecutor:**执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
答:在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。
答:Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。
答:虽然Mybatis解析Xml映射文件是按照顺序解析的,但是,被引用的B标签依然可以定义在任何地方,Mybatis都可以正确识别。
原理是,Mybatis解析A标签,发现A标签引用了B标签,但是B标签尚未解析到,尚不存在,此时,Mybatis会将A标签标记为未解析状态,然后继续解析余下的标签,包含B标签,待所有标签解析完毕,Mybatis会重新解析那些被标记为未解析的标签,此时再解析A标签时,B标签已经存在,A标签也就可以正常解析完成了。
答:Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个、、、标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。
答:Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
面试题看似都很简单,但是想要能正确回答上来,必定是研究过源码且深入的人,而不是仅会使用的人或者用的很熟的人,以上所有面试题及其答案所涉及的内容,在我的Mybatis系列博客中都有详细讲解和原理分析。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUlQeFv8-1615101859308)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps7.jpg)]
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
Shiro主要组件还包括:
Authenticator :认证就是核实用户身份的过程。这个过程的常见例子是大家都熟悉的“用户/密码”组合。多数用户在登录软件系统时,通常提供自己的用户名(当事人)和支持他们的密码(证书)。如果存储在系统中的密码(或密码表示)与用户提供的匹配,他们就被认为通过认证。
Authorizer :授权实质上就是访问控制 - 控制用户能够访问应用中的哪些内容,比如资源、Web页面等等。
SessionManager :在安全框架领域,Apache Shiro提供了一些独特的东西:可在任何应用或架构层一致地使用Session API。即,Shiro为任何应用提供了一个会话编程范式 - 从小型后台独立应用到大型集群Web应用。这意味着,那些希望使用会话的应用开发者,不必被迫使用Servlet或EJB容器了。或者,如果正在使用这些容器,开发者现在也可以选择使用在任何层统一一致的会话API,取代Servlet或EJB机制。
CacheManager :对Shiro的其他组件提供缓存支持
需要继承AuthorizingRealm类
重写doGetAuthenticationInfo方法,实现登录认证
重写doGetAuthorizationInfo方法,实现授权认证
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oThPaRuY-1615101859309)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps8.jpg)]
\1. 易于理解的 Java Security API;
\2. 简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
\3. 对角色的简单的签权(访问控制),支持细粒度的签权;
\4. 支持一级缓存,以提升应用程序的性能;
\5. 内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;
\6. 异构客户端会话访问;
\7. 非常简单的加密 API;
\8. 不跟任何的框架或者容器捆绑,可以独立运行。
首先Shiro较之 Spring Security,Shiro在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势。
Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。如下是它所具有的特点:
易于理解的 Java Security API;
简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
对角色的简单的签权(访问控制),支持细粒度的签权;
支持一级缓存,以提升应用程序的性能;
内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;
异构客户端会话访问;
非常简单的加密 API;
不跟任何的框架或者容器捆绑,可以独立运行。
除了不能脱离Spring,shiro的功能它都有。而且Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。Spring Security的权限细粒度更高
1.1. 描述Servlet调用过程?
答案:
(1)在浏览器输入地址,浏览器先去查找hosts文件,将主机名翻译为ip地址,如果找不到就再去查询dns服务器将主机名翻译成ip地址。
(2)浏览器根据ip地址和端口号访问服务器,组织http请求信息发送给服务器。
(3)服务器收到请求后首先根据Host请求头判断当前访问的是哪台虚拟主机。
(4)服务器根据http请求头中的请求URI判断当前访问的是哪个web应用。
(5)服务器根据http请求头中的请求URI判断当前访问的是web应用中的哪个web资源。
(6)检查web应用的web.xml文件,如果根据路径找到具体的servlet处理类的全路径名交给该servlet处理,如果找不到就交给缺省servlet处理。
(7)这个过程中浏览器只知道自己发出来http请求,不久就收到了http响应,浏览器不知道也不关心服务器内部是如何处理的。浏览器和服务器之间的关系是非常单纯的,只有HTTP协议。
(8)解析请求、封装RequestResponse对象、创建Servlet、调用Service方法都是服务器自动进行的,开发人员只需要写好Servlet配置进容器中即可,无需操心具体的底层实现。
答案:
(1)Servlet第一次被访问到时创建对象,创建出来后立即执行init方法执行初始化的操作。
(2)从此以后该对象一直驻留在内存中为后续的对这个Servlet的请求进行服务。
(3)直到服务器关闭或web应用移除出容器时,随着web应用的销毁Servlet对象销毁掉,在销毁之前调用destory方法执行善后工作。
(4)在存活期间,每次对Servlet 的调用都会导致Service方法的执行。
答案:
HTTP协议就是一套基于tcp/ip协议的应用层协议 。简单来说,就是一个基于应用层的通信规范,双方要进行通信,大家都要遵守一个规范,这个规范就是HTTP协议。它规定了客户端(通常是浏览器)和服务器之间的通信方式。
答案:
HTTP协议基于请求响应模型。
一次请求对应一次响应。
首先客户端发送一个请求(request)给服务器,服务器在接收到这个请求后将生成一个响应(response)返回给客户端。
答案:
(1) 它是一个无状态的协议,服务器端在处理相应请求后不会保留任何客户端的信息,每次请求都是独立的
(2) 客户端与服务器端的每一次数据交互,都要经过一次请求/响应的过程。
(3) 服务器端无法识别能够出发客户端请求的方法。
(4) 一个典型的HTTP请求分为 一个请求行 若干请求头 一个空行 实体内容。
答案:
(1) get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
(2) get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?“连接,而各个变量之间使用”&"连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
(3) get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据, POST数据是没有限制的,上传文件通常要使用post方式;
(4) 使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post;
(5) get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。
(6) Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost()。
答案:
浏览器用什么码表来打开表单页面就用什么编码来发送数据。当前我们的注册页面指定了用utf-8来打开。
这就决定了浏览器是用utf-8打开的页面,浏览器在提交表单时是用utf-8编码的。
而tomcat默认情况下会使用iso8859-1来进行解码。
我们知道全世界的码表都兼容iso8859-1,所以英文处理是没有问题的。
但是iso8859-1中并没有中文,iso8859-1对于无法处理的字节都使用?替代,所以我们看到的都是?。
答案:
由于客户端发送时使用的是utf-8编码而服务器用iso8859-1解码造成了乱码,虽然字符已经乱掉了,但底层的字节仍然是正确的,我们只要将乱码字符getBytes(“iso8859-1”)转换为字节,就是正确的字节,再将这些字节new String(bytes,“utf-8”)按照正确的码表编码,就可以转换回正确的字符了。从而解决了乱码。
答案:
request对象的生命周期是针对一个客户端(一个浏览器应用程序)的一次请求,当请求完毕之后,request里边的内容也将被释放,一个请求开始时创建,请求结束后销毁。
答案:
通过response.setHeader(“Content-Type”, “text/html;charset=utf-8”)方法,通知服务器发送数据时的码表;通过response.setCharacterEncoding(“utf-8”)方法,通知浏览器解析时使用的码表。两码相同就不会有乱码了。
response提供了setContentType(“text/html;charset=UTF-8”)快捷方法,在它的底层,会同时做上面两件事,所以可以一行代码解决response产生的乱码问题。
答案:
ServletContext对象代表当前web应用。当服务器启动时,服务器在启动时会依次加载web应用,每一个web应用加载完成后都会创建一个ServletContext对象唯一代表该web应用,这个对象一直存活,直到web应用移除出容器或服务器关闭时,随着应用销毁,ServletContext对象跟着销毁。
答案:
转发是服务器内部资源跳转,重定向是通过302+Location实现浏览器跳转访问。
转发一次请求一次响应,重定向两次请求两次响应。
转发地址栏不发生变化,重定向地址栏会发生变化。
转发之前和转发之后request是一个,重定向之前和之后不是一个request。
答案:
当程序第一次调用到request.getSession()代码时,服务器明确的知道了需要用到session了,此时创建session。
如果session超过30分钟(可以在web.xml中配置的)没人使用,服务器认为这个session超时了,销毁session。
明确的调用session.invalidate(),session立即销毁。
服务器被非正常关闭或web应用被移除出容器,此时随着web应用的销毁session销毁.如果是正常关闭,session会被钝化.当下次服务器正常启动时,没有超时的session还会被活化回来。
答案:
session的原理:在服务器第一次调用request.getSession()方法的时候,会在内存中创建一个session对象,此对象具有一个独一无二的id值,此id值将会以cookie(JSESSIONID)的形式发送给浏览器,浏览器以后每次访问都会带着此cookie,服务器就利用此cookie区分浏览器找到对应的session空间。
答案:
cookie数据存放在客户的浏览器上,session数据放在服务器上
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE
答案:
其实这个问题在上面已经阐述过了,Servlet是一个特殊的Java程序,它运行于服务器的JVM中,能够依靠服务器的支持向浏览器提供显示内容。JSP本质上是Servlet的一种简易形式,JSP会被服务器处理成一个类似于Servlet的Java程序,可以简化页面内容的生成。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。有人说,Servlet就是在Java中写HTML,而JSP就是在HTML中写Java代码,当然这个说法是很片面且不够准确的。JSP侧重于视图,Servlet更侧重于控制逻辑。
答案:
1:request: 请求对象 在javax.servlet.ServletRequest 作用域为Request来自客服端的请求,如:FORM表单中填写的信息,常用的方法有getParameter,getParamterName 和getParamterValue通过表用获取请求对象中包含的参数值。
2:response表示客服端的响应。
3:pageContext对象为页面的上下文对象,代表当请运行页面的一些属性。
4:session:对象代码服务器与客服端所建立的会话,比如在写购物,客服轨迹跟踪,
session”是建立在cookie的基础之上的。常用方法有getId,getValues等。
5:application对象负责提供应用程序在服务端运行时的一些全局信息,方法有getMimeType等。
6:out:与response不同,通过out对象发送的内容是浏览器需要的显示内容,还可以直接想客服端编写一个有程序动态生成的HTML的文件。
7:page:page里的变量没法从index.jsp传递到test.jsp。只要页面跳转了,就不见了。
8: exception:他是一个列外的对象,当页面发生了列外,就会会创建该对象。
9:config:是在servlet初始化Servlet的时候,JSP引擎向他传递信息用的,此消息包括Servlet初始化时所需要的参数。
答案:
SQL注入:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
防止的方法:
(1) 永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等。
(2) 永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
(3) 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
(4) 不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
(5) 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。
答案:
(1)查询时,能不用* 就不用,尽量写全字段名。
(2)索引不是越多越好,每个表控制在6个索引以内。范围where条件的情况下,索引不起作用,比如where value<100
(3)大部分情况连接效率远大于子查询,但是有例外。当你对连接查询的效率都感到不能接受的时候可以试试用子查询,虽然大部分情况下你会更失望,但总有碰到惊喜的时候不是么…
(4)多用explain 和 profile分析查询语句
(5)有时候可以1条大的SQL可以分成几个小SQL顺序执行,分了吧,速度会快很多。
(6)每隔一段时间用alter table table_name engine=innodb;优化表
(7)连接时注意:小表 jion 大表的原则
(8)学会用explain 和 profile判断是什么原因使你的SQL慢
(9)查看慢查询日志,找出执行时间长的SQL进行优化
(10)尽量避免使用order by
(11)因为where子句后面的条件是执行顺序是从右到左,所以尽量把能过滤掉大部分数据的条件放在最后
答案:
init为初始化方法,在Filter对象被创建出来时,Servlet容器会调用该方法对filter进行初始化。
destory为销毁的方法,在过滤器对象被销毁之前,服务器会调用这个方法执行善后工作。
doFilter为过滤器中最核心的方法,对访问的请求和响应进行拦截,当过滤器拦截到对资源的访问时,服务器会自动调用该方法执行过滤代码。 我们只需要在这个方法中设计过滤器的逻辑代码即可。
答案:
当服务器启动,web应用加载后,立即创建出这个web应用中的所有过滤器对象,创建出来后立即调用过滤器的init方法执行初始化操作.从此这些过滤器对象驻留在内存中为后续的拦截进行服务.每当拦截到资源时,都会导致dofilter方法执行.最终直到服务器关闭或web应用移除出容器时,随着web应用的销毁,过滤器对象销毁,销毁之前调用destory方法执行善后工作。
答案:
对于共享资源,有一个很著名的设计模式:资源池(resource pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
答案:
思路如下:
1:利用class实现DataSource接口
2:在class的构造器一次性创建指定的链接将链接保存LinkedList中
3:实现getConnection从LinkedList返回一个链接
4:提供将链接放回方法
Public class MyDataSource inplements DataSource{
Private LinkedList dataSource=new LinkedList<>();
Public MyDataSource(){
For( int a=0;a<1000;a++){
Try{
DriverManager.registerDriver(new SQLServerDriver());
Connection con=DriverManager.getConnection(“jdbc:sqlserver://localhost:1443;DatabaseName=liming”,”root”,”liming”
}catch(Exception e){
}
}
Public Connection getConnetion(){
Final Connection conn=dataSource.removeFirst();
}
Public void releasConnection(Connection conn){
dataSource.add(conn);
}
}
}
答案:
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
答案:
Servlet是一个供其他java程序调用的类,它不能独立运行,针对客户端的多次请求,通常状况下,Servlet只会创建一个Servlet实例对象,一旦创建它就会驻留在内存中,为后续的请求提供服务,直至退出web应用为止,也就是当我们关闭了浏览器之后我们的Servlet就终止了。
当Servlet第一次访问的时候,就被加载到内存中,以后该实例对各个请求服务,没次情况会调用一次service方法。
这样会出现什么问题:因为Servlet是单例的,所以会出现线程安全问题
答案:
如果说str是null,那么内存根本没创建字符串对像,并由str引用。不能调用object的方法。
如果说str是空串,那么确实存在一个由str引用的字符串对像,只不过这个字符串的值是""。长度为0;
在获取请求参数的时候为什么要这样判断呢?
if(null==str || “”.equals(str)){
return “不合法参数”;
}
如果我们在表单中什么都不填 接收到的字符串就是null;
如果我们在表单中填“”,接受到的字符串是“”,但是存入数据库后,查询出来的就是null;
答案:
Servlet本身是单实例的,这样当有多个用户同时访问某个Servlet时,会访问该唯一的Servlet实例中的成员变量,如果对成员变量进行写入操作,那就会导致Servlet的多线程问题,即数据不一致。
1.解决Servlet多线程同步问题的最好方式:去除实例变量,使用局部变量。
不使用成员变量,而使用局部变量,因为局部变量在每个线程中都有各自的实例。
所以对Servlet来说,如果要对某个变量做写入操作,一定不要使用成员变量,而要使用局部变量。
2.使用同步代码块
synchronized{}
3.Servlet实现javax.serlvet.SingleThreadModel,Servlet2.4中已经废弃了该接口,此时Servlet容器将保证Servlet实例以单线程方式运行,也就是说,同一时刻,只会有一个线程执行Servlet的service()方法。
答案:
a、request.getParameter()获取的类型是String;
request.getAttribute()获取的类型是Object
b、request.getPrameter()获取的是POST/GET传递的参数值和URL中的参数;
request.getAttribute()获取的是对象容器中的数据值/对象
c、request.setAttribute()和request.getAttribute()可以发送、接收对象;
request.getParamter()只能接收字符串,官方不开放request.setParamter()(也就是没有这个方法)
setAttribute()和getAttribute()的传参原理:
setAttribute()是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另外一个页面时,
应用服务器会把这块内存拷贝到另一个页面所对应的那块内存中。这个就可以通过getAttribute()获取到相应的参数值或者对象。
答案:
a、静态include:语法:<%@ include file=“文件名” %>,相当于复制,编辑时将对应的文件包含进来,当内容变化时,不会再一次对其编译,不易维护。
b、动态include:语法:
答案:
基于java的web应用系统采用MVC设计模型,即用Model(模型)、View(视图)和Controller(控制)分离设计,这是目前web应用服务系统的主流设置方向。
Model:处理业务逻辑的模块。
View:负责页面显示,显示Model的处理结果给用户,主要实现数据到页面的转换过程。
Controller:负责每个请求的分发,把Form数据传递给Model进行处理,处理完成后,把处理结果返回给相应的View显示给用户。
答案:
功能:
a、从四个域对象中取出数据数据显示。
b、取出请求参数数据显示。
原因:
在页面中用jsp脚本和jsp表达式来获取数据显示比较麻烦
a、需要判断
b、可能需要强转
答案:
使用session技术:
a、在regist.jsp页面中生成一个为一个随机值,将其保存到session中,同时将其保存为表单的隐藏域的值。
b、在处理注册的请求时,获取session中的值,获取请求参数的值,比较两者是否相同,如果相同说明不是重复提交,请求通过同时删除session中保存的的值,如果不相同则是重复提交,不能通过。
答案:
给处于其中的应用程序组件(JSP、Servlet)提供一个环境,是JSP、Servlet直接跟容器中的变量交互,不必关注其他系统问题。
主要有web服务器来实现。例如:tomcat、weblogic、sphere、JBoss等。该容器提供的接口严格遵守J2EE规范中的web application标准。
我们把遵守以上标准的web服务器叫做J2EE的web容器。
答案:
Java中一共有23中设计模式:
Factory(工厂模式)、Builder(建造模式)、Factory Method(工厂方法模式)、ProtoType(原始模型模式)、Singleton(单例模式)、
Facade(门面模式)、Adapter(适配器模式)、Bridge(桥梁模式)、Composite(合成模式)、Decorator(装饰模式)、
FlyWeight(享元模式)、Proxy(代理模式)、Command(命令模式)、Interpreter(解释器模式)、Visitor(访问者模式)、
Iterator(迭代子模式)、Mediator(调停者模式)、Memento(备忘录模式)、Observer(观察者模式)、State(状态模式)、
Strategy(策略模式)、Template Method(模板方法模式)、Chain Of Responsibility(责任链模式)、
工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某个类的实例,通常一组类中有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。
答案:
事务是作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为ACID(原子性、一致性、隔离性和持久性)属性,
只有这样才能成为一个事务:
原子性:事务必须是原子工作单元,对于其数据修改,要么全都执行,要么全都不执行。
一致性:事务在完成时,必须使所有的数据保持一致的状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如B树索引或双向链表)都必须是正确的。
隔离性:由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前
的状态,要么是另一并发事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播
一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
持久性:事务完成后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
答案:
1、Serializable (串行化):可避免脏读、不可重复读、幻读的发生
2、Repeatable read (可重复读):可避免脏读、不可重复读的发生。
3、Read committed (读已提交):可避免脏读的发生。
4、Read uncommitted (读未提交):最低级别,任何情况都无法保证
答案:
属于部署描述符,在整个JAVA中只要是容器都会存在部署描述符,此部署描述符可以控制整个WEB中各个组件的运行状态,也可以配置整个窗口的状态
答案:
三范式:
第一范式(确保每列保持原子性)最基本范式。数据库表中所有字段值都是不可分解的原子值,就满足了第一范式。
第二范式(确保表中的每列都和主键相关)在第一范式上更近一层。确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关,也就是说一个表中只能保存一种数据,不可以吧多种数据保存在一张表中。
第三范式:确保每列都和主键列直接相关,不是间接相关。
索引:
避免对索引字段进行计算、避免索引在字段上使用not、<>、!=、避免在索引上使用IS NULL和NOT NULL、避免在索引列上出现数据类型转换、避免索引字段使用函数、避免建立索引的列出现空值
答案:
Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
Ajax其核心只有JavaScript、XMLHTTPRequest和DOM,在旧的交互方式中,由用户触发一个HTTP请求到服务器,服务器对其进行处理后再返回一个新的HTHL页到客户端, 每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从服务器端得到很简单的一个数据,都要返回一个完整的HTML页,而用户每次都要浪费时间和带宽去重新读取整个页面。而使用Ajax后用户从感觉上几乎所有的操作都会很快响应没有页面重载(白屏)的等待。
答案:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-In59QCqN-1615101859311)(file:///C:\Users\ASUS\AppData\Local\Temp\ksohtml8876\wps9.jpg)]
答案:
SQL注入是一种将SQL代码添加到输入参数中,传递到服务器解析并执行的一种攻击手法。
SQL注入攻击是输入参数未经过滤,然后直接拼接到SQL语句当中解析,执行达到预想之外的一种行为,称之为SQL注入攻击。
答案:
利用新对象PreparedStatement对象完成,先将SQL骨架发送给数据库服务器,然后再将参数单独发给服务器,并将参数中的关键字当做一个普通字符串来处理,进而起到防止SQL注入的问题
答案:
用来提高程序的效率,创建一个容器,容器中存放已经获取到了的数据库连接对象,对外提供获取连接和还回连接的方法,外界需要时就从容器中获取,用完就还回容器中。
答案:
XML是可扩展标记语言,而HTML超文本标记语言。不同之处:
1、语法有所不同。XML语法比较严谨而HTML语法比较松散。
2、用途不同。XML主要用于数据格式化存储而HTML主要用于网页的编辑。
答案:
简单来说: == 代表相同, ===代表严格相同, 为啥这么说呢,
这么理解: 当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行=比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较, 而=比较时, 如果类型不同,直接就是false.
答案:
\1. SELECT子句中避免使用‘*’
\2. SQL语句用大写的
\3. 用IN来替换OR
\4. 查询语句中不要使用 *
\5. 尽量减少子查询,使用关联查询(left join,right join,inner join)替代
\6. 减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
\7. or 的查询尽量用 union或者union all 代替
\8. 合理的增加冗余的字段(减少表的联接查询)
\9. 增加中间表进行优化(这个主要是在统计报表的场景,
答案:
内存优化:Tomcat依赖于JVM,可以配置JVM的内存配置
最大连接数配置(并发能力)
通常搭配Nginx提升Tomcat的并发性能
答案:
自动刷新不仅可以实现一段时间之后自动跳转到另一个页面,还可以实现一段时间之后自动刷新本页面。Servlet中通过HttpServletResponse对象设置Header属性实现自动刷新例如:
Response.setHeader(“Refresh”,“1000;URL=http://localhost:8080/servlet/example.htm”);
其中1000为时间,单位为毫秒。URL指定就是要跳转的页面(如果设置自己的路径,就会实现没过一秒自动刷新本页面一次)
答案:
\1. C/S用户固定,并且处于相同区域,要求拥有相同的操作系统。B/S要有操作系统和浏览器就行。与操作系统平台无关。
\2. C/S客户端的计算机电脑配置要求较高。B/S客户端的计算机电脑配置要求较低。
\3. C/S每一个客户端都必须安装和配置软件,客户端不必安装,使用浏览器访问,易推广。B/S最大的优点就是可以在任何地方进行操作而不用安装任何专门的软件。
\4. C/S每一个客户端都要升级程序。可以采用自动升级。BS客户端不必安装及维护。
\5. C/S一般面向相对固定的用户群,程序更加注重流程,它可以对权限进行多层次校验,提供了更安全的存取模式,对信息安全的控制能力很强。一般高度机密的信息系统采用C/S结构适宜。
事务的特性:ACID
A - 原子性 Atomic
数据操作的最小单元是事务,而不是SQL语句
C - 一致性 Consistency
转账前 a+b = 100
转帐后 a+b = 100
I - 隔离性 Isolation
一个事物进行中时,另一事物不能操作数据
D - 持久性 Durancy
事务没有提交之前,数据操作只保存在日志文件中
提交事务之后,数据持久生效
答案:
HTML(Hypertext Markup Language)文本标记语言,它是静态页面,和JavaScript一样解释性语言,为什么说是解释性语言呢?因为,只要你有一个浏览器那么它就可以正常显示出来,而不需要指定的编译工具,只需在TXT文档中写上HTML标记就OK。
JSP(Java Server Page)看这个意思就知道是Java服务端的页面,所以它是动态的,它是需要经过JDK编译后把内容发给客户端去显示,我们都知道,Java文件编译后会产生一个class文件,最终执行的就是这个class文件,JSP也一样,它也要编译成class文件!JSP不止要编译,它还得要转译,首先把JSP转译成一个Servlet文件,然后在编译成class文件。当用户访问JSP时就执行了class文件,最 终…
1.最简单的区别就是,HTML能直接打开,jsp只能发布到Tomact等服务器上才能打开
2.定义上HTML页面是静态页面可以直接运行,JSP页面是动态页它运行时需要转换成servlet
3.他们的表头不同,这个是JSP的头“ <%@ page language=“java” import=“java.util.*” pageEncoding=“gbk”%>”在表头中有编码格式和导入包等
4.也是很好区分的在jsp中用<%%>就可以写Java代码了,而html没有<%%>
答案:
不同: Html是静态,servlet是动态 html页面由服务器直接返回, servlet是用来处理客户请求,并返回html页面 ,Servlet需要服务器调用servlet方法生成动态html页面,且需要在web.xml中配置url路径
答案:
1、Request是客户端向服务端发送请求
2、Response是服务端对客户端请求做出响应
3、Session在servlet中不能直接使用,需要通过getSession()创建,如果没有设定它的生命周期,或者通过invildate()方法销毁,关闭浏览器session就会消失
4、Application不能直接创建,存在于服务器的内存中,由服务器创建和销毁
答案:
1、Request可以通过getAttribute()方法直接取值,也可通过getParameter()取值
2、Session需要通过request.getSession().getAttribute()才能取值
3、Request是针对一次请求,Session是针对整个会话
4、在页面通过contentType,pageEncoding,content设置编码格式,必须要一致
答案:
动态导入
是行为元素、是在请求处理阶段引入的,引入执行页面或servlet所生成的应答文本
先编译,后包含,就是将每个jsp页面都单独转化成html页面,最后再将所有的html页面相加,如果有相同变量不会冲突
<%@ include file="" %> 静态导入
是指令元素,是编译时包含,引入静态文本(html,jsp),在JSP页面被转化成servlet之前和它融和到一起。先包含,后编译
答案:
Spring:轻量级框架
作用:Bean工厂,用来管理Bean的生命周期和框架集成。
两大核心:
1、IOC/DI(控制反转/依赖注入) :把dao依赖注入到service层,service层反转给action层,Spring顶层容器为BeanFactory。
2、AOP:面向切面编程
答案:
开启事务注解驱动
事务管理器
开启注解功能,并配置扫描包
配置数据库
配置SQL会话工厂,别名,映射文件
不用编写Dao层的实现类
答案:
工厂模式:每个Bean的创建通过方法
单例模式:默认的每个Bean的作用域都是单例
代理模式:关于Aop的实现通过代理模式
答案:
入口不同:
Struts2:filter过滤器
SpringMvc:一个Servlet即前端控制器
开发方式不同:
Struts2:基于类开发,传递参数通过类的属性,只能设置为多例
SpringMvc:基于方法开发(一个url对应一个方法),请求参数传递到方法形参,可以为单例也可以为多例(建议单例)
请求方式不同:
Struts2:值栈村塾请求和响应的数据,通过OGNL存取数据
SpringMvc:通过参数解析器将request请求内容解析,给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面,jsp视图解析器默认使用的是jstl。
答案:
把Sql语句从Java中独立出来。
封装了底层的JDBC,API的调用,并且能够将结果集自动转换成JavaBean对象,简化了Java数据库编程的重复工作。
自己编写Sql语句,更加的灵活。
入参无需用对象封装(或者map封装),使用@Param注解
1、快照(snapshots)
缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你可以手工调用命令SAVE或BGSAVE。
工作原理
. Redis forks.
. 子进程开始将数据写到临时RDB文件中。
. 当子进程完成写RDB文件,用新文件替换老文件。
. 这种方式可以使Redis使用copy-on-write技术。
2、AOF
快照模式并不十分健壮,当系统停止,或者无意中Redis被kill掉,最后写入Redis的数据就会丢失。这对某些应用也许不是大问题,但对于要求高可靠性的应用来说,
Redis就不是一个合适的选择。
Append-only文件模式是另一种选择。
你可以在配置文件中打开AOF模式
3、虚拟内存方式
当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.
当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.
vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.
自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库
mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据
相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。
如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。
使用keys指令可以扫出指定模式的key列表。
对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。
bgsave做镜像全量持久化,aof做增量持久化。因为bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。在redis实例重启时,会使用bgsave持久化文件重新构建内存,再使用aof重放近期的操作指令来实现完整恢复重启之前的状态。
对方追问那如果突然机器掉电会怎样?取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。
对方追问bgsave的原理是什么?你给出两个词汇就可以了,fork和cow。fork是指redis通过创建子进程来进行bgsave操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
完全基于内存,绝大部分请求是纯粹的内存操作,非常快速
数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
使用多路I/O复用模型,非阻塞IO