Servlet学习笔记

学习Javaweb真的阐述了基础不牢,地动山摇,太吃力了,啥都不知道,就上框架,因此回炉重修


简介

用户使用浏览器访问网页就是发送HTTP请求,web服务器响应请求的过程。所以解析HTTP的工作就交给web服务器了。web服务器有很多,Tomcat是一款小巧灵活并使用最多的Web应用服务器

因此像网络协议、HTTP,servlet根本不管!也管不着!那servlet是干嘛的?很简单,接口的作用是什么?规范呗!servlet接口定义的是一套处理网络请求的规范,所有实现servlet的类,都需要实现它那五个方法,其中最主要的是两个生命周期方法init()和destroy(),还有一个处理请求的service(),也就是说,所有实现servlet接口的类,或者说,所有想要处理网络请求的类,都需要回答这三个问题:

  • 你初始化时要做什么
  • 你销毁时要做什么
  • 你接受到请求时要做什么

servlet是一个规范,那实现了servlet的类,就能处理请求了吗?servlet不会直接和客户端打交道!那请求怎么来到servlet呢?

答案是servlet容器。Servlet与Servlet容器的关系有点像枪和子弹的关系。从技术角度来说是为了解耦,通过标准化接口来相互协作。Servlet容器作为一个独立发展的标准化产品,目前它的种类很多,但是它们都有自己的市场定位,很难说谁优谁劣,各有特点。例如现在比较流行的 Jetty,在定制化和移动领域有不错的发展

但最常用还是Tomcat。Tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端

Java Servlet通常情况下与使用CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于CGI,Servlet有以下几点优势:

  • 性能明显更好
  • Servlet在Web服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求
  • Servlet是独立于平台的,因为它们是用Java编写的
  • 服务器上的Java安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet是可信的
  • Java类库的全部功能对Servlet来说都是可用的。它可以通过sockets和RMI机制与applets、数据库或其他软件进行交互
    Servlet架构

Servlet执行以下主要任务:

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的HTML表单,或者也可以是来自applet或自定义的HTTP客户端程序的表单
  • 读取客户端(浏览器)发送的隐式的HTTP请求数据。这包括cookies、媒体类型和浏览器能理解的压缩格式等等
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行RMI或CORBA调用,调用Web服务,或者直接计算得出对应的响应
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML或XML)、二进制文件(GIF图像)、Excel等
  • 发送隐式的HTTP响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置cookies和缓存参数,以及其他类似的任务

生命周期

Servlet生命周期可被定义为从创建直到毁灭的整个过程。以下是Servlet遵循的过程:

  • Servlet通过调用init()方法进行初始化
  • Servlet 调用service()方法来处理客户端的请求
  • Servlet 通过调用destroy()方法终止(结束)
  • 最后,Servlet是由JVM的垃圾回收器进行垃圾回收的

init()

init方法被设计成只调用一次。它在第一次创建Servlet时被调用,在后续每次用户请求时不再调用

Servlet创建于用户第一次调用对应于该Servlet的URL时,但是您也可以指定Servlet在服务器第一次启动时被加载

当用户调用一个Servlet时,就会创建一个Servlet实例,每一个用户请求都会产生一个新的线程,适当的时候移交给doGet或doPost方法。init() 方法简单地创建或加载一些数据,这些数据将被用于Servlet的整个生命周期

service()

service()方法是执行实际任务的主要方法。Servlet容器(即Web服务器)调用service()方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端

每次服务器接收到一个Servlet请求时,服务器会产生一个新的线程并调用服务。service() 方法检查HTTP请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用doGet、doPost、doPut、doDelete等方法

service()方法由容器调用,service方法在适当的时候调用 doGet、doPost、doPut、doDelete等方法。所以,您不用对service()方法做任何动作,您只需要根据来自客户端的请求类型来重写doGet()或doPost()即可

  • doGet():GET请求来自于一个URL的正常请求,或者来自于一个未指定METHOD的HTML表单,它由doGet()方法处理
  • doPost():POST请求来自于一个特别指定了METHOD为POST的HTML表单,它由doPost()方法处理

destroy()

destroy()方法只会被调用一次,在Servlet生命周期结束时被调用。destroy()方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把Cookie列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用destroy()方法之后,servlet对象被标记为垃圾回收

架构

表单数据

浏览器使用两种方法可将这些信息传递到Web服务器,分别为GET方法和POST方法

Servlet处理表单数据,这些数据会根据不同的情况使用不同的方法自动解析:

  • getParameter():您可以调用request.getParameter()方法来获取表单参数的值。
  • getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框
  • getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法

表单

<form>标签是HTML的原生标签,主要用来向服务器传输数据,一个form表单如下:

1
<form action="url" method="GET"></form>

其中action代表该表单数据要提交到的服务器地址,method表示提交方式,一般有 GET、POST。<form>只是包裹输入数据的标签而已,要有输入框才能提交,所以这时候需要有input

GET

GET方法向页面请求发送已编码的用户信息。页面和已编码的信息中间用?字符分隔

GET方法是默认的从浏览器向Web服务器传递信息的方法,它会产生一个很长的字符串,出现在浏览器的地址栏中。如果您要向服务器传递的是密码或其他的敏感信息,请不要使用GET方法。GET方法有大小限制:请求字符串中最多只能有1024个字符

这些信息使用QUERY_STRING头传递,并可以通过QUERY_STRING环境变量访问,Servlet使用 doGet()方法处理这种类型的请求

POST

另一个向后台程序传递信息的比较可靠的方法是POST方法。POST方法打包信息的方式与GET方法基本相同,但是POST方法不是把信息作为URL中?字符后的文本字符串进行发送,而是把这些信息作为一个单独的消息。消息以标准输出的形式传到后台程序,您可以解析和使用这些标准输出。Servlet使用doPost()方法处理这种类型的请求

客户端HTTP请求

当浏览器请求网页时,它会向Web服务器发送特定信息,这些信息不能被直接读取,因为这些信息是作为HTTP请求的头的一部分进行传输的

HTTP头信息

头信息 描述
Accept 这个头信息指定浏览器或其他客户端可以处理的 MIME 类型。值 image/png 或 image/jpeg 是最常见的两种可能值
Accept-Charset 这个头信息指定浏览器可以用来显示信息的字符集。例如 ISO-8859-1。
Accept-Encoding 这个头信息指定浏览器知道如何处理的编码类型。值 gzip 或 compress 是最常见的两种可能值。
Accept-Language 这个头信息指定客户端的首选语言,在这种情况下,Servlet 会产生多种语言的结果。例如,en、en-us、ru 等。
Authorization 这个头信息用于客户端在访问受密码保护的网页时识别自己的身份。
Connection 这个头信息指示客户端是否可以处理持久 HTTP 连接。持久连接允许客户端或其他浏览器通过单个请求来检索多个文件。值 Keep-Alive 意味着使用了持续连接。
Content-Length 这个头信息只适用于 POST 请求,并给出 POST 数据的大小(以字节为单位)。
Cookie 这个头信息把之前发送到浏览器的 cookies 返回到服务器。
Host 这个头信息指定原始的 URL 中的主机和端口。
If-Modified-Since 这个头信息表示只有当页面在指定的日期后已更改时,客户端想要的页面。如果没有新的结果可以使用,服务器会发送一个 304 代码,表示 Not Modified 头信息。
If-Unmodified-Since 这个头信息是 If-Modified-Since 的对立面,它指定只有当文档早于指定日期时,操作才会成功。
Referer 这个头信息指示所指向的 Web 页的 URL。例如,如果您在网页 1,点击一个链接到网页 2,当浏览器请求网页 2 时,网页 1 的 URL 就会包含在 Referer 头信息中。
User-Agent 这个头信息识别发出请求的浏览器或其他客户端,并可以向不同类型的浏览器返回不同的内容。

读取头信息

这些方法通过HttpServletRequest对象获得

方法 描述
Cookie[] getCookies() 返回一个数组,包含客户端发送该请求的所有的 Cookie 对象。
Enumeration getAttributeNames() 返回一个枚举,包含提供给该请求可用的属性名称。
Enumeration getHeaderNames() 返回一个枚举,包含在该请求中包含的所有的头名。
Enumeration getParameterNames() 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
HttpSession getSession() 返回与该请求关联的当前 session 会话,或者如果请求没有 session 会话,则创建一个。
HttpSession getSession(boolean create) 返回与该请求关联的当前 HttpSession,或者如果没有当前会话,且创建是真的,则返回一个新的 session 会话。
Locale getLocale() 基于 Accept-Language 头,返回客户端接受内容的首选的区域设置。
Object getAttribute(String name) 以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null。
ServletInputStream getInputStream() 使用 ServletInputStream,以二进制数据形式检索请求的主体。
String getAuthType() 返回用于保护 Servlet 的身份验证方案的名称,例如,”BASIC” 或 “SSL”,如果JSP没有受到保护则返回 null。
String getCharacterEncoding() 返回请求主体中使用的字符编码的名称。
String getContentType() 返回请求主体的 MIME 类型,如果不知道类型则返回 null。
String getContextPath() 返回指示请求上下文的请求 URI 部分。
String getHeader(String name) 以字符串形式返回指定的请求头的值。
String getMethod() 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
String getParameter(String name) 以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。
String getPathInfo() 当请求发出时,返回与客户端发送的 URL 相关的任何额外的路径信息。
String getProtocol() 返回请求协议的名称和版本。
String getQueryString() 返回包含在路径后的请求 URL 中的查询字符串。
String getRemoteAddr() 返回发送请求的客户端的互联网协议(IP)地址。
String getRemoteHost() 返回发送请求的客户端的完全限定名称。
String getRemoteUser() 如果用户已通过身份验证,则返回发出请求的登录用户,或者如果用户未通过身份验证,则返回 null。
String getRequestURI() 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
String getRequestedSessionId() 返回由客户端指定的 session 会话 ID。
String getServletPath() 返回调用 JSP 的请求的 URL 的一部分。
String[] getParameterValues(String name) 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。
boolean isSecure() 返回一个布尔值,指示请求是否使用安全通道,如 HTTPS。
int getContentLength() 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。
int getIntHeader(String name) 返回指定的请求头的值为一个 int 值。
int getServerPort() 返回接收到这个请求的端口号。
int getParameterMap() 将参数封装成 Map 类型。

服务器HTTP响应

当一个Web服务器响应一个HTTP请求时,响应通常包括一个状态行、一些响应报头、一个空行和文档

响应报头

头信息 描述
Allow 这个头信息指定服务器支持的请求方法(GET、POST 等)。
Cache-Control 这个头信息指定响应文档在何种情况下可以安全地缓存。可能的值有:public、private 或 no-cache 等。Public 意味着文档是可缓存,Private 意味着文档是单个用户私用文档,且只能存储在私有(非共享)缓存中,no-cache 意味着文档不应被缓存。
Connection 这个头信息指示浏览器是否使用持久 HTTP 连接。值 close 指示浏览器不使用持久 HTTP 连接,值 keep-alive 意味着使用持久连接。
Content-Disposition 这个头信息可以让您请求浏览器要求用户以给定名称的文件把响应保存到磁盘。
Content-Encoding 在传输过程中,这个头信息指定页面的编码方式。
Content-Language 这个头信息表示文档编写所使用的语言。例如,en、en-us、ru 等。
Content-Length 这个头信息指示响应中的字节数。只有当浏览器使用持久(keep-alive)HTTP 连接时才需要这些信息。
Content-Type 这个头信息提供了响应文档的 MIME(Multipurpose Internet Mail Extension)类型。
Expires 这个头信息指定内容过期的时间,在这之后内容不再被缓存。
Last-Modified 这个头信息指示文档的最后修改时间。然后,客户端可以缓存文件,并在以后的请求中通过 If-Modified-Since 请求头信息提供一个日期。
Location 这个头信息应被包含在所有的带有状态码的响应中。在 300s 内,这会通知浏览器文档的地址。浏览器会自动重新连接到这个位置,并获取新的文档。
Refresh 这个头信息指定浏览器应该如何尽快请求更新的页面。您可以指定页面刷新的秒数。
Retry-After 这个头信息可以与 503(Service Unavailable 服务不可用)响应配合使用,这会告诉客户端多久就可以重复它的请求。
Set-Cookie 这个头信息指定一个与页面关联的cookie。

设置响应报头

下面的方法可用于在Servlet程序中设置HTTP响应报头。这些方法通过 HttpServletResponse对象可用

方法 描述
String encodeRedirectURL(String url) 为sendRedirect 方法中使用的指定的 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
String encodeURL(String url) 对包含 session 会话 ID 的指定 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
boolean containsHeader(String name) 返回一个布尔值,指示是否已经设置已命名的响应报头。
boolean isCommitted() 返回一个布尔值,指示响应是否已经提交。
void addCookie(Cookie cookie) 把指定的 cookie 添加到响应。
void addDateHeader(String name, long date) 添加一个带有给定的名称和日期值的响应报头。
void addHeader(String name, String value) 添加一个带有给定的名称和值的响应报头。
void addIntHeader(String name, int value) 添加一个带有给定的名称和整数值的响应报头。
void flushBuffer() 强制任何在缓冲区中的内容被写入到客户端。
void reset() 清除缓冲区中存在的任何数据,包括状态码和头。
void resetBuffer() 清除响应中基础缓冲区的内容,不清除状态码和头。
void sendError(int sc) 使用指定的状态码发送错误响应到客户端,并清除缓冲区。
void sendError(int sc, String msg) 使用指定的状态发送错误响应到客户端。
void sendRedirect(String location) 使用指定的重定向位置 URL 发送临时重定向响应到客户端。
void setBufferSize(int size) 为响应主体设置首选的缓冲区大小。
void setCharacterEncoding(String charset) 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
void setContentLength(int len) 设置在 HTTP Servlet 响应中的内容主体的长度,该方法设置 HTTP Content-Length 头。
void setContentType(String type) 如果响应还未被提交,设置被发送到客户端的响应的内容类型。
void setDateHeader(String name, long date) 设置一个带有给定的名称和日期值的响应报头。
void setHeader(String name, String value) 设置一个带有给定的名称和值的响应报头。
void setIntHeader(String name, int value) 设置一个带有给定的名称和整数值的响应报头。
void setLocale(Locale loc) 如果响应还未被提交,设置响应的区域。
void setStatus(int sc) 为该响应设置状态码。

HTTP状态码

状态码含义

代码 消息 描述
100 Continue 只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求。
101 Switching Protocols 服务器切换协议。
200 OK 请求成功。
201 Created 该请求是完整的,并创建一个新的资源。
202 Accepted 该请求被接受处理,但是该处理是不完整的。
203 Non-authoritative Information
204 No Content
205 Reset Content
206 Partial Content
300 Multiple Choices 链接列表。用户可以选择一个链接,进入到该位置。最多五个地址。
301 Moved Permanently 所请求的页面已经转移到一个新的 URL。
302 Found 所请求的页面已经临时转移到一个新的 URL。
303 See Other 所请求的页面可以在另一个不同的 URL 下被找到。
304 Not Modified
305 Use Proxy
306 Unused 在以前的版本中使用该代码。现在已不再使用它,但代码仍被保留。
307 Temporary Redirect 所请求的页面已经临时转移到一个新的 URL。
400 Bad Request 服务器不理解请求。
401 Unauthorized 所请求的页面需要用户名和密码。
402 Payment Required 您还不能使用该代码。
403 Forbidden 禁止访问所请求的页面。
404 Not Found 服务器无法找到所请求的页面。.
405 Method Not Allowed 在请求中指定的方法是不允许的。
406 Not Acceptable 服务器只生成一个不被客户端接受的响应。
407 Proxy Authentication Required 在请求送达之前,您必须使用代理服务器的验证。
408 Request Timeout 请求需要的时间比服务器能够等待的时间长,超时。
409 Conflict 请求因为冲突无法完成。
410 Gone 所请求的页面不再可用。
411 Length Required “Content-Length” 未定义。服务器无法处理客户端发送的不带 Content-Length 的请求信息。
412 Precondition Failed 请求中给出的先决条件被服务器评估为 false。
413 Request Entity Too Large 服务器不接受该请求,因为请求实体过大。
414 Request-url Too Long 服务器不接受该请求,因为 URL 太长。当您转换一个 “post” 请求为一个带有长的查询信息的 “get” 请求时发生。
415 Unsupported Media Type 服务器不接受该请求,因为媒体类型不被支持。
417 Expectation Failed
500 Internal Server Error 未完成的请求。服务器遇到了一个意外的情况。
501 Not Implemented 未完成的请求。服务器不支持所需的功能。
502 Bad Gateway 未完成的请求。服务器从上游服务器收到无效响应。
503 Service Unavailable 未完成的请求。服务器暂时超载或死机。
504 Gateway Timeout 网关超时。
505 HTTP Version Not Supported 服务器不支持”HTTP协议”版本。

设置状态码

下面的方法可用于在Servlet程序中设置HTTP状态码。这些方法通过HttpServletResponse 对象获取

  • public void setStatus (int statusCode):该方法设置一个任意的状态码。setStatus方法接受一个 int(状态码)作为参数。如果您的响应包含了一个特殊的状态码和文档,请确保在使用 PrintWriter 实际返回任何内容之前调用setStatus
  • public void sendRedirect(String url):该方法生成一个 302 响应,连同一个带有新文档 URL 的 Location 头。
  • public void sendError(int code, String message):该方法发送一个状态码(通常为 404),连同一个在 HTML 文档内部自动格式化并发送到客户端的短消息。

过滤器

Servlet过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息

Servlet过滤器是可用于Servlet编程的Java类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

过滤器通过Web部署描述符(web.xml)中的XML 标签来声明,然后映射到您的应用程序的部署描述符中的Servlet名称或URL模式。当Web容器启动Web应用程序时,它会为您在部署描述符中声明的每一个过滤器创建一个实例

Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前

过滤器是一个实现了javax.servlet.Filter接口的Java类。javax.servlet.Filter 接口定义了三个方法:

  • public void doFilter (ServletRequest, ServletResponse, FilterChain):该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器
  • public void init(FilterConfig filterConfig):web应用程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象,如下图所示

    1
    2
    3
    4
    5
    6
    public void  init(FilterConfig config) throws ServletException {
    // 获取初始化参数
    String site = config.getInitParameter("Site");
    // 输出初始化参数
    System.out.println("网站名称: " + site);
    }
  • public void destroy():Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源

web.xml配置参数

  • <filter>指定一个过滤器。
  • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
  • <filter-class>元素用于指定过滤器的完整的限定类名。
  • <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
  • 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
  • <filter-mapping>元素用于设置一个Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
  • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
  • <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
  • <servlet-name>指定过滤器所拦截的Servlet名称。

<dispatcher>指定过滤器所拦截的资源被Servlet容器调用的方式,可以是REQUEST、INCLUDE、FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定Filter对资源的多种调用方式进行拦截。<dispatcher>子元素可以设置的值及其意义???

  • REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
  • INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
  • FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
  • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

过滤器的常见功能是可以完成编码过滤及登陆验证

异常处理

当一个Servlet抛出一个异常时,Web容器在使用了exception-type元素的web.xml中搜索与抛出异常类型相匹配的配置。您必须在web.xml中使用error-page元素来指定对特定异常或HTTP状态码作出相应的Servlet调用,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- error-code 相关的错误页面 -->
<error-page>
<error-code>404</error-code>
<location>/ErrorHandler</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/ErrorHandler</location>
</error-page>

<!-- exception-type 相关的错误页面 -->
<error-page>
<exception-type>
javax.servlet.ServletException
</exception-type >
<location>/ErrorHandler</location>
</error-page>

<error-page>
<exception-type>java.io.IOException</exception-type >
<location>/ErrorHandler</location>
</error-page>

<!-- 对所有的异常有一个通用的错误处理程序 -->
<error-page>
<exception-type>java.lang.Throwable</exception-type >
<location>/ErrorHandler</location>
</error-page>

  • javax.servlet.error.status_code:该属性给出状态码,状态码可被存储,并存储为java.lang.Integer
  • javax.servlet.error.exception_type:该属性给出异常类型的信息,异常类型可被存储,并存储为java.lang.Class
  • javax.servlet.error.message:该属性给出确切错误消息的信息,信息可被存储,并存储为java.lang.String
  • javax.servlet.error.request_uri:该属性给出有关URL调用Servlet 的信息,信息可被存储,并存储为java.lang.String
  • javax.servlet.error.exception:该属性给出异常产生的信息,信息可被存储,并存储为java.lang.Throwable
  • javax.servlet.error.servlet_name:该属性给出Servlet的名称,名称可被存储,并存储为java.lang.String

在理解异常的时候碰到一个问题

1
2
3
Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
String servletName = (String)request.getAttribute("javax.servlet.error.servlet_name");

一直没想明白:为什么request中会莫名多出来javax.servlet.error.***属性,后来查找资料,流程终于理清、

一个用来向服务器提供客户端请求信息的对象。servlet container产生一个ServletRequest,然后将它作为参数传递给servlet的service方法

属性值可以通过两种方法设置: servlet container可以设置属性,以便请求的特定信息可以被访问;属性同样可以使用setAttribute()方法进行设置。这可以在调用RequestDispatcher之前将信息嵌入到request中

因此如果输入错误的URL,没有对应的Servlet,servlet container就会产生404,并设置javax.servlet.error.status_code,此时由于存在处理异常的servlet,就会调用设置了状态码的ServletRequest传递给该Servlet,接着做出针对该状态码的行为

Cookie

Cookie是存储在客户端计算机上的文本文件,并保留了各种跟踪信息

识别返回用户包括三个步骤:

  • 服务器脚本向浏览器发送一组Cookie。例如:姓名、年龄或识别号码等。
  • 浏览器将这些信息存储在本地计算机上,以备将来使用。
  • 当下一次浏览器向Web服务器发送任何请求时,浏览器会把这些Cookie信息发送到服务器,服务器将使用这些信息来识别用户

Cookie通常设置在HTTP头信息中。设置Cookie的Servlet会发送头信息

1
2
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; 
path=/; domain=runoob.com

Set-Cookie头包含了一个名称值对、一个 GMT 日期、一个路径和一个域。名称和值会被URL编码。expires字段是一个指令,告诉浏览器在给定的时间和日期之后”忘记”该Cookie

如果浏览器被配置为存储 Cookie,它将会保留此信息直到到期日期。如果用户的浏览器指向任何匹配该Cookie的路径和域的页面,它会重新发送Cookie到服务器

设置Cookie

public void setDomain(String pattern):该方法设置cookie适用的域,例如 runoob.com。
public String getDomain():该方法获取cookie适用的域,例如runoob.com。
public void setMaxAge(int expiry):该方法设置cookie过期的时间(以秒为单位)。如果不这样设置,cookie只会在当前 session 会话中持续有效。
public int getMaxAge():该方法返回cookie的最大生存周期(以秒为单位),默认情况下,-1 表示cookie将持续下去,直到浏览器关闭。
public String getName():该方法返回cookie的名称。名称在创建后不能改变。
public void setValue(String newValue):该方法设置与cookie关联的值。
public String getValue():该方法获取与cookie关联的值。
public void setPath(String uri):该方法设置cookie适用的路径。如果您不指定路径,与当前页面相同目录下的(包括子目录下的)所有URL都会返回cookie。
public String getPath():该方法获取cookie适用的路径。
public void setSecure(boolean flag):该方法设置布尔值,表示cookie是否应该只在加密的(即SSL)连接上发送。
public void setComment(String purpose):设置cookie的注释。该注释在浏览器向用户呈现cookie时非常有用。
public String getComment():获取cookie的注释,如果cookie没有注释则返回null。

读取Cookie

要读取Cookie,您需要通过调用HttpServletRequest的getCookies()方法创建一个 javax.servlet.http.Cookie对象的数组。然后循环遍历数组,并使用getName()和getValue()方法来访问每个cookie和关联的值

删除Cookie

删除Cookie是非常简单的

  • 读取一个现有的cookie,并把它存储在Cookie对象中。
  • 使用setMaxAge()方法设置cookie的年龄为零,来删除现有的cookie。
  • 把这个cookie添加到响应头。

Session

HTTP是一种”无状态”协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web服务器,服务器不保留之前客户端请求的任何记录

以下三种方式来维持Web客户端和Web服务器之间的session会话

  • Web服务器可以分配一个唯一的session会话ID作为每个Web客户端的cookie,对于客户端的后续请求可以使用接收到的cookie来识别。这可能不是一个有效的方法,因为很多浏览器不支持cookie
  • 隐藏的表单字段。一个Web服务器可以发送一个隐藏的HTML表单字段,以及一个唯一的session 会话ID,如下所示。该条目意味着,当表单被提交时,指定的名称和值会被自动包含在GET或 POST 数据中。每次当Web浏览器发送请求时,session_id值可以用于保持不同的Web浏览器的跟踪。这可能是一种保持session会话跟踪的有效方式,但是点击常规的超文本链接(<A HREF...>)不会导致表单提交,因此隐藏的表单字段也不支持常规的session会话跟踪。
    <input type="hidden" name="sessionid" value="12345">

  • URL重写:您可以在每个URL末尾追加一些额外的数据来标识session会话,服务器会把该session会话标识符与已存储的有关session会话的数据相关联例如,http://w3cschool.cc/file.htm;sessionid=12345,session会话标识符被附加为sessionid=12345,标识符可被Web服务器访问以识别客户端。URL重写是一种更好的维持session会话的方式,它在浏览器不支持cookie时能够很好地工作,但是它的缺点是会动态生成每个URL来为页面分配一个session 会话 ID,即使是在很简单的静态HTML页面中也会如此

HTTPSession

除了上述的三种方式,Servlet还提供了HttpSession接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式

Servlet容器使用这个接口来创建一个HTTP客户端和HTTP服务器之间的session会话。会话持续一个指定的时间段,跨多个连接或页面请求

通过调用HttpServletRequest的公共方法getSession()来获取HttpSession对象

数据库

Java类库的全部功能对Servlet来说都是可用的。它可以通过sockets和RMI机制与applets、数据库或其他软件进行交互。即使用JDBC来进行了解数据库并访问数据

文件上传

Servlet可以与HTML form标签一起使用,来允许用户上传文件到服务器。上传的文件可以是文本文件或图像文件或任何文档

Servlet3.0已经内置了文件上传这一特性,开发者不再需要将Commons FileUpload组件导入到工程中去(在Servlet包的META-INF文件下可以查看版本)

网页重定向

当文档移动到新的位置,我们需要向客户端发送这个新位置时,我们需要用到网页重定向。当然,也可能是为了负载均衡,或者只是为了简单的随机,这些情况都有可能用到网页重定向

重定向请求到另一个网页的最简单的方式是使用response对象的sendRedirect()方法;也可以通过把setStatus()和setHeader()方法一起使用来达到同样的效果

参考

菜鸟教程