你可能会遇到的面试题:

来源:互联网 发布:淘宝图片热点工具在哪 编辑:程序博客网 时间:2024/05/22 15:19

参考第一题:如果你只答到关系,就结束了,那么根本不能体现出与其他面试者的区别,想想应该再答一些什么,所以在答同样的面试题的时候,如何才能让你的答案比其他同期面试者更出彩?

1,阐述Servlet,GenericServlet,HttpServlet都是什么,他们之间的关系。
答:1、GenericServlet类是所有Servlet类的祖先类。
2、HttpServlet类继承了GenericServlet类。
3、Servlet有两个非常重要的的对象,可以说是Java web核心对象httpservletrequest和httpservletreponse。
下面这幅图就是servlet主要的类之间的关系。
 图
genericservlet是个抽象的父类,必须给出子类才能实例化它。
httpservlet是个子类,继承了genericservlet一切的特性,当然自己还扩张了doput dotrace等方法对应处理http协议里的命令请求响应过程。
4、下面只要简洁介绍一下httpservletrequest和httpservletresponse对象
4.1 httpservletrequest:包装了从客户端提交过来的数据(ip地址,表单数据和Cookies信息)
4.2 httpservletresponse:包装向客户端写出的数据。
这里写图片描述
2,块状元素与行内元素的区别,HTML与JSP的区别。
(1).块级元素会独占一行,默认情况下,其宽度自动填满其父元素宽度.
行内元素不会独占一行,相邻的行内元素会排列在同一行里,直到一行排不下,才会换行,其宽度随元素的内容而变化.
块级元素可以设置width,height属性.
内元素设置width,height属性无效.
块级元素即使设置了宽度,仍然是独占一行.
块级元素可以设置margin和padding属性.
行内元素的margin和padding属性,水平方向的padding-left,padding-right,margin- left,margin-right都产生边距效果,但竖直方向的padding-top,padding-bottom,margin- top,margin-bottom却不会产生边距效果.
块级元素对应于display:block.
行内元素对应于display:inline.
(2).块级元素:div , p , form, ul, li , ol, dl, form, address, fieldset, hr, menu, table
行内元素:span, strong, em, br, img , input, label, select, textarea, cite,

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没有<%%>
3,JSP和Servlet的关系,它们是如何分工合作的。
Servlet是Java提供的用于开发Web服务器应用程序的一个组件,运行在服务器端,由Servlet容器所管理,用于生成动态的内容。Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。
这里写图片描述
如图所示,Java提供一系列接口类(所谓接口类就是类中所有方法只提供方法声明,不提供任何的方法实现,这些类的实现就留给后继者去做。):Servlet、ServletConfig、Serializable,然后通过多重继承产生一个最通用的Servlet实现类(图中Gerneric Servlet类),接下来,通过一个多重继承与实现,产生一个新的实现类HttpServlet,用户在开发Servlet程序时只需继承这个类,从而产生一个自己的类(图中Hello_Servlet类),然后根据实际开发功能与信息处理需要,去实现该类中的相关方法即可。这就是前面提到的按照Servlet规范编写一个Java类,从而编写一个Servlet。

至于JSP(JavaServlet Page)从图中可以看出,实际上它也是从Servlet继承而来。只不过它在Servlet当中又添加/修改了一些方法,作了新的封装。具体到Tomcat Web应用服务器中,它通过一个多重继承,分别从Java的HttpJspPage和HttpServlet两个类那里继承和实现一些方法,然后封装一个叫做HttpJspBase的类从而实现了一个通用化的JSP类,用户在开发自己的JSP时,只需要从HttpJspBase继承一个自己的类(如图中Hello_jsp类),然后根据需要去实现相应的方法即可。

因此这也是为什么JSP的代码中总是闪现Servlet代码框架影子的原因,其实它们只是为实现同样的功能而进行了不同封装的组件而已,血脉里留着的是一样的血。

“既生瑜何生亮?”呵呵,因为JSP确实比Servlet要更胜一筹,所谓“青出于蓝胜于蓝”,既然Sun公司要在Servlet基础上推出JSP技术,那肯定是因为JSP有它更高明的地方。

使用Servlet产生动态网页,需要在代码中打印输出很多HTML的标签,此外,在Servlet中,我们不得不将静态现实的内容和动态产生内容的代码混合在一起。使用Servlet开发动态网页,程序员和网页编辑人员将无法一起工作,因为网页编辑人员不了解Java语言,无法修改Servlet代码,而Java程序员可能也不是很了解网页编辑人员的意图,以至于无法修改和实现网页功能。为了解决这些问题,Sun公司就推出了JSP技术。

JSP是Servlet的扩展,在没有JSP之前,就已经出现了Servlet技术。Servlet是利用输出流动态生成HTML页面,包括每一个HTML标签和每个在HTML页面中出现的内容。
JSP通过在标准的HTML页面中插入Java代码,其静态的部分无须Java程序控制,只有那些需要从数据库读取并根据程序动态生成信息时,才使用Java脚本控制。

事实上,JSP是Servlet的一种特殊形式,每个JSP页面就是一个Servlet实例——JSP页面由系统编译成Servlet,Servlet再负责响应用户请求。JSP其实也是Servlet的一种简化,使用JSP时,其实还是使用Servlet,因为Web应用中的每个JSP页面都会由Servlet容器生成对应的Servlet。对于Tomcat而言,JSP页面生成的Servlet放在work路径对应的Web应用下。

jsp和Servlet的分工:

  • JSP:

    作为请求发起页面,例如显示表单、超链接。

    作为请求结束页面,例如显示数据。

  • Servlet:

    作为请求中处理数据的环节。
    来看一张图:这里写图片描述
    4,我们使用的BaseServlet是如何封装的?简述其大致原理。这种写法模仿的哪个地方的源码?
    /此处代码巧妙之处在于我们把他的service方法覆盖,组织且不用他来调用doxx方法,而是我们让他来调用我们的自己的方法
    //一开可能会疑惑为什么会这样?不符合逻辑啊!!错了哥们.是你不符合逻辑,方法本来就是用来互相调用的,只不过看你怎么调用,当然不能破坏人家给你指定好的参数传递的规则
    //我们看过源码就可以知道,这个service方法来调用doxx方法也是通过方法getMethod获得方法的名字明来判断的具体要调用那个方法.所以我们也这么做,只不过和他的实现过程不一样
    //我们用的是反射.(你也可以把servlet中的doget和dopost看成是我们自己写的. )
    //这里我们也是通过方法明来判断,只不过是获取方法明的方法不一样了.
    //所以说我们的add和update方法,就相当于是doget和dopost方法
    //按照正常的情况我们也可以写成httpservlet的错误实现方法,就是说,父类也有子类的方法,但是如果不重写,父类就会打印出他的所谓的错误信息.
    //如果重写了,就不会执行父类的方法了,而是会执行子类的冲写的方法了.
    //还有一点是我们要思考的就是父类的方法是固定的,而我们的方法是根据需求而定我们不能因为要增加一个方法就要修改源代码,再编译,在部署到客户端上
    //长久下去就麻烦死了.客户还以为你的系统做的不好呢.
    //而我们怎么才能解决这个烦恼呢?
    //我们怎么才嫩让我们在父类调用我们子类不确定的方法呢?(也就是被子类覆盖的方法,怎么才能指向呢?就要通过反射了)
    //我们通过反射把我们要调用得方法通过请求传过来.就像我们在form中的method=post或get 只不过这些都是标配,我们的方法是拓展.但是还有一个区别就是他的传输加密和有大小
    //方式get和post我们是该表不了的
    //但是还有个巧妙之处容易让我们产生误解,就是我们通过反射在baseservlet中得到了request中传过来的方法,我们随让请求的是指定的userservlet虽然我们执行的是baseServlet的servlet方法,
    //但是在baseServlert中执行的时候this.getClass是子类字节码,这!!!!正好是反射的巧妙之处,因为这个service方法是子类调用的,所以我们在service中使用this他是子类的字节码引用(this.getClass是谁最后调用的他就是谁都字节码)
    //所以我们通过这个this得到的字节码文件是子类的,字节码文件得到的方法也是子类的.(到这里是不是有好像没有子类覆盖父类的方法那一说,只不过是一开始方便理解而说的)
    //所以就可以顺理成章的调用了子类的方法,(那我问你!子类可以调用父类的方法吗?我们可以牵强点说可以,为什说牵强呢?就是因为这个this啊,这个this明明在父类里面但是他调用的
    //却是子类的方法)

我们首先建立一个Baseservlet 继承HTTPservlet然后 @test下复写service方法;service中首先接收来自浏览器请求的servlet方法,然后获得当前类的对象,获得类对象的一个方法,接下来是方法的调用,需要对象也就是对象调用方法,我们现在有方法了 还需要一个对象根据之前得到的对象,创建出一个对象的,再使用创建出的这个对象调用method方法,因为创建出的方法是object类型的,是没有method方法的但是我们有方法对象,表示的是被谁调用,
5,Cookie与Session都是什么,他们之间的有怎样的关系?
1. 一、Session的概念

Session 是存放在服务器端的,类似于Session结构来存放用户数据,当浏览器 第一次发送请求时,服务器自动生成了一个Session和一个Session ID用来唯一标识这个Session,并将其通过响应发送到浏览器。当浏览器第二次发送请求,会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的Session。

一般情况下,服务器会在一定时间内(默认30分钟)保存这个 Session,过了时间限制,就会销毁这个Session。在销毁之前,程序员可以将用户的一些数据以Key和Value的形式暂时存放在这个 Session中。当然,也有使用数据库将这个Session序列化后保存起来的,这样的好处是没了时间的限制,坏处是随着时间的增加,这个数据 库会急速膨胀,特别是访问量增加的时候。一般还是采取前一种方式,以减轻服务器压力。

二、Session的客户端实现形式(即Session ID的保存方法)

一般浏览器提供了两种方式来保存,还有一种是程序员使用html隐藏域的方式自定义实现:

[1] 使用Cookie来保存,这是最常见的方法,本文“记住我的登录状态”功能的实现正式基于这种方式的。服务器通过设置Cookie的方式将Session ID发送到浏览器。如果我们不设置这个过期时间,那么这个Cookie将不存放在硬盘上,当浏览器关闭的时候,Cookie就消失了,这个Session ID就丢失了。如果我们设置这个时间为若干天之后,那么这个Cookie会保存在客户端硬盘中,即使浏览器关闭,这个值仍然存在,下次访问相应网站时,同 样会发送到服务器上。

[2] 使用URL附加信息的方式,也就是像我们经常看到JSP网站会有aaa.jsp?JSESSIONID=*一样的。这种方式和第一种方式里面不设置Cookie过期时间是一样的。

[3] 第三种方式是在页面表单里面增加隐藏域,这种方式实际上和第二种方式一样,只不过前者通过GET方式发送数据,后者使用POST方式发送数据。但是明显后者比较麻烦。

cookie与session的区别:

cookie数据保存在客户端,session数据保存在服务器端。

简 单的说,当你登录一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上面,客户端每次请求服务器的时候会发送 当前会话的sessionid,服务器根据当前sessionid判断相应的用户数据标志,以确定用户是否登录,或具有某种权限。由于数据是存储在服务器 上面,所以你不能伪造,但是如果你能够获取某个登录用户的sessionid,用特殊的浏览器伪造该用户的请求也是能够成功的。sessionid是服务 器和客户端链接时候随机分配的,一般来说是不会有重复,但如果有大量的并发请求,也不是没有重复的可能性,我曾经就遇到过一次。登录某个网站,开始显示的 是自己的信息,等一段时间超时了,一刷新,居然显示了别人的信息。

如果浏览器使用的是 cookie,那么所有的数据都保存在浏览器端,比如你登录以后,服务器设置了 cookie用户名(username),那么,当你再次请求服务器的时候,浏览器会将username一块发送给服务器,这些变量有一定的特殊标记。服 务器会解释为 cookie变量。所以只要不关闭浏览器,那么 cookie变量便一直是有效的,所以能够保证长时间不掉线。如果你能够截获某个用户的 cookie变量,然后伪造一个数据包发送过去,那么服务器还是认为你是合法的。所以,使用 cookie被攻击的可能性比较大。如果设置了的有效时间,那么它会将 cookie保存在客户端的硬盘上,下次再访问该网站的时候,浏览器先检查有没有 cookie,如果有的话,就读取该 cookie,然后发送给服务器。如果你在机器上面保存了某个论坛 cookie,有效期是一年,如果有人入侵你的机器,将你的 cookie拷走,然后放在他的浏览器的目录下面,那么他登录该网站的时候就是用你的的身份登录的。所以 cookie是可以伪造的。当然,伪造的时候需要主意,直接copy cookie文件到 cookie目录,浏览器是不认的,他有一个index.dat文件,存储了 cookie文件的建立时间,以及是否有修改,所以你必须先要有该网站的 cookie文件,并且要从保证时间上骗过浏览器,曾经在学校的vbb论坛上面做过试验,copy别人的 cookie登录,冒用了别人的名义发帖子,完全没有问题。

Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用Cookie,那么Session也会失效。

服务器也可以通过URL重写的方式来传递SessionID的值,因此不是完全依赖Cookie。如果客户端Cookie禁用,则服务器可以自动通过重写URL的方式来保存Session的值,并且这个过程对程序员透明。

可以试一下,即使不写Cookie,在使用request.getCookies();取出的Cookie数组的长度也是1,而这个Cookie的名字就是JSESSIONID,还有一个很长的二进制的字符串,是SessionID的值。

三:Session与Cookie区别和联系:

Cookies是属于Session对象的一种。但有不同,Cookies不会占服务器资源,是存在客服端内存或者一个cookie的文本文件中;而“Session”则会占用服务器资源。所以,尽量不要使用Session,而使用Cookies。但是我们一般认为cookie是不可靠的,session是可靠地,但是目前很多著名的站点也都以来cookie。有时候为了解决禁用cookie后的页面处理,通常采用url重写技术,调用session中大量有用的方法从session中获取数据后置入页面。

Cookies与Session的应用场景:
Cookies的安全性能一直是倍受争议的。虽然Cookies是保存在本机上的,但是其信息的完全可见性且易于本地编辑性,往往可以引起很多的安全问题。所以Cookies到底该不该用,到底该怎样用,就有了一个需要给定的底线。

先来看看,网站的敏感数据有哪些。

登陆验证信息。一般采用Session(“Logon”)=true or false的形式。
用户的各种私人信息,比如姓名等,某种情况下,需要保存在Session里
需要在页面间传递的内容信息,比如调查工作需要分好几步。每一步的信息都保存在Session里,最后在统一更新到数据库。

当然还会有很多,这里列举一些比较典型的
假如,一个人孤僻到不想碰Session,因为他认为,如果用户万一不小心关闭了浏览器,那么之前保存的数据就全部丢失了。所以,他出于好意,决定把这些用Session的地方,都改成用Cookies来存储,这完全是可行的,且基本操作和用Session一模一样。那么,下面就针对以上的3个典型例子,做一个分析
很显然,只要某个有意非法入侵者,知道该网站验证登陆信息的Session变量是什么,那么他就可以事先编辑好该Cookies,放入到Cookies目录中,这样就可以顺利通过验证了。这是不是很可怕?
Cookies完全是可见的,即使程序员设定了Cookies的生存周期(比如只在用户会话有效期内有效),它也是不安全的。假设,用户忘了关浏览器 或者一个恶意者硬性把用户给打晕,那用户的损失将是巨大的。
这点如上点一样,很容易被它人窃取重要的私人信息。但,其还有一个问题所在是,可能这些数据信息量太大,而使得Cookies的文件大小剧增。这可不是用户希望所看到的。

显然,Cookies并不是那么一块好啃的小甜饼。但,Cookies的存在,当然有其原因。它给予程序员更多发挥编程才能的空间。所以,使用Cookies改有个底线。这个底线一般来说,遵循以下原则。
不要保存私人信息。
任何重要数据,最好通过加密形式来保存数据(最简单的可以用URLEncode,当然也可以用完善的可逆加密方式,遗憾的是,最好不要用md5来加密)。
是否保存登陆信息,需有用户自行选择。
长于10K的数据,不要用到Cookies。
也不要用Cookies来玩点让客户惊喜的小游戏。

6,请求转发与请求包含之间的区别?请求转发、请求包含与重定向的区别?
(1)请求转发定义:

  Servlet(源组件)先对客户请求做一些预处理操作(一般是对响应头进行处理),然后把请求转发给其他Servlet(目标组件)来完成包括生成响应结果在内的后续操作。
  实现方法:request.getRequestDispatcher(“接收请求的Servlet 路径”). forward(request,response)
  getRequestDispatcher(String path):该方法的返回值类型是RequestDispatcher,请求发送器,该方法的参数是指明要接收请求的Servlet 的路径;
  forward(ServletRequest req,ServletResponse res):该方法是RequestDispatcher 接口的方法,将请求从一个 servlet 转发到服务器上的另一个资源(servlet、JSP 文件或 HTML 文件)。此方法允许一个 servlet 对请求进行初步处理,并使另一个资源生成响应。需要传递两个参数,这两个参数是当前Servlet 的request 对象和 response 对象传递过去的。
  forward() 方法的处理流程:
  ● 清空用于存放响应正文(响应体)数据的缓冲区。
  ● 如果目标组件为Servlet 或JSP,就调用它们的service() 方法,把该方法产生的响应结果发送到客户端,如果目标组件为文件系统中的静态 html 文档,就读去文档中的数据并把它发送到客户端。
  ● 由于 forward() 方法先清空用于存放响应正文数据的缓冲区,因此servlet源组件生成的响应结果不会被发送到客户端,只有目标组件生成的结果才会被发送到客户端,所以对源组件叫“留头不留体”,目标组件为“留体不留头”。
  ● 如果源组件在进行请求转发之前,已经提交了响应结果(例如调用了flush 或close() 方法),那么forward() 方法会抛出IllegalStateException。为了避免该异常,不应该在源组件中提交响应结果,所以叫留体抛异常。
(2)请求包含定义:

  Servlet(源组件)把其他Servlet(目标组件)生成的响应结果包含到自身的响应结果中。
  实现方式:request.getRequestDispatcher(“接收请求的Servlet 路径”). include(request,response)
  include(ServletRequest request,ServletResponse response):该方法是RequestDispatcher 接口的方法,表示包含。它的参数同forward() 方法的参数一样都是由当前Servlet传递过去的。
  包含与转发相比,源组件与被包含的目标组件的输出数据都会被添加到响应结果中,在目标组件中对响应状态代码或者响应头所做的修改都会被忽略,所以对源组件来说是“留头又留体”,对目标组件为“留体不留头”。
  注意:当Servlet 源组件调用 RequestDispatcher 的 forward 或 include 方法时,都要把当前的 ServletRequest 对象和ServletResponse 对象作为参数传给 forward 或 include 方法,这就使得源组件和目标组件共享同一个ServletRequest 对象和ServletResponse 对象,就实现了多个Servlet 协同处理同一个请求。
  1,请求重定向:客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次的请求对象不会保持,地址栏的URL地址会改变。

2,请求转发:服务器行为,request.getRequsetDispatcher().forward(requset,response);是一次请求,转发后请求对象会保存,地址栏的URL地址不会改变。(服务器内部转发,所有客户端看不到地址栏的改变)
1、重定向和转发有一个重要的不同
当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。 与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。因为,当你使用重定向时,浏览器中所显示的URL会变成新页面的URL, 而当使用转发时,该URL会保持不变。重定向的速度比转发慢,因为浏览器还得发出一个新的请求。同时,由于重定向方式产生了一个新的请求,所以经过一次重 定向后,request内的对象将无法使用。
2、怎么选择是重定向还是转发呢?
通常情况下转发更快,而且能保持request内的对象,所以他是第一选择。但是由于在转发之后,浏览器中URL仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。如果你不想看到这样的情况,则选择转发。
3、转发和重定向的区别
不要仅仅为了把变量传到下一个页面而使用session作用域,那会无故增大变量的作用域,转发也许可以帮助你解决这个问题。
重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。
转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。
7,什么原因导致我们后台前台交互时会出现乱码现象?

8,如何理解MVC软件设计规范。
MVC(Model/View/Controller)模式是国外用得比较多的一种设计模式,好象最早是在Smaltalk中出现。MVC包括三类对象。Model是应用对象,View是它在屏幕上的表示,Controller定义用户界面对用户输入的响应方式。
模型-视图-控制器(MVC)是80年代Smalltalk-80出现的一种软件设计模式,现在已经被广泛的使用。
1、模型(Model)
模型是应用程序的主体部分。模型表示业务数据,或者业务逻辑.
2、视图(View)
视图是应用程序中用户界面相关的部分,是用户看到并与之交互的界面。
3、控制器(controller)
控制器工作就是根据用户的输入,控制用户界面数据显示和更新model对象状态。
MVC 式的出现不仅实现了功能模块和显示模块的分离,同时它还提高了应用系统的可维护性、可扩展性、可移植性和组件的可复用性
早期的程序中,如果不注意对数功能和显示的解耦合,常常会导致程序的复杂及难以维护。很多VB,Delphi等RAD程序都有这种问题。甚至现在的C#,Java有时候也会出现把业务逻辑写在显示模块中的现象
管MVC设计模式很早就提出,但在Web项目的开发中引入MVC却是步履维艰。主要原因:一是在早期的Web项目的开发中,程序语言和HTML的分离一直难以实现。CGI程序以字符串输出的形式动态地生成HTML内容。后来随着脚本语言的出现,前面的方式又被倒了过来,改成将脚本语言书写的程序嵌入在HTML内容中。这两种方式有一个相同的不足之处即它们总是无法将程序语言和HTML分离。二是脚本语言的功能相对较弱,缺乏支持MVC设计模式的一些必要的技术基础。直到基于J2EE的JSP Model 2问世时才得以改观。它用JSP技术实现视图的功能,用Servlet技术实现控制器的功能,用JavaBean技术实现模型的功能

9,你是如何解决在写项目时遇到的错误的,说出三个让你印象深刻的错误及解决的过程。