目录
前言
本章主要内容是servlet的部署、创建与运行、servlet的工作原理、通过JSP的页面访问servlet、共享变量、doPost和doGot方法、重定向与转发和使用session。难点是servlet的工作原理和重定向与转发。
6.1 servlet的部署、创建与运行
6.1.1源文件及字节码文件
1.Servlet类
写一个创建servlet的类就是编写一个特殊类的子类,这个特殊的类就是javax.servlet.http包中的HttpServlet类。HttpServlet实现了Servlet接口,实现了响应用户的方法(这些方法将在后续内容中讲述)。HttpServlet的子类被习惯地称作一个Servlet类,这样的类创建的对象习惯地被称作一个servlet。
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_1 extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
//设置响应的MIME类型:
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();//获得向用户发送数据的输出流。
out.println("<html><body bgcolor = #ffccff>");
out.println("<h1>hello servlet,你好 servlet</h1>");
out.println("</body></html>");
}
}
2.字节码文件的保存
字节码文件按着类的包名对应的目录路径保存到Web服务目录中特定子目录中。
6.1.2 编写部署文件web.xml
Servlet类的字节码文件保存到指定的目录后,必须为Tomcat服务器编写一个部署文件,只有这样,Tomcat服务器才会用Servlet类创建servlet对象。
部署文件是一个XML文件,名字必须是web.xml。
web.xml由Tomcat服务器负责管理,xml文件是由标记(元素)组成的文本文件,Tomcat服务器配有内置的解析器,可以解析XML文件的标记中的数据。
编写的web.xml文件必须保存到Web服务目录的WEB-INF子目录中,比如ch6\WEB-INF中(不要保存在ch6中)。根据例子6_1给出的Servlet类,web.xml文件的内容如下(需要用纯文本编辑器编辑web.xml)
<?xml version="1.0" encoding="utf-8" ?>
<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>moon.sun.Example6_1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/lookHello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>lookPic</servlet-name>
<servlet-class>moon.sun.Example6_2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>lookPic</servlet-name>
<url-pattern>/lookPic</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>computeBill</servlet-name>
<servlet-class>moon.sun.Example6_3_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>computeBill</servlet-name>
<url-pattern>/computeBill</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>circle</servlet-name>
<servlet-class>moon.sun.Example6_4_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>circle</servlet-name>
<url-pattern>/circle</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>computePI</servlet-name>
<servlet-class>moon.sun.Example6_5_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>computePI</servlet-name>
<url-pattern>/computePI</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>sumORproduct</servlet-name>
<servlet-class>moon.sun.Example6_6_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sumORproduct</servlet-name>
<url-pattern>/sumORproduct</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>handleForward</servlet-name>
<servlet-class>moon.sun.Example6_7_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>handleForward</servlet-name>
<url-pattern>/handleForward</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>sort</servlet-name>
<servlet-class>moon.sun.Example6_7_Servlet_Sort</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sort</servlet-name>
<url-pattern>/sort</url-pattern>
</servlet-mapping >
<servlet>
<servlet-name>sum</servlet-name>
<servlet-class>moon.sun.Example6_7_Servlet_Sum</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sum</servlet-name>
<url-pattern>/sum</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>guess</servlet-name>
<servlet-class>moon.sun.Example6_8_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>guess</servlet-name>
<url-pattern>/guess</url-pattern>
</servlet-mapping>
</web-app>
一个XML文件应当以XML声明作为文件的第一行,在其前面不能有空白、其他的处理指令和注释。
XML声明以"<? xml"表示开始、以"?>"标识结束。注意"<?"和xml之间,以及"?"和">"之间不要有空格。
1.根标记
xml文件必须有一个根标记,web.xml文件的根标记是 web-app,根标记 web-app 的开始标签是web-app>,结束标签是</web-app>,开始标签和结束标签之间的内容称作根标记的内容。
2.servlet 标记及子标记
web-app 根标记里可以有若于个 servlet 标记(称作根标记的子标记,该标记的开始标签是servlet >,结束标签是</servlet >,开始标签和结束标签之间是 servlet 标记的内容servlet标记需要有两个子标记:servlet-name 和 servlet-class,其中 servlet-name 标记的内容是Tomcat服务器创建的 servlet 的名字,servlet-class 标记的内容告知 Tomcat 服务器用哪个Servlet类来创建servlet。在我们给出的 web.xml文件中,让 Tomcat 服务器使用例6_1给出的Example6_1类创建的名字是 hello 的 servlet。web.xml文件可以有若干个 servlet 标记(一个servlet 标记部署一个servlet 对象),但要求它们的< servlet-name >子标记的内容互不相同,即服务器可以创建多个 servlet,它们的名字必须互不相同。
6.1.3 servlet的创建与运行
用户就可以根据web.xml部署文件来请求Tomcat服务器创建并运行一个servlet。
如果Tomcat服务器没有名字为hello的servlet,就会根据web.xml文件中servlet标记的子标记servlet-class指定的Servlet类创建一个名字为hello的servlet。因此,如果名字是hello的servlet被创建之后,又修改Java源文件、编译得到新的Servlet类,并希望Tomcat服务器用新的Servlet类创建servlet,那么就要重新启动Tomcat服务器。根据6.1.2中的web.xml文件,用户需在浏览器输入:
http://127.0.0.1:8080/ch6/lookHello
请求Tomcat服务器运行名字是hello的servlet。
6.1.4 向servlet传递参数的值
在请求一个servlet时,可以在请求的url-pattern中额外加入参数及其值,格式是:
url-pattern?参数1=值&参数2=值…参数n=值
那么被请求的servlet就可以使用request对象获取参数的值,例如:
request.getParameter(参数n)
package moon.sun;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.geom.*;
import javax.imageio.ImageIO;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_2 extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
request.setCharacterEncoding("utf-8");
double width = Double.parseDouble(request.getParameter("width"));
double height = Double.parseDouble(request.getParameter("height"));
response.setContentType("image/jpeg");
Ellipse2D ellipse=new Ellipse2D.Double(400-width/2,300-height/2,width,height);
BufferedImage image = getImage(ellipse);
try {
OutputStream outClient= response.getOutputStream();//指向用户端的输出流。
boolean boo =ImageIO.write(image,"jpeg",outClient);
}
catch(Exception exp){}
}
BufferedImage getImage(Shape shape){ //得到图形的图像
int width=800, height=600;
BufferedImage image =
new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
Graphics2D g_2d=(Graphics2D)g;
g_2d.setColor(Color.blue);
g_2d.fill(shape);
return image;
}
}
6.2 servlet的工作原理
servlet由Tomcat服务器负责管理,Tomcat服务器通过读取web.xml,然后创建并运行servlet。
6.2.1 servlet 对象的生命周期
servlet由Tomcat服务器负责创建并完成初始化工作。当多个用户请求一个servlet时,服务器为每个用户启动一个线程。
一个servlet的生命周期主要有下列三个过程组成:
(1) servlet第一次被请求加载时,服务器创建servlet,servlet调用init方法完成必要的初始化工作。
(2) 新诞生的servlet再调用service方法响应用户的请求。
(3) 当服务器关闭时,调用destroy方法销毁servlet。
init方法只被调用一次。当后续的用户请求servlet服务时,Tomcat服务器将启动一个新的线程,在该线程中,servlet调用service方法。也就是说,每个用户的每次请求都导致service方法被调用执行,其执行过程分别运行在不同的线程中。
6.2.2 init方法
public void init(ServletConfig config) throws ServletException
servlet第一次被请求加载时,服务器创建一个servlet,这个对象调用init方法完成必要的初始化工作。该方法在执行时,服务器会把一个SevletConfig类型的对象传递给init()方法,这个对象就被保存在servlet中,直到servlet被销毁。
6.2.3 service方法
public void service(HttpServletRequest request HttpServletResponse response)throw ServletException,IOException
Tomcat服务器将两个参数传递给该方法。和init方法不同的是,init方法只被调用一次,而service方法可能被多次的调用。当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。
6.2.4 destroy方法
public destroy()
当Tomcat服务器终止服务时,destroy()方法会被执行,销毁servlet.子类可直接继承这个方法,一般不需要重写。
6.3 通过JSP页面访问servlet
按着部署文件web.xml给出的servlet的url-pattern,用户除了可以在浏览器输入url-pattern请求运行一个servlet外,也可以通过JSP页面来请求一个servlet。
需要特别注意的是,如果web.xml文件中给出的servlet的url-pattern是/lookHello,那么JSP页面请求servlet时,必须要写成 lookHello,不可以写成/lookHello。
1.通过表单向servlet提交数据
如果web.xml文件中给出的servlet的url-pattern是/computeBill,那么form表单中action给出的值就是computeBill :
<form action= "computeBill " >
</form>
当请求一个servlet时,也可以在请求的url-pattern中额外加入参数及其值,格式是:
url-pattern?参数1=值&参数2=值…参数n=值
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<form action="computeBill?discount=6" id= textStyle method=post>
输入账单:<br>
<textArea name='billMess' id =textStyle rows=5 cols=30 >
剁椒鱼头:62.9元,烤鸭:199元,红焖大虾:289.9元。
</textArea>
<br><input type=submit id=textStyle value="提交">
</form>
</body></HTML>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Example6_3_Servlet extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response)
throws IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("<html><body bgcolor=yellow>");
String discountMess=request.getParameter("discount");
double discount = Double.parseDouble(discountMess);
String billMess=request.getParameter("billMess");
if(billMess == null) {
out.print("没有账单");
return;
}
double bill = getPriceSum(billMess); //账单金额。
double billDiscount = bill*(discount/10); //优惠后的金额。
out.print("<h2>"+billMess+"<br>消费:"+bill+"圆");
out.print("优惠"+discount+"折<br>后的金额:"+billDiscount+"圆");
out.print("</h2></body></html>");
}
public double getPriceSum(String input){ // 定义方法
Pattern pattern; //模式对象
Matcher matcher; //匹配对象
String regex="-?[0-9][0-9]*[.]?[0-9]*" ;//匹配数字的正则表达式
pattern = Pattern.compile(regex); //初试化模式对象
matcher = pattern.matcher(input); //初始化匹配对象,用于检索input
double sum = 0;
while(matcher.find()) {
String str = matcher.group();
sum += Double.parseDouble(str);
}
return sum;
}
}
2.通过超链接访问servlet
JSP页面可以使用超链接去请求某个servlet。如果web.xml文件中给出的请求servlet的url-pattern是/circle,那么超链接标记中href的值是circle(不要写成/circle):
<a href="circle"></a>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.geom.*;
import javax.imageio.ImageIO;
public class Example6_4_Servlet extends HttpServlet{
HttpServletRequest request;
HttpServletResponse response;
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response)
throws IOException{
this.request = request;
this.response = response;
request.setCharacterEncoding("utf-8");
String mess = request.getParameter("mess");
String radius = request.getParameter("radius");
if(mess.equals("area")) {
getArea(Double.parseDouble(radius));
}
else if(mess.equals("geometry")){
getGeometry(Double.parseDouble(radius));
}
}
void getArea(double r) throws IOException{
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
double area = Math.PI*r*r;
String result = String.format("%.2f",area);
out.print("<h2>半径"+r+"圆的面积(保留2位小数):<br>");
out.print(result);
out.print("</h2></body></html>");
}
void getGeometry(double r) throws IOException{
response.setContentType("image/jpeg");
Ellipse2D ellipse= new Ellipse2D.Double(30,30,2*r,2*r);
BufferedImage image = getImage(ellipse);
OutputStream outClient= response.getOutputStream();
boolean boo =ImageIO.write(image,"jpeg",outClient);
}
BufferedImage getImage(Shape shape){ //得到图形的图像
int width=800, height=600;
BufferedImage image =
new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
Graphics2D g_2d=(Graphics2D)g;
g_2d.setColor(Color.blue);
g_2d.fill(shape);
return image;
}
}
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<% double r = 100.8;
%>
<p id=textStyle>
<a href ="circle?mess=area&radius=<%= r %>">看半径<%=r%>圆的面积。</a><br>
<a href ="circle?mess=geometry&radius=<%=r%>">看半径<%=r%>圆的图形。</a>
</p></body></HTML>
6.4 共享变量
Servlet类是HttpServlet的一个子类,在编写子类时就可以声明某些成员变量,那么,请求servlet的用户将共享该servlet的成员变量。
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<HTML><body bgcolor=#ffccff>
<p style="font-family:宋体;font-size:36;color:blue">
<a href="computePI" >参与计算PI的值</a>
</p></body></HTML>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_5_Servlet extends HttpServlet{
double sum=0,i=1,j=1; //被所有用户共享
int number=0; //被所有用户共享
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public synchronized void service(HttpServletRequest request,
HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("<html><body bgcolor=cyan>");
number++;
sum=sum+i/j;
j=j+2;
i = -i;
out.println("<h1>servlet:"+getServletName()+
"已经被请求了"+number+"次");
out.println("<br>现在PI的值是:");
out.println(4*sum);
out.println("</h1></body></html>");
}
}
6.5 doGet和doPost方法
HttpServlet类除了init、service、destroy方法外,该类还有两个很重要的方法:doGet和doPost,用来处理用户的请求并作出响应。
实际上HttpServlet类所给出的service方法的功能是检查HTTP请求类型(get、post),并在service方法中根据用户的请求方式,在service方法中对应地再调用doGet或doPost方法。
因此,在编写的Servlet类(HttpServlet类的一个子类)时,也可以不重写service方法来响应用户,直接继承service方法即可。
如果不重写service方法,就需要在Servlet类中重写doPost或doGet方法来响应用户的请求。如果不论用户请求类型是post还是get,Tomcat服务器的处理过程完全相同,那么可以只在doPost方法中编写处理过程,而在doGet方法中再调用doPost方法即可,或只在doGet方法中编写处理过程,而在doPost方法中再调用doGet方法。如果根据请求的类型进行不同的处理,就要在两个方法中编写不同的处理过程(这一点比service方法更为灵活)
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<form action="sumORproduct" id =textStyle method=post>
输入数字,用逗号分隔提交给servlet(post方式):
<br><input type=text id =textStyle name="number"/>
<input type=submit id =textStyle value="提交">
</form>
<form action="sumORproduct" id =textStyle method=get>
输入数字,用逗号分隔提交给servlet(get方式):
<br><input type=text id =textStyle name="number"/>
<input type=submit id =textStyle value="提交"/>
</form>
</body></HTML>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_6_Servlet extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("<html><body bgcolor=cyan>");
String s=request.getParameter("number");
String []a=s.split("[,,]+");
double sum = 0;
for(String item:a) {
if(item.length()>=1)
sum+=Double.parseDouble(item);
}
out.print("<h2>用户的请求方式是"+request.getMethod()+"<br>") ;
for(String item:a) {
if(item.length()>=1)
out.print(item+" ");
}
out.print("<br>的和是"+sum);
out.println("</h2></body></html>");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("<html><body bgcolor=yellow>");
String s=request.getParameter("number");
String []a=s.split("[,,]+");
double product = 1;
for(String item:a) {
if(item.length()>=1)
product*=Double.parseDouble(item);
}
out.print("<h2>用户的请求方式是"+request.getMethod()+"<br>") ;
for(String item:a) {
if(item.length()>=1)
out.print(item+" ");
}
out.print("<br>的乘积是"+product);
out.println("<h2></body></html>");
}
}
6.6 重定向与转发
重定向的功能是将用户从当前页面或servlet定向到另一个JSP页面或servlet。转发的功能是将用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet。本节学习在Servlet类中使用HttpServletResponse类的sendRedirect重定向方法,以及RequestDispatcher类的forward转发方法,并指出二者的区别。
1.sendRedirect方法
重定向方法void sendRedirect(String location)
将用户重新定向到另一个JSP页面或servlet。重定向方法仅仅是将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或servlet的请求(HttpServletRequest对象)转发给所定向的资源。即重定向的目标页面或servlet无法使用request获取用户提交的数据。
执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行。
2.forward方法
RequestDispatcher dispatcher =
request.getRequestDispatcher(JSP页面的URL或servlet的url-pattern);
转发。在步骤(1)中获取的RequestDispatcher对象调用
void forward(ServletRequest request,ServletResponse response) throws ServletException,ava.io.IOException
方法可以将用户对当前JSP页面或servlet的请求转发给RequestDispatcher对象所指定的JSP页面或servlet
dispatcher.forward (request,response);
把用户对当前JSP页面或servlet的请求转变为对转发到的JSP页面或servlet的请求。
RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet,而且将用户对当前JSP页面或servlet的请求传递给转发到的JSP页面或servlet。也就是说,当前页面所转发到的标页面或servlet可以使用request获取用户提交的数据。
3.二者的区别
转发(forwar)和重定向方法(sendRedirect)不同的是,用户可以看到转发到的JSP页面或servlet的运行效果,但是,在浏览器的地址栏中不能看到forward方法转发到的JSP页面的地址或servlet的地址,用户在浏览器的地址栏中所看到的仍然是当前JSP页面的URL或servlet的url-pattern。如果此时刷新浏览器,那么请求将是当前的JSP页面或servlet。所转发到的标页面或servlet可以使用request获取用户提交的数据。而重定向的目标页面或servlet无法使用request获取用户提交的数据。
另外,当servlet中执行forward方法实施转发操作时,Tomcat会立刻结速当前servlet的执行。而servlet中执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行。
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<p id=textStyle>
<form action="handleForward" id= textStyle method=post>
输入数字(用逗号空格或其他非数字字符分隔):<br>
<textArea name='digitData' id =textStyle rows=5 cols=30 >
</textArea>
<br><input type=submit id=textStyle name = submit value="提交(排序数字sort)"/>
<br><input type=submit id=textStyle name = submit value="提交(求数字代数和sum)"/>
</form>
</p></body></HTML>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_7_Servlet extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
RequestDispatcher dispatcher = null; //负责转发的对象。
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String mess = request.getParameter("submit");
String digitData = request.getParameter("digitData");
if(digitData == null ||digitData.length()==0) {
response.sendRedirect("example6_7.jsp");//重定向到输入数据页面。
return;
}
if(mess.contains("sort")) {
dispatcher = request.getRequestDispatcher("sort");//转发给负责排序的servlet
dispatcher.forward(request,response);
}
else if(mess.contains("sum")){
dispatcher = request.getRequestDispatcher("sum");//转发给负责排序的servlet
dispatcher.forward(request,response);
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
}
6.7 使用session
HTTP通信协议是用户与服务器之间一种请求与响应(request/response)的通信协议,属于无状态协议。所谓无状态是指,当用户(浏览器)发送请求给服务器,Tomcat服务器作出响应后,如果同一个用户再发送请求给Tomcat服务器时,Tomcat服务器并不知道就是刚才的那个用户。简单地说,Tomcat服务器不会记录用户的信息。用户在访问一个Web服务目录期间,Tomcat服务器为该用户分配一个session对象(称为用户的会话),Tomcat服务器可以在各个页面以及servlet中使用这个session记录用户的有关信息,而且Tomcat服务器保证不同用户的session对象互不相同。
HttpServletRequest对象request调用getSession方法获取用户的session对象:
HttpSession session=request.getSession(true);
访问某个Web服务目录的用户,在不同的servlet中获取的session对象是完全相同的,不同的用户的session对象互不相同。
实验代码:
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#tom{
font-family:宋体;font-size:26;color:blue
}
</style>
<%
String s ="(20,220)(220,20)(420,220)(220,420)";
%>
<HTML><body bgcolor=#ffccff>
<p id=tom>
<form action="drawPolygon" id= tom method=post>
输入多边形的顶点,格式是(m,n)<br>m,n为整数 0<=m<=800,0<=n<=600<br>
<textArea name="polygonVertex" id =tom rows=5 cols=30 >
<%= s %>
</textArea>
<br><input type=submit id=tom value="提交"/>
</form>
</p></body></HTML>
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.awt.geom.*;
import javax.imageio.ImageIO;
public class DrawPolygon_Servlet extends HttpServlet{
HttpServletRequest request;
HttpServletResponse response;
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response)
throws IOException{
request.setCharacterEncoding("utf-8");
String polygonVertex = request.getParameter("polygonVertex");
if(polygonVertex == null||polygonVertex.length()==0){
response.sendRedirect("inputVertex.jsp");//重定向到输入数据页面。
return;
}
response.setContentType("image/jpeg");
Polygon polygon = getPolygon(polygonVertex);
BufferedImage image = getImage(polygon);
OutputStream outClient= response.getOutputStream();
boolean boo =ImageIO.write(image,"jpeg",outClient);
}
Polygon getPolygon(String polygonVertex){ //得到多边形。
Polygon polygon = new Polygon();
Pattern pattern; //模式对象。
Matcher matcher; //匹配对象。
String regex="(\\d+[,, ]+\\d+)" ;//匹配顶点的正则表达式。
pattern = Pattern.compile(regex); //初试化模式对象。
matcher = pattern.matcher(polygonVertex); //用于检索polygonVertex。
while(matcher.find()) {
String str = matcher.group();
String []vertex = str.split("[( ),, ]+");
polygon.addPoint(Integer.parseInt(vertex[0]),Integer.parseInt(vertex[1]));
}
return polygon;
}
BufferedImage getImage(Shape shape){ //得到图形的图像。
int width=1000, height=800;
BufferedImage image =
new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
Graphics2D g_2d=(Graphics2D)g;
g_2d.setColor(Color.blue);
g_2d.draw(shape);
return image;
}
}
总结
Java Servlet 的核心是在服务器端创建响应用户请求的对象,即创建 servlet 对象。servlet对象第一次被请求加载时,服务器创建一个 servlet 对象,这个对象调用 init 方法完成必要的初始化工作。init 方法只被 servlet 对象调用一次,当后续的客户请求该servlet 对象服务时,服务器将启动一个新的线程,在该线程中,servlet 对象调用 service方法响应客户的请求。每个客户的每次请求都导致 service 方法被调用执行,调用过程运行在不同的线程中,互不干扰。
Servlet 类继承的 service 方法检查 HTTP 的请求类型(get 、post 等),并在 service 方法中根据用户的请求方式,对应地调用 doGet 或 doPost 方法。因此,Servlet 类不必重写service 方法,直接继承该方法即可。可以在 Servlet 类中重写 doPost 或 doGet 方法来响应用户的请求。
RequestDispatcher 对象可以把用户对当前JSP 页面或 servlet 的请求转发给另一个JSP页面或 servlet,而且将用户对当前JSP 页面或 servlet 的请求和响应传递给转发到的JSP页面或 servlet。也就是说,当前页面所要转发到的目标页面或 servlet 对象可以使用request 获取用户提交的数据以上就是本章内容。