第3章servlet基础1.servlet的生命周期。a)init方法:首次创建servlet时,它的init方法会得到调用,因此,init是放置一次性设置代码的地方。i.可以使用此方法进行常规初始化,用来创建或载入在Servlet生命期内用到的一些数据,或者执行某些一次性的计算。ii.由初始化参数控制的初始化。要理解init参数的动机,您需要了解什么样的人可能希望对Servlet的行为方式进行定制。其中包括:开发人员、最终用户、部署人员。开发人员通过改变代码改变Servlet的行为。最终用户通过向HTML表单提供数据改变Servlet的行为。部署人员为了能够在不修改Servlet的源代码的情况下,就可以将Servlet在机器间移动,以及改变特定的参数(例如,数据库的地址,连接共享大小,或者数据文件的位置)。init参数的目的就是为了提供这项能力。b)service方法:在init之后,针对每个用户请求,都会创建一个线程,该线程调用前面创建的实例的service方法。service方法检查HTTP请求的类型(GET,POST,PUT,DELETE等)并相应地调用doGet,doPost,doPut,doDelete等方法。c)doGet,doPost和doXxx方法GET请求起因于正常的URL请求,或没有指定METHOD的HTML表单。POST请求起因于特别将POST列为METHOD的HTML表单。你可以覆盖doGet和/或doPost方法来处理。DELETE请求由doDelete处理,PUT由doPut方法处理,OPTIONS由doOptions处理,TRACE由doTrace方法处理。OPTIONS和TRACE的请求在Servlet中是自动支持的。doHead以处理HEAD请求(HEAD请求规定,服务器应该只返回正常的HTTP头,不含与之相关联的文档)。为了能够更快地生成对HEAD请求的响应(例如来自定制客户的请求,只需要HTTP报头,不需构建实际的文档输出),会实现doHead方法。2.SingleThreadModel接口a)通过让Servlet实现这个接口,系统会保证不会有多个请求线程同时访问该servlet的单个实例。大多数和情况下,系统将所有的请求排队,一次只将一个请求转给单个servlet实例。b)此接口已经过时,如果要同步最好使用synchronized关键字。第4章客户请求的处理:表单数据1.表单数据的读取。a)单个值的读取:getParameter(表单项名称),表单项名称大小写敏感。如果表单项存在但没有相应的值,返回空的String;如果没有这样的表单项,则返回null。b)多个值的读取:getParameterValues(表单项名称),如果同一表单项名称在表单数据中多次出现,则应该调用getParameterValues(返回字符串的数组)。对于不存在的表单项名称,getParameterValues的返回值是null,如果参数只有单一的值,则返回只有一个元素的数组。如果是HTML表单的设计者,最好保证每个文本字段、复选框或其他用户界面元素都有一个唯一的名称。2.参数名的查找:getParameterNames和getParameterMapgetParameterNames以Enumeration的形式返回表单项名称列表,其中的的每一项都可以转换成String,并可以用在getParameter或getParameterValues调用中。如果当前请求中没有表单名称返回空的Enumeration(不是null)。Enumeration只是一个接口,它保证实际的类实现了hasMoreElements和nextElement方法:它并不保证具体的实现会采用某种特定的底层数据结构。getParameterNames的替代方案是getParameterMap。这个方法返回一个Map:表单名称(字符串)是表的键,表单项的值是表的值。3.读取上载的文件和原始数据:getReader或getInputStream当数据不是HTML表单提交,而是来自于定制的客户程序时,可能需要自己读取和分析这些数据。最常见的客户程序是applet。当数据来自于上载的文件时,可能需要自己读取数据。servlet的API没有定义任何机制来读取inputtype=”file”元素的文件。4.多字符集输入的读取:setCharacterEncoding(字符集名称)request.getParameter使用服务器的当前字符集解释输入。要改变这种默认行为,需要使用ServletRequest的setCharacterEncoding方法。setCharacterEncoding必须在访问任何请求参数之前调用。我们可以按照某个字符集读取参数,然后将它转换到另外的字符集;或者用某些字符集提供的自动检测特性。第一种方案:使用getByte提取出原始的字节数据,之后将这些字节连同期望字符集的名称一同传递给String的构造函数。例:StringfirstNameWrongEncoding=request.getParameter(“firstName”);StringfirstName=newString(firstNameWrongEncoding.getBytes(),“shift_JIS”);第二种方案:需要使用一种支持从默认字符集进行检测和转换的字符集。例:如果允许输入既可以是英语,也可以是日语,则要使用下面的语句:request.setCharacterEncoding(“JISAutoDetect”);StringfirstName=request.getParameter(“firstName”);5.参数缺失或异常时默认值的应用如果用户没有提供必需的信息,那么该servlet应该怎么处理这种情况a)使用默认值b)重新显示这个表单(提示用户缺失的值)。c)请求中的参数需要检查下面三种情况:i.参数的值为null用户使用了错误的表单或使用了包含GET数据的URL书签,但在制作URL书签之后,参数名发生变化,都会发生返回值为null的情况。ii.参数的值为空字符串(“”)用户没有输入指定的值。为了安全起见,最好调用trim,移除用户可能输入的任何空格。iii.参数的值为非空字符串,但格式错误在长度和类型(只要求数值的字段)上输入错误。在设计servlet时,要使之能够优雅地处理参数缺失(null或空字符串)或格式不正确等情况。6.过滤字符串中的HTML特殊字符a)如果servlet希望生成含有诸如或等字符的HTML,只需简单地使用标准的HTML字符实体——<或>。b)如果您需要读取请求参数,并将它们的值显示在生成的页面中,则必须过滤出那些特殊的HTML字符。不这样做可能会导致输出中缺失部分,或者某些部分格式错误。c)Java字符串虽不可改变的(即不能修改),因此,重复的字符串拼接操作需要复制许多字符串片段,并在使用后废弃。建议在循环中执行重复性的拼接操作时,应该使用可以改变的数据结构:StringBuffer是通常的选择。7.根据请求参数自动填充Java对象:表单beana)普通的Java对象,如果它所属的类使用私有字段,且拥有遵循get/set命令约定的方法,则可以看作是bean。方法名(除去单词“get”或”set”,并且首字母小写)称为属性(property)。8.当参数缺失或异常时重新显示输入表单。a)由同一servlet提供表单、处理数据并提供最后的结果。表单省略Action属性,从而,表单提交时会自动发送到表单自身的URL。b)由一个servlet提供表单:由第二个servlet处理数据并提供结果。从一个servlet转到另外的servlet可以使用response.sendredirect或RequestDispatcher的forward方法。将数据从负责处理的servlet传递回显示表单的servlet时,最简单的方式是将它存储在HttpSession对象中。c)由一个JSP页面“手动地”提供表单:由一个servlet或JSP页面处理数据并提供结果。d)由一个JSP页面提供表单,用从数据对象获取的值自动填写表单中相应的字段:由一个servlet或JSP页面处理这些数据并提供最终结果。第5章客户请求的处理:HTTP请求报头1.简介:请求报头在JSP中的读取及应用与在servlet中相同。请求报头由浏览器间接地设定,并紧跟在初始的GET和POST请求行之后发送。2.请求报头的读取。只需用报头的名称为参数,调用HttpServletRequest的getHeader方法。如果当前的请求中提供了指定的报头,则这个调用返回一个String,否则返回null。在HTTP1.0中,请求的所有报头都是可选的:在HTTP1.1中,只有Host是必需的。因而,在使用请求报头之前一定要检查是否为null。报头名称对大小写不敏感。a)访问HTTP报头的方法汇总。getHeader是读取输入报头的通用方式。访问其他常用报头的方法有:i.getCookies方法返回Cookie报头的内容。ii.getAuthType和getRemoteUser返回Authorization报头进行拆分,分解成它的各个构成部分。iii.getContentLength返回Content-Length报送的值(作为一个int值返回)iv.getContentType返回Content-Type报头的值(作为一个String返回)v.getDateHeader和getIntHeader读取指定的报头,然后分别将它们转换成Date和int值。vi.getHeaderNames可以使用此方法得到一个Enumeration,枚举当前特定请求中所有的报头名称。vii.getHeaders大多数情况下,每个报头名称在请求中只出现一次。然而,报头偶尔也有可能出现多次,每次出现列出各自的值。可以使用此方法得到一个Enumeration,枚举报头每次出现所对应的值。b)获取主请求行自身的信息,同样是使用HttpServletRequest提供的方法:i.getMethod返回主请求方法(一般是GET或POST,也有可能是HEAD,PUT和DELETE方法)ii.getRequestURI返回URL中主机和端口之后,但在表单数据之前的部分。例:=jsp,getRequestURI返回“/servlet/search.BookSearch”。iii.getQueryString返回表单数据。=jsp,getQueryString返回“subject=jsp”。iv.getProtocol返回请求行的第三部分,一般为HTTP/1.0或HTTP/1.1。c)了解HTTP1.1请求报头i.Accept:这个报头指明浏览器或其他客户程序能够处理的MIME类型。ii.Accept-Charset:标明浏览器可以使用的字符集(如ISO-8859-1)。iii.Accept-Encoding:详细列出客户端能够处理的编码类型。gzip或compress是二种最常见的值。iv.Accept-Language:列出客户程序首选的语言。v.Authorization:在访问密码保护的Web页面时,客户用这个报头来标识自己的身份。vi.Connection:标明客户是否能够处理持续性HTTP连接。持续性连接允许客户或其他浏览器在单个socket中读取多个文件(例如HTML文件及相关的几幅图像),从而节省协商几个独立连接所需的开销。服务器只在读完HTTP请求之后,才会调用servlet。servlet的工作只是使服务器能够使用持续性连接;servlet通过