英特尔第四代酷睿系列i7桌面处理器是基于22纳米工艺技术的64位多核处理器。英特尔第四代酷睿系列i7处理器设计用于由处理器和平台控制器中枢(PCH)组成的双芯片平台。该处理器设计用于与英特尔8系列芯片组配套使用。该款处理器配有英特尔HD Graphics4600,还包括虚拟化技术、新Haswell指令集、新型防盗和身份保护技术。
英特尔第四代i5处理器
英特尔第四代酷睿系列i5桌面处理器包括基于22纳米工艺技术的64位多核处理器。英特尔第四代酷睿系列i5处理器设计用于由处理器和平台控制器中枢(PCH)组成的双芯片平台。该处理器设计用于与英特尔8系列芯片组配套使用。该款处理器配有英特尔HD Graphics4600,还包括虚拟化技术、新Haswell指令集、新型防盗和身份保护技术。
英特尔第四代i3处理器
英特尔第四代酷睿系列i3桌面处理器包括基于22纳米工艺技术的64位多核处理器。英特尔第四代酷睿系列i3处理器设计用于由处理器和平台控制器中枢(PCH)组成的双芯片平台。该处理器设计用于与英特尔8系列芯片组配套使用。该款处理器配有英特尔HD Graphics4600,还包括虚拟化技术、新Haswell指令集、新型防盗和身份保护技术。
http://www.mouser.cn/search/refine.aspx?Ntk=P_MarCom&Ntt=183338403
2电脑内存常见名词术语解释
BUS(总线):计算机中各单元间传送数据的通道。通常情况下,内部总线是指计算机各组件和CPU之间的数据通道。总线的“宽度”通常以位来计算,该参数决定了能够同时传送的数据量。与CPU相似,总线的性能取决于其时钟速度。66MHz总线的数据传输速度要比33MHz的总线快很多。 Cache(内存缓存,CPU缓存):缓存能够在高速静态RAM中存储经常使用的数据,从 而大大加快了数据传输速度。因此,当CPU访问此类数据时,访问速度将比从常规内存读取快很多。 RAM(随机存取内存):内存芯片中的工作内存部分,用于供计算机处理器快速存取。RAM中的数据只能在计算机启动过程中保留。RAM存取速度要比磁盘驱动的存取快很多,因为除了电路传输外不涉及任何的机械问题。对于常规计算,最好使用至少128MB的RAM,在图形工作环境中,至少需要256MB的RAM。 DRAM(动态RAM ):最普通的RAM、DRAM将每个内存位作为一个电荷保存在存储单元中,必须几微秒刷新一次以保证数据不丢失。 SDRAM(同步DRAM):DRAM的替代品。SDRAM将内存存取与CPU时钟同步,加快了数据传输速度。SDRAM还允许在存取某一内存模块时让另一个模块作存取准备,这同样加快了数据传输速度。与DRAM不同,SDRAM使用电流而非存储电荷,因此无需持续刷新。 DDR SDRAM(双数据频率SDRAM):DDR SDRAM与SDRAM相似,但是它在系统时钟上升和下降沿处传输数据,这样从理论上能够将SDRAM的速度加快一倍。 DRDRAM(Direct Rambus DRAM,以前的RDRAM):是Rambus开发的一种SDRAM,DRDRAM用于高端Intel CPU。与DDR SDRAM类似,它也在时钟周期的上升和下降沿传输数据,即也使用双数据通道加快传输速率。在P4系统中,DRDRAM通常称为PC800,将P4的400MHz总线速度加快了一倍。DRDRAM要比DDR SDRAM昂贵很多。 SGRAM(同步图形RAM):与SDRAM不同,SGRAM利用块写入和伪装写入功能加快了视频处理速度。SGRAM是单端口的,因此当SGRAM刷新图形时CPU无法对其进行写入。SGRAM应用于高端图形卡,特别是应用于Matrox Graphics。 DIMM(双嵌入内存模块):此内存芯片模块使用168针连接到PC主板。DIMM支持64位数据传输,而SIMM只支持32位。(Direct Rambus RAM使用名为RIMM的专用模块来实现和DIMM相同的功能。) |
BANK:BANK是指内存插槽的计算单位(也有人称为记忆库),它是计算机系统与内存间资料汇流的基本运作单位。
内存的速度:内存的速度是以每笔CPU与内存间数据处理耗费的时间来计算,为总线循环(bus cycle)以奈秒(ns)为单位。
内存模块 (Memory Module):提到内存模块是指一个印刷电路板表面上有镶嵌数个记忆体芯片chips,而这内存芯片通常是DRAM芯片,但近来系统设计也有使用快取隐藏式芯片镶嵌在内存模块上内存模块是安装在PC 的主机板上的专用插槽(Slot)上镶嵌在Module上DRAM芯片(chips)的数量和个别芯片(chips)的容量,是决定内存模块的设计的主要因素。
SIMM (Single In-line Memory Module):电路板上面焊有数目不等的记忆IC,可分为以下2种型态:
72PIN:72脚位的单面内存模块是用来支持32位的数据处理量。
30PIN:30脚位的单面内存模块是用来支持8位的数据处理量。
DIMM (Dual In-line Memory Module):(168PIN) 用来支持64位或是更宽的总线,而且只用3.3伏特的电压,通常用在64位的桌上型计算机或是服务器。
RIMM:RIMM模块是下一世代的内存模块主要规格之一,它是Intel公司于1999年推出芯片组所支持的内存模块,其频宽高达1.6Gbyte/sec。
SO-DIMM (Small Outline Dual In-line Memory Module) (144PIN): 这是一种改良型的DIMM模块,比一般的DIMM模块来得小,应用于笔记型计算机、列表机、传真机或是各种终端机等。
PLL: 为锁相回路,用来统一整合时脉讯号,使内存能正确的存取资料。
Rambus 内存模块 (184PIN): 采用Direct RDRAM的内存模块,称之为RIMM模块,该模块有184pin脚,资料的输出方式为串行,与现行使用的DIMM模块168pin,并列输出的架构有很大的差异。
6层板和4层板(6layers V.S. 4 layers): 指的是电路印刷板PCB Printed Circuit Board用6层或4层的玻璃纤维做成,通常SDRAM会使用6层板,虽然会增加PCB的成本但却可免除噪声的干扰,而4层板虽可降低PCB的成本但效能较差。
Register:是缓存器的意思,其功能是能够在高速下达到同步的目的。
SPD:为Serial Presence Detect 的缩写,它是烧录在EEPROM内的码,以往开机时BIOS必须侦测memory,但有了SPD就不必再去作侦测的动作,而由BIOS直接读取 SPD取得内存的相关资料。
Parity和ECC的比较:同位检查码(parity check codes)被广泛地使用在侦错码(error detection codes)上,他们增加一个检查位给每个资料的字元(或字节),并且能够侦测到一个字符中所有奇(偶)同位的错误,但Parity有一个缺点,当计算机查到某个Byte有错误时,并不能确定错误在哪一个位,也就无法修正错误。
缓冲器和无缓冲器(Buffer V.S. Unbuffer):有缓冲器的DIMM 是用来改善时序(timing)问题的一种方法无缓冲器的DIMM虽然可被设计用于系统上,但它只能支援四条DIMM。若将无缓冲器的DIMM用于速度为100Mhz的主机板上的话,将会有存取不良的影响。而有缓冲器的DIMM则可使用四条以上的内存,但是若使用的缓冲器速度不够快的话会影响其执行效果。换言之,有缓冲器的DIMM虽有速度变慢之虞,但它可以支持更多DIMM的使用。
自我充电 (Self-Refresh):DRAM内部具有独立且内建的充电电路于一定时间内做自我充电, 通常用在笔记型计算机或可携式计算机等的省电需求高的计算机。
预充电时间 (CAS Latency):通常简称CL。例如CL=3,表示计算机系统自主存储器读取第一笔资料时,所需的准备时间为3个外部时脉(System clock)。CL2与CL3的差异仅在第一次读取资料所需准备时间,相差一个时脉,对整个系统的效能并无显著影响。
时钟信号 (Clock):时钟信号是提供给同步内存做讯号同步之用,同步记忆体的存取动作必需与时钟信号同步。
电子工程设计发展联合会议 (JEDEC):JEDEC大部分是由从事设计、发明的制造业尤以有关计算机记忆模块所组成的一个团体财团,一般工业所生产的记忆体产品大多以JEDEC所制定的标准为评量。
只读存储器ROM (Read Only Memory):ROM是一种只能读取而不能写入资料之记燱体,因为这个特所以最常见的就是主机板上的 BIOS (基本输入/输出系统BasicInput/Output System)因为BISO是计算机开机必备的基本硬件设定用来与外围做为低阶通信接口,所以BISO之程式烧录于ROM中以避免随意被清除资料。
EEPROM (Electrically Erasable Programmable ROM):为一种将资料写入后即使在电源关闭的情况下,也可以保留一段相当长的时间,且写入资料时不需要另外提高电压,只要写入某一些句柄,就可以把资料写入内存中了。
EPROM (Erasable Programmable ROM):为一种可以透过紫外线的照射将其内部的资料清除掉之后,再用烧录器之类的设备将资料烧录进 EPROM内,优点为可以重复的烧录资料。
程序规画的只读存储器 (PROM):是一种可存程序的内存,因为只能写一次资料,所以它一旦被写入资料若有错误,是无法改变的且无法再存其它资料,所以只要写错资料这颗内存就无法回收重新使用。
MASK ROM:是制造商为了要大量生产,事先制作一颗有原始数据的ROM或EPROM当作样本,然后再大量生产与样本一样的 ROM,这一种做为大量生产的ROM样本就是MASK ROM,而烧录在MASK ROM中的资料永远无法做修改。
随机存取内存RAM ( Random Access Memory):RAM是可被读取和写入的内存,我们在写资料到RAM记忆体时也同时可从RAM读取资料,这和ROM内存有所不同。但是RAM必须由稳定流畅的电力来保持它本身的稳定性,所以一旦把电源关闭则原先在RAM里头的资料将随之消失。
动态随机存取内存 DRAM (Dynamic Random AccessMemory):DRAM 是Dynamic Random Access Memory 的缩写,通常是计算机内的主存储器,它是而用电容来做储存动作,但因电容本身有漏电问题,所以内存内的资料须持续地存取不然资料会不见。
FPM DRAM (Fast Page Mode DRAM):是改良的DRAM,大多数为72IPN或30PIN的模块,FPM 将记忆体内部隔成许多页数Pages,从512 bite 到数 Kilobytes 不等,它特色是不需等到重新读取时,就可读取各page内的资料。
EDO DRAM (Extended Data Out DRAM):EDO的存取速度比传统DRAM快10%左右,比FPM快12到30倍一般为72PIN、168PIN的模块。
SDRAM:Synchronous DRAM 是一种新的DRAM架构的技术;它运用晶片内的clock使输入及输出能同步进行。所谓clock同步是指记忆体时脉与CPU的时脉能同步存取资料。SDRAM节省执行指令及数据传输的时间,故可提升计算机效率。
DDR:DDR 是一种更高速的同步内存,DDR SDRAM为168PIN的DIMM模块,它比SDRAM的传输速率更快, DDR的设计是应用在服务器、工作站及数据传输等较高速需求之系统。
DDRII (Double Data Rate Synchronous DRAM):DDRII是DDR原有的SLDRAM联盟于1999年解散后将既有的研发成果与DDR整合之后的未来新标准。DDRII的详细规格目前尚未确定。
DRDRAM (Direct Rambus DRAM):是下一代的主流内存标准之一,由Rambus 公司所设计发展出来,是将所有的接脚都连结到一个共同的Bus,这样不但可以减少控制器的体积,已可以增加资料传送的效率。
RDRAM (Rambus DRAM):是由Rambus公司独立设计完成,它的速度约一般DRAM的10倍以上,虽有这样强的效能,但使用后内存控制器需要相当大的改变,所以目前这一类的内存大多使用在游戏机器或者专业的图形加速适配卡上。
VRAM (Video RAM):与DRAM最大的不同在于其有两组输出及输入口,所以可以同时一边读入,一边输出资料。
WRAM (Window RAM):属于VRAM的改良版,其不同之处在于其控制线路有一、二十组的输入/输出控制器,并采用EDO的资料存取模式。
MDRAM (Multi-Bank RAM):MIDRAM 的内部分成数个各别不同的小储存库 (BANK),也就是数个属立的小单位矩阵所构成。每个储存库之间以高于外部的资料速度相互连接,其应用于高速显示卡或加速卡中。
静态随机处理内存 SRAM (Static Random AccessMemory):SRAM 是Static Random Access Memory 的缩写,通常比一般的动态随机处理内存处理速度更快更稳定。所谓静态的意义是指内存资料可以常驻而不须随时存取。因为此种特性,静态随机处理内存通常被用来做高速缓存。
Async SRAM:为异步SRAM这是一种较为旧型的SRAM,通常被用于电脑上的 Level 2 Cache上,它在运作时独立于计算机的系统时脉外。
Sync SRAM:为同步SRAM,它的工作时脉与系统是同步的。
SGRAM (Synchronous Graphics RAM):是由SDRAM再改良而成以区块Block为单位,个别地取回或修改存取的资料,减少内存整体读写的次数增加绘图控制器。
高速缓存 (Cache Ram):为一种高速度的内存是被设计用来处理运作CPU。快取记忆体是利用 SRAM 的颗粒来做内存。因连接方式不同可分为一是外接方式(External)另一种为内接方式(Internal)。外接方式是将内存放在主机板上也称为Level 1 Cache而内接方式是将内存放在CPU中称为Level2 Cache。
PCMCIA (Personal Computer Memory Card International Association):是一种标准的卡片型扩充接口,多半用于笔记型计算机上或是其它外围产品,其种类可以分为:
Type 1:3.3mm的厚度,常作成SRAM、FlashRAM 的记忆卡以及最近打印机所使用的DRAM记忆卡。
Type 2:5.5mm的厚度,通常设计为笔记计算机所使用的调制解调器接口(Modem)。
Type 3:10.5mm的厚度,被运用为连接硬盘的ATA接口。
Type 4:小型的PCMCIA卡,大部用于数字相机。
FLASH:Flash内存比较像是一种储存装置,因为当电源关掉后储存在Flash内存中的资料并不会流失掉,在写入资料时必须先将原本的资料清除掉,然后才能再写入新的资料,缺点为写入资料的速度太慢。
重新标示过的内存模块(Remark Memory Module):在内存市场许多商家都会贩售重新标示过的内存模块,所谓重新标示过的内存模块就是将芯片Chip上的标示变更过,使其所显示出错误的讯息以提供商家赚取更多的利润。一般说来,业者会标示成较快的速度将( -7改成-6)或将没有厂牌的改为有厂牌的。要避免购买到这方面的产品,最佳的方法就是向好声誉的供货商来购买顶级芯片制造商产品。
内存的充电 (Refresh):主存储器是DRAM组合而成,其电容需不断充电以保持资料的正确。一般有2K与4KRefresh的分类,而2K比4K有较快速的Refresh但2K比4K耗电。
3硬盘接口类型
编辑
硬盘接口是硬盘与主机系统间的连接部件,作用是在硬盘缓存和主机内存之间传输数据。不同的硬盘接口决定着硬盘与计算机之间的连接速度,在整个系统中,硬盘接口的优劣直接影响着程序运行快慢和系统性能好坏。
从整体的角度上,硬盘接口分为IDE、SATA、SCSI、光纤通道和SAS五种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而光纤通道只在高端服务器上,价格昂贵。SATA是种新生的硬盘接口类型,还正处于市场普及阶段,在家用市场中有着广泛的前景。在IDE和SCSI的大类别下,又可以分出多种具体的接口类型,又各自拥有不同的技术规范,具备不同的传输速度,比如ATA100和SATA;Ultra160 SCSI和Ultra320 SCSI都代表着一种具体的硬盘接口,各自的速度差异也较大。
4南北桥总线 BIOS EFI
南北桥是一种芯片结构,南北桥结构是历史悠久而且相当流行的主板芯片组架构。采用南北桥结构的主板上都有两个面积比较大的芯片,靠近CPU的为北桥芯片,主要负责控制AGP显卡、内存与CPU之间的数据交换;靠近PCI槽的为南桥芯片,主要负责软驱、硬盘、键盘以及附加卡的数据交换。传统的南北桥架构是通过PCI总线来连接的,常用的PCI总线是33.3MHz工作频率,32bit传输位宽,所以理论最高数据传输率仅为133MB/s。由于PCI总线的共享性,当子系统及其它周边设备传输速率不断提高以后,主板南北桥之间偏低的数据传输率就逐渐成为影响系统整体性能发挥的瓶颈。因此,从英特尔i810开始,芯片组厂商都开始寻求一种能够提高南北桥连接带宽的解决方案。
EFI,可扩展固件接口英文名Extensible Firmware Interface的缩写,是英特尔,一个主导个人电脑技术研发的公司推出的一种在未来的类PC的电脑系统中替代BIOS的升级方案。同时,EFI也是电子燃料注入(系统)英文名 electronic fuel injection(system) 的缩写,就是利用各种传感器检测发动机的各种状态,经电脑的判断、计算,使发动机在不同工况下,均能获得合适浓度的可燃混合气的一种系统。总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束,按照计算机所传输的信息种类,计算机的总线可以划分为数据总线、地址总线和控制总线,分别用来传输数据、数据地址和控制信号。总线是一种内部结构,它是cpu、内存、输入、输出设备传递信息的公用通道,主机的各个部件通过总线相连接,外部设备通过相应的接口电路再与总线相连接,从而形成了计算机硬件系统。在计算机系统中,各个部件之间传送信息的公共通路叫总线,微型计算机是以总线结构来连接各个功能部件的。BIOS是英文"Basic Input OutputSystem"的缩略语,直译过来后中文名称就是"基本输入输出系统"。其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
5中断:指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断
6进程和线程的区别收藏
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。
7 c string java string:字符串
C语言不支持字符串变量,在C语言程序中使用null终止符代表字符串的结束,在JAVA中字符串是用类对象(String和StringBuffer)来实现的,这些类对象是Java语言的核心,用类对象实现字符串有以下几个优点:
(1)在整个系统中建立字符串和访问字符串元素的方法是一致的;
(2)字符串类是作为Java语言的一部分定义的,而不是作为外加的延伸部分;
(3)JAVA字符串执行运行时检空,可帮助排除一些运行时发生的错误;
(4)可对字符串用“十”进行连接操作。
一直以来对这个问题都不是很清楚:只是知道C语言里有<string.h>这个头文件,所以就想当然的认为C语言里有string这个类型,可以通过下面这种形式来声明string的变量 string aString; 后来编程时发现通不过编译,又查资料才知道原来C语言里压根就没有string这个类型,所以字符串都是通过char数组来存储的,而<string.h>这个头文件里声明的函数原型也全是针对char数组的种种操作。直到C++中才出现了string这个类(注意是类,不是类型)。这是网上我找到的比较满意的答复:
" C语言中有string类型变量吗"
这里的 string 有二义性。
(1)如果 string 是普通词汇,“C语言中有字符类型变量吗”,答,有。字符类型用 char 声明。
char str[]="This is a string";
(2) 如果 string 是专用词汇,“C语言中有string类型变量吗”,答,没有。string 是类,是 class, 不是类型,不是 type.
类的声明用构造函数初始化,或 new 声明。
类 -- C++, 不是 C
C语言提供了丰富的字符串处理函数,大致可分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件"stdio.h";使用其它字符串函数则应包含头文件"string.h"。下面介绍几个最常用的字符串函数。原因是C语言里压根就没有string这个类型,所以字符串都是通过char数组来存储的,而<string.h>这个头文件里声明的函数原型也全是针对char数组的种种操作。直到C++中才出现了string这个类(注意是类,不是类型)。
8 数据结构b树 b+树
这两种处理索引的数据结构的不同之处: 1。B树中同一键值不会出现多次,并且它有可能出现在叶结点,也有可能出现在非叶结点中。而B+树的键一定会出现在叶结点中,并且有可能在非叶结点中也有可能重复出现,以维持B+树的平衡。 2。因为B树键位置不定,且在整个树结构中只出现一次,虽然可以节省存储空间,但使得在插入、删除操作复杂度明显增加。B+树相比来说是一种较好的折中。 3。B树的查询效率与键在树中的位置有关,最大时间复杂度与B+树相同(在叶结点的时候),最小时间复杂度为1(在根结点的时候)。而B+树的时候复杂度对某建成的树是固定的。
9 SE(J2SE),standard edition,标准版,是我们通常用的一个版本,从JDK 5.0开始,改名为JavaSE。
EE(J2EE),enterpriseedition,企业版,使用这种JDK开发J2EE应用程序,从JDK5.0开始,改名为JavaEE。
ME(J2ME),micro edition,主要用于移动设备、嵌入式设备上的java应用程序,从JDK5.0开始,改名为JavaME。
没有JDK的话,无法编译Java程序,如果想只运行Java程序,要确保已安装相应的JRE。
以下是各版本的名称及发布日期:
版本 | 名称 | 发行日期 |
JDK 1.1.4 | Sparkler(宝石) | 1997-09-12 |
JDK 1.1.5 | Pumpkin(南瓜) | 1997-12-13 |
JDK 1.1.6 | Abigail(阿比盖尔–女子名) | 1998-04-24 |
JDK 1.1.7 | Brutus(布鲁图–古罗马政治家和将军) | 1998-09-28 |
JDK 1.1.8 | Chelsea(切尔西–城市名) | 1999-04-08 |
J2SE 1.2 | Playground(运动场) | 1998-12-04 |
J2SE 1.2.1 | none(无) | 1999-03-30 |
J2SE 1.2.2 | Cricket(蟋蟀) | 1999-07-08 |
J2SE 1.3 | Kestrel(美洲红隼) | 2000-05-08 |
J2SE 1.3.1 | Ladybird(瓢虫) | 2001-05-17 |
J2SE 1.4.0 | Merlin(灰背隼) | 2002-02-13 |
J2SE 1.4.1 | grasshopper(蚱蜢) | 2002-09-16 |
J2SE 1.4.2 | Mantis(螳螂) | 2003-06-26 |
Java SE 5.0 (1.5.0) | Tiger(老虎) | 2004-09-30 |
Java SE 6.0 (1.6.0) | Mustang(野马) | 2006-04 |
Java SE 7.0 (1.7.0) | Dolphin(海豚) | 2011-07-28 |
Java SE 8.0 (1.8.0) | 未知 | 2013-09(预定) |
|
|
|
从2006年起,Eclipse基金会每年都会安排同步发布(simultaneousrelease)。至今,同步发布主要在6月进行,并且会在接下来的9月及2月释放出SR1及SR2版本。
版本代号 | 平台版本 | 主要版本发行日期 | SR1发行日期 | SR2发行日期 |
Callisto | 3.2 | 2006年6月26日 | N/A | N/A |
Europa | 3.3 | 2007年6月27日 | 2007年9月28日 | 2008年2月29日 |
Ganymede | 3.4 | 2008年6月25日 | 2008年9月24日 | 2009年2月25日 |
Galileo | 3.5 | 2009年6月24日 | 2009年9月25日 | 2010年2月26日 |
Helios | 3.6 | 2010年6月23日 | 2010年9月24日 | 2011年2月25日 |
Indigo | 3.7 | 2011年6月22日 | 2011年9月23日 | 2012年2月24日 |
Juno | 3.8及4.2 | 2012年6月27日 | 2012年9月28日 | 2013年3月1日 |
Kepler | 4.3 | 2013年6月26日 | 2013年9月27日 | 2014年2月28日 |
Luna | 4.4 | 2014年6月25日 | N/A | N/A |
10 js comjs amd
JavaScript模块编程之写法
2012-10-2913:25 阮一峰阮一峰的网络日志 字号:T | T
JavaScript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。但是,JavaScript不是一种模块化编程语言,它不支持"类"(class),更遑论"模块"(module)了。
随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂。
网页越来越像桌面程序,需要一个团队分工协作、进度管理、单元测试等等......开发者不得不使用软件工程的方法,管理网页的业务逻辑。
JavaScript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。
但是,JavaScript不是一种模块化编程语言,它不支持"类"(class),更遑论"模块"(module)了。(正在制定中的ECMAScript标准第六版,将正式支持"类"和"模块",但还需要很长时间才能投入实用。)
JavaScript社区做了很多努力,在现有的运行环境中,实现"模块"的效果。本文总结了当前"Javascript模块化编程"的最佳实践,说明如何投入实用。虽然这不是初级教程,但是只要稍稍了解Javascript的基本语法,就能看懂。
一、原始写法
模块就是实现特定功能的一组方法。
只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。
1. function m1(){
2. //...
3. }
4. function m2(){
5. //...
6. }
上面的函数m1()和m2(),组成一个模块。使用的时候,直接调用就行了。
这种做法的缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。
二、对象写法
为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面。
1. var module1 = new Object({
2. _count : 0,
3. m1 : function (){
4. //...
5. },
6. m2 : function (){
7. //...
8. }
9. });
上面的函数m1()和m2(),都封装在module1对象里。使用的时候,就是调用这个对象的属性。
1. module1.m1();
但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。
1. module1._count = 5;
三、立即执行函数写法
使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。
1. var module1 = (function(){
2. var _count = 0;
3. var m1 = function(){
4. //...
5. };
6. var m2 = function(){
7. //...
8. };
9. return {
10. m1 : m1,
11. m2 : m2
12. };
13. })();
使用上面的写法,外部代码无法读取内部的_count变量。
1. console.info(module1._count); //undefined
module1就是Javascript模块的基本写法。下面,再对这种写法进行加工。
四、放大模式
如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。
1. var module1 = (function (mod){
2. mod.m3 = function () {
3. //...
4. };
5. return mod;
6. })(module1);
上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块。
五、宽放大模式(Looseaugmentation)
在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。
1. var module1 = ( function (mod){
2. //...
3. return mod;
4. })(window.module1 || {});
与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象。
六、输入全局变量
独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。
为了在模块内部调用全局变量,必须显式地将其他变量输入模块。
1. var module1 = (function ($, YAHOO) {
2. //...
3. })(jQuery, YAHOO);
上面的module1模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module1。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。这方面更多的讨论,参见Ben Cherry的著名文章《JavaScriptModule Pattern: In-Depth》。
这个系列的第二部分,将讨论如何在浏览器环境组织不同的模块、管理模块之间的依赖性。
JS模块化编程之AMD规范
2012-11-0809:45 阮一峰阮一峰的网络日志 字号:T | T
先想一想,为什么模块很重要?因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!
这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块。(接上文)
七、模块的规范
先想一想,为什么模块很重要?
因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。
但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!考虑到Javascript模块现在还没有官方规范,这一点就更重要了。
目前,通行的Javascript模块规范共有两种:CommonJS和AMD。我主要介绍AMD,但是要先从CommonJS讲起。
八、CommonJS
2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。
这标志”Javascript模块化编程”正式诞生。因为老实说,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。
Node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。
1. var math = require('math');
然后,就可以调用模块提供的方法:
1. var math = require('math');
2. math.add(2,3); // 5
因为这个系列主要针对浏览器编程,不涉及node.js,所以对CommonJS就不多做介绍了。我们在这里只要知道,require()用于加载模块就行了。
九、浏览器环境
有了服务器端模块以后,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。
但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。还是上一节的代码,如果在浏览器中运行,会有一个很大的问题,你能看出来吗?
1. var math = require('math');
2. math.add(2, 3);
第二行Math.add(2, 3),在第一行require(‘math’)之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。
这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于”假死”状态。
因此,浏览器端的模块,不能采用”同步加载”(synchronous),只能采用”异步加载”(asynchronous)。这就是AMD规范诞生的背景。
十、AMD
AMD是”Asynchronous ModuleDefinition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:
1. require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:
1. require(['math'], function (math) {
2. math.add(2, 3);
3. });
math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。
目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。本系列的第三部分,将通过介绍require.js,进一步讲解AMD的用法,以及如何将模块化编程投入实战。
11 CEOCOOCFOCTOCIO是什么意思
CEO(Chief executive officer)
首席执行官类似总经理、总裁,是企业的法人
代表。
COO(Chief operating officer)
首席运营官
类似常务总经理
CFO(Chief financial officer)
首席财务官
类似财务总经理
CTO(Chief technology officer)
首席技术官
类似总工程师
CIO(Chief information officer)
首席信息官
主管企业信息的收集和发布
12 深入研究Java类加载机制
类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行。
研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性和适应性。
一、简单过程
Java程序运行的场所是内存,当在命令行下执行:
java HelloWorld
命令的时候,JVM会将HelloWorld.class加载到内存中,并形成一个Class的对象HelloWorld.class。
其中的过程就是类加载过程:
1、寻找jre目录,寻找jvm.dll,并初始化JVM;
2、产生一个Bootstrap Loader(启动类加载器);
3、Bootstrap Loader自动加载ExtendedLoader(标准扩展类加载器),并将其父Loader设为BootstrapLoader。
4、Bootstrap Loader自动加载AppClassLoader(系统类加载器),并将其父Loader设为ExtendedLoader。
5、最后由AppClass Loader加载HelloWorld类。
以上就是类加载的最一般的过程。
二、类加载器各自搜索的目录
为了弄清楚这个问题,首先还要看看System类的API doc文档。
键 | 相关值的描述 |
java.version | Java 运行时环境版本 |
java.vendor | Java 运行时环境供应商 |
java.vendor.url | Java 供应商的 URL |
java.home | Java 安装目录 |
java.vm.specification.version | Java 虚拟机规范版本 |
java.vm.specification.vendor | Java 虚拟机规范供应商 |
java.vm.specification.name | Java 虚拟机规范名称 |
java.vm.version | Java 虚拟机实现版本 |
java.vm.vendor | Java 虚拟机实现供应商 |
java.vm.name | Java 虚拟机实现名称 |
java.specification.version | Java 运行时环境规范版本 |
java.specification.vendor | Java 运行时环境规范供应商 |
java.specification.name | Java 运行时环境规范名称 |
java.class.version | Java 类格式版本号 |
java.class.path | Java 类路径 |
java.library.path | 加载库时搜索的路径列表 |
java.io.tmpdir | 默认的临时文件路径 |
java.compiler | 要使用的 JIT 编译器的名称 |
java.ext.dirs | 一个或多个扩展目录的路径 |
os.name | 操作系统的名称 |
os.arch | 操作系统的架构 |
os.version | 操作系统的版本 |
file.separator | 文件分隔符(在 UNIX 系统中是“/”) |
path.separator | 路径分隔符(在 UNIX 系统中是“:”) |
line.separator | 行分隔符(在 UNIX 系统中是“/n”) |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
可惜这个帮助文档并不全,直接用程序打印出来如下:
for (Map.Entry<Object, Object> entry :System.getProperties().entrySet()) {
System.out.println(entry.getKey()+"\t"+entry.getValue());
}
java.runtime.name | Java(TM) SE Runtime Environment |
sun.boot.library.path | Q:\jdk6\jre\bin |
java.vm.version | 14.0-b16 |
java.vm.vendor | Sun Microsystems Inc. |
java.vendor.url | |
path.separator | ; |
idea.launcher.port | 7532 |
java.vm.name | Java HotSpot(TM) Client VM |
file.encoding.pkg | sun.io |
sun.java.launcher | SUN_STANDARD |
user.country | CN |
sun.os.patch.level | Service Pack 3 |
java.vm.specification.name | Java Virtual Machine Specification |
user.dir | E:\projects\testScanner |
java.runtime.version | 1.6.0_14-b08 |
java.awt.graphicsenv | sun.awt.Win32GraphicsEnvironment |
java.endorsed.dirs | Q:\jdk6\jre\lib\endorsed |
os.arch | x86 |
java.io.tmpdir | C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ |
line.separator | |
java.vm.specification.vendor | Sun Microsystems Inc. |
user.variant | |
os.name | Windows XP |
sun.jnu.encoding | GBK |
java.library.path | Q:\jdk6\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;Q:\jdk6\bin;Q:\JavaFX\javafx-sdk1.2\bin;Q:\JavaFX\javafx-sdk1.2\emulator\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\MySQL Server 5.1\bin;C:\Program Files\StormII\Codec;C:\Program Files\StormII |
java.specification.name | Java Platform API Specification |
java.class.version | 50 |
sun.management.compiler | HotSpot Client Compiler |
os.version | 5.1 |
user.home | d:\我的文档 |
user.timezone | |
java.awt.printerjob | sun.awt.windows.WPrinterJob |
idea.launcher.bin.path | C:\IDEA8\bin |
file.encoding | UTF-8 |
java.specification.version | 1.6 |
java.class.path | Q:\jdk6\jre\lib\alt-rt.jar;Q:\jdk6\jre\lib\charsets.jar;Q:\jdk6\jre\lib\deploy.jar;Q:\jdk6\jre\lib\javaws.jar;Q:\jdk6\jre\lib\jce.jar;Q:\jdk6\jre\lib\jsse.jar;Q:\jdk6\jre\lib\management-agent.jar;Q:\jdk6\jre\lib\plugin.jar;Q:\jdk6\jre\lib\resources.jar;Q:\jdk6\jre\lib\rt.jar;Q:\jdk6\jre\lib\ext\dnsns.jar;Q:\jdk6\jre\lib\ext\localedata.jar;Q:\jdk6\jre\lib\ext\sunjce_provider.jar;Q:\jdk6\jre\lib\ext\sunmscapi.jar;Q:\jdk6\jre\lib\ext\sunpkcs11.jar;E:\projects\testScanner\out\production\testScanner;C:\IDEA8\lib\idea_rt.jar |
user.name | Administrator |
java.vm.specification.version | 1 |
java.home | Q:\jdk6\jre |
sun.arch.data.model | 32 |
user.language | zh |
java.specification.vendor | Sun Microsystems Inc. |
awt.toolkit | sun.awt.windows.WToolkit |
java.vm.info | mixed mode, sharing |
java.version | 1.6.0_14 |
java.ext.dirs | Q:\jdk6\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext |
sun.boot.class.path | Q:\jdk6\jre\lib\resources.jar;Q:\jdk6\jre\lib\rt.jar;Q:\jdk6\jre\lib\sunrsasign.jar;Q:\jdk6\jre\lib\jsse.jar;Q:\jdk6\jre\lib\jce.jar;Q:\jdk6\jre\lib\charsets.jar;Q:\jdk6\jre\classes |
java.vendor | Sun Microsystems Inc. |
file.separator | \ |
java.vendor.url.bug | |
sun.io.unicode.encoding | UnicodeLittle |
sun.cpu.endian | little |
sun.desktop | windows |
sun.cpu.isalist |
1、Bootstrap Loader(启动类加载器):加载System.getProperty("sun.boot.class.path")所指定的路径或jar。
2、Extended Loader(标准扩展类加载器ExtClassLoader):加载System.getProperty("java.ext.dirs")所指定的路径或jar。在使用Java运行程序时,也可以指定其搜索路径,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld
3、AppClass Loader(系统类加载器AppClassLoader):加载System.getProperty("java.class.path")所指定的路径或jar。在使用Java运行程序时,也可以加上-cp来覆盖原有的Classpath设置,例如: java -cp ./lavasoft/classes HelloWorld
ExtClassLoader和AppClassLoader在JVM启动后,会在JVM中保存一份,并且在程序运行中无法改变其搜索路径。如果想在运行时从其他搜索路径加载类,就要产生新的类加载器。
三、类加载器的特点
1、运行一个程序时,总是由AppClass Loader(系统类加载器)开始加载指定的类。
2、在加载类时,每个类加载器会将加载任务上交给其父,如果其父找不到,再由自己去加载。
3、Bootstrap Loader(启动类加载器)是最顶级的类加载器了,其父加载器为null.
四、类加载器的获取
很容易,看下面例子
public class HelloWorld {
public static void main(String[] args) {
HelloWorldhello = new HelloWorld();
Classc = hello.getClass();
ClassLoaderloader = c.getClassLoader();
System.out.println(loader);
System.out.println(loader.getParent());
System.out.println(loader.getParent().getParent());
}
}
打印结果:
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$ExtClassLoader@addbf1
null
Process finished with exit code 0
从上面的结果可以看出,并没有获取到ExtClassLoader的父Loader,原因是Bootstrap Loader(启动类加载器)是用C语言实现的,找不到一个确定的返回父Loader的方式,于是就返回null。
五、类的加载
类加载有三种方式:
1、命令行启动应用时候由JVM初始化加载
2、通过Class.forName()方法动态加载
3、通过ClassLoader.loadClass()方法动态加载
三种方式区别比较大,看个例子就明白了:
public class HelloWorld {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoaderloader = HelloWorld.class.getClassLoader();
System.out.println(loader);
//使用ClassLoader.loadClass()来加载类,不会执行初始化块
loader.loadClass("Test2");
//使用Class.forName()来加载类,默认会执行初始化块
// Class.forName("Test2");
//使用Class.forName()来加载类,并指定ClassLoader,初始化时不执行静态块
// Class.forName("Test2",false, loader);
}
}
public class Test2 {
static {
System.out.println("静态初始化块执行了!");
}
}
分别切换加载方式,会有不同的输出结果。
六、自定义ClassLoader
为了说明问题,先看例子:
package test;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* 自定义ClassLoader
*
* @author leizhimin 2009-7-29 22:05:48
*/
public class MyClassLoader {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException,IllegalAccessException, InstantiationException {
URLurl = new URL("file:/E:\\projects\\testScanner\\out\\production\\testScanner");
ClassLoadermyloader = new URLClassLoader(new URL[]{url});
Classc = myloader.loadClass("test.Test3");
System.out.println("----------");
Test3t3 = (Test3) c.newInstance();
}
}
public class Test3 {
static {
System.out.println("Test3的静态初始化块执行了!");
}
}
运行后:
----------
Test3的静态初始化块执行了!
Process finished with exit code 0
可以看出自定义了ClassLoader myloader = new URLClassLoader(newURL[]{url});已经成功将类Test3加载到内存了,并通过默认构造方法构造了对象Test3 t3 = (Test3) c.newInstance();
有关ClassLoader还有很重要一点:
同一个ClassLoader加载的类文件,只有一个Class实例。但是,如果同一个类文件被不同的ClassLoader载入,则会有两份不同的ClassLoader实例(前提是着两个类加载器不能用相同的父类加载器)。
13Cook和Session
一、cookie机制和session机制的区别
具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session
机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择
二、会话cookie和持久cookie的区别
如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie
一般不保存在硬盘上而是保存在内存里。
如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
三、如何利用实现自动登录
当用户在某个网站注册后,就会收到一个惟一用户ID的cookie。客户后来重新连接时,这个
用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。
四、如何根据用户的爱好定制站点
网站可以使用cookie记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用
户,由服务器端的数据库存储每个标识符对应的页面设置。
五、cookie的发送
1.创建Cookie对象
2.设置最大时效
3.将Cookie放入到HTTP响应报头
如果你创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie:存储在浏览器的内存中,用户退出浏览器之后被删除。如果你希望浏览器将该cookie存
储在磁盘上,则
需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-CookieHTTP请求报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创
建新的报头,因此我们将这个方法称为是addCookie,而非setCookie。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。
六、cookie的读取
1.调用request.getCookie
要获取有浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。
2.对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止
cookie与你的主机(域)相关,而非你的servlet或JSP页面。因而,尽管你的servlet可能只发送了单个cookie,你也可能会得到许多不相关的cookie。
例如:
String cookieName = “userID”;
Cookie cookies[] = request.getCookies();
if (cookies!=null){
for(inti=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
if (cookieName.equals(cookie.getName())){
doSomethingWith(cookie.getValue());
}
}
}
七、如何使用cookie检测初访者
A.调用HttpServletRequest.getCookies()获取Cookie数组
B.在循环中检索指定名字的cookie是否存在以及对应的值是否正确
C.如果是则退出循环并设置区别标识
D.根据区别标识判断用户是否为初访者从而进行不同的操作
八、使用cookie检测初访者的常见错误
不能仅仅因为cookie数组中不存在在特定的数据项就认为用户是个初访者。如果cookie数组为null,客户可能是一个初访者,也可能是由于用户将cookie删除或禁用造成的结果。
但是,如果数组非null,也不过是显示客户曾经到过你的网站或域,并不能说明他们曾经访问过你的servlet。其它servlet、JSP页面以及非JavaWeb应用都可以设置cookie,依据
路径的设置,其中的任何cookie都有可能返回给用户的浏览器。
正确的做法是判断cookie数组是否为空且是否存在指定的Cookie对象且值正确。
九、使用cookie属性的注意问题
属性是从服务器发送到浏览器的报头的一部分;但它们不属于由浏览器返回给服务器的报头。
因此除了名称和值之外,cookie属性只适用于从服务器输出到客户端的cookie;服务器端来自于浏览器的cookie并没有设置这些属性。
因而不要期望通过request.getCookies得到的cookie中可以使用这个属性。这意味着,你不能仅仅通过设置cookie的最大时效,发出它,在随后的输入数组中查找适当的cookie,
读取它的值,修改它并将它存回Cookie,从而实现不断改变的cookie值。
十、如何使用cookie记录各个用户的访问计数
1.获取cookie数组中专门用于统计用户访问次数的cookie的值
2.将值转换成int型
3.将值加1并用原来的名称重新创建一个Cookie对象
4.重新设置最大时效
5.将新的cookie输出
十一、session在不同环境下的不同含义
session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。
然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。
session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。
十二、session的机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
但程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否包含了一个session标识-称为sessionid,如果已经包含一个sessionid则说
明以前已经为此客户创建过session,服务器就按照sessionid把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应
的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。
如果客户请求不包含sessionid,则为此客户创建一个session并且生成一个与此session相关联的sessionid,这个sessionid将在本次响应中返回给客户端保存。
十三、保存sessionid的几种方式
A.保存sessionid的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
B.由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把sessionid传递回服务器,经常采用的一种技术叫做URL重写,就是把sessionid附加在
URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可
能请求的路径后面都包含这个sessionid。
C.另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把sessionid传递回服务器。
十四、session什么时候被创建
一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)这样的语句时才会被创建。
十五、session何时被删除
session在下列情况下被删除:
A.程序调用HttpSession.invalidate()
B.距离上一次收到客户端发送的sessionid时间间隔超过了session的最大有效时间
C.服务器进程被停止
再次注意关闭浏览器只会使存储在客户端浏览器内存中的sessioncookie失效,不会使服务器端的session对象失效。
十六、URL重写有什么缺点
对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL。每个引用你的站点的URL,以及那些返回给用户的URL(即使通过间接手段,比如服务器重定向中的
Location字段)都要添加额外的信息。
这意味着在你的站点上不能有任何静态的HTML页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须使用servlet或JSP动态生成。即使所有的页
面都动态生成,如果用户离开了会话并通过书签或链接再次回来,会话的信息都会丢失,因为存储下来的链接含有错误的标识信息-该URL后面的SESSIONID已经过期了。
十七、使用隐藏的表单域有什么缺点
仅当每个页面都是有表单提交而动态生成时,才能使用这种方法。单击常规的<AHREF..>超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用
于一系列特定的操作中,比如在线商店的结账过程
十八、会话跟踪的基本步骤
1.访问与当前请求相关的会话对象
2.查找与会话相关的信息
3.存储会话信息
4.废弃会话数据
十九、getSession()/getSession(true)、getSession(false)的区别
getSession()/getSession(true):当session存在时返回该session,否则新建一个session并返回该对象
getSession(false):当session存在时返回该session,否则不会新建session,返回null
二十、如何将信息于会话关联起来
setAttribute会替换任何之前设定的值;如果想要在不提供任何代替的情况下移除某个值,则应使用removeAttribute。这个方法会触发所有实现了HttpSessionBindingListener
接口的值的valueUnbound
方法。
二十一、会话属性的类型有什么限制吗
通常会话属性的类型只要是Object就可以了。除了null或基本类型,如int,double,boolean。
如果要使用基本类型的值作为属性,必须将其转换为相应的封装类对象
二十二、如何废弃会话数据
A.只移除自己编写的servlet创建的数据:
调用removeAttribute(“key”)将指定键关联的值废弃
B.删除整个会话(在当前Web应用中):
调用invalidate,将整个会话废弃掉。这样做会丢失该用户的所有会话数据,而非仅仅由我们
servlet或JSP页面创建的会话数据
C.将用户从系统中注销并删除所有属于他(或她)的会话
调用logOut,将客户从Web服务器中注销,同时废弃所有与该用户相关联的会话(每个Web应用至多一个)。这个操作有可能影响到服务器上多个不同的Web应用
二十三、使用isNew来判断用户是否为新旧用户的错误做法
public boolean isNew()方法如果会话尚未和客户程序(浏览器)发生任何联系,则这个方法返回true,这一般是因为会话是新建的,不是由输入的客户请求所引起的。
但如果isNew返回false,只不过是说明他之前曾经访问该Web应用,并不代表他们曾访问过我们的servlet或JSP页面。
因为session是与用户相关的,在用户之前访问的每一个页面都有可能创建了会话。因此isNew为false只能说用户之前访问过该Web应用,session可以是当前页面创建,也可能是
由用户之前访问过的页面创建的。
正确的做法是判断某个session中是否存在某个特定的key且其value是否正确
二十四、Cookie的过期和Session的超时有什么区别
会话的超时由服务器来维护,它不同于Cookie的失效日期。首先,会话一般基于驻留内存的cookie
不是持续性的cookie,因而也就没有截至日期。即使截取到JSESSIONIDcookie,并为它设定一个失效日期发送出去。浏览器会话和服务器会话也会截然不同。
二十五、sessioncookie和session对象的生命周期是一样的吗
当用户关闭了浏览器虽然sessioncookie已经消失,但session对象仍然保存在服务器端
二十六、是否只要关闭浏览器,session就消失了
程序一般都是在用户做logoff的时候发个指令去删除session,然而浏览器从来不会主动在关闭之前通知服务器它将要被关闭,因此服务器根本不会有机会知道浏览器已经关闭。
服务器会一直保留这个会话对象直到它处于非活动状态超过设定的间隔为止。
之所以会有这种错误的认识,是因为大部分session机制都使用会话cookie来保存sessionid,而关闭浏览器后这个sessionid就消失了,再次连接到服务器时也就无法找到原来
的session。
如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求报头,把原来的sessionid发送到服务器,则再次打开浏览器仍然能够找到原来的
session。
恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为session设置了一个失效时间,当距离客户上一次使用session的时间超过了这个失效时间时,服务器就可以认为客
户端已经停止了活动,才会把session删除以节省存储空间。
由此我们可以得出如下结论:
关闭浏览器,只会是浏览器端内存里的sessioncookie消失,但不会使保存在服务器端的session对象消失,同样也不会使已经保存到硬盘上的持久化cookie消失。
二十七、打开两个浏览器窗口访问应用程序会使用同一个session还是不同的session
通常sessioncookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了。
此时我们可以先把sessionid保存在persistentcookie中(通过设置session的最大有效时间),然后在新窗口中读出来,就可以得到上一个窗口的sessionid了,这样通过
session cookie和persistent cookie的结合我们就可以实现了跨窗口的会话跟踪。
二十八、如何使用会话显示每个客户的访问次数
由于客户的访问次数是一个整型的变量,但session的属性类型中不能使用int,double,boolean等基本类型的变量,所以我们要用到这些基本类型的封装类型对象作为session对
象中属性的值
但像Integer是一种不可修改(Immutable)的数据结构:构建后就不能更改。这意味着每个请求都必须创建新的Integer对象,之后使用setAttribute来代替之前存在的老的属性的
值。例如:
HttpSession session = request.getSession();
SomeImmutalbeClass value =(SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
if (value= =null){
value = new SomeImmutableClass(…);//新创建一个不可更改对象
}else{
value = new SomeImmutableClass(calculatedFrom(value)); // 对value重新计算后创建新的对象
}
session.setAttribute(“someIdentifier”,value); // 使用新创建的对象覆盖原来的老的对象
二十九、如何使用会话累计用户的数据
使用可变的数据结构,比如数组、List、Map或含有可写字段的应用程序专有的数据结构。通过这种方式,除非首次分配对象,否则不需要调用setAttribute。例如
HttpSession session = request.getSession();
SomeMutableClass value =(SomeMutableClass)session.getAttribute(“someIdentifier”);
if(value = = null){
value = new SomeMutableClass(…);
session.setAttribute(“someIdentifier”,value);
}else{
value.updateInternalAttribute(…); //如果已经存在该对象则更新其属性而不需重新设置属性
}
三十、不可更改对象和可更改对象在会话数据更新时的不同处理
不可更改对象因为一旦创建之后就不能更改,所以每次要修改会话中属性的值的时候,都需要
调用setAttribute(“someIdentifier”,newValue)来代替原有的属性的值,否则属性的值不会被更新
可更改对象因为其自身一般提供了修改自身属性的方法,所以每次要修改会话中属性的值的时
候,只要调用该可更改对象的相关修改自身属性的方法就可以了。这意味着我们就不需要调
用setAttribute方法
14 find()会在div元素内 寻找class为rain 的元素。
而filter()则是筛选div的class为rain的元素。
一个是对它的子集操作,一个是对自身集合元素筛选。
另外find()其实还可以用选择器表示:
var
15
SpringMVC和Struts2的比较
虽然说没有系统的学习过Spring MVC框架, 但是工作这么长时间, 基本上在WEB层使用的都是SpringMVC, 自己觉得Struts2也是一个不错的WEB层框架, 这两种框架至今自己还未有比较, 今天闲着没事干, 从网上找了一些资料, 再加上平时使用Spring MVC的感触来总结一下。
Spring MVC PK Struts2
我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置。spring3 mvc可以认为已经100%零配置了(除了配置springmvc-servlet.xml外)。 Spring MVC和Struts2的区别:
1. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
2. 性能:spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。
3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。
4. 设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。
5.intercepter的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比springmvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。springmvc是方法级别的拦截,一个方法对应一