千呼萬喚始出來
總算發布了
現在可以去下載囉
這應該是有史以來java跨的最大一步吧
這不只是library大增
整個語言也改頭換面
一定要趕快抓下來玩他一玩
請到這邊下載
http://java.sun.com

最近好像都在摸這個
因為對c++越來越陌生
所以就選擇拿MFC來磨練一下自己
以前對MFC最排斥的就是那些討厭的Macro
還有一大堆記不起來的template method或是Message Handler..
但是對VC比較熟了以後發現原來這些東西都可以自動幫你產生
template method透過class wizard的overload
Message Handler透過class wizard的event
都可以輕鬆幫你建出空殼
再來就是對windows sdk不甚了解
虧我之前還修過視窗程式設計呢
結果都忘了差不多了 真愧對老師... orz
不過寫一寫就大概有感覺了
真的是熟能生巧
以前不知道為什麼很排斥寫windows程式
現在好像越來越有感覺了
但是說真的
寫視窗程式用c#或是java來寫真的是簡單多了
真不知道我在犯賤什麼 還跑回來寫這個快過時的MFC..XD
但是從MFC tutorial一步一步寫上來也挺有成就感的
忽然想請以前學java的時候看O'reilly java example in a nutshell的回憶
萬事起頭難 但是一跨過剛開始的門檻
就發現裡面還有很多很好玩的東西
就跟小朋友看到新事物一樣充滿好奇..^^
怎麼越講越遠了
總之
MFC搭配VC來寫真的不難寫
甚至我覺得開發速度還真的挺快的
但是我挺不喜歡那種跟IDE綁死的東西
像我當初學C#也都是直接用Ultraedit + .NET Framework SDK在學的
學的也挺快的
MFC剛開始也想這樣寫
但是後來發現這個是非常瘋狂的想法 根本不可能
就連用AppWizard建立出MFC空殼後
之後全部用VC的文字編輯器硬寫也很難
還是得配合VC的其他工具如Class Wizard這種東西才能有足夠的基本開發速度
但這樣的結果是很容易造成開發者知其然而不知其所以然的後果
以我的個性我會希望對每一個細節的原理都搞懂
還好細節部分MFC深入淺出還接待的滿清楚的
但是這些細節真的要寫過MFC才有感覺
最近是在寫一個Java Class Browser拿來當作練習
我是直接拿Code Project上的WTL的範例來改的
現在已經把他改成MFC版的^^
小弟的第一個MFC陋作
功能還非常陽春
祇是拿來練習而已
以後希望能夠繼續加強功能
程式連結
好久沒有寫blog囉
冷了一個月了..T_T
前一陣子比趨勢
最近又在打混
唯一有做事情的大概就是研究一下windows platform sdk吧
一個我好久沒有接觸的東西..
因為需要所以實作一個blocking queue
也就是應用producer-consumer這個pattern
沒想到java那麼簡單可以做到的事情跑到windows上就變成那麼困難
我定義了一個BlockingQueue的class
裡面有三個method
enqueue dequeue peek
enqueue是塞資料到queue
dequeue跟peek都是取資料
前者是blocking等到有資料
後者是不管有沒有都會馬上回傳
定義如下
//queue.h
#ifndef queue_h
#define queue_h
#include <windows.h>
#include <queue>
#include <assert.h>
using namespace std;
typedef struct _QueueItem{
int x;
int y;
} QueueItem;
class CBlockingQueue{
private:
queue<QueueItem> m_queue;
HANDLE m_mtx;
HANDLE m_evtAvail;
public:
CBlockingQueue();
virtual ~CBlockingQueue();
void enqueue(const QueueItem&);
BOOL dequeue(QueueItem*);
BOOL peek(QueueItem*);
};
#endif
實作的關鍵在於使用mutex跟event
mutex是一個物件 他只允許同時只能有一個thread擁有這個物件
它透過CreateMutex來產生
WaitForSingleObject或WaitForMultipleObjects來取得這個mutex
而ReleaseMutex來釋放
透過他我門能夠保證我們放入跟取出queue的動作是同時只有一個thread在執行
但是這還不夠
在producer-consumer pattern中
當consumer等不到東西時(queue size = 0)
會靜靜得等producer放東西進來的事件發生
這時候我們就要使用event這個物件
event的狀態可能是set或是unset
我門可以用SetEvent跟ResetEvent來設定他的狀態
同樣的 我門可以使用WaitForSingleObject或WaitForMultipleObjects
來等待這個event被set
所以在以下的程式裡
當enqueue放東西進來時
我門就把m_evtAvail這個event設為set
代表queue裡還有東西
而dequeue時就可以等待m_evtAvail設為set
則透過peek這個method去取得資料
值得注意的是...
在dequeue當中
當event被設為set並不保證peek一定會取得資料
因為可能在此同時也有另一個consumer也取得event被set的通知
而搶先一步去取得資料
所以我們在enqueue中有一個while loop
來保證真的取得資料時候才真正回傳
以下是這部分實作的程式碼
//queue.cpp
#include "stdafx.h"
#include "queue.h"
CBlockingQueue::CBlockingQueue(){
m_mtx = ::CreateMutex(NULL, FALSE, NULL);
assert(m_mtx != NULL);
m_evtAvail = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(m_evtAvail != NULL);
}
CBlockingQueue::~CBlockingQueue(){
if (NULL != m_mtx)
::CloseHandle(m_mtx);
if (NULL != m_evtAvail)
::CloseHandle(m_evtAvail);
}
void CBlockingQueue::enqueue(const QueueItem& item){
DWORD dwWaitResult;
//acquire mutex
dwWaitResult = WaitForSingleObject(m_mtx, INFINITE);
m_queue.push(item);
::SetEvent(m_evtAvail);
//release mutex
ReleaseMutex(m_mtx);
}
BOOL CBlockingQueue::dequeue(QueueItem *item){
DWORD dwWaitResult;
BOOL timeout = FALSE;
BOOL done = FALSE;
while(!done && !timeout){
//printf("dequeue:wait event\n");
dwWaitResult = ::WaitForSingleObject(m_evtAvail, INFINITE);
//
switch(dwWaitResult){
case WAIT_OBJECT_0:
done = peek(item);
break;
case WAIT_TIMEOUT:
timeout = TRUE;
printf("timeout event\n");
break;
case WAIT_ABANDONED:
timeout = TRUE;
printf("abandoned event\n");
break;
default:
;
}
}
return done;
}
BOOL CBlockingQueue::peek(QueueItem *item){
DWORD dwWaitResult;
BOOL done = false;
dwWaitResult = WaitForSingleObject(m_mtx, INFINITE);
switch(dwWaitResult){
case WAIT_OBJECT_0:
if(m_queue.size() > 0){
*item = m_queue.front();
m_queue.pop();
done = TRUE;
}else{
::ResetEvent(m_evtAvail);
}
break;
case WAIT_TIMEOUT:
printf("timeout mutex\n");
break;
case WAIT_ABANDONED:
printf("abandoned mutex\n");
break;
default:
;
}
ReleaseMutex(m_mtx);
return done;
}
記得在visual studio中編譯時
把Runtime程式庫這邊改成multithread的選項(多執行緒或多執行緒偵錯)
它會把/ML(/MLd)的參數改成/MT(/MTd)
這樣一些c的library才會使用正確.. 如printf, strtok等
以下是一個範例的main
// BlockingQueue.cpp
#include "stdafx.h"
#include "queue.h"
CBlockingQueue g_queue;
DWORD WINAPI ProducerFunc(LPVOID lpParameter){
char* name = (char*)lpParameter;
QueueItem item;
for(int i=1; i<100; i++){
item.x = 0; item.y = i;
g_queue.enqueue(item);
printf("[%s](%d,%d)\n", name, item.x, item.y);
::Sleep(rand() % 1000);
}
return 0;
}
DWORD WINAPI ConsumerFunc(LPVOID lpParameter){
char* name = (char*)lpParameter;
QueueItem item;
BOOL done;
while(TRUE){
item.x = 0; item.y = 0;
done = g_queue.dequeue(&item);
//if(done){
printf("[%s](%d,%d)\n", name, item.x, item.y);
//}
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
srand( (unsigned)time( NULL ) );
//create producers
DWORD dwThreadId;
HANDLE hThread;
hThread = CreateThread(NULL, 0, ProducerFunc, "producer", 0, &dwThreadId);
hThread = CreateThread(NULL, 0, ConsumerFunc, "consumer", 0, &dwThreadId);
::Sleep(1000000000);
return 0;
}
原本JDK1.5要加進asynchonous io這個feature的
後來就不見了..有點小失望
不過今天在TTS看到IBM的alphawork有一個在java平台上實作aio的project
馬上就抓回來觀賞一下..^^
在談論這個project之前 先介紹一下什麼是aio
在最早期的java都是使用blocking io
也就是每個read/write都是blocking operation
這些method都會等到真的讀到或是寫到才會return
blocking io的好處是程式好寫 邏輯也比較直覺
但是缺點是如果有較多個連線時
必須要使用multithread的架構
但是thread一多就會使得整體效能變差
在jdk1.4時 多了一個java.nio這個package
稱之為new io
裡面題供一個feature是non-blocking IO
在這種模式中... 呼叫read/write都保證不會被block
也就是有資料可以讀.. 沒有就不讀
絕對不會卡住
但是直接使用會造成busy loop
所通常non-blocking io會搭配multiplexing io的使用
也就是select這東西
首先每個channel必須要跟selector註冊自己感興趣的operation
(如read/write/connect/accept)
之後selector做select時
他會觀察是不是有任何一個channel他所感興趣的operation已經available了
如果有任何一個available時
這個select就會return
之後 我們就可以根據SelectionKey找到該channel
並且做對應的operation
這種編程模式可以使用single thread就可完成
當然就不會有blocking io的太多thread的缺點
但是相對的就不好寫 邏輯很不容易懂
因此還有另一種io的編程模式asynchronous io的出現
aio這種寫作思維是我乾脆就告訴系統我要做哪一個operation(譬如read)
然後系統做好之後再通知我就好
這種委託系統幫你做某個operation就是一種asynchronous的概念
而要知道operation是否完成有三種方法
1. Blocking
站著等別人幫你做完
2. Poll
問說好了沒... 沒有的話就回去做自己的事情
等再過一段時間再去問好了沒...
3. Call-back
你好了再告訴我
在blocking或是non-blocking的模式中
所做的operation都是synchrnous的
也就是return就代表這個operation完成
只是不一定會讀到資料而已
而在aio中
operation return時代表我已經委託這個工作給別人
但不代表這個operation已經完成
alphawork這個專案叫做aio4j
看了一下感覺很不錯
他是使用POSA2:Wrapper Facade這個pattern
也就是底層是使用各個OS的aio實作
上層是用一個共同的API來包裝底層時做細節
所以兼具了跨平台跟效能特性
它提供的OS有WIN32 Linux32 AIX32 AIX64
使用的時候必須把對應平台的library放到正確的位置
使用上也不難
以下是一個例子
//打開一個async socket
AsyncSocketChannel myChannel = AsyncSocketChannel.open();
//非同步的建立連線 回傳一個Future (可以視為一個未來的結果)
IConnectionFuture connectionFuture =
myChannel.connect(new InetSocketAddress(serverhost,serverport));
//等到連線結束 (blocking wait)
connectionFuture.complete();
//讀一筆資料
IAsyncFuture readFuture = myChannel.read(byteBuffer);
//如果讀完則這個call會return, 並且回傳有多少個byte被read
int bytesRead = readFuture.getByteCount();
至於Future的概念
在aio4j中所有的operation都是會回傳一個future
這個叫做Future Pattern..
我們必須透過這個future去取得這個operation的結果
不管是blocking, poll, 或是設一個call-back listener
另外aio4j跟nio一樣
提供了scatter跟gatter io的概念
細節就不多講
以下是一個範例
AsyncSocketChannelHelper myHelper = AsyncSocketChannelHelper(myChannel); IAsyncMultiFuture readFuture = myHelper.read(byteBufsArray); ...
其實我覺得wiki真的可以做很多事情耶
像之前有談到的把javadoc中文化
我覺得也可以用wiki的方式來完成
可以先用一個原始版的javadoc當作內容
有興趣的人可以選一個Class甚至一個method來中文化
這樣一步一步的中文化
集大家的力量
我相信要把javadoc中文化並非難事..^^l

Velocity提供了另一種思維來撰寫Web應用程式,但是要把繼有的Jsp-based的專案轉移到Velocity卻步是一件輕鬆的事情。Jason Briggs這篇文章提出如何以較輕鬆的方式達到此目的。
http://www.cis.nctu.edu.tw/~gis91530/articles/velocity/velocity.html
Features:
1. Ease of programming
2. Automatically reload
Implementation
1. compile就用com.sun.tools.javac.Main
這裡有參考方法
2. jspc就用jasper
包在tomcat當中
3. reload的判斷透過file的last modified
source放在WEB-INF/src此目錄
4. 用URLClassLoader來做dynamic class loading
這裡有參考方法
我希望效率跟功能大不在考量當中
而以開發容易為重點
可能暑假的時候開始動工吧..
不知道有沒有人也有興趣的..^^
20040311_Introduction_Of_DOIT_Platform.ppt
20040407_DOIT_A_MMOG_Middleware_Solution.ppt
這是我的研究所論文最近的一份投影片
大概介紹了一下整個架構還有實作上的概觀
有興趣研究的朋友也可以跟我要source
但是目前還沒有想要完全接受public download
DOIT Platform目前有以下這些features:
下一版會把NPC的部分也加進去
當然NPC也會支援region migration囉..^^
.net根本就是有參考java嘛!!!
先講了一下java的Hashtable的歷史
觀察一下api會發現
contains
containsKey
containsValue
這三個method
前兩個都是測試一個key有沒有存在於hashtable
很奇怪吧 兩個相同的功能的method不會有點多餘嘛
這是因為hashtable早在1.0就存在了
而contains此method就已經存在(另兩個沒有)
但是到了1.2.. J2SE中出現了一個叫collection framework的東西
在其中hashtable為了要實作新提出的Map這個interface
所以多實作了一些method
包括containsKey跟containsValue這兩個method
當然為了向下相容.. 所以contains自然還是保留在內
才會出現contains跟containsKey同時存在也語意相同的兩個method
話鋒一轉
來看.net的Hashtable
啥~~ 裡面竟然也有contains/containsKey/containsValue
而且contains跟containsKey的功能也一樣..
好笑吧
在沒有向下相容的需求下
怎麼會出現兩個語意相同的method呢
這不是參考java是什麼.. ^^|||
在ciyawasay : swanky & shumi的blog中
用java寫hanoi tower
當然我也要不甘示弱
用scheme寫一個hanoi tower
程式碼如下
(define hanoi
(lambda (n a b c)
(let loop ((n n) (a a) (b b) (c c) (acc '()))
(if (= 1 n)
(cons (cons a b) acc)
(loop (1- n) a c b
(cons (cons a b) (loop (1- n) c b a acc)))))))
輸入
(hanoi 4 'a 'b 'c)
輸出
((a . c)
(a . b)
(c . b)
(a . c)
(b . a)
(b . c)
(a . c)
(a . b)
(c . b)
(c . a)
(b . a)
(c . b)
(a . c)
(a . b)
(c . b))
還不錯吧....^^y
http://wwws.sun.com/software/looking_glass/
只能說太屌了吧
看他的demo之後真的是印象深刻
如果效能真的很好的話
那其他桌面管理系統大概都要哭了吧
而且可以開發更多另類的應用程式
很難想像這是java寫的
實在太神奇了
此篇是延續Groovy PartI。同樣的,也是節錄這篇的內容Groovy - Scripting for Java。
Groovy Ranges
Range是由".."或是"..."產生
定義如下
3..7 產生一個range從 3 到 7
3...7 產生一個range從 3 到 6
"A".."D" 產生一個range從 "A" 到 "D"
"A"..."D" 產生一個range從 "A" 到 "C"
Groovy Switch
Groovy中Switch支援個種物件,包括Class、List、Range、Pattern。
case是透過isCase這個method來做判斷。而很groovy提供許多overrloaded的isCase。
除非overloaded特別的型態,isCase是用equals此method。如果case後面是
接一個class,則使用instanceof此operator。而isCase也可以在我們所定義
的class中override掉。
以下是各種type的例子
switch (x) {
case 'Mark':
println "got my name"
break
case 3..7:
println 'got a number in the range 3 to 7 inclusive'
break
case ['Moe', 'Larry', 'Curly']:
println 'got a Stooge name'
break
case java.util.Date:
println 'got a Date object'
break
case ~"\\d{5}":
println 'got a zip code'
break
default:
println "got unexpected value ${x}"
}
Groovy Looping
有提供六種loop
for
for (i in 1..1000) { println i }
i = 1
while (i <= 1000) { println i; i++ }
(1..1000).each { println it }
1000.times { println it }
// values go from 0 to 999
1.upto(1000) { println it }
1.step(1001, 1) { println it }
// values go from 1 to 1000;
// stopping one before the parameter value
List/Map/String Methods That Accept a Closure
List Map String都支援Closure當作參數
each
它會把collection中的每一個元素或是String的每一個字元都跑一遍。
並且都丟入closure執行。如下
[5, 9, 1, 6].each {x | println x} [5, 9, 1, 6].each {println it} doubles = [5, 9, 1, 6].collect {x | x * 2} //回傳[10, 18, 2, 12]
find
取得collection中第一個符合closure中的元素。
[5, 9, 1, 6].find {x | x > 5} //回傳9 [5, 9, 1, 6].findAll {x | x > 5} // 回傳[9, 6]
every
回傳是否所有的collection的item都符合closure的條件。
[5, 9, 1, 6].every {x | x < 7} // 回傳false [5, 9, 1, 6].any {x | x < 7} //回傳true
factorial = [2, 3, 4, 5].inject(1) {
prevResult, x | prevResult * x
}
File I/O
從檔案一行一行讀進來 (兩種選擇)
以下的"..."都代表省略的code
file = new File('myFile.txt')
file.eachLine { println it }
lineList = file.readLines()
file = new File('myFile.txt')
file.eachByte { println it }
byteList = file.readBytes()
dir = new File('directory-path')
dir.eachFile { file | . . . }
file.withReader { reader | . . . }
reader.withReader { reader | . . . }
inputStream.withStream { is | . . . }
file.withWriter { writer | . . . }
file.withPrintWriter { pw | . . . }
file.withOutputStream { os | . . . }
writer.withWriter { writer | . . . }
outputStream.withStream { os | . . . }
Overloaded Left Shift Operator
連接字串(To append strings)
s = 'foo'
s = s << 'bar'
sb = new StringBuffer('foo')
sb << 'bar'
colors = ['red', 'green']
colors << 'blue'
w = new File('myFile.txt').newWriter()
w << 'foo' << 'bar'
w.close()
class Team {
String name
Person coach
players = []
}
class Person {
String name
}
p = new Person(name:'Mike Martz')
t = new Team(name:'Rams', coach:p)
// The next line prints the same as team.getCoach().getName().
println "coach = ${t.coach.name}"
t = new Team(name:'Blues')
// The next line returns null,
// it doesn't throw NullPointerException.
println "coach = ${t->coach->name}"
// The next line throws NullPointerException.
println "coach = ${t.coach.name}"
GString.class.methods.each { it.name }
Catching Unimplemented Methods
類別可以去捕捉所有沒有實作的類別,例子:
o = new CatchCall()
// 這行會印出 "unknown method Mark called with [19]".
println o.foo("Mark", 19)
class CatchCall {
invokeMethod(String name, Object args) {
try {
return metaClass.invokeMethod(this, name, args)
} catch (MissingMethodException e) {
// Can insert logic here to deal with certain
// method names and arguments in special ways.
return "unknown method ${name} called with ${args}"
}
}
}
Groovy Markup
Groovy Markup使用了剛提到的invokeMethod這個method去把所有沒定義
的method轉換成"nodes". 傳進的參數會被視為nodes的屬性。而method後的
closure會被視為nodes的內容。有非常多的使用方式如,
建造簡單的Data Structure tree. (NodeBuilder)
建造Dom Tree. (DomBuilder)
產生SAX Event. (SaxBuiulder)
產生HTML或XML (MakeupBuilder)
執行AntTask (AntBuilder)
產生Swing的GUI (SwingBuilder)
Generating HTML
以下是透過MarkupBuilder產生HTML的範例
import groovy.xml.MarkupBuilder
mb = new MarkupBuilder()
mb.html() {
head() {
title("This is my title.")
}
body() {
p("This is my paragraph.")
}
}
println mb
產生的HTML
<html>
<head>
<title>This is my title.</title>
</head>
<body>
<p>This is my paragraph.</p>
</body>
</html>
import groovy.xml.MarkupBuilder;
mb = new MarkupBuilder()
mb.autos() {
auto(year:2001, color:'blue') {
make('Toyota')
model('Camry')
}
}
println mb
<autos>
<auto year='2001' color='blue'>
<make>Toyota</make>
<model>Camry</model>
</auto>
</autos>
Groovy SQL
Groovy讓使用SQL更容易,以下是範例
import groovy.sql.Sql
dbURL = 'jdbc:odbc:MusicCollection'
jdbcDriver = 'sun.jdbc.odbc.JdbcOdbcDriver'
sql = Sql.newInstance(dbURL, jdbcDriver)
sql.eachRow('select * from Artists') {
println it.Name
}
Groovlets
Groovlet可以拿來取代Servlet或JSP,他提供以下幾種隱性變數。
out - 等同HttpServletResponse.getWriter()
request - the HttpServletRequest
session - the HttpSession
它使用"Here Doc"的方式來產生文件
out.println <<<EOS
<html>
<head>
<title>My Simple Groovlet</title>
</head>
<body>
<h1>My Simple Groovlet</h1>
<p>Today is ${new java.util.Date()}.</p>
</body>
</html>
EOS
<?xml version="1.0"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Groovy</servlet-name>
<servlet-class>groovy.servlet.GroovyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Groovy</servlet-name>
<url-pattern>*.groovy</url-pattern>
</servlet-mapping>
</web-app>
Groovy Language已經加入JSR 241了,他是完全貼近Java Platform的script language
以下是節錄Groovy - Scripting for Java
希望大家可以初步的了解
Introduction
Groovy是設計用來以精簡快速有趣的方式來在Java平台上處理事務,
並且把類似Python Ruby等的強大功能帶到Java的世界裡。
Groovy可以被直譯,也可以被編譯成bytecode,
所以Groovy可以取得跟Java差不多的效能,
這是跟其他script lanaguage是較不一樣的。
Downloading and Installing Groovy
要下載Groovy,請依下列步驟
點最上面瀏覽列的"download"
點"this site"的連結
選擇要下載的版本
安裝Groovy,請依下列步驟
解開下載檔
把GROOVY_HOME環境變數設到解壓縮的位置
把$GROOVY_HOME/bin (UNIX) 或
%GROOVY_HOME%\bin (Windows)放到PATH的環境變數裡
Running Groovy
分四種
Interactive Shell
Interactive Swing Console
Script File Execution
Compiled Script Execution
Some Syntax Details
目標是能夠支援所有的JAVA語法,但是目前還沒完全達到。
statement最後的分號是可有可無的
呼叫method旁邊的括號是可有可無的,只要不會造成ambiguous。但是constructor一定要有。
"return"也是可有可無的。只要最後一個statement有被執行,則他的值就代表回傳值。
Groovy的properties跟method預設皆是public,而非java的pacakge private。
在java.lang groovy.lang groovy.util都是預設被import。
Dynamic Typing
型態對所有varibles、properties、method/closure parameters和
method ruturn type都是可有可無的。它們都是在指定值給他們時才
會真正決定是什麼type。所有type都可以被使用,即使是primitive type。
當有需要時,型別轉換會自動發生在String、primitive type、
wrapper class之間。也因此我們可以把所有type都放在collection中。
Added Methods
Groovy加了一些method在標準的Java類別中,
(如java.lang.Object、java.lang.String)
可以參考http://groovy.codehaus.org/groovy-jdk.html
Groovy Strings
字串可以可以是單引號或是雙引號。當用說引號時,我們可以在
字串中內嵌一些運算式。如以下的例子
String toString() { "${name} is ${age} years old." }
s = " This string
spans three \"lines\"
and contains two newlines."
s = """ This string
spans three "lines"
and contains two newlines."""
s = <<<EOS
This string
spans three "lines"
and contains two newlines.
EOS
Regular Expressions (regex)
使用J2SE1.4的regular expressions,但是多了這三個opeartion
~"pattern" 產生一個Pattern物件且等同於Pattern.compile("pattern").
"text" =~ "pattern" 產生一個Matcher物件且等同於Pattern.compile("pattern").matcher("text").
"text" ==~ "pattern" 回傳true或false,等同於Pattern.compile("pattern").matcher("text").matches().
Groovy Scripts
Groovy scripts是用".groovy"為副檔名的groovy原始檔。他們可以
是不屬於某個class的鬆散statements,可以定義method或是class。
以下是例子
// These are loose statements.
println 'loose statement'
myMethod 'Mark', 19
println new MyClass(a1:'Running', a2:26.2)
// This is a method definition that
// is not associated with a class.
def myMethod(p1, p2) {
println "myMethod: p1=${p1}, p2=${p2}"
}
// This is a definition of a class that
// has two properties and one method.
class MyClass {
a1; a2
String toString() { "MyClass: a1=${a1}, a2=${a2}" }
}
Operator Overloading
Groovy允許某些部分的operator overloading,這些operator會對應到
某些method name,只要實作這些method在你的類別就可以用對應的
operator來呼叫這些method。
Comparison Operators
a == b maps to a.equals(b)
a != b maps to !a.equals(b)
a === b maps to a == b in Java
a <=> b maps to a.compareTo(b)
a > b maps to a.compareTo(b) > 0
a >= b maps to a.compareTo(b) >= 0
a < b maps to a.compareTo(b) < 0
a <= b maps to a.compareTo(b) <= 0
Other Operators
a + b maps to a.plus(b)
a - b maps to a.minus(b)
a * b maps to a.multiply(b)
a / b maps to a.divide(b)
a++ and ++a maps to a.increment(b)
a-- and --a maps to a.decrement(b)
a[b ] maps to a.get(b)
a[b ] = c maps to a.put(b, c)
Groovy Closures
Closure可以看成function,或是說程式的片段。他會被編譯成繼承於groovy.lang.Closure。
這個Class會有call這個method,透過它可以呼叫這個closure。closure用以下這種方法定義
{ comma-separated-parameter-list | statements }
例子
closure = { bill, tipPercentage | bill * tipPercentage / 100 }
tip = closure.call(25.19, 15)
tip = closure(25.19, 15) // equivalent to previous line
{ x | println x }
{ println it }
Groovy Beans
以下是一個Groovy Bean的例子
class Car {
String make
String model
}
但是背後事實上會是如此
public class Car {
private String make;
private String model;
public String getMake() {
return make;
}
public String getModel() {
return model;
}
public void setMake(String make) {
this.make = make;
}
public void setModel(String model) {
this.model = model;
}
}
myCar = new Car(make:'Toyota', model:'Camry')
Groovy Lists
Groovy list是java.util.ArrayList的物件,以下是使用List的例子
cars = [new Car(make:'Honda', model:'Odyssey'),
new Car(make:'Toyota', model:'Camry')]
println cars[1] // refers to Camry
for (car in cars) { println car } // invokes Car toString method
class Car {
make; model
String toString() { "Car: make=${make}, model=${model}" }
}
cars = []
cars.add car
cars << car
[1, 2, 3, 1].count(1) 會回傳2
list = [1, 2, 3].immutable()
list.add 4 // throws java.lang.UnsupportedOperationException
[1, 2, 3, 4].intersect([2, 4, 6]) returns [2, 4].
['one', 'two', 'three'].join('^') 會回傳 "one^two^three".
fruits = ['kiwi', 'strawberry', 'grape', 'banana']
// The next line returns [banana, grape, kiwi, strawberry].
sortedFruits = fruits.sort()
// The next line returns [kiwi, grape, banana, strawberry].
sortedFruits =
fruits.sort {l, r | return l.length() <=> r.length()}
[5, 9, 1, 6].min() 回傳 1
[5, 9, 1, 6].max() 回傳 9
[1, 2, 3].reverse() 回傳 [3, 2, 1]
[1, 2, 3] + [2, 3, 4] 回傳 [1, 2, 3, 2, 3, 4]
[1, 2, 3, 4] - [2, 4, 6] 回傳 [1, 3]
players = ['baseball':'Albert Pujols',
'golf':'Tiger Woods']
println players['golf'] // prints Tiger Woods
println players.golf // prints Tiger Woods
for (player in players) {
println "${player.value} plays ${player.key}"
}
// This has the same result as the previous loop.
players.each {player |
println "${player.value} plays ${player.key}"
}
players = [:]
以下幾篇是在Pyrasun - The Spille Blog 裡面的文章
對transaction有非常深入的探討
XA Exposed, Part I
XA Exposed, Part II
XA Exposed, Part III: The Implementor's Notebook
XA Exposed III.I
第一篇是針對Distributed transaction的簡介
還有2 Phase Commit (2PC)是如何協同合作的
第二篇是針對2PC commit中各個時間點如果有failure
要如何做recover做探討
第三篇是實作Transaction Manager的細節
最主要在Transaction Log的地方探討相當仔細
事實上我覺得如果只是J2EE application developer
看第一篇就很足夠了
而二三篇是給開發TM或是RM的人看的
其實JTA的角色有三個
第一個是Transaction Manager(TM)的開發者
事實上應該說是提供JTS(Java Transaction Manager)
第二個是Resouce Manager(RM)的提供者
他必須實作javax.transaction.xa.XAResouce
他一方面要聽TM的指示
另一方面要能確保底層resouce能達到ACID的原則
比較常見的RM有
jdbc中XAConnection取得的XAResouce
jms中XASession取得的XAResouce
jca中ManagedConnection取得的XAResouce
這些都可以加進global transaction中
第三個就是J2EE client
也就是我們所開發的需要支援distributed transaction的應用程式
他可以跟JTS或是application server要一個global transaction
並且把所有的XAResouce加進(enlist)這個transaction
之後分別對這些resouce做些需要transaction的動作
最後要commit的時候透過TM來完成2PC
在此要非常強調一點
不是所有的transaction都需要2PC
只有對需要同時對很多個transaction resouce做動作的時候才需要做2PC
例如說對很多的database同時做update
或是要支援JMS transaction跟database的update在同一個transaction中
這種需求才需要2PC
如果需求只是對一個資料庫做transaction
那請只需要用到jdbc中connection的transaction就好
不需要使用複雜的2PC也不需要用到JTA/JTS
Alibabar
他是一個IE的Plugin
我覺得很好用
下載網址如下
http://alf-li.tripod.com/c_alibabar.html
在MFC下是Document/View model
這應該算是一種delegation的表現吧
View <>--- Document
view把資料的來源都delegate到Document
而view要呈現時..去跟Document要資料就好
但是這會牽扯到一個問題...
對Document的操作.. 修正...可能有很多種方式
若放在Document裡面則這方面的邏輯就跟Document綁死
放View裡面就跟某個View綁死
(在MFC中...可以把MessageMap放在View或是Document)
所以我們就希望有一個Controller的東西把這部分的邏輯抽出來
由它去決定Document如何去修改
並且告知View怎麼去呈現(或是該去更新)
這就是MVC model的精神
但是MVC在web跟gui app會有些許不同
在gui下...
controller的存在方式是去跟view去註冊event lisener
當事件發生時去改變docuemnt的資料..
並通知view去update
在web下
controller去接收client來的request..
根據request的資料去產生document..
再丟給view端(如jsp)去做呈現
但是asp.net試圖用gui那套來處理web
所以要如何改變document的資料呢
關鍵在於"postback"..
它把document的資料postback到client的hidden field..
下次request會一起把這個state送過來
所以才能以gui的那種方式達到MVC的架構
好像還是很多人搞不清楚耶...
這篇是我po再programming版的
big o :Ο
通常會是來說明一個演算法的upper bound..
而O(f(n)) 代表此演算法所需花的時間最多為 k * f(n)
omega:Ω
通常會是用來說明一個問題的理論lower bound
而Ω(f(n))代表此問題至少需要時間 k * f(n) 才可以解決
theta:θ
當一個演算法的big O跟它所解決的問題的omega在同一個set裡面時
我們會說它是θ(f(n))
可以說明的是這個演算法很好
跟理論的lower bound完全一樣
但是這些符號不一定是用來表示時間的
也可以拿來描述空間的複雜度
只是初學演算法大部分都是拿時間來做分析而已
post在jsptw
目前先看這邊吧...
以後我會把我的文章都整理在我的網頁中的....^^
有寫過網路程式的人寫server的程式最常用的方法就是
Master/Slave threads這種寫法
也就是當有人連進來的時候
產生一個thread去專職服務該連線
我也不知道這是什麼pattern..
不過是大家最常用的
到了j2se1.4的時候
new i/o加進了j2se...
裡面包跨了non-blocking I/O以及Selecter這種概念
在這個架構中..
socket(更明確的說是SelectableChannel)
要跟selector去註冊要處理的operation.. (read/write/accpet/connect)
而selector會不斷的去呼叫一個select的blocking method
當有一個以上註冊在此selector的channel operation是可以動作時
則會此method會返回
之後就一個一個去呼叫這些operation
這個pattern在POSA2叫做Reactor pattern
再到了j2se1.5聽說加進了aio (Aysnchronous I/O)
這個可能有人用過POSIX的aio這個library...
它的行為很像signal handler的機制
在signal handler中..
我們針對某個signal去註冊一個callback function
當signal產生時..則會回呼此function去處理
同樣的aio的概念就是去註冊handler到read/write等的operation
當read/write變成available的時候則回呼handler
這個在POSA2叫做Proactor pattern
現在我想討論的是
什麼情況該要用什麼pattern比較好
比較肯定的是
在第一個pattern中比較適合簡單..
同時連線數目少的server...
如此雖然每個connection要一個thread處理..
但人數不多的化thread的各數還算可以接受
但是人數多的時候
可能就要用nio的selector了
那aio呢
non-blocking io跟asynchronous io分別在哪些時機比較合適
有沒有人有經驗的???
哈哈...還不錯玩啦
並沒有想像中那麼困難
剛開始雖然有點小不習慣
不過用久了 掌握度高了就比較得心應手
DirectX是一個很大的Framework
幾乎所有多媒體的東西都有包進來
最具代表性的當然是Direct3D
做的是3D rendering的東西
再來還有
DirectInput: 輸入裝置的東興,如搖桿 滑鼠
DirectPlay: 網路的部分... p2p client/server
DirectMusic: 音樂部分
DirectSound: 音效部分
DirectShow: streaming media的部分
現在的我只會做一些簡單的繪圖而已...XD
還有很多東西沒有用到
想到就興奮..XD
本實驗室三隊參加mobilehero比賽
分別獲得技術組第一名 第三名
應用組第二名
獎金總額160萬....
XD
可惜我沒參加...~><~
http://objectclub.esm.co.jp/Jude/該有的功能都有
而且剛剛玩玩看也覺得真的不錯用
而且可以全選之後copy到word之上 或是photoshop之上
省下存成檔案的麻煩
大家試了之後發表一下感想吧
http://ettercap.sourceforge.net/
HTTPS跟SSH1都難逃一死
而且他可以跑在switched lan下
用的是ARP meet in the middle的方式
這種東西放在sf.net上實在太可怕了
0. 前言
前面一篇介紹了JMX,此篇將以Log4j以及MX4J這個組合讓大家來感覺一下JMX是什麼樣的東西。可以做些什麼事情。
1. Log4j
首先介紹一下這兩個OpenSource project。Log4j大家應該比較耳熟能詳,他是一個log的utility。此project是掛在apache jakarta之上。使用起來非常簡單,在log4j中最重要的有三個元素。
logger: log的一個基本元件。可以提供不同層級的logging,如fatal, error, warn, info, debug..。
appender: appender是logger的log所要輸出的位置,最簡單的就是Console,另外也可能是file, network,..。
layout: Appender輸出時,所呈現的layout。
2. MX4J
MX4J是一個JMX的implemenation,目前是實作JMX1.1的版本。目前版本的MX4J題供了以下幾點功能:
透過XDoclet自動產生StandardMBean的管理介面
HTTP adaptor (also over SSL)
RMI over JRMP adaptor (also over SSL)
RMI over IIOP adaptor
StandardMBeanProxy以容易的方式呼叫Standard MBeans
AbstractDynamicMBean以容易的開發Dynamic MBeans
3. Unmanaged Application
以下是一個使用log4j但是還沒有加上JMX的程式
//Main.java
import org.apache.log4j.*;
public class Main implements Runnable{
private static final Logger log = Logger.getLogger(Main.class);
public Main(){
try{
while(true){
log.debug("is pop here?");
Thread.sleep(1000);
log.info("yes.. he is here!!");
Thread.sleep(1000);
log.warn("pop is singing!!");
Thread.sleep(1000);
log.error("pop is crazy...!!");
Thread.sleep(1000);
log.fatal("pop is popping");
Thread.sleep(1000);
}
}catch(InterruptedException e){
//ignore
}
}
public static void main(String[] args){
new Main();
}
}
log4j.rootLogger=WARN, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.SimpleLayout
4. 加上JMX,並且使用MX4J的Http Adaptor
承襲上面的程式碼,加上了粗體字的部分:
import javax.management.*;
import org.apache.log4j.*;
import org.apache.log4j.jmx.*;
import mx4j.adaptor.http.HttpAdaptor;
public class Main implements Runnable{
private static final Logger log = Logger.getLogger(Main.class);
public Main(){
try{
new Thread(this).start();
while(true){
log.debug("is pop here?");
Thread.sleep(1000);
log.info("yes.. he is here!!");
Thread.sleep(1000);
log.warn("pop is singing!!");
Thread.sleep(1000);
log.error("pop is crazy...!!");
Thread.sleep(1000);
log.fatal("pop is popping");
Thread.sleep(1000);
}
}catch(InterruptedException e){
//ignore
}
}
public void run(){
try{
MBeanServer server = MBeanServerFactory.createMBeanServer();
ObjectName hdmName = new ObjectName("log4j:hiearchy=default");
ObjectName name = new ObjectName("Server:name=HttpAdaptor");
ObjectName processorName = new ObjectName("Server:name=XSLTProcessor");
server.createMBean("org.apache.log4j.jmx.HierarchyDynamicMBean", hdmName, null);
server.createMBean("mx4j.adaptor.http.HttpAdaptor", name, null);
server.createMBean("mx4j.adaptor.http.XSLTProcessor", processorName, null);
server.setAttribute(name, new Attribute("ProcessorName", processorName));
server.setAttribute(name, new Attribute("Port", new Integer(8082)));
server.invoke(name, "start", null, null);
}catch(Exception e){
log.error("Can't register MBean to MBean server", e);
System.exit(-1);
}
}
public static void main(String[] args){
new Main();
}
}
產生一個MBean Server。
註冊一個Http Adaptor,把MBean的介面轉成http protocol。而比較特別的是此Http Adaptor是產生XML,而非HTML。
註冊一個XSLT Processor。由於Http Adator產生的是xml,若我們不註冊此service的話,我們用brower看到的將是XML的格式。而此service是把Http Adaptor輸出的XML轉換成HTML,則可透過brower直接作操作。
註冊HierarchyDynamicMBean,此MBean會把所有的logger、appender、layout一併註冊到MBean Server中。
5. 執行程式
可以在此抓下檔案
一開始我們執行這個程式
如我們所願,只印出WARN以上的LEVEL的log

之後我們連到http://localhost:8082/的位置,也就是我們註冊的Http Adaptor的位址。
我們會看到下面的網頁,感動吧...

我們點入[Domain: log4j]>[log4j:logger=root]
找到[Attributes]>[priority] 把值改成FATAL
如下圖所示

回到我們原本的程式去看
果然只出現了Fatal... 萬歲...^^y

0.前言
隨著軟體需求越來越複雜,軟體通常不會從無到有重新打造。通常我們的程式會架構在一個middleware之上,在上面寫一些應用程式而使我們的程式享有middleware所提供的system service。但是隨著架構越來越複雜,元件越來越多,所開發的應用程式也越來越難管理。有些middleware會提供一些管理程式來管理每個元件,但是一方面管理介面不是最重要的考量,所以介面通常做的不是非常的好用;另一方面,我們自己開發的應用程式也無法或是很難在他們的管理程式中被管理。再者,每個元件開發的程式開發者必須撰寫自己的元件以外,還要另外開發管理介面,這些功夫導致很多程式都不能被重複利用。因此,管理這個領域的標準化就變成非常重要。而這篇介紹的JMX - Java Management eXtension就是針對這個需求因應而生的。
1.簡介
JMX的官方網站在這,他是在JSR#3所定出來的標準。
在JMX中,他把管理這個領域分成三個層級。由下面這張圖可以看的很清楚:

待續....
網址在這
MTMacro可以定義一些macro來幫助我們把這些macro轉換成html格式
最常見的就是笑臉...還有一些container tag..
如[code]... [/code] [b]...[/b] 等等....
雖然我已經用了quickcode
但是感覺陽春了一點
改天來研究研究這個plugin
以下是個範例...
public class Main{
public static void main(String[] args){
System.out.println("helloworld");
}
}
不過不知道為什麼..
用IE跑起來常常會看不到
這應該是IE的問題
因為我用scrollbar上下拉一下就出現了
裝quickcode還滿簡單的
就連到那個網址抓下.zip檔後
解開來
把.pl檔放在movable type的plugins目錄下就可以了...
而要用的時候要注意一下
在貼文章的時候
記得要把Text Formatting改成quickcode...
才會有這些效果
另外我也改了一些樣式
剛開始他沒有套CSS
所以要去改那個.pl檔
在處理"code"的tag上 在<pre>的tag加上<pre class="code>
之後在去改css就可以了
最後面加上一個.code 的class
再加上這一塊 (這是我改的..)
.code{
padding-right: 0.5em;
margin-top: 1em;
padding-left: 0.5em;
font-size: 8pt;
margin-bottom: 1em;
padding-bottom: 0.5em;
margin-left: 0pt;
padding-top: 0.5em;
font-family: Courier New;
border:1px solid #CCC;
background-color: #FFFFCC;
color:#666;
}
明天來裝這個plugin
網址在這
感謝JiaYun的題供
不過今天太晚了
明天再來裝吧..:D