Servlet服务器端编程初解
Servlet是一种运行在服务器端的Java程序,也可以说是服务器端的应用程序。它能够像CGI脚本一样扩展Web服务器的功能,且比CIG具有更高的效率,功能强大与平台无关等。
1、Servlet简介
Servlet即Java服务小程序,是使用应用程序设计接口以及相关类和方法的Java程序。它可以作为一种插件,像Applet一样嵌入到Web服务器中运行。Servlet主要用于处理和客户之间的通信,当客户传来一个HTTP请求时,通过调用Servlet方法来向客户端发送一个相应。与其他的动态网页编程技术相比,Servlet技术有很多自己特有的优点:
l 高效性:在传统的CGI中,当HTTP服务器收到对CGI程序的请求时,每一个请求都将启动一个新的线程。当有大量用户请求调用CGI应用程序是,多个CGI应用程序的执行将导致服务器的大量负载,会严重影响服务器系统性能。而在Servlet中,Servlet运行在一个进程中,该进程开始于服务器首次访问该Servlet,一直运行到基于该Servlet的程序结束。每一个客户端的请求响应都是对于该进程的一个线程进行相应,即每一个请求建立一个进程,Servlet的效率自然比CGI高出很多。
l 功能强大:在Servlet中,许多使用传统CGI程序很难完成的任务都可以轻松地完成,如Servlet能够直接和Web服务器交互,而普通的CGI却不能。Servlet能够在各个程序之间共享数据,使得数据库的功能很容易实现。
l 可移植性好:Servlet是用Java编写的,因为Java是可移植的面向对象程序设计语言,所以Servlet无须任何实质上的改动即可移植到Apache、Microsoft IIS或其他的Web服务器上。
l 使用方便:Servlet提供了大量的使用工具例程,例如自动地解析HTML表单数据、读取和设置HTTP相应头、处理Cookie、跟踪会话状态等。
2、Servlet常用接口介绍:
与Servlet有关的接口主要包括以下几种:
l Servlet异常相关
l Servlet配置相关
l Servlet实现相关
l 请求与相应相关
l 会话相关
l Servlet上下文
l 过滤
1)、异常相关
相关类主要包括ServletException和UnavailabelException。ServletException类扩展了Exception类,其构造如下:
>ServletException()
>ServletException(String message)
2)、配置相关
与Servlet配置相关的接口是java.servlet.ServletConfig接口。Servlet配置包括Servlet的名字、Servlet类的名字以及初始化参数等内容。下面的代码就是一个Servlet的配置。
<servlet>
<servlet-name>Welcome(/sevlet-name)
<servlet-class>cn.dt.web.Welcome</servlet-class>
</servlet>
<servlet-mapping >
<servlet-name>Welcome</servlet-name>
<url-pattern>/Welcome</url-pattern>
<servlet-mapping >
Java.servlet.ServletConfig接口中提供了很多的方法,常用的如下:
方法 | 说明 |
getInitParameter(String name) | 返回指定名称的参数的字符串 |
getInitParameterNames() | 返回Servlet的所有初始化参数的名字,返回值为一个枚举类型对象 |
getServletContext() | 返回当前Servlet正在执行的那个上下文的引用 |
getServletName() | 返回当前Servlet实例的名字 |
getContext(String uripath) | 返回由参数指定的一个ServletContext对象 |
Long(String msg) | 想Servelt的日志文件中写入信息 |
getServerInfo() | 返回当前运行的Servlet容器的名称和版本号码 |
getAttribute(String name) | 返回由参数指定的名字 |
getAttributeNames() | 返回容器中所有属性的名称 |
getServletContextName() | 返回当前Web应用程序的ServletContext的名字 |
3)、实现相关
与Servlet实现相关的接口和类主要包括Servlet接口、GenericServlet类和HttpServlet类。
(1)、Servlet接口
Servlet接口是所有Servlet必须直接或间接实现的接口,它定义了一些方法用来初始化Servlet、接受客户端的请求、响应客户端请求以及销毁一个Servlet。下面是Servlet接口的常用方法:
方法 | 说明 |
Destroy() | 销毁Servlet |
getServletConfig() | 获取Servlet配置相关的信息 |
getServletInfo() | 获取Servlet的信息 |
Init(ServletConfig config) | 用于初始化Servlet |
Service(ServletRequest req , ServletResponse res) | 这是运行应用程序逻辑的入口点,它接收练个参数,客户端请求信息ServletRequest和对客户端的响应ServletResponse |
(2)、GenericServlet类
Javax.servlet.GenericServlet类是一个抽象类,提供了对Servlet接口的基本实现。GenericServlet的service()方法是一个抽象方法,GenericServlet类的子类必须直接或间接地实现service()方法。下面是GenericServlet类的常用方法:
方法 | 说明 |
getServletConfig() | 返回一个ServletConfig对象 |
getServletContext() | 返回Servlet上下文的引用 |
getServletName() | 返回当前Servlet实例的名字 |
getServletInfo() | 返回当前Servlet的有关信息 |
Log(String msg) | 将信息写入Servlet的文件中 |
Service(ServletRequest req , ServletResponse res) | 用来响应客户端的请求 |
(3)、HttpServlet类
是针对shiyongHTTP协议的Web服务器的Servlet类。HttpServlet类扩展了GenericServlet类,同时HttpServlet类也是一个抽象类。要扩展该类,需要实现以下方法中的一个或多个。下表是HttpServlet子类必须实现的方法:
方法 | 说明 |
doGet(HttpServletRequest req , HttpServletResponse res) | 支持Http Get请求 |
doPost(HttpServletRequest req , HttpServletResponse res) | 支持Http Post请求 |
doPut(HttpServletRequest req , HttpServletResponse res) | 支持Http Put请求 |
doDelete(HttpServletRequest req , HttpServletResponse res) | 支持Http Delete请求 |
Init() | 初始化Servlet所需资源 |
Destroy() | 销毁Servlet占用的资源 |
getServletInfo | 获取Servlet自身的信息 |
4)、请求与响应相关
方法 | 说明 |
ServletInputStream | Servlet的输入流 |
ServletOutputStream | Servlet输出流 |
ServletRequest | 代表Servlet请求的一个接口 |
ServletResponse | 代表Servlet响应的一个接口 |
ServletRequestWrapper | 该类实现ServletRequest接口 |
ServletResponseWrapper | 该类实现ServletResponse |
HttpServletRequest | 继承了ServletRequest接口,表示HTTP请求 |
HttpServletResponse | 继承了ServletResponse接口,表示HTTP请求 |
HttpServletRequestWrapper | HttpServletRequest的实现 |
HttpServletResponseWrapper | HttpServletResponse的实现 |
上面给出的类和接口中,最主要的是HttpServletRequest和HttpServletResponse接口
>HttpServletRequest最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据。同时HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求并且接收请求的服务器端主机名及IP地址,还可以获取客户端正在使用的通信协议等信息。
>HttpServletResponse接口是在Servlet中当服务器响应客户端的一个请求时用到。设置相应的类型可以使用setContentType方法。发送字符数据可以使用getWriter()返回一个对象。
下面是一个使用HttpServletRequest和HttpServletResponse的实例程序。如果你使用的是Eclipse下的Web开发环境,则在工程目录下的”Deployment Descripter:工程名”中,右键Servlets → new → Servlet,新建一个名为StuInfo的文件:
StuInfo.java:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/StuInfo")
public class StuInfo extends HttpServlet {
private static final long serialVersionUID = 1L;
public StuInfo() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置响应类型
//获取PrintWriter对象,用来向客户端输出内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>基本信息</title>");
out.println("</head>");
out.println("<body>");
out.println("<h2>学生的基本信息</h2>");
out.println("<h2>姓名:" + request.getParameter("sname") + "</h2>");
out.println("<h2>学号:" + request.getParameter("snumber") + "</h2>");
out.println("<h2>班级:" + request.getParameter("sclass") + "</h2>");
out.println("</body>");
out.println("</html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
WebContent目录下建立Info.thml:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="StuInfo" name="myform" method="post">
姓名 <input type="text" name="sname"> <br>
学号 <input type="text" name="snumber"><br>
班级 <input type="text" name="sclass"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
5)、会话相关
与会话相关的接口主要是java.sevlet.http.HttpSession接口。HTTP客户端和HTTP会话两者之间的关联是通过HttpSession接口实现的。这种关联可以维持指定的时间,同时也可以跨越多个连接或用户页面请求。一个session只负责和一个用户通信,并存储该用户的有关信息。HttpSession接口提供了一些方法供开发者使用,下面是HttpSession接口的常用方法:
方法 | 说明 |
getAttribute(String name) | 返回session中指定名字的对象 |
getAttributeNames() | 返回当前session中的所有属性对象,其结果为枚举对象 |
getCreationTime() | 返回当前session被创建的时间 |
getId() | 返回关于session的一个ID号 |
getLastAccessedTime() | 返回最后一次客户端发送与当前session相关联的请求的时间 |
getMaxInactiveInterval() | 返回当前session处于活动状态之间间隔的最大时间 |
Invalidate() | 销毁session对象,使与之绑定的对象失效 |
removeAttribute(String name) | 删除与指定name相关联的session |
setAttribute(String name , Object value) | 使用name绑定一个对象存储在session中 |
setHeader(String name , String value) | 用给定的名字和值设置响应的一个头部 |
下面是一个示例程序:
StudentInfo.java:
@WebServlet("/StudentInfo")
public class StudentInfo extends HttpServlet {
private static final long serialVersionUID = 1L;
public StudentInfo() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置响应类型
//获取PrintWriter对象,用来向客户端输出内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String sname = request.getParameter("sname");
String snumber = request.getParameter("snumber");
String sclass = request.getParameter("sclass");
HttpSession session = request.getSession();
session.setAttribute("name", sname);
session.setAttribute("number", snumber);
session.setAttribute("stclass", sclass);
out.println("<html>");
out.println("<head>");
out.println("<title>会话相关</title>");
out.println("</head>");
out.println("<body>");
out.println("这是一个有关会话相关的页面");
out.println("</body>");
out.println("</html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
Info.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="StudentInfo" name="myform" method="post">
姓名 <input type="text" name="sname"> <br>
学号 <input type="text" name="snumber"><br>
班级 <input type="text" name="sclass"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
ShowInfo.html:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>以下是相关的信息</h2>
<%
String a = (String)session.getAttribute("name");
String b = (String)session.getAttribute("number");
String c = (String)session.getAttribute("stclass");
out.println("姓名:" + a + "<br>");
out.println("学号:" + b + "<br>");
out.println("班级:" + c + "<br>");
%>
</body>
</html>
6)、Servlet上下文
与其有关的接口是javax.servlet.ServletContext,它定义了用于Web应用中的服务器组件关联Servlet容器的方法集合。当Servlet初始化时,Web容器将初始化一个ServletContext环境上下文给Servlet,当前ServletContext对象包含在当前ServletConfig对象中,当前Servlet初始化时,Servlet容器把它提供给Servlet。下面是ServletContext接口的常用方法:
方法 | 说明 |
getAttribute(String name) | 返回Servlet指定名称的对象 |
getAttributeNames() | 返回当前Servlet上下文有效的属性名字 |
GetContext(String uriPath) | 返回与指定URL相符的ServletContext对象 |
getInitParameter(String name) | 返回当前上下文中给出名称的初始化参数的值 |
getMineType() | 返回指定文件的MIME类型 |
getRealPath() | 返回一个真实路径 |
removeAttribute() | 从Servlet上下文中删除指定名字的属性 |
setAttribute(String name , Object obj) | 绑定一个对象到当前Servlet上下文指定的属性名字 |
3、HttpServlet对象
Servlet的请求可能包含多个数据项。当Web容器接收到某个对Servlet的请求时,容器会将请求封装为HttpServlet对象,然后将该对象传递给Servlet中对应的服务方法。实现HttpServlet时,必须至少实现以下方法中的一个方法来处理客户端的请求。其中最主要的方法是doGet()和doPost()方法:
>doGet();
>doPost();
>doPut();
>doDelete();
>doTrace();
>其他方法
1)、doGet
doGet方法用来响应浏览器使用get()方法提取数据的请求。使用get方法提取数据会在浏览器的地址栏中显示正在传递给Servlet的参数及其值,这在系统安全方面可能会带来一些问题:如用户登录时,表单里的用户名和密码要发送到服务器进行验证,如果使用get()方法就会在浏览器的地址栏中显示用户名和密码。下面是一个使用doGet()方法接收客户端数据的程序:
*.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>请输入用户名:</p>
<form action="StudentInfo" name="myform" method="get">
<input type="text" name="usingName"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
StudentInfo.java:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/StudentInfo")
public class StudentInfo extends HttpServlet {
private static final long serialVersionUID = 1L;
public StudentInfo() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置响应类型
//获取PrintWriter对象,用来向客户端输出内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String usingName = request.getParameter("usingName");
out.println("<html>");
out.println("<head>");
out.println("<title>用户登录</title>");
out.println("</head>");
out.println("<body>");
out.println("<br><br>");
if (usingName != null && !usingName.equals("")) {
out.println("欢迎你的访问:" + request.getParameter("usingName"));
out.println("<br><br>");
out.println("欢迎你的访问:" + usingName);
}else {
out.println("请重新输入");
}
out.println("</body>");
out.println("</html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
2)、doPost()
doGet方法可以与doPost方法混用,doGet是接收网页用get方法时调用的,而doPost是用来接收post方法的。Post就是用表单传递过去的,就好像把数据都打包发送去一样,下面通过实例讲解doPost方法的使用:
*.html:
<body>
<form action="StudentInfo" name="myform" method="post">
<h3>请输入内容:</h3>
<textarea rows="4" cols="40" name="usingtext"></textarea><br>
<input type="submit" value="提交">
</form>
</body>
StudentInfo.java:
request.setCharacterEncoding("UTF-8");//设置响应类型
//获取PrintWriter对象,用来向客户端输出内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String usingName = request.getParameter("usingName");
out.println("<html>" + "\r" + "<head>") ;
out.println("\r" + "<title>用户登录</title>" + "\r" + "</head>" + "\r" + "<body>");
out.println("<br>" + "\r" + "<h2>一下是doPost方法获取的数据:</h2>");
out.println("<textarea rows=4 cols=40 name=usingtext>" + request.getParameter("usingtext") + "</textarea>");
out.println("</body>" + "\r" + "</html>");