servlet是server applet的缩写,即在服务器端运行的小程序,而servlet框架则是对http服务器(servlet container)和用户小程序中间层的标准化和抽象。这一层抽象隔离了http服务器的实现细节,而servlet规范定义了各个类的行为,从而保证了这些“服务器端运行的小程序”对服务器实现的无关性(即提升了其可移植性)。
在servlet规范有以下几个核心类(接口):
servletcontext:定义了一些可以和servlet container交互的方法。
registration:实现filter和servlet的动态注册。
servletrequest(httpservletrequest):对http请求消息的封装。
servletresponse(httpservletresponse):对http响应消息的封装。
requestdispatcher:将当前请求分发给另一个url,甚至servletcontext以实现进一步的处理。
servlet(httpservlet):所有“服务器小程序”要实现了接口,这些“服务器小程序”重写doget、dopost、doput、dohead、dodelete、dooption、dotrace等方法(httpservlet)以实现响应请求的相关逻辑。
filter(filterchain):在进入servlet前以及出servlet以后添加一些用户自定义的逻辑,以实现一些横切面相关的功能,如用户验证、日志打印等功能。
asynccontext:实现异步请求处理。
servletrequest是对servlet请求消息的封装,其子接口httpservletrequest则是对http请求消息的封装,在servlet框架中默认实现了servletrequestwrapper和httpservletrequestwrapper以便利用户对请求的wrap。
在jetty中,使用request类实现httpservletrequest接口,request包含了httpconnection引用,因为httpconnection包含了httpparser解析http请求后的所有信息,如请求行、请求头以及请求内容。其中servletrequest接口定义与实现如下:
public interface servletrequest {
// request级别的attribute操作,它属于request的私有数据,因而request使用attributes私有字段实现。然而jetty添加了一些自定义的attribute:
// 在getattribute时,org.eclipse.jetty.io.endpoint.maxidletime用于获取endpoint中maxidletime属性,org.eclipse.jetty.continuation用于获取continuation实例(如果该属性没被占用)
// 在setattribute时,org.eclipse.jetty.server.request.queryencoding属性同时用于设置request的queryencoding属性;
// org.eclipse.jetty.server.sendcontent同时用于直接向客户端发送object指定的相应内容,该值必须是httpcontent、resource、buffer、inputstream类型;
// org.eclipse.jetty.server.responsebuffer同时用于设置对客户端相应的bytebuffer数据;org.eclipse.jetty.io.endpoint.maxidletime同时用于设置endpoint中的maxidletime属性。
// 如果注册了servletrequestattributelistener,则相应的attributeadded、attributereplaced、attributeremoved方法会被调用。
public object getattribute(string name);
public enumeration<string> getattributenames();
public void setattribute(string name, object o);
public void removeattribute(string name);
// characterencoding属性,用于指定读取请求内容时使用的编码方式,如果设置的编码方式不支持,抛出unsupportedencodingexception。characterencoding的设置必须在读取parameter或getreader方法的调用之前,不然该方法不会有效果。该属性默认为null,此时jetty默认使用utf-8编码parameter,使用iso-8859-1编码方式创建reader实例。
public string getcharacterencoding();
public void setcharacterencoding(string env) throws unsupportedencodingexception;
// 请求内容的长度,以字节为单位,-1表示长度未知。该值从httpconnection的requestfields字段中获取,该字段在httpparser解析http请求消息时填充。
public int getcontentlength();
// 返回请求内容的mime type,即在请求头中设置的contenttype头,该值同样从httpconnection的requestfields字段中获取,该字段在httpparser解析http请求消息时填充。
public string getcontenttype();
// 使用servletinputstream包装请求内容的读取,该方法和getreader方法,只能使用一种方式来读取请求内容,否则抛出illegalstateexception。
// servletinputstream继承自inputstream,它只是实现了一个readline函数。在该方法实现中返回httpconnection的getinputstream,在该方法返回前,如果当前请求有expect: 100-continue头,则先向客户端发送100 continue相应,然后返回httpinput实例,它继承自servletinputstream,从httpparser中读取数据。
public servletinputstream getinputstream() throws ioexception;
// 请求参数相关的操作,请求参数可以在url使用?paramname=paramvalue&...的方式指定,也可是使用post/put方法在请求消息体中指定(contenttype: application/x-www-form-urlencoded),或同时存在。url的parameter信息读取使用queryencoding字段指定的编码方式(默认编码为utf-8),请求消息体中信息读取使用characterencoding字段指定的编码方式(默认编码为iso-8859-1)。在读取请求消息体中的parameter数据时,可以使用contexthandler中的maxformcontentsize属性或server中的org.eclipse.jetty.server.request.maxformcontentsize的attribute配置最大支持的parameter数据大小,如果contentlength超过该值,则抛出illegalstateexception。
// 相同的paramname可以多次出现,因而一个paramname可能对应多个值,此时使用getparametervalues()方法获取所有的值。
// 如果使用post指定请求参数,使用getinputstream或getreader读取数据会对parameter的读取有影响。
public string getparameter(string name);
public enumeration<string> getparameternames();
public string[] getparametervalues(string name);
public map<string, string[]> getparametermap();
// 返回当前请求使用的协议以及其版本号,如http/1.1,对http请求,它在解析请求行时设置。
public string getprotocol();
// 返回请求的schema,默认为http,在ssl相关的connector的customize方法中会被设置为https。
public string getscheme();
// 返回当前请求发送的服务器名称,如果请求uri中包含host name信息,则servername使用该信息;否则使用host头(值为host:port)中的server name信息;
// 如果不存在host头,尝试使用endpont中的localhost(localaddr,如果_dns值设置为false,即connector的resolvenames属性为false,其默认值为false);
// 否则使用当前server的localhost的address:inetaddress.getlocalhost().gethostaddress();
// 对代理服务器,如果jetty在connector中开启了forwarded检查,如果connector中设置了_hostheader值,则使用强制设置host头为该值,清除已有的servername和port,并重新计算;
// 否则如果存在x-forwarded-host头,强制设置host头为该头值的最左边的值,即第一个代理服务器的主机名,清除已有的servername和port,并重新计算;
// 如果存在x-forwarded-server头,则强制设置request的servername值为该头值的最左边的值,即第一个代理服务器的主机名。
// 如果存在x-forwarded-for头,则更新request的remoteaddr和remotehost值,即最原始客户端的地址和主机名。
// 如果存在x-forwarded-proto头,则更新request的schema为该头值的最左边的值。(这是原始请求的schema还是神马呢?)
// 具体参考:http://benni82.iteye.com/blog/849139
public string getservername();
// serverport有一下查找路径:请求uri中的port;host头中值的port;endpoint的localport;如果都没有找到,则对https默认值为443,对http默认值为80
public int getserverport();
// 将servletinputstream包裹成bufferedreader类型,使用characterencoding编码方式,如果没有设置该编码,默认使用iso-8559-1,因而characterencoding的设置必须在该方法调用之前。
public bufferedreader getreader() throws ioexception;
// 返回客户端的ip地址,如果开启了forwarded检查,则该值会被更新为原始的客户端请求ip,即使该请求穿越了好几个代理服务器。
public string getremoteaddr();
// 如果connector设置了resolvenames属性为true,即request中_dns字段为true,则返回客户端主机名,否则返回客户端主机ip;如果开启了forwarded检查,则该值被更新为最原始的客户端的主机名或ip,即使该请求穿越了好几个代理服务器。
public string getremotehost();
// 返回accept-language请求头中的指定的locale值,支持多个值,以",", " ", "\t"等字符分隔,每个值都可以是如下格式:language-<country>;q<value>或language-<country>; q=<value>的格式,在选择一个locale时使用qvalue最大的那个。如果没有设置,默认使用当前服务器的locale值。
public locale getlocale();
// 返回accept-language头中指定的所有locale枚举值,以qvalue的值降序排列,如果没有指定该头,使用服务器默认的locale值。
public enumeration<locale> getlocales();
// 检查当前请求是否在安全传输通道,如https。
public boolean issecure();
// 返回一个requestdispatcher,内部使用servletcontext获取requestdispatcher实例,根据传入的path计算uriincontext值:如果它以"/"开头,uriincontext的值即为该值,
// 如果它不以"/"开头,即表示它是相对与当前请求的path,则uriincontext的值为相对于当前request uri,如pathinfo为/foo/goo,path为poo,则uriincontext为:<servletpath>/foo/poo
public requestdispatcher getrequestdispatcher(string path);
// 返回客户端的端口,调用endpoint的getremoteport方法。
public int getremoteport();
// 返回当前服务器的主机名,如果connector的resolvenames为true,否则为当前服务器的ip地址。
public string getlocalname();
// 返回当前服务器的ip地址,调用endpoint的getlocaladdr方法。
public string getlocaladdr();
// 返回当前服务器的端口号,即当前连接使用的端口号,不是服务器本身监听的端口号。
public int getlocalport();
// 返回当前request正在执行所在servletcontext。
public servletcontext getservletcontext();
// 启动当前请求的异步模式,该方法调用后,即可以推出当前请求的处理方法,在退出之前需要将返回的asynccontext放到一个等待queue或类似的数据结构中,从而在之后的处理中还能得到这个
// asynccontext实例进一步处理这个request,asynccontext包含了对当前request和response实例的引用,一般唤起这个异步的请求,使用asynccontext的dispatch方法,
// 从而保证在下一次的处理过程中依然存在filter链通道。这个方法和带servletrequest、servletresponse参数的方法区别在于:
// 如果servlet a对应为/url/a,在servlet a中调用request.getrequestdispatcher("/url/b"),此时在servlet b中,如果调用request.startasync().dispatch(),此时会dispatch到/url/a,
// 但是如果在servlet b中调用request.startasync(request, response).dispatch(),此时会dispatch到/url/b中。
// 另外该方法会在调用之前注册的asynclistener的onstartasync()方法之后,清除这些已注册的asynclistener。在onstartasync方法中可以将自己重新注册到asynccontext中,只是这个设计好奇怪。。。
public asynccontext startasync() throws illegalstateexception;
public asynccontext startasync(servletrequest servletrequest, servletresponse servletresponse)
throws illegalstateexception;
// 查看是否当前request异步模式已经启动,即已经调用startasync方法,但是还没有调用asynccontext中的dispatch或oncomplete方法。
public boolean isasyncstarted();
// 查看当前request是否支持异步模式,默认为true,如果filter或servlet不支持异步模式,这在调用对应的dofilter、service之前会把该值设置为false。
public boolean isasyncsupported();
// 获取最近一次调用startasync方法时创建的asynccontext实例,如果当前request没有异步模式还没有启动,则抛出illegalstateexception。
public asynccontext getasynccontext();
// 获取当前请求的dispatcher类型。dispatcher type是container用于选区对应的filter链。请求最初为dispatcher.request;如果调用requestdispatcher.forward()方法,
// 则变为dispatchertype.forward;如果调用requestdispatcher.include()方法,则变为dispatchertype.include;如果调用asynccontext.dispatch()方法,则变为
// dispatchertype.async;最后如果请求被dispatch到error page中,则为dispatchertype.error。
// dispatchertype在httpconnection中的handlerequest方法中,在调用server.handle()/server.handleasync()方法之前,设置为request、async,根据当前request的asynccontext是否处于初始化状态,如果是,则为request,否则为async状态,其他值则在dispatcher中forward或include方法中设置。
public dispatchertype getdispatchertype();
}
httpservletrequest接口定义如下:
public interface httpservletrequest extends servletrequest {
// servlet的四种验证方式(他们在web.xml文件中的long-config/auth-method中定义):
// basic使用authentication头传输认证信息,该信息以base64的编码方式编码,当需要用户验证时会弹出登陆窗口。
// form使用表单的方式认证,用户名和密码在j_username和j_password字段中,登陆url为/j_security_check,第一次使用表单方式明文传输,之后将认证信息存放在session中,在session实效之前可以不用在手动登陆。
// digest也时使用authentication头传输认证信息,但是它使用加密算法将密码加密。
// client_cert则使用客户端证书的方式传输认证信息。
// 更详细的内容参考:http://docs.oracle.com/cd/e19798-01/821-1841/bncas/index.html
public static final string basic_auth = "basic";
public static final string form_auth = "form";
public static final string client_cert_auth = "client_cert";
public static final string digest_auth = "digest";
// 返回当前请求的认证方法,可以是basic、form、client_cert、digest。如果没有定义对应servlet的认证配置,则返回null。在jetty实现中,在servlethandler根据配置信息以及认证的结果设置请求的authentication实例,如果authentication实例是authentication.deffered实例,则先验证,并设置验证后的authentication实例,如果authentication实例是authentication.user实例,则设置返回其authmethod属性,否则返回null。
public string getauthtype();
// 返回当前请求包含的cookie数组,从请求的cookie头中获取,如果没有cookie信息,则返回null。在jetty实现中,使用cookiecutter类解析cookie头。
// cookie值的格式为:<name>=value; [$path=..; $domain=...; $port=...; $version=..]; <name>=<value>.....
// 在servlet中,cookie类包含comment(描述信息)、domain(cookie只是对指定的domain域可见,默认情况下cookie只会传输给设置这个cookie的server)、maxage(cookie的最长可存活秒数,负数表示永远不会失效,0表示cookie会被删除)、path(指定那个path下的请求这个cookie才会被发送,包括它的子目录)、secure(这个cookie是否只在https请求中发送)、version(0表示netscape最初定义的cookie标准,1表示兼容rfc 2109,一般都是0以保持最大兼容性)、ishttponly(httponly标识的cookie一般不应该暴露给客户端的脚本,以部分解决跨站点脚本攻击问题)字段。对浏览器,一般他们应该能为每个web server存储至少20个cookie,总共至少能处理300个cookie,以及至少4k大小。
public cookie[] getcookies();
// 解析指定请求头的date值,并转换成long值,如if-modified-since头。jetty支持的date格式有:eee, dd mmm yyyy hh:mm:ss zzz; eee, dd-mmm-yy hh:mm:ss等。
public long getdateheader(string name);
// 返回指定的请求头的值,没有该头,返回null,如果有多个相同名字的头,则返回第一个该头的值。name是大小写无关。
public string getheader(string name);
// 返回指定请求头的所有值
public enumeration<string> getheaders(string name);
// 返回请求头的所有名称,有些container会禁用该方法,此时返回null。
public enumeration<string> getheadernames();
// 返回指定请求头的int值。
public int getintheader(string name);
// 返回请求方法,如get、post、put等。该值在解析请求行结束后设置。
public string getmethod();
// 设置请求的额外path信息,该值在不同的地方会被设置为不同的值,如果请求的uri为: http://host:80/context/servlet/path/info如在httpconnection中,其值为/context/servlet/path/info
// 在contexthandler的doscope中,其值被设置为/servlet/path/info;在servlethandler的doscope方法中,其值被设置为/path/info,并设置servletpath为/servlet。
// 这里基于的假设为contextpath为/context,servletpath为/servlet,即在web.xml配置中servlet相关的url-pattern为/servlet/*。
// 如果没有/path/info后缀,则pathinfo为null,如果servlet的path-pattern设置为/*,则servletpath为"",对url-pattern为*.do类似的配置,pathinfo永远为null,servletpath则为/path/info.do的值;有些时候servletpath的值也可能是servlet name的值。
public string getpathinfo();
public string getservletpath();
// 返回pathinfo对应的在servletcontext下的真是server路径,如果pathinfo为null,则返回null。
public string getpathtranslated();
// 返回当前请求所属的contextpath。它在contexthandler的doscope方法中或dispatcher的forward方法中设置。
public string getcontextpath();
// 返回当前请求的query字符串,如果设置了queryencoding,使用该编码方式编码。
public string getquerystring();
// 返回请求的登陆用户,如果用户没有认证,则返回null。该信息从设置的authentication实例中获取,如果其实例为authentication.defered,则需要先验证,然后返回获取useridentity,并从中获取principal,而从principal中可以获取用户名。
public string getremoteuser();
// 验证当前请求的user是否在传入的role中,即使用设置的authentication实例验证,当前登陆的user所在的roles中是否存在传入的rolename。其中useridentity.scope实例用于查找rolename对应在container使用的rolename,如果没有这个映射则使用传入的rolename本身,这个scope在servlethandler的doscope方法中设置。这个映射在web.xml中的security-rol-ref(role-name->role-link)中设置。
public boolean isuserinrole(string role);
// 返回当前登陆user的principal实例,从设置的authentication实例中获取,或者为null。
public java.security.principal getuserprincipal();
// 返回客户端指定的session id,它可以和server的当前session id不同。客户端可以使用两种方式设置该值:cookie和url。默认先从cookie中找,找不到再从url中找。
// 对cookie方式,在web.xml的cookie-config/name中配置session的cookie name(默认值为jssessionid),找到该cookie name对应的cookie值作为requested session id
// 对url方式,在;<sessionidpathparamname>=....[;#?/]之间的值作为requested session id的值。其中sessionidpathparamname可以通过web.xml的context-param,使用org.eclipse.jetty.servlet.sessionidpathparametername属性值配置,默认为jsessionid。
public string getrequestedsessionid();
public boolean isrequestedsessionidfromcookie();
public boolean isrequestedsessionidfromurl();
// 检查当前requested session id是否valid,在jetty中valid是指requstedsessionid存在,并且和当前请求的server session的clusterid相同,即他们的sessionid相同。
public boolean isrequestedsessionidvalid();
// 返回/contextpath/servletpath/pathinfo的值。对forward后请求,该值为forward后的uri。
public string getrequesturi();
// 返回getschema()://getservername():getport()/getrequesturi(),对forward后请求,该值为forward后的url。
public stringbuffer getrequesturl();
// 返回和当前请求相关联的httpsession,如果没有关联的httpsession,且create为true,则创建新的httpsession实例。没有参数即create为true。
public httpsession getsession(boolean create);
public httpsession getsession();
//使用container定义的认证机制验证请求用户的合法性。在jetty实现中,只是对authentication.deferred的authentication类型进行验证,否则返回401 unauthorized错误相应,并返回false。
public boolean authenticate(httpservletresponse response) throws ioexception,servletexception;
// 提供用户名和密码并交由container对其进行认证。在jetty实现中,只对authentication.deferred类型提供用户名和密码认证,否则抛出servletexception。
public void login(string username, string password) throws servletexception;
// 注销当前用户,并清理_authentication字段。
public void logout() throws servletexception;
// 对multipart/form-data请求类型,表示请求内容由多个部分组成,此时使用rfc1867来解析该内容到多个part中。在servlet中一个part有自己的请求头和请求消息提,包含contenttype、name、headers、size(已写入的大小)、inputstream等信息,它还提供了一个方法将请求内容写入指定的文件中,以及删除该内部文件。并提供multipartconfigelement类来做相关的配置,如写文件时的位置location;最大可上传的文件大小maxfilesize;最大可包含的所有part的请求大小maxrequestsize;如果写入的数据超过配置的大小,则开始将数据写入文件中maxfilesizethreshold。该配置信息可以使用org.eclipse.multipartconfig属性设置,而location信息可以使用javax.servlet.context.tempdir属性在servletcontext中设置,或这使用java.io.tmpdir中指定的值。在jetty中使用multipartinputstream来表达并解析请求内容到多个part(multipart)中。具体格式可以参考:http://blog.zhaojie.me/2011/03/html-form-file-uploading-programming.html
public collection<part> getparts() throws ioexception, servletexception;
public part getpart(string name) throws ioexception, servletexception;
除了以上实现,request还包含了一些额外的字段,如_timestamp在请求开始时设置,即解析请求头完成时;_dispatchtime在requestloghandler的handle方法,当request是非initial的状态下设置,即当前request已经为dispatched的状态;_handled表示该请求是否已经处理完成;
servletresponse是对servlet响应消息的封装,其子接口httpservletresponse则是对http响应消息的封装,
servletresponse接口定义如下:
public interface servletresponse {
// 设置与返回消息体中的字符编码方式。如果没有设置,默认使用iso-8559-1。其中setcontenttype和setlocale会隐式的设置该值,但是显示的设置会覆盖之前隐式的设置,而该值的设置也会影响contenttype的值。该值的设置必须在调用getwriter()方法之前,否则不会起作用。在set方法中,如果传入的charset为null,则清楚原来设置的值,并将原来的_mimetype值设置为content-type头;否则,更新characterencoding的值,并更新contenttype的属性以及content-type头(更新contenttype中"charset="之后部分的值,或使用"mimetype; charset=<charactertype>")。
public void setcharacterencoding(string charset);
public string getcharacterencoding();
// 设置响应消息的content-type头以及contenttype字段的值,它会同时影响mimetype字段以及characterencoding字段。如果type为null,则清除contenttype、mimetype的值,移除content-type响应头,并且如果locale也为null,同时清除charactertype值;否则,设置mimetype为";"之前的值,而characterencoding的值为"charset="之后的值,如果没有"charset="之后的值,则是使用"charset=<charactertype>"值拼接以设置content-type响应头。
public void setcontenttype(string type);
public string getcontenttype();
// 设置locale的值,同时设置响应的content-language头。同时该set也会影响characterencoding、mimetype和content-type响应头。其中characterencoding从contexthandler中的locale到charset的映射中获取,即web.xml中的locale-encoding-mapping-list中定义,而对content-type的值只影响"charset="之后的值。
public void setlocale(locale loc);
// 设置contentlength字段以及content-length响应消息头。如果当前写入的数据已经大于或等于设置的值,则该方法还会关闭当前的servletoutputstream或writer。
public void setcontentlength(int len);
// 返回向客户端写数据的servletoutputstream或printwriter。它们只能使用其中一个方法。在jetty中使用httpoutput内部封装httpgenerator实例用于向socket中写数据。
public servletoutputstream getoutputstream() throws ioexception;
public printwriter getwriter() throws ioexception;
// 响应消息处理相关的buffer操作,在jetty中即为httpgenerator中响应消息体的buffer大小与刷新操作。设置buffersize必须在写响应消息体之前。另外reset只是清除消息体的缓存,并不会清除响应状态码、响应头等信息,如果该方法调用时消息已经被commit,则抛出illegalstateexception。
public void setbuffersize(int size);
public int getbuffersize();
public void flushbuffer() throws ioexception;
public void resetbuffer();
// 是否响应消息已经commit,即响应消息状态行和消息头已经发送给客户端。
public boolean iscommitted();
// 清除所有的响应消息状态,所有已经设置的响应头(但是不包括connection头),如果响应已经commit,则抛出illegalstateexception。
public void reset();
httpservletresponse接口定义如下,它添加了一些cookie、header相关的操作:
public interface httpservletresponse extends servletresponse {
// 向响应消息中添加一个cookie实例。即添加"set-cookie"头。
public void addcookie(cookie cookie);
// 消息头操作:增删改查。一个相同名字的头可能会有多个条纪录,因而可以对应多个值。在jetty实现中代理给httpconnection中的responsefields字段。其中date头的格式为:eee, dd mmm yyyy hh:mm:ss 'gmt',对于string为值的设置来说,处于include dispatch状态下,只能设置org.eclipse.jetty.server.include.<headername>的头。
public boolean containsheader(string name);
public void setdateheader(string name, long date);
public void adddateheader(string name, long date);
public void setheader(string name, string value);
public void addheader(string name, string value);
public void setintheader(string name, int value);
public void addintheader(string name, int value);
public collection<string> getheaders(string name);
public collection<string> getheadernames();
// 编码传入的url,决定并添加是否需要在url中加入session id信息以作为session追踪。处于健壮性的考虑,所有servlet产生的url必须使用改方法编码,不然对不支持cookie的浏览器将会失去session信息。在实现中,如果request使用cookie作为session追踪,则去除url中的sessionid信息;否则如果session存在并可用,则向url中添加session追踪信息,在"#"或"?"之前。
public string encodeurl(string url);
// 编码传入的url,用于sendredirect方法中。在jetty中改方法直接调用encodeurl()方法。
public string encoderedirecturl(string url);
// 向客户端发送响应状态码和原因(如果有的话)。服务器会保留已经设置的cookie,但是会在必要情况下修改响应头。如果在web.xml中定义了响应的状态码到error page的映射,则该响应会被转发到那个错误页面中。在jetty实现中,它清除buffer信息,characterencoding值,expires、last-modified、cache-control、content-type、content-length头,设置响应状态和消息,对非204(no content)、304(not modified)、206(partial content)、200(ok)的状态码(即允许有消息体),首先查找有没有注册的errorhandler ,如果有,向request的属性中设置javax.servlet.error.status_code, javax.servlet.error.message, javax.servlet.error.request_uri, javax.servlet.error.servlet_name为相应的值(requestdispatcher中定义的属性key),并调用errorhandler的handle方法;否则设置cache-control头为must-revalidate,no-cache,no-store,设置content-type头为text/html;charset=iso-8859-1,并返回一个简单的错误页面包含状态码和消息原因。最后调用httpconnection的completeresponse()方法以完成响应。
public void senderror(int sc, string msg) throws ioexception;
public void senderror(int sc) throws ioexception;
// 发送客户端一个重定向的消息和url,即设者响应状态码为302 moved temporary,在location中包含要重定向目的地的url,此时客户端会使用新的url重新发送请求。如果location以"/"开头,表示它是绝对地址,否则为相应请求的相对地址,即最终解析成request.getrequesturi()/location,location可以包含query信息。最后调用httpconnection的completeresponse()方法以完成当前响应。
public void sendredirect(string location) throws ioexception;
// 设置响应状态码和状态描述信息。
public void setstatus(int sc);
public void setstatus(int sc, string sm);
public int getstatus();