練功房推薦書單

  • Google!Android 3手機應用程式設計入門(第四版)
  • 賈伯斯傳(軟皮精裝版)
  • 猛虎出閘制霸版:最新OCP Java SE 6 Programmer專業認證(附原始程式碼及範例檔)
  • SCWCD 5 猛虎出閘:Java Web 應用程式專業認證
Messages posted by: andowson
Forum Index » Profile for andowson » Messages posted by andowson
Message
不用客氣,如果您的網站順利上線了,不妨到以下文章報到一下
http://www.andowson.com/posts/list/27.page
可以參考這幾篇
Choosing A Java Web Framework: A Comparison by Richard Pack
http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-6457.pdf

Comparing Web Frameworks - JSF, Spring MVC, Stripes, Struts 2, Tapestry and Wicket by Matt Raible
http://static.raibledesigns.com/repository/presentations/ComparingJavaWebFrameworks-ApacheConEU2007.pdf
http://parleys.com/display/PARLEYS/Comparing+Java+Web+Frameworks?showComments=true

Comparing JVM Web Frameworks - Flex, Grails, GWT, Seam, Struts 2 and Wicket by Matt Raible
http://static.raibledesigns.com/repository/presentations/ComparingJVMWebFrameworks-ApacheConUS2007.pdf

Java Web Framework
http://docs.google.com/View?docID=ajgdx7ccvkxg_50ccp25f&revision=_latest
SFTP(SSH File Transfer Protocol or FTP over SSH)

預先安裝函式庫:JSch(Java Secure Channel)
程式碼:
sftp.jsp:
<%@ page import="java.io.File"%>
<%@ page import="java.io.FileInputStream"%>
<%@ page import="java.io.FileOutputStream"%>
<%@ page import="java.util.Properties"%>
<%@ page import="java.util.Vector"%>
<%@ page import="com.jcraft.jsch.Channel"%>
<%@ page import="com.jcraft.jsch.ChannelSftp"%>
<%@ page import="com.jcraft.jsch.JSch"%>
<%@ page import="com.jcraft.jsch.Session"%>
<%@ page import="com.jcraft.jsch.ChannelSftp.LsEntry"%>
<%
	try {
		String host = "192.168.1.2";
		int port = 22;
		String username = "andowson";
		String password = "changeit";
		String directory = "/home/andowson/download/";
		String uploadFile = "C:\\temp\\upload.txt";
		
		String downloadFile = "C:\\temp\\download.txt";
		String deleteFile = "delete.txt";
	
		//
		// First Create a JSch session
		//
		System.out.println("Creating session.");
		JSch jsch = new JSch();
		ChannelSftp sftp = null;
	
		//
		// Now connect and SFTP to the SFTP Server
		//
		try {
			// Create a session sending through our username and password
			Session sshSession = jsch.getSession(username, host, port);
			System.out.println("Session created.");
			sshSession.setPassword(password);
			// Security.addProvider(new com.sun.crypto.provider.SunJCE());
	
			//
			// Setup Strict HostKeyChecking to no so we don't get the
			// unknown host key exception
			//
			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");
			sshSession.setConfig(sshConfig);
			sshSession.connect();
			System.out.println("Session connected.");
	
			//
			// Open the SFTP channel
			//
			System.out.println("Opening Channel.");
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			sftp = (ChannelSftp) channel;
			System.out.println("Connected to " + host + ".");
		} catch (Exception e) {
			System.err.println("Unable to connect to FTP server." + e.toString());
			throw e;
		}
	
		//
		// Change to the remote directory
		//
		System.out.println("Changing to FTP remote dir: " + directory);
		// CWD
		sftp.cd(directory);
		// PWD
		System.out.println(sftp.pwd());
	
		//
		// Send the file we generated, PUT
		//
		File filePut = new File(uploadFile);
		try {				
			System.out.println("Storing file as remote filename: "	+ filePut.getName());
			sftp.put(new FileInputStream(filePut), filePut.getName());
		} catch (Exception e) {
			System.err.println("Storing remote file failed." + e.toString());
			throw e;
		}
	
		//
		// Get the list of files in the remote server directory
		//
		Vector files = sftp.ls(directory);
	
		//
		// Log if we have nothing to download
		//
		if (files.size() == 0) {
			System.out.println("No files are available for download.");
		}
		//
		// Otherwise download all files except for the . and .. entries
		//
		else {
			long totalSize = 0L;
			for (int i = 0; i < files.size(); i++) {
				LsEntry file = (LsEntry) files.get(i);					
				if (!file.getFilename().equals(".")	&& !file.getFilename().equals("..")) {
					System.out.printf("%s %s [%d bytes]\n",
							(file.getAttrs().isDir() ? "[D]" : "   "), file.getFilename(), file.getAttrs().getSize());
					if (!file.getAttrs().isDir()) {
						totalSize += file.getAttrs().getSize();
					}						
				}
			}
			System.out.println("totalSize = " + totalSize/(1024 * 1024) + "MB");
			//
			// Get the file and write it to our local file system, GET
			//
			System.out.println("Downloading file " + filePut.getName());
			File fileGet = new File(downloadFile);
			sftp.get(filePut.getName(), new FileOutputStream(fileGet));
			//
			// Remove the file from the server, DELE
			//
			System.out.println("Deleting file " + deleteFile);
			sftp.rm(deleteFile);
		}
	
		//
		// Disconnect from the FTP server
		//
		try {
			sftp.quit();
		} catch (Exception e) {
			System.err.println("Unable to disconnect from FTP server. "	+ e.toString());
		}
	
	} catch (Exception e) {
		System.err.println("Error: " + e.toString());
		e.printStackTrace();
	}
	
	System.out.println("Process Complete.");
%>

參考資料:
Sending Files via FTP From Your Java Applications - Part 2 of 2 - Using Jsch for SFTP
「發文時啟用圖形識別確認」目前無法在Control Panel內設定,但JForum 2.1.8已內建這個功能,只是預設是關閉而已。故我們只需手動修改設定檔,不需另外開發程式。
修改方法是請在JForum安裝目錄下的WEB-INF/config/jforum-custom.conf中新增下列設定參數即可:
captcha.posts=true
captcha.ignore.case = true
captcha.min.words = 4
captcha.max.words = 5

又,有關JForum的使用問題請盡量發表在JForum中文社群版面上,以便日後參考,謝謝!
FTPS(FTP Secure or FTP over SSL/TLS)

預先安裝函式庫:ftp4che, log4j
程式碼:
ftp4che.jsp:
<%@ page import="java.io.File"%>
<%@ page import="java.io.IOException"%>
<%@ page import="org.ftp4che.*"%>
<%@ page import="org.ftp4che.util.ftpfile.*"%>
<%@ page import="org.ftp4che.exception.*"%> 
<%@ page import="org.ftp4che.impl.SecureFTPConnection"%>
<%
	String server = "192.168.1.2";
	String username = "andowson";
	String password = "changeit";
	String directory = "download";
	String filename = "C:\\Users\\Andowson\\Desktop\\jspSmartUpload.zip";
	File filePut = new File(filename);
	String filename2 = "C:\\Users\\Andowson\\Desktop\\commons-net-1.4.1.zip";
	File fileGet = new File(filename2);
	String filename3 = "jdk-6u3-windows-i586-p.exe";
	
	FTPConnection ftp = null;
	try {
		ftp = FTPConnectionFactory.getInstance(server, 21, username, password, FTPConnection.AUTH_TLS_FTP_CONNECTION, true);
        ftp.connect();
		System.out.println("Connected to " + server + ".");
		
		// transfer files
		long totalSize = 0L;
		for (FTPFile file : ftp.getDirectoryListing(directory)) {
			System.out.printf("%s %s [%d bytes]\n",
					(file.isDirectory() ? "[D]" : "   "), file.getName(), file.getSize());
			if (!file.isDirectory()) {
				totalSize += file.getSize();
			} 
		}			
		System.out.println("totalSize = " + totalSize/(1024 * 1024) + "MB");
		
		// PASV
		ftp.setPassiveMode(true);
		// CWD
		ftp.changeDirectory(directory);
		// PWD
		System.out.println(ftp.getWorkDirectory());		
		// PUT
		FTPFile fromFile = new FTPFile(filePut);
		FTPFile toFile = new FTPFile(new File(filePut.getName()));
		ftp.uploadFile(fromFile, toFile);
		// GET
		fromFile = new FTPFile(new File(fileGet.getName()));
		toFile = new FTPFile(fileGet);
		ftp.downloadFile(fromFile, toFile);
		// DELE
		ftp.deleteFile(new FTPFile(new File(filename3)));
	} catch (NotConnectedException nce) {
		nce.printStackTrace();
	} catch (FtpFileNotFoundException ffnfe) {
		ffnfe.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (ftp != null) {
			ftp.disconnect();
		}
	}
%>

備註:
最近找到了支援FTPS的免費Java FTP Library(採用LGPL授權) -- ftp4che,將原先的程式碼略微修改一下,搭配FileZilla Server測試一下,可以成功執行。
參考資料:
http://www.javaworld.com.tw/jute/post/view?bid=11&id=237813&sty=3
增加檔案大小限制及檔案類型的篩選:
程式碼:
fileupload_control.html:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>File Upload</title>
<style type="text/css">
<!--
.topic {color: #FF0000; font-size: 1.5em; font-weight: bold}
-->
</style>
</head>
<body>
<p class="topic">檔案上傳</p>

<form name="upload" enctype="multipart/form-data" method="post" action="fileupload_control.jsp"> 
<p>上傳檔案: <input type="file" name="file" size="20" maxlength="20" /> </p>
<p>檔案說明: <input type="text" name="filedesc" size="30" maxlength="50" /> </p>
<p> <input type="submit"value="上傳" /> <input type="reset" value="清除" /> </p>
</form>

</body>
</html>


fileupload_control.jsp:
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="java.io.File"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.List"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@ page import="org.apache.commons.io.FilenameUtils"%>
<%!
    int yourMaxMemorySize = 1024 * 1024 * 1024;
	File yourTempDirectory = new File("/tmp");
	int yourMaxRequestSize = 100 * 1024 * 1024;
	boolean writeToFile = true;
	String allowedFileTypes = ".txt .pdf .doc .ppt .xls .csv .dbf .gif .jpg .jpeg .png .swf .htm .html .zip .rar";
%>
<%
	String saveDirectory = application.getRealPath("/upload");

	// Check that we have a file upload request
	boolean isMultipart = ServletFileUpload.isMultipartContent(request);
	out.println("isMultipart=" + isMultipart + "<br>");

	// Create a factory for disk-based file items
	DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);
	
	// Create a new file upload handler
	ServletFileUpload upload = new ServletFileUpload(factory);

	// Set overall request size constraint
	upload.setSizeMax(yourMaxRequestSize);

	//Create a progress listener
	ProgressListener progressListener = new ProgressListener() {
		private long megaBytes = -1;

		public void update(long pBytesRead, long pContentLength, int pItems) {
			long mBytes = pBytesRead / 1000000;
			if (megaBytes == mBytes) {
				return;
			}
			megaBytes = mBytes;
			System.out.println("We are currently reading item "	+ pItems);
			if (pContentLength == -1) {
				System.out.println("So far, " + pBytesRead	+ " bytes have been read.");
			} else {
				System.out.println("So far, " + pBytesRead + " of "	+ pContentLength + " bytes have been read.");
			}
		}
	};
	upload.setProgressListener(progressListener);

	try {
		// Parse the request
		List /* FileItem */items = upload.parseRequest(request);

		// Process the uploaded items
		Iterator iter = items.iterator();
		while (iter.hasNext()) {
			FileItem item = (FileItem) iter.next();

			if (item.isFormField()) {
				// Process a regular form field	
				//processFormField(item);		
				String name = item.getFieldName();
				String value = item.getString("UTF-8");
				out.println(name + "=" + value + "<br />");
			} else {
				// Process a file upload
				//processUploadedFile(item);						
				String fieldName = item.getFieldName();
				String fileName = item.getName();
				String contentType = item.getContentType();
				boolean isInMemory = item.isInMemory();
				long sizeInBytes = item.getSize();
				out.println("fieldName=" + fieldName + "<br />");
				out.println("fileName=" + fileName + "<br />");
				out.println("contentType=" + contentType + "<br />");
				out.println("isInMemory=" + isInMemory + "<br />");
				out.println("sizeInBytes=" + sizeInBytes + "<br />");
				if (fileName != null && !"".equals(fileName)) {
					if (writeToFile) {
						fileName = FilenameUtils.getName(fileName);
						out.println("fileName to be saved=" + fileName + "<br />");
						String extension = FilenameUtils.getExtension(fileName);
						if (allowedFileTypes.indexOf(extension.toLowerCase()) != -1) {
						    File uploadedFile = new File(saveDirectory,	fileName);						
						    item.write(uploadedFile);
						} else {
							out.println("上傳的檔案不能是" + extension + "<br />");
						}
					} else {
						//InputStream uploadedStream = item.getInputStream();
						//...
						//uploadedStream.close();
						// Process a file upload in memory
						byte[] data = item.get();
						out.println("data size=" + data.length + "<br />");
					}
				}
			}
		}
	} catch (FileUploadBase.SizeLimitExceededException ex1) {
		out.println("上傳檔案超過最大檔案允許大小" + yourMaxRequestSize / (1024 * 1024) + "MB !");
	}
%>


另外需要在web.xml中加上下列設定:
<web-app>
  ...
  <listener>
    <listener-class>
      org.apache.commons.fileupload.servlet.FileCleanerCleanup
    </listener-class>
  </listener>
  ...
</web-app>

參考資料:
http://commons.apache.org/fileupload/using.html
1.新增分類或版面後必須再到群組設定權限才會看得到,這是預設的行為模式,避免誤開分類或版面。
2.在允許票選的版面內發表文章時會顯示三顆按鈕:選項,附加檔案,票選主題,按票選主題再把票選的項目填入即可。如果有票選主題進行中,則會顯示在最上方,每人只能單選投票一次。
3.版面管理員要先開一個版主群組,然後設定這個版主群組可以管理的版面,再將要擔任版主的會員加入到這個群組。如果您有三個版面甲、乙、丙,分別給A、B、C管理,則您需要開三個群組甲版主、乙版主、丙版主,然後將A設定到甲板主群組,B設定到乙版主群組,C設定到丙版主群組。
要設定某些版面必須經過審核後才能把文章顯示出來,可以設定一般群組內的權限為需審核才能顯示,一般使用者發表文章後不會立即顯示,會等候版主審核。該版面的版主登入後會看到上方有個待審核文章清單,版主可以選擇核准或拒絕,核准就會顯示出來,拒絕則該文章則被刪除。
管理日誌則可以設定要不要讓一般網友看到版主的管理行為,可分詳細或簡要兩種,詳細的會列出較多的內容,包含原因和文章內容等。

使用說明文件目前還沒有時間做,可能還是先請您參考一下原來網站上英文版的簡要說明或是在本站上發問。
英文的文件網址如下:
http://www.jforum.net/Wiki.jsp
一、報名日期:自即日起至 98 年 2 月 5 日(以郵戳為憑)。
二、面試日期:98 年 2 月 18 日 e-mail 通知書面審查合格者於 98 年 3 月 1 日(星期日)面試。

詳細資訊請見: http://www.cht.com.tw/CompanyCat.php?CatID=4&NewsID=1702&Page=HotNewsDetail
Tuning PostgreSQL for performance
http://www.varlena.com/GeneralBits/Tidbits/perf.html
Performance Tuning PostgreSQL
http://www.revsys.com/writings/postgresql-performance.html
5-Minute Introduction to PostgreSQL Performance
http://www.westnet.com/~gsmith/content/postgresql/pg-5minute.htm
原因是在原來的net.jforum.view.forum.SearchAction類別的buildSearchArgs() method裡request抓的參數名字是forum,而search.htm裡面表單的參數名稱是search_forum,兩者不一致的關係。

解決方法一是:
1.修改表單樣版檔<jforum_installed_path>/templates/default/search.htm

<select class="post" name="search_forum">
改為
<select class="post" name="forum">
2.修改分頁樣版檔<jforum_installed_path>/templates/macros/search_pagination.ftl
將第5行的參數
	<#if (searchArgs.forumId > 0)><#assign params = params +"&search_forum="+ searchArgs.forumId/></#if>

修改為
	<#if (searchArgs.forumId > 0)><#assign params = params +"&forum="+ searchArgs.forumId/></#if>


解決方法二是:
1.修改net/jforum/view/forum/SearchAction.java的buildSearchArgs() method內這幾行
		if (this.request.getParameter("forum") != null) {
			args.setForumId(this.request.getIntParameter("forum"));
		}



		if (this.request.getParameter("search_forum") != null && !"".equals(this.request.getParameter("search_forum"))) {
			args.setForumId(this.request.getIntParameter("search_forum"));
		}

2.修改<jforum_installed_path>/templates/default/forum_show.htm
將第66行的
<input type="hidden" name="forum" value="${forum.id}" />

修改為
<input type="hidden" name="search_forum" value="${forum.id}" />

3.重新載入JForum或重新啟動Tomcat

另外,如果文章有被搬移過版面,則雖然有指定版面但可能會被意外搜尋到,此時可以透過管理介面再重新完整重頭建立索引一次。
此時也意外發現之前v2.1.8漏翻譯了一個字串,可以將它加進去
en_US.properties:
SearchStats.informationUnavailable = Information unavailable at the moment

zh_TW.properties:
SearchStats.informationUnavailable = \u76EE\u524D\u7121\u6CD5\u5F97\u5230\u4EFB\u4F55\u8CC7\u8A0A
1.修改generic_queries.sql,加上KarmaModel.deletePostKarma
# ###########
# KarmaModel
# ###########
...
KarmaModel.deletePostKarma = DELETE FROM jforum_karma WHERE post_id = ?
...


2.修改net/jforum/dao/KarmaDao.java,加上deletePostKarma(int postId) method宣告
public interface KarmaDAO
{
...
	/**
	 * Deletes the karma belonging to some post.
	 * This method will remove the post's karma from the
	 * karma table. 
	 *  
	 * @param postId The id of the post to delete	 
	 */
	public void deletePostKarma(int postId) ;
...
}


3.修改net/jforum/dao/generic/GenericKarmaDao.java,加上deletePostKarma(int postId) method實做
public class GenericKarmaDAO implements net.jforum.dao.KarmaDAO
{
...
	/**
	 * @see net.jforum.dao.KarmaDAO#deletePostKarma(int)
	 */
	public void deletePostKarma(int postId)
	{
		PreparedStatement p = null;		
		try {
			p = JForumExecutionContext.getConnection()
					.prepareStatement(SystemGlobals.getSql("KarmaModel.deletePostKarma"));
			p.setInt(1, postId);
			p.executeUpdate();
		}
		catch (SQLException e) {
			throw new DatabaseException(e);
		}
		finally {
			DbUtils.close(p);
		}
	}
...


4.修改net/jforum/view/forum/PostAction.java,修改delete() method,在Karma處理部分插入karmaDao.deletePostKarma(p.getId());在重算Karma之前
public class PostAction extends Command 
{
...
	public void delete()
	{
                ...
		// Karma
		KarmaDAO karmaDao = DataAccessDriver.getInstance().newKarmaDAO();
		karmaDao.deletePostKarma(p.getId());
		karmaDao.updateUserKarma(p.getUserId());
                ...
	}
...
}


5.重新編譯,並重新載入JForum
一、報名日期:自 97.12.24 (星期三) 至 98.01.06 (星期二)中午 12 點止
二、第一試(資歷論文審查)日期:98.01.13 (星期二)至 98.01.15 (星期四)由數據分公司資歷審查小組上網遴選。
三、第二試通知日期:98.01.16 (星期五),以 Email 通知詳細口試時程及順序表,並請於收到 mail 後回覆是否參加。
四、第二試(口試)日期:98.01.20 (星期二)(若有異動,以通知變更日期為準)。
五、放榜日期:98.01.21 (星期三)下午(若有異動,以通知變更日期為準)。
詳細資訊請見: http://www.cht.com.tw/CompanyCat.php?CatID=533&NewsID=1669&Page=HotNewsDetail
因部分版面一直無人發文,故將其刪除,另部分版面僅有單獨一篇者合併至較適當版面,並新增一其他分區,新增一工作機會版面。
大家好,今天是網站成立兩週年的日子,去年的展望是
1.會員數成長到1000人,啟用率八成
2.發表文章數成長到500篇,發文率8%

先來檢視一下去年網站運作的成果:
1.會員數:
smilie 註冊會員數:1103(達成 smilie
select count(*) from jforum_users where user_regdate < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:680(1103-423)
成長率:60.76%((680-423)/423)
smilie 已啟用帳號數:832
select count(*) from jforum_users where user_actkey is null and user_regdate < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:530(832-302)
啟用率:75.43%(832/1103) (未達成 smilie

2.文章數:
發表文章數:450篇(未達成 smilie
select count(*) from jforum_posts where post_time < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:229(450-221)
成長率:3.62%((229-221)/221)
smilie 主題數:229
select count(*) from jforum_topics where topic_time < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:90(229-139)
成長率:-35.25%((90-139)/139)

3.發文狀況
smilie 發文人數:33
select count(*) from jforum_users where user_regdate < to_date('2009-01-01', 'yyyy-mm-dd') and user_posts > 0

發文率:3.97%(33/832)(未達成 smilie
smilie 發文排行榜:
1.andowson:304
2.viva:22
3.wu_net2008:16
4:windstorm:14
5.wtom:12
6.fly:11
7.lynx286:10
8.ofather:8
9.~HIM~:8
10.Anonymous:7
select username, user_posts from jforum_users where user_posts > 0 order by user_posts desc limit 10


4.流量統計
最高月參觀者數:7562(2008/10)

整體來說,2008年只有達成一項目標,其他幾項指標可能有過份樂觀。

今年的展望是:
1.會員數成長到2000人,啟用率75%
2.發表文章數成長到750篇,發文率5%
3.流量月最高參觀者數突破10000人
已修改為fly。也希望再見到您發表新文章。
 
Forum Index » Profile for andowson » Messages posted by andowson
Go to: