(Hibernate)cascade

在我前面的笔记中已经写过关联关系的使用,但主要是演示,在这篇中,我将再细分析!
利用关联关系操作对象:
数据对象之间的关联关系有一对一,一对多及多对多三种。在数据库操作中,数据对象之间的关联关系使用JDBC处理很困难。例如,当删除一个班级的信息时,还要删除该班级的所有学生的基本信息。如果直接使用JDBC执行这种级联操作,会非常繁锁。Hibernate通过把实体对象之间的关联关系及级联关系在映射文件中声明,比较简单地解决了这类级联操作问题。
一对一关联关系的使用:
一对一关联关系在实际生活中是比较觉的,例如学生与学生证的关系,通过学生证可以找到学生。一对一关联关系在Hibernate中的实现有两种方式,分别是主键关联和外键关联。
主键关联:
主键关联的重点是,关联两个实体共享一个主键值。例如student与card是一对一关系,它们在数据库中对应的表分别是t_student和t_card。它们共用一个主键值ID,这个主键可由t_student或t_card表生成。问题是如何让另一张表引用已经生成的主键值呢?例如,t_student表未老先衰了ID的值,t_card表如何引用它?这需要在Hibernate的映射文件中使用主键的foreign生成机制!

为了表示Student与Card之间的一对一的关联关系,我们需要在它们各自的映射文件 中都要使用标记!
一对一关系我在前面已经写过例子程序了,在这里仅给出两个映射文件。如下:
学生PO映射信息:

xml version="1.0" encoding="GBK"?>
DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<hibernate-mapping>
<class name="hibernate.PO.TStudent" table="t_student" lazy="true">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="increment" />
id>
<property name="userName" type="java.lang.String">
<column name="userName" length="20" />
property>
<property name="cardId" type="java.lang.String">
<column name="card_id" length="20" />
property>
<property name="sex" type="java.lang.String">
<column name="sex" length="2" />
property>
<property name="age" type="java.lang.Integer">
<column name="age" />
property>
<one-to-one name="card" class="hibernate.PO.TCard" fetch="join" cascade="all" />
class>
hibernate-mapping>


学生证PO映射信息:

xml version="1.0" encoding="GBK"?>
DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<hibernate-mapping>
<class name="hibernate.PO.TCard" table="t_card" lazy="true">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="foreign">
<param name="property">studentparam>
generator>
id>

<property name="name" type="java.lang.String">
<column name="name" length="20" />
property>


<one-to-one name="student" class="hibernate.PO.TStudent" constrained="true" />

class>
hibernate-mapping>

外键关联:
外键关联的要点是:两个实体各自有不同的主键,但其中一个实体有一个外键引用另一个实体的主键。例如,假设,Student和Card是外键关联的一对一关系们在数据库中相应的表分别如下:t_student表有一个主键ID,t_card表有一个主键ID和一个外键student_id,此外键对应t_student表的主键ID,那么student的映射信息如上面一样不做改动,而Card的映射文件要做相应的改动。如下:
<hibernate-mapping>
<class name="hibernate.PO.TCard" table="t_card" lazy="true">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="increment"/>
id>

<property name="name" type="java.lang.String">
<column name="name" length="20" />
property>

<many-to-one name="student" column="student_id" class="hibernate.PO.TStudent" unique="true"/>



class>
hibernate-mapping>

一对多关联关系的使用
一对多关系很觉,例如班级与学生的关系就是典型的一对多的关系。在实际编写程序时,一对多关系有两种实现方式:单向关联和双向关联。单向的一对多关系只需要在一方进行映射配置,而双向的一对多需要在关联的双方进行映射配置。下面以Group(班级)和Student(学生)为例讲解如何配置一对多的关系。
单向关联:
单向的一对多关系只需要在一方进行映射配置,所以我们只配置Group的映射文件:
<hibernate-mapping>
<class name="hibernate.PO.Group" table="t_group" lazy="true">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="increment"/>
id>

<property name="name" type="java.lang.String" update="true" insert="true">
<column name="name" length="20" />
property>


<set name="students"
table
="t_student"
lazy
="true"
inverse
="false"
cascade
="all"
sort
="unsorted">
<key column="ID"/>
<one-to-many class="hibernate.PO.TStudent"/>
set>
class>
hibernate-mapping>
双向关联:
如果要设置一对多双向关联关系,那么还需要在“多”方的映射文件中使用标记。例如,在Group与Student一对多的双向关联中,除了Group的映射文件外还需要在Student的映射文件中加入如下代码:
<many-to-one name="group"
class
="Group"
cascade
="none"
outer-join
="auto"
update
="true"
insert
="true"
column
="ID" />

inert和update设定是否对column属性指定的关联字段进行insert和update操作。
此外将Group.hbm.xml中元素的inverse设置为true.

多对多关联关系的使用
Student(学生)和Course(课程)的关系就是多对多关系。在映射多对多关系时需要另外使用一个连接表(如Student_Course)。Student_Course表包含二个字段:courseID和studentID。此处它们的映射文件中使用标记,在Student的映射文件中加入以下描述信息:

<set name="courses"
table
="student_course"
lazy
="false"
inverse
="false"
cascade
="save-update">
<key column="studentID" />
<many-to-many class="Course" column="CourseID"/>
set>
相应的Course的映射文件中加入以下:
<set name="students"
table
="student_course"
lazy
="false"
inverse
="true"
cascade
="save-update">
<key column="CourseID" />
<many-to-many class="Student" column="StudentID"/>
set>
添加关联关系:
首先编写一个程序来看看一个名为Bill的学生选择了什么课程:
//获取代表Bill的Student对象
Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
List list
= new ArrayList(stu.getCourses());
for(int i = 0 ; i < list.size(); i++)
{
Course course
= (Course)list.get(i);//取得Course对象
System.out.println(course.getName());//打印出Bill所选课程的清单
}
现在Bill还想chemistry课程,这对于程序员来说只是为Bill添加一个到chemistry的关联,也就是说在student_course表中新增加一条记录,而T_student和T_Course表都不用变更。
//获取代表Bill的Student对象
Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
Course course
= (Course)session.createQuery("from Course c where c.name='chemistry'").uniqueResult();
//设置stu与course的关联关系
stu.getCourses().add(course);
course.getStudents().add(stu);
删除关联关系:
删除关联关系比较简单,直接调用对象集合的remove()方法删除不要的对象就可。例如:要从学生Bill的选课清单中删除politics和chemistry两门课,程序代码如下:
//获取代表Bill的Student对象
Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
Course course1
= (Course)session.createQuery("from Course c where c.name='politics'").uniqueResult();
Course course2
= (Course)session.createQuery("from Course c where c.name='chemistry'").uniqueResult();
stu.getCourse().remove(course1);
//删除politics课程
stu.getCourse().remove(course2);//删除chemistry课程
运行以上程序将从student_course表中删除这两条记录,但T_student和T_course表没有任何变化

完整的错误:

javax.servlet.ServletException: Couldn't create type for property expList on class cn.gov.bjp.ceping.xfire.model.User: Cannot create mapping for java.util.List, unspecified component type for interface java.util.List org.codehaus.xfire.transport.http.XFireServletController.doService(XFireServletController.java:142) org.codehaus.xfire.spring.remoting.XFireServletControllerAdapter.handleRequest(XFireServletControllerAdapter.java:67) org.codehaus.xfire.spring.remoting.XFireExporter.handleRequest(XFireExporter.java:48) org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:723) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:663) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:394) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:348) javax.servlet.http.HttpServlet.service(HttpServlet.java:690) javax.servlet.http.HttpServlet.service(HttpServlet.java:803) com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118) com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)

在论坛上有人这么写:

如果是jdk1.5的话 直接public ArrayList custom(String custom) 就不用配置aegis.xml

客户端:
MyTestServiceClient client = new MyTestServiceClient();

//create a default service endpoint
MyTestServicePortType myTestServicePortType = client
.getMyTestServiceHttpPort();

ArrayOfUserBean array = myTestServicePortType.custom( " ");
ArrayList al = (ArrayList )array.getUserBean();//注意强制转换


所以利用了jdk1.5特性,只是在Dojo中list所定义的get方法返回值写成:List《Object>,就解决了错误


XFire 最新生火指南(上):http://wiki.springside.org.cn/display/springside/XFire

Windows系统的Svchost.exe和Explorer.exe是非常重要的两种进程,上次我们介绍了Explorer.exe进程的应用技巧,今天我们介绍Svchost.exe进程的特点以及在各个操作系统中的应用。 

Svchost.exe是NT核心系统的非常重要的进程,对于2000、XP来说,不可或缺。很多病毒、木马也会调用它。所以,深入了解这个程序,是玩电脑的必修课之一。

大家对Windows操作系统一定不陌生,但你是否注意到系统中“Svchost.exe”这个文件呢?细心的朋友会发现Windows中存在多个 “Svchost”进程(通过“ctrl+alt+del”键打开任务管理器,这里的“进程”标签中就可看到了),为什么会这样呢?下面就来揭开它神秘的 面纱。

在基于NT内核的Windows操作系统家族中,不同版本的Windows系统,存在不同数量的“Svchost”进程,用户使用“任务管理器”可 查看其进程数目。一般来说,Win 2000有两个Svchost进程,Win XP中则有四个或四个以上的Svchost进程(以后看到系统中有多个这种进程,千万别立即判定系统有病毒了哟),而Win 2003 server中则更多。这些Svchost进程提供很多系统服务,如:rpcss服务(remote procedure call)、dmserver服务(logical disk manager)、dhcp服务(dhcp clieNT)等。〕

查看Svchost中的多个服务

如果要了解每个Svchost进程到底提供了多少系统服务,可以在Win 2000的命令提示符窗口中输入“tlist -s”命令来查看,该命令是Win 2000 support tools提供的。在Win XP则使用“tasklist /svc”命令。

Windows系统进程分为独立进程和共享进程两种,“Svchost.exe”文件存在于“%systemroot% system32”目录下,它属于共享进程。随着Windows系统服务不断增多,为了节省系统资源,微软把很多服务做成共享方式,交由 Svchost.exe进程来启动。

但Svchost进程只作为服务宿主,并不能实现任何服务功能,即它只能提供条件让其他服务在这里被启动,而它自己却不能给用户提供任何服务。那这些服务是如何实现的呢?

原来这些系统服务是以动态链接库(dll)形式实现的,它们把可执行程序指向 Svchost,由Svchost调用相应服务的动态链接库来启动服务。那Svchost又怎么知道某个系统服务该调用哪个动态链接库呢?这是通过系统服务在注册表中设置的参数来实现。

从启动参数中可见服务是靠Svchost来启动的。

查看Svchost中是否有病毒进程

因为Svchost进程启动各种服务,所以病毒、木马也想尽办法来利用它,企图利用它的特性来迷惑用户,达到感染、入侵、破坏的目的。但Windows系统存在多个Svchost进程是很正常的,在受感染的机器中到底哪个是病毒进程呢?这里仅举一例来说明。

假设Windows XP系统被病毒感染了。正常的Svchost文件存在于“c:Windowssystem32”目录下,如果发现该文件出现在其他目录下就要小心了。病毒 存在于“c:Windowssystem32Wins”目录中,因此使用进程管理器查看Svchost进程的执行文件路径就很容易发现系统是否感染了病 毒。

Windows系统自带的任务管理器不能够查看进程的路径,可以使用第三方进程管理软件,通过这些工具就可很容易地查看到所有的Svchost进程的执行文件路径,一旦发现其执行路径为不平常的位置就应该马上进行检测和处理。

1、在一个位置上建立一个存放日志和监控程序的目录,比如我在C盘下建立一个RDP的目录

2、在其目录下建立一个名为RDPlog.txt的文本文件

3、在其目录下建立一个名为RDPlog.bat的批处理文件,内容为:
date /t >>RDPlog.txt
time /t >>RDPlog.txt
netstat -n -p tcp | find ":3389">>RDPlog.txt
start Explorer

4、进入系统管理工具中的“终端服务器配置”,进入到默认RDP-Tcp属性中

5、切换到“环境”页下,启用“用户登录时启用下列程序”

6、在程序路径和文件名处填写:C:\RDP\rdplog.bat;并在起始于填写:C:\RDP\

完成以上的配置步骤后,当再次登录服务器时就会记录当前登录者的时间和IP。

DOS命令 At

作用:

列出在指定的时间和日期在计算机上运行的已计划命令或计划命令和程序。首先要保证“计划”服务已启动才能使用 at 命令。

格式:

at [\\IP] [[ID] [/delete] /delete [/yes]]

at [\\computername] time [/interactive] [/every:date[,...] /next:date[,...]] command

使用说明:

(1)如果在没有参数的情况下使用,则 at 列出已计划的命令。

(2)\\IP:指定远程计算机,在此输入远程计划机的IP地址。如果省略该参数,命令将安排在本地计算机。

(3)ID:指定指派给已计划命令的识别码。

(4)/delete:取消已计划的命令。如果省略了ID,计算机中已计划的命令将被全部取消。

/yes:当删除已计划的事件时,对系统的查询强制进行肯定的回答。

(5)/time:指定运行命令的时间。将时间以 24 小时标记(00:00 [午夜] 到 23:59)的方式表示为小时:分钟。

(6)/interactive:允许作业与在作业运行时登录用户的桌面进行交互。

(7)/every:date[,...]:在每个星期或月的指定日期(例如,每个星期四, 或每月的第三天)运行命令。将 date 指定为星期的一天或多天 (M,T,W,Th,F,S,Su),或月的一天或多天(使用 1 到 31 的数字)。用逗号分隔多个日期项。如果省略了 date,将假定为该月的当前日期。

(8)/next:date[,...]:在重复出现下一天(例如,下个星期四)时,运行指 定命令将 date 指定为星期的一天或多天 (M,T,W,Th,F,S,Su),或月的一天或多天(使用 1 到 31 的数字)。用逗号分隔多个日期项。如果省略了 date,将假定为该月的当前日期。

(9)command:指定要运行的 Windows 2000 命令、程序(.exe 或 .com 文件)或批处理程序(.bat 或 .cmd 文件)。当命令需要路径作为参数时,请使用绝对路径,也就是从驱动器号开始的整个路径。如果命令在远程计算机上,请指定服务器和共享名的 UNC 符号,而不是远程驱动器号。如果命令不是可执行 (.exe) 文件,必须在命令前加上 cmd /c,例如: cmd /c dir > c:\test.out

实例:

(1)列出本机已有的计划命令。

C:\>at

由于本机没有计划命令,所在显示为“清单是空的”。

(2)查看IP地址为192.168.1.13的计算机计划服务列表。

C:\>at \\192.168.1.13

运行后可以看到在IP地址为192.168.1.13计算机中有一项计划服务,这项计划服务要执行的日期、时间以及程序。

(3)取消IP地址为192.168.1.13的计算机计划服务。

(4)指定d:\muma.exe程序在IP为192.168.1.13的远程计算机上,于20:50运行。

Linux的nohup命令

昨晚在DreamHost的shell里wget了一个文件,想传到我的ftp上,却又急着回家吃饭。用ftp命令put上去,一断开连接,传输就停止了。觉得Windows都有at命令,Linux应该有定时执行的功能吧。上网查了一番,找到这篇活用Linux的后台任务,原来只要在命令后面加上&符号就可以让任务在后台运行了。不过,这只是让任务在后台执行,断开连接一样会被结束掉。又找到这篇《用nohup命令让Linux下程序永远在后台执行》,介绍了nohup命令和ncftpput程序。于是用了这么一条命令:

nohup ncftpput -u yskin -p *** ftp.server.com /wwwroot 123.zip&

执行后,用jobs命令查看到他正在运行,然后用exit命令退出shell,ftp到我的ftp服务器上,发现文件大小在不停地增加。今天早上上网,发现文件已经传完了。自己睡觉让机器干活,真爽!

好像jobs命令只能显示当前连接中的job,退出后再telnet进去就显示不出来了。另外有一个小发现,ftp服务器上的文件时间被设置过了,看来ncftpput程序会自动设置上传文件的时间呀,我用过的ftp客户端好像都没有这样的功能,以后有空要查一查。

Update:今天特别有兴趣研究这个问题:怎样在ftp 里修改FTP服务器上远程文件时间。ncftpput的帮助里有一条"-y Try using 'SITE UTIME' to preserve timestamps on remote host."好像是利用"SITE UTIME"命令来修改远程文件时间的。在网上查到说:Not many remote FTP servers support this, so it may not work.试了一下,我的两个FTP服务器都不支持这条命令,晕倒,Serv-U都不支持。无奈,去ncftp官网把NcFTP Client的源代码下了下来,直接用WinRAR搜索"UTIME",找到c_utime.c文件,里面写的很清楚了,先尝试用"SITE UTIME"命令修改,不行再用MDTM命令修改。试了一下,用ftp命令登陆,敲入quote MDTM 20060101000000 filename,修改成功,bingo.

另外,我还查到PHP里可以用touch()touch()函数修改文件的最后修改时间,和Linux里的touch命令名字一样,hoho

Update2:好像我的FTP服务器上的Serv-U FTP Server v6.0和yskin.net上的vsFTPd 2.0.3都支持MDTM命令,而DreamHost的ProFTPD 1.3.0rc2 Server不支持MDTM命令。So,只能telnet上去,用touch命令改咯。

Update3:Kirin Lin大大推荐使用Linux的screen程序。去Google找了一圈,找到《使用 Screen 看管不适合“无人看管”的终端软件》和《Unix/Linux 工具: Screen 命令使用》。 这个工具就相当于在shell里再运行一个shell,就像登陆shell,然后输入bash命令,或者Win+R->cmd进Windows命令 行提示符后再输入cmd回车一样。只不过,这个新的shell可以随时暂停,而且登出shell后它还在运行,下次还能再登陆进去。

命令很简单,screen -S test即可建立一个叫test的screen,可以在这个screen里运行程序,假设我运行python:

[burns]$ python
Python 2.5 (r25:51908, Nov 23 2006, 19:51:08)
[GCC 3.3.5 (Debian 1:3.3.5-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

好吧,我承认我是在炫耀刚在DreamHost上安装的Python 2.5,具体安装过程在这里有详细描述。

这时,按下Ctrl+a,再按下d键,这是显示"[detached]",表示断开了这个screen。然后,我们用screen -ls命令查看一下

[burns]$ screen -ls
There is a screen on:
1906.test (Detached) 1 Socket in /var/run/screen/S-yskin.

显示有一个已经断开连接的screen。输入exit,退出shell,然后再telnet进去。键入screen -ls命令,可以发现我可爱的叫test的screen仍然乖乖的躺在那儿。只要DreamHost主机不重启,这个screen应该一直存在吧。输入screen -r test可以重新连接上这个screen(因为我给了它个名字叫test,否则就必须记住1906这个号码咯),我的python还在。按下Ctrl+D退出python,再输入exit就可以退出这个screen,屏幕上会显示"[screen is terminating]"。唔,terminating,这个词好耳熟啊,昨天看《终结者Ⅲ》时好像听过。

Windows命令行提示符和Linux的bash可以进很多层,不过退出时要输入一层一层输入exit退出。呃,试着在一个screen里再开一 个screen,按Ctrl+A->D退出,会直接退出第一层screen。用screen -ls命令查看,可以看到第一层已经断开了,第二层还连着。不知道如果开好多层,然后用-D命令强制停止中间的某一层有什么结果,嘿嘿。

才学了几天Linux,发现Linux真好玩,比DOS好玩多了。

Update3:用nohup命令,可以直接在后台运行命 令。如果用screen,在一个screen里的时候,即使telnet断线,在登陆上去,切换进screen,还能进入断线前的页面。不过,如果用 ncftpput命令,那么命令执行完之后,screen并不会关闭。DOS下有个&符号,可以相继运行几个命令。(Windows应该是 &,纯DOS下应该是Ctrl+T吧)在Linux试了一下,&符号好像表示的是同时运行多个命令,以多线程的方式运行。所以, ncftpput还在运行,这边screen已经退出了,screen打开的bash进程也停了。不过这个ncftpput还能继续运行下去,直到上传完 文件才自行关闭,好玩的很。而|和<还有>是管道符号。刚才因为输错了命令,偶然间发现一个符号:分号;。分号间隔的命令可以相继运行。在 screen里输入ncftpput ... ;exit,等ncftpput上传完文件,这个screen就自动关闭了,hoho

还学了两个命令:ps -e查看进程,kill -9 +进程号强行关闭进程。

在javascript中定义变量用
var a;

定义函数用这种格式:
function method(){}

但是不能体现出java的类的特点,也就是没有有效的把这些变量函数组织到一起,不便于管理。

看了ajax in action 那本书中所写的,受了点启发。
我们可以先定义一个object,再在object之下定义变量和函数,使之成为一个整体。
例:
var checkExp=new Object();
定义变量:
checkExp.SAVING_='保存中...';
定义函数:
checkExp.getXmlHttpRequestObject=function() {}

调用时:
checkExp.getXmlHttpRequestObject();

scp

使用 scp 在远程机器上 copy 档案
例如:
copy 本地的档案到远程的机器上
scp /etc/lilo.conf k@net67.ee.oit.edu.tw:/home/k
会将本地的 /etc/lilo.conf 这个档案 copy 到 net67.ee.oit.edu.tw,使用者 k 的家目录下。
copy远程机器上的档案到本地来
scp k@net67.ee.oit.edu.tw:/etc/lilo.conf /etc
会将 net67.ee.oitdu.tw 中 /etc/lilo.conf 档案 copy 到本地的 /etc 目录下。
保持从来源 host 档案的属性
scp –p k@net67.ee.tw:/etc/lilo.conf /etc
在此必须注意使用者的权限是否可读取远程上的档案,若想知道更多关于 scp 的使用方法,可去看看 scp 的使用手册。
ssh-keygen
产生公开钥 (pulib key) 和私人钥 (private key),以保障 ssh 联机的安性, 当 ssh 连 shd 服务器,会交换公开钥上,系统会检查 /etc/ssh_know_hosts 内储存的 key,如果找到客户端就用这个 key 产生一个随机产生的session key 传给服务器,两端都用这个 key 来继续完成 ssh 剩下来的阶段。

它会产生 identity.pub、identity 两个档案,私人钥存放于identity,公开钥 存放于 identity.pub 中,接下来使用 scp 将 identity.pub copy 到远程机器的家目录下.ssh下的authorized_keys。 .ssh/authorized_keys(这个 authorized_keys 档案相当于协议的 rhosts 档案), 之后使用者能够不用密码去登入。RSA的认证绝对是比 rhosts 认证更来的安全可靠。
执行:
scp identity.pub k@linux1.ee.oit.edu.tw:.ssh/authorized_keys

若在使用 ssh-keygen 产生钥匙对时没有输入密码,则如上所示不需输入密码即可从 net67.ee.oit.edu.tw 去登入 linux1.ee.oit.edu.tw。在此,这里输入的密码可以跟帐号的密码不同,也可以不输入密码。

java hello world

-------------
java环境设置
-------------

在环境变量中设置以下三个变量:
JAVA_HOME=C:\j2sdk1.4.1 //可以改为相应的目录
CLASSPATH=%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar
PATH=%JAVA_HOME%\bin;%PATH%

然后在命令行输入java -version命令,如果出现
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
则说明已经配置成功!

HelloWorld.java源程序如下:
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

在命令行执行javac HelloWorld.java
如果没有输出任何信息则说明编译成功。

在命令行运行java HelloWorld,输出:
Hello World!
代表成功执行了java程序。

-----------------
初学者常犯的错误
-----------------

1. 运行时,带了.class后缀
如果你试图使用如下命令:
E:\java\src>java HelloWorld.class
系统会误认为你运行的是HelloWorld包下的名为class的类文件,会到系统的CLASSPATH下(一般都包括当前目录)企图寻找 HelloWorld.class.class这样的类,这样的类当然不存在了;并且也不可能存在,因为class是关键字,不能作为一个类的名字。所以会报如下错误信息:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/class

2. 文件名大小写错误
对于像Windows这样的系统,编译时可以不关心大小写。比如编译HelloWorld.java时,也可以使用:
E:\java\src>javac helloworld.java
也可以编译通过,但产生的类文件仍然是和源文件相符的:HelloWorld.class。
但在运行时一定要注意大小写,比如试图使用如下命令运行:
E:\java\src>java helloworld
将报类似于1中的错误:
Exception in thread "main" java.lang.NoClassDefFoundError: helloworld (wrong name: HelloWorld)


----------------------------
包含包层次的HelloWorld.java
----------------------------

比如上面的HelloWorld.java修改如下:
package org.javaresearch;
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

编译时有两种方法

1. 直接编译
E:\java\src>javac HelloWorld.java
此时在当前目录下输出HelloWorld.class。此时,运行不能使用上面相同的方法,使用:
E:\java\src>java HelloWorld
运行时,出现如下错误:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld (wrong name: org/javaresearch/HelloWorld)
从上述错误信息你也可以看到,系统可以找到HelloWorld类(因为当前路径包含在CLASSPATH中,具体为什么会提示wrong name,有兴趣的朋友参见Java语言规范),但这个类属于org.javaresearch包。所以,你要做的就是按照上述包层次,相应的创建目录层次,把上面生成的HelloWorld.class放到E:\java\src\org\javaresearch\目录下。运行:
E:\java\src >java org.javaresearch.HelloWorld
系统打印出:
Hello World!
这儿要注意的是,不能使用java org\javaresearch\HelloWorld来运行,此时同样会出现如下错误:
Exception in thread "main" java.lang.NoClassDefFoundError:org\javaresearch\HelloWorld (wrong name: org/javaresearch/HelloWorld)

2. 使用 -d 编译选项
是不是觉得上面的编译方法有点麻烦,能不能自动在当前路径(或任意指定的路径)下生成包层次呢?有!使用-d 编译选项就能做到。
E:\java\src >javac -d . HelloWorld.java
此时,在当前目录下就生成了一个org\javaresearch目录,并且输出的.class文件也在里面。运行:
E:\java\src >java org.javaresearch.HelloWorld
系统打印:Hello World!
如果你想把生成的类文件集中存放在一个目录中,比如:E:\java\classes下,那么你首先创建这个目录,然后编译时:
E:\java\src >javac -d E:\java\classes HelloWorld.java
就可以把生成的类文件放到E:\java\classes目录下,并且按照包层次相应的创建目录路径。你可以在E:\java\classes\org\ javaresearch下找到HelloWorld.class文件。此时使用如下命令可以正确运行(注意如果要用到其它类,请在CLASSPATH中设好):
E:\java\classes >java org.javaresearch.HelloWorld

或者你可以在E:\java目录下面运行以下命令来执行
E:\java >java -classpath .\classes org.javaresearch.HelloWorld
使用java的-classpath参数可以将一些目录加入类路径

-------------------
打包jar文件
-------------------
可以把一个包内的所有class文件打包为一个jar文件,便于存放和运行。以上文的org.javaresearch包为例,其打包命令如下:
E:\java\classes >jar cvf wxb.jar org
会生成一个wxb.jar文件,将其中META-INF\MANIFEST.MF文件中添加如下一行:
Main-Class: org.javaresearch.HelloWorld
保存jar文件。

或者首先创建并编辑一个MANIFEST.MF文件,其内容如下:
Manifest-Version: 1.0
Created-By: 1.4.1 (Sun Microsystems Inc.)
Main-Class: org.javaresearch.HelloWorld
将其保存到classes目录中
然后将其一起打包到jar文件中,打包命令如下:
E:\java\classes >jar cvfm wxb.jar MANIFEST.MF org

-------------
运行jar文件
-------------
在命令行中输入如下命令即可:
E:\java\classes >java -jar wxb.jar
输出为:
Hello World!

------------------------
用Ant来编译运行java程序
------------------------
首先安装Ant,步骤很简单:
1.将Ant压缩包解压到一个目录,例如D:\Ant1.5.2;
2.在环境变量中添加以下变量:
ANT_HOME=D:\Ant1.5.2 //可以改为相应的目录
3.修改Path环境变量
PATH=%ANT_HOME%\bin;%PATH%

最后给出了一个Ant的build.xml文件,运行ant即可完成所有以上的编译和运行过程,其build文件如下:


building HelloWorld!




















































java hello world

-------------
java环境设置
-------------

在环境变量中设置以下三个变量:
JAVA_HOME=C:\j2sdk1.4.1 //可以改为相应的目录
CLASSPATH=%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar
PATH=%JAVA_HOME%\bin;%PATH%

然后在命令行输入java -version命令,如果出现
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
则说明已经配置成功!

HelloWorld.java源程序如下:
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

在命令行执行javac HelloWorld.java
如果没有输出任何信息则说明编译成功。

在命令行运行java HelloWorld,输出:
Hello World!
代表成功执行了java程序。

-----------------
初学者常犯的错误
-----------------

1. 运行时,带了.class后缀
如果你试图使用如下命令:
E:\java\src>java HelloWorld.class
系统会误认为你运行的是HelloWorld包下的名为class的类文件,会到系统的CLASSPATH下(一般都包括当前目录)企图寻找 HelloWorld.class.class这样的类,这样的类当然不存在了;并且也不可能存在,因为class是关键字,不能作为一个类的名字。所以会报如下错误信息:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/class

2. 文件名大小写错误
对于像Windows这样的系统,编译时可以不关心大小写。比如编译HelloWorld.java时,也可以使用:
E:\java\src>javac helloworld.java
也可以编译通过,但产生的类文件仍然是和源文件相符的:HelloWorld.class。
但在运行时一定要注意大小写,比如试图使用如下命令运行:
E:\java\src>java helloworld
将报类似于1中的错误:
Exception in thread "main" java.lang.NoClassDefFoundError: helloworld (wrong name: HelloWorld)


----------------------------
包含包层次的HelloWorld.java
----------------------------

比如上面的HelloWorld.java修改如下:
package org.javaresearch;
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

编译时有两种方法

1. 直接编译
E:\java\src>javac HelloWorld.java
此时在当前目录下输出HelloWorld.class。此时,运行不能使用上面相同的方法,使用:
E:\java\src>java HelloWorld
运行时,出现如下错误:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld (wrong name: org/javaresearch/HelloWorld)
从上述错误信息你也可以看到,系统可以找到HelloWorld类(因为当前路径包含在CLASSPATH中,具体为什么会提示wrong name,有兴趣的朋友参见Java语言规范),但这个类属于org.javaresearch包。所以,你要做的就是按照上述包层次,相应的创建目录层次,把上面生成的HelloWorld.class放到E:\java\src\org\javaresearch\目录下。运行:
E:\java\src >java org.javaresearch.HelloWorld
系统打印出:
Hello World!
这儿要注意的是,不能使用java org\javaresearch\HelloWorld来运行,此时同样会出现如下错误:
Exception in thread "main" java.lang.NoClassDefFoundError:org\javaresearch\HelloWorld (wrong name: org/javaresearch/HelloWorld)

2. 使用 -d 编译选项
是不是觉得上面的编译方法有点麻烦,能不能自动在当前路径(或任意指定的路径)下生成包层次呢?有!使用-d 编译选项就能做到。
E:\java\src >javac -d . HelloWorld.java
此时,在当前目录下就生成了一个org\javaresearch目录,并且输出的.class文件也在里面。运行:
E:\java\src >java org.javaresearch.HelloWorld
系统打印:Hello World!
如果你想把生成的类文件集中存放在一个目录中,比如:E:\java\classes下,那么你首先创建这个目录,然后编译时:
E:\java\src >javac -d E:\java\classes HelloWorld.java
就可以把生成的类文件放到E:\java\classes目录下,并且按照包层次相应的创建目录路径。你可以在E:\java\classes\org\ javaresearch下找到HelloWorld.class文件。此时使用如下命令可以正确运行(注意如果要用到其它类,请在CLASSPATH中设好):
E:\java\classes >java org.javaresearch.HelloWorld

或者你可以在E:\java目录下面运行以下命令来执行
E:\java >java -classpath .\classes org.javaresearch.HelloWorld
使用java的-classpath参数可以将一些目录加入类路径

-------------------
打包jar文件
-------------------
可以把一个包内的所有class文件打包为一个jar文件,便于存放和运行。以上文的org.javaresearch包为例,其打包命令如下:
E:\java\classes >jar cvf wxb.jar org
会生成一个wxb.jar文件,将其中META-INF\MANIFEST.MF文件中添加如下一行:
Main-Class: org.javaresearch.HelloWorld
保存jar文件。

或者首先创建并编辑一个MANIFEST.MF文件,其内容如下:
Manifest-Version: 1.0
Created-By: 1.4.1 (Sun Microsystems Inc.)
Main-Class: org.javaresearch.HelloWorld
将其保存到classes目录中
然后将其一起打包到jar文件中,打包命令如下:
E:\java\classes >jar cvfm wxb.jar MANIFEST.MF org

-------------
运行jar文件
-------------
在命令行中输入如下命令即可:
E:\java\classes >java -jar wxb.jar
输出为:
Hello World!

------------------------
用Ant来编译运行java程序
------------------------
首先安装Ant,步骤很简单:
1.将Ant压缩包解压到一个目录,例如D:\Ant1.5.2;
2.在环境变量中添加以下变量:
ANT_HOME=D:\Ant1.5.2 //可以改为相应的目录
3.修改Path环境变量
PATH=%ANT_HOME%\bin;%PATH%

最后给出了一个Ant的build.xml文件,运行ant即可完成所有以上的编译和运行过程,其build文件如下:


building HelloWorld!



















description="generate the distribution" >

















fork="true"
failonerror="true"
maxmemory="128m"
>








description="clean up" >




一. 终止进程的工具 kill 、killall、pkill、xkill

终止一个进程或终止一个正在运行的程序,一般是通过 kill 、killall、pkill、xkill 等进行。比如一个程序已经死掉,但又不能退出,这时就应该考虑应用这些工具。

另外应用的场合就是在服务器管理中,在不涉及数据库服务器程序的父进程的停止运行,也可以用这些工具来终止。为什么数据库服务器的父进程不 能用这些工具杀死呢?原因很简单,这些工具在强行终止数据库服务器时,会让数据库产生更多的文件碎片,当碎片达到一定程度的时候,数据库就有崩溃的危险。 比如mysql服务器最好是按其正常的程序关闭,而不是用pkill mysqld 或killall mysqld 这样危险的动作;当然对于占用资源过多的数据库子进程,我们应该用kill 来杀掉。

1. kill

kill的应用是和 或pgrep 命令结合在一起使用的;

kill 的用法:

kill [信号代码] 进程ID

注:信号代码可以省略;我们常用的信号代码是 -9 ,表示强制终止;

举例:

[root@localhost ~]# auxf |grep httpd

root 4939 0.0 0.0 5160 708 pts/3 S 13:10 0:00 \_ grep httpd

root 4830 0.1 1.3 24232 10272 ? 13:02 0:00 /usr/ in/httpd

apache 4833 0.0 0.6 24364 4932 ? S 13:02 0:00 \_ /usr/ in/httpd

apache 4834 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/ in/httpd

apache 4835 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/ in/httpd

此文来自电脑故障 网


apache 4836 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/ in/httpd

apache 4840 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/ in/httpd
我们查看httpd 服务器的进程;您也可以用pgrep -l httpd 来查看;


我们看上面例子中的第二列,就是进程PID的列,其中4830是httpd服务器的父进程,从4833-4840的进程都是它4830的子进程;如果我们杀掉父进程4830的话,其下的子进程也会跟着死掉;

[root@localhost ~]# kill 4840 注:杀掉4840这个进程;

[root@localhost ~]# -auxf |grep httpd 注:查看一下会有什么结果?是不是httpd服务器仍在运行?

[root@localhost ~]# kill 4830 注:杀掉httpd的父进程;

[root@localhost ~]# -aux |grep httpd 注:查看httpd的其它子进程是否存在,httpd服务器是否仍在运行?


对于僵尸进程,可以用kill -9 来强制终止退出;


比如一个程序已经彻底死掉,如果kill 不加信号强度是没有办法退出,最好的办法就是加信号强度 -9 ,后面要接杀父进程;比如;

[root@localhost ~]# aux |grep gaim

beinan 5031 9.0 2.3 104996 17484 ? S 13:23 0:01 gaim

root 5036 0.0 0.0 5160 724 pts/3 S 13:24 0:00 grep gaim

或 [root@localhost ~]# pgrep -l gaim

5031 gaim

[root@localhost ~]# kill -9 5031

 
Copyright 2005-2007. Hello Wiki designed by Fen, Blogger Templates by Blogcrowds.