關(guān)于RSS
RSS是站點(diǎn)用來(lái)和其他站點(diǎn)之間共享內(nèi)容的一種簡(jiǎn)易方式(也叫聚合內(nèi)容)
在門戶網(wǎng)站大行其道,人們已經(jīng)習(xí)慣通過(guò)搜索引擎來(lái)獲取新聞資訊的今天,一種全新的資訊傳播方式已經(jīng)悄悄地來(lái)到我們身邊,仔細(xì)觀察一些網(wǎng)站,你可能注意到一些被標(biāo)記為"XML"或"RSS"的橙色圖標(biāo)。
面對(duì)撲面而來(lái)的新聞,不用再花費(fèi)大量的時(shí)間沖浪和從新聞網(wǎng)站下載,只要通過(guò)下載或購(gòu)買一種小程序,這種技術(shù)被稱為簡(jiǎn)易信息聚合(RSS:Really Simple Syndication)。RSS會(huì)收集和組織定制的新聞,按照你希望的格式、地點(diǎn)、時(shí)間和方式,直接傳送到你的計(jì)算機(jī)上。新聞網(wǎng)站和那些在線日記作者已體會(huì)到了RSS提要帶來(lái)的樂(lè)趣,這也使讀者可以更容易跟蹤RSS提要
RSS是一個(gè)縮寫的英文術(shù)語(yǔ),在英文中被認(rèn)為有幾個(gè)不同的源頭,并被不同的技術(shù)團(tuán)體做不同的解釋。它既可以是"Rich Site Summary"(豐富站點(diǎn)摘要),或"RDF Site Summary"(RDF站點(diǎn)摘要),也可以是"Really Simple Syndication"(真正簡(jiǎn)易聚合)。現(xiàn)在已有的有Netscape, 1.0 (RSS-DEV版本),和 0.9x and 2.0 (UserLand Software版本) 0.9x和2.0。不過(guò)幾乎所有能支持RSS的程序都可以瀏覽不同版本的RSS。
RSS是基于文本的格式。它是XML(可擴(kuò)展標(biāo)識(shí)語(yǔ)言)的一種形式。通常RSS文件都是標(biāo)為XML,RSS files(通常也被稱為RSS feeds或者channels)通常只包含簡(jiǎn)單的項(xiàng)目列表。一般而言,每一個(gè)項(xiàng)目都含有一個(gè)標(biāo)題,一段簡(jiǎn)單的介紹,還有一個(gè)URL鏈接(比如是一個(gè)網(wǎng)頁(yè)的地址)。其他的信息,例如日期,創(chuàng)建者的名字等等,都是可以選擇的。
RSS是站點(diǎn)用來(lái)和其他站點(diǎn)之間共享內(nèi)容的一種簡(jiǎn)易方式(也叫聚合內(nèi)容),通常被用于新聞和其他按順序排列的網(wǎng)站,例如Blog。一段項(xiàng)目的介紹可能包含新聞的全部介紹,Blog post等等。或者僅僅是額外的內(nèi)容或者簡(jiǎn)短的介紹。這些項(xiàng)目的鏈接通常都能鏈接到全部的內(nèi)容。網(wǎng)絡(luò)用戶可以在客戶端借助于支持RSS的新聞聚合工具軟件(例如NewzCrawler、FeedDemon),在不打開(kāi)網(wǎng)站內(nèi)容頁(yè)面的情況下閱讀支持RSS輸出的網(wǎng)站內(nèi)容。網(wǎng)站提供RSS輸出,有利于讓用戶發(fā)現(xiàn)網(wǎng)站內(nèi)容的更新。
RSS如何工作?首先您一般需要下載和安裝一個(gè)RSS閱讀器,然后從網(wǎng)站提供的聚合新聞目錄列表中訂閱您感興趣的新聞欄目的內(nèi)容。訂閱后,您將會(huì)及時(shí)獲得所訂閱新聞?lì)l道的最新內(nèi)容。 對(duì)于一般用戶來(lái)說(shuō),用RSS訂閱新聞可以像使用Outlook Express收取訂閱的郵件一樣簡(jiǎn)單;而對(duì)于Web應(yīng)用程序的開(kāi)發(fā)者而言,RSS的工作過(guò)程也不是那么復(fù)雜,至少比大多數(shù)其他常見(jiàn)的Web技術(shù)都更容易被理解和被實(shí)現(xiàn)。 有人認(rèn)為,RSS的初衷似乎是為了給郵件列表訂閱服務(wù)以致命的打擊,若從RSS的應(yīng)用方式來(lái)看,這幾乎是不可避免的。但從實(shí)際效果來(lái)看,RSS最火爆的應(yīng)用并非是商業(yè)信息的集中訂閱,而是個(gè)人通過(guò)Web實(shí)現(xiàn)的信息聚合,一個(gè)典型的例子就是各國(guó)的網(wǎng)志作者(Blogger)首先成為最普遍的RSS應(yīng)用人群。
create database hy
on primary --默認(rèn)就屬于primary主文件組
(
--主數(shù)據(jù)文件的具體描述
name='hy_data', --主數(shù)據(jù)文件的邏輯名
filename='E:\temp1\hy_data.mdf', --主數(shù)據(jù)文件的物理名
size=3mb,--主數(shù)據(jù)文件的初始大小
maxsize=100mb,--主數(shù)據(jù)文件的增長(zhǎng)最大值
filegrowth=10%--主數(shù)據(jù)文件的增長(zhǎng)率
),(
--次數(shù)據(jù)文件的具體描述,具體參數(shù)含義同主數(shù)據(jù)文件的含義
name='hyn_data',
filename='E:\temp1\hyn_data.ndf',
size=3mb,
maxsize=100mb,
filegrowth=10%
)
log on
(
--日志文件的具體描述,各參數(shù)的含義同主數(shù)據(jù)文件各參數(shù)含義
name='hylog_log1',
filename='E:\temp1\hylog1_log.ldf',
size=1mb,
filegrowth=10%
),(
--次日志文件的具體描述,具體各參數(shù)含義同上
name='hylog_log2',
filename='E:\temp1\hylog2_log.ldf',
size=1mb,
filegrowth=10%
)
use hy
go
create table 忍者派別表 --創(chuàng)建忍者派別表
(
編號(hào) int,--編號(hào)
稱號(hào) Nvarchar(20) not null --稱號(hào)
)
go
create table 師傅表--創(chuàng)建師傅表
(
編號(hào) int,--編號(hào)
姓名 Nvarchar(20) not null,--姓名
稱號(hào) int--稱號(hào)
)
go
create table 忍者信息表--創(chuàng)建忍者信息表
(
編號(hào) int identity(1,1),--編號(hào)
姓名 Nvarchar(20) not null,--姓名
性別 char(2),--性別
攻擊力 int,--攻擊力
派別 int not null,--派別
師傅 int not null--師傅
)
go
--為忍者派別表添加約束
alter table 忍者派別表
add constraint pk_編號(hào) primary key (編號(hào))
go
--為師傅表添加約束
alter table 師傅表
add constraint pk_ 編號(hào) primary key (編號(hào))
稱號(hào) int not null
go
--為忍者信息表添加約束
alter table 忍者信息表
add constraint pk_ 編號(hào) primary key (編號(hào))
add constraint df_性別
default ('男') for 性別
攻擊力 int check(攻擊力>0)
派別 int references 忍者派別表(編號(hào))
師傅 int not null references 師傅表(編號(hào))
go
--為忍者派別表添加數(shù)據(jù)
insert into 忍者派別表(編號(hào),稱號(hào))values(1,'木葉下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(2,'木葉中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(3,'木葉上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(4,'砂隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(5,'砂隱中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(6,'砂隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(7,'雨隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(8,'雨隱中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(9,'雨隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(10,'音隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(11,'音隱中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(12,'音隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(13,'巖隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(14,'巖隱中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(15,'巖隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(16',云隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(17',云隱中忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(18',云隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(19',霧隱下忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(20',霧隱中忍 ')
insert into 忍者派別表(編號(hào),稱號(hào))values(21',霧隱上忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(22',曉')
insert into 忍者派別表(編號(hào),稱號(hào))values(23',逃之忍')
insert into 忍者派別表(編號(hào),稱號(hào))values(24',火影 ')
insert into 忍者派別表(編號(hào),稱號(hào))values(25',風(fēng)影 ')
insert into 忍者派別表(編號(hào),稱號(hào))values(26',雨影')
insert into 忍者派別表(編號(hào),稱號(hào))values(27',音影')
insert into 忍者派別表(編號(hào),稱號(hào))values(28',巖影')
insert into 忍者派別表(編號(hào),稱號(hào))values(29',未知')
insert into 忍者派別表(編號(hào),稱號(hào))values(99',三忍')
go
--為師傅表添加數(shù)據(jù)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(1,'旗木卡卡西',3)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(2,'依魯卡',2)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(3,'自來(lái)也',99)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(4,'夕日紅',3)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(5,'阿斯瑪',3)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(6,'阿凱',3)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(7,'猿飛',24)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(8,'馬基',6)
insert into 師傅表(編號(hào),姓名,稱號(hào))values(9,'未知',29)
go
--為忍者信息表添加約束
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('漩渦鳴人','男',100,1,1)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('日向雛田','男',100,1,5)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('春野櫻','女',60,1,1)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('犬冢牙','男',100,1,4)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('犬冢牙','男',100,1,4)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('山中井野','女',100,1,4 )
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('奈良鹿丸','男',150,2,5)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('宇智波佐助','男',200,1,1)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('秋道丁次','男',100,1,5)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('我愛(ài)羅','男',160,25,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('勘九郎','男',100,4,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('手鞠','女',110,4,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('白','男',120,20,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('桃地再不斬','男',180,23,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('干柿鬼鮫','男',250,22,9)
insert into 忍者信息表(編號(hào),姓名,性別,攻擊力,派別,師傅)values('藥師兜','男',120,11,9)
go
--查詢數(shù)據(jù)
select * from 忍者派別表
select * from 師傅表
select * from 忍者信息表
一、三層體系架構(gòu)
1.表示層(USL):主要表示Web方式,也可以表示成WINFORM方式。如果邏輯層相當(dāng)強(qiáng)大和完善,無(wú)論表現(xiàn)層如何定義和更改,邏輯層都能完善地提供服務(wù)。
2.業(yè)務(wù)邏輯層(BLL):主要是針對(duì)具體的問(wèn)題的操作,也可以理解成對(duì)數(shù)據(jù)層的操作,對(duì)數(shù)據(jù)業(yè)務(wù)邏輯處理。如果說(shuō)數(shù)據(jù)層是積木,那邏輯層就是對(duì)這些積木的搭建。
3.數(shù)據(jù)訪問(wèn)層(DAL):主要是對(duì)原始數(shù)據(jù)(數(shù)據(jù)庫(kù)或者文本文件等存放數(shù)據(jù)的形式)的操作層,而不是指原始數(shù)據(jù),也就是說(shuō),是對(duì)數(shù)據(jù)的操作,而不是數(shù)據(jù)庫(kù),具體為業(yè)務(wù)邏輯層或表示層提供數(shù)據(jù)服務(wù)。

二、具體區(qū)分
1.表示層:主要對(duì)用戶的請(qǐng)求接受,以及數(shù)據(jù)的返回,為客戶端提供應(yīng)用程序的訪問(wèn)。
2.業(yè)務(wù)邏輯層:主要負(fù)責(zé)對(duì)數(shù)據(jù)層的操作,也就是說(shuō)把一些數(shù)據(jù)層的操作進(jìn)行組合。
3.數(shù)據(jù)訪問(wèn)層:主要看你的數(shù)據(jù)層里面有沒(méi)有包含邏輯處理,實(shí)際上他的各個(gè)函數(shù)主要完成各個(gè)對(duì)數(shù)據(jù)文件的操作,而不必管其他操作。
三、總結(jié)
三層結(jié)構(gòu)是一種嚴(yán)格分層方法,即數(shù)據(jù)訪問(wèn)層只能被業(yè)務(wù)邏輯層訪問(wèn),業(yè)務(wù)邏輯層只能被表示層訪問(wèn),用戶通過(guò)表示層將請(qǐng)求傳送給業(yè)務(wù)邏輯層,業(yè)務(wù)邏輯層完成相關(guān)業(yè)務(wù)規(guī)則和邏輯,并通過(guò)數(shù)據(jù)訪問(wèn)層訪問(wèn)數(shù)據(jù)庫(kù)獲得數(shù)據(jù),然后按照相反的順序依次返回將數(shù)據(jù)顯示在表示層。
一、 引言
JMX(
Java管理擴(kuò)展)提供了一組工具用來(lái)管理本地和遠(yuǎn)程應(yīng)用程序、系統(tǒng)對(duì)象、設(shè)備等。本文將解釋如何使用JMX(JSR 160)來(lái)遠(yuǎn)程控制
Web應(yīng)用程序,并將解釋應(yīng)用程序中可用于JMX客戶的代碼,同時(shí)將展示使用如MC4J和jManage等的不同客戶如何連接到支持JMX的應(yīng)用程序。此外,我們還將詳細(xì)地討論使用RMI協(xié)議和JNDI來(lái)保護(hù)通訊層。
首先我們要分析一個(gè)簡(jiǎn)單的web應(yīng)用程序,它監(jiān)控已經(jīng)登陸的用戶數(shù)目并通過(guò)一個(gè)安全的JMX服務(wù)來(lái)顯示該項(xiàng)統(tǒng)計(jì)。我們還將運(yùn)行這個(gè)應(yīng)用程序的多個(gè)實(shí)例并且從所有的運(yùn)行實(shí)例中跟蹤這個(gè)統(tǒng)計(jì)數(shù)字。當(dāng)然,你可以
下載這個(gè)示例web應(yīng)用程序。它需要你安裝
J2SE 5.0 SDK并且你的JAVA_HOME環(huán)境變量指向基安裝目錄。J2SE 5.0實(shí)現(xiàn)了1.2版本的JMX API和JMX 1.0版本的Remote API。同時(shí)還需要一個(gè)支持
Servlet的容器;我使用的是Apache Tomcat 5.5.12。另外,我還使用Apache Ant來(lái)構(gòu)建這一示例應(yīng)用程序。
二、 建立示例應(yīng)用程序
首先,你要下載示例應(yīng)用程序并且使用ant war(更多的細(xì)節(jié)見(jiàn)build.
XML中的注釋)來(lái)創(chuàng)建一個(gè)WAR文件。把jmxapp.war復(fù)制到Tomcat的webapps目錄。假定Tomcat正在運(yùn)行于你的本地機(jī)器的端口8080,那么該應(yīng)用程序的URL將是:
http://localhost:8080/jmxapp
如果你看到一個(gè)提示你輸入名字和口令的登陸屏幕,那么一切已經(jīng)就緒了。
三、 跟蹤一些有意義的數(shù)據(jù)
本文中的應(yīng)用程序使用
Struts框架來(lái)提交登錄表單。一旦提交結(jié)束,即執(zhí)行LoginAction.execute(..)方法-它將簡(jiǎn)單地檢查是否用戶的ID為"hello"以及是否其口令為"world"。如果二者都正確,那么登錄成功并且控制被導(dǎo)向login_success.
JSP;如果不正確,那么我們返回到登錄表單。根據(jù)登錄成功與否決定調(diào)用incrementSuccessLogins(HttpServletRequest)方法還是incrementFailedLogins(HttpServletRequest)方法。現(xiàn)在,讓我們先分析一下incrementFailedLogins(HttpServletRequest):
private void incrementFailedLogins(HttpServletRequest request) {
HttpSession session = request.getSession();
ServletContext context =session.getServletContext();
Integer num = (Integer) context.getAttribute( Constants.FAILED_LOGINS_KEY);
int newValue = 1;
if (num != null) { newValue = num.intValue() + 1; }
context.setAttribute( Constants.FAILED_LOGINS_KEY, new Integer(newValue));
} |
這個(gè)方法增加一個(gè)在應(yīng)用程序范圍存儲(chǔ)的FAILED_LOGINS_KEY變量。這個(gè)incrementSuccessLogins(HttpServletRequest)方法是以相似的方法實(shí)現(xiàn)的。該應(yīng)用程序追蹤有多少人成功地登錄和有多少人認(rèn)證失敗。這真不錯(cuò),但是我們?cè)撊绾未嫒∵@些數(shù)據(jù)?這就是引入JMX的原因。
四、 創(chuàng)建JMX MBeans
MBeans
基礎(chǔ)知識(shí)及其適于JMX架構(gòu)的方面超出了本文所討論的范圍。我們將為我們的應(yīng)用程序簡(jiǎn)單地創(chuàng)建、實(shí)現(xiàn)、暴露和保護(hù)一個(gè)MBean。我們所感興趣的是暴露相應(yīng)與下列兩個(gè)方法的兩種數(shù)據(jù)。下面是我們的簡(jiǎn)單MBean接口:
public interface LoginStatsMBean {
public int getFailedLogins();
public int getSuccessLogins();
} |
這兩個(gè)方法簡(jiǎn)單地返回成功和失敗登陸的數(shù)目。LoginStatsMBean的實(shí)現(xiàn)-LoginStats,為上面兩種方法提供了一種具體的實(shí)現(xiàn)。讓我們分析一下getFailedLogins()實(shí)現(xiàn):
public int getFailedLogins() {
ServletContext context = Config.getServletContext();
Integer val = (Integer) context.getAttribute( Constants.FAILED_LOGINS_KEY);
return (val == null) ? 0 : val.intValue();
} |
該方法返回一個(gè)存儲(chǔ)在ServletContext中的值。getSuccessLogins()方法是以相似的方式實(shí)現(xiàn)的。
五、 創(chuàng)建和保護(hù)一個(gè)JMX代理
管理應(yīng)用程序的JMX相關(guān)方面的JMXAgent類有以下幾個(gè)責(zé)任:
1. 創(chuàng)建一個(gè)MBeanServer。
2. 用MBeanServer注冊(cè)LoginStatsMBean。
3. 創(chuàng)建一個(gè)JMXConnector以允許遠(yuǎn)程客戶進(jìn)行連接。
o 包含對(duì)JNDI的使用。
o 也必須有一個(gè)RMI注冊(cè)運(yùn)行。
4. 使用一個(gè)用戶名和口令保護(hù)JMXConnector。
5. 分別在應(yīng)用程序啟動(dòng)和停止時(shí),啟動(dòng)和停止JMXConnector。
JMXAgent的類輪廓是:
public class JMXAgent {
public JMXAgent() {
//初始化JMX服務(wù)器
}
public void start() {
//啟動(dòng)JMX服務(wù)器
}
//在應(yīng)用程序結(jié)束時(shí)調(diào)用
public void stop() {
//停止JMX服務(wù)器
}
} |
讓我們理解在該構(gòu)造器的這部分代碼-它能夠使得客戶遠(yuǎn)程地監(jiān)控該應(yīng)用程序。
用MBeans創(chuàng)建一個(gè)MBeanServer
我們首先創(chuàng)建一個(gè)MBeanServer對(duì)象。它是JMX基礎(chǔ)結(jié)構(gòu)的核心組件,它允許我們暴露我們的MBeans作為可管理的對(duì)象。MBeanServerFactory.createMBeanServer(String)方法使得這一任務(wù)極為輕松。所提供的參數(shù)是服務(wù)器的域。可以把它當(dāng)作這個(gè)MBeanServer的唯一的名字。然后,我們用MbeanServe來(lái)注冊(cè)LoginStatsMBean。MBeanServer.re
GISterMBean(Object,ObjectName)方法使用的參數(shù)有兩個(gè):一個(gè)是MBean實(shí)現(xiàn)的一個(gè)實(shí)例;另一個(gè)是類型ObjectName的一個(gè)對(duì)象-它用于唯一地標(biāo)識(shí)該MBean;在這種情況下,DOMAIN+":name=LoginStats"就足夠了。
MBeanServer server = MBeanServerFactory.createMBeanServer(DOMAIN);
server.registerMBean(new LoginStats(),new ObjectName(DOMAIN+ ":name=LoginStats")); |
六、 創(chuàng)建JMXServiceURL
到現(xiàn)在為止,我們已經(jīng)創(chuàng)建了一個(gè)MBeanServer并且用它注冊(cè)了LoginStatsMBean。下一步是使得該
服務(wù)器對(duì)客戶可用。為此,我們必須創(chuàng)建一個(gè)JMXServiceURL-它描述了客戶將用來(lái)存取該JMX服務(wù)的URL:
JMXServiceURL url = new JMXServiceURL("rmi",null,
Constants.MBEAN_SERVER_PORT,
"/jndi/rmi://localhost:" +Constants.RMI_REGISTRY_PORT +"/jmxapp"); |
讓我們細(xì)致地分析一下上面一行代碼。該JMXServiceURL構(gòu)造器使用了四個(gè)參數(shù):
1. 在連接時(shí)使用的協(xié)議(rmi,jmxmp,iiop,等等)。
2. JMX服務(wù)的主機(jī)。用localhost作為參數(shù)就足夠了。然而,提供null強(qiáng)制JMXServiceURL找到可能是最好的主機(jī)名。例如,在這種情況下,它將把null翻譯成zarar-這是我的計(jì)算機(jī)的名字。
3. JMX服務(wù)使用的端口。
4. 最后,我們必須提供URL路徑-它指示怎樣找到JMX服務(wù)。在這種情況下,它會(huì)是/jndi/rmi://localhost:1099/jmxapp。
其中,/jndi部分是指,客戶必須為JMX服務(wù)做一下JNDI查詢。rmi://localhost:1099指示,存在一個(gè)運(yùn)行于本機(jī)的端口1099的RMI注冊(cè)。這里的jmxapp是在RMI注冊(cè)中唯一標(biāo)識(shí)這個(gè)JMX服務(wù)的。在JMXServiceURL對(duì)象上的一個(gè)toString()產(chǎn)生下列結(jié)果:
service:jmx:rmi://zarar:9589/jndi/rmi://localhost:1100/jmxapp
上面是客戶將最終使用來(lái)連接到該JMX服務(wù)的URL。
J2SE 5.0文檔有關(guān)于這個(gè)URL結(jié)構(gòu)的更為詳細(xì)的解釋。
(一) 保護(hù)服務(wù)
J2SE 5.0提供了一種有利于JMX用一種容易的方式進(jìn)行用戶認(rèn)證的機(jī)制。我創(chuàng)建了一個(gè)簡(jiǎn)單的文本文件-它存儲(chǔ)用戶名和口令信息。文件的內(nèi)容是:
zarar siddiqi
fyodor dostoevsky
用戶zarar和fyodor被分別通過(guò)口令siddiqi和dostoevsky認(rèn)證。下一步是創(chuàng)建并保護(hù)一個(gè)JMXConnectorServer,它暴露了該MbeanServer。username/password文件的路徑被存儲(chǔ)在該鍵下的一個(gè)映射中-jmx.remote.x.password.file。這個(gè)映射在以后創(chuàng)建JMXConnectorServer時(shí)使用。
ServletContext context = Config.getServletContext();
//得到存儲(chǔ)jmx用戶信息的文件
String userFile =context.getRealPath("/")+"/Web-INF/classes/"+Constants.JMX_USERS_FILE;
//創(chuàng)建authenticator并且初始化RMI服務(wù)器
Map<string> env = new HashMap<string>();
env.put("jmx.remote.x.password.file", userFile);
現(xiàn)在,讓我們創(chuàng)建JMXConnectorServer。下面一行代碼完成這一功能:
connectorServer = JMXConnectorServerFactory.
newJMXConnectorServer(url, env, server); |
這個(gè)JMXConnectorServerFactory.newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)方法使用我們剛創(chuàng)建的三個(gè)對(duì)象作為參數(shù)-它們是JMXServiceURL,存儲(chǔ)認(rèn)證信息的映射和MBeanServer。其中,connectorServer實(shí)例變量允許我們分別在應(yīng)用程序啟動(dòng)和停止時(shí),分別用start()和stop()來(lái)啟動(dòng)和停止JMXConnectorServer。
提示 盡管JSR 160的J2SE 5.0實(shí)現(xiàn)相當(dāng)有力;但是另外的實(shí)現(xiàn),例如MX4J,也提供了一些類-它們提供了方便的特性,例如口令混淆,也就是PasswordAuthenticator類。
七、 啟動(dòng)RMI注冊(cè)
在早些時(shí)候,我提到RMI注冊(cè)并且指出當(dāng)訪問(wèn)服務(wù)時(shí)執(zhí)行一個(gè)JNDI查詢。然而,現(xiàn)在我們沒(méi)有一個(gè)正運(yùn)行的RMI注冊(cè),因此一個(gè)JNDI查詢將失敗。一個(gè)RMI注冊(cè)的啟動(dòng)可以用手工方式或編程方式來(lái)實(shí)現(xiàn)。
(一) 使用命令行
在你的
Windows或
Linux命令行上,輸入下列一名來(lái)啟動(dòng)一個(gè)RMI注冊(cè):
rmiregistry &
這將啟動(dòng)你的默認(rèn)主機(jī)和端口(分別是localhost和1109)的RMI注冊(cè)。然而,對(duì)于我們的web應(yīng)用程序來(lái)說(shuō),我們不可能依賴一個(gè)在應(yīng)用程序啟動(dòng)時(shí)可用的RMI而寧愿用編程方式來(lái)實(shí)現(xiàn)之。
(二) 以編程方式啟動(dòng)RMI注冊(cè)
為了以編程方式啟動(dòng)RMI注冊(cè),你可以使用LocateRegistry.createRegistry(int port)方法。該方法返回類型注冊(cè)的一個(gè)對(duì)象。當(dāng)我們想在應(yīng)用程序一端終止這個(gè)注冊(cè)時(shí),我們保存這個(gè)參考。就在我們啟動(dòng)我們的在JMXAgent.start()中的JMXConnectorServer之前,我們首先啟動(dòng)RMI注冊(cè),使用下列代碼行:
registry = LocateRegistry.createRegistry(Constants.RMI_REGISTRY_PORT);
在應(yīng)用程序一端,在JMXAgent.stop()中停止JMXConnectorServer之后,調(diào)用下列方法來(lái)終止該注冊(cè):
UnicastRemoteObject.unexportObject(registry,true);
注意,StartupListener類觸發(fā)了應(yīng)用程序開(kāi)始和結(jié)束任務(wù)。
八、 訪問(wèn)我們的JMX服務(wù)
我們可以有好幾種方法來(lái)存取JSR 160服務(wù)。為此,我們可以通過(guò)編程或通過(guò)使用一個(gè)GUI來(lái)實(shí)現(xiàn)。
(一) 使用MC4J連接
通過(guò)把jmxapp.war復(fù)制到Tomcat的
Webapps目錄來(lái)發(fā)布該應(yīng)用程序。
下載并且安裝MC4J。一旦安裝完,創(chuàng)建一新的類型JSR 160的
服務(wù)器連接并且指定該服務(wù)器URL-它在應(yīng)用程序啟動(dòng)時(shí)在應(yīng)用程序服務(wù)器日志中打印。在我的示例中,它是:
service:jmx:rmi://zarar:9589/jndi/rmi://localhost:1100/jmxapp
提供用戶名和口令,MC4J分別把它們參考為"Principle"和"Credentials"。點(diǎn)擊Next將把你帶到一個(gè)屏幕-在此你可以定制你的classpath。默認(rèn)設(shè)置應(yīng)該工作正常,并且你可以點(diǎn)擊"Finish"來(lái)連接到該JMX服務(wù)。一旦建立連接,瀏覽如圖1所示的MC4J樹(shù)結(jié)構(gòu),直到你找到LoginStats MBean實(shí)現(xiàn)的"Properties"選項(xiàng)。

圖1.MC4J視圖
|
點(diǎn)擊Properties顯示統(tǒng)計(jì),如圖2所示:

圖2.屬性窗口
|
(二) 使用jManage連接到一個(gè)"簇"
通過(guò)把jmxapp.war復(fù)制到Tomcat的webapps目錄發(fā)布該應(yīng)用程序。請(qǐng)注意一下在應(yīng)用程序啟動(dòng)時(shí)所打印的URL。接下來(lái),發(fā)布這個(gè)應(yīng)用程序的另一個(gè)實(shí)例-通過(guò)改變Constants類中的RMI_RE
GISTRY_PORT并且MBEAN_SERVER_PORT變量,這樣該應(yīng)用程序的第二個(gè)實(shí)例就不會(huì)試圖使用已經(jīng)在使用的端口了。改變?cè)赽uild.
XML文件中的app.name屬性,以便新的實(shí)例將被發(fā)布到一個(gè)不同的上下文(例如,jmxapp2)。用ant創(chuàng)建一個(gè)清理的war文件-它將在其目錄下創(chuàng)建jmxapp2.war。把jmxapp2.war復(fù)制到Tomcat的webapps目錄。該應(yīng)用程序?qū)⒁l(fā)布,而且現(xiàn)在你有相同應(yīng)用程序的兩個(gè)實(shí)例在運(yùn)行了。我再次提醒你注意在啟動(dòng)時(shí)所打印的URL。
下載和安裝jManage。一旦安裝了,使用jManage的web接口來(lái)創(chuàng)建一個(gè)JSR 160應(yīng)用程序-通過(guò)使用主頁(yè)中的"添加新應(yīng)用程序"鏈接。"添加應(yīng)用程序"頁(yè)面顯示在圖3中:

圖3."添加應(yīng)用程序"頁(yè)面
|
為要發(fā)布的第二個(gè)應(yīng)用程序重復(fù)前面的步驟并再次使用適當(dāng)?shù)挠脩裘⒖诹詈蚒RL。。一旦你創(chuàng)建了這兩個(gè)應(yīng)用程序,你必須通過(guò)遵循在主頁(yè)中找到的"添加新應(yīng)用程序簇"鏈接來(lái)創(chuàng)建一個(gè)簇。現(xiàn)在,把這兩個(gè)已經(jīng)創(chuàng)建的應(yīng)用程序添加到你的簇上,如圖4所示:

圖4.添加應(yīng)用程序簇頁(yè)面
|
好了,我們已經(jīng)完成了!從主頁(yè)上,點(diǎn)擊簇中的一個(gè)應(yīng)用程序,然后點(diǎn)擊"Find More Objects"按鈕。你將看到name=LoginStats MBean;點(diǎn)擊它,則你就會(huì)看到我們已經(jīng)暴露的FailedLogins和SuccessLogins屬性。點(diǎn)擊在該同一頁(yè)面上的"Cluster View"鏈接將顯示與圖5相類似的一個(gè)頁(yè)面-其中,你可以看到兩個(gè)應(yīng)用程序的運(yùn)行計(jì)數(shù)統(tǒng)計(jì):

圖5.針對(duì)jmxapp和jmxapp2的簇視圖
|
試著登錄到兩個(gè)應(yīng)用程序(http://localhost:8080/jmxapp和http://localhost:8080/jmxapp2)并且觀察這些數(shù)字是怎樣改變的。
九、 結(jié)論
現(xiàn)在你已經(jīng)知道了怎樣使你的新的和現(xiàn)有web應(yīng)用程序支持JMX并且安全地管理它們-使用MC4J和jManage。盡管
J2SE 5.0提供了JMX說(shuō)明書的一個(gè)有力的實(shí)現(xiàn),但是另外的開(kāi)源工程例如XMOJO和MX4J還提供了另外的特征,例如經(jīng)由web接口甚至更多的方式的連接。如果有興趣的讀者想了解更多地有關(guān)JMX的知識(shí),你可以看一下J. Steven Perry寫的《
Java Management Extensions》一書。如果你對(duì)遠(yuǎn)程應(yīng)用程序管理感興趣的話,Jeff Hanson寫的《Connecting JMX客戶and Servers》將是很有閱讀價(jià)值的,其中提供了許多真實(shí)世界的例子。
J2SE 5.0中的
Java.util.concurrent程序包提供了一個(gè)新的
線程框架組件,這個(gè)框架組件處理了與建立、執(zhí)行和管理線程相關(guān)的很多低層細(xì)節(jié)信息。在本文中我們將細(xì)致地了解一下它的重要特性。
如果你使用C、
C++或Java先前的版本進(jìn)行多線程編程,就知道在代碼中管理線程是多么頭疼的事情。在單線程程序中,代碼中引起應(yīng)用程序失敗的bug每次都在同一個(gè)點(diǎn)出現(xiàn)。但是在多線程程序中,只有某些原因遇到一起的時(shí)候才會(huì)出現(xiàn)失敗。由于預(yù)見(jiàn)可能引發(fā)應(yīng)用程序失敗的所有條件是非常困難的,所以多線程編程是有挑戰(zhàn)性的。有些程序員從根本上避免這種挑戰(zhàn),而另外一些--聰明的解決問(wèn)題的人員--則一直坐在他們的計(jì)算機(jī)面前直到問(wèn)題解決。
J2SE 5.0平臺(tái)包含了一個(gè)新的并發(fā)工具程序包。這個(gè)程序包中的類替并發(fā)類(concurrent classe)或并發(fā)設(shè)計(jì)中使用的應(yīng)用程序建立阻塞(blocking)。該并發(fā)工具包含下面一些內(nèi)容:
· 高性能的、靈活的線程池
· 異步執(zhí)行事務(wù)的框架組件
· 為并發(fā)訪問(wèn)優(yōu)化過(guò)的集合類宿主(host)
本文介紹了J2SE 5.0框架組件類和它們的重要特性。本文的
下載代碼提供了一些簡(jiǎn)單的、容易使用的示例,它演示了所有的新線程框架組件類。你在閱讀文章內(nèi)容之后運(yùn)行這些示例可以使自己對(duì)這些特性有更好的理解。
Executor(執(zhí)行器)框架組件
Executor框架組件提供了一個(gè)簡(jiǎn)單的、標(biāo)準(zhǔn)的、可擴(kuò)充的類,它提供了一些有用的功能,如果沒(méi)有這些功能,我們要手工實(shí)現(xiàn)這些它們,會(huì)覺(jué)得十分單調(diào)和困難。該框架組件使調(diào)用、調(diào)度和執(zhí)行的操作標(biāo)準(zhǔn)化了。它通過(guò)一組執(zhí)行策略為控制異步事務(wù)提供了支持。
Executor接口執(zhí)行已提交的可以運(yùn)行的事務(wù)。它提供了一條途徑,允許我們把事務(wù)提交從事務(wù)執(zhí)行機(jī)制中分離出來(lái)。程序員通常使用Executor代替顯式地(explicitly)建立線程。Executor接口也提供事務(wù)的同步和異步執(zhí)行。
對(duì)于同步執(zhí)行,使用下面的命令:
Class MySynExecutor implements Executor{
public void execute(Runnable r) {
r.run();
}
}
對(duì)于異步執(zhí)行,使用下面的命令:
Class MyASynExecutor implements Executor{
public void execute(Runnable r) {
new Thread(r).start();
}
}
ExecutorService(執(zhí)行器服務(wù))類
ExecutorService類為管理一個(gè)或多個(gè)異步事務(wù)的終止和跟蹤事務(wù)執(zhí)行的過(guò)程提供了方法。代碼下載中的MyExecutorService.java文件演示了管理事務(wù)終止的過(guò)程。它初始化了大小為三個(gè)的線程池,然后依次添加了線程。當(dāng)線程的數(shù)量達(dá)到線程池的大小限制時(shí),它調(diào)用關(guān)閉(shutdown)方法。在調(diào)用shutdown()方法之后,這個(gè)線程池不再接受新事務(wù)的執(zhí)行。在等待十秒以后,該線程池調(diào)用shutDownNow()。這個(gè)方法會(huì)盡最大的努力來(lái)終止所有運(yùn)行中的事務(wù)。在示例中,應(yīng)用程序試圖終止運(yùn)行中的線程失敗了。
ScheduledExecutorService(調(diào)度執(zhí)行器服務(wù))
ScheduledExecutorService類是我的最喜歡的類。它對(duì)于調(diào)度那些周期性執(zhí)行的事務(wù)非常方便,而周期性執(zhí)行的事務(wù)對(duì)于清除工作(例如清除你的應(yīng)用程序建立的臨時(shí)文件等等)尤其有用。下載代碼中的MyScheduledExecutorService.java文件通過(guò)每五秒鐘發(fā)出"嘟嘟"一聲演示了調(diào)度的過(guò)程:
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture beeperHandle =scheduler.scheduleAtFixedRate(beeper, 1, 5, SECONDS);
首先說(shuō)一說(shuō)進(jìn)入計(jì)算機(jī)專業(yè)的目的,我個(gè)人是因?yàn)槭窒矚gIT業(yè),很喜歡折騰電腦,所以在填報(bào)志愿是毫不猶豫的在報(bào)了的所有的學(xué)校都填寫的計(jì)算機(jī)專業(yè),夢(mèng)想著進(jìn)入計(jì)算機(jī)專業(yè)后能遇見(jiàn)很多高手,能交到幾個(gè)知己,誰(shuí)之進(jìn)來(lái)后卻大失所望。計(jì)算機(jī)專業(yè)的學(xué)生有很多以前對(duì)計(jì)算機(jī)不怎么了解,而且還有部分人進(jìn)大學(xué)前連計(jì)算機(jī)摸都沒(méi)摸過(guò),對(duì)計(jì)算機(jī)很熟悉的很少,高手更是鳳毛麟角,大多數(shù)人是服從了父母之命,顯而易見(jiàn),目前社會(huì)最熱的行業(yè)是IT業(yè),工資最高的也是IT業(yè),抱著這個(gè)因素,大多數(shù)考生的父母都讓自己的孩子進(jìn)入了計(jì)算機(jī)專業(yè),而大多數(shù)學(xué)生也天真的認(rèn)為從計(jì)算機(jī)專業(yè)畢業(yè)后就能夠像電視里演的大多數(shù)白領(lǐng)一樣每天只用坐在辦公室里和同事們聊聊天,和老板吃吃飯,每天簽幾個(gè)字然后就有高工資等著你去拿。
進(jìn)校后他們發(fā)現(xiàn)其實(shí)他們?cè)趯I(yè)課方面什么都聽(tīng)不懂,自己也一點(diǎn)興趣都沒(méi)有,沒(méi)有興趣那就沒(méi)有學(xué)習(xí)的動(dòng)力,而且這個(gè)專業(yè)是要靠悟性的,而興趣是培養(yǎng)悟性的第一步,然后他們會(huì)發(fā)現(xiàn)越往后學(xué)專業(yè)課越難,也越聽(tīng)不懂,好一點(diǎn)的就會(huì)狠下心來(lái),硬著頭皮苦學(xué)一通,有可能也就能走出一片路來(lái),而不好的就會(huì)就此放棄,只需要混著考試通過(guò),混畢業(yè),找個(gè)單位安心上班。有些人上了幾年學(xué)連自己上哪些課都不知道;拿個(gè)程序他分不清是用C語(yǔ)言寫的還是用PASCAL寫的;不小心進(jìn)了DOS不知道怎么再回到WINDOWS。但說(shuō)起游戲來(lái)頭頭是道,好像每個(gè)都是職業(yè)玩家一樣,有的每天只知道泡在網(wǎng)吧。這就是中國(guó)計(jì)算機(jī)人才下一代的悲哀!
再說(shuō)現(xiàn)在計(jì)算機(jī)專業(yè)大學(xué)生的學(xué)習(xí)和生活。大多數(shù)計(jì)算機(jī)專業(yè)的學(xué)生對(duì)本專業(yè)的發(fā)展及前景一無(wú)所知,每天都是看小說(shuō)、玩游戲、看電影、打牌、喝酒、睡覺(jué)等等很有"前途"的事情。偶爾看見(jiàn)一兩個(gè)同學(xué)看看與計(jì)算機(jī)專業(yè)有關(guān)的書,跑去拿來(lái)一看,全是什么"游戲攻略"、"黑客秘技"等此類書籍。還有的人連C語(yǔ)言和C++誰(shuí)是誰(shuí)都還沒(méi)搞清楚,就拿本VC的書"刻苦鉆研",真不知他們看懂了沒(méi)有。好多學(xué)生都買了電腦,但用處都是游戲機(jī)+碟機(jī)+音響,每天都在用電腦玩著各種流行的游戲、看著最新的大片、聽(tīng)著時(shí)尚的音樂(lè),就是不用電腦學(xué)習(xí)。有的學(xué)生甚至問(wèn)我電腦除了玩游戲還能干什么,我問(wèn)他你為什么這么問(wèn),他告訴我他覺(jué)得電腦只能用來(lái)玩游戲,不知道還能不能干干別的什么。據(jù)我了解,近幾年在國(guó)內(nèi)好幾所高校的計(jì)算機(jī)專業(yè)的畢業(yè)生的畢業(yè)設(shè)計(jì)竟然是做網(wǎng)頁(yè),在大學(xué)了四年,學(xué)完了《數(shù)據(jù)結(jié)構(gòu)》、《軟件工程》、《C語(yǔ)言》等專業(yè)課后,竟然交了一個(gè)沒(méi)有學(xué)過(guò)計(jì)算機(jī)的人自學(xué)一兩天就能做好的東西!
這就是大多數(shù)計(jì)算機(jī)專業(yè)的學(xué)生,在我在大學(xué)玩了兩年之后,我突然明白該為自己的未來(lái)打算打算了,但還有許多人仍然還什么都不明白,所以就有了這篇文章。
如果你是以上我說(shuō)的那種受父母之命來(lái)學(xué)計(jì)算機(jī)的學(xué)生,如果你看了《計(jì)算機(jī)應(yīng)用文摘》第15期的《寫給想當(dāng)程序員的朋友》一文后,發(fā)現(xiàn)自己沒(méi)有當(dāng)程序員的欲望,那么我這里有幾條路給你選擇:
1、**頁(yè)制作,將來(lái)去網(wǎng)站工作!
2、學(xué)習(xí)3D MAX等軟件,去作動(dòng)畫!
3、學(xué)習(xí)美術(shù)設(shè)計(jì)!
4、網(wǎng)絡(luò),將來(lái)考個(gè)CCNA,去專業(yè)組網(wǎng)!
5、在保證能順利畢業(yè)的前提下,去瘋狂玩游戲,做個(gè)職業(yè)玩家或做一個(gè)或幾個(gè)網(wǎng)絡(luò)游戲的GM。(我身邊就有這樣的人)
6、以上五條都與計(jì)算機(jī)有關(guān),要有一定的專業(yè)知識(shí),但比起你的專業(yè)課簡(jiǎn)單多了。如果你看到這里還不覺(jué)得有適合你干的,那這條最適合你:在你們學(xué)校去修雙學(xué)位,修一個(gè)自己感興趣的專業(yè),計(jì)算機(jī)真的不適合你!
如果以上幾條有適合你的,那么你就努力去做適合你的那一片天地,去看雜志的下一篇文章,下面的文字你看了只會(huì)浪費(fèi)你的時(shí)間。
如果你是計(jì)算機(jī)專業(yè)的在校大學(xué)生,而且想當(dāng)軟件設(shè)計(jì)師,那么請(qǐng)往下看:
1、大學(xué)生活豐富多彩,會(huì)令你一生都難忘,但難忘有很多種,你可以學(xué)了很多東西而難忘,也會(huì)因?yàn)槭裁炊紱](méi)學(xué)到而難忘!
2、計(jì)算機(jī)專業(yè)是一個(gè)很枯燥的專業(yè),但即來(lái)之、則安之,只要你努力學(xué),也會(huì)發(fā)現(xiàn)其中的樂(lè)趣的。
3、記住:萬(wàn)丈高樓平地起!基礎(chǔ)很重要,尤其是專業(yè)基礎(chǔ)課,只有打好基礎(chǔ)才能學(xué)得更深。
4、C語(yǔ)言是基礎(chǔ),很重要,如果你不學(xué)好C語(yǔ)言,那么什么高級(jí)語(yǔ)言你都學(xué)不好。
5、C語(yǔ)言與C++語(yǔ)言是兩回事。就象大熊貓和小熊貓一樣,只是名字很像!
6、請(qǐng)先學(xué)習(xí)專業(yè)課《數(shù)據(jù)結(jié)構(gòu)》、《計(jì)算機(jī)組成原理》,不要?jiǎng)傞_(kāi)始就拿著一本VC在看,你連面向?qū)ο蠖几悴磺宄碫C沒(méi)有任何用處。
7、對(duì)編程有一定的認(rèn)識(shí)后,就可以學(xué)習(xí)C++了。(是C++而不是VC,這兩個(gè)也是兩碼事!C++是一門語(yǔ)言,而VC教程則是講解如何使用MFC類庫(kù),學(xué)習(xí)VC應(yīng)建立在充分了解C++的基礎(chǔ)之上。看VC的書,是學(xué)不了C++語(yǔ)言的。)
8、學(xué)習(xí)編程的秘訣是:編程,編程,再編程;
9、認(rèn)真學(xué)習(xí)每一門專業(yè)課,那是你的吃飯碗。
10、在學(xué)校的實(shí)驗(yàn)室就算你做錯(cuò)一萬(wàn)次程序都不會(huì)有人罵你,如果你在公司你試試看!所以多去實(shí)驗(yàn)室上機(jī),現(xiàn)在錯(cuò)的多了,畢業(yè)后就錯(cuò)的少了。
11、從現(xiàn)在開(kāi)始,在寫程序時(shí)就要養(yǎng)成良好的習(xí)慣。
12、不要漏掉書中任何一個(gè)練習(xí)題--請(qǐng)全部做完并記錄下解題思路。
13、你會(huì)買好多參考書,那么請(qǐng)把書上的程序例子親手輸入到電腦上實(shí)踐,即使配套光盤中有源代碼。
14、VC、C#、.NET這些東西都會(huì)過(guò)時(shí),不會(huì)過(guò)時(shí)的是數(shù)據(jù)結(jié)構(gòu)和優(yōu)秀的算法!
15、記住:書到用時(shí)方恨少。不要讓這種事發(fā)生在你身上,在學(xué)校你有充足的時(shí)間和條件讀書,多讀書,如果有條件多讀原版書,你要知道,當(dāng)一個(gè)翻譯者翻譯一本書時(shí),他會(huì)不知不覺(jué)把他的理念寫進(jìn)書中,那本書就會(huì)變得像雞肋!
16、我還是強(qiáng)調(diào)認(rèn)真聽(tīng)專業(yè)課,因?yàn)橛行┱n像《數(shù)據(jù)結(jié)構(gòu)》、《編譯原理》、《操作系統(tǒng)》等等,這種課老師講一分鐘能讓你明白的內(nèi)容,你自己看要看好幾個(gè)月,有的甚至看了好幾年都看不明白。
17、抓住在學(xué)校里的各種實(shí)踐的機(jī)會(huì),要為自己積累經(jīng)驗(yàn),就業(yè)時(shí)經(jīng)驗(yàn)比什么都有用。
18、多去圖書館,每個(gè)學(xué)校的圖書館都有很多好書等你去看!
19、編程不是技術(shù)活,而是體力活。
20、如果你決定了要當(dāng)一個(gè)好的軟件設(shè)計(jì)師,那么請(qǐng)你放棄游戲,除非你是那種每天只要玩游戲就能寫出好程序的天才!
21、你要有足夠的韌性和毅力!有個(gè)高手出了一道題測(cè)試你的韌性和毅力:找個(gè)10000以內(nèi)的素?cái)?shù)表,把它們?nèi)汲聛?lái),然后再檢查三遍,如果能夠不間斷地完成這一工作,你就可以滿足這一條。
22、找到只屬于你自己的學(xué)習(xí)方法!不要盲目的追隨別人的方法,適合自己的才是最好的!
23、請(qǐng)熱愛(ài)軟件設(shè)計(jì)這項(xiàng)工作!
以上的話有些是我的經(jīng)驗(yàn),有些是我從高手那里直接COPY來(lái)的,但他們都很有用,記住他們,并遵守他們,那你們一定會(huì)成功!
對(duì)于大多數(shù)初學(xué)者來(lái)說(shuō),好多人有這種問(wèn)題存在:我到底先學(xué)什么?學(xué)C/C++?還是學(xué)VC?還是學(xué)Borland C++ Builder呢?還是Delphi?哪一個(gè)更好呢?學(xué)習(xí)程序設(shè)計(jì)和學(xué)習(xí)程序設(shè)計(jì)語(yǔ)言究竟是怎么一個(gè)關(guān)系?初學(xué)者究竟應(yīng)該如何取舍呢?就這些問(wèn)題,我從一個(gè)高手那里看了一下的這段話,可以幫助在這方面有問(wèn)題的人:學(xué)習(xí)程序設(shè)計(jì)就好比學(xué)習(xí)射擊,而程序設(shè)計(jì)語(yǔ)言就對(duì)應(yīng)射擊中的氣槍、手槍、步槍等各種槍械。學(xué)習(xí)射擊必須要選擇一種槍械,不可能沒(méi)有槍還能學(xué)好射擊的,也不可能同時(shí)學(xué)會(huì)使用所有的槍械。但是,如果掌握一種槍械的射擊,再學(xué)別的也就觸類旁通了。因?yàn)樵谑煜ひ环N槍械的同時(shí),也學(xué)習(xí)了射擊技術(shù)本身。再學(xué)其他的,自然事半功倍。學(xué)習(xí)程序設(shè)計(jì)也是一樣,必然要從學(xué)習(xí)一門程序設(shè)計(jì)語(yǔ)言開(kāi)始入手。在學(xué)會(huì)系統(tǒng)的編程理念之后,用什么工具都一樣!
之所以寫這篇文章呢是因?yàn)樽约貉劭瓷磉吥敲炊嗟耐瑢W(xué)一個(gè)個(gè)都"不務(wù)正業(yè)",荒廢了學(xué)業(yè),心急如焚,自己也荒廢了好幾年,眼看微軟的Windows從3.X到現(xiàn)在的2003 Server,而中國(guó)的軟件業(yè)還是在原地踏步,難道我們真要每年等微軟給他的操作系統(tǒng)換一次名字,我們給他交一次錢嗎?這么大的利潤(rùn)為什么不留給我們自己,為什么不讓別的國(guó)家給我們交錢呢?這是廣大中國(guó)軟件工程師的一個(gè)共同的夢(mèng),要實(shí)現(xiàn)這個(gè)夢(mèng)的人是現(xiàn)在還在大學(xué)里的"軟件設(shè)計(jì)師"們,他們是中國(guó)軟件明天的希望!希望廣大計(jì)算機(jī)業(yè)的大學(xué)生看到這篇文章后,睡覺(jué)的能醒來(lái),玩游戲的能停下來(lái),在網(wǎng)吧的能出來(lái),一起拿起課本,坐在電腦前,用程序?qū)懗鲋袊?guó)軟件業(yè)明天的輝煌!
附: 雖然非常的現(xiàn)實(shí),對(duì)有些同學(xué)來(lái)說(shuō)有點(diǎn)殘酷,但是的是一針見(jiàn)血!!!!!
前段時(shí)間考過(guò)了SUN CERTIFIED JAVA PROGRAMMER ,考完后一直很忙,現(xiàn)在閑下來(lái),和大家分享一下考試的經(jīng)驗(yàn) 。
1 ) JAVA 2 PLAT FORM 考試科目是310-025 ,有59題,及格線是61%,即答對(duì)36題。考試時(shí)間是90 分鐘。特別令人厭惡的是考試前有個(gè)AGREEMENT,連你讀它的時(shí)間也被計(jì)算在內(nèi)。小弟開(kāi)始不知道,還在慢慢讀,突然發(fā)現(xiàn)已經(jīng)用了3分鐘,趕緊開(kāi)始作題。估計(jì) AGREEMENT 沒(méi)有什么重要的東西,可以直接跳過(guò)。時(shí)間勉強(qiáng)夠用,我大概花了60分鐘作完題,剩下20多分鐘檢查,居然又給我發(fā)現(xiàn)了3-5 題錯(cuò)誤,都是一時(shí)疏忽,落入題目設(shè)下的圈套,所以一定要留時(shí)間檢查。可惜我剩下10 題左右沒(méi)有時(shí)間檢查 。
2)考試范圍非常窄。基本上都是基本語(yǔ)言知識(shí),象SWING,JSP,SERVLET,JDBC,BEANS等等都不涉及。大家可以到SUN 網(wǎng)站上下載考試大綱。考試范圍窄不意味著容易,相反,一些很基本的東西被翻來(lái)覆去,變著花樣考,反而更難 。
3)考試只有選擇題,包括單選和復(fù)選。多數(shù)復(fù)選題明確指明有幾個(gè)答案,不會(huì)搞錯(cuò)。
4)印象中幾乎所有的考題都涉及2-3個(gè)以上的知識(shí)點(diǎn),幾乎沒(méi)有可以一眼就看出答案的題目。70%的考題是給你一段程序,然后問(wèn)運(yùn)行結(jié)果變量的值。這種題目非常容易落入陷阱,一不小心就被費(fèi)了。還有20%的題目是給你幾個(gè)陳述句,選正確的。這些陳述句都是考很偏很偏的東西,也不太好答。基本上我的經(jīng)驗(yàn)是:如果一個(gè)題目馬上能看出答案,請(qǐng)你在仔細(xì)研究一下題目,多數(shù)情況是你落入陷阱了。如果一個(gè)題目你能很明確的看出來(lái)他要考你什么知識(shí)點(diǎn),那這個(gè)題目就完成一半了。最慘的是知道題目要考你什么,但是忘記了或沒(méi)有復(fù)習(xí)相關(guān)知識(shí)細(xì)節(jié),只好胡猜答案了。
5)考試的一個(gè)重點(diǎn)是INNER CLASS。印象中一半以上的題目和他有關(guān)。都是大CLASS套小CLASS 等。我復(fù)習(xí)時(shí)花了很多時(shí)間在這上面,以為自己很懂了,結(jié)果考試是還是有問(wèn)題。一定要透徹理解相關(guān)定義,語(yǔ)法,特別是各種各樣的MODIFIER 的用法。有很多很特殊的MODIFER 規(guī)則。這些規(guī)則一定要熟練掌握并牢記在心。
6)考試的另一個(gè)重點(diǎn)是循環(huán)語(yǔ)句。我考,我自以為對(duì)循環(huán)控制語(yǔ)句很熟悉了,結(jié)果考試考一些很偏很特別的用法,雖然慢慢作都能作出來(lái),但浪費(fèi)太多時(shí)間在這上面,實(shí)在可惜。大家好好看看書。
7)其它的象:CASTING ,IO ,LAYOUT ,EVEN HANDLING,AWT,THREAD,GARBAGECOLLECTION,MATH CLASS 等等,都有若干考題。
8)考試題目幾乎完全不體現(xiàn)實(shí)際應(yīng)用。如果我有一個(gè)JAVA 編譯器在身邊,幾乎所有的考題都可以輕松解決。我感覺(jué)SUN 希望考生能象JAVA 編譯器一樣熟悉JAVA 的特殊語(yǔ)法和特殊規(guī)則。這實(shí)際是完全沒(méi)有必要的。
9)我收集了很多模擬考題和BRAINDUMP ,有近千題。奇怪的是只有不到10 題出現(xiàn)在考試中,看來(lái)SUN 的考試題庫(kù)實(shí)行的可能是動(dòng)態(tài)題庫(kù),考背BRAINDUMP 是沒(méi)有什么希望通過(guò)了。而且程序考題只有稍微改動(dòng)一個(gè)符號(hào),結(jié)果就完全不同,BRAINDUMP 很多題目靠不住。所以大家一定要在一定實(shí)際經(jīng)驗(yàn)的基礎(chǔ)上,好好看透一本輔導(dǎo)書,多作題,多分析題,多思考,才能比較容易通過(guò)考試。
10)不管大家如何評(píng)價(jià)認(rèn)證考試,反正考多幾個(gè)證書不是壞事。起碼加薪找工比較方便。 I have:SCJP, MCSE, MCSD, MCDBA, MCSE+Internet.haha...It is better than nothing.Don't trust the people who sell SCJP questions online!It is very useless and a lot of errors!Work on your own experience!
1.OOP中唯一關(guān)系的是對(duì)象的接口是什么,就像計(jì)算機(jī)的銷售商她不管電源內(nèi)部結(jié)構(gòu)是怎樣的,他只關(guān)系能否給你提供電就行了,也就是只要知道can or not而不是how and why.所有的程序是由一定的屬性和行為對(duì)象組成的,不同的對(duì)象的訪問(wèn)通過(guò)函數(shù)調(diào)用來(lái)完成,對(duì)象間所有的交流都是通過(guò)方法調(diào)用,通過(guò)對(duì)封裝對(duì)象數(shù)據(jù),很大限度上提高復(fù)用率。
2.OOP中最重要的思想是類,類是模板是藍(lán)圖,從類中構(gòu)造一個(gè)對(duì)象,即創(chuàng)建了這個(gè)類的一個(gè)實(shí)例(instance)。
3.封裝:就是把數(shù)據(jù)和行為結(jié)合起在一個(gè)包中)并對(duì)對(duì)象使用者隱藏?cái)?shù)據(jù)的實(shí)現(xiàn)過(guò)程,一個(gè)對(duì)象中的數(shù)據(jù)叫他的實(shí)例字段(instance field)。
4.通過(guò)擴(kuò)展一個(gè)類來(lái)獲得一個(gè)新類叫繼承(inheritance),而所有的類都是由Object根超類擴(kuò)展而得,根超類下文會(huì)做介紹。
5.對(duì)象的3個(gè)主要特性
behavior---說(shuō)明這個(gè)對(duì)象能做什么
state---當(dāng)對(duì)象施加方法時(shí)對(duì)象的反映
dentity---與其他相似行為對(duì)象的區(qū)分標(biāo)志
每個(gè)對(duì)象有唯一的indentity 而這3者之間相互影響。
6.類之間的關(guān)系
use-a:依賴關(guān)系
has-a:聚合關(guān)系
is-a:繼承關(guān)系--例:A類繼承了B類,此時(shí)A類不僅有了B類的方法,還有其自己的方法.(個(gè)性存在于共性中)。
7.構(gòu)造對(duì)象使用構(gòu)造器:構(gòu)造器的提出,構(gòu)造器是一種特殊的方法,構(gòu)造對(duì)象并對(duì)其初始化。
例:Data類的構(gòu)造器叫Data
new Data()---構(gòu)造一個(gè)新對(duì)象,且初始化當(dāng)前時(shí)間。
Data happyday=new Data()---把一個(gè)對(duì)象賦值給一個(gè)變量happyday,從而使該對(duì)象能夠多次使用,此處要聲明的使變量與對(duì)象變量二者是不同的.new返回的值是一個(gè)引用。
構(gòu)造器特點(diǎn):構(gòu)造器可以有0個(gè),一個(gè)或多個(gè)參數(shù)
構(gòu)造器和類有相同的名字
一個(gè)類可以有多個(gè)構(gòu)造器
構(gòu)造器沒(méi)有返回值
構(gòu)造器總是和new運(yùn)算符一起使用
8.重載:當(dāng)多個(gè)方法具有相同的名字而含有不同的參數(shù)時(shí),便發(fā)生重載.編譯器必須挑選出調(diào)用哪個(gè)方法。
9.包(package)Java允許把一個(gè)或多個(gè)類收集在一起成為一組,稱作包,以便于組織任務(wù),標(biāo)準(zhǔn)Java庫(kù)分為許多包.java.lang java.util java,net等,包是分層次的所有的java包都在java和javax包層次內(nèi)。
10.繼承思想:允許在已經(jīng)存在的類的基礎(chǔ)上構(gòu)建新的類,當(dāng)你繼承一個(gè)已經(jīng)存在的類時(shí),那么你就復(fù)用了這個(gè)類的方法和字段,同時(shí)你可以在新類中添加新的方法和字段。
11.擴(kuò)展類:擴(kuò)展類充分體現(xiàn)了is-a的繼承關(guān)系. 形式為:class (子類) extends (基類)。
12.多態(tài):在java中,對(duì)象變量是多態(tài)的.而java中不支持多重繼承。
13.動(dòng)態(tài)綁定:調(diào)用對(duì)象方法的機(jī)制。
(1)編譯器檢查對(duì)象聲明的類型和方法名。
(2)編譯器檢查方法調(diào)用的參數(shù)類型。
(3)靜態(tài)綁定:若方法類型為priavte static final 編譯器會(huì)準(zhǔn)確知道該調(diào)用哪個(gè)方法。
(4)當(dāng)程序運(yùn)行并且使用動(dòng)態(tài)綁定來(lái)調(diào)用一個(gè)方法時(shí),那么虛擬機(jī)必須調(diào)用x所指向的對(duì)象的實(shí)際類型相匹配的方法版本。
(5)動(dòng)態(tài)綁定:是很重要的特性,它能使程序變得可擴(kuò)展而不需要重編譯已存代碼。
14.final類:為防止他人從你的類上派生新類,此類是不可擴(kuò)展的。
15.動(dòng)態(tài)調(diào)用比靜態(tài)調(diào)用花費(fèi)的時(shí)間要長(zhǎng)。
16.抽象類:規(guī)定一個(gè)或多個(gè)抽象方法的類本身必須定義為abstract。
例:public abstract string getDescripition
17.Java中的每一個(gè)類都是從Object類擴(kuò)展而來(lái)的。
18.object類中的equal和toString方法。
equal用于測(cè)試一個(gè)對(duì)象是否同另一個(gè)對(duì)象相等。
toString返回一個(gè)代表該對(duì)象的字符串,幾乎每一個(gè)類都會(huì)重載該方法,以便返回當(dāng)前狀態(tài)的正確表示.
(toString 方法是一個(gè)很重要的方法)
19.通用編程:任何類類型的所有值都可以同object類性的變量來(lái)代替。
20.數(shù)組列表:ArrayList動(dòng)態(tài)數(shù)組列表,是一個(gè)類庫(kù),定義在java.uitl包中,可自動(dòng)調(diào)節(jié)數(shù)組的大小。
21.class類 object類中的getclass方法返回ckass類型的一個(gè)實(shí)例,程序啟動(dòng)時(shí)包含在main方法的類會(huì)被加載,虛擬機(jī)要加載他需要的所有類,每一個(gè)加載的類都要加載它需要的類。
22.class類為編寫可動(dòng)態(tài)操縱java代碼的程序提供了強(qiáng)大的功能反射,這項(xiàng)功能為JavaBeans特別有用,使用反射Java能支持VB程序員習(xí)慣使用的工具。
能夠分析類能力的程序叫反射器,Java中提供此功能的包叫Java.lang.reflect反射機(jī)制十分強(qiáng)大.
1.在運(yùn)行時(shí)分析類的能力。
2.在運(yùn)行時(shí)探察類的對(duì)象。
3.實(shí)現(xiàn)通用數(shù)組操縱代碼。
4.提供方法對(duì)象。
而此機(jī)制主要針對(duì)是工具者而不是應(yīng)用及程序。
反射機(jī)制中的最重要的部分是允許你檢查類的結(jié)構(gòu).用到的API有:
java.lang.reflect.Field 返回字段
java.reflect.Method 返回方法.
java.lang.reflect.Constructor 返回參數(shù)
方法指針:java沒(méi)有方法指針,把一個(gè)方法的地址傳給另一個(gè)方法,可以在后面調(diào)用它,而接口是更好的解決方案。
23.接口(Interface)說(shuō)明類該做什么而不指定如何去做,一個(gè)類可以實(shí)現(xiàn)一個(gè)或多個(gè)interface。
24.接口不是一個(gè)類,而是對(duì)符合接口要求的類的一套規(guī)范。
若實(shí)現(xiàn)一個(gè)接口需要2個(gè)步驟:
1.聲明類需要實(shí)現(xiàn)的指定接口。
2.提供接口中的所有方法的定義。
聲明一個(gè)類實(shí)現(xiàn)一個(gè)接口需要使用implements 關(guān)鍵字
class actionB implements Comparable 其actionb需要提供CompareTo方法,接口不是類,不能用new實(shí)例化一個(gè)接口。
25.一個(gè)類只有一個(gè)超類,但一個(gè)類能實(shí)現(xiàn)多個(gè)接口。Java中的一個(gè)重要接口:Cloneable
26.接口和回調(diào).編程一個(gè)常用的模式是回調(diào)模式,在這種模式中你可以指定當(dāng)一個(gè)特定時(shí)間發(fā)生時(shí)回調(diào)對(duì)象上的方法。
例:ActionListener 接口監(jiān)聽(tīng)
類似的API有:java.swing.JOptionPane
java.swing.Timer
java.awt.Tookit
27.對(duì)象clone:clone方法是object一個(gè)保護(hù)方法,這意味著你的代碼不能簡(jiǎn)單的調(diào)用它。
28.內(nèi)部類:一個(gè)內(nèi)部類的定義是定義在另一個(gè)內(nèi)部的類。
原因是:
1.一個(gè)內(nèi)部類的對(duì)象能夠訪問(wèn)創(chuàng)建它的對(duì)象的實(shí)現(xiàn),包括私有數(shù)據(jù)。
2.對(duì)于同一個(gè)包中的其他類來(lái)說(shuō),內(nèi)部類能夠隱藏起來(lái)。
3.匿名內(nèi)部類可以很方便的定義回調(diào)。
4.使用內(nèi)部類可以非常方便的編寫事件驅(qū)動(dòng)程序。
29.代理類(proxy):
1.指定接口要求所有代碼
2.object類定義的所有的方法(toString equals)
30.數(shù)據(jù)類型:Java是強(qiáng)調(diào)類型的語(yǔ)言,每個(gè)變量都必須先申明它都類型,java中總共有8個(gè)基本類型.4種是整型,2種是浮點(diǎn)型,一種是字符型,被用于Unicode編碼中的字符,布爾型。
由基本概念開(kāi)始全面認(rèn)識(shí)Java
Java應(yīng)該怎么學(xué)?Java能做什么?什么是Applet?什么是Servlet、Jsp、EJB?還有Webspere、Weblogic又是做什么的等等。之所以學(xué)員會(huì)有這些疑問(wèn),是因?yàn)榇蠹移毡閷?duì)Java相關(guān)概念聽(tīng)說(shuō)的太多而了解的又相對(duì)少的緣故。
學(xué)通Java語(yǔ)言需要一個(gè)過(guò)程,所有Java相關(guān)的概念都會(huì)在學(xué)習(xí)的過(guò)程中逐漸變得清昕。這個(gè)過(guò)程的開(kāi)始就是要先學(xué)會(huì)標(biāo)準(zhǔn)的Java技術(shù)(J2SE),然后是學(xué)Java的簡(jiǎn)單Web運(yùn)用,然后分布式運(yùn)用,再以后對(duì)Java的移動(dòng)技術(shù)運(yùn)用就很容易理解了。
以下是Java標(biāo)準(zhǔn)技術(shù)的一些要點(diǎn):
一、Java的跨平臺(tái)性,即一次編譯到處運(yùn)行
簡(jiǎn)單地說(shuō)Java的跨平臺(tái)性就是指,編譯后的Java程序可直接在不同的平臺(tái)上運(yùn)行而不用重新編譯,這一特性使得Java隨著Web應(yīng)用的普及而迅速普及起來(lái)。而Java的跨平臺(tái)性是如何實(shí)現(xiàn)的呢?這就要理解Java虛擬機(jī)和字節(jié)碼的概念。
實(shí)際上,編譯后的Java代碼并不是傳統(tǒng)的二進(jìn)制代碼(如Windows下的.exe文件),而是Java字節(jié)碼,這種字節(jié)碼文件是不能直接在操作系統(tǒng)上執(zhí)行的。要想在一個(gè)操作系統(tǒng)上運(yùn)行一個(gè)Java程序必須有一個(gè)中間環(huán)節(jié)來(lái)負(fù)責(zé)將Java字節(jié)碼解釋成二進(jìn)制碼,這個(gè)中間環(huán)節(jié)就是Java虛擬機(jī)(簡(jiǎn)稱JVM)。由于目前大多數(shù)操作系統(tǒng)已經(jīng)實(shí)現(xiàn)了JVM,所以Java輕松實(shí)現(xiàn)跨平臺(tái)性。
二、面象對(duì)象技術(shù)
Java全面支持面象對(duì)象技術(shù),這體現(xiàn)在Class(類)是Java程序構(gòu)成的基本單元,一個(gè)Java程序通常由許多Class組成,而且這些Class還會(huì)有一定的繼承關(guān)系,Java支持Class的單繼承,從而使類之間的繼承關(guān)系更明確。繼承的結(jié)果產(chǎn)生類的多態(tài)性,類的多態(tài)本質(zhì)上講就是可以用父類的引用訪問(wèn)繼承類的實(shí)現(xiàn)(子類對(duì)象),類的這種多態(tài)性最終形成了組件對(duì)象模型的基礎(chǔ),即通過(guò)接口(父類)訪問(wèn)實(shí)現(xiàn)(子類)。
三、Java中的I/O操作
Java中以字節(jié)流(InputStream和OutputStream)、節(jié)符流(Reader和Writer)來(lái)分別讀寫二進(jìn)制數(shù)據(jù)和字符數(shù)據(jù),使用非常簡(jiǎn)單有效。Java類庫(kù)中的File類不僅提供文件操作而且還包含文件夾操作,如下面這幾行代碼可以列出C盤根目錄下的所有文件:
File f=new File("c://");
String [] m_dir= f.list();
for(int i=0;iSystem.out.println(m_dir[i]);
四、Java中的圖形及事件處理
可以用awt包或swing包的Java類來(lái)進(jìn)行大部分的Java圖形界面設(shè)計(jì),下面的幾行代碼將產(chǎn)生一個(gè)200*200像素的窗體:
Frame f=new Frame("Welcome");f.setSize(200,200);f.setVisible(true);
默認(rèn)情況下,F(xiàn)rame窗體的關(guān)閉按鈕不起作用,這也是Java初學(xué)者迷惑的地方。為了使用戶按下關(guān)閉按鈕時(shí)能關(guān)閉Frame窗體,需要讓這個(gè)窗體響應(yīng)一個(gè)WindowEvent事件,具體的做法就是給這個(gè)窗體添加一個(gè)事件監(jiān)聽(tīng)器對(duì)象,這個(gè)事件監(jiān)聽(tīng)器就是WindowListener接口的實(shí)現(xiàn)。在上面的代碼中插入如下代碼就可以關(guān)閉窗體:
f.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}
這里用到一個(gè)無(wú)名內(nèi)部類,無(wú)名內(nèi)部類是Java中內(nèi)部類的一種靈活運(yùn)用方式。
五、Java中線程及同步控制
線程概念的引入是為了實(shí)現(xiàn)并行處理,從而提高程序的效率。Java中的線程實(shí)現(xiàn)非常簡(jiǎn)單,可以用兩種方式來(lái)創(chuàng)建線程,一種是實(shí)現(xiàn)Runnable接口,另一種是繼承Thread類重寫run()方法。兩種方式唯一的不同就是前者保留了繼承一個(gè)類的可能(因?yàn)镴ava只支持類的單繼承,但接口沒(méi)有此限制)。
永遠(yuǎn)都用start()方法來(lái)啟動(dòng)一個(gè)線程,線程類中的run()可以被直接調(diào)用,但決不是啟動(dòng)一個(gè)線程,二者有著本質(zhì)的區(qū)別。
用同步控制關(guān)鍵字synchronized來(lái)保護(hù)線程敏感數(shù)據(jù),synchronized塊中的內(nèi)容可以保證同一時(shí)刻只能被一個(gè)線程訪問(wèn),所以其中的數(shù)據(jù)是線程安全的。
用Object類中的wait()和notify()方法可以實(shí)現(xiàn)線程間交互,但要記住wait()和notify()方法只有發(fā)生在同一個(gè)對(duì)象上才能真正實(shí)現(xiàn)線程間交互。被某一對(duì)象wait()方法阻塞的線程需要另外一個(gè)調(diào)用了同一對(duì)象notify()的線程干預(yù)才能恢復(fù)運(yùn)行。notify()方法一次喚醒一個(gè)被wait()方法阻塞的線程,notifyAll()方法可以一次喚醒所有被wait()方法阻塞的線程。
六、Java本地方法(native方法)的實(shí)現(xiàn)
Java不是完美的,Java的不足除了體現(xiàn)在運(yùn)行速度上要比傳統(tǒng)的C++慢許多之外,Java無(wú)法直接訪問(wèn)到操作系統(tǒng)底層(如系統(tǒng)硬件等),為此Java使用native方法來(lái)擴(kuò)展Java程序的功能。
可以將native方法比作Java程序同C程序的接口,其實(shí)現(xiàn)步驟:
1、Java中聲明native()方法,然后編譯;
2、用javah產(chǎn)生一個(gè).h文件;
3、寫一個(gè).cpp文件實(shí)現(xiàn)native導(dǎo)出方法,其中需要包含第二步產(chǎn)生的.h文件(注意其中又包含了JDK帶的jni.h文件);
4、將第三步的.cpp文件編譯成動(dòng)態(tài)鏈接庫(kù)文件;
5、在Java中用System.loadLibrary()方法加載第四步產(chǎn)生的動(dòng)態(tài)鏈接庫(kù)文件,這個(gè)native()方法就可以在Java中被訪問(wèn)了。
上述所提及的一些Java技術(shù)具有一定的普遍性,它們基本上是在Java各個(gè)方面的運(yùn)用中都需要掌握的術(shù)。實(shí)際上Java的運(yùn)用非常廣泛,而且每個(gè)方面都需要遵循不同的規(guī)范。以下是對(duì)Java應(yīng)用的簡(jiǎn)要介紹。
(一)理解Java SDK的三個(gè)版本:
Java SDK Micro Edition (J2ME)
用于開(kāi)發(fā)掌上電腦、手機(jī)等移動(dòng)通信設(shè)備上使用的應(yīng)用程序。并不是所有的移動(dòng)設(shè)備都支持Java,只有具備J2ME運(yùn)行環(huán)境(JVM+J2ME API)的設(shè)備才能運(yùn)行Java程序。J2ME的集成開(kāi)發(fā)工具(通常都有帶有一些訪真器)有 Sun 的J2ME Wireless Toolkit 、IBM的Visul Age Micro Edition 等。
Java SDK Standard Edition(J2SE)
主要用于開(kāi)發(fā)一般臺(tái)式機(jī)應(yīng)用程序。我們平時(shí)所說(shuō)的JDK就指J2SE,而我們學(xué)Java就是從學(xué)習(xí)J2SE開(kāi)始的。
Java SDK Enterprise Edition (J2EE)
用于開(kāi)發(fā)分布式的企業(yè)級(jí)大型應(yīng)用程序。其中的核心是Entetprise Java Beans(EJB,分布式Java組件)的開(kāi)發(fā)。
(二)Java小程序 (Applet)
Java小程序是一個(gè)繼承了Applet類并重寫了init()、paint()、stop()等方法的的Java類,它被布署在Web服務(wù)器(如IIS)上,當(dāng)客戶端請(qǐng)求Web頁(yè)時(shí),瀏覽器從Web服務(wù)器上將其下載到本地客戶端,然后,瀏覽器創(chuàng)建該Applet類的實(shí)例并調(diào)用其init()方法,從安全角度考慮,Applet沒(méi)有訪問(wèn)本地文件的權(quán)限。由于Applet是被瀏覽器執(zhí)行的,所以Applet不需要一個(gè)main()方法。實(shí)際上,除了Java Application之外,所有其它Java應(yīng)用都不需要一個(gè)main()方法。
(三)服務(wù)器端Java小程序 (Servlet)
Servlet也是一個(gè)Java類,和Applet形成對(duì)比,Servlet是運(yùn)行于服務(wù)器端的Java小程序,而且Servlet需要一個(gè)單獨(dú)的Web服務(wù)器(如Tomcat)做容器。除此之外,Servlet中用到的一些類(如HttpServlet)并不包含在J2SE API中,所以需要將Servlet.jar(在Tomcat的common\lib文件夾下)加到環(huán)境變量中去。下面是一個(gè)簡(jiǎn)單的Servlet例子:
public class Myservlet extends HttpServlet{ public void doGet(HttpServletRequest request,HttpServletResponse response){try{response.setContentType("text/html");PrintWriter out=response.getWriter();out.println("");out.println("");out.println("Hello world");out.println("");out.println("");}catch(IOException e){}}}
將這個(gè)Class文件編譯后放至Tomcat\webapps\examples\WEB-INF\classes下,然后在瀏覽器地址欄里輸入http://127.0.0.1:8080/examples/servlet/Myservlet即可看到 Hello world出現(xiàn)在瀏覽器中。
(四)Java Server Page (JSP)
同Servlet相似的是,JSP運(yùn)行于Web服務(wù)器端,并且也需要Tomcat之類的容器。不同的是,由于JSP是將Java代碼嵌在html標(biāo)記里(同ASP一樣用),JSP的界面設(shè)計(jì)同后臺(tái)開(kāi)發(fā)人員的工作可以有效分離。可以想像讓開(kāi)發(fā)人員用Servlet寫一個(gè)花捎的Web頁(yè)面有多困難,所以JSP+Servlet混合Web應(yīng)用是比較理想的選擇。
看起來(lái)JSP同ASP的實(shí)現(xiàn)機(jī)制大同小異,其實(shí)也存在著本質(zhì)的區(qū)別。所有的ASP頁(yè)面都是解釋運(yùn)行的,而JSP頁(yè)在第一次被請(qǐng)求時(shí)會(huì)被編譯,再以后的客戶請(qǐng)求都是直接運(yùn)行服務(wù)器上的.class文件(在Tomcat的Work文件夾下),所以JSP要比ASP速度上快許多。
(五)Java Beans
Java Bean 是可復(fù)用的組件,對(duì)Java Bean并沒(méi)有嚴(yán)格的規(guī)范,理論上講,任何一個(gè)Java類都可以是一個(gè)Bean。但通常情況下,由于Java Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java Bean應(yīng)具有一個(gè)無(wú)參的構(gòu)造器,另外,通常Java Bean還要實(shí)現(xiàn)Serializable接口用于實(shí)現(xiàn)Bean的持久性。
(六)Enterprise Java Beans (EJB)
Java Bean實(shí)際上相當(dāng)于微軟COM模型中的本地進(jìn)程內(nèi)COM組件,它是不能被跨進(jìn)程訪問(wèn)的。Enterprise Java Bean 相當(dāng)于DCOM,即分布式組件。它是基于Java的遠(yuǎn)程方法調(diào)用(RMI)技術(shù)的,所以EJB可以被遠(yuǎn)程訪問(wèn)(跨進(jìn)程、跨計(jì)算機(jī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問(wèn)真正的EJB組件,而是通過(guò)其容器訪問(wèn)。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過(guò)容器來(lái)訪問(wèn)真正的EJB組件。
這種模型很像COM+管理器,其實(shí)EJB容器正是起到COM+管理器的作用,只是EJB組件相對(duì)COM組件來(lái)說(shuō)更易用、更安全。
總的說(shuō)來(lái),Java作為面象對(duì)象技術(shù)的一個(gè)代表,在當(dāng)今商業(yè)應(yīng)用中更容易開(kāi)發(fā)出高效的、多層的分布式應(yīng)用程序,而且,由于Java技術(shù)有很強(qiáng)的健壯性和易用性,加上同UML應(yīng)用的結(jié)合,開(kāi)發(fā)一個(gè)商業(yè)應(yīng)用軟件的周期會(huì)大大縮短,所以Java會(huì)有不錯(cuò)的前景。
------------------