Servlet

简介

java servlet:作为一个程序,其运行在web服务器或其他应用服务器上。其充当客户端请求和服务器上数据库、应用程序的中间层。(HTTP)。其本身为一个.java文件,编写一个继承自HttpServlet的public类。但没有main。

用处:收集来自网页表单的用户输入;呈现来自数据库或其他源的记录;动态创建网页。

和CGI对比:

  • 性能明显更好。

  • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。

  • Servlet 是独立于平台的,因为它们是用 Java 编写的。

  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。

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

流程示意图:

servlet-arch.jpg

Servlet任务

主要包含:

  • 读取客户端、浏览器发送的显式的数据。这包扩网页上的HTML表单。或者来自applet(小程序)、自定义HTTP程序客户端的表单。
  • 读取客户端发送的隐式HTTP请求数据。包括数据类型(媒体类型)、压缩格式、cookies等
  • 处理数据并生成结果。在这过程可能需要访问数据库,执行RMI(Remote Method Invocatiopn,远程方法调用)或CORBA调用。(调用Web服务;或者直接计算并得出响应。)
  • 发送显式的数据(文档格式)到客户端。文档格式可包含文本、图片、excel等。
  • 发送隐式的HTTP响应当客户端。包含:数据的类型、设置缓存参数等。

Servlet 包

创建:

java服务器小程序可以通过javax.servletjavax.servlet.http包创建。(J2EE的标准组成部分)

运行环境:

其本身属于java 类,要运行在支持java Servlet解释器的web服务器上。


运行环境设置

eclipse中servlet运行环境设置

①使用eclipseEE版,或者从SE版升到EE版(通过help/install new... /安装Web...)

②在eclipse中改变buildPath(SE)

环境配置:https://www.runoob.com/jsp/eclipse-jsp.html


设置 CLASSPATH

https://www.jianshu.com/p/a3fcd1ec7a17


Servlet生命周期

定义:从创建到毁灭的整个过程。

  • 调用init():初始化servlet
  • 调用service():处理客户端请求
  • 调用destroy():终止程序。

类所包含函数:

init()

仅在第一次创建Servlet时被调用。后续请求时,已创建所以不需要调用。

何时被调用:用户第一次请求对应于该Servlet的URL时;或者可以指定Servlet在服务器启动时就初始化。

service():

执行任务的主要函数。

Servlet的容器(Web服务器)调用service()来处理客户端的请求,并返回格式化的响应给客户端。

每次服务器接收到一个Servlet请求,服务器会产生一个新的线程,并调用该函数。

功能:该函数检查HTTP请求的类型(GET\POST\PUT等),并适时调用doGet、doPost等函数方法。

调用:由容器Web服务器来调用,我们只用重载doGet等函数即可。不用重写service.

doGet():

参数:HttpServletRequest request、HTTPServletResponse response

request来自于一个URL定位符的正常请求,或者来自于一个未指定METHOD的HTML表单。

doPost:

参数:和doGet一样

request来自于一个特别指定了METHOD=Post的HTML表单。

destroy():

只会被调用一次,该类(Servlet)生命周期结束时被调用。

功能:关闭数据库连接、停止后台线程、把Cookies列表或点击计数器写入磁盘、执行其他类似的清理活动。

调用了destroy后,servlet对象被标记为垃圾回收。


架构图

一个典型的 Servlet 生命周期方案。

  • 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
  • Servlet 容器在调用 service() 方法之前加载 Servlet。
  • 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。
架构图.jpg

非IDE开发

当创建一个不依赖集成开发环境如eclipse的Servlet程序时:

①创建一个.java文件:包含类java.io.; javax.servlet. * ; javax.servlet.http.;继承自HttpServlet;

②对必要函数进行重载:一般为构造函数、doGet、doPost.

③编译:

  • 将所包含的库,添加到CLASSPATH中。像tomcat的servlet-api.jar的路径要包含到CLASSPATH中去。
  • 将.java文件目录添加到CLASSPATH中

*我尝试了,发现编译仍不成功。找不到包含的类。


Servlet部署

编译完,生成.class文件之后,就可以进行部署到web中了。

默认情况:

Servlet的应用程序放在Tomcat/webapps/ROOT/下;

类文件放在.../webapps/ROOT/WEB_INF/classes下;

我们需要将编译好的.class文件放到web.xml中(位于.../ROOT/WEB_INF/)。如下:如HelloWorld.class文件

<web-app>      
    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
    </servlet-mapping>
</web-app>  

Servlet表单数据

信息传递:从浏览器——web服务器——后台程序

使用方法:通常位GET、POST。

GET方法

说明:作为从浏览器到服务器传递的默认方法。

数据载体:URL:页面地址和参数。中间用 '?' 分隔。如:http://www.test.com/hello?key1=value1&key2=vaue2

大小限制:最多1024个字符。

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

注意:敏感信息,如密码等,不要使用GET方法传递。

POST方法

说明:相比GET,更可靠的传递方法。

POST 方法打包信息的方式与 GET 方法基本相同,但是 POST 方法不是把信息作为 URL 中 ? 字符后的文本字符串进行发送,而是把这些信息作为一个单独的消息。

消息以标准输出的形式传到后台程序,您可以解析和使用这些标准输出。Servlet 使用 doPost() 方法处理这种类型的请求。

使用Servlet读取表单数据

根据不同情况,使用不同方法自动解析:

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

使用URL的GET方法实例

说明:就是在浏览器中,URL=(域名)/.../Servlet +"?"+ "para1=String1&para2=String2&..."

如:http://localhost:8080/Test2/Test2/MyServlet2?name=%E5%AD%99%E6%9E%97&url=www.runoob.com

此时参数列表将会以参数request中,传到doGet中。

可对其进行处理,并用PrintWriter response.getWriter()来进行处理。(如在该页面输出)

使用表单的GET方法实例

①建立一个html:hello.html,如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我的网页</title>
</head>
<body>
<form action="Test2/MyServlet2" method="GET">
网址名:<input type="text" name="name">
<br />
网址:<input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

②eclipse中:保存到WebContent/

③当输入完成,提交时,会调用Myservlet2小程序,并进行输出。

使用表单的POST方法实例

在Servlet中基本和GET一样。只是hello.html里面,mothod=“POST”;因为doPost会调用doGet,所以基本一样。

使用复选框的表单方法实例

方法都和上述类似,建立一个带有复选框的html,然后可以新建一个servlet来处理。

这需要html的知识。

读取所有表单参数

使用getParameterName()返回一个enumerate枚举类型的序列。

然后一一处理。


Servlet客户端HTTP请求

请求包含:状态(请求)行,请求头,请求数据及空行。

Accept 这个头信息指定浏览器或其他客户端可以处理的 MIME 类型。值 image/pngimage/jpeg 是最常见的两种可能值。
Accept-Charset 这个头信息指定浏览器可以用来显示信息的字符集。例如 ISO-8859-1。
Accept-Encoding 这个头信息指定浏览器知道如何处理的编码类型。值 gzipcompress 是最常见的两种可能值。
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 这个头信息识别发出请求的浏览器或其他客户端,并可以向不同类型的浏览器返回不同的内容。

读取 HTTP 头的方法

下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用。

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

实例可以看https://www.runoob.com/servlet/servlet-client-request.html,或者ubuntu里面的eclipse work space


Servlet服务器HTTP响应

响应包含:状态行、响应头(报头)、响应数据(响应正文)、空行。

状态行:HTTP版本、响应码、状态码对应的简短信息(用于简单的阐述。如200 为OK表示正常响应)。

常用响应报头:

头信息 描述
Allow 这个头信息指定服务器支持的请求方法(GET、POST 等)。
Cache-Control 这个头信息指定响应文档在何种情况下可以安全地缓存。可能的值有:public、privateno-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。

设置 HTTP 响应报头的方法

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

如:response.setIntHeader("Refresh",value); 可以设置每value秒,自动刷新页面

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

Servlet HTTP状态码

HTTP请求和响应的消息格式是类似的:

  • 状态行+回车换行符(回车+换行)
  • 0或多个标题行(表明数据的某些状态或格式)+回车换行符
  • 空白行(即回车换行符)
  • 可选的消息主体。(如文件、查询数据、查询输出等)

如:

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
  (Blank Line)
<!doctype ...>
<html>
<head>...</head>
<body>
...
</body>
</html>

具体状态码可以在HTTP.md中查看,这里只写出主要类型。

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

设置HTTP状态码的方法

通过doGet中的response参数进行设置。(HttpServletResponse)

如:response.setStatus(int statusCode);

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

Servlet过滤器Filter

用处:过滤器用来拦截请求或响应。并将自身及过滤器链执行完毕后,再执行相应请求或响应。

可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。调用 Servlet 前调用所有附加的 Servlet 过滤器。

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

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

根据规范建议的各种类型的过滤器:

  • 身份验证过滤器(Authentication Filters)。
  • 数据压缩过滤器(Data compression Filters)。
  • 加密过滤器(Encryption Filters)。
  • 触发资源访问事件过滤器。
  • 图像转换过滤器(Image Conversion Filters)。
  • 日志记录和审核过滤器(Logging and Auditing Filters)。
  • MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
  • 标记化过滤器(Tokenizing Filters)。
  • XSL/T 过滤器(XSL/T Filters),转换 XML 内容。

说明:在servlet 3.0后,可以不在web.xml中进行声明,可直接在Filter.java中,在@webFilter里面,进行声明。

过滤器类函数:

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

针对2中的config,其配置信息可以在@WebFilter中设置。

@WebFilter常用属性:

属性 类型 是否 必需 说明
asyncSupported boolean 指定Filter是否支持异步模式
dispatcherTypes DispatcherType[] 指定Filter对哪种方式的请求进行过滤。支持的属性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;默认过滤所有方式的请求
filterName String Filter名称
initParams WebInitParam[] 配置参数
displayName String Filter显示名
servletNames String[] 指定对哪些Servlet进行过滤
urlPatterns/value String[] 两个属性作用相同,指定拦截的路径

示例:

@WebFilter(filterName = "loginFilter", 
    urlPatterns = "/*", 
    initParams = {
            @WebInitParam(name = "loginUI", value = "/home/loginUI"),
            @WebInitParam(name = "loginProcess", value = "home/login"),
            @WebInitParam(name = "encoding", value = "utf-8")
    })

如想要设置该过滤器针对所有servlet,可以设置urlPatterns=“/*”即可。

还有一种方法:web.xml中配置,必须要在servlet配置之前:

<filter>
    <filter-name>loginFilter</filter-name>
    <filter-class>cn.edu.njit.filter.LoginFilter</filter-class>
    <init-param>
        <param-name>loginUI</param-name>
        <param-value>/home/loginUI</param-value>
    </init-param>
    <init-param>
        <param-name>loginProcess</param-name>
        <param-value>home/login</param-value>
    </init-param>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>loginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

过滤器的顺序(应用中)

如果在web.xml中,调整<filter-mapping>的先后顺序可以控制过滤器的先后顺序。

web.xml配置各节点说明

  • <filter>指定一个过滤器。
    • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
    • <filter-class>元素用于指定过滤器的完整的限定类名。
  • <init-para>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
    • 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
  • <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
    • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
    • <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
  • <servlet-name>指定过滤器所拦截的Servlet名称。
  • <dispathcer>(调度员)指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是 REQUEST , INCLUDE , FORWARD 和 ERROR之一,默认REQUEST。用户可以设置多个<dispathcer>子元素用来指定 Filter 对资源的多种调用方式进行拦截。
  • <dispatcher>子元素可以设置的值及其意义
    • REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
    • INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
  • FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

Servlet异常处理

说明:当抛出异常时,可以用异常处理程序进行处理。只可以处理自己编写的servlet等程序,如果客户在浏览器中输入了服务器主机+端口+任意号,是不会调用的。

声明:

可以在web.xml中,进行声明,格式如下:

<!-- error-code 相关的错误页面 -->
<error-page>
    <error-code>404</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.lang.Throwable</exception-type>
    <location>/ErrorHandler0</location>
</error-page>  


上述异常程序ErrorHandler0可以处理所有异常,因为异常都是实现Throwable的类。

异常处理类的具体实现:与servlet、Filter都类似。都是继承自HttpServlet类。

实现要素:

①通过request得到:具体异常Throwable、异常号status_code、异常的servlet名字 servlet_name、异常的uri(统一资源标识符)request_uri;

②设置response格式及字符集,并设置建立一个输出对象。

③输出一个html来应答。

下面是关于上面的 web.xml 异常处理要注意的点:

  • Servlet ErrorHandler 与其他的 Servlet 的定义方式一样,且在 web.xml 中进行配置。
  • 如果有错误状态代码出现,不管为 404(Not Found 未找到)或 403(Forbidden 禁止),则会调用 ErrorHandler 的 Servlet。
  • 如果 Web 应用程序抛出 ServletExceptionIOException,那么 Web 容器会调用 ErrorHandler 的 Servlet。
  • 您可以定义不同的错误处理程序来处理不同类型的错误或异常。上面的实例是非常通用的,希望您能通过实例理解基本的概念。

请求属性 - 错误/异常

以下是错误处理的 Servlet 可以访问的请求属性列表,用来分析错误/异常的性质。

序号 属性 & 描述
1 javax.servlet.error.status_code 该属性给出状态码,状态码可被存储,并在存储为 java.lang.Integer 数据类型后可被分析。
2 javax.servlet.error.exception_type 该属性给出异常类型的信息,异常类型可被存储,并在存储为 java.lang.Class 数据类型后可被分析。
3 javax.servlet.error.message 该属性给出确切错误消息的信息,信息可被存储,并在存储为 java.lang.String 数据类型后可被分析。
4 javax.servlet.error.request_uri 该属性给出有关 URL 调用 Servlet 的信息,信息可被存储,并在存储为 java.lang.String 数据类型后可被分析。
5 javax.servlet.error.exception 该属性给出异常产生的信息,信息可被存储,并在存储为 java.lang.Throwable 数据类型后可被分析。
6 javax.servlet.error.servlet_name 该属性给出 Servlet 的名称,名称可被存储,并在存储为 java.lang.String 数据类型后可被分析。

Servlet Cookie处理

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

步骤:

  • 服务器脚本向浏览器发送一组Cookie,如:账号、密码、识别号等。

  • 浏览器将这些信息储存在本地计算机上,备用。

  • 当再次访问之前的服务器时,无论任何请求URL,都会把Cookie发送到服务器,服务器使用这些信息来识别用户。

Servlet Cookie 处理需要对中文进行编码与解码,方法如下:

String   str   =   java.net.URLEncoder.encode("中文","UTF-8");            //编码
String   str   =   java.net.URLDecoder.decode("编码后的字符串","UTF-8");   // 解码

通常Cookie由HTTP头来传输。(虽然 JavaScript 也可以直接在浏览器上设置一个 Cookie)

如下是服务器中,设置了Cookie的servlet会发送的响应头信息:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; 
                 path=/; domain=runoob.com
Connection: close
Content-Type: text/html

Cookie包含:一个名称值对、一个GMT日期(expires,到期,期限)、一个路径、一个域名。

expires告诉浏览器在此日期后忘记Cookie

如果设置浏览器为储存Cookie,就会保存这些信息,直到到期日期。当用户通过此浏览器访问与Cookie中域名、路劲相匹配的页面时,就会发送此Cookie到服务器。

此时的HTTP请求头信息可能为:

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name=xyz

而此时服务器的Servlet就可以通过Cookie[] request.getCookies()来访问Cookie。

Servlet Cookie 函数(方法)

以下是在 Servlet 中操作 Cookie 时可使用的有用的方法列表。

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

设置步骤:

通过servlet设置Cookie的步骤包括:

①创建一个Cookie对象:构造函数参数可以传入cookie的名称和值。

Cookie cookie = new Cookie("key","value");

这两个字符串不能包含这些字符:[] () = , '' / ? @ : ;

②设置最大生存周期:使用cookie.setMaxAge()来指定保持有效的时间(秒为单位)。

cookie.setMaxAge(60*60*24*7);    //保存七天

③发送Cookie到HTTP响应头:用response.addCookie来添加

response.addCookie(cookie);

实例:https://www.runoob.com/servlet/servlet-cookies-handling.html


通过Servlet读取Cookie

在servlet:doGet中调用Cookie[] request.getCookies() (java.servlet.http.Cookie),然后遍历数组,进行处理。

实例:https://www.runoob.com/servlet/servlet-cookies-handling.html

通过servlet删除Cookie

步骤:

①读取一个cookie = request.getCookies[x];

②设置其最大年龄为0:cookie.setMaxAge(0);

③response.addCookie(cookie);


Servlet Session跟踪

session会话,大概表示指定浏览器和服务器之间发生过的会议信息。即类似于Cookie。

HTTP是一种“无状态"协议,每次客户端检索网页时,打开一个单独的连接,到服务器。服务器不保存之前客户端请求的任何记录。

用三种方法来维护客户端和服务器之间的session:

  • Cookie

    服务器可以分配一个唯一的session ID作为标识唯一Web浏览器客户端的cookie。客户端再次请求时,可以根据接收到的cookie来识别该客户端。

    ps:不是很有效,因为有的浏览器不支持cookie,不建议使用。

  • 隐藏的表单字段

    服务器servlet可以发送一个隐藏的HTML表单字段,以及一个唯一的session ID,如下:

    <input type="hide" name="sessionid" value="12345">
    

    该条目意味着,当表单被提交时,指定的名称和值会被自动包含在 GET 或 POST 数据中。每次当 Web 浏览器发送回请求时,session_id 值可以用于保持不同的 Web 浏览器的跟踪。

    这可能是一种保持 session 会话跟踪的有效方式,但是点击常规的超文本链接(<A HREF...>)不会导致表单提交,因此隐藏的表单字段也不支持常规的 session 会话跟踪。

  • URL重写

    在每个URL末尾追加一些额外的数据来标识session会话。服务器会把该session会话标识符与一组有关的会话数据相关联。

    例如:http://w3cschool.cc/file.html;sessionid=12345

    session会话标识符会被附加为sessionid=12345,web服务器可以访问其,来识别客户端。

    URL 重写是一种更好的维持 session 会话的方式,它在浏览器不支持 cookie 时能够很好地工作,但是它的缺点是会动态生成每个 URL 来为页面分配一个 session 会话 ID,即使是在很简单的静态 HTML 页面中也会如此。

HTTPSession对象

除上三种外,servlet提供了HttpSession接口,提供一种跨多个页面请求或访问网站时,识别用户及其相关数据的方式。

HttpSession session = request.getSession();

要在servlet中发送任何文档内容之前,调用request.getSession().

下面是HttpSession接口的重要函数:

序号 方法 & 描述
1 public Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。
2 public Enumeration getAttributeNames() 该方法返回 String 对象的枚举,String 对象包含所有绑定到该 session 会话的对象的名称。
3 public long getCreationTime() 该方法返回该 session 会话被创建的时间,自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
4 public String getId() 该方法返回一个包含分配给该 session 会话的唯一标识符的字符串。
5 public long getLastAccessedTime() 该方法返回客户端最后一次发送与该 session 会话相关的请求的时间自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
6 public int getMaxInactiveInterval() 该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。
7 public void invalidate() 该方法指示该 session 会话无效,并解除绑定到它上面的任何对象。
8 public boolean isNew() 如果客户端还不知道该 session 会话,或者如果客户选择不参入该 session 会话,则该方法返回 true。
9 public void removeAttribute(String name) 该方法将从该 session 会话移除指定名称的对象。
10 public void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话。
11 public void setMaxInactiveInterval(int interval) 该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。

实例可以看https://www.runoob.com/servlet/servlet-session-tracking.html


删除 Session 会话数据

当您完成了一个用户的 session 会话数据,您有以下几种选择:

  • 移除一个特定的属性:您可以调用 public void removeAttribute(String name) 方法来删除与特定的键相关联的值。
  • 删除整个 session 会话:您可以调用 public void invalidate() 方法来丢弃整个 session 会话。
  • 设置 session 会话过期时间:您可以调用 public void setMaxInactiveInterval(int interval) 方法来单独设置 session 会话超时。
  • 注销用户:如果使用的是支持 servlet 2.4 的服务器,您可以调用 logout 来注销 Web 服务器的客户端,并把属于所有用户的所有 session 会话设置为无效。
  • web.xml 配置:如果您使用的是 Tomcat,除了上述方法,您还可以在 web.xml 文件中配置 session 会话超时,如下所示:
  <session-config>
    <session-timeout>15</session-timeout>
  </session-config>

上面实例中的超时时间是以分钟为单位,将覆盖 Tomcat 中默认的 30 分钟超时时间。

在一个 Servlet 中的 getMaxInactiveInterval() 方法会返回 session 会话的超时时间,以秒为单位。所以,如果在 web.xml 中配置 session 会话超时时间为 15 分钟,那么 getMaxInactiveInterval() 会返回 900。


数据库的连接

这节暂时没学数据库,等学了再回来学。


文件上传

步骤:

①建立一个Upload.jsp:用html form标签提供浏览器页面上传渠道,和提交按钮。

②建立一个servlet:来进行文件处理,如保存文件,传递消息给③中文件。

③建立一个ShowResult.jsp:接收servlet中信息,并显示反馈给浏览器。

Upload.jsp:

要点说明:

<form action="UploadServlet" method="post" enctype="multipart/form-data"/>
  • method只能为POST
  • enctype要是多媒体格式
  • 多个文件上传时,要使用多个<input ... />标签。

UploadServlet.java:

要点说明:

  • 可以没有doGet,代码必须写在doPost中

  • 使用类:

    • DiskFileItemFactory类:配置上传文件项目的内存临界值、临时存放目录等。

    • ServletFileUpload upload = new ...(factory):servlet文件上传类,配置上传的属性:文件最大字节数、包含表单的最大字节数、字节编码等。

    • FileItem:来接收解析的文件项目。 = upload.parseRequest(new ServletRequestContext(request));

    • File:建立一个文件来接收FileItem。

  • 将成功或错误信息交给ShowResult.jsp:request.getServletContext().getRequestDispatcher("/Showresult.jsp").forward(request,response);

实例:https://www.runoob.com/servlet/servlet-file-uploading.html或者ubuntu eclipse/workspace/Upload.jsp...

ShowResult:

一张html,将收到的message发送给浏览器。

body里面放入这个即可:

<center>
        <h2>${message}</h2> 
</center>

servlet处理日期

  • Date类

  • SimpleDateFormat类

    使用保留ASICC码来识别年月日时等

    字符 描述 实例
    G Era 指示器 AD
    y 四位数表示的年 2001
    M 一年中的月 July 或 07
    d 一月中的第几天 10
    h 带有 A.M./P.M. 的小时(1~12) 12
    H 一天中的第几小时(0~23) 22
    m 一小时中的第几分 30
    s 一分中的第几秒 55
    S 毫秒 234
    E 一周中的星期几 Tuesday
    D 一年中的第几天 360
    F 所在的周是这个月的第几周 2 (second Wed. in July)
    w 一年中的第几周 40
    W 一月中的第几周 1
    a A.M./P.M. 标记 PM
    k 一天中的第几小时(1~24) 24
    K 带有 A.M./P.M. 的小时(0~11) 10
    z 时区 Eastern Standard Time
    ' Escape for text Delimiter
    " 单引号 `


网页重定向

方法:

①response.sendRedirect(String location),就可以重定向。

②Servlet通过设置状态码和响应头,返回给浏览器,随后浏览器访问重定向后的页面。

...

String site = "http://www.baidu.com";

response.setStatus(response.SC_MOVED_TEMPORARILY); //临时地移动

response.setHeader("Location",site);

...

说明:site:如果不加http://则默认为当前目录下的地址。


网页点击量

简单实现:

①创建全局成员变量int hitCount;

②每次doGet、doPost自增。

拓展:如果需要在服务器重启后能续接上,则可以在销毁destroy时,将其放入数据库,初始化时,将其从库中取出。(或者存在文件中,切记:文件写入流会清空文件,需要在读取后再建立。)

整个网站的点击量,可以利用过滤器。


自动刷新时间:通过response,将头信息传回给浏览器:

response.setIntHeader("Refresh","5");每5秒刷新一次

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342