|
|
(承接 漫步j2ee之jsp技术(1))
首先说明一下,这是我写的关于j2ee技术介绍的第五篇文章,这篇是专门讨论jsp技术,适合有一定的jsp基础的人员参考总结用。
Resin服务器的输出如下: Resin 1.2.2 -- Tue Jan 16 09:53:18 PST 2001 http listening to *:8080 srun listening to 127.0.0.1:6802 BulidConnection()方法被调用 会话级别的数据库连接已经建立!!! 由此可知,当DBBean1.jsp文件中定义DBCon对象的生命周期为session时,就触发了HttpSessionBindingEvent事件,并调用了valueBound方法,建立了“会话级别的数据库联机”。 然后,我们再在DBBean2.jsp等多个页面中跳转,Resin服务器的输出仍然如上所示,这就表明了,同一会话中的各个页面均使用了同一个数据库联机,所以才没有建立新的联机。 当关闭服务器的时候,输出数据如下: Resin 1.2.2 -- Tue Jan 16 09:53:18 PST 2001 http listening to *:8080 srun listening to 127.0.0.1:6802 BulidConnection()方法被调用 会话级别的数据库连接已经建立!!! closing server 会话级别的数据库连接已经关闭!!! 此时,会话结束,触发了HttpSessionBindingEvent事件,并调用了valueUnbound方法,关闭了先前建立的会“话级别的数据库联机”。 4. Bean的保存与读取 到目前为止,我们所使用的Bean对象均能于建立该对象的页面中使用,而无法将执行的结果保存下来供下次页面执行使用。现在,我们就来讨论一下Bean的保存的问题。 若要某个Bean对象保存进文件,就必须使该Bean可串行化,即该Bean必须实现java.io.Serializable接口。 另外,如果要把Bean对象保存进文件,或是从文件中读取Bean对象,需要用到四个特别的java.io包中的对象,它们是FileOutputStream、ObjectOutputStream、FileInputStream、ObjectInputStream,其中的前两个使用来保存Bean对象的,后两个则是用来读取Bean对象的。具体的使用方法,我们还是通过例子来说明吧!!! ² Bean对象的保存与读取 我们将要建立如下几个文件,它们的用途及说明如下表: 文件名称 说明 用途 SaveBean.java 定义要保存进文件的Bean对象,此对象将实现Serializable接口。 此Bean中将保存姓名、性别、年龄、生日、爱好这五个个人信息。 BeanSaver.java 定义将Bean对象保存进文件,或是从文件中读取Bean对象的BeanSaver对象。 用来保存或是读取Bean对象。 SaveBean.jsp 建立SaveBean对象,并设定相应的个人信息,然后,把此对象写入文件。 建立SaveBean对象,并利用BeanSaver对象把SaveBean对象写入文件SB.ser。 LoadBean.jsp 利用BeanSaver对象,从文件中取得SaveBean对象。 从文件SB.ser中取得SaveBean对象,然后将其内容,即个人信息显示在页面上。 两个Bean的源文件如下: SaveBean.java
编译上面的两个源文件,产生j2ee.jsp.SaveBean.class与j2ee.jsp.BeanSaver.class。 两个jsp页面的程序代码如下: SaveBean.jsp
- <%@ page contentType="text/html; charset=GB2312" %>
- <HTML>
- <HEAD>
- <TITLE>Bean对象的保存与取得</TITLE>
- </HEAD>
- <BODY>
- <CENTER>
- <FONT SIZE = 5 COLOR = blue>Bean对象的保存</FONT>
- </CENTER>
- <HR>
-
- <jsp:useBean id="info" scope="page"
- class="j2ee.jsp.SaveBean"/>
- <%
- //调用Bean对象的方法, 设定属性
- info.setName("最后的决定");
- info.setSex("男");
- info.setAge(22);
- info.setBirth("1981-9-10");
- info.setLove("流行音乐,武侠剧,唱歌,互联网,漂亮mm");
- %>
-
-
- <jsp:useBean id="saver" scope="page"
- class="j2ee.jsp.BeanSaver"/>
- <%
- //保存对象
- saver.save(info,"D:\\java\\SB.ser");
- %>
-
- <H2>
- SaveBean对象已经保存完毕
- </H2>
-
- </BODY>
- </HTML>
- LoadBean.jsp
- <%@ page contentType="text/html; charset=GB2312"
- import="j2ee.jsp.*"%>
- <HTML>
- <HEAD>
- <TITLE>Bean对象的保存与取得</TITLE>
- </HEAD>
- <BODY>
- <CENTER>
- <FONT SIZE = 5 COLOR = blue>Bean对象的取得</FONT>
- </CENTER>
- <HR>
- <P></P>
- <jsp:useBean id="saver" scope="page"
- class="BeanSaver"/>
- <jsp:useBean id="info" scope="page"
- class="SaveBean"/>
- <%
- //将对象设定至pageContext对象中
- pageContext.setAttribute("info", saver.load("d:\\java\\SB.ser"));
-
- //若欲已调用Bean对象方法的方式运用Bean时, 需使用此叙述
- info = (SaveBean) pageContext.getAttribute("info");
- %>
-
- 个人资料<br>
- <Font color = red>姓名:</Font>
- <Font color = blue>
- <%= info.getName() %></Font><BR>
- <Font color = red>性别:</Font>
- <Font color = blue>
- <%= info.getSex() %></Font><BR>
- <Font color = red>年龄:</Font>
- <Font color = blue>
- <%= info.getAge() %></Font><BR>
- <Font color = red>生日:</Font>
- <Font color = blue>
- <%= info.getBirth() %></Font><BR>
- <Font color = red>爱好:</Font>
- <Font color = blue>
- <%= info.getLove() %></Font><BR>
-
- </BODY>
- </HTML>
首先在运行SaveBean.jsp,结果如下: 然后运行LoadBean.jsp,显示如下: 至此,恭喜你已经学会了JavaBeans所有最核心的应用了,jsp强大的功用也已经展现在了你的眼前,快去构建威力无穷的Web应用吧,祝你一路顺风:) 。
六. JSP中的文件操作 自从有了数据库系统以后,文件的操作似乎变得不再那么重要了,很多大型的应用系统也往往愿意把数据的存取工作交给数据库而不是文件。就笔者自身的体会是,数据库的确在很多时候可以替代文件,但在某些特定的应用上使用文件可以得到更佳的应用效果和方便的操作特性,而且在操作少量数据的存取时,文件不但方便保存携带,更不像数据库那样运行时需要消耗大量的服务器资源。因此,笔者认为,文件的操作仍然是一个重点。 要在JSP中操作文件,大体上需要用到java.io.*包中的数个类及其相应的方法,很多时候实现同一功能都有数种不同的方法。在此,笔者不想在各个类的基本定义格式及其相应方法的说明上多费笔墨,而是直接把一个集合了众多文件操作功能的Bean呈现在各位读者面前。使用此Bean,可以进行绝大多数的文件操作,至于其中具体到某个类、某个方法的操作原理及其细节,请各位参看相关资料。 下表列出了CtrlFile类的所有公开方法及其说明: 方法名 用途说明 createNewFile 建立一个新的文件 deleteFile 删除文件 createNewDir 建立一个新的目录 deleteDir 删除目录 fileLength 测量文件的长度 isFile 判断是不是文件 isDir 判断是不是目录 readLine 读取文件的第一行 readAll 读取整个文件的内容 writeLine 把数据写入文件 writeAppend 把数据追加入文件
- /*
- * 文件名:CtrlFile.java
- *
- * 类名:CtrlFile
- *
- * 所属包:j2ee.jsp
- *
- * 导入包:import java.io.*;
- *
- * 作者:杨??
- *
- * 创建时间:2003.12.10
- *
- * 用途描述:对目录、文件进行读、写、新建、删除等操作。
- *
- * 版本号:1.0
- *
- */
-
- package j2ee.jsp;
-
- import java.io.*;
-
- //注意:各个函数中要到的参数path均为实际路径.
-
- public class CtrlFile
- {
-
- /**
- * 方法名:FileName
- * 级别:private
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return String 文件名
- * @throws (无)
- * 作用:从文件的实际路径中取出文件名
- */
- private String FileName(String path)
- {
- int pos = path.lastIndexOf('\\');
- String FileName = path.substring(pos+1);
- return(FileName);
- }
-
- /**
- * 方法名:PathName
- * 级别:private
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return String 路径
- * @throws (无)
- * 作用:从文件的实际路径中取出路径
- */
- private String PathName(String path)
- {
- int pos = path.lastIndexOf('\\');
- String PathName = path.substring(0,pos);
- return(PathName);
- }
-
- /**
- * 方法名:createNewFile
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @param boolean 是否覆盖
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:建立一个新的文件
- */
- public void createNewFile(String path,boolean rebuild) throws Exception
- {
- String FileName = new String(FileName(path));
- String PathName = new String(PathName(path));
- File f = new File(PathName,FileName);
- if(rebuild==true)
- {
- if(f.exists()==true)
- {
- f.delete();
- }
- f.createNewFile();
- }
- else
- {
- if(f.exists()==false)
- {
- f.createNewFile();
- }
- }
-
- }
-
- /**
- * 方法名:deleteFile
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:删除文件
- */
- public void deleteFile(String path) throws Exception
- {
- String FileName = new String(FileName(path));
- String PathName = new String(PathName(path));
- File f = new File(PathName,FileName);
- f.delete();
- }
-
- /**
- * 方法名:createNewDir
- * 级别:public
- * @param String 目录的实际路径
- * @param boolean 是否覆盖
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:建立一个新的目录
- */
- public void createNewDir(String path,boolean rebuild) throws Exception
- {
- File d = new File(path);
- if(rebuild==true)
- {
- if(d.exists()==true)
- {
- d.delete();
- }
- d.mkdir();
- }
- else
- {
- if(d.exists()==false)
- {
- d.mkdir();
- }
- }
- }
-
- /**
- * 方法名:deleteDir
- * 级别:public
- * @param String 目录的实际路径
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:删除目录
- */
- public void deleteDir(String path) throws Exception
- {
- File d = new File(path);
- d.delete();
- }
-
- /**
- * 方法名:fileLength
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return long 文件的长度
- * @throws Exception 如果发生错误
- * 作用:测量文件的长度
- */
- public long fileLength(String path) throws Exception
- {
- String FileName = new String(FileName(path));
- String PathName = new String(PathName(path));
- File f = new File(PathName,FileName);
- long fileLength = f.length();
- return(fileLength);
- }
-
- /**
- * 方法名:isFile
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return boolean 是否文件
- * @throws Exception 如果发生错误
- * 作用:用来判断是不是文件
- */
- public boolean isFile(String path) throws Exception
- {
- String FileName = new String(FileName(path));
- String PathName = new String(PathName(path));
- File f = new File(PathName,FileName);
- boolean isFile = f.isFile();
- return(isFile);
- }
-
- /**
- * 方法名:isDir
- * 级别:public
- * @param String 目录的实际路径
- * @return boolean 是否目录
- * @throws Exception 如果发生错误
- * 作用:用来判断是不是目录
- */
- public boolean isDir(String path) throws Exception
- {
- File d = new File(path);
- boolean isDir = d.isDirectory();
- return(isDir);
- }
-
- /*-------------------------以上是针对文件的操作-------------------------*/
-
- /*-------------------------以下是针对文件的读写-------------------------*/
-
- /**
- * 方法名:readLine
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return String 文件中第一行的内容
- * @throws Exception 如果发生错误
- * 作用:用来读取文件的第一行
- */
- public String readLine(String path) throws Exception
- {
- FileReader fr = new FileReader(path);
- BufferedReader br = new BufferedReader(fr);
- String Line = br.readLine();
- return(Line);
- }
-
- /**
- * 方法名:readAll
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @return String 文件中的所有内容
- * @throws Exception 如果发生错误
- * 作用:用来读取整个文件的内容
- */
- public String readAll(String path) throws Exception
- {
- FileReader fr = new FileReader(path);
- BufferedReader br = new BufferedReader(fr);
- String txt = new String();
- String Line = new String();
- Line = br.readLine();
- while(Line!=null)
- {
- txt = txt + Line;
- Line = br.readLine();
- }
- br.close();
- fr.close();
- return(txt);
- }
-
- /**
- * 方法名:writeLine
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @param String 要写入文件中的内容
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:用来把数据写入文件
- */
- public void writeLine(String path,String content) throws Exception
- {
- FileWriter fw = new FileWriter(path);
- fw.write(content);
- fw.close();
- }
-
- /**
- * 方法名:writeAppend
- * 级别:public
- * @param String 文件的实际路径 , 即:路径 + 文件名
- * @param String 要写入文件中的内容
- * @return (无)
- * @throws Exception 如果发生错误
- * 作用:用来把数据追加入文件
- */
- public void writeAppend(String path,String content) throws Exception
- {
- FileWriter fw = new FileWriter(path,true);
- PrintWriter pw = new PrintWriter(fw);
- pw.print(content + "\n");
- pw.close();
- fw.close();
- }
- }
七. JSP运行原理剖析 谈到JSP的运行原理,就不得不谈到Servlet了。虽然按照Sun的观点,将来是要用JSP替代Servlet的,但JSP是在Servlet的基础上发展起来的,要深刻理解JSP的运行原理,就一定需要Servlet的相关知识。在阅读本节前,笔者假设你已经至少对Servlet有了基本的概念理解。OK,不再多说废话了,Let’s go!! Servlet技术的出现时间很早,是当时为了Java的服务器端应用而开发的。大家都知道Applet是应用小程序,Servlet就是服务器端小程序了。但在Microsoft公司的ASP技术出现后,使用Servlet进行响应输出时一行行的输出语句就显得非常笨拙,对于复杂布局或者显示页面更是如此。JSP就是为了满足这种需求在Servlet技术之上开发的。可见,JSP和Servlet之间有着内在的血缘关系,在学习JSP时,如果能够抓住这种联系,就能更深刻地理解JSP的运行机理,达到事半功倍的效果。 JSP页面的请求响应过程如下图: 下面笔者举例说明: HelloWorld.jsp代码清单如下:
- <%@ page contentType="text/html; charset=GB2312"%>
- <HTML>
- <HEAD>
- <TITLE>Hello World</TITLE>
- </HEAD>
- <BODY>
- <%="Hello World!!!!!!"%>
- </BODY>
- </HTML>
这个文件存放在D:\java\resin1.2.2\webapps中,通过浏览器请求执行HelloWorld.jsp: http://127.0.0.1:8080/helloworld.jsp。 服务器resin接到这个请求后,调出jsp引擎,首先将HelloWorld.jsp解析成Servlet存入D:\java\resin1.2.2\work\_jsp目录,文件名是_helloworld__jsp.java,此Servlet的源代码如下:
- /*
- * JSP generated by Resin 1.2.2 -- Tue Jan 16 09:53:18 PST 2001
- */
-
- package _jsp;
- import java.io.*;
- import javax.servlet.*;
- import javax.servlet.jsp.*;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.http.*;
-
- public class _helloworld__jsp extends com.caucho.jsp.JavaPage{
-
- public void
- _jspService(javax.servlet.http.HttpServletRequest request,
- javax.servlet.http.HttpServletResponse response)
- throws java.io.IOException, javax.servlet.ServletException
- {
- com.caucho.jsp.QPageContext pageContext = (com.caucho.jsp.QPageContext)
- com.caucho.jsp.QJspFactory.create().getPageContext(
- this, request, response, null, true, 8192, true);
- javax.servlet.jsp.JspWriter out = (javax.servlet.jsp.JspWriter)
- pageContext.getOut();
- javax.servlet.ServletConfig config = getServletConfig();
- javax.servlet.Servlet page = this;
- javax.servlet.http.HttpSession session = pageContext.getSession();
- javax.servlet.ServletContext application = pageContext.getServletContext();
- response.setContentType("text/html; charset=GB2312");
- try {
- pageContext.write(_jsp_string0, 0, _jsp_string0.length);
- out.print(("Hello World!!!!!!"));
- pageContext.write(_jsp_string1, 0, _jsp_string1.length);
- } catch (java.lang.Throwable e) {
- pageContext.handlePageException(e);
- } finally {
- JspFactory.getDefaultFactory().releasePageContext(pageContext);
- }
- }
-
- private com.caucho.java.LineMap _caucho_line_map;
- private java.util.ArrayList _caucho_depends = new java.util.ArrayList();
-
- public boolean _caucho_isModified()
- {
- if (com.caucho.util.CauchoSystem.getVersionId() != -1355223632)
- return true;
- for (int i = _caucho_depends.size() - 1; i >= 0; i--) {
- com.caucho.vfs.Depend depend;
- depend = (com.caucho.vfs.Depend) _caucho_depends.get(i);
- if (depend.isModified())
- return true;
- }
- return false;
- }
-
- public long _caucho_lastModified()
- {
- return 0;
- }
-
- public com.caucho.java.LineMap _caucho_getLineMap()
- {
- return _caucho_line_map;
- }
-
- public void init(com.caucho.java.LineMap lineMap,
- com.caucho.vfs.Path appDir)
- throws javax.servlet.ServletException
- {
- com.caucho.vfs.Path resinHome = com.caucho.util.CauchoSystem.getResinHome();
- com.caucho.vfs.MergePath mergePath = new com.caucho.vfs.MergePath();
- mergePath.addMergePath(appDir);
- mergePath.addMergePath(resinHome);
- mergePath.addClassPath(getClass().getClassLoader());
- _caucho_line_map = new com.caucho.java.LineMap
- ("_helloworld__jsp.java", "/helloworld.jsp");
- _caucho_line_map.add(1, 1);
- _caucho_line_map.add(1, 27);
- _caucho_line_map.add(7, 28);
- com.caucho.vfs.Depend depend;
- depend = new com.caucho.vfs.Depend(appDir.lookup("helloworld.jsp"),
- 1071120876000L, 155L);
- _caucho_depends.add(depend);
- }
-
- private static byte []_jsp_string1;
- private static byte []_jsp_string0;
- static {
- try {
- _jsp_string1 = "\r\n</BODY>\r\n</HTML>".getBytes("GB2312");
- _jsp_string0 = "\r\n<HTML>\r\n<HEAD>\r\n<TITLE>Hello World</TITLE>\r\n</HEAD>\r\n<BODY>\r\n".
- getBytes("GB2312");
- } catch (java.io.UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- }
从上面可以看出,HelloWorld.jsp在运行时首先解析成一个Java类_helloworld__jsp.java,该类继承于com.caucho.jsp.JavaPage基类,此基类实现了HttpServlet接口。可见,JSP在运行前首先将编译为一个Servlet,这就是理解JSP技术的关键。 我们还知道JSP页面中内置了几个对象,如pageContext、application、config、page、session、out等,你可能会奇怪,为什么在JSP中的代码片断中可以直接使用这些内置对象。观察_jspService()方法,实际上这几个内置对象就是在这里定义的。在对JSP文件中的代码片断进行解析之前,先对这几个内置对象进行初始化。 原来jsp文件中的“<%="Hello World!!!!!!"%>”被翻译成了“out.print(("Hello World!!!!!!"));”。 jsp引擎将HelloWorld.jsp解析成_helloworld__jsp.java后,再将_helloworld__jsp.java编译成_helloworld__jsp.class,接着执行_helloworld__jsp.class,这时才通过out内置对象将HelloWorld.jsp页面内容送至客户端的浏览器。 最后,_helloworld__jsp.class就存入了服务器电脑的内存里,往后再执行请求页面HelloWorld.jsp时,就直接执行存于服务器电脑内存里面的_helloworld__jsp.class了。 本篇“JSP技术”到此结束,一路走来,笔者详述了jsp的整个框架结构以及开发中最核心的技术应用,最后还从全新的角度对jsp的运行原理进行了阐述。现在,你是否感觉自己已经是个jsp的高手了呢?
--------------------====全文完===-----------------
author:杨坤 address:华中科技大学 qq:281174319 |
|