2008年4月5日
作者:EasyJF開源團(tuán)隊(
www.easyjf.com) 大峽
經(jīng)常會跟一些朋友討論怎么樣才能學(xué)好Java,學(xué)到什么程度才算撐握了Java的問題。其中有一個J2EE程序員層次及武功修為的問題,有點(diǎn)意思。這里就把討論的內(nèi)容大致整理一下發(fā)出來,大家繼續(xù)討論。 縱觀國內(nèi)的軟件行業(yè),靠Java吃飯的程序員還真不是少,而且Java程序員是有很大優(yōu)越感的,畢竟對于很多用b/s搞開發(fā)的業(yè)內(nèi)朋友來說,Java技術(shù)意味著難度大、門檻高,因此相對來說Java程序員比其它的程序員(如php、.net)收入高就理所當(dāng)然。然而J2EE所涉及到的范疇是很廣的,不能一個Java程序員就概括了事,而應(yīng)該具有層次及水平之分,很多時候經(jīng)常需要進(jìn)行分類或評級,有時他評、有時自評。 談到國內(nèi)J2EE領(lǐng)域的程序員層次水平,當(dāng)前流行的稱謂及評級不外乎就下面幾種: 第一種是精通掌握記事本、Dreamweaver等工具來寫JSP+JavaBean數(shù)據(jù)庫應(yīng)用的是J2EE程序員;
第二種是用JBuilder、Eclipse等專用Java開發(fā)工具寫著一堆一堆過程式Java Bean,而且還能精通Struts+Spring+Hibernate等應(yīng)用框架的高級J2EE程序員;
第三種是用Together建模,然后生成一堆Java接口或代碼,開口閉口都是設(shè)計模式的資深Java程序同及高級系統(tǒng)分析、構(gòu)架師;
最后還有一種是整天在BlogJava或JavaEye上談經(jīng)論道的大師們,這些大師技術(shù)水平難以觸摸,武功門派也各具特色,不好歸類,有時不好稱為程序員(因為有的時候他們甚至不寫或者寫不出程序),但又做著與J2EE程序員密切相關(guān)的事情,我們暫且就歸為“牛牛”或“大師”。 稱謂畢竟只是稱謂,帶有點(diǎn)主觀或者功利色彩,有時很難鑒定一個人應(yīng)該屬于什么,因此,我們再從純技術(shù)的角度,也即武功修為的角度,作了一個簡單的分析及歸類,把2EE領(lǐng)域程序員大致分成以下幾個層次,可以作為大家自評的一個參考標(biāo)準(zhǔn): 第一個層次:精通掌握J(rèn)ava語法、能調(diào)試基本的程序錯誤,精通掌握J(rèn)SP+Java Bean寫一些N年前ASP、PHP翻版的Java Web應(yīng)用程序(如論壇、網(wǎng)站新聞發(fā)布系統(tǒng)、OA、網(wǎng)上商城等),精通JDBC使用、精通SQL語句、精通XML等。 第二個層次:掌握設(shè)計模式原理及應(yīng)用,掌握基于OO的分析及設(shè)計方法,并能精通熟練使用幾種Java專業(yè)設(shè)計及開發(fā)工具,精通掌握流行的J2EE框架如Hibernate、EJB、Webwork、Spring的原理及應(yīng)用,精通J2EE中一兩個組成部分(如Servlet、EJB等)的工作原理及細(xì)節(jié)。 第三個層次:少林的高僧有兩種,禪僧及武僧。J2EE程序員的第三個層次也同樣有禪、武兩個分支,這里我們重點(diǎn)分析一下: 第一個分支屬于走的禪僧線路。在練完第二個層次中的各種武功基礎(chǔ)上,結(jié)合實(shí)際項目中的千奇百怪的用戶需求,游刃有余的選擇適合的技術(shù)方案為客戶解決問題,并形成自己的一套解決方案。達(dá)到這一個層次的J2EE程序員已經(jīng)不在乎使用任何工具、任何框架了,而是根據(jù)不同的對手,使用不同的武器或招式來應(yīng)對。好比 小李飛刀一樣,只有達(dá)到了“手中無刀、心中有刀”的境界,才能達(dá)到“出手一刀,例不虛發(fā)”的效果。這一層次的武功屬于一個熟練度問題,刀練得多了、遇到的對手多了,再加上前面的武功修為,就算做不到例不虛發(fā),也可達(dá)到十發(fā)九中。 第二個分支屬于走的武僧線路,在撐握熟悉第一二個層次中涉及到的內(nèi)容后,進(jìn)一步專研并撐握J(rèn)2EE底層開發(fā),J2EE規(guī)范制訂、規(guī)范實(shí)現(xiàn)、Java虛擬機(jī)的工作原理、各種常見的J2EE服務(wù)器內(nèi)核工作機(jī)制、內(nèi)存管理、進(jìn)程機(jī)制、源代碼等。因為涉及的很多東西都比較抽象,代碼也很多,練這一層的武功需要有很好的資質(zhì)及耐性、并具還得有一定的環(huán)境及條件。好比神雕大俠楊過拿起“玄鐵劍”,并練成“暗然銷魂掌”的成長過程,需要前面的武功修為作基礎(chǔ),更需那只威力神武神雕的幫助指點(diǎn)及他處處為民、懲奸除惡的俠之心態(tài)。
胡侃了這么多,現(xiàn)在來根據(jù)自己情況測算一下自己的份量,結(jié)果如下: 第一層 練到8成;
第二層 練到5成;
第三層 準(zhǔn)備走禪僧線路,當(dāng)前算是練到1成;
唉,后面的武功提升越來越難,真不知道要到何年何月才能達(dá)到10成啊。你的武功練到哪一個層次了,不防亮出來大家切磋切磋。嘿嘿,要是有一天,咱們中國的Java程序員人手一把“玄鐵劍”、人人會使“暗然銷魂掌”,那還了得!汗...,寫著寫著居然做起白日夢了,不好意思,就此打住。
手中雞蛋先別扔,還要打個廣告:本人剛開始涉足Java開源,目前在EasyJF開源團(tuán)隊中負(fù)責(zé)EasyJWeb(官網(wǎng)www.easyjf.com)項目,歡迎大家前來指導(dǎo)。
很牛的一個人物啊!
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* @(#)VerifyCodeServlet.java Dec 9, 2007 8:14:14 PM
*
* @author Yuan
* 驗證碼生成器,使用此類需要將表單里的驗證碼輸入框的name屬性設(shè)為"verifycode"
*/
public class VerifyCodeGenerator {
private static final VerifyCodeGenerator generator = new VerifyCodeGenerator();
private final String ATTRIBUTE_NAME = "verifycode";
//圖片的寬度
private final int WIDTH = 15;
//圖片的高度
private final int HEIGHT = 22;
//字符串長度
private final int CODE_LENGTH = 4;
//隨機(jī)字符串范圍
private final String RAND_RANGE = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "1234567890"
+ "@#quot;;
private final char[] CHARS = RAND_RANGE.toCharArray();
private Random random = new Random();
private VerifyCodeGenerator(){
//
}
public static VerifyCodeGenerator getInstance(){
return generator;
}
/**
* 生成隨機(jī)字符串
* @return 隨機(jī)字符串
*/
private String getRandString(){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < CODE_LENGTH; i++)
sb.append(CHARS[random.nextInt(CHARS.length)]);
return sb.toString();
}
/**
* 生成隨機(jī)顏色
* @param ll 產(chǎn)生顏色值下限(lower limit)
* @param ul 產(chǎn)生顏色值上限(upper limit)
* @return 生成的隨機(jī)顏色對象
*/
private Color getRandColor(int ll, int ul){
if (ll > 255) ll = 255;
if (ll < 1) ll = 1;
if (ul > 255) ul = 255;
if (ul < 1) ul = 1;
if (ul == ll) ul = ll + 1;
int r = random.nextInt(ul - ll) + ll;
int g = random.nextInt(ul - ll) + ll;
int b = random.nextInt(ul - ll) + ll;
Color color = new Color(r,g,b);
return color;
}
/**
* 生成指定字符串的圖像數(shù)據(jù)
* @param verifyCode 即將被打印的隨機(jī)字符串
* @return 生成的圖像數(shù)據(jù)
* */
private BufferedImage getImage(String verifyCode){
BufferedImage image = new BufferedImage(WIDTH * CODE_LENGTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
//獲取圖形上下文
Graphics graphics = image.getGraphics();
//設(shè)置背景色
graphics.setColor(getRandColor(1,50));
//填充背景色
graphics.fillRect(0, 0, WIDTH * 4, HEIGHT);
//設(shè)置邊框顏色
graphics.setColor(new Color(0,255,0));
//畫邊框
for (int i=0; i<2; i++)
graphics.drawRect(i, i, WIDTH * CODE_LENGTH - i * 2 - 1, HEIGHT - i * 2 - 1);
//設(shè)置隨機(jī)干擾線條顏色
graphics.setColor(getRandColor(50,100));
//產(chǎn)生50條干擾線條
for (int i=0; i<50; i++){
int x1 = random.nextInt(WIDTH * CODE_LENGTH - 4) + 2;
int y1 = random.nextInt(HEIGHT - 4) + 2;
int x2 = random.nextInt(WIDTH * CODE_LENGTH - 2 - x1) + x1;
int y2 = y1;
graphics.drawLine(x1, y1, x2, y2);
}
//設(shè)置字體
graphics.setFont(new Font("Times New Roman", Font.PLAIN, 18));
//畫字符串
for (int i=0; i<this.CODE_LENGTH; i++){
String temp = verifyCode.substring(i, i+1);
graphics.setColor(getRandColor(100,255));
graphics.drawString(temp, 13 * i + 6, 16);
}
//圖像生效
graphics.dispose();
return image;
}
/**
* 將驗證碼的圖像輸出
* @param request 用戶的請求對象
* @param response 用戶的響應(yīng)對象
* */
public void printImage(HttpServletRequest request,
HttpServletResponse response){
//將ContentType設(shè)為"image/jpeg",讓瀏覽器識別圖像格式。
response.setContentType("image/jpeg");
//設(shè)置頁面不緩存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 2000);
//獲得隨機(jī)驗證碼
String verifyCode = this.getRandString();
String str = "ssss";
for(int i=0; i<10; i++)
str = str + str;
//獲得驗證碼的圖像數(shù)據(jù)
BufferedImage bi = this.getImage(verifyCode);
//把驗證碼存入session
request.getSession().setAttribute(ATTRIBUTE_NAME, verifyCode);
try{
//獲得Servlet輸出流
ServletOutputStream outStream = response.getOutputStream();
//創(chuàng)建可用來將圖像數(shù)據(jù)編碼為JPEG數(shù)據(jù)流的編碼器
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outStream);
//將圖像數(shù)據(jù)進(jìn)行編碼
encoder.encode(bi);
//強(qiáng)行將緩沖區(qū)的內(nèi)容輸入到頁面
outStream.flush();
//關(guān)閉輸出流
outStream.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
/**
* 檢查輸入的驗證碼是否正確,若用戶輸入的驗證碼與生成的驗證碼相符則返回true,否則返回false。
* @param request 用戶的請求對象
* @return 驗證結(jié)果
* */
public boolean check(HttpServletRequest request){
if (((String)request.getParameter(ATTRIBUTE_NAME))
.equalsIgnoreCase((String)request.getSession().getAttribute(ATTRIBUTE_NAME))){
request.getSession().removeAttribute(ATTRIBUTE_NAME);
return true;
}
return false;
}
}
/**此代碼為我們?nèi)豪洗笊钋镄∮?br />
所編寫,真的比較實(shí)用,來自qq群J道
**/
為什么我寫的一個顯示系統(tǒng)時間的小腳本不能在這里顯示出來?
還有就是如何使用DOM的getelementbyid方法顯示系統(tǒng)時間?
<SCRIPT LANGUAGE="JavaScript">
<!--
var timerID = null
var timerRunning = false
function showtime(){
var today,hour,second,minute,year,month,date;
var strDate ;
today=new Date();
var n_day = today.getDay();
switch (n_day)
{
case 0:{
strDate = "星期日"
}break;
case 1:{
strDate = "星期一"
}break;
case 2:{
strDate ="星期二"
}break;
case 3:{
strDate = "星期三"
}break;
case 4:{
strDate = "星期四"
}break;
case 5:{
strDate = "星期五"
}break;
case 6:{
strDate = "星期六"
}break;
case 7:{
strDate = "星期日"
}break;
}
year = today.getYear();
month = today.getMonth()+1;
date = today.getDate();
hour = today.getHours();
minute =today.getMinutes();
second = today.getSeconds();
if(month<10) month="0"+month;
if(date<10) date="0"+date;
if(hour<10) hour="0"+hour;
if(minute<10) minute="0"+minute;
if(second<10) second="0"+second;
timeValue =year + " 年 " + month + " 月 " + date + " 日 " + strDate +" " + hour + ":" + minute + ":" + second
document.GG.MM.value = timeValue
wuxingjia= setTimeout("showtime()",1000)
}
//-->
</SCRIPT>
</HEAD> <BODY onLoad="showtime()">
<FORM NAME="GG" onSubmit="0">
<INPUT TYPE="text" NAME="MM" SIZE=40 >
</FORM>
1、取出剛剛插入(刪除)的數(shù)據(jù)SELECT 字段名 FROM INSERTED(DELETED)
2、對于UPDATE實(shí)際上是先DELETE然后再INSERT所以如果想得到UPDATE前后的數(shù)據(jù)值,應(yīng)該先從DELETED取出,然后從INSERTED取出;
3、IF UPDATE(列名)可以判斷更新或插入哪一個字段的值;
4、@@ROWCOUNT可以判斷上一行查詢操作得到的列數(shù);
5、給變量賦值用SET @ZQB = 13;
6、察看是否有符合條件的記錄IF EXISTS (SELECT name FROM sysobjects WHERE name = 'reminder' AND type = 'TR');
7、定義游標(biāo),如下:
DECLARE c1 CURSOR FOR
SELECT emp_mgr.emp
FROM emp_mgr, inserted
WHERE emp_mgr.emp = inserted.mgr
OPEN c1
FETCH NEXT FROM c1 INTO @e--從游標(biāo)中取出數(shù)據(jù)
WHILE @@fetch_status = 0--判斷是否到最后
BEGIN
UPDATE emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1 -- Add 1 for newly
WHERE emp_mgr.emp = @e -- added employee.
FETCH NEXT FROM c1 INTO @e
END
CLOSE c1
DEALLOCATE c1--刪除游標(biāo)引用
如何了解用戶和需求
如何了解用戶需求?根據(jù)用戶是否主動參與分為顯式與隱式兩種挖掘模式,因為顯式的動靜比較大,有很大局限性,所以為了保證結(jié)果準(zhǔn)確性以及提高用戶接受度,一般都采用隱式。
用戶的日常交互行為會產(chǎn)生四類關(guān)鍵數(shù)據(jù):鼠標(biāo)移動軌跡、鏈接點(diǎn)擊分布、頁面瀏覽流、頁面停留時間。通過用戶的行為能反映用戶的觀點(diǎn),同時利用訪問的網(wǎng)頁次序可以找出網(wǎng)頁之間的隱性關(guān)系。
收集數(shù)據(jù)
Web服務(wù)器的日志(用戶會話記錄)
Web trends或類似的第三方共享軟件(客戶端分析,流量分析,可用性分析)
自己開發(fā)的第三方軟件/插件(需求自定義)
大型網(wǎng)站通常會把以上三種方法組合應(yīng)用,大致原理就是給進(jìn)入網(wǎng)站的用戶賦予身份識別,每次產(chǎn)生交互動作就向服務(wù)器發(fā)回請求,通過時間和頁面判斷連接各個請求點(diǎn)并且記錄下來。(算法不討論)
過濾數(shù)據(jù)
明確目標(biāo),定義核心數(shù)據(jù)。
界定用戶行為,利用多數(shù)人的行為來消除個人行為的主觀性。
對用戶進(jìn)行歸類,確定數(shù)據(jù)類別。
大型網(wǎng)站每天所產(chǎn)生的數(shù)據(jù)量是驚人的,所以常規(guī)需求一般都是定時或定量的分析。另外,額外的數(shù)據(jù)處理會減慢網(wǎng)站的速度,搜集的數(shù)據(jù)越多,潛在的負(fù)面影響越大。
習(xí)慣分析
對用戶瀏覽過的頁面進(jìn)行內(nèi)容分析,根據(jù)信息主題對頁面進(jìn)行聚類。
聚類過程中除了考慮頁面內(nèi)容相近程度,還應(yīng)該考慮頁面路徑。
把用戶瀏覽行為對其興趣的作用列入聚類結(jié)果,得到綜合評估模型。
用戶興趣分偶然和穩(wěn)定兩種情況,其中偶然可以認(rèn)為是隨機(jī)變化的,穩(wěn)定的挖掘又有基于內(nèi)容和行為兩種方式,在內(nèi)容上表現(xiàn)有重復(fù)度、相似度等,在行為上表現(xiàn)有停留時長、點(diǎn)此次數(shù)、拉動滾動條次數(shù)等。
實(shí)際案例
類似系統(tǒng)、瀏覽器、分辨率的客戶端分析,常見而且簡單,略過。
關(guān)于鼠標(biāo)軌跡、點(diǎn)擊分布的可用性例子:
跟蹤用戶在進(jìn)行檢索時的鼠標(biāo)移動軌跡,可以獲取用戶操作的先后順序、熱點(diǎn)功能、動作曲線等一手?jǐn)?shù)據(jù),這些都是改善或簡化表單的重要參考。
在重要的頁面進(jìn)行詳細(xì)的點(diǎn)擊分布監(jiān)控統(tǒng)計,主要檢查信息呈現(xiàn)的易用性,看看有沒有偏離設(shè)計初衷,經(jīng)常更新,找到規(guī)律。
處理特定用戶行為、用戶群、用戶來路的任務(wù)流例子:
監(jiān)控分布式注冊流程,能夠看到有多少用戶填了表單、填完了表單,或者在某個步驟有異常流失。
監(jiān)控不同模塊入口過來的注冊用戶,能夠統(tǒng)計出各模塊導(dǎo)入的有效注冊量、百分比、成功率,以便合理調(diào)配資源。
監(jiān)控投放廣告過來的注冊量、注冊成功率、轉(zhuǎn)換付費(fèi)用戶成功率,以便明確廣告的投入產(chǎn)出比。
監(jiān)控用戶的縱深瀏覽行為,是測試導(dǎo)航可用性很好的辦法,也就是說用戶會不會在你的網(wǎng)站內(nèi)迷路。