1.3 编写基础的Servlet应用程序

其实,编写Servlet应用程序出奇简单。只需要创建一个目录结构,并把Servlet类放在某个目录下。本节将教你如何编写一个名为app01aServlet应用程序。最初,它会包含一个Servlet,即MyServlet,其效果是向用户发出一条问候。 要运行Servlet,还需要一个Servlet容器Tomcat是一个开源的Servlet容器,它是免费的,并且可以在任何能跑Java的平台上运行。如果你到现在都还没有安装 Tomcat,先安装Tomcat.

1.3.1编写和编译Servlet类

确定你的机器上有了Servlet容器后,下一步就要编写和编译一个Servlet类。本例中的Servlet类是MyServlet,按照惯例,Servlet类的名称要以Servlet作为后缀。

MyServlet类

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package app01a;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
@WebServlet(
name = "MyServlet",
urlPatterns ={"/my"}
)
public class MyServlet
implements
Servlet
{
private transient ServletConfig servletConfig;
@Override
public void init(ServletConfig servletConfig)
throws ServletException
{
this.servletConfig = servletConfig;
}
@Override
public ServletConfig getServletConfig()
{
return servletConfig;
}
@Override
public String getServletInfo()
{
return "My Servlet";
}
@Override
public void service(ServletRequest request,
ServletResponse response)
throws ServletException,IOException
{
String servletName = servletConfig.getServletName();
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.print("<html><head></head>" +
"<body>Hello from " +
servletName +
"</body></html>");
}
@Override
public void destroy()
{}
}

代码详解

WebServlet注解

1
2
3
4
@WebServlet(
name = "MyServlet",
urlPatterns = { "/my" }
)

WebServlet注解用来声明一个Servlet。命名Servlet时,还可以告诉容器,是哪个URL调用这个Servletname属性是可选的,如有,通常用Servlet类的名称。重要的是urlPatterns属性,它也是可选的,但是一般都是有的。在MyServlet中,urlPatterns告诉容器,当URL样式为:/my时应该调用MyServlet
注意,**URL样式必须用一个正斜杠开头**。

init方法

Servletinit方法只被调用一次,并将private transient变量ServletConfig设为传给该方法的ServletConfig对象:

1
2
3
4
5
6
7
private transient ServletConfig servletConfig;
@Override
public void init(ServletConfig servletConfig)
throws ServletException
{
this.servletConfig = servletConfig;
}

如果想通过Servlet内部使用ServletConfig,只需要将被传入的ServletConfig赋给一个类变量。

service方法

service方法发送字符串“Hello from MyServlet”给浏览器。对于每一个针对Servlet进来的HTTP请求,都会调用service方法

Servlet程序目录结构

Servlet应用程序必须在某一个目录结构下部署。图1.2展示了app01a的应用程序目录。
这个目录结构最上面的 app01a目录就是应用程序目录。在应用程序目录下,是WEB-INF目录。它有两个子目录:

  • classesServlet类及其他Java类必须放在这里面。类以下的目录反映了类包的结构。在图1.2中,只部署了一个类:app01a.MyServlet
  • libServlet应用程序所需的JAR文件要在这里部署。但Servlet APIJAR文件不需要在这里部署,因为Servlet容器已经有它的备份。在这个应用程序中,lib目录是空的。空的lib目录可以删除。

Servlet/JSP应用程序一般都有JSP页面、HTML文件、图片文件以及其他资料。这些应该放在应用程序目录下,并且经常放在子目录下。例如,所有的图片文件可以放在一个image目录下,所有的JSP页面可以放在jsp目录下,等等。
放在应用程序目录下的任何资源,用户只要输入资源URL,都可以直接访问到

WEB-INF目录

如果想让某一个资源可以被Servlet访问,但不可以被用户访问,那么就要把它放在WEB-INF目录下

手动部署

现在,准备将应用程序部署到Tomcat。使用Tomcat时,一种部署方法是将应用程序目录复制到Tomcat安装目录下的webapps目录中。也可以通过在Tomcatconf目录中编辑server.xml文件实现部署,或者单独部署一个XML文件,这样就不需要编辑server.xml了。其他的Servlet容器可能会有不同的部署规则。

部署为WAR文件

部署Servlet/JSP应用程序时,建议将它部署成一个WAR文件。WAR文件其实就是以.war作为扩展名的JAR文件。利用带有JDK或者类似WinZip工具的JAR软件,都可以创建WAR文件。然后,将WAR文件复制到Tomcatwebapps目录下。当开始启动Tomcat时,Tomcat就会自动解压这个war文件。部署成WAR文件在所有Servlet容器中都适用。我们将在第13章讨论更多关于部署的细节。

1.3.3调用Servlet

要测试这个Servlet,需要启动或者重启Tomcat,并在浏览器中打开下面的URL(假设Tomcat配置为监听端口8080,这是它的默认端口):
http://localhost:8080/app01a/my
浏览器显示效果如下:
这里有一张图片

1.2 Servlet

Servlet接口中定义了以下5个方法:

方法 描述
void init(ServletConfig config) throws ServletException 初始化方法
void service(ServletRequest request,ServletResponse response) throws ServletException, java.io.IOException 响应请求方法
void destroy() 销毁Servlet
java.lang.String getServletInfo() 返回Servlet的描述信息
ServletConfig getServletConfig() 返回由Servlet容器传给init方法的ServletConfig对象

注意,编写Java方法签名时,如果方法的返回值类型或者抛出的异常类型和定义这个方法的类不再同一个包下,则返回值类型或异常类型要使用类全名。 正因为如此,在service方法的签名中,由于javax.servlet.ServletException这个类与当前类Servlet位于同一个包中,所以ServletException,可以不用写类全名,而java.io.Exception和当前类javax.servlet.Servlet,不再同一个包下,所以Exception类要写完整的名称。

生命周期方法

initservicedestroy是生命周期方法。Servlet容器根据以下规则调用这3个方法:

  • init方法,当该Servlet第一次被请求时,Servlet容器会调用这个方法。这个方法只调用这一次,在后续请求中将不会再被调用。我们可以利用这个方法执行相应的初始化工作。 调用这个方法时,Servlet容器会传入一个 ServletConfig对象的引用作为init方法的参数。一般来说,你会在init方法体中把ServletConfig对象引用赋给一个类变量。
  • service方法,每当请求Servlet时,Servlet容器就会调用这个service方法。当第一次请求Servlet时,Servlet容器要同时调用init方法和service方法。后续的请求将只调用service方法。
  • destroy方法,当要销毁Servlet时,Servlet容器就会调用这个方法。当要卸载应用程序,或者当要关闭 Servlet容器时,就会发生这种情况。一般会在这个方法中编写清除代码。

非生命周期方法

Servlet中的另外两个方法是非生命周期方法,即 getServletInfogetServletConfig方法:

  • getServletInfo方法,这个方法会返回Servlet的描述。你可以返回有用的或者为null的任意字符串。
  • getServletConfig方法,这个方法会返回由Servlet容器传给init方法的ServletConfig对象。但是,为了让 getServletConfig方法返回一个非null值,必须将传给init 方法的ServletConfig赋给一个类变量。 ServletConfig将在本章的1.6节中讲解。

注意线程安全性。**Servlet实例会被一个应用程序中的所有用户共享**,因此不建议使用类级变量,除非它们是只读的,或者是java.util.concurrent.atomic包的成员。 下一节“编写基础的Servlet应用程序”将介绍如何编写Servlet实现。

第1章 Servlets

Servlet API是开发Servlet的主要技术。掌握Servlet API是成为一名强大的Java web开发者的基本条件,你必须熟悉Servlet API中定义的核心接口和类。 本章介绍了Servlet API,并教你如何编写第一个 Servlet

1.1 Servlet API概览

Servlet API有以下4个Java包:

  • javax.servlet,其中包含定义ServletServlet容器之间契约的类和接口。
  • javax.servlet.http,其中包含定义HTTP ServletServlet容器之间契约的类和接口。
  • javax.servlet.annotation,其中包含标注ServletFilterListener的标注。它还为被标注元件定义元数据。
  • javax.servlet.descriptor,其中包含提供程序化登录 web应用程序的配置信息的类型。

本章主要关注javax.servletjavax.servlet.http的成员。

Servlet技术的核心是Servlet,它是所有Servlet类必须直接或间接实现的一个接口。在编写实现ServletServlet类时,直接实现它。在扩展实现这个接口的类时,间接实现它。 Servlet接口定义了ServletServlet容器之间的契约。

这个契约归结起来就是,**Servlet容器将Servlet类载入内存,并在Servlet实例上调用具体的方法在一个应用程序中,每种Servlet类型只能有一个实例**。

Servlet请求响应过程

用户请求到达时,Servlet容器会调用Servletservice方法,并传入一个ServletRequest实例和一个ServletResponse实例作为service方法的参数。ServletRequest中封装了当前的HTTP请求,因此,Servlet开发人员不必解析和操作原始的HTTP数据。ServletResponse表示当前用户的HTTP响应,通过ServletResponse,使得将响应发回给用户变得十分容易。

对于每一个应用程序,Servlet容器还会创建一个 ServletContext实例。这个对象中封装了上下文(应用程序)的环境详情。每个上下文只有一个ServletContext。 每个Servlet实例也都有一个封装Servlet配置的 ServletConfig
下面来看Servlet接口。上面提到的其他接口,将在本章的其他小节中讲解。

内容提要

ServletJSP是开发Java Web应用程序的两种基本技术。Spring MVCSpring框架中用于Web应用快速开发的一个模块,是当今最流行的Web开发框架之一。
本书是ServletJSPSpring MVC的学习指南。全书内容分为两个部分,第一部分主要介绍ServletJSP基础知识和技术,包括第1章至第15章;第2部分主要介绍Spring MVC,包括第16章至第24章。最后,附录部分给出了Tomcat安装和配置指导,还介绍了Servlet and JSP注解以及SSL证书。
本书内容充实、讲解清晰,非常适合Web开发者尤其是基于JavaWeb应用开发者阅读。

前言

Java Servlet技术简称Servlet技术,是Java开发Web 应用的底层技术。由Sun公司于1996年发布,用来代替 CGI的一门技术,CGI是当时生成Web动态内容的主流技术。CGI技术的主要问题是每个Web请求都需要新启动一个进程来处 理。创建进程会消耗不少CPU周期,导致难以编写可扩 展的CGI程序。而Servlet有着比CGI程序更好的性能, 因为Servlet在处理第一个请求时被创建后就一直保持 在内存中。此后,SUN公司发布了Java Server PagesJSP)技术,以进一步简化servlet程序开发。

自从ServletJSP技术诞生后,涌现出大量的基于 JavaWeb框架来帮助开发人员快速编写Web应用。这 些框架构建于ServletJSP之上,帮助开发人员更加关 注业务逻辑,无须编写重复性(技术)代码。目前, Spring MVC是最为流行的可扩展Java Web应用开发框 架。
Spring MVC又叫Spring Web MVC,是Spring框架 的一个模块,用于快速开发Web应用。MVC代表 Model-View-Controller,是一个广泛应用于GUI开发的 设计模式。该模式不局限于Web开发,也广泛应用在桌 面开发技术上,如Java SwingJavaFX。 下面将简要介绍HTTP、基于ServletJSPWeb编 程,以及本书的章节内容编排。

注意
本书中所有示例代码基于Servlet 3.0JSP 2.3以及Spring MVC 4。 本书假定读者已有Java以及面向对象编程基础。对于Java新手,我们建 议阅读由Budi Kurniawan编写的《Java : A Beginner's Tutorial (Fourth Edition)》(ISBN 9780992133047)一书。