2.7 Servlet介绍 2.7.1 Servlet的开发

2.7 Servlet介绍

前面已经介绍过,JSP的本质就是Servlet,开发者把编写好的JSP页面部署在web容器中之后,web容器会将JSP编译成对应的Servlet。但直接使用Servlet的坏处是:Servlet的开发效率非常低,特别是当使用Servlet生成表现层页面时,页面中所有的HTML标签,都需采用Servlet的输出流来输出,因此极其烦琐。而且Servlet是标准的Java类,必须由程序员开发、修改,美工人员难以参与Servlet页面的开发。这一系列的问题,都阻碍了Servlet作为表现层的使用。
MVC规范出现后,Servlet的责任开始明确下来,仅仅作为控制器使用,不再需要生成页面标签,也不再作为视图层角色使用。

2.7.1 Servlet的开发

前面介绍的JSP的本质就是Servlet,Servlet通常被称为服务器端小程序,是运行在服务器端的程序,用于处理及响应客户端的请求.
Servlet是个特殊的Java类,这个Java类必须继承HttpServlet。每个Servlet都可以响应客户端的请求.

HttpServlet方法

相应特定请求的方法

Servlet提供不同的方法用于响应客户端请求:

  • doGet:用于响应客户端的GET请求。
  • dopost:用于响应客户端的POST请求。
  • doPut:用于响应客户端的PUT请求。
  • doDelete:用于响应客户端的DELETE请求。

事实上,客户端的请求通常只有GETPOST两种,Servlet为了响应这两种请求,必须重写doGeto0donoso两个方法。如果Servlet为了响应4种方式的请求,则需要同时重写上面的4个方法。

service方法

大部分时候,Servlet对于所有请求的响应都是完全一样的。此时,可以采用重写一个方法来代替上面的几个方法:只需重写service()方法即可响应客户端的所有请求
另外,HttpServlet还包含两个方法:

  • init(ServletConfig config):创建Servlet实例时,调用该方法的初始化Servlet资源
  • destroy():销毁Servlet实例时,自动调用该方法的回收资源

通常无须重写initdestroy两个方法,除非需要在初始化Servlet时,完成某些资源初始化的方法,才考虑重写init方法。如果需要在销毁Servlet之前,先完成某些资源的回收,比如关闭数据库连接等,才需要重写destroy方法。

不用为Servlet类编写构造器,如果需要对Servlet执行初始化操作,应将初始化操作放在Servletinit()方法中定义。如果重写了init(ServletConfig config)方法,则应在重写该方法的第一行调用super.init(config)。该方法将调用HttpServletinit方法.

下面提供一个Servlet的示例,该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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package lee;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.*;

// Servlet必须继承HttpServlet类
@WebServlet(name = "firstServlet", urlPatterns = { "/firstServlet" })
public class FirstServlet extends HttpServlet {
// 客户端的响应方法,使用该方法可以响应客户端所有类型的请求
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
// 设置解码方式
request.setCharacterEncoding("GBK");
response.setContentType("text/html;charSet=GBK");
// 获取name的请求参数值
String name = request.getParameter("name");
// 获取gender的请求参数值
String gender = request.getParameter("gender");
// 获取color的请求参数值
String[] color = request.getParameterValues("color");
// 获取country的请求参数值
String national = request.getParameter("country");
// 获取页面输出流
PrintStream out = new PrintStream(response.getOutputStream());
// 输出HTML页面标签
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet测试</title>");
out.println("</head>");
out.println("<body>");
// 输出请求参数的值:name
out.println("您的名字:" + name + "<hr/>");
// 输出请求参数的值:gender
out.println("您的性别:" + gender + "<hr/>");
// 输出请求参数的值:color
out.println("您喜欢的颜色:");
for (String c : color) {
out.println(c + " ");
}
out.println("<hr/>");
// 输出请求参数的值:national
out.println("您来自的国家:" + national + "<hr/>");
out.println("</body>");
out.println("</html>");
}
}

上面的Servlet类继承了HttpServlet类,表明它可作为一个Servlet使用。程序的粗体字代码定义了service方法来响应用户请求。对比该Servlet和2.6.6节中的request1.jsp页面,该Servletrequest1.jsp页面的效果完全相同,都通过HttpServletRequest获取客户端的form请求参数,并显示请求参数的值。
ServletJSP的区别在于:

  • Servlet中没有内置对象,原来JSP中的内置对象都必须由程序显式创建。
  • 对于静态的HTML标签,Servlet都必须使用页面输出流逐行输出。

这也正是前面介绍的,JSPServlet的一种简化,使用JSP只需要完成程序员需要输出到客户端的内容,至于JSP脚本如何嵌入一个类中,由JSP容器完成。而Servlet则是个完整的Java类,这个类的service方法用于生成对客户端的响应。
普通Servlet类里的service方法的作用,完全等同于JSP生成Servlet类的_jspService()方法。因此原JSP页面的JSP脚本、静态HTML内容,在普通Servlet里都应该转换成service方法的代码或输出语句;原JSP声明中的内容,对应为在Servlet中定义的成员变量或成员方法。