blog.Ring.idv.tw

Java

Jetty - Java HTTP Servlet Server

.2008-12-15 新增Apache Commons DBCP範例

大約六、七年前剛開始初學Web Application的時候~ 那時常聽到的是TomcatResin~ 至於Jetty... 嗯~ 我聞不見其名...XD

Jetty.是一個100%以Java撰寫而成並開放源碼的HTTP Server & Servlet Container~ 從三年前的「Jetty vs. Tomcat vs. Resin: A Performance Comparison」這篇文章來看~ 它的效率似乎表現不錯~ 好了~ 回歸重點~ 為什麼我對它燃起了興趣?... 二個原因,其一,到目前Hadoop 0.19.0版所內建的Servlet Container就是採用Jetty 5.1.4~ 不過根據「(#HADOOP-1650) Upgrade Jetty to 6.x - ASF JIRA」這個issue來看~ 0.20版就會變成Jetty 6.x版了~

另一個原因,由於今年年初有協助老師將一個「English Collocations」的雛型系統改寫成Web版~ 而這樣的系統其實只需要「唯讀」資料庫的內容即可~ 想將整個這樣的系統都做成「DVD-ROM」版本~ 這樣就變成可以帶著跑的Web Application了~ 方便性大大的提高~ 所以Jetty相當適合這樣的應用!!

下面簡單地記錄一下一些常用的設定及步驟:

啟動Jetty Sever

java -jar start.jar etc/jetty.xml

手動增加一個新的Web Application (含VirualHost設定)

請修改「/etc/jetty.xml」。

<New class="org.mortbay.jetty.webapp.WebAppContext">
	<Arg><Ref id="Contexts"/></Arg>
	<Arg><SystemProperty name="jetty.home"/>/webapps/webapp</Arg>
	<Arg>/webapp</Arg>
	<Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
	<Set name="VirtualHosts">
	<Array type="java.lang.String">
		<Item>localhost</Item>
	</Array>
	</Set>
</New>

測試Servlet - Hello World

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

public class Test extends HttpServlet
{
	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		res.setContentType("text/html");
		PrintWriter out = res.getWriter();
		out.println("<html>");
		out.println("<head><title>Hello</title></head>");
		out.println("<body>");
		out.println("HIHI");
		out.println("</body>");
		out.println("</html>");
	}
}

修改「web.xml」

<servlet>
	<servlet-name>Hello</servlet-name>
	<servlet-class>Test</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>Hello</servlet-name>
	<url-pattern>/Hello.do</url-pattern>
</servlet-mapping>

最後開啟「http://localhost:8080/webapp/Hello.do」即可。

PostgreSQL - ConnectionPoolDataSource

請修改「/etc/jetty.xml」。

<New id="DSTest" class="org.mortbay.jetty.plus.naming.Resource">
	<Arg>jdbc/DSTest</Arg>
	<Arg>
	<New class="org.postgresql.ds.PGConnectionPoolDataSource">
		<Set name="User">postgres</Set>
		<Set name="Password">xxx</Set>
		<Set name="DatabaseName">test</Set>
		<Set name="ServerName">localhost</Set>
		<Set name="PortNumber">5432</Set>
	</New>
	</Arg>
</New>

修改「web.xml」。

<resource-ref>
	<description>My DataSource Reference</description>
	<res-ref-name>jdbc/DSTest</res-ref-name>
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
</resource-ref>

一個簡單的測試程式如下:

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

public class PostgresDBTest extends HttpServlet
{
	public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		res.setContentType("text/html");
		PrintWriter out = res.getWriter();
		
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		try
		{
			ConnectionPoolDataSource source = (ConnectionPoolDataSource)new InitialContext().lookup("jdbc/DSTest");
    			con = source.getPooledConnection().getConnection();  
    			stmt = con.createStatement();
    			rs = stmt.executeQuery("select * from test");
    			while(rs.next())
    			{
    				out.println("Title:"+rs.getString(1)+"<br/>");
    			}
		} catch(Exception e){
    			e.printStackTrace();
		} finally {
    			if(con != null)
    			{
        			try {
       	 				con.close();
        			}catch(SQLException e)
        			{
        				e.printStackTrace();
        			}

    			}
		}		
	}	
}

修改「web.xml」。

<servlet>
	<servlet-name>PostgresDBTest</servlet-name>
	<servlet-class>PostgresDBTest</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>PostgresDBTest</servlet-name>
	<url-pattern>/PostgresDBTest.do</url-pattern>
</servlet-mapping>

最後開啟「http://localhost:8080/webapp/PostgresDBTest.do」即可。

Apache Commons DBCP - PostgreSQL

下載下述這三個Library,並複製到「Jetty_Home/lib」底下。

commons-dbcp.jar

commons-pool.jar

commons-collections.jar

請修改「/etc/jetty.xml」。

<New id="pgsqldbcp" class="org.mortbay.jetty.plus.naming.Resource">
	<Arg>jdbc/Blog</Arg>
	<Arg>
	<New class="org.apache.commons.dbcp.BasicDataSource">
	<Set name="driverClassName">org.postgresql.Driver</Set>
	<Set name="url">jdbc:postgresql://localhost/Blog</Set>
	<Set name="username">postgres</Set>
	<Set name="password">1234</Set>
	<Set name="maxActive">10</Set>
	</New>
	</Arg>
</New>

修改「web.xml」。

<resource-ref>
	<description>My DataSource Reference</description>
	<res-ref-name>jdbc/DSTest</res-ref-name>
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
</resource-ref>

測試程式如下:

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

public class PostgresDBTest extends HttpServlet
{
	public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		res.setContentType("text/html");
		PrintWriter out = res.getWriter();
		
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		try
		{
			InitialContext ic = new InitialContext();
			DataSource source = (DataSource)ic.lookup("jdbc/Blog");
			con = source.getConnection();  
			stmt = con.createStatement();
			rs = stmt.executeQuery("select * from test");
			while(rs.next())
			{
    				out.println("Title:"+rs.getString(1)+"<br/>");
			}
		} catch(Exception e){
			e.printStackTrace();
		} finally {
			if(con != null)
			{
				try {
					con.close();
				}catch(SQLException e)
				{
					e.printStackTrace();
				}
			}
		}
	}		
}

2008-12-07 21:36:29 | Comments (5)

cpdetector - 編碥偵測(Java)

cpdetector, free java code page detection.」,這是另一套編碼偵測的解決方案(Java)~ 同時也包含了Mozilla's chardet (jchardet)~

另外根據「Shared Development: Character encoding detection」所針對「cpdetector」的編碼測試~ 它所顯現的成果的確相當顯著~ 有需要的人用看看吧~

範例程式

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;

import cpdetector.io.CodepageDetectorProxy;
import cpdetector.io.HTMLCodepageDetector;
import cpdetector.io.JChardetFacade;

public class CPdetector
{
	private static CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
	
	static
	{
		detector.add(new HTMLCodepageDetector(false));
		detector.add(JChardetFacade.getInstance());
	}
	
	public String getEncoding(File f)throws Exception
	{
		return getEncoding(f.toURI().toURL());
	}
	public String getEncoding(URL url)throws IOException
	{
		Charset charset = detector.detectCodepage(url);

		if (charset != null)
			return charset.name();

		return null;
	}

	public static void main(String[] args)
	{
		CPdetector detector = new CPdetector();
		try
		{
			String encoding = detector.getEncoding(new File("Big5.txt"));
			System.out.println("encoding:"+encoding);
			encoding = detector.getEncoding(new URL("http://www.google.com.tw"));
			System.out.println("encoding:"+encoding);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

範例結果:

encoding:UTF-8
encoding:Big5

2008-09-29 14:55:43 | Add Comment

Nutch - 打造一個屬於自己的搜尋引擎

首先請先至Nutch官網下載「nutch-0.9.tar.gz」~

安裝步驟

請先解壓縮「nutch-0.9.tar.gz」

tar zxvf nutch-0.9.tar.gz

然後建立一個爬行器的爬行清單檔案~ 這裡以筆者的部落格為範例:

cd nutch-0.9
echo http://blog.ring.idv.tw/index.ser > urls

修改「conf/crawl-urlfilter.txt」中的「MY.DOMAIN.NAME」改成下述:

+^http://([a-z0-9]*.)*ring.idv.tw/

修改「conf/nutch-site.xml」,加上一個「http.agent.name」的參數值:

<property>  
<name>http.agent.name</name>  
<value>crawler</value>  
</property>  

啟動Crawler開始抓網頁~ 預設啟動十個Thread來爬~

bin/nutch crawl urls -dir ring -depth 5 -topN 50 &

抓完網頁的相關資料並建立索引之後~ 就要開始部署搜尋引擎了~

請將「nutch-0.9.war」搬移至你JBossTomcat部署的資料夾下

mkdir nutch.war
mv nutch-0.9.war nutch.war
unzip nutch-0.9.war

修改「nutch.war/WEB-INF/classes/nutch-site.xml」,為它加上要搜尋的資料夾,也就是我們剛剛透過Crawler所建立的那些索引檔~

<property>  
<name>searcher.dir</name>  
<value>/usr/local/data/nutch-0.9/ring</value>  
</property>  

修改「server.xml」,如果你的環境是JBoss 4.2.2GA的話~ 請參考下述做法:

cd JBoss-4.2.2.GA/server/default/deploy/jboss-web.deployer
vi server.xml

找到「<Connector port="8080"」這一行,為它加上「URIEncoding="UTF-8" useBodyEncodingForURI="true"」即可~ 避免利用Get傳送方式導致編碼錯誤~

最後啟動你的JBoss來玩嚕~

參考資源

Nutch 笔记(一):Quick Start

Nutch 0.9 安裝心得(小攻略)

相關資源

Introduction to Nutch, Part 1: Crawling

Introduction to Nutch, Part 2: Searching

Nutch 笔记(二):Craw more urls and Recrawl

Nutch 初体验之二

2008-03-16 16:41:58 | Add Comment

PHP Question - ($a-- +1)

剛剛在小海格友的Blog看到一篇文章「PHP Question」,他的問題如下所述:

<?php  
$a = 1;  
$a = $a-- +1;  
echo $a;  
?> 

這時候 $a 會等於多少?

其實這種問題只要針對內部的堆疊運作去Run一次就可以得到詳解了~

不過我不曉得PHP有沒有「類似」javap這樣的工具,或是有辦法可以讓我們看到PHP內部一個個opcode處理的方式?有的話分享一下唄~ 感恩呢 ^^

所以我去下載了「php-5.2.5」原始碼~ 本來想打算從PHP的原始碼中來找答案~

可是我看了看~ 總覺得不曉得要花費多少時間~ 而且這樣實在太沒效率了~ 除非你想研究則不在此限~

不過也意外發現~ PHP的原始程式還是用了「Virtual Machine」這樣的字眼 ^^~

P.S. PHP全部的opcode都定義在「Zend/zend_vm_opcodes.h」 <== 檔名有「vm」

Java解釋

這裡我打算換個角度來解釋~ 乾脆用Java來模擬一樣的問題~ 程式如下:

public class Plus
{
	public static void main(String arg[])
	{
		int a = 1;  
		a = a-- + 1;  
		System.out.println(a);
	}
}

接著我用「javap」來反組譯一下~ 看看operand stack是怎麼Run的~

我們就直接來看上圖所用黃色框起來的opcode~

0: iconst_1 #將int constant「1」推入到Operand Stack。

1: istore_1 #將Operand Stack的「1」存到Local Variable[1]的位置(所以到這邊已經完成了「int a = 1;」)。

2: iload_1 #將剛剛那個Local Variable[1]的整數值再載入到Operand Stack。

3: iinc 1, -1 #將目前Local Variable[1]的值「減1」。

6: iconst_1 #將int constant「1」推入到Operand Stack (所以現在Operand Stack有兩個都為「1」的值)。

7: iadd #將Operand Stack前兩個整數值相加後再推入到Operand Stack (所以目前Operand Stack只有一個「2」的整數值)。

8: istore_1 #將Operand Stack「2」存到Local Variable[1]的位置。

結果出來了~ 重點就在於「3: iinc 1, -1」是減掉Local Variable[1]的值~ 而不是減掉Operand Stack中待會要進行「iadd」相加的值~,所以這個範例會印出的值當然就是「2」嚕~ ^^

呃... 又2點多了~ 來去睡~ 這個三月挺忙的 ^^a

2008-03-01 02:32:10 | Comments (2)

BOMKiller

底下是一個針對UTF-8編碼的BOMKiller程式~ 如果你開發程式時所採用的文字編輯器會自動為你加上BOM的話~ 那BOMKiller可以協助你更容易刪除這些BOM~

好久沒寫Java了~~ 趁這個機會再回味一下用UltraEdit純手工寫程式~

BOMKiller原始檔

/**
 * Date: 2008-02-18
 * Shen (http://blog.ring.idv.tw)
 **/
import java.io.*;  
import java.nio.channels.*;

public class BOMKiller
{  
	private String suffix = null;
	public BOMKiller(String suffix)
	{
		this.suffix = suffix;
	}
	
	public static void main(String arg[])
	{
		if(arg.length != 2 || (new File(arg[0])).isDirectory() == false)
		{
			System.out.println("Usage:java BOMKiller [directory_path] [suffix_name]");
			System.exit(0);
		}
		BOMKiller killer = new BOMKiller(arg[1]);
              	killer.listFiles(new File(arg[0]));
      	}
      	public void listFiles(File f)
      	{
		File[] filelist = f.listFiles(new FileFilter()
		{
			public boolean accept(File tempf)
			{
				if(tempf.isDirectory())
				{
					listFiles(tempf);
					return false;
				}
				return tempf.getName().endsWith(suffix);
			}
		});
		
          	int flength = filelist.length;
          	for(int i = 0; i < flength ; ++i)
		{  
              		killBOM(filelist[i]);
          	}
	}
	public void killBOM(File f)
	{
		try
		{
			FileInputStream fis = new FileInputStream(f);		
			if(fis.read() == 0xEF)
			{
				if(fis.read() == 0xBB)
				{
					if(fis.read()==0xBF)
					{
						String path = f.getPath();
						System.out.println("BOMKiller:"+path);
						
						File toFile = new File(path+".tmp");
						FileChannel fic = fis.getChannel();
						FileChannel foc = new FileOutputStream(toFile).getChannel();
						fic.transferTo(3, fic.size(),foc);
						fic.close();
						foc.close();
						f.delete();
						toFile.renameTo(new File(path));
					}
				}
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

用法

Usage:java BOMKiller [directory_path] [suffix_name]

e.g.

java BOMKiller C:\htdocs .php

相關文章

IE Bug? UTF-8 Encoding for Byte Order Mark(BOM)

2008-02-18 04:38:44 | Add Comment

Next Posts~:::~Previous Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: Ads :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment

::: 人氣指數 :::

今日人氣:684

累積人氣:3132345


::: 線上人數 :::

counter