1 / 49

第三讲 JSP技术

第三讲 JSP技术. 深入 JSP 应用. 本节目标. 标记扩展的概念 标记扩展和 JavaBean 的区别 会使用 JSP+Servlet+JavaBean 开发自己的 Web 应用. 在浏览器显示. HTML. ················· <i>jb-aptech</i> ·················. 根据规范. 2. 1. HTML 规范: http://www.w3.org/TR/html401. 符合规范. 相似. 相似. XML 的 DTD. 解析器 ( 处理器 ). 从 HTML 说起. ?. Qu.:

Télécharger la présentation

第三讲 JSP技术

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第三讲 JSP技术 深入JSP应用

  2. 本节目标 • 标记扩展的概念 • 标记扩展和JavaBean的区别 • 会使用JSP+Servlet+JavaBean开发自己的Web应用

  3. 在浏览器显示 HTML ················· <i>jb-aptech</i> ················· 根据规范 2 1 HTML规范: http://www.w3.org/TR/html401 符合规范 相似 相似 XML的DTD 解析器(处理器) 从HTML说起 ? Qu.: 可不可以放置自己的“标记”,同时定义自己的“标记库”,设计自己的“处理器”?

  4. 标记的概念 功能:在next.jsp中使用 request.getParameter(“image”),把属性“image”的值取出来,也即house.gif <jsp:forward page=”next.jsp”> <jsp:param name=”image” value=”house.gif” /> </jsp:forward> • 假如上面例子使用的JSP标签是我们自己定义的,那么对于该标记而言: • 标记名称:也即jsp:forward,jsp是前缀,forward是后缀,中间用冒号分割 • 标记的属性:page就是jsp:forward的属性,而name、value是jsp:param的属性 • 嵌套:在<jsp:forward>中还有<jsp:param>,前者为父标记,后者为子标记 • 体内容:上面的例子两个标记都没有体内容

  5. 标记扩展的概念 • 标记扩展 把“标记”映射到一个或多个Java类,使得用Java类 完成“标记”的功能 • 标记库描述器(Tag Library Descriptor, TLD)文件 是一个XML文档,它描述了包含着一个或多个标 记扩展的标记库

  6. 标记扩展的概念 • 标记处理器 实现了标记具体功能的类,是一个JavaBean,它扩展了JSP API提供的javax.servlet.jsp.tagext.TagSupport类 • 在一个要使用标记库任何扩展标记的JSP中,都必须要使用JSP的taglib指令,以引入标记库中的相关标记

  7. 为特定需求开发 Java Bean 公共的构建块 应用1 标记扩展 应用2 Java Bean 为特定需求开发 标记扩展和bean的主要区别

  8. 标记处理程序 • 执行与自定义标记关联的动作的 Java对象 • 必须实现javax.servlet.jsp.tagext包的Tag或Body Tag接口 • 支持以下方法 • setPageContext(), 设置页面上下文 • setParent(),设置父标记 • doStartTag(),处理开始标记 • doEndTag(), 处理结束标记 • release()

  9. 标记处理程序 • BodyTag接口扩展Tag接口,并提供两个附加方法来处理标记主体 • doInitBody() • setBodyContent() • 继承以下两个类来提供这两个接口的实现: • TagSupport(实现Tag接口) • BodyTagSupport(实现BodyTag接口)

  10. 标记处理程序 • doStartTag() • 自定义标记开始时调用 • 返回在标记接口中定义的 int 常量的EVAL_BODY_INCLUDE或 SKIP_BODY,以决定是否处理标记的主题部分 • doEndTag() • 在自定义标记结束时调用 • 返回 EVAL_PAGE 或 SKIP_PAGE,以决定是否处理页面的其余部分

  11. 自定义标记举例:<examples:hello> <%@ taglib uri="/hello" prefix="examples" %> <html> <head> <title>First custom tag</title> </head> <body> This is static output. <p> <i> <examples:hello></examples:hello> </i> This is static output again. </body> </html> 标记前缀 标记库描述器 hello.jsp 使用标记

  12. 自定义标记举例:标记处理器HelloTag 当在JSP中遇到这个标记时,标记处理器必须对从JSP引擎(容器)发来的调用作出反应 package tagext; //放在包tagext中,也即tagext目录下 import java.io.IOException; //向JSP文件输出时,有可能产生IO异常 import java.util.Date; //输出时间时用到的类 import javax.servlet.jsp.*;//和jsp有关的类在该包下 import javax.servlet.jsp.tagext.*; //和标记处理有关的类在该包下 public class HelloTag extends TagSupport //自定义的标记处理器, {// 要继承TagSupport类 ······································

  13. 自定义标记举例:标记处理器HelloTag(续) ···································· public int doStartTag() throws JspTagException { return EVAL_BODY_INCLUDE; } ··································· • 在 JSP中的标记:<examples:hello>,相当于开始标记,遇到此标记就调用方法doStartTag() • doStartTag()有两个返回常量:EVAL_BODY_INCLUDE和SKIP_BODY • 返回值EVAL_BODY_INCLUDE表示,JSP引擎要分析标记的体内容和它所拥有的任何的子标记 • 返回值SKIP_BODY表示,JSP引擎应该忽略体内容 • 注意,doStartTag()覆盖了TagSupport的该方法,会抛出JspTagException异常

  14. 自定义标记举例:标记处理器HelloTag(续) ········································ public int doEndTag() throws JspTagException { String dateString = new Date().toString(); //当前日期的字符串形式 try { pageContext.getOut().write("Hello world.<br/>"); pageContext.getOut().write("My name is " + getClass().getName() + " and it's " + dateString + "<p/>"); } ································· • 遇到JSP中的结束标记:</examples:hello>,引擎就调用对象的doEndTag()方法 •  其实pageContext对象就是使用hello标记的JSP页面的隐含对象,getout方法返回JspWriter对象 • getClass().getName()返回类名

  15. 自定义标记举例:标记处理器HelloTag(续) ·········································· catch (IOException ex) { throw new JspTagException("Fatal error: hello tag could not write to JSP out"); }   return EVAL_PAGE; } } • 注意调用JspWriter对象write方法会抛出IOException异常,所以要catch异常 • doEndTag()方法可有两个返回值:EVAL_PAGE和SKIP_PAGE • EVAL_PAGE会让JSP引擎去分析页面的其余内容 • SKIP_PAGE会终止页面分析过程

  16. 自定义标记举例:标记库描述器hello.tld • 标记库描述器把标记映射到标记处理器类,并且定义JSP与Hello.Tag类之间的交互方式 • 遵循Sun Microsystems定义的DTD标准的XML文档 • 标记库的所有定义放在<taglib>和</taglib>之间 

  17. 自定义标记举例:标记库描述器hello.tld(续) • <tlibversion>1.0</tlibversion>表示标记库的版本号码 • <jspversion>1.1</jspversion>表示jsp的版本号 • <shortname>examples</shortname> 是标记的前缀,当在jsp中使用标记时,它的前缀必须是在此处定义的 • <info>Simple example library.</info>是一个对标记的描述

  18. 自定义标记举例:标记库描述器hello.tld(续) ······························· <tag> <name>hello</name> <tagclass>tagext.HelloTag</tagclass> <bodycontent>JSP</bodycontent> <info>Simple example</info> </tag> ····································· • 标记库中能够包含任何数量的标记。比如此例子,我们还可以增加另外的<tag>······</tag>标记 • <name>hello</name>表示标记名称,也即标记的后缀

  19. 标记扩展目录结构 hello.jsp WEB-INF/ web.xml classes/ tagext/ HelloTag.class tlds/ hello.tld

  20. 标记扩展 的web.xml文件 ······································· <taglib> <taglib-uri>/hello</taglib-uri> <taglib-location>/WEB-INF/tlds/hello.tld</taglib-location> </taglib> ································ • 使用标记<taglib>来让服务器知道当在要在JSP引入标记时,从哪儿可以找到TLD • <taglib-uri>/hello</taglib-uri>标记对应于hello.jsp中的该行代码:<%@ taglib uri="/hello" prefix="examples" %> • <taglib-location>···</taglib-location>标记指明标记描述器的位置

  21. hello.jsp <%@ taglib uri=“/hello” prefix=“examples” %> <taglib-uri>/hello</taglib-uri> <taglib-location>/WEB-INF/tlds/hello.tld</taglib-location> web.xml <shortname>example</shortname> ·············· <name>hello</name> <tagclass>tagext.HelloTag</tagclass> ············· hello.tld 实例化 tagext.HelloTag new tagext.HelloTag(); 标记扩展的工作过程 HelloTag 1. 当在jsp中遇到自定义标记时,要找到标记处理器,首先要实例化标记处理器类

  22. <examples:hello></examples:hello> 调用对象的doStartTag()方法 调用对象的doEndTag()方法 标记扩展的工作过程(续) • 以后在JSP中遇到标记库中的标记,调用标记处理器的相应方法

  23. 一个综合的例子 • Servlet • Jsp • JavaBean

  24. login.html 功能:要求用户输入用户名和密码 请求 validate.jsp 功能:验证是否合法用户 mypackage.validate 功能:完成验证的javabean 返回结果 合法 不合法 error.jsp 功能:显示错误信息 mypackage.forky 功能:根据用户名转到不同的页面 用户名为jb或aptech 用户名为teacher teacher.jsp 功能:显示“老师们,看到了么,成功了!!同学们,你们看到了么,也成功了!”语句 jb_aptech.jsp 功能:显示“欢迎加入激动人心的ACCP之旅!”等语句 JSP+JavaBean+Servlet案例流程

  25. 案例的目录结构 %TOMCAT_HOME%\webapps\ mysample/ login.html validate.jsp jb_aptech.jsp teacher.jsp error.jsp  WEB-INF/ web.xml classes/ mypackage/ validate.class forky.class

  26. server.xml文件 • 在server.xml中加上代码: • <Context path="/mysample" docBase="mysample" reloadable="true" /> • 标签Context表示上下文应用环境,path为在浏览器中和在其他文件中使用该应用时要用的应用名 • reloadable标签的值为true表示应用中的任何类文件改变以后,在任何文件中使用的该类都要重新加载,否则不会重新加载

  27. web.xml文件 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> <web-app> <welcome-file-list> <welcome-file>login.html</welcome-file> </welcome-file-list> </web-app> <welcome-file>login.html</welcome-file>表示“欢迎”页面,就如同一个网站的index.html,是默认页面一样

  28. login.html文件 <HTML> <HEAD> </HEAD> <BODY> <form name="form1" method="post" action="validate.jsp"> 用户名: <input type="text"name="username" size="15"><br><br> 密码: <input type="password" name="password" size="15"><br><br> <input type="submit" name="Submit" value="确定"> </form> </BODY> </HTML> POST请求到validate.jsp 有两个请求变量post到validate.jsp:username和passward

  29. 变量声明部分 <%! boolean isnotlogin = false; %> <% String username = request.getParameter("username"); String password = request.getParameter("password"); if(username==null || password==null) { response.sendRedirect("error.jsp?errmsg=页面值传递错误,或者非法进入该页(在validate.jsp中)"); return; } %> ·································· 取得请求参数的值 如果没有接收到请求参数,就转到错误页面error.jsp,errmsg参数被GET请求发送到error.jsp validate.jsp文件

  30. validate.jsp文件(续) 使用javabean:mypackage.validate ···································· <jsp:useBean id="validatebean" scope="page" class="mypackage.validate" /> <jsp:setProperty name="validatebean" property="username" param="username" /> <jsp:setProperty name="validatebean" property="pwd" param="password" /> </jsp:useBean> ············································ 把请求参数username和password分别传给validatebean的属性:username和pwd

  31. validate.jsp文件(续) uservalidate()是validatebean的方法,是合法用户返回真,是非法用户返回假 ······································ <% islogin = validatebean.uservalidate(); if(!islogin) { response.sendRedirect(“error.jsp?errmsg=用户名或者口令错误!(在validate.jsp中)”); return; } else { session.setAttribute("username",username); %> ········································· 如果是合法用户,则设置session的属性/值

  32. validate.jsp文件(续) 如果是合法用户,就要转到servlet:mypackage.forky,该servlet完成的功能是根据不同的用户名,转到不同的页面 ······································· <jsp:forward page="servlet/mypackage.forky" > <jsp:param name="username" value="<%=username %>" /> </jsp:forward> <% } %> 该段代码在本程序中是没有实际意义的,只作为测试使用

  33. 错误处理文件:error.jsp <%@ page language="java" %> <%@ page contentType="text/html;charset=gb2312" %> <% String str=request.getParameter("errmsg"); String errmsg=new String(str.getBytes("ISO-8859-1"),"GBK"); //上面是处理汉字输出的很重要的方法 %> <html> <head> </head> <body> 对不起,您的操作有误。请参考下列提示: <p> <b><%=errmsg %></b> </body> </html>

  34. JavaBean:mypackage.validate package mypackage; public class validate { final String user1="jb"; final String password1="jb"; final String user2="aptech"; final String password2="aptech"; final String user3="teacher"; final String password3="student"; ······································ 在这里直接定义了登陆名和密码,但在实际编程时,登陆名和密码放在数据库里,javabean要通过JDBC访问数据库来验证用户合法性

  35. JavaBean:mypackage.validate(续) ········································ private String username=""; private String pwd=""; public void setUsername(String username) { this.username = username; } public StringgetUsername() { return this.username; } public void setPwd(String password) { this.pwd = password; } public String getPwd() { return this.pwd; } ··········································

  36. JavaBean:mypackage.validate(续) ······································································· public boolean uservalidate() { boolean temp = false; if(username.equals(user1) && pwd.equals(password1)) { temp=true; } else if(username.equals(user2) && pwd.equals(password2)) { temp=true; } else if(username.equals(user3) && pwd.equals(password3)) { temp=true; } else { temp=false; } return temp; } }

  37. servlet:mypackage.forky package mypackage; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class forky extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ //Get session HttpSession session = request.getSession(false);//false 参数禁止创建新会话 if(session==null) { response.sendRedirect(“error.jsp?errmsg=会话已经过期了!。。。”); return; } ·····························································

  38. servlet:mypackage.forky(续) ············································ String username1 = (String)session.getAttribute("username"); if(username1 == null) { return; } //Set MIME type for the response response.setContentType("text/html; charset=GBK"); //Obtain a print writer object PrintWriter out = response.getWriter(); ·············· ·····················································

  39. ···················································································· request.setAttribute("username",username2); if(username1.equals("teacher")) { getServletConfig().getServletContext().getRequestDispatcher("/teacher.jsp"). forward(request,response); } else{ getServletConfig().getServletContext().getRequestDispatcher("/jb_aptech.jsp"). forward(request,response); } } } ····································· 把request和response继续发送到定向的文件中 servlet:mypackage.forky(续)

  40. jb_aptech.jsp //如果用户名是jb或者是aptech,则从servlet转入该页面 <%@ page language="java" %> <%@ page contentType="text/html;charset=gb2312" %> <% String username1 = (String)session.getAttribute("username"); if(username1==null) { response.sendRedirect(“error.jsp?errmsg=会话已经过期了。。。”); return; } out.print("<br>"); out.print("欢迎加入激动人心的ACCP之旅!"); out.print("<br>"); out.print("同学们,只要你刻苦、努力的学习,我们相信,你就有美好的前程!"); out.print("<br>"); %>

  41. teacher.jsp //如果用户名是teacher,则从servlet导入该页面 <%@ page language="java" %> <%@ page contentType="text/html;charset=gb2312" %> <% String username1 = (String)session.getAttribute("username"); if(username1==null) { response.sendRedirect(“error.jsp?errmsg=会话已经过期了!”); return; } out.print("哈哈!"); out.print("<br>"); out.print("老师们,看到了么,成功了!!"); out.print("<br>"); out.print("同学们,你们看到了么,也成功了!"); out.print("<br>"); out.print(“成功来之不易,要继续努力哦!"); %>

  42. 案例运行 • 启动tomcat,在浏览器中输入http://127.0.0.1:8080/mysample/ ,将会显示登陆页面,如果用户名或密码错误,会出现错误信息 • 如果用户名为jb或aptech、teacher,将显示不同的页面

  43. 本讲总结 • JSP标记可以分为三种类型 指令 脚本元素 动作

  44. 本节小结 • 标记扩展的概念 把“标记”映射到一个或多个Java类,使得用Java类完成“标记”的功能

  45. 本讲总结(续) • 标记处理器,实际上是实现了标记具体功能的类,是一个JavaBean,它扩展了JSP API提供的某个类

  46. 本讲总结(续) • 一个标记库描述器TLD文件是一个XML文档,它描述了包含着一个或多个标记扩展的标记库

  47. 本节小结(续) • 标记扩展和JavaBean的区别 标记扩展用于公共的构建块 JavaBean为特定需求开发

  48. 本节小结(续) • 使用JSP+Servlet+JavaBean开发自己的Web应用 在实际的应用中,用户名信息存储在数据库中, javabean要使用JDBC和数据库相连 在设计Web应用程序时,尽量把“应用逻辑”放在servlet或者javabean中,对数据库的操作应该放在javabean中

  49. 下课了。。。 休息一会儿。。。

More Related