2009年12月21日
#
If you are building standalone application in Java, Maven is your friend when packing your application,
There are two way to let Maven package your application, either as a single jar with all your dependencies jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
One advantage if you choose to do this way is if you need to sign your application jar.
This is needed if you are building a Java Web Start client and you need more access than connecting back to the server.
To read more about have Maven signing your jar read http://maven.apache.org/plugins/maven-jar-plugin/usage.html.
But if you choose to go this way, make sure that all license agreement are shipped with your one single jar.
Another way is to let Maven package your source code only and then referring the dependent jar file from the MANIFEST file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>se.msc.adapter.Main</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
public class Main {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("15370720.pdf4"), "utf-16");
LineNumberReader lnr=new LineNumberReader(isr);
String line = null;
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+"\t"+line);
}
}
}
兩個(gè)方法的區(qū)別是資源的定義不同, 一個(gè)主要用于相對(duì)與一個(gè)object取資源,而另一個(gè)用于取相對(duì)于classpath的
資源,用的是絕對(duì)路徑。
在使用Class.getResourceAsStream 時(shí), 資源路徑有兩種方式, 一種以 / 開頭,則這樣的路徑是指定絕對(duì)
路徑, 如果不以 / 開頭, 則路徑是相對(duì)與這個(gè)class所在的包的。
在使用ClassLoader.getResourceAsStream時(shí), 路徑直接使用相對(duì)于classpath的絕對(duì)路徑。
舉例,下面的三個(gè)語句,實(shí)際結(jié)果是一樣的:
com.explorers.Test.class.getResourceAsStream("abc.jpg")
= com.explorers.Test.class.getResourceAsStream("/com/explorers/abc.jpg")
= ClassLoader.getResourceAsStream("com/explorers/abc.jpg")
There's a variety of clients for CAS. The
Java-based clients (JA-SIG, Yale, see JA-SIG
website) typically handle the browser-based client interaction with
CAS very well through ServletFilter implementations.
Now what
about programmatic authentication, i.e. achieving authentication through
non-browser based applications? There exists a CAS
.NET client but I did not manage to find the appropriate Java
implementation. So here goes - it is based on the Apache HttpClient.
In
case I missed any existing implementation achieving the same purpose,
let's look at the bright side: at least now I understand the CAS
protocol :-)
My CAS client works within any application. It uses
the HttpClient and behaves like a browser client as CAS requires cookie
support.
Here's the code:
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
/**
* The CasClient allows users to programmatically login
* to CAS protected services based on the CAS 2 protocol.
* This client behaves like a browser-client in terms of
* cookie handling.<br>
*
* @author Mathias Richter
*/
public class CasClient
{
public static Logger LOG = Logger.getLogger( CasClient.class );
public static final String LOGIN_URL_PART = "login";
public static final String SERVICE_VALIDATE_URL_PART = "serviceValidate";
public static final String TICKET_BEGIN = "ticket=";
private static final String LT_BEGIN = "name="lt" value="";
public static final String CAS_USER_BEGIN = "<cas:user>";
public static final String CAS_USER_END = "</cas:user>";
private HttpClient fClient;
private String fCasUrl;
/**
* Construct a new CasClient.
*
* @param casUrl The base URL of the CAS service to be used.
*/
public CasClient( String casBaseUrl )
{
this( new HttpClient(), casBaseUrl );
}
/**
* Construct a new CasClient which uses the specified HttpClient
* for its HTTP calls.
*
* @param client
* @param casBaseUrl
*/
public CasClient( HttpClient client, String casBaseUrl )
{
fClient = client;
fCasUrl = casBaseUrl;
}
/**
* Authenticate the specified username with the specified password.
* This will not yield any ticket, as no service is authenticated
* against. This wil just set the CAS cookie in this client upon
* successful authentication.
*
* @param username
* @param password
*/
public void authenticate( String username, String password )
{
authenticate( null, username, password );
}
/**
* Validate the specified service ticket against the specified service.
* If the ticket is valid, this will yield the clear text user name
* of the autenticated user.<br>
* Note that each service ticket issued by CAS can be used exactly once
* to validate.
*
* @param serviceUrl
* @param serviceTicket
*
* @return Clear text username of the authenticated user.
*/
public String validate( String serviceUrl, String serviceTicket )
{
String result = null;
PostMethod method = new PostMethod( fCasUrl + SERVICE_VALIDATE_URL_PART );
method.setParameter( "service", serviceUrl );
method.setParameter( "ticket", serviceTicket );
try
{
int statusCode = fClient.executeMethod(method);
if (statusCode != HttpStatus.SC_OK)
{
LOG.error( "Could not validate: " + method.getStatusLine() );
method.releaseConnection();
} else
{
result = extractUser( new String( method.getResponseBody() ) );
}
} catch ( Exception x )
{
LOG.error( "Could not validate: " + x.toString () );
x.printStackTrace();
}
method.releaseConnection();
return result;
}
/**
* Authenticate the specified user with the specified password against the
* specified service.
*
* @param serviceUrl May be null. If a url is specified, the authentication will happen against this service, yielding a service ticket which can be validated.
* @param username
* @param password
* @return A valid service ticket, if and only if the specified service URL is not null.
*/
public String authenticate( String serviceUrl, String username, String password )
{
String lt = getLt( serviceUrl );
if ( lt == null )
{
LOG.error( "Cannot retrieve LT from CAS. Aborting authentication for '" + username + "'" );
return null;
}
String result = null;
PostMethod method = new PostMethod( fCasUrl + LOGIN_URL_PART );
if ( serviceUrl != null ) // optional
method.setParameter( "service", serviceUrl );
method.setParameter( "_eventId", "submit" );
method.setParameter("username", username );
method.setParameter("password", password );
method.setParameter("lt", lt );
method.setParameter( "gateway", "true" );
try
{
fClient.executeMethod(method);
if ( serviceUrl == null )
{
if ( extractLt( new String( method.getResponseBody() ) ) != null ) // if CAS does not return a login page with an LT authentication was successful
{
LOG.error( "Authentication for '" + username + "' unsuccessful" );
if ( LOG.isDebugEnabled() )
LOG.debug( "Authentication for '" + username + "' unsuccessful." );
} else
{
if ( LOG.isDebugEnabled() )
LOG.debug( "Authentication for '" + username + "' unsuccessful." );
}
} else
{
Header h = method.getResponseHeader( "Location" );
if ( h != null )
result = extractServiceTicket( h.getValue() );
if ( result == null )
LOG.error( "Authentication for '" + username + "' unsuccessful." );
}
} catch ( Exception x )
{
LOG.error( "Could not authenticate'" + username + "':" + x.toString () );
}
method.releaseConnection();
return result;
}
/**
* Helper method to extract the user name from a "service validate" call to CAS.
*
* @param data Response data.
* @return The clear text username, if it could be extracted, null otherwise.
*/
protected String extractUser( String data )
{
String user = null;
int start = data.indexOf( CAS_USER_BEGIN );
if ( start >= 0 )
{
start += CAS_USER_BEGIN.length();
int end = data.indexOf( CAS_USER_END );
if ( end > start )
user = data.substring( start, end );
else
LOG.warn( "Could not extract username from CAS validation response. Raw data is: '" + data + "'" );
} else
{
LOG.warn( "Could not extract username from CAS validation response. Raw data is: '" + data + "'" );
}
return user;
}
/**
* Helper method to extract the service ticket from a login call to CAS.
*
* @param data Response data.
* @return The service ticket, if it could be extracted, null otherwise.
*/
protected String extractServiceTicket( String data )
{
String serviceTicket = null;
int start = data.indexOf( TICKET_BEGIN );
if ( start > 0 )
{
start += TICKET_BEGIN.length();
serviceTicket = data.substring( start );
}
return serviceTicket;
}
/**
* Helper method to extract the LT from a login form from CAS.
*
* @param data Response data.
* @return The LT, if it could be extracted, null otherwise.
*/
protected String extractLt( String data )
{
String token = null;
int start = data.indexOf( LT_BEGIN );
if ( start < 0 )
{
LOG.error( "Could not obtain LT token from CAS: LT Token not found in response." );
} else
{
start += LT_BEGIN.length();
int end = data.indexOf( """, start );
token = data.substring( start, end );
}
return token;
}
/**
* This method requests the original login form from CAS.
* This form contains an LT, an initial token that must be
* presented to CAS upon sending it an authentication request
* with credentials.<br>
* If a service URL is provided (which is optional), this method
* will post the URL such that CAS authenticates against the
* specified service when a subsequent authentication request is
* sent.
*
* @param serviceUrl
* @return The LT token if it could be extracted from the CAS response.
*/
protected String getLt( String serviceUrl )
{
String lt = null;
HttpMethod method = null;
if ( serviceUrl == null )
method = new GetMethod( fCasUrl + LOGIN_URL_PART );
else
{
method = new PostMethod( fCasUrl + LOGIN_URL_PART );
( ( PostMethod ) method ).setParameter( "service", serviceUrl );
}
try
{
int statusCode = fClient.executeMethod(method);
if (statusCode != HttpStatus.SC_OK)
{
LOG.error( "Could not obtain LT token from CAS: " + method.getStatusLine() );
method.releaseConnection();
} else
{
Object o = method.getResponseHeaders() ;
return extractLt( new String( method.getResponseBody() ) );
}
} catch ( Exception x )
{
LOG.error( "Could not obtain LT token from CAS: " + x.toString () );
}
method.releaseConnection();
return lt;
}
}
System.getProperty("line.separator")
html
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
servlet
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setDateHeader("expires", 0);
response.addHeader("P3P","CP=CAO PSA OUR");
原文地址 http://lsong17.spaces.live.com/blog/cns!556C21919D77FB59!603.trak
用vim這么久
了,始終也不知道怎么在vim中使用系統(tǒng)粘貼板,通常要在網(wǎng)上復(fù)制一段代碼都是先gedit打開文件,中鍵粘貼后關(guān)閉,然后再用vim打開編輯,真的不
爽;上次論壇上有人問到了怎么在vim中使用系統(tǒng)粘貼板,印象里回復(fù)很多,有好幾頁的回復(fù)卻沒有解決問題,今天實(shí)在受不了了又在網(wǎng)上找辦法,竟意外地找到
了,貼出來分享一下。
如果只是想使用系統(tǒng)粘貼板的話直接在輸入模式按Shift+Inset就可以了,下面講一下vim的粘貼板的基礎(chǔ)知識(shí),有興趣的可以看看,
應(yīng)該會(huì)有所收獲的。
vim幫助文檔里與粘貼板有關(guān)的內(nèi)容如下:
- vim有12個(gè)粘貼板,分別是0、1、2、...、9、a、“、+;用:reg命令可以查看各個(gè)粘貼板里的內(nèi)容。在vim中簡單用y只是復(fù)制到
“(雙引號(hào))粘貼板里,同樣用p粘貼的也是這個(gè)粘貼板里的內(nèi)容;
- 要將vim的內(nèi)容復(fù)制到某個(gè)粘貼板,需要退出編輯模式,進(jìn)入正常模式后,選擇要復(fù)制的內(nèi)容,然后按"Ny完成復(fù)制,其中N為粘
貼板號(hào)(注意是按一下雙引號(hào)然后按粘貼板號(hào)最后按y),例如要把內(nèi)容復(fù)制到粘貼板a,選中內(nèi)容后按"ay就可以了,有兩點(diǎn)需要說明一下:
- “號(hào)粘貼板(臨時(shí)粘貼板)比較特殊,直接按y就復(fù)制到這個(gè)粘貼板中了,直接按p就粘貼這個(gè)粘貼板中的內(nèi)容;
- +號(hào)粘貼板是系統(tǒng)粘貼板,用"+y將內(nèi)容復(fù)制到該粘貼板后可以使用Ctrl+V將其粘貼到其他文檔(如firefox、gedit)
中,同理,要把在其他地方用Ctrl+C或右鍵復(fù)制的內(nèi)容復(fù)制到vim中,需要在正常模式下按"+p;
- 要將vim某個(gè)粘貼板里的內(nèi)容粘貼進(jìn)來,需要退出編輯模式,在正常模式按"Np,其中N為粘貼板號(hào),如上所述,可以按"5p將
5號(hào)粘貼板里的內(nèi)容粘貼進(jìn)來,也可以按"+p將系統(tǒng)全局粘貼板里的內(nèi)容粘貼進(jìn)來。
注意:在我這里,只有vim.gtk或vim.gnome才能使用系統(tǒng)全局粘貼板,默認(rèn)的
vim.basic看不到+號(hào)寄存器。
登錄LINUX系統(tǒng)后,經(jīng)常會(huì)看到"you have mail",卻苦于不知道如何查看,相信菜鳥們都遇到過,偶在網(wǎng)上用“linux
mail"找了很久,但大都是介紹mail服務(wù)器的,黃天總算沒負(fù)有心人,在洪恩在找到一篇介紹基礎(chǔ)的文章,不敢獨(dú)享。
系統(tǒng)提供了用戶
之間通信的郵件系統(tǒng),當(dāng)用戶打開終端注冊(cè)登錄時(shí)發(fā)現(xiàn)系統(tǒng)給出如下信息:
you have mail.
這時(shí)用戶可通過鍵入mail命令讀取信件:
$ mail
mail程序?qū)⒅饌€(gè)顯示用戶的信件,并依照時(shí)間順序,顯示最新的信件。每顯示一段信件,mail都詢問用戶是否要對(duì)該信件作些處理。若用戶回答d,則表示
刪除信件;若僅按回車鍵,表示對(duì)信件不作任何改動(dòng)(信件仍舊保存,下次還可讀這一信件);若回答p,則要求重復(fù)顯示信件;s
filename表示要把信件存入所命名的文件;若回答q,表示要從mail退出。
我們?cè)诒菊碌牡谝粋€(gè)例子中演示了如何寫一封信,作為練習(xí),你可送信件給自己,然后鍵入mail讀取自己發(fā)的信件,看看會(huì)有什么效果。(發(fā)信給自己是一種設(shè)
置備忘錄的方法)。
$mail frank 給自己寫信
subject: test
This is a mail test
CRL-d
EOT
$
$mail 查看信件
“/var/spool/mail/frank:”1 message 1 new
>Nfrank@xteam.xteamlinux.comThu
Mar 25 11:00 13/403 “test”
&
Message 1:
From frank Thu Mar 25 11:00:25 1999/3/25
Received: (fromfrank@localhost)
by xteam.xteamlinux.com(8.8.4/8.8.4)
id LAA05170 for frank;Thu 25 Mar 1999 11:00:25 GMT
Date: Thu,25 Mar 1999 11:00:25 GMT
From:RHS Linux User <frank@xteam.xteamlinux.com>
Message-Id:<199903251142.LAA05170@xteam.xteamlinux.com>
To:frank@xteam.xteamlinux.com
Subject:test
Status:R
This is a mail test
&
mail命令還有很多其它用法,例如發(fā)送事先準(zhǔn)備好的信件,或一次送信給若干人。還可以用其它方法送信件。
Mysql中l(wèi)imit的用法:在我們使用查詢語句的時(shí)候,經(jīng)常要返回前幾條或者中間某幾行數(shù)據(jù),這個(gè)時(shí)候怎么辦呢?
不用擔(dān)心,mysql已經(jīng)為我們提供了這樣一個(gè)功能。
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
LIMIT 子句可以被用于強(qiáng)制 SELECT 語句返回指定的記錄數(shù)。LIMIT 接受一個(gè)或兩個(gè)數(shù)字參數(shù)。參數(shù)必須是一個(gè)整數(shù)常量。
如果給定兩個(gè)參數(shù),第一個(gè)參數(shù)指定第一個(gè)返回記錄行的偏移量,第二個(gè)參數(shù)指定返回記錄行的最大數(shù)目。初始記錄行的偏移量是 0(而不是 1):
為了與 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15
//為了檢索從某一個(gè)偏移量到記錄集的結(jié)束所有的記錄行,可以指定第二個(gè)參數(shù)為 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.
//如果只給定一個(gè)參數(shù),它表示返回最大的記錄行數(shù)目:
mysql> SELECT * FROM table LIMIT 5; //檢索前 5 個(gè)記錄行
//換句話說,LIMIT n 等價(jià)于 LIMIT 0,n。
注意limit 10和limit 9,1的不同:
例如:
1.Select * From cyclopedia Where ID>=(
Select Max(ID) From (
Select ID From cyclopedia Order By ID limit 90001
) As tmp
) limit 100;
2.Select * From cyclopedia Where ID>=(
Select Max(ID) From (
Select ID From cyclopedia Order By ID limit 90000,1
) As tmp
) limit 100;
第1句是先取了前90001條記錄,取其中最大一個(gè)ID值作為起始標(biāo)識(shí),然后利用它可以快速定位下100條記錄
第2句擇是僅僅取90000條記錄后1條,然后取ID值作起始標(biāo)識(shí)定位下100條記錄
第1句執(zhí)行結(jié)果.100 rows in set (0.23) sec
第2句執(zhí)行結(jié)果.100 rows in set (0.19) sec
其實(shí)第2句完全可以簡化成:
Select * From cyclopedia Where ID>=(
Select ID From cyclopedia limit 90000,1
)limit 100;
直接利用第90000條記錄的ID,不用經(jīng)過Max運(yùn)算,這樣做理論上效率因該高一些,但在實(shí)際使用中幾乎看不到效果,
因?yàn)楸旧矶ㄎ籌D返回的就是1條記錄,Max幾乎不用運(yùn)作就能得到結(jié)果,但這樣寫更清淅明朗,省去了畫蛇那一足.
Select Top 100 * From cyclopedia Where ID>=(
Select Top 90001 Max(ID) From (
Select ID From cyclopedia Order By ID
) As tmp
)
但不管是實(shí)現(xiàn)方式是存貯過程還是直接代碼中,瓶頸始終在于MS-SQL的TOP總是要返回前N個(gè)記錄,這種情況在數(shù)據(jù)量不大時(shí)感受不深,
但如果成百上千萬,效率肯定會(huì)低下的.相比之下MySQL的limit就有優(yōu)勢(shì)的多,執(zhí)行:
Select ID From cyclopedia limit 90000
Select ID From cyclopedia limit 90000,1
的結(jié)果分別是:
90000 rows in set (0.36) sec
1 row in set (0.06) sec
而MS-SQL只能用Select Top 90000 ID From cyclopedia 執(zhí)行時(shí)間是390ms,執(zhí)行同樣的操作時(shí)間也不及MySQL的360ms.
limit的offset(偏移量)用于記錄較多的時(shí)候,記錄較少時(shí),偏移offset較小,直接使用limit較優(yōu)。offset越大,后者越優(yōu)。
1、offset比較小的時(shí)候。
select * from yanxue8_visit limit 10,10
多次運(yùn)行,時(shí)間保持在0.0004-0.0005之間
Select * From yanxue8_visit Where vid >=(
Select vid From yanxue8_visit Order By vid limit 10,1
) limit 10
多次運(yùn)行,時(shí)間保持在0.0005-0.0006之間,主要是0.0006
結(jié)論:偏移offset較小的時(shí)候,直接使用limit較優(yōu)。這個(gè)顯示是子查詢的原因。
2、offset大的時(shí)候。
select * from yanxue8_visit limit 10000,10
多次運(yùn)行,時(shí)間保持在0.0187左右
Select * From yanxue8_visit Where vid >=(
Select vid From yanxue8_visit Order By vid limit 10000,1
) limit 10
多次運(yùn)行,時(shí)間保持在0.0061左右,只有前者的1/3。可以預(yù)先offset越大,后者越優(yōu)。
mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.
//如果只給定一個(gè)參數(shù),它表示返回最大的記錄行數(shù)目.
public enum OrderStatus {
A(1), B(2), C(3), D(4), F(5), INCOMPLETE(6);
private final int value;
/**
* Constructor.
*/
private OrderStatus(int value) {
this.value = value;
}
/**
* Get the value.
* @return the value
*/
public int getValue() {
return value;
}
}
<script language="javascript">
try
{
throw new
Error(10,"asdasdasd")
}
catch (e)
{
alert(e.message);
alert(e.description)
alert(e.number)
alert(e.name)
throw new
Error(10,"asdasdasd")
}
</script>
在JavaScript可以使用try...catch來進(jìn)行異常處理。例如:
try {
foo.bar();
} catch (e) {
alert(e.name + ": " + e.message);
}
目前我們可能得到的系統(tǒng)異常主要包含以下6種:
- EvalError: raised when an error occurs
executing code in eval()
- RangeError: raised when a numeric
variable or parameter is outside of its valid range
- ReferenceError: raised when
de-referencing an invalid reference
- SyntaxError: raised when a syntax
error occurs while parsing code in eval()
- TypeError: raised when a variable or
parameter is not a valid type
- URIError: raised when encodeURI() or
decodeURI() are passed invalid parameters
上面的六種異常對(duì)象都繼承自Error對(duì)象。他們都支持以下兩種構(gòu)造方法:
new Error();
new Error("異常信息");
手工拋出異常的方法如下:
try {
throw new Error("Whoops!");
} catch (e) {
alert(e.name + ": " + e.message);
}
如要判斷異常信息的類型,可在catch中進(jìn)行判斷:
try {
foo.bar();
} catch (e) {
if (e instanceof EvalError) {
alert(e.name + ":" + e.message);
}
else if (e instanceof RangeError) {
alert(e.name + ": " + e.message);
}
// etc
}
Error具有下面一些主要屬性:
- description: 錯(cuò)誤描述 (僅IE可用).
- fileName: 出錯(cuò)的文件名 (僅Mozilla可用).
- lineNumber: 出錯(cuò)的行數(shù) (僅Mozilla可用).
- message: 錯(cuò)誤信息 (在IE下同description)
- name: 錯(cuò)誤類型.
- number: 錯(cuò)誤代碼 (僅IE可用).
- stack: 像Java中的Stack Trace一樣的錯(cuò)誤堆棧信息 (僅Mozilla可用).
因此為了更好的了解錯(cuò)誤信息我們可以將catch部分改為如下形式:
try {
foo.bar();
} catch (e) {
if (browserType != BROWSER_IE) {
alert("name: " + e.name +
"message: " + e.message +
"lineNumber: " + e.lineNumber +
"fileName: " + e.fileName +
"stack: " + e.stack);
}
else {
alert("name: " + e.name +
"errorNumber: " + (e.number & 0xFFFF ) +
"message: " + e.message");
}
}
JavaScript中的throw命令事實(shí)上可以拋出任何對(duì)象,并且我們可以在catch接受到此對(duì)象。例
如:
try {
throw new Date(); // 拋出當(dāng)前時(shí)間對(duì)象
} catch (e) {
alert(e.toLocaleString()); // 使用本地格式顯示當(dāng)前時(shí)間
}
import java.io.*;
public class ObjectCloner
{
// so that nobody can accidentally create an ObjectCloner object
private ObjectCloner(){}
// returns a deep copy of an object
static public Object deepCopy(Object oldObj) throws Exception
{
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
// serialize and pass the object
oos.writeObject(oldObj);
oos.flush();
ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bin);
// return the new object
return ois.readObject();
}
catch(Exception e)
{
System.out.println("Exception in ObjectCloner = " + e);
throw(e);
}
finally
{
oos.close();
ois.close();
}
}
}
select cast(1 as char)
char 不能換成varchar,否則會(huì)報(bào)錯(cuò)。
If u are on an unknown
server
and keen to know it’s
linux
distribution info, you can check the linux distribution info by just a
single command (eg. version, codename, etc). Just tested this command in
UBuntu and CentOS, both return as what i expected.
To check linux distribution and
version, follow the steps below:-
Run-->External Tools-->External tools configurations
new 一個(gè) program
location 里面填 :C:\WINDOWS\explorer.exe
Arguments 里面填: ${container_loc}
點(diǎn)擊 Run
ArrayUtils //簡化數(shù)組的操作
LocaleUtils
SerializationUtils
StringEscapeUtils
StringUtils
SystemUtils
Validate //輸入?yún)?shù)驗(yàn)證
NestableException
NestableRuntimeException
StopWatch //秒表類
xmind是繪制思維導(dǎo)圖的工具。
使用之后,發(fā)現(xiàn)繪制組織結(jié)構(gòu)圖和wbs都很方便。
軟件基于eclipse框架開發(fā),反應(yīng)速度和操作性也都很不錯(cuò)。
更重要的,圖形的效果也是專業(yè)級(jí)的 :)
serialVersionUID作用:
序列化時(shí)為了保持版本的兼容性,即在版本升級(jí)時(shí)反序列化仍保持對(duì)象的唯一性。
有兩種生成方式:
一個(gè)是默認(rèn)的1L,比如:private static final long serialVersionUID = 1L;
一個(gè)是根據(jù)類名、接口名、成員方法及屬性等來生成一個(gè)64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
當(dāng)你一個(gè)類實(shí)現(xiàn)了Serializable接口,如果沒有定義serialVersionUID,Eclipse會(huì)提供這個(gè)
提示功能告訴你去定義 。在Eclipse中點(diǎn)擊類中warning的圖標(biāo)一下,Eclipse就會(huì)
自動(dòng)給定兩種生成的方式。如果不想定義它,在Eclipse的設(shè)置中也
可以把它關(guān)掉的,設(shè)置如下:
Window ==> Preferences ==> Java ==> Compiler ==>
Error/Warnings ==>
Potential programming problems
將Serializable class without serialVersionUID的warning改成ignore即可。
如果你沒有考慮到兼容性問題時(shí),就把它關(guān)掉,不過有這個(gè)功能是好的,只要任何類別實(shí)現(xiàn)了Serializable這個(gè)接口的話,如果沒有加入
serialVersionUID,Eclipse都會(huì)給你warning提示,這個(gè)serialVersionUID為了讓該類別
Serializable向后兼容。
如果你的類Serialized存到硬盤上面后,可是后來你卻更改了類別的field(增加或減少或改名),當(dāng)你Deserialize時(shí),就會(huì)出現(xiàn)
Exception的,這樣就會(huì)造成不兼容性的問題。
但當(dāng)serialVersionUID相同時(shí),它就會(huì)將不一樣的field以type的預(yù)設(shè)值Deserialize,可避開不兼容性問題。
ApplicationContext wac = WebApplicationContextUtils .getRequiredWebApplicationContext(config.getServletContext());
環(huán)境->虛擬主機(jī)->default_host->其它屬性(主機(jī)別名)->修改端口
服務(wù)器->應(yīng)用程序服務(wù)器->server1->端口->WC_defaulthost->修改端口
/* 追加自定義驗(yàn)證方法 */
// 身份證號(hào)碼驗(yàn)證
jQuery.validator.addMethod("idcardno", function(value, element) {
return this.optional(element) || isIdCardNo(value);
}, "請(qǐng)正確輸入身份證號(hào)碼");
//字母數(shù)字
jQuery.validator.addMethod("alnum", function(value, element) {
return this.optional(element) || /^[a-zA-Z0-9]+$/.test(value);
}, "只能包括英文字母和數(shù)字");
// 手機(jī)號(hào)碼驗(yàn)證
jQuery.validator.addMethod("cellphone", function(value, element) {
var length = value.length;
return this.optional(element) || (length == 11 && /^(1\d{10})$/.test(value));
}, "請(qǐng)正確填寫手機(jī)號(hào)碼");
// 電話號(hào)碼驗(yàn)證
jQuery.validator.addMethod("telephone", function(value, element) {
var tel = /^(\d{3,4}-?)?\d{7,9}$/g;
return this.optional(element) || (tel.test(value));
}, "請(qǐng)正確填寫電話號(hào)碼");
// 郵政編碼驗(yàn)證
jQuery.validator.addMethod("zipcode", function(value, element) {
var tel = /^[0-9]{6}$/;
return this.optional(element) || (tel.test(value));
}, "請(qǐng)正確填寫郵政編碼");
// 漢字
jQuery.validator.addMethod("chcharacter", function(value, element) {
var tel = /^[\u4e00-\u9fa5]+$/;
return this.optional(element) || (tel.test(value));
}, "請(qǐng)輸入漢字");
/**
* 身份證號(hào)碼驗(yàn)證
*
*/
function isIdCardNo(num) {
var factorArr = new Array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1);
var parityBit=new Array("1","0","X","9","8","7","6","5","4","3","2");
var varArray = new Array();
var intValue;
var lngProduct = 0;
var intCheckDigit;
var intStrLen = num.length;
var idNumber = num;
// initialize
if ((intStrLen != 15) && (intStrLen != 18)) {
return false;
}
// check and set value
for(i=0;i<intStrLen;i++) {
varArray[i] = idNumber.charAt(i);
if ((varArray[i] < '0' || varArray[i] > '9') && (i != 17)) {
return false;
} else if (i < 17) {
varArray[i] = varArray[i] * factorArr[i];
}
}
if (intStrLen == 18) {
//check date
var date8 = idNumber.substring(6,14);
if (isDate8(date8) == false) {
return false;
}
// calculate the sum of the products
for(i=0;i<17;i++) {
lngProduct = lngProduct + varArray[i];
}
// calculate the check digit
intCheckDigit = parityBit[lngProduct % 11];
// check last digit
if (varArray[17] != intCheckDigit) {
return false;
}
}
else{ //length is 15
//check date
var date6 = idNumber.substring(6,12);
if (isDate6(date6) == false) {
return false;
}
}
return true;
}
/**
* 判斷是否為“YYYYMM”式的時(shí)期
*
*/
function isDate6(sDate) {
if(!/^[0-9]{6}$/.test(sDate)) {
return false;
}
var year, month, day;
year = sDate.substring(0, 4);
month = sDate.substring(4, 6);
if (year < 1700 || year > 2500) return false
if (month < 1 || month > 12) return false
return true
}
/**
* 判斷是否為“YYYYMMDD”式的時(shí)期
*
*/
function isDate8(sDate) {
if(!/^[0-9]{8}$/.test(sDate)) {
return false;
}
var year, month, day;
year = sDate.substring(0, 4);
month = sDate.substring(4, 6);
day = sDate.substring(6, 8);
var iaMonthDays = [31,28,31,30,31,30,31,31,30,31,30,31]
if (year < 1700 || year > 2500) return false
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) iaMonthDays[1]=29;
if (month < 1 || month > 12) return false
if (day < 1 || day > iaMonthDays[month - 1]) return false
return true
}
為了在windows和linux平臺(tái)公用相同的郵件客戶端和郵件內(nèi)容,主要是有時(shí)候切換操作系統(tǒng)又要看以前的郵件。最后找到了
thunderbird(下面簡稱TB)客戶端。這個(gè)客戶端就是有點(diǎn)慢,倒是能滿足我的要求。但是它的默認(rèn)設(shè)置有時(shí)候有點(diǎn)不符合我們的使用習(xí)慣,我對(duì)它的
設(shè)置作了下面的一些修改:
1:轉(zhuǎn)發(fā)郵件
默認(rèn)的設(shè)置轉(zhuǎn)發(fā)把郵件的內(nèi)容作為附件轉(zhuǎn)發(fā)。這樣有兩個(gè)不好的地方:第一,如果郵件有附件,這個(gè)附件不能轉(zhuǎn)發(fā);第二,接收方必須要用TB客戶端了,否則打不
開。
修改:編輯 -> 首選項(xiàng) -> 編寫 -> 常規(guī):轉(zhuǎn)發(fā)消息改成內(nèi)聯(lián)
2:其它郵件客戶端接收TB發(fā)的中文附件是亂碼
這個(gè)是標(biāo)準(zhǔn)問題,TB使用的是新的標(biāo)準(zhǔn),但是別的客戶端使用的是舊的標(biāo)準(zhǔn)(具體那個(gè)標(biāo)準(zhǔn)忘了,google一下就可以了)。這樣就會(huì)出現(xiàn)亂碼了。
修改:編輯 -> 首選項(xiàng) -> 高級(jí) ->
配置編輯器:mail.strictly_mime.parm_folding 改成0或者1
3:自動(dòng)打開附件
TB默認(rèn)的是在打開郵件的時(shí)候同時(shí)自動(dòng)打開郵件的附件。這樣的話,如果附件大就很頭痛。
修改:編輯 -> 首選項(xiàng)
-> 高級(jí) -> 配置編輯器:
mail.inline_attachments 改成faulse
mail.content_disposition.type 改成1
4:回復(fù)郵件時(shí)回復(fù)的郵件內(nèi)容在下面
TB默認(rèn)的回復(fù)郵件的回復(fù)內(nèi)容是在下面的,這樣如果郵件來回幾次,回復(fù)比較多,看起來很不方便。
修改:編輯
-> 首選項(xiàng) -> 高級(jí) -> 配置編輯器:Mail.identify.default.reply_on_top值由0改為1
還有一個(gè)問題沒有解決,就是有時(shí)候在TB中打開一個(gè)文件夾,它會(huì)重新建索引還是什么的,這時(shí)候打開一個(gè)文件夾比較慢。看網(wǎng)上有說把這個(gè)文件夾重命名,再創(chuàng)
建一個(gè)同名的文件夾,最后把老的文件夾的內(nèi)容拷貝到新的里面就好了,這個(gè)沒有試過。不過這個(gè)也不是特別大的問題,就沒有繼續(xù)搞了,什么時(shí)候有空再看看,到
時(shí)候再貼上來。
格式: tar 選項(xiàng) 文件目錄列表
功能: 對(duì)文件目錄進(jìn)行打包備份
選項(xiàng):
-c 建立新的歸檔文件
-r 向歸檔文件末尾追加文件
-x 從歸檔文件中解出文件
-O 將文件解開到標(biāo)準(zhǔn)輸出
-v 處理過程中輸出相關(guān)信息
-f 對(duì)普通文件操作
-z 調(diào)用gzip來壓縮歸檔文件,與-x聯(lián)用時(shí)調(diào)用gzip完成解壓縮
-Z 調(diào)用compress來壓縮歸檔文件,與-x聯(lián)用時(shí)調(diào)用compress完成解壓縮
例如:
1.將當(dāng)前目錄下所有.txt文件打包并壓縮歸檔到文件this.tar.gz,我們可以使用
tar czvf this.tar.gz ./*.txt
2.將當(dāng)前目錄下的this.tar.gz中的文件解壓到當(dāng)前目錄我們可以使用
tar xzvf this.tar.gz ./
Application Servers > server1 > Process Definition > Java
Virtual Machine > Custom Properties
虛擬機(jī)參數(shù)在命令行的形式為 -Dproperty=value,在程序中可以用System.getProperty("property")取值。
利用這個(gè)特性可以對(duì)程序運(yùn)行進(jìn)行控制,避免代碼的修改。
地址欄輸入about:support,在打開的頁面有打開配置文件夾的按鈕;
擴(kuò)展在Extensions文件夾下,插件在安裝文件夾下的plugin和其他目錄。
import java.net.URL;
import org.codehaus.xfire.client.Client;
public class XfireClient
{
public static void main(String[] args)
{
DyClient();
}
/**
* You get a DynamicClient when you create a Client with the URL of a WSDL
*/
public static void DyClient()
{
try
{
Client client = new Client(
new URL(
"http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl"));
Object[] results = client.invoke("qqCheckOnline",
new Object[] { "31506173" });
System.out.println((String) results[0]);
}
catch ( Exception e)
{
e.printStackTrace();
}
}
}
必須jar:
commons-codec-1.3.jar
commons-httpclient-3.0.jar
commons-logging-1.0.4.jar
jdom-1.0.jar
wsdl4j-1.6.1.jar
xfire-all-1.2.6.jar
XmlSchema-1.1.jar
import java.io.UnsupportedEncodingException;
public class UTF {
public static void main(String[] args) {
String s = "非常好";
try {
byte[] b = s.getBytes("UTF-8");
for(int i=0; i< b.length; i++){
System.out.println(Integer.toHexString(b[i]).substring(6));
}
System.out.println(new String(b, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
輸出:
e9
9d
9e
e5
b8
b8
e5
a5
bd
非常好
是否需要在State類或Strategy類中訪問Context.
狀態(tài)模式通常需要調(diào)用Context中的方法,以改變Context的狀態(tài)。
Strategy通常不需要。
記號(hào) |
含義 |
舉例 |
匹配 |
. |
任何字符 |
a.. |
a后兩個(gè)字符 |
^ |
行首 |
^wood |
位于行首的wood |
$ |
行尾 |
x$
^INSERT$
^$ |
位于行尾的x
只包含字符串INSERT的行
不包含任何字符的行 |
* |
前導(dǎo)的正則表達(dá)式重復(fù)0或若干次 |
x*
xx*
.*
w.*s |
0或若干次連續(xù)的x
1或多個(gè)連續(xù)的x
0或若干個(gè)字符
以w開始,s結(jié)尾的任何字符串 |
[字符表] |
字符表中的任一 |
[tT]
[a-z]
[a-zA-Z] |
小寫或大寫的t
小寫字母
字母(大寫或小寫) |
[^字符表] |
任一不在字符表中的字符 |
[^0-9]
[^a-zA-Z] |
任何數(shù)字
非字母 |
\{min,max\} |
前導(dǎo)的正則表達(dá)式重復(fù)至少min次,最多max次 |
X\{1,5\}
[0-9]\{3,9\}
[0-9]\{3\}
[0-9]\{3,\} |
最少1個(gè),最多5個(gè)x
3到9個(gè)數(shù)字
正好3個(gè)數(shù)字
至少3個(gè)數(shù)字 |
\(…\) |
將小括號(hào)中匹配的字符串存儲(chǔ)到下一個(gè)寄存器中(1-9) |
^\(.\)
^\(.\)\1 |
行中第1個(gè)字符存到1號(hào)寄存器
行首兩個(gè)字符,且它們相同 |
如下命令含有正則表達(dá)式:
cut
paste
sed
tr
grep
sort
uniq
spring
svn checkout https://src.springframework.org/svn/spring-framework/trunk spring-framework
ant resolve
struts2
svn checkout http://svn.apache.org/repos/asf/struts/struts2/trunk struts2
svn checkout http://svn.apache.org/repos/asf/struts/xwork/trunk/ xwork
mvn install
mvn eclipse:eclipse
tomcat6
svn checkout http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk tc6.0.x
1.下載ant 1.6.x
2. 命令行下執(zhí)行 ant download,下載依賴jar.
在JavaEye論壇上回答網(wǎng)友joyjiang的疑問:“REST的優(yōu)勢(shì)到底是什么?開發(fā)效率?文檔的管理?url的直觀?還是其它的什么優(yōu)勢(shì)呢?”
REST的主要優(yōu)勢(shì)在我看來其實(shí)在于它是一種對(duì)于服務(wù)器的更加有效的抽象方式。
對(duì)于基于網(wǎng)絡(luò)的應(yīng)用來說,你怎么樣看待服務(wù)器,就會(huì)產(chǎn)生什么樣的架構(gòu)風(fēng)格,隨之產(chǎn)生與該架構(gòu)風(fēng)格相關(guān)的交互模式。
RPC架構(gòu)風(fēng)格將服務(wù)器看作是由一些過程組成,客戶端調(diào)用這些過程來執(zhí)行特定的任務(wù)。SOAP就是RPC風(fēng)格的一種架構(gòu)。過程是動(dòng)詞性的(做某件事),因此RPC建模是以動(dòng)詞為中心的。
分布式對(duì)象架構(gòu)風(fēng)格認(rèn)
為服務(wù)器是由一些對(duì)象和對(duì)象上的方法組成,客戶端通過調(diào)用這些對(duì)象上的方法來執(zhí)行特定的任務(wù)。并且客戶端調(diào)用這些對(duì)象上的方法應(yīng)該就像是調(diào)用本地對(duì)象上的
方法一樣,這樣開發(fā)就可以完全按照統(tǒng)一的面向?qū)ο蠓椒▉碜觥5呛芸上В@樣的抽象并不是很有效,因?yàn)榉植际綄?duì)象與本地對(duì)象存在著巨大的本質(zhì)差別,想要掩
蓋這些差別很多時(shí)候甚至是有害無益的。
REST架構(gòu)風(fēng)格并
沒有試圖掩蓋這些差別,而是將服務(wù)器抽象為一組離散資源的集合。資源是一個(gè)抽象的概念,而不是代表某個(gè)具體的東西。注意:要真正理解REST,就一定要增
強(qiáng)自己的抽象思維能力,充分理解到資源是抽象的。如果完全不具有抽象思維的能力,一定要將資源與數(shù)據(jù)庫中的一張表或服務(wù)器端的一個(gè)文件(HTML、
Servlet、JSP、etc.)一一掛起鉤來,就無法真正理解REST了。資源是名詞性的,因此REST建模是以名詞為中心的。
上述
是目前基于網(wǎng)絡(luò)的應(yīng)用的主要的三種抽象方式。這三種不同的抽象方式會(huì)嚴(yán)重影響客戶端與服務(wù)器的交互模式,而不同交互模式的交互效率差別相當(dāng)大。分布式對(duì)象
的交互模式很多時(shí)候效率很低,因?yàn)檠谏w了分布式對(duì)象與本地對(duì)象的差別,很多時(shí)候都會(huì)導(dǎo)致細(xì)粒度的API(需要一再強(qiáng)調(diào)才能讓一些不明就里的架構(gòu)初哥按照正
確的方式來做設(shè)計(jì))。實(shí)踐已經(jīng)證明,與RPC和分布式對(duì)象相比,REST是一種對(duì)于服務(wù)器更加有效的抽象方式,將會(huì)帶來粒度更大和更有效率的交互模式。這
樣的效果與Fielding設(shè)計(jì)REST的初衷是吻合的,REST就是專門為交互的性能和可伸縮性進(jìn)行過優(yōu)化的一種架構(gòu)風(fēng)格。而SOAP在設(shè)計(jì)的時(shí)候優(yōu)先
考慮的從來不是性能和可伸縮性,而是互操作性。除非出現(xiàn)奇跡,否則你種什么,就應(yīng)該長出來什么。你種的是瓜,長出來的就是瓜;你種的是豆,長出來的就是
豆。
Fielding寫到:“
REST提供了一組架構(gòu)約束,當(dāng)作為一個(gè)整體來應(yīng)用時(shí),強(qiáng)調(diào)組件交互的可伸縮性、接口的通用性、組件的獨(dú)立部署、以及用來減少交互延遲、增強(qiáng)安全性、封裝遺留系統(tǒng)的中間組件。”
有
人認(rèn)為REST不是面向?qū)ο蟮模鋵?shí)REST雖然沒有分布式對(duì)象那么面向?qū)ο螅谖铱磥碇辽俦萊PC更加面向?qū)ο蟆0凑铡镀髽I(yè)應(yīng)用架構(gòu)模式》,以動(dòng)詞為中
心建模是什么?是不是就是事務(wù)腳本?以名詞為中心建模是什么?是不是就是領(lǐng)域模型?這就扯遠(yuǎn)了,網(wǎng)絡(luò)通信是否一定需要實(shí)現(xiàn)為面向?qū)ο蟮男问剑艺J(rèn)為是不需
要的。
“REST的主要優(yōu)勢(shì)在我看來其實(shí)在于它是一種對(duì)于服務(wù)器的更加有效的抽象方式。”
這句話等于是,我先把一個(gè)骨架放在這里,還沒有用血肉來充實(shí)它,也就是還沒有舉出具體的實(shí)例來。具體的實(shí)例以后我們還需要來詳細(xì)討論。REST是非常簡練的,同時(shí)又是一種非常強(qiáng)大的抽象方式,在我看來就是從根本上簡化Web開發(fā)的一味良藥。
select index_name from dba_indexes where table_name
in (select table_name from user_tables)
1.位圖索引用于數(shù)據(jù)倉庫,不能用于普通系統(tǒng)
2.使用組合索引. 當(dāng)大量字段同同時(shí)作為過濾條件時(shí),使用組合索引會(huì)大大提高性能。
建立組合索引時(shí),注意小基數(shù)字段在前,大基數(shù)字段在后。
3.同一字段出現(xiàn)在不同表要保持類型一致(確有需要,可使用函數(shù)索引)
4.使用count(*)
5.使用返回單個(gè)結(jié)果的查詢改寫外連接能取得較好的性能
Oracle優(yōu)化器會(huì)自動(dòng)選擇以下三種方式的一種運(yùn)行表連接,但在數(shù)據(jù)環(huán)境上配合強(qiáng)化選擇合適的方式或強(qiáng)制使用某種方式是SQL優(yōu)化的需要:
NESTED LOOP
對(duì)于被連接的數(shù)據(jù)子集較小的情況,nested loop連接是個(gè)較好的選擇。nested loop就是掃描一個(gè)表,每讀到一條記錄,就根據(jù)索引去另一個(gè)表里面查找,沒有索引一般就不會(huì)是 nested loops。
一般在nested loop中, 驅(qū)動(dòng)表滿足條件結(jié)果集不大,被驅(qū)動(dòng)表的連接字段要有索引,這樣就走nested loop。如果驅(qū)動(dòng)表返回記錄太多,就不適合nested loops了。如果連接字段沒有索引,則適合走h(yuǎn)ash join,因?yàn)椴恍枰饕?/p>
可用ordered提示來改變優(yōu)化器默認(rèn)的驅(qū)動(dòng)表,可用USE_NL(table_name1 table_name2)提示來強(qiáng)制使用nested loop。
HASH JOIN
hash join是優(yōu)化器做大數(shù)據(jù)集連接時(shí)的常用方式。優(yōu)化器掃描小表(或數(shù)據(jù)源),利用連接鍵(也就是根據(jù)連接字段計(jì)算hash 值)在內(nèi)存中建立hash表,然后掃描大表,每讀到一條記錄就來探測(cè)hash表一次,找出與hash表匹配的行。
當(dāng)
小表可以全部放入內(nèi)存中,其成本接近全表掃描兩個(gè)表的成本之和。如果表很大不能完全放入內(nèi)存,這時(shí)優(yōu)化器會(huì)將它分割成若干不同的分區(qū),不能放入內(nèi)存的部分
就把該分區(qū)寫入磁盤的臨時(shí)段,此時(shí)要有較大的臨時(shí)段從而盡量提高I/O 的性能。臨時(shí)段中的分區(qū)都需要換進(jìn)內(nèi)存做hash
join。這時(shí)候成本接近于全表掃描小表+分區(qū)數(shù)*全表掃描大表的代價(jià)和。
至于兩個(gè)表都進(jìn)行分區(qū),其好處是可以使用parallel query,就是多個(gè)進(jìn)程同時(shí)對(duì)不同的分區(qū)進(jìn)行join,然后再合并。但是復(fù)雜。
使用hash join時(shí),HASH_AREA_SIZE初始化參數(shù)必須足夠的大,如果是9i,Oracle建議使用SQL工作區(qū)自動(dòng)管理,設(shè)置WORKAREA_SIZE_POLICY 為AUTO,然后調(diào)整PGA_AGGREGATE_TARGET即可。
以下條件下hash join可能有優(yōu)勢(shì):
兩個(gè)巨大的表之間的連接。
在一個(gè)巨大的表和一個(gè)小表之間的連接。
可用ordered提示來改變優(yōu)化默認(rèn)的驅(qū)動(dòng)表,可用USE_HASH(table_name1 table_name2)提示來強(qiáng)制使用hash join。
SORT MERGE JOIN
sort merge join的操作通常分三步:對(duì)連接的每個(gè)表做table access full;對(duì)table access full的結(jié)果進(jìn)行排序;進(jìn)行merge join對(duì)排序結(jié)果進(jìn)行合并。sort merge join性能開銷幾乎都在前兩步。一般是在沒有索引的情況下,9i開始已經(jīng)很少出現(xiàn)了,因?yàn)槠渑判虺杀靖撸蠖酁閔ash join替代了。
通常情況下hash join的效果都比sort merge join要好,然而如果行源已經(jīng)被排過序,在執(zhí)行sort merge join時(shí)不需要再排序了,這時(shí)sort merge join的性能會(huì)優(yōu)于hash join。
在全表掃描比索引范圍掃描再通過rowid進(jìn)行表訪問更可取的情況下,sort merge join會(huì)比nested loops性能更佳。
可用USE_MERGE(table_name1 table_name2)提示強(qiáng)制使用sort merge join。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ProcessTest {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder ( "tasklist");
try {
Process process = pb.start();
InputStream fis = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
StringBuffer cmdout = new StringBuffer();
while ((line = br.readLine()) != null) {
cmdout.append(line).append("\n");
}
System.out.println(cmdout.toString().trim());
} catch (IOException e) {
e.printStackTrace();
}
}
}
輸出如下:
圖像名 PID 會(huì)話名 會(huì)話# 內(nèi)存使用
========================= ====== ================ ======== ============
System Idle Process 0 Console 0 28 K
System 4 Console 0 324 K
smss.exe 1076 Console 0 812 K
csrss.exe 1152 Console 0 3,296 K
winlogon.exe 1176 Console 0 31,580 K
services.exe 1220 Console 0 4,684 K
lsass.exe 1232 Console 0 1,672 K
svchost.exe 1408 Console 0 6,236 K
svchost.exe 1496 Console 0 5,036 K
svchost.exe 1656 Console 0 38,656 K
spoolsv.exe 1872 Console 0 8,000 K
explorer.exe 332 Console 0 18,888 K
avp.exe 376 Console 0 24,960 K
db2dasrrm.exe 460 Console 0 34,652 K
TSVNCache.exe 672 Console 0 12,476 K
igfxtray.exe 1380 Console 0 7,344 K
hkcmd.exe 1236 Console 0 4,056 K
igfxpers.exe 1428 Console 0 3,468 K
db2mgmtsvc.exe 1444 Console 0 10,072 K
RTHDCPL.exe 1460 Console 0 32,480 K
igfxsrvc.exe 1572 Console 0 3,772 K
avp.exe 1680 Console 0 6,008 K
db2systray.exe 1700 Console 0 32,512 K
ctfmon.exe 1780 Console 0 4,892 K
picpick.exe 1984 Console 0 3,600 K
QQ.exe 2024 Console 0 34,648 K
dsNcService.exe 264 Console 0 3,880 K
365日歷.EXE 1952 Console 0 43,788 K
CLCL.exe 1028 Console 0 8,252 K
klnagent.exe 1052 Console 0 3,196 K
thunderbird.exe 352 Console 0 38,692 K
rtxc.exe 472 Console 0 29,968 K
db2rcmd.exe 1836 Console 0 11,832 K
TXPlatform.exe 2488 Console 0 3,808 K
firefox.exe 2724 Console 0 195,912 K
cmd.exe 2716 Console 0 52 K
sh.exe 3936 Console 0 152 K
conime.exe 2752 Console 0 3,424 K
eclipse.exe 3060 Console 0 2,592 K
JAVAW.EXE 2984 Console 0 446,692 K
EXCEL.EXE 3232 Console 0 1,936 K
wmiprvse.exe 4084 Console 0 6,368 K
JAVAW.EXE 320 Console 0 6,860 K
tasklist.exe 2936 Console 0 4,812 K
當(dāng)運(yùn)行其他命令 ,如dir等時(shí),用如下寫法:
ProcessBuilder pb = new ProcessBuilder ( "cmd", "/c", "dir");
Ubuntu下上網(wǎng)解析DNS慢有很大程度上是和IPV6有關(guān),而目前國內(nèi)大部分地方都還沒有IPV6網(wǎng)絡(luò),所以一般用戶應(yīng)該需要關(guān)閉IPV6
網(wǎng)上流傳著很多IPV6的關(guān)閉方法,但是經(jīng)過測(cè)試大部分都是針對(duì)老版本的,而且效果不好。
這里提供一種方法作為參考
/proc/sys/net/ipv6/conf/lo/disable_ipv6
這個(gè)檔案,用cat指令可以看到 0 這個(gè)數(shù)字,將他設(shè)定為1就可以了。
因?yàn)橐呀?jīng)將ipv6編入kernel,因此在proc里面就可以看得到相關(guān)的設(shè)定。
設(shè)定的方式有很多種,有的是用echo 1 >> [路徑]/檔桉名稱
的方式,這種方式是每次開機(jī)以后就得要打一次。
所以延伸出第二個(gè)方法,在rcS.d里面設(shè)定一個(gè)連結(jié),去執(zhí)行這個(gè)指令的script。
第3個(gè)方法,就是設(shè)定sysctl.conf檔桉,也是最正統(tǒng)的做法。
位置在
/etc/sysctl.conf
這個(gè)檔桉可以設(shè)定很多,包括要當(dāng)成NAT時(shí)的封包轉(zhuǎn)發(fā)等等。
要設(shè)定
/proc/sys/net/ipv6/conf/lo/disable_ipv6
這個(gè)檔桉,就是在sysctl.conf里面加上
net.ipv6.conf.lo.disable_ipv6 = 1
In git, you can’t update a tag directly, but you can branch the code to create a new tag. Here’s how you would do that:
First, you need to checkout the tag:
git checkout <tag_name>
Then create a branch:
git branch -b <branch_name>
After you make your changes, commit them (there are a few ways to do this, keeping it simple):
git commit -am 'my descriptive comment on this commit'
You can create a new tag:
git tag <new_tag_name>
Then you can push the tag:
git push --tags
I just learned that if you have some changes in your working tree that you want to get rid of, you don't type 'git revert' like you might guess. No, that's what cvs, subversion, mercurial, and bazaar (to name a few) use revert to mean, but not git. With git, revert is used to undo actual commits. Thankfully, you can undo your revert with another 'git revert', I just learned. So let me repeat to be clear, if you have changes to your working files that you want to abandon, DO NOT do this:
git revert HEAD
That will undo your last commit. Do this instead:
git reset --hard HEAD
I'm glad I have that straightened out now. I'm wondering if /etc was really a good place for me to start out playing with git.
UPDATE: Nearly two years later and I'm still getting comments on this. I'm glad I've been able to help people out this way. The discussion in the comments is good, and one thing I'd like to point out is that I now always use and recommend:
git checkout filename
(as recommended by Anonymous and others below) instead of git reset. I think the git stash trick from Nicolas is pretty cool too.
內(nèi)核版本指的是在Linus領(lǐng)導(dǎo)下的開發(fā)小組開發(fā)出的系統(tǒng)內(nèi)核的版本號(hào)。第一數(shù)字叫主版本號(hào),第二個(gè)叫次版本號(hào),第三個(gè)叫修訂版本號(hào)。一般說來次版本號(hào)還
有特定的意義,以序號(hào)的第二位為偶數(shù)的版本表明這是一個(gè)可以使用的穩(wěn)定版本,如2.0.35,而序號(hào)的第二位為奇數(shù)的版本一般有一些新的東西加入,是不一
定很穩(wěn)定的測(cè)試版本,如2.1.88。這樣穩(wěn)定版本來源于上一個(gè)測(cè)試版升級(jí)版本號(hào),而一個(gè)穩(wěn)定版本發(fā)展到完全成熟后就不再發(fā)展。
總結(jié)一下:
第一個(gè)數(shù)字表示大版本,相當(dāng)于大升級(jí)了.
第二個(gè)數(shù)字有兩個(gè)含義:大版本的小版本;偶數(shù)表示生產(chǎn)版(奇數(shù)表示測(cè)試版);
第三個(gè)數(shù)字表示指定小版本的補(bǔ)丁包;如2.6.10 Linux內(nèi)核的推出,表明一年中已經(jīng)發(fā)布了10個(gè)版本.
不過,2.6.x系列以前版本沒有帶有次小數(shù)點(diǎn)的版本號(hào),即沒有四個(gè)數(shù)字組成的版本號(hào),而在2.6.x系列中,從2.6.8.1內(nèi)核開始,一直持續(xù)到2.6.11,較小的內(nèi)核隱患和安全補(bǔ)丁被賦予了次小數(shù)點(diǎn)版本號(hào)(例如2.6.11.1)。
但
值得注意的是.readhat
linux內(nèi)核的版本稍有不同如2.4.20-10,可以發(fā)現(xiàn)多了一組數(shù)字(10),該數(shù)字是建立(build)號(hào)。每個(gè)建立可以增加少量新的驅(qū)動(dòng)程序或
缺陷修復(fù)。一些readhat 內(nèi)核還帶“pp”,就是“pre-patch”的意思,是個(gè)內(nèi)核的測(cè)試版本。
PV(pageview),即頁面瀏覽量,或點(diǎn)擊量;通常是衡量一個(gè)網(wǎng)絡(luò)新聞?lì)l道或網(wǎng)站甚至一條網(wǎng)絡(luò)新聞液沒滌的主要指標(biāo);當(dāng)然,有時(shí)還會(huì)同時(shí)考察另外一個(gè)指標(biāo),即uv(unique
visitor),指訪問某個(gè)站點(diǎn)或點(diǎn)擊某條新聞的不同IP地址的人數(shù)。
PV之于網(wǎng)站,就像收視率之于電視,從某種程度上已成為投資者衡量商業(yè)網(wǎng)站表現(xiàn)的最重要尺度。從長遠(yuǎn)看,很多網(wǎng)站也意識(shí)到,PV的追求需要和品牌的打造結(jié)合起來;但現(xiàn)代商業(yè)行為在投資者急功近利的評(píng)判壓力下,往往無奈為了使PV提升而不擇手段。
一條新聞發(fā)布以后,其PV便可以加以跟蹤,通常是每5分鐘統(tǒng)計(jì)一次。不同網(wǎng)站的不
同頻道,對(duì)其所發(fā)布新聞的PV表現(xiàn)有一個(gè)大致的評(píng)判尺度。新聞發(fā)布后,一般PV值總有一個(gè)上升的過程。可以從不同時(shí)段來計(jì)算PV的單位時(shí)間變化幅度,有經(jīng)
驗(yàn)的網(wǎng)絡(luò)編輯,經(jīng)過幾個(gè)5分鐘的數(shù)據(jù)積累,便能大致預(yù)料到這條新聞的PV峰值水平。如果這個(gè)水平不能令人滿意,則編輯就要采取一些手段,如“優(yōu)化”標(biāo)題、
增加圖片、挪動(dòng)位置等。一般來說,通過這樣的“處理”,一條新聞的PV表現(xiàn)能有所改善,達(dá)到新的高峰。也就是說,網(wǎng)絡(luò)新聞的編輯手段影響著PV值。
還有哪些因素對(duì)PV有影響呢?至少還有這些因素:新聞發(fā)布的時(shí)間。不同的時(shí)間段,上網(wǎng)的人數(shù)不同,訪問該站點(diǎn)的人數(shù)也不同,因此,有時(shí)PV的漲落,其主要貢獻(xiàn),在于不同時(shí)段上網(wǎng)人數(shù)的自然波動(dòng)。同樣一條新聞,在不同的時(shí)段發(fā)布,PV就會(huì)有差別。
不同時(shí)段上網(wǎng)的人,其人口特征(性別、年齡、教育程度、閱讀旨趣等)不同,所以,同樣是一萬個(gè)上網(wǎng)的人,甚至同樣是對(duì)某個(gè)網(wǎng)站的一萬次訪問,不同時(shí)段,這一萬次訪問在不同頻道/內(nèi)容上的分布是有差別的。所以PV的變化,與這些因素導(dǎo)致的變化有關(guān)。
訪問的周期。對(duì)于一些常瀏覽的網(wǎng)站,我們可能一天之中會(huì)訪問幾次,這中間有一定的
時(shí)間間隔。這個(gè)間隔,很多時(shí)候和人們的現(xiàn)實(shí)工作節(jié)奏有關(guān)系。比如,不少人一上班會(huì)抽空瀏覽一下新聞,第二次再來看看又有什么新聞的時(shí)候,往往是上午中間休
息時(shí),甚至是午飯后的休息時(shí)間。因此,即使其他因素不變,由于人們回訪網(wǎng)站的周期性,也會(huì)對(duì)新聞或網(wǎng)站的PV帶來影響。當(dāng)然,由于不同的人回訪的周期長短
不一、時(shí)段不一,這個(gè)影響因素未必會(huì)導(dǎo)致明顯的波動(dòng),而可能分散在不同時(shí)段的PV表現(xiàn)中,但可以肯定的是,任何一個(gè)PV數(shù)據(jù),也有這種回訪周期的因素所起
的作用。
搭便車因素。比如一些突發(fā)事件,會(huì)導(dǎo)致人們對(duì)某一網(wǎng)站的訪問增加,但這些訪問的
初衷,本只是突發(fā)事件相關(guān)新聞。然而由于人們的新聞消費(fèi),往往具有不可預(yù)期性,所以常見的現(xiàn)象是,人們?cè)诳赐晗肟吹男侣労螅€會(huì)順帶看看其他的。這一因
素,也可能對(duì)某條新聞(與突發(fā)事件無關(guān))的PV有所貢獻(xiàn)。
最后,偶然因素也對(duì)PV有一定影響,比如天氣因素,比如非典期間等等。
由此看來,一個(gè)簡單的PV數(shù)據(jù),其實(shí)是多種因素綜合貢獻(xiàn)的結(jié)果,所以有時(shí)的PV漲
落,實(shí)在不是完全可以通過編輯手段來加以引導(dǎo)和影響的。知道這一點(diǎn)很重要,因?yàn)檫@告訴我們,盲目地、不加具體分析地以PV來衡量成敗好壞,是不合理的。在
社會(huì)科學(xué)研究中,這種區(qū)分不同因素對(duì)某一個(gè)現(xiàn)象的貢獻(xiàn),就是所謂的詳析模式。很多看似不變的東西,其實(shí)內(nèi)部構(gòu)成比例上發(fā)生了很大的變化。而有些看似變化的
東西,其相對(duì)關(guān)系其實(shí)沒有什么變化,只是一種單純的數(shù)量上的漲落。
這使我想到那本《統(tǒng)計(jì)陷阱》,一本由一個(gè)記者所寫的通俗讀物。這本書的英文名稱直譯,叫“如何用統(tǒng)計(jì)數(shù)據(jù)說謊”。
Sun微系統(tǒng)的JavaHelp系統(tǒng)是一種應(yīng)用程序幫助技術(shù),它可以在所有支持Java的平臺(tái)和瀏覽器中運(yùn)行只要它是一個(gè)純粹的Java產(chǎn)品。通過
applet和Java應(yīng)用程序,在其他環(huán)境下,比如在互聯(lián)網(wǎng)或企業(yè)內(nèi)部互聯(lián)網(wǎng)中,它是理想的使用對(duì)象。在本文中,我將回顧JavaHelp的主要作用,
并闡明它的簡單使用方法。
優(yōu)點(diǎn)
JavaHelp通過使用Java基礎(chǔ)類(JFC) 軟件組件來實(shí)現(xiàn),這使得開發(fā)戶自定義界面和功能變得靈活輕松。您可以輕而易舉地將應(yīng)用程序的幫助信息嵌入到應(yīng)用程序之中,或者嵌入到另一個(gè)獨(dú)立的窗口里。JFC 還具有通過自定義導(dǎo)航控件拓展幫助功能的能力。
JavaHelp使動(dòng)態(tài)更新幫助數(shù)據(jù)或?qū)⑵浯鎯?chǔ)在一個(gè)便利的位置變得簡單易行,不管是在客戶端還是服務(wù)器端。內(nèi)容窗口使用HTML 3.2格式顯示話題,使內(nèi)容設(shè)計(jì)變得簡單。標(biāo)準(zhǔn)導(dǎo)航提供內(nèi)容表單(TOC)、索引和全文搜索。(TOC和索引都遵循W3C標(biāo)準(zhǔn)。)
JavaHelp Data
Sheet提供以下信息:TOC提供層疊式和擴(kuò)展式話題展示,無限量等級(jí)層次和多重TOC的合并。TOC與內(nèi)容閱讀器同步顯示,也就是說顯示的話題在
TOC中被突出。索引支持多重索引的合并。全文搜索被設(shè)計(jì)得很靈活,并且可以配置。搜索引擎也可置于用戶或服務(wù)器中的任一方。
幫助內(nèi)容和搜索引擎被壓縮成一個(gè)使用標(biāo)準(zhǔn)JAR格式的單個(gè)文件。盡管為了使存儲(chǔ)和訪問更具靈活性,推薦將所有文件壓縮成一個(gè)單獨(dú)的文件,但是您仍然可以將
所有文件以擴(kuò)展的格式保存在目錄中。您可以在自定義編寫的導(dǎo)航器、搜索引擎、標(biāo)準(zhǔn)JavaHelp閱讀器或在任何HTML顯示中,包括標(biāo)準(zhǔn)Web瀏覽器
中,查看和導(dǎo)航內(nèi)容。
JavaHelp API提供一個(gè)上下文敏感幫助和ID映射的機(jī)制。您可以將多重組件的幫助信息用JavaHelp API合并,這樣用戶就看到一個(gè)單獨(dú)的完整文檔。合并機(jī)制可以應(yīng)用于TOC、索引和搜索數(shù)據(jù)庫。
特性
JavaHelp有兩個(gè)主要版本:1.1.3和2.0版。最早支持JavaHelp 2.0的Java版本是J2SE
1.2.2,因此您無需擔(dān)心自己的代碼是否支持JavaHelp。JavaHelp系統(tǒng)由一個(gè)特性完整的、可擴(kuò)展的規(guī)范、API以及一個(gè)參考執(zhí)行組成。
標(biāo)準(zhǔn)JavaHelp系統(tǒng)的主窗口:有三個(gè)顯示窗口,在您退出窗口時(shí)并未被關(guān)閉,依然可配置。在默認(rèn)情況下,一個(gè)主要窗口有以下三個(gè)窗格:工具欄、導(dǎo)航窗口和內(nèi)容窗口。見圖表1。
用戶可以應(yīng)用多種方式通過內(nèi)部應(yīng)用程序調(diào)用在線幫助,例如,當(dāng)一個(gè)用戶從幫助菜單中選擇一項(xiàng),或在應(yīng)用程序GUI中點(diǎn)擊幫助按鈕,JavaHelp系統(tǒng)提
供一個(gè)簡便的界面,通過這個(gè)界面,應(yīng)用程序要求話題的ID 得以顯示。然后JavaHelp系統(tǒng)將話題ID與相應(yīng)的URL相連接并將其顯示出來。
ID被映射到一個(gè)被稱作映射文件的JavaHelp系統(tǒng)元數(shù)據(jù)文件中的URL上。例如,當(dāng)為文件選擇對(duì)話框編碼時(shí),開發(fā)人員要求話題ID
fc_help在當(dāng)對(duì)話框底部的幫助按鈕被點(diǎn)擊時(shí)顯示。在映射文件中,ID fc_help被定義為名為
FileChooser.html的文件,使用以下XML句法:
將文件名(或URL)的規(guī)范從程序代碼分離為內(nèi)容的作者提供了控制與話題ID相關(guān)的信息的自由。
工具提示是一個(gè)顯示給用戶的簡短信息,當(dāng)光標(biāo)停留在一個(gè)按鈕上的時(shí)間間隔長于閾值時(shí)它就會(huì)出現(xiàn)。您還可以將工具提示信息納入JavaHelp系統(tǒng)數(shù)據(jù)。
JavaHelp系統(tǒng)數(shù)據(jù)具有調(diào)用在線幫助的能力,能夠在應(yīng)用程序GUI中描述圖形組件。用戶操縱激活語境敏感幫助,然后將組件以問題形式特定化。與組件相聯(lián)系的ID被顯示。您可以從TOC、索引導(dǎo)航或主要窗口的內(nèi)容窗格中顯示幫助話題。
輕型組件
輕型組件能夠向幫助話題添加功能。這些組件與Java的applet相似,但它們的加載和執(zhí)行更為迅速。一個(gè)幫助的創(chuàng)作者能夠使用已經(jīng)在JavaHelp
中執(zhí)行的輕型組件;這個(gè)組件執(zhí)行彈出窗口和次級(jí)窗口。在HTML
話題文件中使用輕型組件,您可以使用HTML<o(jì)bject>標(biāo)記,正如列表A中的例子所顯示的。
在例子中,彈出的對(duì)象包括文件../topicB/glossary_def.html,用戶點(diǎn)擊的對(duì)象(viewerActivator)是個(gè)鏈接,窗
口類型屬于彈出型,窗口大小為300x400,用戶在鏈接中看到的內(nèi)容是“Click here(點(diǎn)擊這里)”。
Java開發(fā)商還可以創(chuàng)造新的輕型組件。例如,這樣的組件可能為幫助話題添加動(dòng)畫和多媒體功能。
要求抽象查看的輕型組件必須執(zhí)行javax.javahelp.impl.ViewAwareComponen。這些組件執(zhí)行setViewData()
方法。這個(gè)組件能夠根據(jù)抽象查看中的信息決定它所執(zhí)行的環(huán)境。(注意:要訪問抽象查看,您應(yīng)該使用JavaHelp
API。)在列表B中,文檔對(duì)象下面的編碼片斷來自于抽象查看。
需要更多關(guān)于創(chuàng)造Java輕型組件的信息,請(qǐng)參閱相關(guān)文件。
JavaHelp編寫工具
有很多通過商業(yè)途徑可以得到的編寫工具能夠?yàn)槟膽?yīng)用程序編寫和維護(hù)一個(gè)完美的幫助系統(tǒng)。最有名的三個(gè)是Software7
Gmbh的Helen
1.5、Solutionsoft的HelpBreeze和Pivotonic的JawaHelpAuthor。所有這些第三方產(chǎn)品都支持Java 2
和Java 1.1標(biāo)準(zhǔn)。需要更多關(guān)于編寫工具的信息,請(qǐng)參閱Sun的幫助編寫工具頁面。
試試看吧
如果JavaHelp聽起來像是一個(gè)您認(rèn)為您的用戶和伙伴開發(fā)商都喜歡的系統(tǒng)的話,那么從Sun Microsystem公司的網(wǎng)站上立刻下載吧。這個(gè)地址提供了安裝過程所需要的所有信息。