ShenXianGL's Billboard

来访者请看这里,团队创建中
弃用QQ,gtalk找我,shenxiangl@gmail.com,或者blog留言,点击文章下的comment链接或者在旁边的connect with me都可以和我联系
有人知道如何灭火,请和我联系
引用我文章的朋友请看这里
Showing posts with label java及相关技术. Show all posts
Showing posts with label java及相关技术. Show all posts

Sunday, April 1, 2007

西单图书大厦

798出来,就跑到西单图书大厦了,逛到死,找程序设计艺术,结果发现并不是很实用,就买了另外几本书
JSP程序设计
J2EE核心模式
STRUTS基础教程
SPRING IN ACTION中文版
HIBERNATE QUICKLY中文版

Tuesday, March 20, 2007

当咔吧死机遇到jdk

重装系统,一直都好懒 ,现在才装jdk
装过无数次,可以用轻车熟路来形容我装jdk的感觉,但是今天的车似乎换成方轮子,路却多了几条岔路

正常启动jdk安装文件,我用的是jdk1.5.0.07,NEtBeans版本.新版本懒得下,让他自己升级去吧,一切顺利,安装.
到了百分比进度条,到了7%却发生了让人觉得不可思议的事情,完全升级之后的咔吧死机,居然弹出对话框说有

已检测到: 风险软件 RootShell 运行进程: C:\Documents and Settings\***\Local Settings\Temp\LRE9D.tmp\bin\java.exe
奇怪,sun的东西怎么能出现这种东西呢?算了,权且相信sun,允许
完蛋了,居然jdk卡在那里不动了,莫名其妙,只有从进城里面关闭,重新安装
重新安装时候情况同样,就不罗嗦,最后是把咔吧死机关掉才正确安装的jdk

回头搜索了什么是 风险软件 RootShell 没发现什么,并没有发现这个风险软件到底是什么,去咔吧死机官网,对这个风险软件的解释也是空页面,现在开始怀疑是不是咔吧死机患有猜忌症了,同时搜索也发现咔吧死机也对oracle有相应的阻止记录(当然甲骨文也是用jdk的)

所以建议大家在安装jdk相关的东西的时候先把咔吧死机停止掉,还,我这里安装完成之后就并没有出现任何问题

Tuesday, February 13, 2007

利用Servlet技术实现Web数据库查询

Servlet最重要的用途之一就是实现三层结构的Web数据库模式,即客户浏览器、 Web服务器和数据库服务器三层结构,这也是当前Internet/Intranet最流行的应用模式之一。本文讨论了基于这种模式利用Servlet技术查询Web数据库的方法。

本文使用的软件包为jsdk2.1,安装的目录为 C:jdk1.2jsdk2.1。客户机的平台为Windows XP,安装IE 5.0,Web服务器为Windows NT 4.0 SP4,安装Microsoft Internet Information Server (IIS) 4.0,IP地址为98.53.72.169。

一、关于Servlet

Servlet是用Java编写的、协议和平台独立的服务器端组件,它采用“请求/响应”模式, 提供了一种基于Java的Web服务器的解决方案,可以动态地扩展支持Java的Web服务器。由于Servlet运行在服务器内部,它们不需要图形用户接口。

虽然所有的Servlet都是用Java写的,但它们的客户端可以使用别的语言编写,当Servlet作为在分布式应用系统的中间层使用时,对于用其他语言编写的其他的服务,它们可以交替地成为客户机或服务器。

Servlet API的最大优点是协议的独立性,它不假定网络传输使用的协议、Servlet如何装载以及运行的服务器环境,这些特性使得Servlet API可以方便地嵌入到许多不同种类的服务器中。另外,它还具有可扩展、简单、短小、容易使用的特点。

Servlet最突出的特征之一就是对于每一个请求不需要像 CGI那样单独创建一个新的进程。在大多数环境中,许多Servlet可以并行运行在与服务器相同的进程中,这是因为Servlet仅仅要求轻量级的、现 成的上下文转换,即便是Fast -CGI,每个请求都涉及重量级的进程上下文的转换。由于在大多数环境中,Servlet可以处理许多已初始化的客户请求,这些初始化的开销由许多方法分 担,对于该Service方法所面对的所有客户请求,它们都有机会共享数据和通讯资源,并充分利用系统缓存的优点。

二、Servlet编程基础

1. HttpServlet类

HttpServlet类是一个抽象类,我们可以从该类派生出一个子类来实现一个 Http servlet,接受来自Web站点的请求(该请求来自访问该Web站点的客户浏览器),并将处理后的响应结果发回Web站点(Web站点再将响应结果发 送给客户浏览器),在HttpServlet的子类中,我们必须至少重载表1中所列的一种方法。对于表 1中的每一种Http请求,service方法通过分派它们到相应的handler线程(doXXX方法)来处理这些标准的Http请求。

Servlet通常运行在多线程的服务器中,因此,我们编写的 Servlet代码必须能够处理并行请求和对数据资源的同步访问。共享资源包括内存中的数据(例如:实例或类变量)和外部对象(例如:文件、数据库连接或网络连接)。

在DemoTable.java中使用的doGet方法的原型如下:

  protected void doGet (HttpServletRequest req,
HttpServletResponse resp)

  throws ServletException, IOException

doGet方法从service方法接受并处理HTTP GET请求。 GET方法允许客户读取来自Web服务器的信息,客户通过传递一个带URL的查询字符串可以告诉服务器它需要什么信息。

如果重载该方法,我们应该从请求读数据,在响应中设置整个headers,访问 PrintWriter或输出流对象,最后写响应数据。当设置headers时,应确保包含content type和encoding。如果使用PrintWriter对象返回响应,在存取PrintWriter对象之前必须设置content type。Servlet引擎必须在写响应数据之前写headers,因为在写数据之后headers随时都可能被刷新。如果请求的格式不正确, doGet方法将返回一个HTTP BAD_REQUEST信息。

参数req为一个HttpServletRequest对象,含有客户浏览器的Servlet请求;resp是一个HttpServletResponse对象,含有Servlet发送给客户浏览器的响应。

2.HttpServletRequest接口

HttpServletRequest接口扩展了javax.servlet. ServletRequest 接口,用于提供更多的功能给HttpServlet。Servlet引擎实现该接口,创建HttpServletRequest 对象,将来自客户浏览器的信息传递给HttpServlet的service方法。

3.HttpServletResponse接口

HttpServletResponse接口扩展了OutputStream类,因此,我们可以使用OutputStream类中声明的方法,例如getOutputStream和println方法。

三、Windows NT服务器端数据库的设置

为简单起见,本文不使用SQL Server作为数据库服务器,而是直接使用一个简单的数据库DemoTable.DBF,该数据库的内容如图2所示。NT服务器上设置ODBC数据库资源的方法如下:

(1)在“控制面板”选择“ODBC Data Sources”;

(2)在弹出的对话框中选择“User DSN”选项卡,选择“Visual FoxPro Tables”,点击“Add...”按钮;

(3)在弹出的对话框中选择“Microsoft Visual FoxPro Driver(*.dbf)”,点击“下一步”按钮;

(4)在“ODBC Visual FoxPro Setup”对话框中。

四、源程序:DemoTable.java

import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class DemoTable extends HttpServlet
{
Connection con;

public void init(ServletConfig config)
throws ServletException
{
super.init(config);

try {
// 加载 jdbc-odbc 桥驱动程序
Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver");
//得到与数据库的连接
con = DriverManager.getConnection
(“jdbc:odbc:DemoTable", “", “");
}catch (ClassNotFoundException e){
throw new UnavailableException(this,
“Couldn't load JdbcOdbcDriver");
}catch (SQLException e) {
throw new UnavailableException(this,
“Couldn't get db connection");
}
}

public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
String sql = “SELECT
* from DemoTable ORDER BY test_id";

try {
//建立输出的类型
res.setContentType(“text/plain");
//得到输出流
ServletOutputStream out = res.getOutputStream();

try {
//得到一个Statement对象
Statement stmt = con.createStatement();

if (stmt.execute(sql))
{
//查询数据库中的表DemoTable,
得到以test_id排序后的所有记录,
并存储在ResultSet对象rs中
ResultSet rs = stmt.getResultSet();
out.println(“< TABLE >
");

ResultSetMetaData rsmd = rs.getMetaData();
int numcols = rsmd.getColumnCount();
// 输出表头
out.println(“< TR >");
for (int i = 1; i < = numcols; i++)
out.println(“< TH >" + rsmd.getColumnLabel(i));
out.println(“< /TR >
");

//输出记录
while(rs.next()){
out.println(“< TR >");

for(int i = 1; i < = numcols; i++) {
out.println(“< TD >");
Object obj = rs.getObject(i);
if (obj != null)
out.println(obj.toString());
else
out.println(“&nbsp;");
}
out.println(“< /TR >
");
}
out.println(“< /TABLE >
");
}
else {
out.println(“< B >Records Affected:< /B >
" +stmt.getUpdateCount());
}
}catch (SQLException e) {
out.println(“< /TABLE >< H1 >ERROR:
< /H1 > " + e.getMessage());
}
con.close(); //关闭与数据库的连接
}catch(SQLException e) {
//不处理异常
}
}
}

五、程序编译与发布

在编译Servlet程序时,必须指定Javax包的类路径,我们即可以在CLASPATH环境变量中设置server.jar和servlet.jar的路径,也可以直接在编译时指定,例如:

javac -classpath c:jdk1.2jsdk2.1server.jar; c:jdk1.2jsdk2.1servlet.jar DemoTable.java

编译通过后,我们应该将编译得到的HelloWorl.class文件复制到 Servlet服务器的HOME目录下,由于当前jsdk2.1的安装目录为C:jdk1.2jsdk2.1,所以其HOME目录为C: jdk1.2jsdk2.1examplesWEB-INFservlets,这是一个真实路径,对于本例中所使用的服务器而言,其对应的虚拟路径为: http://98.53.72.169:8080/servlets/,客户浏览器访问Servlet服务器时,应该使用虚拟路径。

六、运行Servlet

在使用浏览器访问该 Servlet之前,必须先启动Servlet 服务器。在Windows NT上启动Servlet服务器很简单,可以在MS-DOS命令行上直接运行startserver批处理文件(在C:jdk1.2jsdk2.1目录 下)。如果Servlet服务器启动正确,将弹出另一个DOS窗口,作为一个单独的进程运行。在DOS命令行上运行stopserver可以停止。


JAVA中对象创建和初始化过程

分析一下JAVA中对象创建和初始化过程中涉及的相关概念问题,java中栈(stack)与堆(heap),对象、引用、句柄的概念。

@Author:ZJ 06-11-25

Blog: http://zhangjunhd.blog.51cto.com/

1.Java中的数据类型

Java中有3个数据类型:基本数据类型(在Java中,boolean、byte、short、int、long、char、float、double这八种是基本数据类型)、引用类型和null类型。其中,引用类型包括类类型(含数组)、接口类型。

下列语句声明了一些变量:

以下是引用片段:
int k ;
A a; //a是A数据类型的对象变量名。
B b1,b2,…,b10000;// 假定B是抽象类或接口。
String s;

注意:从数据类型与变量的角度看,基本数据类型变量k、类类型变量a和s、抽象类或接口类型变量b(1万个),它们都是变量(标识符)。

2.关于句柄(handle)

为了区别引用类型的变量标识符和基本数据类型变量标识符,我们特别的使用Handle来称呼引用类型的变量标识符。上面例子中b1至b10000、a、s都是Handle。Handle直观的看就是手柄、把手,我们采用计算机界常用的中文翻译“句柄”。

2.1【Windows编程中的】句柄的含义

句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一 样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句 柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的 各对象是驻留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错 特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足 各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?

为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元 的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可 以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。

句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象

2.2Java中句柄的意义

对句柄以前的【Windows编程中的】含义有了深刻的认识,我们可以说Handle是一个我们学习Java时非常需要的术语。它的意义在于区别“对象本身”和对象变量(或者严格点:对象所属的数据类型的变量标识符)。

2.3回到1中的变量声明:

现在,你应该对下面的注释一目了然。

int k, j ;//k里面存放的是一个整型数。

A a; //a里面存放地址。

B b1,b2,…,b10000;// b1,…,b10000里面存放地址。

String s; //s里面存放地址。

  3.关于引用(reference)

  什么是“引用”? “the identifier you manipulate is actually a ‘reference’ to an object”。(Thinking in Java 2e )

  翻译是:你操纵的标识符实际上是一个对象的“引用”。或者精确些,翻译成:你操作的标识符实际上是指向一个对象的“引用”。显然,原文中reference是一个有方向感的东西。

  回到Java中来,引用可以想象成对象的身份证号码、对象的ID或者对象的手机号码。当然,更多的说法是,引用是对象在内存中住的房间号码。直观的说,对象的引用是创建对象时的返回值!引用是new表达式的返回值。

  new A(); 这里真正创建了一个对象,但我们没有用句柄去持有(hold、拿着、保存)该引用。从微观上看,new表达式完成了对象初始化的任务(三步曲,下文详细分析),整体上看则返回一个引用。

  再次回到1中的变量声明,再看看下面的注释。

  A a; //声明句柄a,但未初始化,所以里面的值为null。

  B b1,b2,…,b10000;// 声明句柄b1,…,b10000,但未初始化,所以里面的值为null。

  String s; //声明句柄s,但未初始化,所以里面的值为null。

  4.句柄与引用的关系

  A a;//声明句柄a,值为null

  a=new A();//句柄的初始化(句柄 = 引用;即把引用赋值给句柄)

  引用:new A()的值。引用可以简单的看作对象占据内存空间的地址;通过对象的引用,就可以方便的与其他对象区别开来,引用就是对象独特的身份标识。

  完成句柄的初始化后,就可以用句柄遥控对象了。

  当然,这只是从一方面解释对象的创建和初始化,理解了句柄和引用的关系后,下面分析对象初始化的整个过程。先做以下准备工作,说说栈与堆。

  5.java中栈(stack)与堆(heap)

  在java中内存分为“栈”和“堆”这两种(Stack and Heap).基本数据类型存储在“栈”中,对象引用类型实际存储在“堆”中,在栈中只是保留了引用内存的地址值。

  顺便说说“==”与“equals()方法”,以帮助理解两者(Stack and Heap)的概念。

  在Java中利用"=="比较变量时候,系统使用变量在stack(栈)中所存的值来作为对比的依据,基本数据类型在stack中所存的值就是 其內容值,而引用类型在stack中所存放的值是本身所指向Heap中对象的地址值。 Java.lang包中的Object类有public boolean equals (Object obj)方法。它比较两个对象是否相等。仅当被比较的两个引用指向同一对象时(句柄相等),对象的equals()方法返回true。(至于String 类的equals()方法,它重写(override)equals()方法,不在本文讨论之列。)

  6.对象的创建和初始化过程

  在java中对象就是类的实例。在一般情况下,当把一个类实例化时,此类的所有成员,包括变量和方法,都被复制到属于此数据类型的一个新的实例中去。分析以下两段代码。

  6.1 Vehicle veh1 = new Vehicle();

  上面的语句做了如下的事情:

  ①右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。

  ②末尾的()意味着,在对象创建后,立即调用Vehicle类的构造函数,对刚生成的对象进行初始化。构造函数是肯定有的。如果没创建,Java会补上一个默认的构造函数。

  ③左边的“Vehicle veh1”创建了一个Vehicle类引用变量。

  ④“=”操作符使对象引用指向刚创建的那个Vehicle对象。(回想一下句柄与引用)

  将上面的语句分为两个步骤:

  Vehicle veh1;

  veh1 = new Vehicle();

  这样写,就比较清楚了,有两个实体:一是对象引用变量,一是对象本身。在堆空间里创建的实体,与在栈空间里创建的实体不同。尽管它们也是确确实 实存在的实体,但是似乎很难准确的“抓”住它。我们仔细研究一下第二句,找找刚创建的对象叫什么名字?有人说,它叫“Vehicle”。不对, “Vehicle”是类(对象的创建模板)的名字。一个Vehicle类可以据此创建出无数个对象,这些对象不可能全叫“Vehicle”。对象连名都没 有,没法直接访问它。我们只能通过对象引用来间接访问对象。

  6.2 Vehicle veh2;

  veh2 = veh1;

  由于veh1和veh2只是对对象的引用,第二行所做的不过是把veh1的引用(地址)赋值给veh2,使得veh1和veh2同时指向唯一的一个Vehicle对象。

  6.3 veh2 = new Vehicle();

  则引用变量veh2改指向第二个对象。

  从以上叙述再推演下去,我们可以获得以下结论:①一个对象引用可以指向0个或1个对象;②一个对象可以有N个引用指向它。

  7.参考资料

  ⑴阎宏,Java与模式,电子工业出版社,2006

  ⑵yqj2065,句柄、引用与对象,http://blog.csdn.net/yqj2065

  ⑶Java对象及其引用,http://java.chinaitlab.com/base