设为首页 加入收藏

TOP

在上海的一场Java面试题的答案,包括AJAX, JavaScript, Struts等
2014-11-20 07:45:06 来源: 作者: 【 】 浏览:46
Tags:上海 Java 试题 答案 包括 AJAX JavaScript Struts

1.用js创建一个对象


<script language=”java script”>


Function student()


{


Var name;


Var address;


}


Var stu=new Student();




2.什么是json ,jquery


JSON: (java script Object Notation)是一种轻量级的数据交换格式。


JSON两种结构:


名称/值对的集合,不同的语言中,它被理解为对象,记录,结构,字典,哈希表,有键列表,关联数组。


值的有序列表,数组


jQuery:


jQuery由美国人John Resig创建 是一个优秀的java script框架 使用户能够方便的处理HTML documents events 实现动画效果,并且方便地为网站提供AJAX交互。



3.ajax的工作原理


Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用java script来操作DOM而更新页面。


Ajax处理过程中的第一步是创建一个XMLHttpRequest实例。使用HTTP方法(GET或POST)来处理请求,并将目标URL设置到XMLHttpRequest对象上。


当你发送HTTP请求,你不希望浏览器挂起并等待服务器的响应,取而代之的是,你希望通过页面继续响应用户的界面交互,并在服务器响应真正到达后处理它们。要完成它,你可以向XMLHttpRequest注册一个回调函数,并异步地派发XMLHttpRequest请求。控制权马上就被返回到浏览器,当服务器响应到达时,回调函数将会被调用。


ajax的优点
Ajax的给我们带来的好处大家基本上都深有体会,在这里我只简单的讲几点:
1、最大的一点是页面无刷新,在页面内与服务器通信,给用户的体验非常好。
2、使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力。


3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。


ajax的缺点


下面我着重讲一讲ajax的缺陷,因为平时我们大多注意的都是ajax给我们所带来的好处诸如用户体验的提升。而对ajax所带来的缺陷有所忽视。


下面所阐述的ajax的缺陷都是它先天所产生的。


1、ajax干掉了back按钮,即对浏览器后退机制的破坏。后退按钮是一个标准的web站点的重要功能,但是它没法和js进行很好的合作。这是ajax所带来的一个比较严重的问题,因为用户往往是希望能够通过后退来取消前一次操作的。那么对于这个问题有没有办法?答案是肯定的,用过Gmail的知道,Gmail下面采用的ajax技术解决了这个问题,在Gmail下面是可以后退的,但是,它也并不能改变ajax的机制,它只是采用的一个比较笨但是有效的办法,即用户单击后退按钮访问历史记录时,通过创建或使用一个隐藏的IFRAME来重现页面上的变更。(例如,当用户在Google Maps中单击后退时,它在一个隐藏的IFRAME中进行搜索,然后将搜索结果反映到Ajax元素上,以便将应用程序状态恢复到当时的状态。)


但是,虽然说这个问题是可以解决的,但是它所带来的开发成本是非常高的,和ajax框架所要求的快速开发是相背离的。这是ajax所带来的一个非常严重的问题。


2、安全问题


技术同时也对IT企业带来了新的安全威胁,ajax技术就如同对企业数据建立了一个直接通道。这使得开发者在不经意间会暴露比以前更多的数据和服务器逻辑。ajax的逻辑可以对客户端的安全扫描技术隐藏起来,允许黑客从远端服务器上建立新的攻击。还有ajax也难以避免一些已知的安全弱点,诸如跨站点脚步攻击、SQL注入攻击和基于credentials的安全漏洞等。


3、对搜索引擎的支持比较弱。


4、破坏了程序的异常机制。至少从目前看来,像ajax.dll,ajaxpro.dll这些ajax框架是会破坏程序的异常机制的。关于这个问题,我曾经在开发过程中遇到过,但是查了一下网上几乎没有相关的介绍。后来我自己做了一次试验,分别采用ajax和传统的form提交的模式来删除一条数据……给我们的调试带来了很大的困难。


5、另外,像其他方面的一些问题,比如说违背了url和资源定位的初衷。例如,我给你一个url地址,如果采用了ajax技术,也许你在该url地址下面看到的和我在这个url地址下看到的内容是不同的。这个和资源定位的初衷是相背离的。


6、一些手持设备(如手机、PDA等)现在还不能很好的支持ajax,比如说我们在手机的浏览器上打开采用ajax技术的网站时,它目前是不支持的,当然,这个问题和我们没太多关系。


4 java script DOM 对象结构图


window
-navigator
-plugins[]
-mime types[]
-frames[]
-location
-history
-window objects(self,parent,etc)
-document
-forms[]
-elements[]
-images[]
-embeds[]
-links[]
-anchors[]
-applets[]






5 Struts的流程图





6动态操作表格







我是表格,你看到我了么





<script>
function san(dj,cj){
if(dj==0)tabs.insertRow(cj).insertCell().innerText=’表达我的意思了否’
else tabs.deleteRow(cj)
}


7 谈谈HTTP协议,doGet和doPost的区别?


HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应,相应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。


通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。


通用头域


通用头域包含请求和响应消息都支持的头域,通用头域包含Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via。对通用头域的扩展要求通讯双方都支持此扩展,如果存在不支持的通用头域,一般将会作为实体头域处理。下面简单介绍几个在UPnP消息中使用的通用头域。


Cache-Control头域


Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-reva lidate、proxy-reva lidate、max-age。各个消息中的指令含义如下:


Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。


Date头域


Date头域表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。


Pragma头域


Pragma头域用来包含实现特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。


请求消息


请求消息的第一行为下面的格式:
MethodSPRequest-URISPHTTP-VersionCRLFMethod表示对于Request-URI完成的方法,这个字段是大小写敏感的,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE。方法GET和HEAD应该被所有的通用WEB服务器支持,其他所有方法的实现是可选的。GET方法取回由Request-URI标识的信息。HEAD方法也是取回由Request-URI标识的信息,只是可以在响应时,不返回消息体。POST方法可以请求服务器接收包含在请求中的实体信息,可以用于提交表单,向新闻组、BBS、邮件群组和数据库发送消息。


SP表示空格。Request-URI遵循URI格式,在此字段为星号(*)时,说明请求并不用于某个特定的资源地址,而是用于服务器本身。HTTP-Version表示支持的HTTP版本,例如为HTTP/1.1。CRLF表示换行回车符。请求头域允许客户端向服务器传递关于请求或者关于客户机的附加信息。请求头域可能包含下列字段Accept、Accept-Charset、Accept-Encoding、Accept-Language、Authorization、From、Host、If-Modified-Since、If-Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、Proxy-Authorization、Range、Referer、User-Agent。对请求头域的扩展要求通讯双方都支持,如果存在不支持的请求头域,一般将会作为实体头域处理。


典型的请求消息:


GEThttp://download.microtool.de:80/somedata.exe
Host:download.microtool.de
Accept:*/*
Pragma:no-cache
Cache-Control:no-cache
Referer:http://download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-


上例第一行表示HTTP客户端(可能是浏览器、下载程序)通过GET方法获得指定URL下的文件。棕色的部分表示请求头域的信息,绿色的部分表示通用头部分。


Host头域


Host头域指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回。


Referer头域


Referer头域允许客户端指定请求uri的源资源地址,这可以允许服务器生成回退链表,可用来登陆、优化cache等。他也允许废除的或错误的连接由于维护的目的被追踪。如果请求的uri没有自己的uri地址,Referer不能被发送。如果指定的是部分uri地址,则此地址应该是一个相对地址。


Range头域


Range头域可以请求实体的一个或者多个子范围。例如,


表示头500个字节:bytes=0-499
表示第二个500字节:bytes=500-999
表示最后500个字节:bytes=-500
表示500字节以后的范围:bytes=500-
第一个和最后一个字节:bytes=0-0,-1
同时指定几个范围:bytes=500-600,601-999


但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200(OK)。


User-Agent头域


User-Agent头域的内容包含发出请求的用户信息。


响应消息


响应消息的第一行为下面的格式:


HTTP-VersionSPStatus-CodeSPReason-PhraseCRLF
HTTP-Version表示支持的HTTP版本,例如为HTTP/1.1。Status-Code是一个三个数字的结果代码。Reason-Phrase给Status-Code提供一个简单的文本描述。Status-Code主要用于机器自动识别,Reason-Phrase主要用于帮助用户理解。Status-Code的第一个数字定义响应的类别,后两个数字没有分类的作用。第一个数字可能取5个不同的值:


1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求


响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和Request-URI进一步的信息。响应头域包含Age、Location、Proxy-Authenticate、Public、Retry-After、Server、Vary、Warning、WWW-Authenticate。对响应头域的扩展要求通讯双方都支持,如果存在不支持的响应头域,一般将会作为实体头域处理。


典型的响应消息:


HTTP/1.0200OK
Date:Mon,31Dec200104:25:57GMT
Server:Apache/1.3.14(Unix)
Content-type:text/html
Last-modified:Tue,17Apr200106:46:28GMT
Etag:”a030f020ac7c01:1e9f”
Content-length:39725426
Content-range:bytes554554-40279979/40279980
上例第一行表示HTTP服务端响应一个GET方法。棕色的部分表示响应头域的信息,绿色的部分表示通用头部分,红色的部分表示实体头域的信息。


Location响应头


Location响应头用于重定向接收者到一个新URI地址。


Server响应头


Server响应头包含处理请求的原始服务器的软件信息。此域能包含多个产品标识和注释,产品标识一般按照重要性排序。


实体


请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息,实体头包括Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header。extension-header允许客户端定义新的实体头,但是这些域可能无法未接受方识别。实体可以是一个经过编码的字节流,它的编码方式由Content-Encoding或Content-Type定义,它的长度由Content-Length或Content-Range定义。


Content-Type实体头


Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型Content-Range实体头


Content-Range实体头用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:


Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth
例如,传送头500个字节次字段的形式:Content-Range:bytes0-499/1234如果一个http消息包含此节(例如,对范围请求的响应或对一系列范围的重叠请求),Content-Range表示传送的范围,Content-Length表示实际传送的字节数。


Last-modified实体头


Last-modified实体头指定服务器上保存内容的最后修订时间。


Doget和dopost的区别:


get只有一个流,参数附加在url后,地址行显示要传送的信息,大小个数有严格限制且只能是字符串。
post的参数是通过另外的流传递的, 不通过url,所以可以很大,也可以传递二进制数据,如文件的上传。


1、安全


GET调用在URL里显示正传送给SERVLET的数据,这在系统的安全方面可能带来问题,例如用户名和密码等


POST就可以在一定程度上解决此类问题


2、服务器接收方式


服务器随机接受GET方法的数据,一旦断电等原因,服务器也不知道信息是否发送完毕


而POST方法,服务器先接受数据信息的长度,然后再接受数据


3、form运行方式


当form框里面的method为get时,执行doGet方法
当form框里面的method为post时,执行doPost方法


4、容量限制


GET方法后面的信息量字节大小不要超过1.3K,而Post则没有限制


###########最后说明的是:


你可以用service()来实现,它包含了doget和dopost ;service方法是接口中的方法,servlet容器把所有请求发送到该方法,该方法默认行为是转发http请求到doXXX方法中,如果你重载了该方法,默认操作被覆盖,不再进行转发操作!


service()是在javax.servlet.Servlet接口中定义的, 在 javax.servlet.GenericServlet
中实现了这个接口, 而 doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的, javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子类.


所有可以这样理解, 其实所有的请求均首先由 service() 进行处理, 而在 javax.servlet.http.HttpServlet 的 service() 方法中, 主要做的事情就是判断请求类型是 Get 还是 Post, 然后调用对应的 doGet/doPost 执行.


8 Struts怎么解决表单重复提交


相关文章:


Struts的Token(令牌)机制能够很好的解决表单重复提交的问题,基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。


这时其实也就是两点,第一:你需要在请求中有这个令牌值,请求中的令牌值如何保存,其实就和我们平时在页面中保存一些信息是一样的,通过隐藏字段来保存,保存的形式如: 〈input type=”hidden” name=”org.apache.struts.taglib.html.TOKEN” value=”6aa35341f25184fd996c4c918255c3ae”〉,这个value是TokenProcessor类中的generateToken()获得的,是根据当前用户的session id和当前时间的long值来计算的。第二:在客户端提交后,我们要根据判断在请求中包含的值是否和服务器的令牌一致,因为服务器每次提交都会生成新的Token,所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致。下面就以在数据库中插入一条数据来说明如何防止重复提交。


在Action中的add方法中,我们需要将Token值明确的要求保存在页面中,只需增加一条语句:saveToken(request);,如下所示:


public ActionForward add(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)


//前面的处理省略


saveToken(request);


return mapping.findForward(“add”);


}在Action的insert方法中,我们根据表单中的Token值与服务器端的Token值比较,如下所示:


public ActionForward insert(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)


if (isTokenValid(request, true)) {


// 表单不是重复提交


//这里是保存数据的代码


} else {


//表单重复提交


saveToken(request);


//其它的处理代码


}


}


其实使用起来很简单,举个最简单、最需要使用这个的例子:


一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,由于更新、删除一般都是通过id来操作(例如:updateXXXById, removeXXXById),所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。


先说一下,我们目前所做项目的情况:


目前的项目是用Struts+Spring+Ibatis,页面用jstl,Struts复杂View层,Spring在Service层提供事务控制,Ibatis是用来代替JDBC,所有页面的访问都不是直接访问jsp,而是访问Structs的Action,再由Action来Forward到一个Jsp,所有针对数据库的操作,比如取数据或修改数据,都是在Action里面完成,所有的Action一般都继承BaseDispatchAction,这个是自己建立的类,目的是为所有的Action做一些统一的控制,在Struts层,对于一个功能,我们一般分为两个Action,一个Action里的功能是不需要调用Struts的验证功能的(常见的方法名称有add,edit,remove,view,list),另一个是需要调用Struts的验证功能的(常见的方法名称有insert,update)。


就拿论坛发贴来说吧,论坛发贴首先需要跳转到一个页面,你可以填写帖子的主题和内容,填写完后,单击“提交”,贴子就发表了,所以这里经过两个步骤:


1、转到一个新增的页面,在Action里我们一般称为add,例如:


public ActionForward add(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)


throws Exception {


//这一句是输出调试信息,表示代码执行到这一段了


log.debug(“:: action – subject add”);


//your code here


//这里保存Token值


saveToken(request);


//跳转到add页面,在Structs-config.xml里面定义,例如,跳转到subjectAdd.jsp


return mapping.findForward(“add”);


}


2、在填写标题和内容后,选择 提交 ,会提交到insert方法,在insert方法里判断,是否重复提交了。


public ActionForward insert(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response){


if (isTokenValid(request, true)) {


// 表单不是重复提交


//这里是保存数据的代码


} else {


//表单重复提交


saveToken(request);


//其它的处理代码


}


}


下面更详细一点(注意,下面所有的代码使用全角括号):


1、你想发贴时,点击“我要发贴”链接的代码可以里这样的:


〈html:link action=”subject.do method=add”〉我要发贴〈/html:link〉


subject.do 和 method 这些在struct-config.xml如何定义我就不说了,点击链接后,会执行subject.do的add方法,代码如上面说的,跳转到subjectAdd.jsp页面。页面的代码大概如下:


〈html:form action=”subjectForm.do method=insert”〉


〈html:text property=”title” /〉


〈html:textarea property=”content” /〉


〈html:submit property=”发表” /〉


〈html:reset property=”重填” /〉


〈html:form〉


如果你在add方法里加了“saveToken(request);”这一句,那在subjectAdd.jsp生成的页面上,会多一个隐藏字段,类似于这样〈input type=”hidden” name=”org.apache.struts.taglib.html.TOKEN” value=”6aa35341f25184fd996c4c918255c3ae”〉,


2、点击发表后,表单提交到subjectForm.do里的insert方法后,你在insert方法里要将表单的数据插入到数据库中,如果没有进行重复提交的控制,那么每点击一次浏览器的刷新按钮,都会在数据库中插入一条相同的记录,增加下面的代码,你就可以控制用户的重复提交了。


if (isTokenValid(request, true)) {


// 表单不是重复提交


//这里是保存数据的代码


} else {


//表单重复提交


saveToken(request);


//其它的处理代码


}


注意,你必须在add方法里使用了saveToken(request),你才能在insert里判断,否则,你每次保存操作都是重复提交。


记住一点,Struts在你每次访问Action的时候,都会产生一个令牌,保存在你的Session里面,如果你在Action里的函数里面,使用了saveToken(request);,那么这个令牌也会保存在这个Action所Forward到的jsp所生成的静态页面里。


如果你在你Action的方法里使用了isTokenValid,那么Struts会将你从你的request里面去获取这个令牌值,然后和Session里的令牌值做比较,如果两者相等,就不是重复提交,如果不相等,就是重复提交了。


由于我们项目的所有Action都是继承自BaseDispatchAction这个类,所以我们基本上都是在这个类里面做了表单重复提交的控制,默认是控制add方法和insert方法,如果需要控制其它的方法,就自己手动写上面这些代码,否则是不需要手写的,控制的代码如下:


public abstract class BaseDispatchAction extends BaseAction {


protected ActionForward perform(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)


throws Exception {


String parameter = mapping.getParameter();


String name = request.getParameter(parameter);


if (null == name) { //如果没有指定 method ,则默认为 list


name = “list”;


}


if (“add”.equals(name)) {


if (“add”.equals(name)) {


saveToken(request);


}


} else if (“insert”.equals(name)) {


if (!isTokenValid(request, true)) {


resetToken(request);


saveError(request, new ActionMessage(“error.repeatSubmit”));


log.error(“重复提交!”);


return mapping.findForward(“error”);


}


}


return dispatchMethod2(mapping, form, request, response, name);


}


}



9 Hibernate 的缓存和延迟加载



缓存:


缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。


缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。


Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。


Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的两个特性:缓存的范围和缓存的并发访问策略。


持久化层的缓存的范围


缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。


1 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式。


2 进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。


3 集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。


对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。


持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存,通常它是必需的;进程范围或集群范围的缓存是持久化层的第二级缓存,通常是可选的。


持久化层的缓存的并发访问策略


当多个并发的事务同时访问持久化层的缓存的相同数据时,会引起并发问题,必须采用必要的事务隔离措施。


在进程范围或集群范围的缓存,即第二级缓存,会出现并发问题。因此可以设定以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。


事务型:仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。


读写型:提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。


非严格读写型:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读。对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。   只读型:对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。


事务型并发访问策略是事务隔离级别最高,只读型的隔离级别最低。事务隔离级别越高,并发性能就越低。


什么样的数据适合存放到第二级缓存中?


1、很少被修改的数据


2、不是很重要的数据,允许出现偶尔并发的数据


3、不会被并发访问的数据


4、参考数据


不适合存放到第二级缓存的数据?


1、经常被修改的数据


2、财务数据,绝对不允许出现并发


3、与其他应用共享的数据。


Hibernate的二级缓存


如前所述,Hibernate提供了两级缓存,第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。第一级缓存是必需的,不允许而且事实上也无法比卸除。在第一级缓存中,持久化类的每个实例都具有唯一的OID。


第二级缓存是一个可插拔的的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存。


Hibernate的二级缓存策略的一般过程如下:


1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。


2) 把获得的所有数据对象根据ID放入到第二级缓存中。


3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。


4) 删除、更新、增加数据的时候,同时更新缓存。


Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query缓存。


Hibernate的Query缓存策略的过程如下:


1) Hibernate首先根据这些信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。


2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。


3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。


延迟加载:


当系统从数据库中初始化某个持久化类时,集合属性是否随持久化类一起初始化
呢 如果集合属性里包含十万,甚至百万的记录,在初始化持久化类之时,要完成所有
集合属性的加载,势必将导致性能急剧下降。系统很有可能只需要使用持久化类的某个
属性中的部分记录,这样,没有必要一次加载所有的集合属性。
对于集合属性,通常推荐使用延迟加载策略。所谓延迟加载就是当系统需要使用合属性时才从数据库装载关联的数据。
Hibernate 对集合属性默认采用延迟加载,在某些特殊的情况下为set, list, map 等元
设置lazy= “false” 属性来取消延迟加载
根据前面的讲解,可将集合分成如下两类。
·有序集合:集合里的元素可以根据key 或index 访问。
·无序集合:集合里的元素只能遍历。
有序集合都拥有一个由组成的联合主键,在这种情况下,集合属性
的更新是非常高效的一一主键已经被有效地索引。因此当Hibernate 试图更新或删除某行
时,可以迅速找到该行数据。
对无序集合而言,如果集合中元素是组合元素或者大量文本及二进制宇段,数据
库可能无法有效地对复杂的主键进行索引。即使可以建立索引,性能也非常差。例如Set
的主键由和其他元素宇段构成,或者根本没有主键。
显然,有序集合的属性在增加、删除及修改中拥有较好的性能表现
在设计良好的Hibernate Domain Object 中,集合属性通常都会增加inverse=”true”
属性,此时集合端不再控制关联关系。因此,无须考虑其集合的更新性能。



10 Spring 的事务处理


Spring的声明式事务顾名思义就是采用申明的方式来处理事务。这里所说的声明,就是指在配置文件中申明。用在Spring配置文件中申明式地处理事务来代替代码式的。这样的好处是业务逻辑(Dao)就不会意识到事务管理的存在,而且维护起来极其方便。
使用声明式事务管理时,通常要把我们的Dao交给一个代理,由其进行管理。这个代理一般spring里的:org.springwork.transaction.interceptor.TransactionProxyFactoryBean
我的配置清单如下:
class=”org.springwork.transaction.interceptor.TransactionProxyFactoryBean”>

<>
cn.sunrain.test.service.hibernate.IHabtestService












class=”org.springwork.transaction.interceptor.NameMatchTransactionAttributeSource”>



PROPAGATION_REQUIRED



以上定义后,表示在hibernateService中,方法executeTest()会加上事务处理,该方法内发生异常将回滚。
修改完以后,当要调用hibernateService这个id的bean时,改成调用hibernateTestProxy即可.


显然,以这种方式进行代理,配置太过复杂,因为每定义一个方法为事务方法就需要配置如此一大段。因此,可以用自动代理来解决。


class=”org.springwork.aop.work.autoproxy.DefaultAdvisorAutoProxyCreator”>


class=”org.springwork.transaction.interceptor.TransactionAttributeSourceAdvisor”>




class=”org.springwork.transaction.interceptor.TransactionInterceptor”>








class=”org.springwork.transaction.interceptor.NameMatchTransactionAttributeSource”>


PROPAGATION_REQUIRED



元素–>
class=”org.springwork.transaction.interceptor.MethodMapTransactionAttributeSource”>



<>PROPAGATION_REQUIRED





———————————————————————————————————


2.如何优化Oracle数据库保持优良性能



根据实际经验,在一个大数据库中,数据库空间的绝大多数是被少量的表所占有。为了简化大型数据库的管理,改善应用的查询性能,一般可以使用分区这种手段。 1.分区(建立分区表,分区索引,分区管理(根据实际需要,还可以使用Alter table 命令来增加、删除、交换、移动、修改、重命名、划分、截短一个已存在分区的结构))2.重建索引3.段的碎片整理


————————————————————————————————————-


3.什么是SQL注入?


① http://www.19cn.com/showdetail.asp id=49


② http://www.19cn.com/showdetail.asp id=49 and 1=1


③ http://www.19cn.com/showdetail.asp id=49 and 1=2



这就是经典的1=1、1=2测试法了,怎么判断呢?看看上面三个网址返回的结果就知道了:



可以注入的表现:



正常显示(这是必然的,不然就是程序有错误了)


正常显示,内容基本与①相同


提示BOF或EOF(程序没做任何判断时)、或提示找不到记录(判断了rs.eof时)、或显示内容为空(程序加了on error resume next



不可以注入就比较容易判断了,①同样正常显示,②和③一般都会有程序定义的错误提示,或提示类型转换时出错。


——————————————————————————————————–


4.正则表达式的验证规则?


匹配中文字符的正则表达式: [\u4e00-\u9fa5]



匹配双字节字符(包括汉字在内):[^\x00-\xff]



匹配空行的正则表达式:\n[\s| ]*\r



匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/



匹配首尾空格的正则表达式:(^\s*)|(\s*$)



匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*



匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./ %&=]*)


———————————————————————————————–


5.运用JSP上传文件


1、uploadimage.jsp



<%@ page contentType=”text/html;charset=gb2312″ language=”java” import=”java.io.*,java.awt.Image,java.awt.image.*,com.sun.image.codec.jpeg.*,


java.sql.*,com.jspsmart.upload.*,java.util.*,cn.oof.database.*,cn.oof.house.*”%>


<%


SmartUpload mySmartUpload =new SmartUpload();


long file_size_max=4000000;


String fileName2=””,ext=””,testvar=””;


String url=”uploadfile/images/”; //应保证在根目录中有此目录的存在


//初始化


mySmartUpload.initialize(pageContext);


//只允许上载此类文件


try {


mySmartUpload.setAllowedFilesList(“jpg,gif”);


//上载文件


mySmartUpload.upload();


} catch (Exception e){


%>


<SCRIPT language=java script>


alert(“只允许上传.jpg和.gif类型图片文件”);


window.location=”upfile.jsp”;



<%


}


try{



com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(0);


if (myFile.isMissing()){%>


<SCRIPT language=java script>


alert(“请先选择要上传的文件”);


window.location=”upfile.jsp”;



<%}


else{


//String myFileName=myFile.getFileName(); //取得上载的文件的文件名


ext= myFile.getFileExt(); //取得后缀名


int file_size=myFile.getSize(); //取得文件的大小


String saveurl=””;


if(file_size


//更改文件名,取得当前上传时间的毫秒数值


Calendar calendar = Calendar.getInstance();


String filename = String.valueOf(calendar.getTimeInMillis());


saveurl=request.getRealPath(“/”)+url;


saveurl+=filename+”.”+ext; //保存路径


myFile.saveAs(saveurl,mySmartUpload.SAVE_PHYSICAL);


//out.print(filename);


//———————–上传完成,开始生成缩略图————————-


java.io.File file = new java.io.File(saveurl); //读入刚才上传的文件


String newurl=request.getRealPath(“/”)+url+filename+”_min.”+ext; //新的缩略图保存地址


Image src = javax.imageio.ImageIO.read(file); //构造Image对象


float tagsize=200;


int old_w=src.getWidth(null); //得到源图宽


int old_h=src.getHeight(null);


int new_w=0;


int new_h=0; //得到源图长


int tempsize;


float tempdouble;


if(old_w>old_h){


tempdouble=old_w/tagsize;


}else{


tempdouble=old_h/tagsize;


}


new_w=Math.round(old_w/tempdouble);


new_h=Math.round(old_h/tempdouble);//计算新图长宽


BufferedImage tag = new BufferedImage(new_w,new_h,BufferedImage.TYPE_INT_RGB);


tag.getGraphics().drawImage(src,0,0,new_w,new_h,null); //绘制缩小后的图


FileOutputStream newimage=new FileOutputStream(newurl); //输出到文件流


JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);


encoder.encode(tag); //近JPEG编码


newimage.close();



}


else{


out.print(“<SCRIPT language=”java script”>”);


out.print(“alert(”上传文件大小不能超过”+(file_size_max/1000)+”K”);”);


out.print(“window.location=”upfile.jsp;””);


out.print(“”);


}


}


}catch (Exception e){



e.toString();



}


%>



2 upload.htm




</strong><strong>请选择上传的图片









请选择上传的图片



上传”>





——————————————————————————————-


6.HTML中的表标签



“http://www.w3.org/TR/html4/loose.dtd”>





</strong><strong>无标题文档



<script language=”java script”>


var count;


function add()


{


count=document.all.mytable.rows.length;


var mtr=document.all.mytable.insertRow(count-1);



var mtd=mtr.insertCell();


mtd.innerHTML=””;


mtd=mtr.insertCell();


mtd.innerHTML=””;


}



function del(a)


{


document.all.mytable.deleteRow(a.rowIndex);


}



















增加” onClick=”add()”>






1: JAVA 中怎么实现多线程



单核CPU来用多线程的方式来计算1加到100000和用单线程的方式计算那个好些呢?


(可以使用多线程来输出10000个string类型的和单线程相比时间上的区别)



2: 怎么读写二进制文件?



3: Statement和PreparedStatement的区别和联系?



public interface Statement


The object used for executing a static SQL statement and returning the results it produces.



By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment’s current ResultSet object if an open one exists.






public interface PreparedStatementextends StatementAn object that represents a precompiled SQL statement.



A SQL statement is precompiled and stored in a PreparedStatement object. This object can then be used to efficiently execute this statement multiple times.



Note: The setter methods (setShort, setString, and so on) for setting IN parameter values must specify types that are compatible with the defined SQL type of the input parameter. For instance, if the IN parameter has SQL type INTEGER, then the method setInt should be used.



If arbitrary parameter type conversions are required, the method setObject should be used with a target SQL type.



In the following example of setting a parameter, con represents an active connection:



PreparedStatement pstmt = con.prepareStatement(“UPDATE EMPLOYEES


SET SALARY = WHERE ID = ”);


pstmt.setBigDecimal(1, 153833.00)


pstmt.setInt(2, 110592)



4. JAVA对象的创建过程?


1)、首先为对象分配内存空间


基本数据类型成员设置为默认值,其中boolean类型为false,整数类型为0小数为0.0;引用类型为null


2)、然后执行显式初始化,即执行在类成员声明时带有的简单赋值表达式


父类静态成员->子类静态成员->父类非静态成员->子类非静态成员


3)、执行构造方法,进行对象初始化。


父类构造函数->子类构造函数


请参考JAVA编程思想


5: AJAX帧与XML http 的实现方式?《”AJAX帧”网上找不到》


JAVA帧:使用一个隐藏的frame/iframe,主页面发送请求时,指定返回页面为该隐藏帧,这样,整个页面就不会被刷新,然后,主页面到隐藏帧中去取得返回的数据并进行处理即可。特点:只需浏览器支持HTML 4即可,不须ActiveX之类的支持; 可以维护浏览器历史,用户仍然可以使用浏览器上的后退和前进按钮。


XML HTTP: 用java script来创建XMLHttpRequest 类向服务器发送一个HTTP请求,当收到服务器的响应后,用java script绑定和处理所有数据。它是一种支持异步请求的技术



6: 十万条数据用什么方法分页? ORACLE && MYSQL


Oracle 使用 rownum


Mysql 使用 limit


Sql server 使用top



】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ASP.NET笔试题小汇总 下一篇介绍一下XMLHttpRequest对象

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: