人力资源中软JAVA面试_第1页
人力资源中软JAVA面试_第2页
人力资源中软JAVA面试_第3页
人力资源中软JAVA面试_第4页
人力资源中软JAVA面试_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

struts1的工作原理图:

[img]/upload/picture/pic/52368/b185b878-9771-33e4-a25d-cc123df0bc00.jpg[/img]

1.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控制器会读取配置文件(struts-config.xml)的配置信息,为struts中不同的模块初始化相应的对象。(面向对象思想)

2.发送请求:用户提交表单或通过URL向WEB服务器提交请求,请求的数据用HTTP协议传给web服务器。

3.form填充:struts的总控制器ActionServlet在用户提交请求时将数据放到对应的form对象中的成员变量中。

4.派发请求:控制器根据配置信息对象ActionConfig将请求派发到具体的Action,对应的formBean一并传给这个Action中的excute()方法。

5.处理业务:Action一般只包含一个excute()方法,它负责执行相应的业务逻辑(调用其它的业务模块)完毕后返回一个ActionForward对象。服务器通过ActionForward对象进行转发工作。

6.返回响应:Action将业务处理的不同结果返回一个目标响应对象给总控制器。

7.查找响应:总控制器根据Action处理业务返回的目标响应对象,找到对应的资源对象,一般情况下为jsp页面。

8.响应用户:目标响应对象将结果传递给资源对象,将结果展现给用户。网页跳转的三种方式:

方法1response.redirect这个跳转页面的方法跳转的速度不快,因为它要走2个来回(2次postback),但他可以跳转到任何页面,没有站点页面限制(即可以由雅虎跳到新浪),同时不能跳过登录保护。但速度慢是其最大缺陷!redirect跳转机制:首先是发送一个http请求到客户端,通知需要跳转到新页面,然后客户端在发送跳转请求到服务器端。需要注意的是跳转后内部空间保存的所有数据信息将会丢失,所以需要用到session.(此方法与JSP中的redirect相似)

方法2server.transfer速度快,只需要一次postback,但是……他必须是在同一个站点下,因为它是server的一个方法。另外,他能跳过登录保护。你可以写个小程序试试:设计一个由页面一到页面二的跳转,但要进入到页面二需要登录,forms认证,但如果跳转语句使用transfer的话,那就不会弹出登录页面了。这个方法的重定向请求是发生在服务器端,所以浏览器的url地址仍然保留的是原页面的地址!方法3sever.execute这个方法主要是用在页面设计上面,而且他必须是跳转同一站点下的页面。这个方法是需要将一个页面的输出结果插入到另一个aspx页面的时候使用,大部分是在表格中,将某一个页面类似于嵌套的方式存在于另一页面。(此方法效果类似于JSP中的<jsp:include>标签效果)

总结:

当需要把用户跳转到另一台服务器上的页面的时候使用redirect

当需要把用户跳转到非aspx页面时候,如html使用redirect

需要把查询字符串作为url一部分的时候保留传给服务器的时候,因为其他2种方法不能做到2次postback,把数据先带回服务器使用redirect

需要aspx页面间的转换(不涉及登录)使用transfer

当需要把aspx页面的输出结果插入到另一个aspx页面的时候使用execute方法。

当然,忘记了还有一个超链接!当然这个就不需要讲太多了。他是在当需要用户来决定什么时候跳转页面,就使用超链接。

顺便提一下,如何使用redirect方法在查询字符串中使用汉字,因为经常的情况是出现乱码,原因是url不支持汉字。这个时候需要转换:

stringmessage=server.urlencode("欢迎来到赛跑专栏");

先转换,再使用查询字符串

response.redirect("webform2.aspx?msg="+message);各位javaeye的朋友们,我这里有个问题请求你们的帮忙,谢谢。

我希望可以配置spring管理hibernate事务,当一个service调用多dao的时候,全部save成功才commit,可以怎么实现?

这是配置文件Java代码<bean

id="transactionManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager"

/>

<bean

id="accountManagerTarget"

class="com.vas.brd.service.impl.AccountManagerImpl">

<property

name="userOrderDAO"><ref

local="userOrderDAO"/></property>

</bean>

<bean

id="accountManager"

class="erceptor.TransactionProxyFactoryBean">

<property

name="transactionManager"><ref

local="transactionManager"/></property>

<property

name="target"><ref

local="accountManagerTarget"/></property>

<property

name="transactionAttributes">

<props>

<prop

key="save*">PROPAGATION_REQUIRED</prop>

<prop

key="remove*">PROPAGATION_REQUIRED</prop>

<prop

key="*">PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

/*******************************************************************************/

sevice就没写了Java代码public

class

AccountManagerImpl

implements

AccountManager

{

public

SyncResponseInfo

saveKnSyncData(){

//1

dao.saveObject2(object1);

//2

dao.saveObject1(object2));

}

}

Springio首先想说说IoC(InversionofControl,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。如果你还不明白的话,我决定放弃。IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(DependencyInjection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢?Java1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。关于反射的相关资料请查阅javadoc。理解了IoC和DI的概念后,一切都将变得简单明了,剩下的工作只是在spring的框架中堆积木而已。strtus2.0实现上传

实现原理

Struts2是通过CommonsFileUpload文件上传。

1.CommonsFileUpload通过将HTTP的数据保存到临时文件夹,我们可以设置保存临时文件夹的路径,若不设置那么它会放到tomcat服务器安装目录下\work\Catalina\localhost\你的项目名下的文件夹;如我的将上传文件项目Struts2Upload发布到tomcat后,那么上传的文件的临时文件会保存形如:D:\Java\apache-tomcat-6.0.20\work\Catalina\localhost\Struts2Upload\upload_243601eb_1277f7c2df8__7ffc_00000001.tmp,我们在action类里再相当于本地的资源一样来读取,再转移到如数据库等的地方去。总之,我觉得上传文件时,数据会随用户的提交,而由浏览器端将识别出的传输文件标签,将本地的文件转化为文件流,再通过建立好的tcp连接(每次用户访问一个页面时,会建立tcp连接,服务器应答完响应后会断开连接),将数据上传至服务器,应该是这样,而不是用服务器端的action类或servlet类来完成传输的,应该是浏览器对上传文件标签的解析,从而完成本地资源的传输的。

2.然后Struts使用fileUpload拦截器将文件绑定到Action的实例中。从而我们就能够以本地文件方式的操作浏览器上传的文件。

以下是例子所依赖类包的列表:

commons-fileupload-1.2.1.jar

commons-io-1.3.2.jar

commons-logging-1.0.4.jar

freemarker-2.3.8.jar

ognl-2.6.11.jar

struts2-core-2.0.14.jar

xwork-2.0.7.jar

注意:

1.页面的表单enctype须设置为"multipart/form-data";

2.<s:filename="loadFile">标签将上传文件赋值给ACTION中的FileloadFile属性,并且将文件名,文件类型都会邦定到action类里去,就上面这个标签例子,action类里可以邦定如下属性:

/*

*一个loadFile,

*不但须设置setLoadFile(),

*还需要设置setLoadFileContentType(StringcontentType):获取上传文件的MIME类型

*

setLoadFileFileName(StringfileName):上传文件的文件名,此文件名不包括文件路径

*因此:

*<s:filename="xxx">,则ACTION中要有三个对应的setter方法:

*setxxx(),

*setxxxContentType(StringcontentType)

*setxxxFileName(StringfileName)

**/

privateFileloadFile;

privateStringcontentType;

privateStringfileName;

(2)能获取到本地文件信息,那在服务器端的操作就很容易了。

strtus2.0实现下载

(1)实现下载也不难,在页面上显示待下载的资源的链接,将链接与action类链接起来,当用户点击时,会到action类去,action类里得到下载资源的路径(这个路径一般写在配置文件或者从数据库里查出来),有路径就可以给出一个读取服务器端资源的输入流,并将该流交邦定给页面端。这主要是用struts.xml配置来实现:<resultname="success"type="stream">这句可以将从action类跳转到页面时,以输出流的形式跳转,当浏览器识别出是以流的形式返回的页面时,它会弹出一个保存(打开)的对话框,从而实现下载的功能,上面都是我个人理解,如有不对,希望大家直接指出。

(2)以流的形式跳转到页面前,我们可以给出其它参数:

contentType:文件类型

inputName:这个就是文件流,主要的参数,其它都是辅助说明

contentDisposition:这个是文件的描述

bufferSize:缓冲的大小,这个我没研究过,可能还有其它参数,我没时间去研究,所以就列出这几个。

这样后在页面端弹出的保存文件对话框会将contentDisposition的信息在“名称”那里显示出来。

(3)下载还涉及到中文文件名等的问题,所以也要处理,具体可以参考如下文章*

Object类的方法:

*

clone()

*

equals()

*

finalize()

*

hashCode()

*

toString()

*

*

1、equals()方法:

*

^

equals方法强调比较的值的是否相等

*

==强调对象的地址是否相同

*

^

s1

s2的值都保存在对内存中

*

s3

s4的值都保存在占内存的字符串缓冲池中,缓存池的分配原则是按值是否相同来分配。

*

^

如果值相同则分在一起,指向他们的引用的hashCode()值也相同。如果不同,则不分在一起,也就不==了。

*

所以s3和s4是相同的两个引用,而s5和他们俩内存地址不同,hashCode值当然也不同了

*

*

2、finalize()方法:

*

由于在Object()类的以下所有子类中的对象都是在java的垃圾回收前自动调用此Object类(父类)的此finalize方法。

*

所以可以重写这样运行的过程可以看的更清楚。

*

*

3、hashCode()方法:

*

^

hashCode()方法的返回值调用它的对象的十进制哈希码

*

(不同的对象必有不同的hashCode返回值,但是如果两个引用的值相同则hashCode返回值相同,

*

因为引用不是对象,不是new出来的。)

*

^

总结:两个对象或者引用的hashCode()是否相同,就是看这些对象或引用的地址是否相同,

*

hashCode()方法只看地址。

*

^

Integer类的静态方法toHexString方法作用是将十进制整型数转化成十六进制数

*

*

4、toString()方法:

*

^

toString

方法功能是以字符串形式返回当前对象的有关信息。

*

^

其返回值是调用它的对象的类名加十六进制哈希码。

*

*/

java中的对象名比如Stringss就是对象名它的值是个地址类似C++的指针如果你用==去判断就是判断它们的地址是不是一样用equlas判断是判断对象的内容是否一样Strings1="abc";Strings2=newString(s1);s1.equals(s2)是trues1==s2是false因为它们对象的内容是一样的可不是同一个对象==就表示判断它们是不是同一个对象你有一本语文书我有一本语文书虽然内容一样,可我的书不是你的书这是两本书hibernate延迟加载关键字:lazy延迟加载:

延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。下面我们就分别介绍这些种类的延迟加载的细节。A、实体对象的延迟加载:

如果想对实体对象使用延迟加载,必须要在实体的映射配置文件中进行相应的配置,如下所示:<hibernate-mapping>

<classname=”com.neusoft.entity.User”table=”user”lazy=”true”>

……

</class></hibernate-mapping>通过将class的lazy属性设置为true,来开启实体的延迟加载特性。如果我们运行下面的代码:Useruser=(User)session.load(User.class,”1”);(1)System.out.println(user.getName());(2)当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们此时通过一些调试工具(比如JBuilder2005的Debug工具),观察此时user对象的内存快照,我们会惊奇的发现,此时返回的可能是User$EnhancerByCGLIB$$bede8986类型的对象,而且其属性为null,这是怎么回事?还记得前面我曾讲过session.load()方法,会返回实体对象的代理类对象,这里所返回的对象类型就是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目标对象的代理类对象,并且在代理类对象中包含目标对象的所有属性和方法,而且所有属性均被赋值为null。通过调试器显示的内存快照,我们可以看出此时真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,当代码运行到(2)处时,此时调用user.getName()方法,这时通过CGLIB赋予的回调机制,实际上调用CGLIB$CALBACK_0.getName()方法,当调用该方法时,Hibernate会首先检查CGLIB$CALBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName方法,如果为空,则会发起数据库查询,生成类似这样的SQL语句:select*fromuserwhereid=’1’;来查询数据,并构造目标对象,并且将它赋值到CGLIB$CALBACK_0.target属性中。

这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完成的,所以只有session.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。B、

集合类型的延迟加载:在Hibernate的延迟加载机制中,针对集合类型的应用,意义是最为重大的,因为这有可能使性能得到大幅度的提高,为此Hibernate进行了大量的努力,其中包括对JDKCollection的独立实现,我们在一对多关联中,定义的用来容纳关联对象的Set集合,并不是java.util.Set类型或其子类型,而是net.sf.hibernate.collection.Set类型,通过使用自定义集合类的实现,Hibernate实现了集合类型的延迟加载。为了对集合类型使用延迟加载,我们必须如下配置我们的实体类的关于关联的部分:

<hibernate-mapping>

<classname=”com.neusoft.entity.User”table=”user”>…..<setname=”addresses”table=”address”lazy=”true”inverse=”true”><keycolumn=”user_id”/>

<one-to-manyclass=”com.neusoft.entity.Arrderss”/></set>

</class>

</hibernate-mapping>通过将<set>元素的lazy属性设置为true来开启集合类型的延迟加载特性。我们看下面的代码:Useruser=(User)session.load(User.class,”1”);Collectionaddset=user.getAddresses();

(1)Iteratorit=addset.iterator();

(2)while(it.hasNext()){

Addressaddress=(Address)it.next();

System.out.println(address.getAddress());}当程序执行到(1)处时,这时并不会发起对关联数据的查询来加载关联数据,只有运行到(2)处时,真正的数据读取操作才会开始,这时Hibernate会根据缓存中符合条件的数据索引,来查找符合条件的实体对象。这里我们引入了一个全新的概念——数据索引,下面我们首先将接一下什么是数据索引。在Hibernate中对集合类型进行缓存时,是分两部分进行缓存的,首先缓存集合中所有实体的id列表,然后缓存实体对象,这些实体对象的id列表,就是所谓的数据索引。当查找数据索引时,如果没有找到对应的数据索引,这时就会一条select

SQL的执行,获得符合条件的数据,并构造实体对象集合和数据索引,然后返回实体对象的集合,并且将实体对象和数据索引纳入Hibernate的缓存之中。另一方面,如果找到对应的数据索引,则从数据索引中取出id列表,然后根据id在缓存中查找对应的实体,如果找到就从缓存中返回,如果没有找到,在发起selectSQL查询。在这里我们看出了另外一个问题,这个问题可能会对性能产生影响,这就是集合类型的缓存策略。如果我们如下配置集合类型:<hibernate-mapping>

<classname=”com.neusoft.entity.User”table=”user”>…..<setname=”addresses”table=”address”lazy=”true”inverse=”true”>

<cacheusage=”read-only”/><keycolumn=”user_id”/>

<one-to-manyclass=”com.neusoft.entity.Arrderss”/></set>

</class>

</hibernate-mapping>这里我们应用了<cacheusage=”read-only”/>配置,如果采用这种策略来配置集合类型,Hibernate将只会对数据索引进行缓存,而不会对集合中的实体对象进行缓存。如上配置我们运行下面的代码:Useruser=(User)session.load(User.class,”1”);Collectionaddset=user.getAddresses();

Iteratorit=addset.iterator();

while(it.hasNext()){

Addressaddress=(Address)it.next();

System.out.println(address.getAddress());}System.out.println(“Secondquery……”);Useruser2=(User)session.load(User.class,”1”);Collectionit2=user2.getAddresses();while(it2.hasNext()){

Addressaddress2=(Address)it2.next();

System.out.println(address2.getAddress());}运行这段代码,会得到类似下面的输出:Select*fromuserwhereid=’1’;Select*fromaddresswhereuser_id=’1’;TianjinDalianSecondquery……Select*fromaddresswhereid=’1’;Select*fromaddresswhereid=’2’;TianjinDalian我们看到,当第二次执行查询时,执行了两条对address表的查询操作,为什么会这样?这是因为当第一次加载实体后,根据集合类型缓存策略的配置,只对集合数据索引进行了缓存,而并没有对集合中的实体对象进行缓存,所以在第二次再次加载实体时,Hibernate找到了对应实体的数据索引,但是根据数据索引,却无法在缓存中找到对应的实体,所以Hibernate根据找到的数据索引发起了两条selectSQL的查询操作,这里造成了对性能的浪费,怎样才能避免这种情况呢?我们必须对集合类型中的实体也指定缓存策略,所以我们要如下对集合类型进行配置:<hibernate-mapping>

<classname=”com.neusoft.entity.User”table=”user”>…..<setname=”addresses”table=”address”lazy=”true”inverse=”true”>

<cacheusage=”read-write”/><keycolumn=”user_id”/>

<one-to-manyclass=”com.neusoft.entity.Arrderss”/></set>

</class>

</hibernate-mapping>此时Hibernate会对集合类型中的实体也进行缓存,如果根据这个配置再次运行上面的代码,将会得到类似如下的输出:Select*fromuserwhereid=’1’;Select*

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论