《2023年中软JAVA面试.doc》由会员分享,可在线阅读,更多相关《2023年中软JAVA面试.doc(19页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、struts1的工作原理图: img/img 1.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控制器会读取配置文献(struts-config.xml)的配置信息,为struts中不同的模块初始化相应的对象。(面向对象思想) 2.发送请求:用户提交表单或通过URL向WEB服务器提交请求,请求的数据用HTTP协议传给web服务器。 3.form填充:struts的总控制器ActionServlet在用户提交请求时将数据放到相应的form对象中的成员变量中。 4.派发请求:控制器根据配置信息对象Ac
2、tionConfig将请求派发到具体的Action,相应的formBean一并传给这个Action中的excute()方法。 5.解决业务:Action一般只包含一个excute()方法,它负责执行相应的业务逻辑(调用其它的业务模块)完毕后返回一个ActionForward对象。服务器通过ActionForward对象进行转发工作。 6.返回响应:Action将业务解决的不同结果返回一个目的响应对象给总控制器。 7.查找响应:总控制器根据Action解决业务返回的目的响应对象,找到相应的资源对象,一般情况下为jsp页面。 8.响应用户:目的响应对象将结果传递给资源对象,将结果展现给用户。网页跳
3、转的三种方式: 方法1 response.redirect 这个跳转页面的方法跳转的速度不快,由于它要走2个来回(2次postback),但他可以跳 转到任何页面,没有站点页面限制(即可以由雅虎跳到新浪),同时不能跳过登录保护。但速度慢是其最大缺陷!redirect跳转机制:一方面是发送一个http请求到客户端,告知需要跳转到新页面,然后客户端在发送跳转请求到服务器端。需要注意的是跳转后内部空间保存的所有数据信息将会丢失,所以需要用到session.(此方法与JSP中的redirect相似) 方法2 server.transfer 速度快,只需要一次postback ,但是他必须是在同一个站点
4、下,由于它是server的一个方法。此外,他能跳过登录保护。你可以写个小程序试试:设计一个由页面一到页面二的跳转,但要进入到页面二需要登录,forms认证,但假如跳转语句使用transfer的话,那就不会弹出登录页面了。这个方法的重定向请求是发生在服务器端,所以浏览器的url地址仍然保存的是原页面的地址! 方法3 sever.execute 这个方法重要是用在页面设计上面,并且他必须是跳转同一站点下的页面。这个方法是需要将一个页面的输出结果插入到另一个aspx页面的时候使用,大部分是在表格中,将某一个页面类似于嵌套的方式存在于另一页面。(此方法效果类似于JSP中的标签效果) 总结:当需要把用户
5、跳转到另一台服务器上的页面的时候 使用redirect当需要把用户跳转到非aspx页面时候,如html 使用redirect需要把查询字符串作为url一部分的时候保存传给服务器的时候,由于其他2种方法不能做到2次postback,把数据先带回服务器使用redirect需要aspx页面间的转换(不涉及登录) 使用transfer当需要把aspx页面的输出结果插入到另一个aspx页面的时候使用 execute方法。当然,忘掉了尚有一个超链接!当然这个就不需要讲太多了。他是在当需要用户来决定什么时候跳转页面,就使用超链接。顺便提一下,如何使用redirect方法在查询字符串中使用汉字,由于经常的情况
6、是出现乱码,因素是url不支持汉字。这个时候需要转换:string message =server.urlencode(欢迎来到赛跑专栏);先转换,再使用查询字符串response.redirect(webform2.aspx?msg=+message);各位javaeye的朋友们,我这里有个问题请求你们的帮忙,谢谢。 我希望可以配置spring管理hibernate事务,当一个service调用多dao的时候,所有save成功才commit,可以怎么实现? 这是配置文献 Java代码 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. PROPAGATION_REQ
7、UIRED 13. PROPAGATION_REQUIRED 14. PROPAGATION_REQUIRED 15. 16. 17. 18. /*/ PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED /*/sevice就没写了 Java代码 1. publicclassAccountManagerImplimplementsAccountManager 2. 3. publicSyncResponseInfosaveKnSyncData() 4. /1 5. dao.saveObject2(object1); 6.
8、/2 7. dao.saveObject1(object2); 8. 9. Spring io 一方面想说说IoC(Inversion of Control,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简朴的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得美丽身材又好的mm,然后打听她们的爱好爱好、qq号、电话号、ip号、iq号,想办法结识她们,投其所好送其所要,然后嘿嘿这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,
9、假如要使用此外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。 那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的规定,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简朴明了,假如婚介给我们的人选不符合规定,我们就会抛出异常。整个过程不再由我自己控制,而
10、是有婚介这样一个类似容器的机构来控制。Spring所提倡的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运营到适当的时候,把你要的东西积极给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。假如你还不明白的话,我决定放弃。IoC的一个重点是在系统运营中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Depen
11、dency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运营时,spring会在适当的时候制造一个Connection,然后像打针同样,注射到A当中,这样就完毕了对各个对象之间关系的控制。A需要依赖 Connection才干正常运营,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之
12、后一个重要特性是反射(reflection),它允许程序在运营的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。关于反射的相关资料请查阅java doc。 理解了IoC和DI的概念后,一切都将变得简朴明了,剩下的工作只是在spring的框架中堆积木而已。strtus2.0实现上传 实现原理 Struts 2是通过Commons FileUpload文献上传。 1.Commons FileUpload通过将HTTP的数据保存到临时文献夹,我们可以设立保存临时文献夹的途径,若不设立那么它会放到tomcat服务器安装目录下workCatalinalocalh
13、ost你的项目名下的文献夹;如我的将上传文献项目Struts2Upload发布到tomcat后,那么上传的文献的临时文献会保存形如:D:Javaapache-tomcat-6.0.20workCatalinalocalhostStruts2Uploadupload_243601eb_1277f7c2df8_7ffc_00000001.tmp,我们在action类里再相称于本地的资源同样来读取,再转移到如数据库等的地方去。总之,我觉得上传文献时,数据会随用户的提交,而由浏览器端将辨认出的传输文献标签,将本地的文献转化为文献流,再通过建立好的tcp连接(每次用户访问一个页面时,会建立tcp连接,服
14、务器应答完响应后会断开连接),将数据上传至服务器,应当是这样,而不是用服务器端的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-c
15、ore-2.0.14.jar xwork-2.0.7.jar 注意: 1.页面的表单enctype须设立为multipart/form-data; 2.标签将上传文献赋值给ACTION中的File loadFile属性,并且将文献名,文献类型都会邦定到action类里去,就上面这个标签例子,action类里可以邦定如下属性: /* * 一个loadFile, * 不仅须设立setLoadFile(), * 还需要设立setLoadFileContentType(String contentType):获取上传文献的MIME类型 * setLoadFileFileName(String file
16、Name):上传文献的文献名,此文献名不涉及文献途径 * 因此: * ,则ACTION中要有三个相应的setter方法: * setxxx(), * setxxxContentType(String contentType) * setxxxFileName(String fileName) * */ private File loadFile; private String contentType; private String fileName; (2)能获取到本地文献信息,那在服务器端的操作就很容易了。 strtus2.0实现下载 (1) 实现下载也不难,在页面上显示待下载的资源的链接,
17、将链接与action类链接起来,当用户点击时,会到action类去, action类里得到下载资源的途径(这个途径一般写在配置文献或者从数据库里查出来),有途径就可以给出一个读取服务器端资源的输入流,并将该流交邦定给页面端。这重要是用struts.xml配置来实现:这句可以将从action类跳转到页面时,以输出流的形式跳转,当浏览器辨认出是以流的形式返回的页面时,它会弹出一个保存(打开)的对话框,从而实现下载的功能,上面都是我个人理解,如有不对,希望大家直接指出。 (2) 以流的形式跳转到页面前,我们可以给出其它参数: contentType:文献类型 inputName:这个就是文献流,重要
18、的参数,其它都是辅助说明 contentDisposition:这个是文献的描述 bufferSize:缓冲的大小,这个我没研究过,也许尚有其它参数,我没时间去研究,所以就列出这几个。 这样后在页面端弹出的保存文献对话框会将contentDisposition的信息在“名称”那里显示出来。 (3) 下载还涉及到中文文献名等的问题,所以也要解决,具体可以参考如下文章1. *Object类的方法: 2. *clone() 3. *equals() 4. *finalize() 5. *hashCode() 6. *toString() 7. * 8. *1、equals()方法: 9. *equa
19、ls方法强调比较的值的是否相等 10. *=强调对象的地址是否相同 11. *s1和s2的值都保存在对内存中 12. *s3和s4的值都保存在占内存的字符串缓冲池中,缓存池的分派原则是按值是否相同来分派。 13. *假如值相同则分在一起,指向他们的引用的hashCode()值也相同。假如不同,则不分在一起,也就不=了。 14. *所以s3和s4是相同的两个引用,而s5和他们俩内存地址不同,hashCode值当然也不同了 15. * 16. *2、finalize()方法: 17. *由于在Object()类的以下所有子类中的对象都是在java的垃圾回收前自动调用此Object类(父类)的此fi
20、nalize方法。 18. *所以可以重写这样运营的过程可以看的更清楚。 19. * 20. *3、hashCode()方法: 21. *hashCode()方法的返回值调用它的对象的十进制哈希码 22. *(不同的对象必有不同的hashCode返回值,但是假如两个引用的值相同则hashCode返回值相同, 23. *由于引用不是对象,不是new出来的。) 24. *总结:两个对象或者引用的hashCode()是否相同,就是看这些对象或引用的地址是否相同, 25. *hashCode()方法只看地址。 26. *Integer类的静态方法toHexString方法作用是将十进制整型数转化成十六
21、进制数 27. * 28. *4、toString()方法: 29. *toString方法功能是以字符串形式返回当前对象的有关信息。 30. *其返回值是调用它的对象的类名加十六进制哈希码。 31. * 32. */java中的对象名 比如 String ss就是对象名 它的值 是个地址 类似C+的指针假如你用=去判断 就是判断它们的地址是不是同样用equlas判断是判断对象的内容是否同样String s1=abc;String s2=new String(s1);s1.equals(s2) 是trues1=s2 是false由于 它们对象的内容是同样的 可不是同一个对象= 就表达判断它们是
22、不是同一个对象你有一本语文书 我有一本语文书 虽然内容同样,可我的书不是你的书 这是两本书hibernate延迟加载关键字: lazy 延迟加载:延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,此外在Hibernate3中还提供了对属性的延迟加载。下面我们就分别介绍这些种类的延迟加载的细节。A、实体对象的延迟加载:假如想对实体对象使用延迟加载,必须要在实体的映射配置文献中进行相应的配置,如下所示: 通过将class的lazy属性设立为true,来启动实体的延
23、迟加载特性。假如我们运营下面的代码:User user=(User)session.load(User.class,”1”);(1)System.out.println(user.getName();(2)当运营到(1)处时,Hibernate并没有发起对数据的查询,假如我们此时通过一些调试工具(比如JBuilder2023的Debug工具),观测此时user对象的内存快照,我们会惊奇的发现,此时返回的也许是User$EnhancerByCGLIB$bede8986类型的对象,并且其属性为null,这是怎么回事?还记得前面我曾讲过session.load()方法,会返回实体对象的代理类对象,这
24、里所返回的对象类型就是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目的对象的代理类对象,并且在代理类对象中包含目的对象的所有属性和方法,并且所有属性均被赋值为null。通过调试器显示的内存快照,我们可以看出此时真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,当代码运营到(2)处时,此时调用user.getName()方法,这时通过CGLIB赋予的回调机制,事实上调用CGLIB$CALBACK_0.getName()方法,当调用该方法时,Hibernate会一方面检查CGLIB$CALBACK_0.target属
25、性是否为null,假如不为空,则调用目的对象的 getName方法,假如为空,则会发起数据库查询,生成类似这样的SQL语句:select * from user where id=1;来查询数据,并构造目的对象,并且将它赋值到CGLIB$CALBACK_0.target属性中。 这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完毕的,所以只有session.load()方法才会运用实体延迟加载,由于只有session.load()方法才会返回实体类的代理类对象。B、
26、集合类型的延迟加载:在 Hibernate的延迟加载机制中,针对集合类型的应用,意义是最为重大的,由于这有也许使性能得到大幅度的提高,为此Hibernate进行了大量的努力,其中涉及对JDK Collection的独立实现,我们在一对多关联中,定义的用来容纳关联对象的Set集合,并不是java.util.Set类型或其子类型,而是 net.sf.hibernate.collection.Set类型,通过使用自定义集合类的实现,Hibernate实现了集合类型的延迟加载。为了对集合类型使用延迟加载,我们必须如下配置我们的实体类的关于关联的部分: . 通过将元素的lazy属性设立为true来启动集
27、合类型的延迟加载特性。我们看下面的代码:User user=(User)session.load(User.class,”1”);Collection addset=user.getAddresses(); (1)Iterator it=addset.iterator(); (2)while(it.hasNext()Address address=(Address)it.next();System.out.println(address.getAddress();当程序执行到(1)处时,这时并不会发起对关联数据的查询来加载关联数据,只有运营到(2)处时,真正的数据读取操作才会开始,这时Hibe
28、rnate会根据缓存中符合条件的数据索引,来查找符合条件的实体对象。这里我们引入了一个全新的概念数据索引,下面我们一方面将接一下什么是数据索引。在 Hibernate中对集合类型进行缓存时,是分两部分进行缓存的,一方面缓存集合中所有实体的id列表,然后缓存实体对象,这些实体对象的id列表,就是所谓的数据索引。当查找数据索引时,假如没有找到相应的数据索引,这时就会一条selectSQL的执行,获得符合条件的数据,并构造实体对象集合和数据索引,然后返回实体对象的集合,并且将实体对象和数据索引纳入Hibernate的缓存之中。另一方面,假如找到相应的数据索引,则从数据索引中取出 id列表,然后根据i
29、d在缓存中查找相应的实体,假如找到就从缓存中返回,假如没有找到,在发起select SQL查询。在这里我们看出了此外一个问题,这个问题也许会对性能产生影响,这就是集合类型的缓存策略。假如我们如下配置集合类型: . 这里我们应用了配置,假如采用这种策略来配置集合类型,Hibernate将只会对数据索引进行缓存,而不会对集合中的实体对象进行缓存。如上配置我们运营下面的代码:User user=(User)session.load(User.class,”1”);Collection addset=user.getAddresses(); Iterator it=addset.iterator();
30、 while(it.hasNext()Address address=(Address)it.next();System.out.println(address.getAddress();System.out.println(“Second query”);User user2=(User)session.load(User.class,”1”);Collection it2=user2.getAddresses();while(it2.hasNext()Address address2=(Address)it2.next();System.out.println(address2.getAd
31、dress();运营这段代码,会得到类似下面的输出:Select * from user where id=1;Select * from address where user_id=1;TianjinDalianSecond querySelect * from address where id=1;Select * from address where id=2;TianjinDalian我们看到,当第二次执行查询时,执行了两条对address表的查询操作,为什么会这样?这是由于当第一次加载实体后,根据集合类型缓存策略的配置,只对集合数据索引进行了缓存,而并没有对集合中的实体对象进行缓存,
32、所以在第二次再次加载实体时,Hibernate找到了相应实体的数据索引,但是根据数据索引,却无法在缓存中找到相应的实体,所以Hibernate根据找到的数据索引发起了两条select SQL的查询操作,这里导致了对性能的浪费,如何才干避免这种情况呢?我们必须对集合类型中的实体也指定缓存策略,所以我们要如下对集合类型进行配置: . 此时Hibernate会对集合类型中的实体也进行缓存,假如根据这个配置再次运营上面的代码,将会得到类似如下的输出:Select * from user where id=1;Select * from address where user_id=1;TianjinDa
33、lianSecond queryTianjinDalian这时将不会再有根据数据索引进行查询的SQL语句,由于此时可以直接从缓存中获得集合类型中存放的实体对象。C、 属性延迟加载:在Hibernate3中,引入了一种新的特性属性的延迟加载,这个机制又为获取高性能查询提供了有力的工具。在前面我们讲大数据对象读取时,在User对象中有一个resume字段,该字段是一个java.sql.Clob类型,包含了用户的简历信息,当我们加载该对象时,我们不得不每一次都要加载这个字段,而不管我们是否真的需要它,并且这种大数据对象的读取自身会带来很大的性能开销。在Hibernate2中,我们只有通过我们前面讲过
34、的面性能的粒度细分,来分解User类,来解决这个问题(请参照那一节的论述),但是在Hibernate3中,我们可以通过属性延迟加载机制,来使我们获得只有当我们真正需要操作这个字段时,才去读取这个字段数据的能力,为此我们必须如下配置我们的实体类: 通过对元素的lazy属性设立true来启动属性的延迟加载,在Hibernate3中为了实现属性的延迟加载,使用了类增强器来对实体类的Class文献进行强化解决,通过增强器的增强,将CGLIB的回调机制逻辑,加入实体类,这里我们可以看出属性的延迟加载,还是通过CGLIB来实现的。CGLIB是 Apache的一个开源工程,这个类库可以操纵java类的字节码
35、,根据字节码来动态构造符合规定的类对象。根据上面的配置我们运营下面的代码:String sql=”from User user where user.name=zx ”;Query query=session.createQuery(sql); (1)List list=query.list();for(int i=0;ilist.size();i+)User user=(User)list.get(i);System.out.println(user.getName();System.out.println(user.getResume(); (2)当执行到(1)处时,会生成类似如下的SQL语句:Select id,age,name from user where name=zx;这时Hibernate会检索User实体中所有非延迟加载属性相应的字段数据,当执行到(2)处时,会生成类似如下的SQL语句:Select resume from user where id=1;这时会发起对resume字段数据真正的读取操作。
限制150内