Websphere 入门基础 第十一课 IBM WebSphere应用开发实验指导

  Servlet 1A:创建一个简单的客户注册servlet
    Servlet 1B:改进客户注册servelt
    Servlet2:JKToys Login和Toy Display Servlets
    JSP3:JSP页面
    JSPBeans4:JavaServer Pages with Beans
    Studio5:WebSphere Studio Servlet Wizards
    JDBCLab:用JDBC访问一个数据库
    安全:Servlet安全

  Servlet 1A:创建一个简单的客户注册servlet
  在这个练习里,你将创建一个简单的servlet。这个servlet的目的是确认一个新客户在JKToys站点的成功注册。
  在这个练习里你将访问JKToys网站。你从主页选择Kids Zone区域,注册为一个新客户。注册表格和网站的余下部分已经由网站设计者为你提供。在注册表格上按Register me now!按钮,将会调用服务器上的JKRegistration servlet。注册servlet将会用表格的信息注册一个用户,在JKTOYS数据库的CUSTOMER表创建一个新的条目。在注册时,指派一个唯一的客户号码。在下一个练习里你将用这个信息提供一个定制的 HTML页面确认注册。
  第一部分
  对所有的练习,确信你用了id:USERID和口令:PASSWORD登录进系统。
  这个练习的前5个步骤只是给你的信息,请花时间读它们。实际的代码从第二部分开始。
  1. 你将用IBM VisualAge for Java,version 2,Enterprise Edition+Enterprise Update(从现在开始用VAJ指代)来编辑,编译和发表你的练习。现在双击桌面上的图标打开VAJ产品。如果你看到了VAJ的欢迎窗口,选择“取消”按钮,这将放上Workbench窗口。你将看到带有几个包的WASDev项目已经为你预先装载了。选择com.ibm.waslab.servlet1包。在这个包里你将能看到RegistratonServlet类。这个类包含RegistrationServlet和startup methods required for you to complete this exercise.在这个练习里,你将集中注意力于doPost()方法。
  2. JKToys网站已经布置到安装在你的机器上的web server上。这个站点的根目录是:[x]:/www/HTML/JKToys;[X]是web server所在的驱动器字母。网站是用NetObjects Fusion创建的。这个站点的HTML页面在html子目录里。JKToys注册页面的完整的路径是:[x]:/WWW/HTML/JKToys/html/body_jktoys_kids_zone_registraiton.aspl
  3. 你还记得在讲座里提到,当用户按了一个表格上的提交按钮,在我们这里按钮上写着“Register me now!”,浏览器调用HTML <FORM>标记的ACTION子句里规定的URL。看一下HTML文件你将看到<FORM>标记包含以下文字:
  <FORM NAME=”RegistrationForm”
  ACTION=http://127.0.0.1/servlet/JKRegister METHOD=POST>
  向网站设计者提供<FORM>标记的正确的参数是你的责任。
  在ACTION子句里的URL指向主机127.0.0.1,这是一个指向本地主机的IP地址,换句话说,指向你自己的机器。网站设计者也许用“localhost”这个字代替IP地址。
  注意:在某些情况下用”localhost”会降低你的服务器的性能,为了避免这个问题,你必须在你的机器里的一个叫HOSTS的文件里加一行,把localhost和IP地址对应起来。
  在URL里跟在IP地址后面的servlet应用键,使得web server调用WebSphere Applicaiton Server(把HTTP请求传给它)。应用服务器在servlet classpath里配置的某个子目录或jar文件里定位servlet。IBM WebSphere Application Server的缺省servlet classpath是:[x]:/WebSphere/AppServer/servlets目录,[x]是WebSphere安装的目录。
  JKRegister是servlet名字。这不是servlet的真实名字,而是在WebServer里给servlet的名字。在实践中,给servlets名字是很常见的,它降低显示在浏览器上的URL的复杂性和混乱。它还允许你向WebSphere里的你的servlet提供初始参数。按我们的配置,JKRegister被对应为:
com.ibm.waslab.servlet1.RegistrationServlet,这是这个servlet的包和类的名字。
METHOD=POST子句表示在servlet被调用时,servlet的doPost()方法将被service()方法调用。
  4. 正如上面提到的,你的servlet将在doPost()方法里取得控制。选择RegistrationServlet。定位doPost()方法。注意给doPost的两个参数,HttpServletRequest和HttpServletResponse。这些对象让你找出你从哪里来,到哪里去,输入HTML表格的值是什么。在下面的步骤里你将学会怎样用它们。
  5. doPost的开头几行提取输入到表格中的值,在数据库里注册新客户。现在你不需要关心哪个方法实际在数据库里注册了用户,在以后的练习里,你将自己写这个方法,你将学几个访问数据库的方法。你将在这个练习的后半部分写getFormImput()方法。
  //Get the input form contents
  Properties formInput=getFormInput(req);
  //Register new customer in the database
  register(formInput);
  第二部分
  在这个servlet里,当doPost()得到控制,第一个任务是取得用户输入和注册新客户。这是前面讨论的两行代码所作的。最后一步是通知客户注册成功了。
  你在第二部分的任务是写doPost()方法的余下部分,通知用户注册成功。现在打开doPost()方法,看看有些什么:
  public void doPost(HttpServletRequest req,HttpServletResponse res)
  throws ServletException,jiava.io.IOException
  {
  //Get the input form contents
  Properties formInput=getFormInput(req);
  //Register new customer in the database
  register(formInput);
  //Obtain a PrintWriter from response object
  //Set content type on the response header
  //Output confirmation message
  return;
  }
  注释说明了你的代码将要执行的任务。第一个任务是从response取得一个PrintWriter.看看你的课堂笔记,找个例子。如果你还是不懂,看最后的答案部分。得到一个PrintWriter后,你将需要设置response header的内容类型为”text/html”。你再看以下课堂笔记,找个例子吧。
  最后,你将需要输出确认消息。页面的标题应该是”Registration Complete”,包含以下文字:
  Greetings:
  Your registration has been recorded in the database.
  Thank you for your interest in JKToys.
  We look forward to serving you in the future!
  你的课堂笔记给出了在一个Servlet里打印文字的例子。如果你不懂,看最后的答案部分。
  按Ctrl-s,或从右键选项选择”“保存””,保存doPost().记住,在VAJ保存你的方法的时候也编译了你的方法。如果你在编译时得到错误,VAJ会警告你,有时会提供正确的方法名或正确的语法来建议你怎样改正错误。改正你的错误,保存它。如果你不能解决错误,请向你的辅导员请求帮助。
  一旦编译完成而没有错误,你可以试试你的servlet。为了调试的目的,你将在VAJ里运行你的servlet。你的 workspace已经用IBM WebSphere Application Server libraries配置过了。用这个配置你可以在VAJ里使用HTML和servlets。这将允许你在VAJ环境里调试你的servlets.
  测试你的第一个servelt的步骤
  1. 在VAJ里启动web server。打开IBM WebSphere Test Enviroment项目,在包com.ibm.servlet里,选择SERunner类,按Run按钮来启动服务器。你可以看控制台来确定web server是否在运行。它将打印许多行输出。
  2. 然后,启动你的浏览器,在URL输入域输入http://127.0.0.1/JKToys/index.aspl,按enter。这将显示JKToys的主页。从banner选择Kids Zone。在kids zone,单击拖着标语的飞机,这将把你带到注册页面。填入表格的信息,按注册按钮,几秒钟之后你应该得到servlet的回应,表示一个成功的注册。
  如果你真的要确信你的记录已经在数据库里,你可以在JKTOYS数据库的CUSTOMER表上执行一个查询,来看看你自己。你可以在DB2命令行里,或DB2文件夹里的Control Center工具作这个。
  在这个练习里你作了些什么
  在这个练习里你创建了一个将被JKToys的新客户注册表格调用的servlet。你在doPost()方法里增加代码,来提供给客户的反馈,告诉他们注册成功。你现在理解了表格,servlet和回应HTML页面之间的控制流。
  你在你的servlet里动态创建一个HTML页面。在下一个练习里你将使用客户提供的信息进一步定制servlet给客户的回应。你还将检查错误,如表格信息遗漏或数据库问题。
  答案
  在你能向客户送回信息以前,你需要创建一个输出流,你将用这个同浏览器通信。
HttpServletResponse对象有一个方法来获取这样一个流。把下面的代码加到doPost()方法里register()调用的下面:
  //Obtain output stream form response object
  PrintWriter out=res.getWriter();
  也可以创建别的类型的流,要看什么会回到浏览器。PrintWriter尤其适用于送字符串,因为它有打印新行和在一个现存行后面打印的方法,分别是println()和print()。
  现在你已经有一个输出流,你可以开始把你的消息送回浏览器。记住,你实际作的是编辑一个HTML页面,它将被在用户的浏览器上显示。任何有效的HTML页面都可以送回。
  在你送实在的文字以前,你应该设置回应的MIME类型。你用setContentType()方法在回应头里设置内容类型。输入以下行:
  //Set content type on the response header
  res.setContentType(“text/html”);
  你可以输入这些行完成你的HTML页面。
  //Output confirmaiton message
  out.println(“<html>”);
  out.println(“<head><title>Registration Complete</title></head>”);
  out.println(“<body>”);
  out.println(“<h2><br><br>Greetings:</h2>”);
  out.println(“<br>Your registration has been recorded in the database”);
  out.println(“<br>Thank you for your interest in JKToys”);
  out.println(“<br>”);
  out.println(“<h2>We look forward to serving you in the future!</h2>”);
  out.println(“</body></html>”);
  最后,你可以刷新和关闭流。在一个servlet的末尾这么作是可以的,只要你知道这个servlet将不会被另一个servlet调用来提供输出到流。你会在以后的练习里看到,一个servlet可以调用另外的servlets,每一个servlet的输出只是要完成一个HTML页面的所有的信息的一部分。如果任何一个servlet关闭流,主调servlets将不能使用这个流来完成页面的变换。所以当你关闭输出流时要小心。输入以下的行来完成servlet的编码。
  outflush();
  //Closing the output stream is not really necessary
  out.close();
  注意:在设置和在这些练习的指导里,你将会被要求编辑.properties文件。确信你没有使用Notepad。用Wordpad或别的编辑器,保存你的操作系统的原始的句子结束符。
  所有的练习从JKToysDBInfo.properties文件获得访问数据库所需要的参数。在这个文件里,你会看到USERID和PASSWORD等等的定义。如果你需要改变这个文件来适应你的配置,可在以下目录找到:
  d:/IBMVJava/ide/project_resources/WASDev
  d:/WebSphere/AppServer/servlets
  第一个在运行在VAJ里是用,第二个在运行在一个网络服务器时用。

  Servlet 1B:改进客户注册servelt
  在这个练习里你将在输入表格上执行错误检查,发现用户没有填写的字段。对这个例子来说,所有字段都是强制的。
  你将从上一个servlet你丢下的地方开始这个练习。你将从草稿重写getFormInput()方法。这个方法从表格提取参数,返回一个Properties对象,用字段名字作键值。这个方法还检查空白或空参数。你将使用属性对象中的值来定制送回去的确认消息。
  第一部分:创建getFormInput()方法
  1. 在VAJ里打开com.ibm.waslab.Servlet1包里的RegistrationServlet。改变现存的getFormInput()方法的signature,增加以下的”throws”列表。
  Private Properties getFormInput (HttpSErvletRequest req) throws
  InvalidParameterException
  {
  }
  注意:这个方法抛出一个InvalidParameterException,这个异常的类已经提供给你了,在VAJ的com.ibm.waslab.exception包里。
  getFormInput()方法声明为private,返回一个Properties对象,它将包含表格的参数名字和值。它把HttpServletRequest对象作为一个参数,因为它包含原始形式的输入表格的值。
  2. 然后,增加代码检查空白字段。
  注意:在这些指导里,因为印刷的行的长度限制,有很多行代码在纸上被分开了。你应该在VAJ里把  这些行作为一个单独的行输入。
  Properties formInput=new Properties();
  Enumeration fieldNames=req.gerParameterName();
  while (filedNames.hasMoreElemenets())
  {
  String paramName=(String)fieldNames.nextElement();
  String paramValue=(String)
  req.getParamterValues(paramName)[0];

  //check for missing parameters(code to be added)
  if (paramValue.length()= =0)
  throw(new InvalidParameterException(“Required parameter missing”));
  formInput.put(paramName,paramValue);
  }
  return formInput;
  确信你理解所有已经有的代码。第一行声明一个新的Properties对象,命名为formInput,来保存参数名字/值对。然后这个request对象的getParameterNames()方法是用来取得一个所有参数名字的枚举。这些是表格里字段的名字,将被用作formInput properties对象的键值。
  反复通过枚举,你取得参数名字和值。你检查,来确保每一个值有一个比0大的长度。如果长度等于0,一个异常被抛出和处理。如果值的长度比0大,它被保存在formInput,用字段名字作为键值。当枚举里没有更多的元素时,循环结束,返回填好的forminput Properties对象。
  保存getFormInput()方法,重新打开doPost()方法。
  第二部分:处理InvalidParameterException异常
  因为getFormInput()现在可以抛出一个异常,doPost()里的代码得处理这个情况,把这个方法的调用放在一个try/catch块里。修改调用getFormInput()的代码段来处理这个异常。如果异常被抛出,调用方法missingParameterResponse(),这将生成一个错误HTML页面。在异常的情况下,你还将需要从doPost()方法返回,结束事务,不写任何东西到数据库。
  重新提交一个表格来测试代码,这次有一个参数(输入表格上的一个字段)没有填入。错误页面应该被显示,而不是你在前一个练习里编码的成功注册消息。
  第三部分:产生一个定制的输出HTML页面
  1. 在这个部分你将定制用户在记录被存入数据库后看到的信息。你会在页面里显示客户的名字和新指派给客户的客户号码。在register()调用后面输入以下的行:
  //Output confirmation message
  out.println(“<html>”);
  out.println(“<head><title>Registration Complete</title></head>”);
  out.println(“<body>”);
  //modified or additional lines of code are in bold
  out.print(“<h2><br>Greetings:”);
  out.println(“formInput.getProperty(“FNAME”)+”</h2>”);
  out.println(“<br>Your registration has been recorded in the database”);
  out.println(“<br><br>You have been assigned customer number”<strong>” +formInput.gerProperty(“CUSTNO”)+”</strong>);
  out.println(“<br>Thank you for your interest in JKToys”);
  out.println(“<br><h2>We lo“确定” forward to serving you in the future!</h2>”);
  out.println(“<a href=/””+ServletUtil.getClientURL(req)+”  /jktoys/htm/jktoys_kids_zone.aspl/”>”+”Back to the kids Zone!!!</a><br>”);
  out.println(“</body></html>”);
  out.flush();
  out.close();
  return;
  在这个练习里我们假设写数据库成功。在一个真实的应用里,你应该捕捉在register()方法里的任何异常,显示合适的错误信息。
  注意字段的值怎样从属性里提取,插入被建立的HTML页面的正确的地方。
  从底向上第四行建立一个回到注册页面的超链接。ServletUtil.gerClientURL(req)的调用返回URL的第一部分,包含一些东西,象:http://127.0.0.1。http和主机名从请求对象里得到,组合进一个字符串,用来形成这个这个页面的完整的URL。web server的端口号,如果不是80,也要带上。ServletUtil是一个在com.ibm.waslab.common包里向你提供的类。
  2. Property对象里的客户号条目不是原始表格的一部分,而是插入register()方法。这个唯一的号码是从数据库得到的:查询一个现有的最大的客户号,再加1。
  3. 保存doPost()方法。如果你在编译期间得到错误,返回到源代码,改正它们,再编译。如果你不能解决错误,请向你的辅导员请求帮助。
  4. 现在你已经准备好测试你的改进的servelt了。遵从前一个练习里的同样的测试步骤,通过正常的执行路径,输入所有的字段,按register,现在应该得到新的,改进的和定制的祝贺。
  5. 再试一次,让一个或两个字段空白。按register按钮,你应该得到自己的错误HTML页面。
  第四部分:输出和在VisualAge外面运行servlet
  1. 要从“生产”环境运行Registration Servlet,先停止WebSphere Text   Enviroment(SERunner)。
  2. 从VisualAge输出类和源代码到WebSphere Application Server。选择WASDev项目,鼠标右击,选择Export。选择”directory”,击”Next”。按“Browse”按钮,浏览到c:/WebSphere/AppServer/servlets目录。选择.class和源代码。按Finish。这把类文件布置到AppServer。
  3. 启动HTTP Server(Start->Programs->IBM HTTP Server->Start Server)。
  4. 从浏览器访问Registration 页面,象以前一样重新运行Registration场景。
  你在这个练习里做了些什么
  在这个练习里,你学会怎样提取一个表格里的字段的值,和怎样把它们包含在属性里。你使用Properties对象里的信息来生成一个定制的动态的HTML页面。你也处理表格里提供的信息不全的情况,显示一个错误页。
  答案
  Properties formInput=null;
  //Get the input form contens
  try
  {
  formInput=getFormInput(req);
  }
  catch (InvalidParameterException e)
  {
  missingParameterResponse(out);
  return;
  }

  Servlet2:JKToys Login和Toy Display Servlets
  在这个练习里你将学会在一个web会话里用户在许多HTML页面和servlets里移动时维护信息,完成一个事务。
  按照这个练习,你将能用HttpSession类存储在会话里持续的信息。你还将学习怎样阻止在浏览器里缓存页面,来防止缓存的页面显示前一个会话或查询的错误信息。在这个练习里,你将建立三个servlets:
   Login
   DisplayToys
   TotalPurchase
  这个三个servlets的组合将满足用户的需求。对每一个方法,大多数答案代码可以在一个叫cutAndPaste的方法里找到。这将使你在敲键盘敲烦的时候能”cut-and-paste”。
  第一部分:修改Login servlet来保存会话数据
  1. 在VAJ选择com.ibm.waslab.Servlet2包。从这个包里选择LoginSevlet。在doPost()里定位包含下面文字的代码行:
  //Enter code here to retrieve the customer number form the form data
  2. 在那个下面输入以下的代码。这个代码调用getCustomerNumber()方法来提取输入到HTML表格里的客户号。如果Login按钮被按下时客户号码为空,这个方法抛出一个InvalidParameterException;你用outputLoginFailedMessage()显示一个错误消息来处理这个异常。
  String customerNumber=null;
  try
  {
  customerNumber=getCustomerNumber(req);
  }
  catch (InvalidParameterException e)
  {
  //Output failure message
  outputLoginFailedMessage(out,”You did not enter your customer number.”);
  return;
  }
  3. 保存方法。你将得到错误,因为getCustomerNumber()和outputLoginFailedMessage()方法还没有被编码。带着错误保存方法,继续下一步。
  4. 创建getCustomerNumber()方法。这个方法比前一个练习里的同名方法简单得多,因为只有一个字段要从表格里取出来。以下行表示这个方法:
  private String getCustomerNumber(HttpServletRequest req) throws
  InvalidParameterException{
  String paramValue=(String)
  req.getParameterValues(“CUSTNO”)[0];
  //check for missing parameters
  if(paramValue.length()==0)
  throws(new InvalidParameterException(“Required parameter missing”));
  return paramValue;
  }
  保存这个方法,返回到doPost()。
  5. 在doPost()方法的下一行,调用locate()方法来取出对应输入的客户号码的记录:
  //Look for this customer in the database
  JKToysCustomer customer=locate(customerNumber);
  如果没有在数据库里发现客户,返回一个null客户对象,否则的话它包含先前为这个客户号码保存在数据库里的信息。
  6. 如果客户号码没有在数据库里找到,你需要提供一个合适的消息。在locate()调用下面输入这些行:
  //customer will be null if customer not found in the database
  if(customer= =null)
  {
  //Output failure message
  outputLoginFailedMessage(out,”The customer number you entered was not found in our     database.”);
  return;
  }
  7. 继续下面的代码,处理客户号码在数据库里找到的情况:
  else
  {
  //create a session and store the customer information
  HttpSession session=req.getSession(true);
    
  //if there is an existing session,invalidate it and re-create
  if (session.isNew()= = false)
  {
  session.invalidate();
  session=req.getSession(true);
  }
  session.putValue(“CUSTOMER”,customer);
  //Output confirmation message
  //Ensure that no caching takes place in the browser
  res.setHeader(“Pragma”,”no-cache”);
  res.setHeader(“Cache-Control”,”no-cache”);
  res.setDateHeader(“Expires”,0);
  String clientURL=ServletUtil.getClientURL(req);
  out.println(“<html>”);
  out.println(“<head><title>Login complete</title></head>”);
  out.println(“<body>”);
  out.print(“<p><h2>Greetings:”);
  out.println(customer.getFirstName()+” ”+customer.getLastName()+”,from “  +customer.getCity()+”</h2></p>”);
  out.println(“<p>Welcome back to JK Toys</p>”);
  out.println(“<p>what can we do for you? Please select from the options below:</p>”);
  out.println(“<a href=/””+clientURL+”  /jktoys/html/body_jktoys_kids_zone_change.jsp/”>Update registration information</a><br>”  );
  out.println(“a href=/””+clientURL+”/servlet/JKOrderStatus/”>Status of my last   order</a><br>”);
  out.println(“a href=/””+clientURL+”/servlet/JKDisplayToys/”>Display toys for my age group(“+customer.getAge()+”)</a><br>”);
  out.println(“<p>Thank you for your interest in JKToys</p>”);
  out.println(“</body></html>”);
  }
  else语句后面的最初几行创建了一个会话。然后你检查是否是一个新的会话。如果这个会话不是新的,就把它失效掉,再创建一个新的会话。现下你有一个有效的会话了。用一个键值CUSTOMER保存会话里的customer Properties。这个数据将被同一个会话里的servlets使用。
  接下去的三行是必需的,确保浏览器不会缓存servlet产生的页面。如果页面被缓存,它将可能在页面上显示从一个以前的缓存页面得来的错误的信息。
  在这一页有一些定制。我们用客户的全名和城市来祝贺客户。我们也提到他在哪一个年龄组,在:Display Toys for my age group choice。同前一个练习一样,这个客户的数据是用getProperty()方法从customer Properties对象里取出来的。如果你希望,你可以修改HTML标记来修改消息的内容或格式为你更喜欢的样子。
  注意,Display Toys choice的href标记会调用JKDisplayToys servlet。你将在这个练习的下一个步骤里继续做这个servlet。
  保存doPost()方法。现在我们已经准备好写outputLoginFailedMessage()方法来完成这个servlet。这个有用的方法在doPost()里已经被调用了两次,因为需要输出同样的HTML,这两个只有一个句子不一样。我们可以在doPost()方法里编写HTML代码,但是,这是更好的方法。在”New Method”SmartGuide里创建outputLoginFailed(PrintWriter out,Stirng message)方法,输入以下的代码:
  /**
  *This is method prints the generic failure page with a specified message
  *@param out java.io.PrintWriter
  *@param message java.lang.String
  */
  private void outputLoginFailedMessage(PrintWriter out,String message)
  {
  out.println(“<html>”);
  out.println(“<head><title>Login Failed</title></head>”);
  out.println(“<body>”);
  out.println(“<p><h2>Sorry,could not log you in</h2>”);
  out.println(“<p><font color=/”red/”>+message+”</font></p>”);
  out.println(“<p>Please press the <strong>Back</strong>button,and resubmit.</p>”);
  out.println(“<p>Thank you for your interest in JKToys!!!”);
  out.println(“</body></html>”);
  out.flush();
  }
  一旦你输入这个代码,最后的错误应该从doPost()里消失。
确信服务器在VAJ里运行,测试Login servlet。
进入JKToys Kids Zone页面里工作。在有飞行的飞机的页面上,击右边的椭圆图案。它将把你带到Login表格。输入一个你知道的已经存在的客户号码,按Login按钮。你将得到servlet的祝贺。现在试一下无效的客户号码,和一个空白客户号码。确信你在每种情况下都得到了正确的消息。
  第二部分:创建DisplayToysServlet servlet
它将搜查数据库,按照客户的年龄显示玩具。
在VAJ的Servlet2包里,你将找到建了一半的servlet。打开DisplayToysServlet类。
1. 因为这个servlet不是从一个表格调用的,而是从网页上的一个href HTML标记调用的,它的doGet()方法将从servlet的service()方法调用。在doGet()方法里开始工作。在设置回应头不要缓存的代码后面输入这些行:
//Get customer information from session
HttpSession session=req.getSession(false);

  //We should have a previous session,otherwise it’s an error
  if(session= = null)
  {
  //Output failure message
  showError(out);
  return;
  }
  2. 注意,这次你把false作为参数传递给获取session的调用。这么作会只返回一个已经存在的session,而不会创建一个session。如果一个存在的session被找到,下一步是获取包含在session里的JKToysCustomer对象,它包含了客户信息。这个信息是这个练习的第一部分里的LoginServlet存进去的。如果我们有一个session,但是用键CUSTOEMR找不到值,我们就有一个无效的session,你会显示一个错误,然后退出。
  //Create a new Customer and initialize withthe value in the session
  JKToysCustomer customer=(JKToyscustomer)session.getValue(“CUSTOMER”);

  //We should have a customer stored in the session,if not ,it’s an error
  if(custmer= =null)
  {
  //Output failure message
  showError(out);
  return;
  }
  3. 下一行findToys()方法。客户的年龄作为参数被传进去。在这个方法里,数据库被访问,返回一个玩具的向量(vector)。如果没有为这个特定的客户找到玩具,一个null vector被返回。
  //Look for toys in the database for customer’s age group
  Vector toys=findToys(customer.getAge());
  4. 在检查了玩具的向量不为空,displayToys()方法被调用,来建立一个表,显示向量里的玩具。类toy在com.ib.waslab.common包里提供给你。displayToys()方法接受请求对象、玩具向量、客户对象和PrintWriter作为参数。在显示了玩具以后,向量被保存在会话里,以备客户要定购。
  if(toys!=null)
  {
  displayToys(req,toys,customer,out);
  session.putValue(“TOYS”,toys);
  }
  5. 输入以下代码完成displayToys()方法。研究这个代码,看看HTML表是怎样创建的,向量是怎样循环取得所有元素的。
  out.println(“<head><title>Your JK Toys,toys selection</title></head>”);
  out.println(“<body>”);
  out.println(“<p><h2>”+customer.getFirstName()+”,here are the toys we have in stock   for your age group(“+customer.getAge()+”)</h2></p>”);
  //show selected toys in a table
  out.println(“<BR>”);
  //Create form to display and select toys
  out.println(“<FORM NAME=/”JKPurchaseForm/” ACTION=/””  +ServletUtil.getClientURL(req)+”/servlet/JKTotalPurchase/” METHOD=POST>”);
  out.println(“<TABLE>”);
  out.println(“<TABLE BORDER=1”);
  out.println(“<tr bgcolor=#993366>”);
  out.println(“<TH><font color=#FFFFFF>Picture</font>”);
  out.println(“<TH><font color=#FFFFFF>Name</font>”);
  out.println(“<TH><font color=#FFFFFF>Description</font>”);
  out.println(“<TH><font color=#FFFFFF>Price</font>”);
  out.println(“<TH><font color=#FFFFFF>Buy it?</font>”);
  Enumeration selectedToys=toys.elements();
  Toys aToy=null;
  int checkboxNumber=0;
  while (selectedToys.hasMoreElements())
  {
  aToy=(Toy)selectedToys.nextElement();
  out.println(“<TR>”);
  out.println(“<TD><IMG SRC=/”..”+aToy.getThumbnailFile()+”/”>”);
  out.println(“<TD>”+aToy.getShortDescription());
  out.println(“<TD>”+aToy.getFullDescription());
  out.println(“<TD>”+aToy.getPriceAsString());
  String boxId=String.valueOf(checkboxNumber++);
  out.println(“<TD><INPUT id=”+boxId+”/”TYPE=/”checkbox/” NAME=/””+boxId+”/”>”  );
  }
  out.println(“</TABLE>”);
  out.println(“<br><br>”);
  out.println(“<INPUT TYPE=/”submit/” NAME=/”PurchaseButton/” VALUE=/”Purchase   selected toys/” id=/”PurchaseButton/”>”);
  out.println(“</FORM>”);
  out.println(“<p><h2>Thank you for your inteest in JKToys!!!</h2>”);
  out.println(“</body></html>”);
  out.flush();
  out.close();
  return;
  }
  注意,显示玩具的table是在一个form里建立的。table的最后一列包含一个checkbox,用来让客户选择哪些玩具他希望购买。checkbox的名字是从0开始的顺序的数字。它们将被用作索引,从包含所有玩具的向量里提取选择的玩具。这将在TotalPurchaseServlet里作。
  每一个玩具的价格存在玩具对象里,这个值作为float保存。floats的格式不能被正确地打印,所以toy类有一个方法getPriceAsString(),它执行格式化。
  保存这个方法。
  6. 最后,创建一个showError()方法。它将在会话信息不管因何种原因无效时被调用。输入以下行实现这个方法。
  private void showError(PrintWriter out){
  //Outpur failure message
  out.println(“<head><title>JK Toys error page</title></head>”);
  out.println(“<body>”);
  out.println(“<p><h2>Sorry,we don’t have a record of your customer name make a valid selection</h2>”);
  out.println(“<p>Please press the <strong>Back</strong>button,and resubmit.</p>”);
  out.println(“<p>Thank you for your interest in JKToys!!!”);
  out.println(“</body></html>”);
  out.flush();
  return;
  }
  保存这个方法。
  这个完成了DisplayToysServlet。你应该登录进JKToys Kids Zone,在确认你成功登录进站点的页面上选择Display toysfor my age group链接,以测试这个servlet。
  第三部分:完成servlet,显示在DisplayToysServlet里选中的玩具
  这个servlet,TotalPurchaseServlet,也总计选中的玩具的价格,显示总数。客户有个机会确认购买,完成定单,或取消定单。
  1. 从com.ibmwaslab.servlet2包里选择TotalPurchaseServlet。打开doPost()方法。最初的几行已经为你输入好了:
  //Obtain output stream from response object
  PrintWriter out=res.getWriter();
  //Set content type on the response header
  res.setContentType(“text/html”);
  //Get the session and retrieve the customer information
  HttpSession session=req.getSession(false);
  Vector toys=(Vector)session.getValue(“TOYS”);
  这些行执行一些你在前面建立的servlets里作的典型的任务。PrintWriter从resposne 对象里取得,你设置MIME内容,从会话里取得玩具向量。这个向量包含所有这个客户的年龄组的玩具。
  2. 在下面的步骤里,你将向doPost()方法里增加代码来完成功能。在doPost()输入:
  //declare an object to hold the toy order
  JKToysOrder toysToBuy=null;
  //Get the input form contents
  toysToBuy = getFromInput(req,toys);
  实现你声明一个null JKToyOrder对象。这个对象将包含客户选择的玩具的集合。JKToyOrder类还包含定单的价格总和。
  下一行调用了getFormInput()方法,你将在下一个步骤里建立它。保存doPost()方法,你将得到错误,因为你还没有些getFormInput()方法。继续,带着错误保存。
  3. 创建getFormInput()方法。这个方法循环通过前面表格里的checkboxs,用checkbox的名字作为玩具向量的索引。被选中的玩具被加进定单。
  注意:只有被选中的(checked)checkbox被从表格发送回servlet。submit按钮也被传送。按钮的值被忽略,看下面的代码。
  输入下面的代码来完成getFormInput()方法。
  private JKToyOrder getFormInput(HttpServletRequest req,Vector allToys){
  JKToyOrder selectedToys =new JKToyOrder();
  Enumeration fieldName=req.getParameterName();
  int i=0;
  while (fieldNames.hasMoreElements())
  {
  String paramName=(String)fieldName.nextElement();
  String paramValue=(String)req.getParameterValue(paramName)[0];
  try
  {
  int toyIndex=Integer.parseInt(paramName);
  selectedToys.addToy(allToys.elementAt(toyIndex));
  }
  catch (NumberFormatException e)
  {
  //Skipping the button widget,only interested in checkboxes
  //with numeric names
  }
  }
  return slectedToys;
  }
  你也许要看看JkToyOrder类,看它是怎么工作的,它可以在com.ibm.waslab.common包里找到。
保存方法,打开doPost()。
  4. 在你输入的最后一行后面,继续建立doPost()方法,输入以下的代码:
  //toysToBuy order will be empty if nothing was selected
  if(toysToBuy.isEmpty())
  {
  //Output failure message
  out.println(“<html>”);
  out.println(“<head><title>No toys selected</title></head>”);
  out.println(“<body>”);
  out.print(“<p><h2>Nothing selected</h2>”);
  out.println(“<p><font color=/”red/”> You did not select any toys!</font></p>”);
  out.println(“<p>Please press the <strong>Back</strong> button,and resubmit.</p>”);
  out.println(“<p>Thank you for your interest in JKToys!!!”);
  out.println(“</body></html>”);
  out.flush();
  return;
  }
  else
  (
  displaySelections(res,req,toysToBuy);
  }
  这段代码检查是否至少有一个玩具被选择,如果toysToBuy定单是空的,一个错误消息被显示。如果定单不空,displaySelections()方法被调用来显示一个包含被选中的玩具的表。
保存doPost()方法,应该没有错误。
  5. 完成displaySelections()方法。这个方法同DisplayToysServlet里的displayToys方法很相似,有一些差别。输入以下的代码来完成TotalPurchase Servlet类里的一个新的方法:
  //Enumeration selectedToys=toys.elements();
  Toy aToy=null;
  while(!toys.isEmpty())
  {
  aToy=(Toy) toys.getNextToy();
  out.println(“<TR>”);
  out.println(“<TD><IMG SRC=/”..”+aToy.getThumbnailFile()+”/”>”);
  out.println(“<TD>”+aToy.getShortDescription());
  out.println(“<TD>”+aToy.getFullDescriptin());
  out.println(“<TD>”+aToy.getPriceAsString());
  }
  out.println(“<TR>”);
  out.println(“<TD><INPUT TYPE=/”submit/=”
  NAME=/”ConfirmationPurchaseButton/”
  VALUE=/”Confirmation Purchase/”
  id=/”ConfirmPurchaseButton/”>”);
  out.println(“<TD><strong>Your total purchase amount is:</strong>”);
  out.pritnln(“<TD><strong>”+toys.getTotalPriceAsString()+”</strong>”);
  out.println(“</TABLE>”);
  }
  6. 这个方法负责显示选中的玩具,和显示定单的总价格。这里有两个按钮在表格上,一个处理购买,另一个取消定单;在这个课程里这两个按钮调用的servlets没有被实现,学生在业余时间实现它们。
在这个练习里你处理客户登录,基于客户的年龄显示一个选中的玩具的表,让客户从列表里选择玩具,显示最后的选中的玩具的总和和这次定购的总额。你学习了怎样用会话保持servlets和HTML页面之间的状态。你还学会了几种从一个表格里显示和选择项目的方法。

  JSP3:JSP页面
  在这个练习里你将创建一个JavaServer Page。servlet的目的是允许Customer Profile更新信息。
客户登录进JKToys的Kids Zone部分以后,客户可以作的一个选择是:更新他们的客户信息。为了处理这个,我们需要一个网页显示这个JKToysCustomer对象相联系的每一个信息(客户ID除外),作为编辑区域。这些字段需要用当前的客户记录的数据初始化。这些字段将是一个客户记录更新表格的一部分,将被提交给ProfileUpdateServlet来处理。
  第一部分:JSP文件
  1. 你将从一个HTML文件开始,[x]:/www/html/JKToys/html/body_jktoys-kids_zone_change_start.aspl(x是Lotus Domino Go Webserver安装的驱动器字母,文件是用NetObjects Fusion编辑的。第一步是在你的浏览器里打开这个文件(作为本地文件)。你看到的是一个Table,字段对应JKToysCustomer properties。每一个字段(加上一个隐藏字段)都需要在运行时用live Customer data生成。我们将用JSP语法作这个。
  2. 用NetObjects ScriptBuilder打开HTML文件(Start->Programs->NetObjects ScriptBuilder->NetObjects ScriptBuilder 3.0)。ScriptBuilder是一个简单的(基于文字的)编辑器,重要用来编辑基于HTML的文件(.aspl,.asp,.jsp,.shtml,....)在这个文件里你将注意到几个HTML注释表明需要使用JSP代码的地方。定位第一个这样的注释,看上去应该象:
  <!—The value field should be the Customer Number retrieved from the Customer object   saved in the Session -->
  你将需要先写一个scriptlet来从HttpSession里取得JKToysCustomer。下面的代码使用了JSP声明和JSP Scriptlet来完成这个:
  <%@ import=com.ibm.waslab.common.* %>
  <%KToysCustomer CUSTOMER=(JKToysCustomer)request.getSession(false).getValue(“CUSTOMER”);%>
  Declaration provides a global import for the Servlet which will be generated during page compilation.这样com.ibm.waslab.common包里的类在我们的JSP scriptlet和expression里就不要用全名了。把以上的行加进HTML文件。
  3. 然后,我们将提供JKToysCustomer对象的customerNumber属性作为HIDDEN输入域的值。在同INPUT 标签的VALUE=element相联系的引号里加入以下的JSP表达式:
  <%=CUSTOMER.getCustomerNumber() %>
  4. 我们现在需要把每一个字段放进表,用从CUSTOMER对象里来的它们当前的值。当你往下扫过文件,你会发现几个HTML标记看上去象:
  <INPUT id=”FormsEditFieldx” TYPE=”text” NAME=”xxx” VALUE=”” SIZE=....>
对这些中的每一个,你要在值域的引号之间增加一个JSP表达式。(看注释一确定你应该输入什么。有6个这样的字段。)
  5. 我们要显示的最后一个输入域是一个下拉列表,让客户选择年龄组。This needs to be populated and have the “currently” specified age group,”selected”.这需要更多的scriptlet来有效地作这个。你所要的是产生5个<OPTION>标签标记(在<SELECT>块的里面)。每一个标签应该是“Under 5”,”5-7”,”7-9”,”9-13”和”Over 13”。接着,这些”subtags”中有一个应该看上去这样:
  <OPTION SELECTED> age_group
  这个规定了初始选中的项目。
  第二部分:发表、运行和调试JSP
  1. 把改过的文件保存在[x]:/www/html|JKToys/html/body_jktoys_kids_zone_change.jsp。注意,这个文件名和文件类型同提供的不一样。
  2. 接着输出你的WASDev项目(VA Java)到两个分开的目录树里(x;/WebSphere/AppServer/servlets和x:/IBMVJava/ide/project_resources/IBM WebSphere Test Enviroment/servlets).(第一个目录允许在VA Java外面运行,而第二个在SERunner的类路径里。)
  3. 下面通过网站,登录进Kids Zones。(你应该从VAJava里面运行SERunner。)在登录确认页面,你选择Update registratio information。一旦你选择了这个,IBM WebSphere Application Server将调用页面编译。一个servlet将从.jsp文件产生,这个servlet将被编译。如果编译有错误(因为你的.jsp文件里的不合法的JSP语法),编译错误消息将在一个HTML错误页里返回(回到浏览器)。(注意,”Retrieve syntax error infromation”必须在JSP Execution Monitor Options dialog里被启用。选择Workspace->Tools->JSP Execution Monitor;等对话框窗口出现;确认”Retrieve syntax error infromation” checkbox 被checked。)
  你将需要查看任何一个编译错误消息,修改你的.jsp文件,重复处理。如果你被错误消息弄糊涂了,你可以查看生成的servlet代码。这个代码被写进VA Java里的”JSP Page Compiler Generator Code”项目。
  4. 在某些时候,如果你要调试你的JSP文件,你需要停止SERunner。确信”JSP Page Compiler Generator Code”项目被加进SERunner的类路径。重启SERunner,重新访问站点。就象你在你的servlet里加断点一样,你可以把它们加进JSP Servlet。
  5. 你也许还希望看看页面编译的翻译过程。打开JSP Execution Monitor(JSP Execution Monitor Options dialog),在监视器里一步一步地访问.jsp文件。
  你在这个练习里作了什么
  这个练习说明了用JavaServer Pages来建立“HTML模板”文件,这个文件会被JSP页面编译过程转化为可执行的Servlets。得到的模板文件(.jsp)可以被WYSIWYG HTML编辑工具处理,可以用这个格式来维护而不是代码的格式(也就是servlet).
  不同的JSP语法被试探,JSP Declaration,JSP Scriplets和JSP Expressions在被建立的.jsp文件里用到了。
  答案
  这里是建立下拉列表的scriptlet
  <%
  String[] ages=
  {“Under 5”,”5-7”,”9-13”,”Over 13”};
  for (int i=0;i<ages.length;i++){
  out.print(“<OPTION”);
  if ((CUSTOMER.gerAge().trim()).equals(ages[i]))
  out.print(“SELECTED”);
  out.println(“>”+ages[i]);
  }

  >

  JSPBeans4:JavaServer Pages with Beans
  在这个练习里,你将更新一个JavaBean,用它来在两个servlets之间通信,其中第二个servlet是从一个JavaServer Page生成的。JSP的目的是显示客户选择的可能要购买的玩具。
  许多网页有复杂的布置。这很难在一个servlet里用编程的方法表达。这是服务器端脚本技术的主要理由。JSP编程模型的力量在于隔离可重用的组件(JavaBeans)里的应用代码,而不污染演示 HTML模板。
你将把一个JavaBean的一些状态扩展为属性,以便使用HTML模板语法的JSP容易地使用这个JavaBean。你还将用JSP标记和JSP HTML模板标记(insert、repeat)来扩充HTML文件。
  第一部分:更新JKToys JavaBean
  1. 在这个练习里我们将在com.ibm.waslab.common包里工作。我们从在类JKToyOrder上打开一个类浏览器开始。选择这个类的BeanInfo view。这个类是用来维护当前选择的要定购的玩具的。It is populated by the TotalPurchaseServlet。我们会让一个JSP表示“order review”信息,而不是用现在输出HTML和动态内容的displaySelections方法。
  为了做到这个,我们需要一个新的方法来以”JavaBean”风格的方式循环过一个选择的玩具。这需要把列表作为一个Indexed Property。
  创建一个新的IndexedProperty,orderedToy,在类JKToyOrder里。为了做到这个,单击Property Wizard 按钮。在结果对话框check readable,writeable,indexed。提供Property的名字为orderedToy,选择Property的类型为com.ibm.waslab.common.Toy(这个将被向导转化为Toy[])。对我们的目的而言,uncheck规定property为bound的box。按Finish.
  2. 返回到类的Methods或Hierarchy视图,来实现刚才生成的4个方法。如果你看类定义,你会发现一个新的实例变量名字叫fieldOrderedToy,类型为Toy[]。这个是Bean Property wizard产生的。这个实例变量并不需要,因为玩具已经存在一个实例变量叫orderedToys,类型为java.util.Stack。这个实例变量已经在类的其它地方被使用了。
  删除变量fieldOrderedToy,保存类。你将会在步骤1里Property wizard产生的三或四个附属方法里得到错误标记。
  3. 编辑四个附属方法的每一个。使用java.util.Stack和java.util.Vector的正确的方法(例如CopyInto,elementAt,setElementAt,....)来实现这个四个方法的每一个。(需要帮助的话,看这个练习的末尾的答案。)
  应该注意到,setOrderedToy(int Toy)和getOrderedToy(int)方法也许会抛一个ArrayOutOfBoundsException异常。这个异常会触发JSP里<REPEAT>标记里循环的结束。
  4. 验证类JKToyOrder实现java.io.Serializable。
  5. 最后,输出com.ibm.waslab.common包到以下路径:
[x:]/IBMVJava/ide/project_resources/IBM WebSphere Test Environment/servlets
[x:]/WebSphere/AppServer/servlets(只有在要在VAJava外面运行时才需要)
  第二部分:调用JSP
  1. 打开com.ibm.waslab.servlet2.TotalPurchaseServlet。编辑doPost()方法。在方法的底部(在另一个块里),displaySelections被调用。这个需要被对JSP的调用掉换。第一步是把JKToyOrder对象放进HttpSession对象或HttpServletRequest对象。
  为了把定单对象加进会话,增加以下的代码:
  session.putValue(“OrderedToys”,toysToBuy);
  注意,定单从会话里取得的键是”OrderedToys”。
  可选的,JavaBean可以被放在请求范围(而不是会话),把setAttribute方法用在com.sum.serve.http.HttpServiceRequest对象。
  2. 下一步是调用callPage()方法来调用JSP。CallPage在回应对象里被调用。callPage是一个com.sun.server.http.HttpServiceResponse类上的方法。你必须先把res造型为类型com.sun.server.http.HttpServiceResponse。以下的代码将足够了(如果你加了一个import语句到类定义里面)。
  HttpServiceResponse response=(HttpServiceResponse) res;
  response.callPage(“/JKToys/html/jktoys_display_order.jsp”,req);
  第三部分:Populating the JSP
  1. 最后一步是创建JSP文件。文件jktoys_display_order_start.jsp(在x:/www/html/JKToys/html目录里找到)包含从displaySelection方法里提取的HTML(从com.ibm.waslab.servlet2.TotalPurchaseServlet)。你将需要为”OrderedToys”Bean增加一个BEAN标记。这个可以被放在文件的任何地方(在Bean被引用以前)。
  2. 你还将要把TABLE的<tr>块包进一个<REPEAT>块。用insert标记和JSP表达式把动态内容插入HTML表格。
  注意:你还将要增加一个scriptlet来在REPEAT块的开头测试一个ArrayOutOfBoundsException(在任何静态内容被推到回应流里去以前)。也要注意,getPriceAsString()方法没有同一个Property(在JkToyOrder类或Toy类)联系起来。<INSERT>标记不能用来显示这个信息,除非方法在每一个各自的类里被prompted为一个Property。如果你不想”prompt“这个属性的话,这个方法可以用scriptlet来调用。
或者,你可以只用scriptlet和JSP表达式而不是<REPEAT>和<REPEAT>标记。
  3. 保存更新过的JSP文件为jktoys_display_order.jsp。(注意新的文件名!!!)测试正确的操作。
你在这个练习里作了什么
在这个练习里,你作了一个典型的Servlet->Bean->JSP“控制”流。注意,JSP文件可以被HTML WYSIWYG编辑器维护和编辑(同在Java方法里管理它不一样)。
  答案:
  public Toy getOrderedToy(int index) throws
  ArrayIndexOutOfBoundsException{
  return (Toy)orderedToys.elementAt(index);
  }
  public com.ibm.waslab.common.Toy[] getOrderedToy(){
  com.ibm.waslab.commom.Toy[] toys=new
  com.ibm.waslab.common.Toy{orderedToys.size()};
  orderedToys.copyInto(toys);
  return toys;
  }
  public void setOrderedToy(int index,Toy orderedToy)throws
  ArrayIndexOutOfBoundsException{
  orderedToys.setElementAt(orderedToy,index);
  }
  public void setOrderedToy(com.ibm.waslab.common.Toy[] orderedToy)
  {
  orderedToys=new java.util.Stack();
  int max=orderrdToy.length;
  for (int i=0;i<max;i++)
  orderedToys.addElement(orderedToy[i]);
  }

  JSP的答案参见:x:/www/html/JKToys/jspSolutions/jktoys_display_order_soln.jsp。

  Studio5:WebSphere Studio Servlet Wizards
  在这个练习里,你将使用IBM WebSphere Studio的一个向导来创建一个客户管理界面。产生的servlet和JSP页面是让站点管理员能查看数据库里所有JKToys客户的记录。按照这个这个练习,你将能用Studio servlet wizard来建立更复杂的servlets和JSP的骨架。
  对所有的练习,确信你用USEID为id和PASSWORD为口令登录进去的。
  1. 你将用IBM WebSphere Studio,version 1.0(从此以后用Studio指代),建立一个简单的管理应用。选择Start,Programs,IBM WebSphere,Studio 1.0,WebSphere Studio,启动Studio。这将带来Developer Workbench,Studio的主窗口。Workbench给出一个基于项目的网站视图。从File菜单选择New Project选项创建一个新的项目。在Name域,输入JKToys,按“确定”按钮。
  2. 建立管理应用的第一步是建立一个SQL查询对象。为了做到这个,你将利用Workbench提供的SQL向导。从Tools菜单选择SQL Wizard...项目。
  3. 向导显示为一个对话框,有一个”tabbed”象notebook的外观。当它最初弹出时,对话框显示Welcome页面,问将要产生的SQL命令文件的名字。输入ViewAllCustomer到name输入域,按Next按钮。
  4. 在下一页(Logon),输入jdbc:db2:JKToys到数据库URL输入域;USERID到用户输入域;PASSWORD到口令输入域。在Driver输入域选择IBM DB2 UDB local。输入这些值以后,按Connect按钮。这会连接数据库,取得JKToys数据库的元数据。
  5. 确信Select Statement 类型被checked。还check USERID.CUSTOMER表。按Next按钮。
  6. 因为只有一个表,Join是不需要的。按Next按钮。
  7. 对Columns入口,先按Select all按钮,然后是Add按钮。然后按Next.
  8. 你在建立的查询要从数据库取得所有的行。所以,你不要where子句。按Next按钮。
  9. 按Finish来完成SQL语句。
  10. 接着我们将运行Data Access Servlet Wizard。为了启动向导,从Tools菜单选择Studio Wizard...项目。Studio Wizard是一个同SQL wizard相似的对话框。
  11. 在Welcome tab,选择Data Access Servlet,按Next按钮。
  12. 在“第二个”Welcome tab,输入ViewCustomer到Name输入域,按Next。
  13. 在SQL语句页面,“select from an active project”选项应该被选中,ViewAllCustomers.sql应该被选中。按Next。
  14. 在输入页,确信”Yes please”被选中。按Next。
  15. 对InputLayout,输入:为Page title输入View All Customers;清除User prompt的输入;Check Submit button check box,把文字改为View All Customers;uncheck Reset button 输入。按Next。
  16. 对输出页面接受缺省值(所有列)。按Next。
  17. 在Heading输入域增加文字JKToys Customers.然后选择输出字段(每次一个),用上下箭头移动字段,使得它们可以以以下的顺序出现:LNAME,FNAME,AGE,ADDR,CITY,STATE,ZIP,CUSTNO。按Next。
  18. 选择不要创建一个custom Error Page。按Next。
  19. 按Finish来生成Servlet,DataBean,Output JSP和Input HTML文件。一旦确认对话框消失,你应该看到以下文件在Workbench在JKToys项目里:
 
  
ViewAllCustomers.sql;ViewCustomersOutputPage.jsp;ViewcustomersInputPage.aspl。如果你看

  
classes/JKToys文件夹,你还会发现:
  ViewCustomersServlet.java;
  ViewCustomersServlet.servlet;
  ViewCustomersServletBean.java;
  ViewCustomersServlet.class;
  ViewCustomersServletBean.class。
  20.在发表这个应用之前,编辑ViewCustomersServlet.servlet,在Workbench里双击这个文件。这个文件是XML的servlet配置文件。我们要改变”default-page”的路径。在第5行,在<URL>后面,插入”/JKToys/html”。缺省页面的路径现在应该是/JKToys/html/ViewCustomersOutputPage.jsp。
  21. 下一步是发表到JKToys站点。为了作这个,先创建一个“Publishing Server”。从Options菜单里选择Publishing servers...选项。
  22. 按Add按钮。在New Publishing Server Settings对话框,输入JKToys到Name输入域。Check Local radio button。然后,选择html目标,按“浏览”按扭。在文件浏览器里,定位/打开x:/www/html/JKToys/html(x是IBM HTTP Server文件根所在的驱动器字母)。然后,选择html目标,按“浏览”按扭。在文件浏览器里,定位/打开x:/WebSphere/Appserver/servlets。最后,按“确定”按钮。
  23. 为了发表,在Workbench左手的树视图里选择JKToys站点。从File菜单选择Publish选项。当Select Publishing Server对话框弹出来,选择JKToys作为服务器;按Continue按钮。然后按Publish按钮。最后按“确定”让对话框消失。
  24. 为了测试这个应用,我们将在VA Java外面运行,使用IBM HTTP Server。确信SERunner被停止。然后启动IBM HTTP Server。
  25. 在一个浏览器,打开URL http://127.0.0.1/JKToys/html/ViewCustomerInputPage.aspl。按View All Customers按钮。这将调用servlet,它将创建一个访问bean的实例,ViewCustomersServletBean,然后调用执行Bean的方法来发布SQL查询。Bean被放在请求范围内,键是viewCustomersServletBean。Servlet对ViewCustomersOutputPage.jsp执行一个callPage,在一个HTML表格里显示SQL查询的输出。
  26. 最后的步骤是看产生的代码。尤其是,看输出JSP和ServletBean.
IBM WebSphere Studio里的两个不同的向导被用来建立小的网络应用来查询客户数据库,返回内容作为动态内容。有许多不同的工具可用来执行业务数据的Web网关。而向导能有效地建立servlet、”servlet bean”、JSP,从而支持JSP编程。

  JDBCLab:用JDBC访问一个数据库
  在这个练习里你将学习使用JDBC访问数据库和插入一个记录到数据库的基础知识。
  在这个练习里,你将写RegistrationServlet类的register方法。这个类和你在Servlet1A练习里用的一样。在这个练习里,你将使用数据库的功能。这个练习将展示实现用户需求的步骤。
  第一部分:理解regsiter()方法在RegistrationServlet中的工作原理
  在这个练习里,你将在com.ibm.waslab.JDBC包上工作。扩展RegistrationServlet类,理解register()。这个方法抛一个SQLException。完整的方法声明是:
  public synchronized void register(Properties formInput)
  throws SQLException{
  }
  register()方法在servlet取得控制时从doPost()方法里被调用。register()方法实际上写一个新的记录到数据库。我们将在第二部分写register()方法。同时,我们需要确信一些设置步骤已经完成。
  1. 打开init()方法,在super.init()的调用后面输入以下的代码:
  //Load JDBC driver for DB2
  try
  {
  Class.forName(JKToysDBInfo.gerDriver());
  }
  catch (ClassNotFoundException e)
  {
  erroLog(“JDBC Driver not found”+e);
  }

  保存init()方法。记住,在驱动器管理可以得到一个连接以前,一个正确的数据库驱动器必须被servlet装载。每一个servlet只在servlet的init()方法里作一次。这个方法并不真地建立一个连接,它只是允许连接被建立。
  注意:在这个情况下,我们装载DB2 app驱动器。这个驱动器是在数据库装在servlet将要运行的同一台机器上时使用的。如果你在访问另一台机器上的数据库,你要使用net驱动器:
  COM.ibm.db2.jdbc.net.DB2Driver
  当用net驱动器得到一个连接,你需要在getConnection()里使用的URL里提供更多的信息。数据库所在的机器名或URL,和DB2 Java Gateway侦听的端口号。一个有效的URL参数看上去是这样的:
jdbc:db2://servrid:8888/databasename
  第二部分
  1. 现在,回去,重新打开register()方法。代码的第一行创建一个数据库连接:
Connection conn=DriverManager.getConnection(URL,USER,PASSWORD);
  你用驱动器管理器的静态方法getConnection(),把数据库的URL,一个有效的用户ID和口令传递给它。url,userid和password在类被装载时从一个属性文件里得到(看静态变量声明)。
  2. 现在到了有挑战性的部分了。我们要作的第一件事是找到已经被分配掉的最后一个客户号码,这样我们可以分配给正在注册的新客户一个新的客户号码(比以前的最高的还要高)。我们要存储这个新的客户号码在一个int变量名为nextId。为了做到这个,你会需要确信使用Statement类和ResultSet类。以下的SQL;
  “SELECT MAX(CUSTNO) FORM”+DBOWNER+”.CUSTOMER”
将允许你获得当前最高的客户号。试试自己写这个代码,基于课程笔记的例子。如果你需要帮助,看答案页。
  3. 接着你将用一个prepared statement对象来把客户属性对象里的信息插入数据库。输入以下的行:
  //Insert record in the database
  PreparedStatement insertStatement=
  conn.prepareStatement(“INSERT INTO”+DBOWNER+”  .CUSTOMER(FNAME,LNAME,ADDR,CITY,STATE,AGE,ZIP,CUSTNO)”+”VALUES(?,?,?,?,?,?,?,?)”);

  上面的行要求连接创建一个prepared statement对象叫insertStatement。SQL语句作为参数被传递。数据库行的每一列的值用问号代表。每一个问号必须被一个正确类型的值代替。输入以下行:
  insertStatement.setString(1,formInput.getProperty(“FNAME”));
  insertStatement.setString(2,formInput.getProperty(“LNAME”));
  insertStatement.setString(3,formInput.getProperty(“ADDR”));
  insertStatement.setString(4,formInput.getProperty(“CITY”));
  insertStatement.setString(5,formInput.getProperty(“STATE”));
  insertStatement.setString(6,formInput.getProperty(“AGE”));
  insertStatement.setString(7,formInput.getProperty(“ZIP”));
  insertStatement.setInt(8,nextId);
  4. insertStatement执行对数据库的更新。输入下面两行:
  insertStatement.executeUpdate();
  如果有错误出现在创建连接时,语句或访问数据库,这个方法会抛出一个SQLException。
  5. 最后你需要存储客户号码到formInput属性对象。输入下面行:
formInput.put(“CUSTNO”,new Integer(nextId).toString());
  6. 保存方法。应该没有错误。
  7. 接着你将需要为JKRegister servlet编辑WebSphere配置文件。(编辑”[x:]/IBMVJava/ide/project_resources/IBM WebSphere Test Environment/properties/server/servlet/servletservice/serrvlets.properties”.)
改变看上去这样的行:
  servlet.JKRegister.code=com.ibm.waslab.servlet1.RegistrationServlet
为这样:
  servlet.JKRegister,code=com.ibm.waslab.JDBC.RegistrationServlet
  8. 如果你的webserver在运行,关掉它。在VAJ,启动SERunner。打开你的web浏览器,到JK Toys网站的注册页面。在表格里输入注册信息,按注册按钮。你的新的servlet将被调用。登录进JKToys站点确信注册已经发生。你的新的客户号码应该能在数据库找到。
  在这个练习你作了什么
  在这个练习,你编写了Registration Servlet的register方法。这个方法用JDBC来创建一个新的客户号码,注册一个新的客户到数据库。现在你有了在你的servlets里访问数据库的基本知识。
  答案
  以下的代码创建一个SQL语句,执行在前一页里定义的SQL查询。
  //Get next customer number
  Statement sqlStatement=conn.createStatement();
  ResultSet result=sqlStatement.executeQuery(“SELECT MAX(CUSTNO) FROM”+DBOWNER+”.CUSTOMER”);
  查询的结果被放在ResultSet对象叫result里面。结果的集合包含一个游标,最初指向返回的第一行前面。为了得到查询的值游标必须用next()往前移动。用这个方法,游标只能向前移动。下面几行移动游标到返回的值,增加1。
  int nextId=0;
  if(result.next()= =true)
  {
  nextId=result.getInt(1)+1;
  }
  if检查确定是否有行被返回。如果没有,结果为false。我们不处理错误的情况,但是它可以简单地用把nextId设置为1来处理。我们还可以用ResultSet的方法getInt(String),列的名字为”CUSTNO”,但是因为我们知道只有一列会被返回,我们选择用getInt(int)..

  安全:Servlet安全
  这个练习展示你怎样使用WebSphere的Servlet安全特性来创建一个用户组,一个用户集合,和一个访问控制列表,然后增加一个servlet到被这个访问控制列表保护的资源列表。
  这个练习将有三个部分。在第一个部分我们将作一些初始设置,包括取得前一个练习(WebSphere studio lab)里创建的servlet,给它一个名字。第二个部分将展示怎样在WebSphere里创建用户和用户组,最后一个部分会介绍创建ACL和把资源(包括servlet)指派到ACL。
  第一部分:初始设置和Servlet命名
  1. 这个练习从你以前完成的WebSphere studio练习(练习5)的结果开始。如果你没有完成那个练习,解开文件c:/Lab5Solutions.zip到c:/。
  2. 把文件ViewCustomersServlet.servlet从/WebSphere/Appserver/servlets/JKToys 目录拷贝到/WebSphere/Appserver/servlets目录。
  3. 下一个任务是让JKToys.ViewCustomersServlet类成为一个named servlet。WebSphere的访问控制特性依靠servlet命名――对没有命名的servlet它们不工作。为了做到这个,我们将用WebSphere Application Server管理工具工作。为此你需要从IBM HTTP Server启动Application Server(记住首先在VA Java里停掉SERunner)。在Web Server和Application Server被启动以后,从你的浏览器用http://localhost:9527登录进WebSphere管理页面。记住缺省的WebSphere管理用户的ID和口令为admin,admin。当管理页面打开,打开标签为”Servlets”的树节点,选择”Configuration”来打开Servlet Configuration page。
  4. 按”Add”按钮。我们将命名这个servlet为“ViewCustomersServlet”。在”Servlet Name”域键入”ViewCustomersServlet”。View Customers servlet的类是”JKToys.ViewCustomersServlet”。在”Servlet Class:”域键入这个,按”Add”按钮。(如果你要,按”Test”按钮来测试这个servelt,然后释放说测试被通过的对话框。)
  5. 我们接着需要作一些整理工作,检验我们的命名是否工作正常。在你的硬盘上的[x:]/www/html/JKToys/html(或jspSolutions)目录里找到”ViewCustomersInputPage.aspl”文件。用notepad或别的文字编辑器打开那个文件。找到行“<FORM METHOD=POST ACTION=”/servlet/JKToys.ViewCustomersServlet”>”改成,“<FORM METHOD=POST ACTION=”/servlet/ViewCustomersServlet”>”。保存这个文件。现在,往你的浏览器里输入以下的URL:”http://localhost/JKToys/html/ViewCustomerInputPage.aspl”.。确信”View Customers”按钮出现,一旦按钮被按下,包含客户信息的表出现。
  第二部分:增加用户和用户组
  1. 既然我们的重命名已经完成,我们可以开始向我们的ViewCustomersServlet servlet增加口令保护。回去到Administration GUI(如果你测试和命名servlet用了同样的浏览器,你将需要重新登录进WebSphere管理)。从树里选择”Security”节点。你会看到Security tree有四个节点:
  Users
  Groups
  Access Control Lists
  Resources
  我们将在我们的练习里用所有四个tabs。
  2. 选择“Users”。一个表会打开,显示WebSphere已经在它的内部数据库里有的用户的列表。一个缺省的WebSphere安装会有两个用户,”jeeves”和”admin”。我们将增加一个新的用户叫”sales”。按”Add”。一个对话框显示出来,问用户的名字和口令,要你确认口令。在用户名域输入“sales”,在口令和确认口令域都输入”bluefish”。然后按对话框里的“确定”按钮。用户”sales”将被加进表。在一个实在的应用里,我们显然不用一个可在字典里找到的口令――你可以用字母和数字的随机组合。
  3. 我们将增加一个用户组到WebSphere。我们要允许销售人员和管理人员都可以列出客户――销售人员会看客户列表,管理员会需要在数据库崩溃时维护客户列表。我们要创建一个新的用户组名字为“customer-access”包含所有这些用户。按”Group”。显示器有三个列表。最上边的是”Defined Groups”(现在忽略”realm”下拉菜单――让它保持”DefaulgRealm”设置)。左边的按钮是增加和删除组。按“Add”按钮。一个对话框显示出来,向你要要增加的组的名字。输入”customer_access”按“Add”按钮。”customer_access”组将被加进列表。我们现在已经准备好用底部的两个列表。左边的是成员列表,现在还空着。在右边的列表(“non-memebers”)里选择”admin”用户,按”<Add”按钮。这个用户会被加到用户组。对”sales”用户作同样的事。我们现在完成了创建用户组的工作。
  第三部分:创建ACL和增加资源
  1. 我们现在准备好向WebSphere的ACL增加新的ACL了。按”Access Control List”.显示的面板和Groups的面板相似,最上边的下拉菜单显示realms(再一次,让它保持“defaultRealm”),最上边的列表显示ACL’s的列表。应该有一个ACL,简单的叫做”defaultAcl”。我们将创建一个新的ACL叫做”customer_access_ACL”。按左边的Add按钮。一个对话框会显示出来,要求要加入的新的ACL的名字。在文字域输入”customer_access_ACL”,按”Add”。一个新的ACL叫做”customer_access_ACL”的ACL将被加进列表。
  2. 这里我们已经准备好向用户组指派权限。在ACL列表下面有一个树形图包含三个分枝:Users,groups,computers。所有这些分枝应该都是空的(没有儿子)。按中间的分枝(Groups),然后按这个视图左边的”Add”按钮。这个将带出来一个对话框,让你向不同的用户组指派权限。
  3. 现在对话框出现了,下一步是在我们的ACL里向新的用户组指派权限。在”Assign Permission for:”对话框的上面有两个radio button。这两个选择是”files and folders”和”servlets”。你也许以为我们要”servlets”,但是相反我们要选择”files and folders”。”servlets“选项是指一个运行的servlet拥有的权限,例如打开sockets,读文件等。我们要设置访问一个servlet的权限;这是HTTP协议下的文件访问。另一组radio buttons让你选择你是否要为”Users”,”Groups”,或”Host”设置权限。选择”Groups”。因为只有一个组,它(customer_access)应该在第二组radio buttons下面的”principals”列表里被选中。在 ”principals”列表下面是一组check boxes,标着”GET”,”PUT”,”POST”,”DELETE”。check”GET”和“POST”check boxes,按check boxes下面的“确定”按钮。这给这个用户组对这个ACL保护的文件,文件夹和servlets使用”GET“和”POST“方法的权限。
  4. 我们现在要结束我们的练习。按”Resouces”。在”realm”下拉菜单下面你将看到一个空的表。按表左边的”Add”按钮。这个会带出来一个对话框,让我们增加资源到我们创建的customer_access_ACL保护的资源列表里。
  5. 当”Protect A Resource”对话框出现,改变ACL下拉菜单为”customer_access_ACL”。然后在”Resource to Protect”下面,选择”Servlet” radio button,从下拉菜单选择”ViewCustomers”servlet,然后按“确定”释放对话框。你会在Resource表里看到资源”ViewCustomersServlet”和”customer_access_ACL”ACL之间有一个联系。我们现在结束了编辑我们的ACL和资源,准备测试了。
  6. 在一个浏览器,输入URLhttp://localhost/JKToys/html/ViewCustomersInputPage.aspl。”View Customers”按钮出现,按它。一个challenge dialog应该出现,向你要名字和口令。如果对话框没有出现,重新看看你在这以前的步骤。如果你不能找到错误,向你的实验辅导员请求帮助。首先输入一个无效的用户名和口令。你应该接着收到challenge dialog。输入”sales”和”bluefish”给名字和口令。现在,客户的表应该象在这个练习的开头一样显示出来。如果challenge dialog又出现了,重新输入名字和口令。challenge dialog通常会给你三次机会输入正确的名字/口令对,如果都失败,浏览器会显示错误“401 Unauthorized”。
  在这个来年练习里,我们创建用户和用户组,创建一个ACL和指派一个servlet资源到ACL。我们已经展示怎样给一个servlet增加口令保护。

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebSphere介绍: WebSphere Studio,一个Web站点开发和设计工具包,包括项目管理,Java Servlet代码生成器,HTML写作工具,各种Script的编制工具,以及JAVA代码(Beans和Servlets)的开发工具。    WebSphere应用服务器提供三个等级的版本,它们是:    标准版(Standard Edition),是整个应用服务器家族的基础,提供从电子商务网站的建构、发布 到管理能力。标准版提供了开放、标准的平台和工具,以加速向电子商务的迁移。新加入的DB2UniversalDatabase5.2 支持,使开发者能够设计更强大有效的应用。WebSphere应用服务器标准版V1.1已经面世。包 括Servlet运行时引擎(RuntimeEngine),高性能的数据库连接程序(提供预联接,会话和状态管理的 应用服务,以及支持XML(eXtensibleMark-upLanguage)文档结构.   高级版(Advanced Edition),在标准版本的基础上,又增加了对安全性和交易处理能力的强化支持。连接已有的 数据库系统和基于主机的交易系统。并提供了复杂的工具以简化分布式组件应用的开发.   企业版(Enterprise Edition),提供了一个高可靠性的解决方案,能够将电子商务应用移植进关键性的企业环 境,起到平衡现有IT系统的作用。它组合了IBM享誉世界的交易环境TXSeries,和ComponentBroker,IBM的一个支持 完全的分布式对象访问和商务处理连接能力的产品。所有现在运行在TXSeries或ComponentBroker上的应用将在 Webshpere企业版中得到完全支持。    IBMWebSphere Performance Pack,包括eNetwork Dispatcher,Web Traffice Express 代理服务器和AFS分布式文件系统。让ISP(Internet Service Provider)和公司IT(Information Technology)专家降低 Web服务器拥塞,提高信息可获取性,改进服务器性能。 目录: WebSphere Application Server v7.1互补产品 WAS v7.0 的价值在IBM z/OS WebSphere Application Server Version 7.0 特色 WebSphere Application Server Version V7.0技术简介 WebSphere Application Server v7.0安装与迁移 WebSphere Application Server v7.0系统管理 WebSphere Application Server v7.0安全功能 WebSphere Application Server v7.0运行配置 WebSphere Application Server v7.0的价值-服务集成总线 WebSphere Application Server v7.0:IBM® Rational® Application Developer V7.5 WebSphere Application Server v7.0 附加值增强 WebSphere Application Server v7.0 特色总结 WebSphere Application Server v7.1互补产品 WAS v7.0 的价值在IBM z/OS WebSphere Application Server Version 7.0 特色 WebSphere Application Server Version V7.0技术简介 WebSphere Application Server v7.0安装与迁移 WebSphere Application Server v7.0系统管理 WebSphere Application Server v7.0安全功能 WebSphere Application Server v7.0运行配置 WebSphere Application Server v7.0的价值-服务集成总线 WebSphere Application Server v7.0:IBM® Rational® Application Developer V7.5 WebSphere Application Server v7.0 附加值增强 WebSphere Application Server v7.0 特色总结

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值