Servlet部分
servlet
是如何被处理的?
1. Servlet其实就是java类,
2. 因为java开发平台的默认包中没有包含可以处理servlet的相关包,所以要使用server开发商开发的包(tomcat,javaserver web development kit,)。
3. 当然java编译器要识别这些包,包(通常是jar形式)的路径设置要符合class path的规范。
4. 之后,写好的servlet就可以用java编译器编译成class文件了。
5. 为了让server运行class文件,要根据server的要求将class文件放到指定目录,这样才能被server识别。
比如在tomcat3.1中的特定路径:
•
install_dir/webapps/ROOT/
WEB
-
INF
/classes
Standard location for servlet classes.
• install_dir/classes
Alternate location for servlet classes.
• install_dir/lib
Location for JAR files containing classes.
另外,可以配置你指定的路径为class文件所在目录。
其实,多说server都应该有这三种路径:
[1] 经常改变的servlet的class的目录;
[2] 不常改变的servlet的class的目录;
[3] 不常改变的servlet的jar形式的目录;
6. 然后调用servlet,通常会用这种格式。
http://host/servlet/ServletName
.
7. 如果servlet要生成html,有两个额外步骤:
[1] 告诉浏览器将返回一个html。
[2] 用println输出一个合法的html。
注意:虽然
html
是
servlet
返回得最多的一种格式的文档,但是
servlet
还是可以返回其他类型的文档的。
另外,在用PrintWriter返回内容之前,要先设置response headers。这是因为html的response应该以status line,headers,a blank line,文档,这样的顺序。但是因为server可以缓存headers,所以status line可以在header之后。因为PrintWriter没有缓存文档,所以当开始使用PrintWriter就没有办法返回去设置header了。虽然现在对文档也可以缓存,但是为了方便和准确,按照顺序来没有错。
8. 为了管理servlet,使用package是相当必要的。在package中的servlet要这样调用:
http://host/servlet/packageName.ServletName
9.
1 servlet的基本结构
init()
doGet()
doPost()
doGet/doPost:
a) 用
request读http header/data
b) 用
response写http返回的status code/headers
c) 用
PrintWriter写html
2 single servlet-àpackage servletàset classpath for the packageàinvoke servlet
3 servlet的编译与运行
Most servers have three distinct locations for servlet classes, as detailed
below.
1.
A directory for frequently changing servlet classes.
With Tomcat 3.0,place servlets in
install_dir
/webpages/WEB-INF/classes
.
2.
A directory for infrequently changing servlet classes.
With Tomcat5.0(maybe):install_dir/server/classes
With tomcat6.0(hasn’t found)
3.
A directory for infrequently changing servlets in JAR files.
With tomcat 6.0:install_dir/lib
在设计阶段:
配置好服务器,将servlet放在规定的地方,就可以编译servlet。
Tomcat 5 supports the servlet API 2.4; the JAR file that you need on the classpath is located at
<Tomcat-5-installation-directory>/common/lib/servlet-api.jar.
在产品阶段:
为了避免重名,引入包规则。
通常将
html做为servlet的前台形式,所以要确定服务器规定的html的位置。而jsp可以放在任何html可以放的位置。
4由jsp或servlet生成的html如果要验证,
the two most popular on-line validators are the ones from the World Wide Web Consortium
(
http://validator.w3.org/
) and from the Web Design Group
(
http://www.htmlhelp.com/tools/validator/
).They let you submit a
URL, then they retrieve the page, check the syntax against the formal HTML
specification, and report any errors to you. Since a servlet that generates
HTML looks like a regular Web page to visitors, it can be validated in the
normal manner unless it requires
POST
data to return its result. Remember
that
GET
data is attached to the URL, so you can submit a URL that includes
GET
data to the validators.
Tip
:如果
html
结构中的某些部分经常出现(比如
header
和
html
的大框架),可以用下面的方法来简化:
Listing 2.6
ServletUtilities.java
package coreservlets;
import javax.servlet.*;
import javax.servlet.http.*;
public class ServletUtilities {
public static final String DOCTYPE =
"<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.0 " +
"Transitional//EN/">";
public static String headWithTitle(String title) {
return(DOCTYPE + "/n" +
"<HTML>/n" +
"<HEAD><TITLE>" + title + "</TITLE></HEAD>/n");
}
...
}
Listing 2.7
HelloWWW3.java
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWWW3 extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(
ServletUtilities.headWithTitle("Hello WWW")
+
"<BODY>/n" +
"<H1>Hello WWW</H1>/n" +
"</BODY></HTML>");
}
}
5servlet的life cycle
1) servlet的创建策略是:只为一个servlet类创建一个实例,每个对servlet的请求创建一个线程。
2) Servlet被创建,调用init,初始化。
3) 对每个请求调用相应的servlet 的service方法,service调用doGet或doPost或doXXX(根据http request的类型)。
4) Server决定upload某servlet,调用其destory。
5.1 init方法
一种无参数init:
public void init() throws ServletException {
// Initialization code...
}
一种以ServletConfig为参数的init,用该参数来读取servlet-specific settings。For example,
the servlet might need to know about database settings, password files,
server-specific performance parameters, hit count files, or serialized cookie
data from previous requests.
public void init(ServletConfig config)
throws ServletException {
super.init(config);
// Initialization code...
}
用ServletConfig.getInitParameter来读取settings,估计是一系列的名值对。
注意:
[1] 对不同的server,settings的保存方式不一样。For example, with Tomcat, you embed servlet properties in
a file called web.xml, with the JSWDK you use servlets.properties, with
the WebLogic application server you use weblogic.properties, and with
the Java Web Server you set the properties interactively via the administration
console.
因此,初始化参数的读的方式一样,但写的时候不一样(server-specific)。因为不同server的settings保存方式不一样,如果要在各server间转移程序就会有问题。因此,一种实现方法:只在settings中指明保存初始化数据的文件的位置,这样可以用一种方式保存settings。
建议:初始化数据尽可能少。
[2] 有参数的init里面有个super.init(config);其作用是将servlet注册。(无参数的init是不是也该有这样的代码?)
5.2 service方法
request
àserver
àspawn a new thread and call service
àcheck http request type(get,post,put,delete,etc.)
àcall
doGet,doPost,doPut,doDelete,etc.
如果要同时处理get,post请求,就要override原来的service方法。
或者在doGet中call doPost,反之亦然。
后者好于前者的原因:(似乎就是,不override service,可以利用原有service提供的已有的特性处理一些问题。)下面是具体的原因:
1. You can add support for other services later by adding
doPut,
doTrace, etc., perhaps in a subclass. Overriding service
directly precludes this possibility.
2. You can add support for modification dates by adding a
get-
LastModified method. If you use doGet, the standard service
method uses the getLastModified method to set
Last-Modified headers and to respond properly to conditional
GET requests (those containing an If-Modified-Since
header). See Section 2.8 (An Example Using Servlet Initialization
and Page Modification Dates) for an example.
3. You get automatic support for
HEAD requests. The system just
returns whatever headers and status codes doGet sets, but omits
the page body. HEAD is a useful request method for custom
HTTP clients. For example, link validators that check a page for
dead hypertext links often use HEAD instead of GET in order to
reduce server load.
4. You get automatic support for
OPTIONS requests. If a doGet
method exists, the standard service method answers OPTIONS
requests by returning an Allow header indicating that GET,
HEAD, OPTIONS, and TRACE are supported.
5. You get automatic support for
TRACE requests. TRACE is a
request method used for client debugging: it just returns the
HTTP request headers back to the client.
5.3 doGet,doPost,doXXX
这些是servlet的核心内容。
1. 99%的情况下,只要处理(override)doGet和doPost。
2. 但是有时可以override doDelete for DELETE requests, doPut for PUT,doOptions for OPTIONS, and doTrace for TRACE.
3. 对比service方法,OPTIONS,TRACE已经被service支持了。而虽然没有doHeader,系统automatically uses the status line and header settings of doGet to answer HEAD requests.
多线程的问题:
因为servlet只有一个实例,每次的request都会产生一个thread,所以doPost,doGet等都可能会有:多个线程同时读取一个数据的问题。一种解决方法是禁止多线程的读取。
public class YourServlet extends HttpServlet
implements SingleThreadModel
{
...
}
这样,每个实例只能有一个线程。
1. 通过将request排序,每次只将一个request传递给实例的形式。
2. 产生一个实例池,其中的每个实例一次处理一个request。这种情况下,不用担心对实例变量的并发访问,但是还要处理对类变量(static)和共享数据的并发访问。
这种对并发的控制,显然会降低servlet的性能,尤其是该servlet被大量访问的情况。
Destroy方法
其作用to close database connections, halt background threads, write cookie lists or hit counts to disk, and perform other such cleanup activities.
但是基于技术和非技术的原因(
not all Web servers
are written in reliable programming languages like Java; some are written
in languages (such as ones named after letters of the alphabet) where it is
easy to read or write off the ends of arrays, make illegal typecasts, or have
dangling pointers due to memory reclamation errors. Besides, even Java
technology won’t prevent someone from tripping over the power cable running
to the computer.
)所以
不要让destory作为唯一的
将
状态
保存到
disk
的地方。
Activities like hit counting or accumulating lists of cookie values that indicate special access should also proactively write their state to disk periodically.
有几个策略可以考虑:
1. 查看html代码;
2. 如果servlet能够指出关于错误的描述性信息,那么可以将它返回client;
3. 如果server是随着系统启动的,那么可以改从命令行,或IDE环境启动,这样就可以查看到System.out.println,System.err.println等信息;
4. 使用log文件:HttpServlet有名为log的类,可以用来写日志信息;
5. 查看请求的数据是否正确;
6. 查看响应数据是否正确;
7. 重启server。
Part 3 处理Form data
1. HttpServletRequest可以利用form中的参数名,显式读取其值,HttpServletRequest.getParameter("param1")
2. HttpServletRequest可以一次读取所有参数名,然后以遍历的方式读取每个参数的值,
Enumeration paramNames =HttpServletRequest.getParameterNames();
String paramName = (String)paramNames.nextElement();
String[] paramValues =
HttpServletRequest.getParameterValues(paramName);
3. 注意处理格式不正确的form输入。
注意:html的特殊字符,如<,>,这些特殊字符在html中有自己的表示,如<,>。在servlet中,程序员在写一个返回的html时,可以正确判断是否要使用特殊字符,如果要使用,就能以html中的表示方式表示。但是有两种情况,要让程序员预测并处理是比较难的:
1. 从其他地方导入的文档里面有html的特殊字符
2. 来自的form数据中包含了特殊字符,这没法在写servlet的时候程序员处理掉。这是发生在运行时的问题,程序员不能在编程程序时把它写掉。如果对用户输入的包含特殊字符的数据不能正确处理,就很可能导致servlet的输出也是不正确的。并且这个问题还能被利用来进行跨站点的脚本攻击cross-site scripting attack。
详见:
建议:以类似如下代码的形式来处理html的特殊字符:
/** Given a string, this method replaces all occurrences of
* '<' with '<', all occurrences of '>' with
* '>', and (to handle cases that occur inside attribute
* values), all occurrences of double quotes with
* '"' and all occurrences of '&' with '&'.
* Without such filtering, an arbitrary string
* could not safely be inserted in a Web page.
*/
public static String filter(String input) {
StringBuffer filtered = new StringBuffer(input.length());
char c;
for(int i=0; i<input.length(); i++) {
c = input.charAt(i);
if (c == '<') {
filtered.append("<");
} else if (c == '>') {
filtered.append(">");
} else if (c == '"') {
filtered.append(""");
} else if (c == '&') {
filtered.append("&");
} else {
filtered.append(c);
}
}
return(filtered.toString());
}
}
• Reading HTTP request headers from servlets
• Building a table of all the request headers
• Reducing download times by compressing pages
• Restricting access with password-protected servlets
创建高效的
servlet
的一个关键是明白超文本传输协议
HTTP
。
下面将讲解,以请求头的形式,从浏览器传递到server的HTTP信息。
请求头与form数据不一样,是直接由浏览器给出,紧跟form数据之后。
下面是一个包括form数据和请求头的例子:
GET
/search?keywords=servlets+jsp HTTP/1.1
Accept: image/gif, image/jpg, */*
Accept-Encoding: gzip
Connection: Keep-Alive
Cookie: userID=id456578
Host: www.somebookstore.com
Referer: http://www.somebookstore.com/findbooks.html
User-Agent: Mozilla/4.7 [en] (Win98; U)
Request = Request-Line ;
*(( general-header ;
| request-header ;
| entity-header ) CRLF) ;
CRLF
[ message-body ] ;
参见:
这是http1.1规范的一部分,可以直接从http1.1规范
)中查看。
[2] HTTP Response Headers
[3] HTTP Tutorial(比较详细介绍了三种header,request,response,entity)
1. 最简单的方式就是:getHeader(headername),
注意:没有大小写之分。
2. 因为header中有一些部分常用,所以对应有具有的方法:
l
getCookies
The getCookies method returns the contents of the Cookie
header, parsed and stored in an array of Cookie objects. This
method is discussed more in Chapter 8 (Handling Cookies).
l
getAuthType and getRemoteUser
The getAuthType and getRemoteUser methods break the
Authorization header into its component pieces. Use of the
Authorization header is illustrated in Section 4.5 (Restricting
Access to Web Pages).
l •
getContentLength
The getContentLength method returns the value of the
Content-Length header (as an int).
l
getContentType
The getContentType method returns the value of the
Content-Type header (as a String).
l
• getDateHeader and getIntHeader
The getDateHeader and getIntHeader methods read the
specified header and then convert them to Date and int values,
respectively.
l •
getHeaderNames
Rather than looking up one particular header, you can use the
getHeaderNames method to get an Enumeration of all header
names received on this particular request. This capability is
illustrated in Section 4.2 (Printing All Headers).
l •
getHeaders
In most cases, each header name appears only once in the
request. Occasionally, however, a header can appear multiple
times, with each occurrence listing a separate value.
Accept-Language is one such example. If a header name is
repeated in the request, version 2.1 servlets cannot access the
later values without reading the raw input stream, since
getHeader returns the value of the first occurrence of the
header only. In version 2.2, however, getHeaders returns an
Enumeration of the values of all occurrences of the header.
3. 除了对请求头的获取,还可以获取第一行上(
GET
/search?keywords=servlets+jsp HTTP/1.1)的另外一些信息,
•
getMethod
The getMethod method returns the main request method
(normally GET or POST, but things like HEAD, PUT, and DELETE
are possible).
•
getRequestURI
The getRequestURI method returns the part of the URL that
comes after the host and port but before the form data. For
example, for a URL of
http://randomhost.com/servlet/search.BookSearch,
getRequestURI would return
/servlet/search.BookSearch.
•
getProtocol
Lastly, the getProtocol method returns the third part of the
request line, which is generally HTTP/1.0 or HTTP/1.1. Servletsshould usually check getProtocol before specifying
response
headers (Chapter 7) that are specific to HTTP 1.1.
1.1的headers是1.0的超集。
Accept
Accept 请求报头域用语指定客户端接受哪些类型的信息。例如: Accept: image/gif, 表明客户端希望接受 GIF 图象格式的资源; Accept: text/html, 表明客户端希望接受 html 文本。
Accept 请求报头域用语指定客户端接受哪些类型的信息。例如: Accept: image/gif, 表明客户端希望接受 GIF 图象格式的资源; Accept: text/html, 表明客户端希望接受 html 文本。
Accept-Charset
Accept-Charset 请求报头域用于指定客户端接受的字符集。例如: Accept-Charset: ios-8859-1,gb2312 。如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
Accept-Encoding
Accept-Encoding 请求报头域类似 Accept ,但是它是用于指定可接受的内容编码。例如: Accept-Encoding: gzip,default 。如果请求消息中没有设置这个域,服务器假定客户端对各种内容编码都可接受。
Accept-Language
Accept-Language 请求报头域类似于 Accept, 但是它是用于指定一种自然语言。例如: Accept-Language: zh-cn 。如果请求消息中没有设置这个域,服务器假定客户端对各种语言都可接受。
Authorization
Authorization 请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为 401( 未授权 ) ,可以发送一个包含 Authorization 请求报头域的请求,要服务器对其进行验证。
Host
Host 请求报头域主要用于指定被请求资源的 Internet 主机和端口号,它通常是从 HTTP URL 中提取出来的。
例如 :http://www.sunxin.org/index.html 。浏览器发送的请求消息中,就会包含 Host 请求报头域,如下: Host: www.sunxin.org
后面没有跟端口号,表明使用的是缺省端口号 80 ,如果端口号不是 80 ,那么就要在主机名后面加上一个冒号 (":"), 然后接上端口号,例如:
Host: www.sunxin.org:8080 。 要注意的是,在发送 HTTP 请求的时候,这个报头域是必须的。
User-Agent
User-Agent 允许客户端将它的操作系统浏览器和其他属性告诉服务器。我们上网登陆论坛的时候,往往看到些欢迎信息,其中列出了你的操作系统的名称 和版本等等信息。原因是:服务器从 User-Agent 请求报头域中获取的这些信息,自己编写浏览器可以不用这个请求报头域。服务器就无法得知了。
Accept-Charset 请求报头域用于指定客户端接受的字符集。例如: Accept-Charset: ios-8859-1,gb2312 。如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
Accept-Encoding
Accept-Encoding 请求报头域类似 Accept ,但是它是用于指定可接受的内容编码。例如: Accept-Encoding: gzip,default 。如果请求消息中没有设置这个域,服务器假定客户端对各种内容编码都可接受。
Accept-Language
Accept-Language 请求报头域类似于 Accept, 但是它是用于指定一种自然语言。例如: Accept-Language: zh-cn 。如果请求消息中没有设置这个域,服务器假定客户端对各种语言都可接受。
Authorization
Authorization 请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为 401( 未授权 ) ,可以发送一个包含 Authorization 请求报头域的请求,要服务器对其进行验证。
Host
Host 请求报头域主要用于指定被请求资源的 Internet 主机和端口号,它通常是从 HTTP URL 中提取出来的。
例如 :http://www.sunxin.org/index.html 。浏览器发送的请求消息中,就会包含 Host 请求报头域,如下: Host: www.sunxin.org
后面没有跟端口号,表明使用的是缺省端口号 80 ,如果端口号不是 80 ,那么就要在主机名后面加上一个冒号 (":"), 然后接上端口号,例如:
Host: www.sunxin.org:8080 。 要注意的是,在发送 HTTP 请求的时候,这个报头域是必须的。
User-Agent
User-Agent 允许客户端将它的操作系统浏览器和其他属性告诉服务器。我们上网登陆论坛的时候,往往看到些欢迎信息,其中列出了你的操作系统的名称 和版本等等信息。原因是:服务器从 User-Agent 请求报头域中获取的这些信息,自己编写浏览器可以不用这个请求报头域。服务器就无法得知了。
Connection
是否支持持续的http连接,
These let the client or other browser retrieve multiple files
(e.g., an HTML file and several associated images) with a single socket
connection, saving the overhead of negotiating several independent
connections.
the server
invokes the servlet only after the server has already read the HTTP
request. This means that servlets need help from the server to handle
persistent connections. Consequently, the servlet’s job is just to make it
possible for the server to use persistent connections, which is done by
sending a Content-Length response header.
Content-Encoding
Content-Encoding 实体报头域被使用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容编码,因而要获得 Content- Type 报头域中所引用的媒体类型,必须采用相应的解码机制。 Content-Encoding 主要用语记录文档的压缩方法,下面是它的一个例子: Content-Encoding: gzip 。如果一个实体正文采用了编码方式存储,在使用之前就必须进行解码。
Content-Language
Content-Language 实体报头域描述了资源所用的自然语言。 Content-Language 允许用户遵照自身的首选语言来识别和区分实体。 如果这个实体内容仅仅打算提供给丹麦的阅读者,那么可以按照如下的方式设置这个实体报头域: Content-Language: da 。
如果没有指定 Content-Language 报头域,那么实体内容将提供给所以语言的阅读者。
Content-Length
Content-Length 实体报头域用于指明正文的长度,以字节方式存储的十进制数字来表示,也就是一个数字字符占一个字节,用其对应的 ASCII 码存储传输。
要注意的是:这个长度仅仅是表示实体正文的长度,没有包括实体报头的长度。
Content-Type
content-type 通常在 response 中使用,但是当将一个文档作为 post 的数据或者使用 put request 的时候,也可以使用 content-type 。
Content-Encoding 实体报头域被使用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容编码,因而要获得 Content- Type 报头域中所引用的媒体类型,必须采用相应的解码机制。 Content-Encoding 主要用语记录文档的压缩方法,下面是它的一个例子: Content-Encoding: gzip 。如果一个实体正文采用了编码方式存储,在使用之前就必须进行解码。
Content-Language
Content-Language 实体报头域描述了资源所用的自然语言。 Content-Language 允许用户遵照自身的首选语言来识别和区分实体。 如果这个实体内容仅仅打算提供给丹麦的阅读者,那么可以按照如下的方式设置这个实体报头域: Content-Language: da 。
如果没有指定 Content-Language 报头域,那么实体内容将提供给所以语言的阅读者。
Content-Length
Content-Length 实体报头域用于指明正文的长度,以字节方式存储的十进制数字来表示,也就是一个数字字符占一个字节,用其对应的 ASCII 码存储传输。
要注意的是:这个长度仅仅是表示实体正文的长度,没有包括实体报头的长度。
Content-Type
content-type 通常在 response 中使用,但是当将一个文档作为 post 的数据或者使用 put request 的时候,也可以使用 content-type 。
Content-Type
实体报头域用语指明发送给接收者的实体正文的媒体类型。例如:
Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=GB2312
Last-Modified
Last-Modified 实体报头域用于指示资源最后的修改日期及时间。
Expires
Expires 实体报头域给出响应过期的日期和时间。通常,代理服务器或浏览器会缓存一些页面。当用户再次访问这些页面时,直接从缓存中加载并显示给用 户,这样缩短了响应的时间,减少服务器的负载。为了让代理服务器或浏览器在一段时间后更新页面,我们可以使用 Expires 实体报头域指定页面过期的时 间。当用户又一次访问页面时,如果 Expires 报头域给出的日期和时间比 Date 普通报头域给出的日期和时间要早 ( 或相同 ) ,那么代理服务器或浏览器就 不会再使用缓存的页面而是从服务器上请求更新的页面。不过要注意,即使页面过期了,也并不意味着服务器上的原始资源在此时间之前或之后发生了改变。
Expires 实体报头域使用的日期和时间必须是 RFC 1123 中的日期格式,例如:
Expires: Thu, 15 Sep 2005 16:00:00 GMT
HTTP1.1 的客户端和缓存必须将其他非法的日期格式 ( 也包括 0) 看作已过期。例如,为了让浏览器不要缓存页面,我们也可以利用 Expires 实体报头 域,设置它的值为 0 ,如下 (JSP) : response.setDateHeader("Expires",0);
Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=GB2312
Last-Modified
Last-Modified 实体报头域用于指示资源最后的修改日期及时间。
Expires
Expires 实体报头域给出响应过期的日期和时间。通常,代理服务器或浏览器会缓存一些页面。当用户再次访问这些页面时,直接从缓存中加载并显示给用 户,这样缩短了响应的时间,减少服务器的负载。为了让代理服务器或浏览器在一段时间后更新页面,我们可以使用 Expires 实体报头域指定页面过期的时 间。当用户又一次访问页面时,如果 Expires 报头域给出的日期和时间比 Date 普通报头域给出的日期和时间要早 ( 或相同 ) ,那么代理服务器或浏览器就 不会再使用缓存的页面而是从服务器上请求更新的页面。不过要注意,即使页面过期了,也并不意味着服务器上的原始资源在此时间之前或之后发生了改变。
Expires 实体报头域使用的日期和时间必须是 RFC 1123 中的日期格式,例如:
Expires: Thu, 15 Sep 2005 16:00:00 GMT
HTTP1.1 的客户端和缓存必须将其他非法的日期格式 ( 也包括 0) 看作已过期。例如,为了让浏览器不要缓存页面,我们也可以利用 Expires 实体报头 域,设置它的值为 0 ,如下 (JSP) : response.setDateHeader("Expires",0);
Several recent browsers know how to handle gzipped content, automatically uncompressing documents that are marked with the Content-Encoding
header and then treating the result as though it were the original document.
与非压缩的页面的区别:
非压缩页面用PrintWriter来写,
压缩页面:
PrintWriter out;
OutputStream out1 = response.getOutputStream();
out =
new
PrintWriter(
new
GZIPOutputStream(out1),
false
);
response.setHeader(
"content-encoding"
,
"gzip"
);//
并通知
client
压缩格式
并且最后有一个
out.close;//
是不是因为是用流方式写的,所以要
close
。
有两种方式:
form-based access control
(
servlet
需要更多的控制,
web.xml?filter?
)
l和
HTTP-based authorization
(简单)
一种基本的授权步骤:
1. Check whether there is an Authorization header. If there is
no such header, go to Step 2. If there is, skip over the word
“
basic” and reverse the base64 encoding of the remaining part.
This results in a string of the form username:password. Check
the username and password against some stored set. If it
matches, return the page. If not, go to Step 2.
(
base64 encoding
is explained in RFC 1521
,
http://www.rfc-editor.org/)
2. Return a
401
(Unauthorized) response code and a header of
the following form:
WWW-Authenticate:
BASIC realm="some-name"
This response instructs the browser to pop up a dialog box telling
the user to enter a name and password for some-name, then
to reconnect with that username and password embedded in a
single base64 string inside the Authorization header.
注意:
1 上述步骤存在
安全问题,base64 encoding可以很容易被破解。
it does not obviate
the need for SSL to thwart attackers who might be able to snoop on your
network connection
。
SSL
, or Secure Sockets Layer, is a variation of HTTP where the entire
stream is encrypted. It is supported by many commercial servers and is
generally invoked by using
https
in the URL instead of
http
. Servlets can
run on SSL servers just as easily as on standard servers, and the encryption
and decryption is handled transparently before the servlets are invoked.
2
sun.misc.BASE64Decoder
sun提供上述类对base64解码,这是非标准包,所以部署程序时,确保包含该类。
http
响应头
response header
的意义:
给出server的一些信息,以及指示下一步的操作。
server端对request的返回通常有几个部分:
l a status line,
l some response headers,
l a blank line,
l and the document.
一个简单的例子:
HTTP/1.1 200 OK
//status line
Content-Type: text/plain
//response headers
//blank line
Hello World
//doc
Request = Status-Line ;
*(( general-header ;
| response-header ;
| entity-header ) CRLF) ;
CRLF
[ message-body ] ;
对状态行,包括:
l http version,
l 状态代码,
l 相应message,其实算是code的说明,注意:server可以修改该message,而不是标准(http1.1)的message。
对响应头,只有
content-type
是必须的。
状态行和响应头,可以被
server
利用来做很多事情,如:
they can forward the user to
other sites; indicate that the attached document is an image, Adobe Acrobat
file, or HTML file; tell the user that a password is required to access the document;
and so forth.
对文档部分:虽然大多数响应有文档,但是也有没有文档的。
5.1.1 指定状态代码
因为状态行中的http servion由server指定,
而message直接与status code相关,
所以要做的事情就是指定
status code。
通过
HttpServletResponse.setStatus设定status code。如果server还返回了documents,一定要先设置status code,再call PrintWriter来返回doc。
这样做,有深刻的原因:()
(有点乱,到底是header还是status code可以buffer?)
理论上来说,应该按照status codes,http headers,docs的顺序call相关的方法产生相应的东东。但是buffer的概念所以,产生的顺序可以变化。
因为,servlet可
buffer http headers
(用
setHeader
),所以http headers可以在任何顺序产生,servlet buffer它,然后一次性send,其他则不行。
Servlet2.1里
PrintWriter不能buffer,所以当开始使用PrintWriter来output时,就不能再设置header了。
Servlet2.2中
PrintWriter的输出允许buffer。
You can use the
getBufferSize
method of
HttpServletResponse
to determine the size,
or use
setBufferSize
to specify it. In version 2.2 with buffering enabled,
you can set status codes until the buffer fills up and is actually sent to the
client. If you aren’t sure if the buffer has been sent, you can use the
isCommitted
method to check.
通常的设置方式:setStatus,
两个专门的设置方法:
• public void sendError(int code, String message)
The sendError method sends a status code (usually 404) along
with a short message that is automatically formatted inside an
HTML document and sent to the client.
•
public void sendRedirect(String url)
The sendRedirect method generates a 302 response along
with a Location header giving the URL of the new document.
With servlets version 2.1, this must be an absolute URL. In
version 2.2, either an absolute or a relative URL is permitted
and the system automatically translates relative URLs into
absolute ones before putting them in the Location header.
问题:意义不明?
Setting a status code does not necessarily mean that you don’t need to
return a document. For example, although most servers automatically generate
a small “File Not Found” message for 404 responses, a servlet might want
to customize this response. Remember that if you do send output, you have
to call
setStatus or
sendError
first.
5.2.2 http1.1的状态码,定义在RFC 2616
A good understanding of these codes can dramatically
increase the capabilities of your servlets
。
简单的描述:
|
五类status code
•
100-199
Codes in the 100s are informational, indicating that the client
should respond with some other action.
•
200-299
Values in the 200s signify that the request was successful.
•
300-399
Values in the 300s are used for files that have moved and usually
include a Location header indicating the new address.
•
400-499
Values in the 400s indicate an error by the client.
•
500-599
Codes in the 500s signify an error by the server.
100 (Continue)
If the server receives an Expect request header with a value of
100-continue, it means that the client is asking if it can send an
attached document in a follow-up request. In such a case, the server
should either respond with status 100 (SC_CONTINUE) to tell the client
to go ahead or use 417 (Expectation Failed) to tell the browser it
won’t accept the document. This status code is new in HTTP 1.1.
101 (Switching Protocols)
A 101 (SC_SWITCHING_PROTOCOLS) status indicates that the server will
comply with the Upgrade header and change to a different protocol.
This status code is new in HTTP 1.1.
200 (OK)
A value of 200 (SC_OK) means that everything is fine. The document follows
for GET and POST requests.
This status is the default for servlets; if
you don’t use setStatus, you’ll get 200.
201 (Created)
A status code of 201 (SC_CREATED) signifies that the server created a
new document in response to the request; the Location header should
give its URL.
202 (Accepted)
A value of 202 (SC_ACCEPTED) tells the client that the request is being
acted upon, but processing is not yet complete.
203 (Non-Authoritative Information)
A 203 (SC_NON_AUTHORITATIVE_INFORMATION) status signifies that the
document is being returned normally, but some of the response headers
might be incorrect since a document copy is being used. This status
code is new in HTTP 1.1.
204 (No Content)
A status code of 204 (SC_NO_CONTENT) stipulates that the browser
should continue to display the previous document because no new document
is available.
This behavior is useful if the user periodically
reloads a page by pressing the “Reload” button, and you can determine
that the previous page is already up-to-date. For example, a servlet
might do something like this:
int pageVersion =
Integer.parseInt(request.getParameter("pageVersion"));
if (pageVersion >= currentVersion) {
response.setStatus(response.SC_NO_CONTENT);
} else {
// Create regular page
}
However, this approach does not work for pages that are automatically
reloaded via the Refresh response header or the equivalent <
META
HTTP-EQUIV="Refresh" ...> HTML entry, since returning a 204 status
code stops future reloading.
JavaScript-based
automatic reloading
could still work in such a case, though.See the discussion of Refresh in
Section 7.2 (HTTP 1.1 Response Headers and Their Meaning) for
details.
205 (Reset Content)
A value of 205 (SC_RESET_CONTENT) means that there is no new document,
but the browser should reset the document view.
This status
code is used to force browsers to clear form fields. It is new in HTTP
1.1.
206 (Partial Content)
A status code of 206 (SC_PARTIAL_CONTENT) is sent when the server
fulfills a partial request that includes a Range header. This value is new
in HTTP 1.1.
300 (Multiple Choices)
A value of 300 (SC_MULTIPLE_CHOICES) signifies that the requested
document can be found several places, which will be listed in the
returned document. If the server has a preferred choice, it should be
listed in the Location response header.
301 (Moved Permanently)
The 301 (SC_MOVED_PERMANENTLY) status indicates that the requested
document is elsewhere; the new URL for the document is given in the
Location response header. Browsers should automatically follow the
link to the new URL.
302 (Found)
This value is similar to 301, except that the URL given by the Location
header should be interpreted as a temporary replacement, not a permanent
one. Note: in HTTP 1.0, the message was Moved Temporarily
instead of Found, and the constant in HttpServletResponse is
SC_MOVED_TEMPORARILY, not the expected SC_FOUND.
Status code 302 is
very useful because browsers automatically follow
the reference to the new URL given in the Location response header.
It is so useful, in fact, that
there is a special method for it, sendRedirect.
Using response.sendRedirect(url) has a couple of advantages
over using
response.setStatus(response.SC_MOVED_TEMPORARILY) and
response.setHeader("Location", url).
First, it is shorter and easier.
Second, with sendRedirect, the servlet automatically builds a
page containing the link to show to older browsers that don’t automatically follow redirects.
Finally, with version 2.2 of servlets (the version
in J2EE), sendRedirect can handle relative URLs, automatically
translating them into absolute ones. You must use an absolute URL in
version 2.1, however.
If you redirect the user to another page within your own site, you should
pass the URL through
the encodeURL method of HttpServletResponse.
Doing so is a simple precaution in case you ever use
session
tracking based on
URL-rewriting.
URL-rewriting is a way to track users who have cookies disabled while they are at your site. It is implemented
by adding extra path information to the end of each URL, but the servlet
session-tracking API takes care of the details automatically.
If you redirect users to a page within your site, plan ahead for session
tracking by using
response.sendRedirect(response.encodeURL(url))
,
rather than just
response.sendRedirect(url)
.
问题:encodeURL的到底怎么用的?
This status code is sometimes used interchangeably with 301. For example,
if you erroneously ask for http://host/~user (missing the trailing
slash), some servers will reply with a 301 code while others will use 302.
Technically, browsers are only supposed to automatically follow the
redirection if the original request was GET. For details, see the discussion
of the 307 status code.
303 (See Other)
The 303 (SC_SEE_OTHER) status is similar to 301 and 302,
except that
if the original request was POST, the new document (given in the
Location header) should be retrieved with GET. This code is new in
HTTP 1.1.
304 (Not Modified)
When a client has a cached document, it can perform a conditional
request by supplying an If-Modified-Since header to indicate that it
only wants the document if it has been changed since the specified date.
A value of 304 (SC_NOT_MODIFIED) means that the cached version is
up-to-date and the client should use it. Otherwise, the server should
return the requested document with the normal (200) status code. Servlets
normally should not set this status code directly. Instead, they
should implement the getLastModified method and let the default
service method handle conditional requests based upon this modification
date. An example of this approach is given in Section 2.8 (An Example
Using Servlet Initialization and Page Modification Dates).
305 (Use Proxy)
A value of 305 (SC_USE_PROXY) signifies that the requested document
should be retrieved via the proxy listed in the Location header. This
status code is new in HTTP 1.1.
307 (Temporary Redirect)
The rules for how a browser should handle a 307 status are identical to
those for 302. The 307 value was added to HTTP 1.1 since many browsers
erroneously follow the redirection on a 302 response even if the
original message is a POST. Browsers are supposed to follow the redirection
of a POST request only when they receive a 303 response status.
This new status is intended to be unambiguously clear: follow redirected
GET
and POST requests in the case of 303 responses; follow redirected
GET but
not POST requests in the case of 307 responses. Note:
For some reason there is no constant in HttpServletResponse corresponding
to this status code. This status code is new in HTTP 1.1.
There is no
SC_TEMPORARY_REDIRECT constant in
HttpServletResponse, so you have to use 307 explicitly.
400 (Bad Request)
A 400 (SC_BAD_REQUEST) status indicates bad syntax in the client
request.
401 (Unauthorized)
A value of 401 (SC_UNAUTHORIZED) signifies that the client tried to
access a password-protected page without proper identifying information
in the Authorization header. The response must include a
WWW-Authenticate header. For an example, see Section 4.5, “Restricting
Access to Web Pages.”
403 (Forbidden)
A status code of 403 (SC_FORBIDDEN) means that the server refuses to
supply the resource, regardless of authorization. This status is often the
result of bad file or directory permissions on the server.
404 (Not Found)
The infamous 404 (SC_NOT_FOUND) status tells the client that no
resource could be found at that address. This value is the standard “no
such page” response. It is such a common and useful response that
there is a special method for it in the HttpServletResponse class:
sendError("message"). The advantage of sendError over setStatus
is that, with sendError, the server automatically generates an error
page showing the error message. Unfortunately, however, the default
behavior of Internet Explorer 5 is to ignore the error page you send
back and displays its own, even though doing so contradicts the HTTP
specification. To turn off this setting, go to the Tools menu, select Internet
Options, choose the Advanced tab, and make sure “Show friendly
HTTP error messages” box is not checked. Unfortunately, however, few
users are aware of this setting, so this “feature” prevents most users of
Internet Explorer version 5 from seeing any informative messages you
return. Other major browsers and version 4 of Internet Explorer properly
display server-generated error pages. See Figures 6–3 and 6–4 for
an example.
405 (Method Not Allowed)
A 405 (SC_METHOD_NOT_ALLOWED) value indicates that the request
method (GET, POST, HEAD, PUT, DELETE, etc.) was not allowed for this
particular resource. This status code is new in HTTP 1.1.
406 (Not Acceptable)
A value of 406 (SC_NOT_ACCEPTABLE) signifies that the requested
resource has a MIME type incompatible with the types specified
by the client in its Accept header. See Table 7.1 in Section 7.2
(HTTP 1.1 Response Headers and Their Meaning) for the names
and meanings of the common MIME types. The 406 value is new in
HTTP 1.1.
407 (Proxy Authentication Required)
The 407 (SC_PROXY_AUTHENTICATION_REQUIRED) value is similar
to 401, but it is used by proxy servers. It indicates that the client must
authenticate itself with the proxy server. The proxy server returns a
Proxy-Authenticate response header to the client, which results
in the browser reconnecting with a Proxy-Authorization request
header. This status code is new in HTTP 1.1.
408 (Request Timeout)
The 408 (SC_REQUEST_TIMEOUT) code means that the client took too
long to finish sending the request. It is new in HTTP 1.1.
409 (Conflict)
Usually associated with PUT requests, the 409 (SC_CONFLICT) status is
used for situations such as an attempt to upload an incorrect version of a
file. This status code is new in HTTP 1.1.
410 (Gone)
A value of 410 (SC_GONE) tells the client that the requested document
is gone and no forwarding address is known. Status 410 differs from
404 in that the document is known to be permanently gone, not just
unavailable for unknown reasons, as with 404. This status code is new
in HTTP 1.1.
411 (Length Required)
A status of 411 (SC_LENGTH_REQUIRED) signifies that the server cannot
process the request (assumedly a POST request with an attached document)
unless the client sends a Content-Length header indicating the
amount of data being sent to the server. This value is new in HTTP 1.1.
412 (Precondition Failed)
The 412 (SC_PRECONDITION_FAILED) status indicates that some precondition
specified in the request headers was false. It is new in HTTP
1.1.
413 (Request Entity Too Large)
A status code of 413 (SC_REQUEST_ENTITY_TOO_LARGE) tells the client
that the requested document is bigger than the server wants to handle
now. If the server thinks it can handle it later, it should include a
Retry-After response header. This value is new in HTTP 1.1.
414 (Request URI Too Long)
The 414 (SC_REQUEST_URI_TOO_LONG) status is used when the URI is
too long. In this context, “URI” means the part of the URL that came
after the host and port in the URL. For example, in
http://www.y2k-disaster.com:8080/we/look/silly/now/, the
URI is /we/look/silly/now/. This status code is new in HTTP 1.1.
415 (Unsupported Media Type)
A value of 415 (SC_UNSUPPORTED_MEDIA_TYPE) means that the request
had an attached document of a type the server doesn’t know how to
handle. This status code is new in HTTP 1.1.
416 (Requested Range Not Satisfiable)
A status code of 416 signifies that the client included an unsatisfiable
Range header in the request. This value is new in HTTP 1.1. Surprisingly,
the constant that corresponds to this value was omitted from
HttpServletResponse in version 2.1 of the servlet API.
In version 2.1 of the servlet specification, there is no
SC_REQUESTED_RANGE_NOT_SATISFIABLE constant in
HttpServletResponse, so you have to use 416 explicitly. The constant
is available in version 2.2 and later.
417 (Expectation Failed)
If the server receives an Expect request header with a value of
100-continue, it means that the client is asking if it can send an
attached document in a follow-up request. In such a case, the server
should either respond with this status (417) to tell the browser it won’t
accept the document or use 100 (SC_CONTINUE) to tell the client to go
ahead. This status code is new in HTTP 1.1.
500 (Internal Server Error)
500 (SC_INTERNAL_SERVER_ERROR) is the generic “server is confused”
status code. It often results from CGI programs or (heaven forbid!)
servlets that crash or return improperly formatted headers.
501 (Not Implemented)
The 501 (SC_NOT_IMPLEMENTED) status notifies the client that the
server doesn’t support the functionality to fulfill the request. It is used,
for example, when the client issues a command like PUT that the server
doesn’t support.
502 (Bad Gateway)
A value of 502 (SC_BAD_GATEWAY) is used by servers that act as proxies
or gateways; it indicates that the initial server got a bad response from
the remote server.
503 (Service Unavailable)
A status code of 503 (SC_SERVICE_UNAVAILABLE) signifies that the
server cannot respond because of maintenance or overloading. For
example, a servlet might return this header if some thread or database
connection pool is currently full. The server can supply a Retry-After
header to tell the client when to try again.
504 (Gateway Timeout)
A value of 504 (SC_GATEWAY_TIMEOUT) is used by servers that act as
proxies or gateways; it indicates that the initial server didn’t get a timely
response from the remote server. This status code is new in HTTP 1.1.
505 (HTTP Version Not Supported)
The 505 (SC_HTTP_VERSION_NOT_SUPPORTED) code means that the
server doesn’t support the version of HTTP named in the request line.
This status code is new in HTTP 1.1.
• A servlet that uses status codes to redirect users to other sites and to report errors
part 6 generating server response:http response headers
用HttpServletResponse.setHeader
必须在返回实际的文档前,设置header。即必须在使用PrintWriter或
OutputStream传递文档前使用setHeader。在serlvet2.2中,PrinterWrite可以使用buffer,因此可以设置header直到buffer第一次flush前,都是可以的。
特定的方法:
setDateHeader
setIntHeader
有时会对同一类型的header设置多个实例,如Accept,Set-Cookie都会有多个,因
此应该使用
addHeader,
addIntHeader,
addDateHeader,
另外,为了方便还有如下方法的存在:
setContentType,
setContentLength,
addCookie,
sendRedirect,
参见:
另,下面这个地址讲了request和response共用的,私有的header,以及entity headers,
1. 一个servlet可以同时处理多个并发的连接,每个连接是一个thread。所以当一个thread结束,新的thread生成的时候,新thread可以看到前一个thread的部分运算结果。
2. servlet能比较容易地在多个请求间保存状态,这一点对cgi和很多cgi的替代者来说是比较难的。一个servlet只有一个实例被创建,每一个对该servlet的请求都生成一个thread,因此在多个请求间共享的数据可以保存在servlet的实例变量中。因此可以保存最常使用的n个请求的结果。当然对共享数据存在同步等常规问题。
3. Servlet还可以将存放状态的一致性数据放在ServletContext对象中。这种方式与第二种方式的区别是ServletContext对象对servlet引擎中的所有servlet都是可访问的。
有这样一个例子,
有类PrimeNumber,类PrimeList,类Primes,目的是获取numPrimes个质数prime,且质数至少numDigits位。
1. PrimeNumber是一个servlet,收到带参数numPrimes和numDigits的请求。
2. 这两个参数被转换为integer。
3. 根据转换后的两个整数,在方法findPrimeList中查找PrimeNumber中的Vector(该Vector由一组PrimeList组成,每个PrimeList都是一次已经存在或正在根据这两个参数进行的计算结果)是否包含这两个整数对应的数据。
4. 如果存在,就直接返回找到的值。
5. 如果不存在,创建新的PrimeList(由numPrimes,numDigits,一组质数组成),并加到Vector中。
6. 检查这个PrimeList是否将符合条件的质数都加进去了(因为,现在的环境是并发的,假设客户A以2,3为参数发请求,servlet在Vector中没有找到相应的PrimeList。这时需要新建一个PrimeList加入Vector,并计算出满足2,3这两个参数的值加到PrimeList中。如果在PrimeList创建完成并加到Vector中之后,计算出满足2,3参数的值之前,客户B同样以2,3为参数发出请求,这时servlet在Vector中找到了相应的PrimeList,但是PrimeList还没有数据,这就是“检查这个PrimeList是否将符合条件的质数都加进去了”,这个检查对客户A对应的thread没有意义,但是对客户B对应的thread就是必须而有意义的。)
7. 如果还没有,就向客户端发Refresh的header,让它5秒钟之后再回来取数据。
8. 如果有了数据,就返回给客户端。
值得注意的一个问题是:上述问题的编程中广泛使用了
synchronized
这个特性,详见代码。
如果一个页面中带有<img><applet>这样的标志,就是说需要下载图片和applet,那么在html文档被传到客户端之后,就需要传递图片和applet了。传递html文档需要建立一个socket,一个socket就有一个conneciton,在传递图片和applet时,对每个图片和applet都要建立一个socket,这个显然比较耗资源。
因此,使用keep-alive在servet和client两者间约定,在传递完文档之后,还是用这个传文档的socket来传图片和applet,但是要正确指定图片和applet的字节数,用setContentLength,
注意:
在返回响应之前调用setContentLength,
不正确的字节数可能会带来问题。
除了返回html文档之后,servlet还可以返回多种类型的文档,比如gif。
如下5步:
1. Create an Image.
You create an Image object by using the createImage method
of the Component class. Since server-side programs should not
actually open any windows on the screen, they need to explicitly
tell the system to create a native window system object, a process
that normally occurs automatically when a window pops
up. The addNotify method accomplishes this task. Putting this
all together, here is the normal process:
Frame f = new Frame();
f.addNotify();
int width = ...;
int height = ...;
Image img = f.createImage(width, height);
2. Draw into the Image.
You accomplish this task by calling the Image’s getGraphics
method and then using the resultant Graphics object in the
usual manner. For example, with JDK 1.1, you would use various
drawXxx and fillXxx methods of Graphics to draw
images, strings, and shapes onto the Image. With the Java 2
platform, you would cast the Graphics object to Graphics2D,
then make use of Java2D’s much richer set of drawing operations,
coordinate transformations, font settings, and fill patterns
to perform the drawing. Here is a simple example:
Graphics g = img.getGraphics();
g.fillRect(...);
g.drawString(...);
3. Set the Content-Type response header.
As already discussed, you use the setContentType method of
HttpServletResponse for this task. The MIME type for GIF
images is image/gif.
response.setContentType("image/gif");
4. Get an output stream.
As discussed previously, if you are sending binary data, you
should call the getOutputStream method of HttpServlet-
Response rather than the getWriter method.
OutputStream out = response.getOutputStream();
5. Send the Image in GIF format to the output stream.
Accomplishing this task yourself requires quite a bit of work.
Fortunately, there are several existing classes that perform this
operation. One of the most popular ones is Jef Poskanzer’s
GifEncoder class, available free from
http://www.acme.com/java/. Here is how you would use this
class to send an Image in GIF format:
try {
new GifEncoder(img, out).encode();
} catch(IOException ioe) {
// Error message
}
1. 在购物网站或电子商务网站上的整个交易过程中对用户进行识别。
2. 保存用户名和密码,避免重复输入的问题。
3. 个性化设置一个站点,像google可以设置个性化主页,
4. 利用cookie记录用户在网上的某些行为,以针对性投放广告。
虽然cookies没有严重的安全问题,并且可以控制cookies总的大小,不会对硬盘造成压力,但是却存在隐私问题privacy。
1. 搜索引擎可能会记住用户经常搜索的topics,更遭的是cookies可能被多个网站共享了。
2. 别人使用记录了你的cookies的机器时,显然会有一些privacy问题。
如果出于上述原因,cookies被用户关掉,那么影响是:
1. 用户不能体验利用cookies带来的附加效果。
2. 程序员必须注意不能使用cookies处理敏感问题,
• The Cookie API
1. cookie通过response header被返回client
Cookie userCookie = new Cookie("user", "uid1234");
userCookie.setMaxAge(60*60*24*365); // 1 year
response.addCookie(userCookie);
2. 用getCookie可以将所有cookie返回一个Cookie对象数组,
对每个Cookie对象用getName检查其名字是否是你要的,
然后用getValue,
cookie除了name和value外,还有属性attribute,每个attribute都有相应的读取方法:setXxxx,getXxxx
1. comment
2. domain
3. maxAge
4. path
5. secure
6. version,
7. 还能对name和value操作:setName,setValue
http是无状态的协议,在需要记录状态的情况下,(典型的就是购物网站,需要记录下用户已经在购物车中放了哪些物品)就有问题了。
有三种方式来记录状态:
1. cookies,
将cookies用于session的话,其privacy的问题就比较严重了。
2. URL重写rewriting,
通过在url后加上额外的数据来标识一个session。
但是同样有cookies一样的privacy问题。
3. 隐藏的form字段。
通过在form中加入hidden的字段来存放session信息。但问题是这招只对动态生成的页面有用。
4. servlet给出了一个技术方案:HttpSession的api。建立在cookies和url重写之上的。
实际上,多数的server都使用cookies,当cookies被禁用的时候自动转向url重写。Servlet对程序员封装了cookies和url重写。
在servlet中使用session很简单,包括:
1. 查找当前请求中的session对象,
2. 创建新的session对象,
3. 在session中查找信息,
4. 在session中存信息,
5. 清理完成的,或被放弃的session,
6. 将session信息加到url中。
Session基础:
1. Servlet用session对象HttpSession来记录和检索信息,这些信息是对象的方式。即HttpSession通过保存一系列对象来保存状态。
2. Servlet使用getSession获取当前的session,getSession必须在给client发送响应前调用。
3. 用setAttribute将有信息的对象绑定到HttpSession上。
4. 用getAttribute和removeAttribute来操作HttpSession上的数据对象。
5. 当session在一定时间不是active的,就会被server关闭。也可以有servlet显结束。
关于session的超时问题:
这里有个时间:当session多少时间不active的时候需要terminate整个session。
一是在web.xml中设置,以分钟为单位,
一是在HttpSession.setMaxInactiveInterval设置,以秒为单位。
获取session更多的信息:
isNew,
invalidate:人为结束session,
getCreationTime,
getLastAccessedTime,
getId
当用户第一次访问时,会被分配一个HttpSession对象和一个会话ID。
如果使用url重写技术,那么要显式地将session信息加到url后面,这时使用
encodeURL,encodeRedirectURL将session信息加到url后面,而不是手动添加。
当url被嵌到servlet生产的html文档内部的时候,使用encodeURL,
当使用sendRedirect时需要session信息的话,使用encodeRedictURL来处理。
jsp的构成元素,
1. 除了html元素外,还有:
2. scripting element:指定java代码,
3. directive:控制jsp将转换而成的servlet的结构,
4. action:指定要使用的component,或者控制jsp引擎的行为。
关于scripting element:
1. <%= expression>,表达式还可以使用xml格式:<jsp:expression>java expression</jsp:expression>
2. <% code %>,可以用xml的格式:<jsp:script>code</jsp:script>
3. <!% code %>:全局变量的声明
template text:
1. jsp中的html代码被称为template text,
2. 一般被直接传递给client。
Jsp注释和html注释的区别:
Jsp:<%-- --%>
Html:<!-- -->
Jsp注释不会出现在最后传递给client的结果文档中,html的注释会。
预定义的变量:
request,
response,
session,
out:PrintWriter。
Application:getServletConfig().getContext()
Config:ServletConfig,
pageContext:
page:
在jsp中,你可以在不同的地方设置response header,或status code。这与servlet不同。
page,
通过import类,定制servlet的superclass,设置content type等来控制serlvet的结构。
其位置是任何位置。
include,
导入文件,
taglib
page:
[1] 语法:
<%@ page %>
<jsp:directive.page />
[2] 作用:
指定jsp生成的servlet的父类,
import的类,
是否使用session对象,
是否能处理一个以上的请求isThreadSafe,
异常发生时指向哪个网页:errorPage,
指定MIME类型和编码方式:contentType,
通过指定MIME为application/vnd.ms-excel,可以很容易返回excel文件,有两个方法:
[1] <%@ page contentType="application/vnd.ms-excel" %>
<%-- Note that there are tabs, not spaces, between columns. --%>
1997 1998 1999 2000 2001 (Anticipated)
12.3 13.4 14.5 15.6 16.7
![](https://p-blog.csdn.net/images/p_blog_csdn_net/yethyeth/ef72f00b96444bd9aab2248d21068505.png)
[2] 用html的table来返回excel
使用使用EL表达式,isELIgnored
1. 语法:
<%@ include file=””%>
<jsp:directive.include file=””/>
2. include包含的文件是静态的,url不能是变量,也不能带参数。如helloworld.jsp?var=value。
3. 使用include指令的时候,文件的包含发生在jsp转换为servlet的时候。因此被包含的当被包含的文件发生变化的时候,包含它的jsp必须update,似乎要手动。
4. 使用include的action的时候<jsp:include>,包含发生在clinet请求的时候,因此文件的改变可以被及时反映出来。但是这时的文件不能包含jsp内容。但是似乎现在可以了?
1. 语法:
<%@ taglib uri=”” prefix=”” %>
<jsp:directive.taglib uri=”” prefix=”” />
区别大小写,有20多个action:
1. 第一类:跟bean有关
<jsp:useBean>
<jsp:setProperty>
<jsp:getProperty>
2. 第二类:
<jsp:include>
在jsp中包含applet。注意:如果使用applet标签可能没有用,因为不同的浏览器都有自己内建的vm。你不得不对IE使用OBJECT,而对netscape使用EMBED。但是在jsp中使用<jsp:plugin>可以让server为你将不同的浏览器区别对待。
<jsp:param>:用在<jsp:include><jsp:forward><jsp:plugin>中传递参数。
<jsp:params>。
<jsp:forward>
<jsp:element>:动态定义xml元素标签
<jsp:body>
<jsp:attribute>:
用在<jsp:element>中来定义element的属性,
或者也可以定义标准的tag和自定义tag的属性。
<jsp:fallback>
3. 第三类:用在jsp document中
<jsp:root>
<jsp:declaration>
<jsp:scriptlet>
<jsp:scriptlet>
<jsp:expression>
<jsp:text>
<jsp:output>
4. 第四类:动态生成xml元素标签的值
<jsp:attribute>
<jsp:body>
<jsp:element>
5. 第五类:用在tag file中
<jsp:invoke>
<jsp:doBody>
java bean
是
java
类,并且具有三个特性:
1. public类,
2. 具有无参的constructor,
3. property的访问方法,必须是setXxxx,getXxxx。
<jsp:useBean id=”” scope=”” class=”” beanName=”” type=””>
id:在jsp中的标识
scope:page,request,session,application
class:bean所实例化的类,
beanName:可以指向一个类,或一个包含多个bean的文件。
Type:给bean指定一个不同的类型,比如其实际类的父类。
<jsp:setProperty>
的四种方式:
1. <jsp:setProperty name=”beanName” property=”*” />
2. <jsp:setProperty name=”beanName” property=”aProperty” />
只给bean中指定的属性aProperty赋值。
3. <jsp:setProperty name=”beanName” property=”aProperty” param=”paramName”/>
将从client传来的参数名为paramName的参数赋值给bean中名为aProperty的属性。
4. <jsp:setProperty name=”beanName” property=”aProperty” value=”aValue”/>
<jsp:getProperty>
javabean
的范围:
1. page
javabean只在页面内有效
2. request
javabean除了在当前页面外,当使用<jsp:include><jsp:forward>时,被include和forward的页面也可以使用该bean。
3. session
写一个记录登陆页面次数的jsp的时候,如果将计算次数的javabean设为session的,那么就可以在每次刷新之后计数增加1。
4. application
只要服务器不重新启动就有效。
关于bean的创建的两个问题:
1. 使用<jsp:useBean>的时候,会根据id和scope检查是否已存在这个bean,存在才创建,否则直接将引用赋值。如果已存在的bean的类型比当前声明特殊,即是当前声明的后代,那么就做一个类型转换。
2. 可以在声明useBean的时候,做多一些的工作,比如:
<jsp:useBean ...>
statements
</jsp:useBean>
显式删除
javabean
:
根据bean的scope
pageContext.removeAttribute();
session.removeAttribute()
或利用EL和标签库。
<c:remove var=”beanName” scope=”page” />
功能与javabean类似,但是标签库:
1. 能更方便地处理网页内容的数据。
2. 相对网页开发者,更容易上手,因为是<mytag></mytag>的形式。
制作标签的步骤:
1. 定义标签的处理方式,即某个标签应该做的事情。
用标签处理类:
该类必须继承TagSupport等标签处理类,
然后覆盖doStartTag方法,该方法就是该标签应作的处理。在doStartTag的最后要返回一个值指示:处理完毕,下一步应该怎样做。
javax.servlet.jsp.tagext中定义了三类接口:
BodyTag,Tag,IterationTag,
JspTag,SimpleTag,
DynamicAttributes,TryCatchFinally。
一般开发Tag必要继承下面两个类之一:
TagSupport类实现了Tag,IterationTag,JspTag,Serializable接口,
BodyTagSupport类继承了TagSupport类,并实现了BodyTag接口。
要处理tag里面的内容的话,需要使用这个类。
SimpleTagSupport类:简化了tag的开发,似乎是用来替代上面两个类的。
TagExtraInfo类,
VariableInfo类,
较少使用的:TagLibraryInfo,TagInfo,TagAttributeInfo:通常是jsp
容器使用的。
用
tag file
:
可以利用jsp2中的tag file以jsp语法来制作tag,而不是用java类。
实际上tag file将翻译成SimpleTagSupport类。
2. 标签性质文件
tag library descriptor file,定义标签的名称、简述、对应的处理类、标签的属性等。
这些描述放在tld文件中。
3. 在jsp网页中使用自定义的标签。
当然需要指定tld文件的位置,
一是直接指定。
二是利用web.xml做映射。
JSTL:jsp
标准标签库
Jstl JavaServer pages Standard Tag Library:由jcp(java community process)指定的规范,给开发人员提供一个标准的标签函数库。
可以用jstl和el来开发web程序,而不在页面上嵌java程序。
其内容包括:
Jstl
|
前缀
|
Uri
|
|
核心标签库
|
C
|
|
|
I18格式标签库
|
Fmt
|
|
|
SQL标签库
|
Sql
|
|
|
XML标签库
|
Xml
|
|
|
函数标签库
|
fn
|
|
|
由apache实现,
core tag library:输入输出,流程控制,迭代操作,表达式,url操作,
I18N:国际化支持,消息,数字日期格式化。
SQL标签库:注意一个问题,使用这个标签库可以方便查询修改数据库,就等于在
view中加入了control,这跟现在的表示,结构,行为分离的做法不一致。
只建议在小项目中使用。
XML:解析xml文件,配合xslt在jsp中显示xml。
EL。