Servlet的功能就是:提供服务器端对HTTP请求的处理; WEB服务器最初是作为用最简单的http协议向WEB浏览器发送静态Web文档的一种机制,不久, 人们开始寻找扩展Web浏览器能力的途径,以便可以显示更加复杂的表单元素,日期确认域以及 电子表格对象;与此同时,出现了许多为服务器添加程序逻辑的技术:CGI,plug-in, server-side include,服务器端脚本;
可以给Servlet一个美好的定义:是使用Java Servlet应用程序接口及相关类和方法的Java程序;
Servlet是由web服务器(辅助虚拟机)加载和执行的;Applet是虚拟机来干的; Applet可以让web浏览器显示更复杂的用户界面; Servlet可以让web服务器产生更复杂的..............; Applet可以在任何支持Java的web浏览器上执行; Servlet可以在任何支持Java的web服务器上执行; ”Servlet是一个类“,靠,好一句话惊醒梦中人也!不就是Applet一样的家伙嘛! 但是Applet虽然产生于服务器端,却是跑到客户端载工作; B/S:Browser/Server 需要说明的是Servlet就是一种和CGI同样功能的技术,就象J2EE和.NET的关系;
所有的Servlet都必须直接或者间接地实现javax.servlet.Servlet接口,才能在Servlet Engine上运行; (多么象是在说Applet呀!)
"HTTP是Servlet最常用的协议”它岂不是在说Servlet还可以处理其他的应用协议;
service()方法的作用就是: Receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class 所以你必须重写有可能用到的doXXX()方法; 但是它是根据什么来决定doXXX()的呢?? 回答如下: service()将会得到一个ServletRequest的对象,该对象描述了客户的html表单上的请求数据, 基于http协议,我们可以用ServletRequest的getXXX()方法得到这个表单上的数据,因为 有http协议作为标准嘛!!然后这个Servlet就获得了用户的信息,不就可以处理了; 也许你会问:我可没有调用service()来从html表单上把数据誊到servlet中; 放心,这个方法是有service container自己调用的,用户既然通过这个容器服务器的端口请求 一个服务并且在这个请求中夹带着自己的请求信息,容器服务器能不响应吗??响应的时候 能不接受请求信息然后通过service传给Servlet吗?有http作为协议,容器能不理解这个请求 信息表达了一个什么事情吗???
既然容器是用来调用service()的,那么可以知道以下servlet的功能都是 容器来完成的: 1:接受用户的请求表单参数信息;通过传给Servlet的ServletRequest对象。 2:为用户产生一个表单返回;通过传给Servlet的ServletResponse对象。 可见:Servlet确实只是处理数据;从用户端接受数据以及给用户发送数据都是容器的事情; 而Servlet只是从容器那拿数据来处理后又给容器结果,它可不关心对外交往的事情; 无论何时请求Servlet,引擎都会派生一个新的线程并执行servlet的service()方法; service()方法判断调用doXXX();实际上,doXXX()上我们用户在html表单里指明了的; 当然如果我们没有在html表单里指定应该doXXX(),或者我们直接在浏览器中请求servlet, 根本没有指定该调用的方法,这时默认调用的是doGet()方法;
总之呢,一个Servlet类负责把一个对html构造的串写到响应对象中,然后由容器负责勾勒出这个 响应对象所描述的html文件来;一般在Servlet类中我们用一个PrintWriter来写很多html的标记通过 响应对象传送给容器(并不是完全写完了后才可以传送给容器的,响应对象只是传输线,而不是 传输车,即有一行发一行,不在传输线上逗留),但是很麻烦,为了方便,你完全可以自己写一个html 类;因为我们总是只需要将一个字符串描述的html标记组合给响应对象,所以我们可以用这个html 类来返回整个html标记字符串,然后在Servlet类中我们只需要一次简单的out.println(html.getPages()) 就可以了;
Servlet肯定是要强调效率的,但是我们总是会new 出很多String或者StringBuffer对象来; 所以我们尽量不要用+或者直接用String对象,我们可以out.println一行串来描述整个html, 同时用StringBuffer.append()方法来连接字符串而不是+;
Servlet中的异常处理 异常有时候是个好的事情,因为我们可能自愿抛出异常以抵抗某种操作; 关于html标记的几个小常识:<br>是一个换行符号!如果用<h1></h1>标记标起来的将回以 强调的字体并且单独一行显示; 异常错误代替return 语句的过程: 以前你如果想调用一个方法检查某组数据是否有错时会这样做,让这个方法 返回不同的值以代表数据正确与否;这样你的主代码中还需要用if来判断 返回值以做出下一步动作‘ 而现在我们的方法是让方法自己抛出异常而不是返回值,这样主代码中 只管处理这个异常就行了,这样的代码更健壮; service方法抛出的异常自己不管,都抛给了引擎,如果发生异常,引擎会停止运行; 这就好像我们把底层的所有异常都逐级抛,直到JVM为止; 这里我们都逐级抛,知道引擎为止; HTTP协议是无状态的协议; 会话的作用 怎么说这个东西呢? 有时候你的信息不是在一次请求中传递给servlet的,比如买书,你可能挑了 很多次,每挑一本就点击了“提交”按钮请求了一个servlet服务; 而Http是无状态的,当你挑好了下一本书,你上次点击请求的servlet已经结束 生命,所以新的请求将只会知道你当前挑的这本书而不知道你以前还挑过别的书, 会话(HttpSession)正是致力于解决这个问题; 通过很多个Servlet实例共享同一个Session就可以保存这些信息了; 在这样的应用中,Servlet为了正确处理数据,应该从Session对象里取数据, 而不是从Request取数据;因为从Request取出的数据只是本次浏览器提交的 信息,而从Session取出的数据则是这个Session对象的生命周期中浏览器 提交的所有信息; 重起Tomcat之后这个Session还可以起作用,但是重起浏览器后Session就没了, 所以Session是客户端的浏览器保存的而不是web服务器的,这句话对吗? Session对象不会自动加上一些信息,必须用setAttribute()来维护Session 以保证它记录了所有用户请求信息; 对于原来以有的记录项,新的加入将会更新; 对于原来没有的记录项,新的加入将会产生一个新的记录项! HttpSession.setMaxInactiveInterval(int interval)方法的疑问: 这个时间从什么时候算起?? ServletContext 大家也看到了,接口ServletSession没有实现类,说明你根本没办法实例一个HttpSession; 而只能通过HttpRequest的getSession()方法来得到,这说明一个Session只对应于一个HttpRequest, 也就是说,它只提供对同一个Servlet的同一个HttpRequest的多次请求的共享,而不能提供不同的 Servlet的HttpRequest之间的共享;
注意:Servlet引擎通过URI来标识和配置了多个Servlet环境;这个URI就在web.xml文件里; 这个映射并不是用路径名来做的,有什么好处呢? 一般的映射名称可以十分简略,因为它可以略掉实现类的包名,实际上它完全与 实现类的名字无关,短名称使得对Servlet的引用更容易,并且更容易更换servlet 的实现类而不改变应用对servlet的引用; 如果用路径和完整类名,至少应用中的对servlet的引用必须老是换; 目前为止,你的应用指的就是你给用户的用来请求的html文件; 映射名保证了当servlet更换的时候,html文件不需要更改; MIME MIME就是"多用途的因特网邮件扩充业务"来的,最初被开发成允许包含非ASCII信息的E-MAIL信息. HTTP很依赖于MIME.每个传送到某个客户端浏览器的文件都由一个MIME数据头开始, http协议也使用mine,浏览器一般是根据服务器返回的mine type决定文件类型.
或许你看到这句话就明白了 1,response.setContentType("text/html;charset=gb2312"); 2, <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>无标题文档</title> </head> 在Content-Type响应标头中指定了HTTP数据的内容类型; 如果没有指定,则会默认为"text/html";
可以在一个http请求中提供一张可接受的内容类型表: Accept:image/gif,image/jpeg,image/pjpeg,*/* 一个Content type是形式为type/sub-type的字符串: image/jpeg: 是渐进的; image/gif: 是交错的; .............. Response.getWriter()得到一个PrintSwriter只能给浏览器传送text类型的字符数据, 如果是二进制数据则需要Response.getOutputStream(); servlet不能打开窗口,取而代之的是,它可以创建屏幕上不显示的图像,就象双缓冲技区创建不显示 的图像一样; servlet发送图像给web浏览器的步骤和原理是这样的: 为了得到一个Image对象,必须有一个组件,通过这个组件获得它,因为你知道 Image是个抽象类,是受保护的不可以直接得到的保护类,如Graphics一样; 所以可以先new Component()得到一个Component; 然后用这个Component.addNotify() 连接在主机平台上的AWT工具集上; 然后就可以createImage(); 然后传递这个Image给编码类,编码到Response.getOutputStream()得到的 指向web浏览器的输出流上; 必须将ContentType设置为image/sub-type,不然浏览器还是不认识; 注意:Response除了getWriter,getResponse得到输出流写到响应对象之外,还可以setXXX等为将要 发送给客户的响应对象设置内容,比如头,等东西; 对于Servlet 这种模式你现在应该有所体会: 无论用户要什么信息,需要什么处理,需要什么数据结构,需要什么对象, 你都不可以把这些东西放到或者传送到浏览器端去; 也就是说,出了传送Content Tpye 规定的数据给浏览器显示之外,浏览器不拥有 任何处理逻辑哪怕是为了显示而做的处理逻辑;浏览器端更本就没有显而易见的 Java程序; Color的两种表示法: 1,RGB,红,绿,蓝 2, HSB,色调,饱和度,亮度 可以用Color.HSBtoRGB和Color.RGBtoHSB来实现两者的转换;
CSDN关于float的回答: 带小数的常值都会被认为是 double 型的,就像整型的常值都会 被认为是 int 型的一样。 你可以这样 float x = 0.01f; 也就是加个 f 后缀就行了。
继续关于html和服务器端的交互 html中,一个表单form中,每个表单元素都有一个唯一的名字和值; 当用户按下submit按钮的时候, 表单数据就被打包作为请求发送给 html中的<form>标签指定的服务器端的脚本或者说 是指定的用来处理的特定的CGI或者S特定的ervlet等; 好像有这么一个道理:.html文件里显示的文件不一定是text/html类型的数据, 数据类型和文件类型完全是两回事;
Web服务器通过URL来与Servlet联系,所以说URL虽然是用户给的....;
Servlet模型中,为每个URL仅创建一个对象 任何客户每次访问服务器上的那个URL时,都调用同一个Servlet对象的service()方法; 这其实说明了什么呢?说明对一个URL多次请求都只对应用相同的一个Servlet对象来处理;
Tomcat启动的时候并没有加载所有的servlet,而是做了一个什么动作; 当第一次请求发生时,Tomcat调用了init()方法; Servlet的一些类和方法的说明 如果你的servlet类只是继承了GenericServlet的话,就不要写doXXX()一类的方法,因为 这个类并不是针对http协议的,所以它根本就不认识什么get,post请求,与此同时,它也就 没有这些方法,反正都会调用service()方法,你就实现这个方法就行了; 对继承HttpServlet的类来说,要么实现service()方法,自己决定doXXX()方法,要么不写service()方法 让它自己分配去;但是如果两者不一致,那会怎么样?比如当我的html请求里是get请求,但是在我的 servlet类中却是调用了doPost()方法,这时候tomcat就会发生异常: The specified HTTP method is not allowed for the requested resource (HTTP method GET is not supported by this URL).
对于http风格的Servlet 来说,内容类型在http响应中返回给客户,而输出流和书写器在HTML体中 返回数据; 你必须明确,getServletContext()是从接口ServletConfig继承而不是Servlet; 关于部署 WEB-INF结点不是应用程序的公共文档树的一部分,在这个目录中的文件不能直接为客户服务;
如果想要服务器启动的时候就加载一个Servlet,只要在web.xml部署中 写<load-on-startup>就行了,具体待看: <load-on-startup>4</load-on-startup> 对于ServletRequest中的getParameter()和getReader()方法不能混用; 你也不能太死板了!在只继承GenericServlet的Servlet不写doXXX()方法是因为它没有这个请求方法的 约束;而另一方面又说在继承了HttpServlet的Servlet里应该实现doXXX()方法,你就以为这必须做; 实际上也可以不写doXXX()方法,因为引擎调用的是默认的service()方法,如果你直接重写service()方法, 那你的sercice()方法完全可以不调用doXXX()方法而自己做所有的事情不就完了吗?
注意,要牢牢记住的是:Servlet通过ServletRequest和ServletResponse所做的是: 得到http报文和构造http报文而不是你以前所理解的 得到html表单和构造html;Servlet针对的是http而不是html; HttpSession会话的进一步学习
可以这样描述会话的功能:会话跟踪机制允许把任意对象通过会话关联起来。
其实会话就是一个驻在内存中的ID;
会话只是针对无状态的Http而言存在的,所以必须是在HttpServlet里谈论会话;
HttpSession是从HttpRequest得到的,所以一个会话 对应一个HttpRequest而不是一个HttpServlet; 更确切的说,一个会话对应着一个Html表单里的一个Form标签的一个action动作,当然这只是我个人的 猜测;
一个会话中的值都是对象!在web服务器上,因为我们或许会想要存储会话记录的某些对象, 所以使这些对象可串行化是很重要的;
会话保存什么样的对象是手动维护的;并不是你想像的会话会自动保存来自客户端的请求对象, 事实上,客户的请求信息未必是对象;所以会话是非常依赖人工的;
Session里的对象是按照name(String)---value(Object)来存储,检索的;
Cookie的学习 Cookie也是从HttpRequest得到的;而且可以一个HttpRequest可以得到多个Cookie; cookie必须是Http头的一部分; 多线程Servlet 啊,一切都是在变化和不断的广泛化! 我们已经不是象以前那样认为线程共享的是变量,对象等内存中的东西; 而是文件,数据库连接等东西了;
|