2008年5月29日
#
刪除 ActiveX 控件,請按照相應(yīng)部分中的步驟操作。
Internet Explorer 3.0、3.01 和 3.02
- 單擊“開始”,指向“設(shè)置”,單擊“控制面板”,雙擊“添加/刪除程序”,然后單擊“安裝/卸載”選項卡。
- 如果您要刪除的 ActiveX 控件出現(xiàn)在安裝的程序列表中,請單擊該 ActiveX 控件,單擊“添加/刪除”,然后按照屏幕上的說明操作。如果該 ActiveX 控件沒有出現(xiàn)在安裝的程序列表中,則繼續(xù)執(zhí)行下一步。
- 單擊“開始”,單擊“運行”,在“打開”框中鍵入下列行,然后單擊“確定”:
regsvr32 drive:\windows\occache\filename.ocx /u
注意:drive 是 Windows 文件夾所在的驅(qū)動器號,windows 是安裝 Windows 的文件夾名,而 filename.ocx 是您想要刪除的 ActiveX 控件。
注意:如果您不知道要刪除的 ActiveX 控件 (.ocx) 的文件名,則可以通過查看安裝或使用 ActiveX 控件的網(wǎng)頁的超文本標記語言 (HTML) 源文件來確定該文件名。要查看一個網(wǎng)頁的 HTML 源文件,請右鍵單擊該網(wǎng)頁的空白區(qū)域,然后單擊“查看源文件”。
- 在 Windows 資源管理器或 Windows NT 資源管理器中,單擊 Windows\Occache 文件夾中的 .ocx 文件,然后單擊“文件”菜單上的“刪除”。
Occache 是在 Internet Explorer 3.x 的所有版本中安裝有 ActiveX 控件的文件夾的名稱。Regsvr32.exe 文件是由 Internet Explorer 安裝的,并且可用于注冊和刪除 ActiveX 控件的注冊表項。
Internet Explorer 4.x 或更高版本(所有平臺)
Internet Explorer 4.x 或更高版本,包括 Occache.dll 文件,該文件可用于使用“shell 文件夾”枚舉、更新和安全地卸載 ActiveX 控件。
- 單擊“開始”,指向“設(shè)置”,單擊“控制面板”,雙擊“添加/刪除程序”,然后單擊“安裝/卸載”選項卡。
- 如果您要刪除的 ActiveX 控件出現(xiàn)在安裝的程序列表中,請單擊該 ActiveX 控件,單擊“添加/刪除”,然后按照屏幕上的說明操作。如果該 ActiveX 控件沒有出現(xiàn)在安裝的程序列表中,則繼續(xù)執(zhí)行下一步。
- 在 Windows 資源管理器或 Windows NT 資源管理器中,雙擊 Windows\Downloaded Program Files 文件夾或 Winnt\Downloaded Program Files 文件夾,右鍵單擊您想要刪除的 ActiveX 控件,然后單擊“刪除”。
- 在系統(tǒng)提示您是否刪除該 ActiveX 控件后,單擊“是”。
重要說明:如果您運行的是 Internet Explorer 4.0,則不應(yīng)刪除以下 ActiveX 控件:
- DirectAnimation Java Classes
- Internet Explorer Classes for Java
- Microsoft XML Parser for Java
- Win32 Classes
Internet Explorer 5.0 或更高版本不要求 Downloaded Program Files 文件中的這些組件。
刪除 ActiveX 控件時出現(xiàn)的錯誤消息
在您嘗試使用 Occache shell 文件夾刪除一個 ActiveX 控件時,可能顯示以下錯誤消息之一:
- 共享沖突 這些程序文件當前正由一個或多個程序使用。請關(guān)閉一些程序,然后重試。您可能需要重新啟動 Windows。
- 組件刪除 即將刪除 Windows 系統(tǒng) DLL:(<path\filename>)。是否刪除?
共享沖突:
如果您要嘗試刪除的 ActiveX 控件當前在內(nèi)存中由 Internet Explorer 或“活動桌面”組件加載,則顯示此錯誤消息。
要解決此錯誤消息,請按照下列步驟操作:
- 關(guān)閉所有打開的 Internet Explorer 窗口。
- 禁用“活動桌面”。為此,請右鍵單擊桌面上的空白區(qū)域,指向“活動桌面”,然后單擊“查看網(wǎng)頁”以清除該復選標記。
- 按照本文中前面部分的“Internet Explorer 4.0 或更高版本”部分中介紹的步驟,刪除該 ActiveX 控件。
注意:您最好在刪除 ActiveX 控件前重新啟動 Windows。
組件刪除:
僅當您要刪除的 ActiveX 控件向已注冊的 Occache 文件夾以外的文件夾(例如,Windows\System 或 Winnt\System32)安裝文件時,該消息才出現(xiàn)在 4.01 Service Pack 1 (SP1) 之前的 Internet Explorer 4 版本中。Occache 不是總能確定這些文件是否正由其程序共享。
如果您確定消息中顯示的一個或多個文件未由 Windows 或其他程序使用,請單擊“是”。否則,單擊“否”。
注意:在 Internet Explorer 4.01 SP1 和更高版本中,Occache 不刪除(或提示您刪除)注冊的 Occache 文件夾之外的相關(guān)文件。
支持多個 Occache 文件夾
Internet Explorer 4.0 和更高版本支持多個 Occache 文件夾。Occache 文件夾的列表位于以下注冊表項中:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ActiveX Cache
默認情況下,Internet Explorer 4.0 和更高版本使用 Windows\Downloaded Program Files 或 Winnt\Downloaded Program Files 文件夾。如果是從 Internet Explorer 3.x 升級的,則 Occache 和 Downloaded Program Files 文件夾可能都存在。在此情況下,所有新的 ActiveX 控件都安裝在 Downloaded Program Files 文件夾中,但以前安裝的 ActiveX 控件仍在 Occache 文件夾中工作。當您在 Windows 資源管理器、Windows NT 資源管理器或“我的電腦”中打開 Occache 或 Downloaded Program Files 文件夾時,將顯示所有 ActiveX 控件,而與該 ActiveX 控件的文件所在的文件夾無關(guān)。在此情況下,注冊表項中將出現(xiàn)以下字符串值:
"0"="C:\\WINDOWS\\OCCACHE"
"1"="C:\\WINDOWS\\Downloaded Program Files"
有關(guān) ActiveX 控件的其他信息,請參見 Microsoft 知識庫中的以下文章:
154544 (http://support.microsoft.com/kb/154544/LN/ ) ActiveX 技術(shù)說明
有關(guān) Internet Explorer 在發(fā)生沖突(例如,如果文件已存在)時如何下載 ActiveX 控件的信息,請參見 Microsoft 知識庫中的以下文章:
196150 (http://support.microsoft.com/kb/196150/LN/ ) INFO:為什么會在代碼下載期間創(chuàng)建 CONFLICT 目錄
a very cool pdf to word converter:http://www.pdftoword.com
摘要:
<head>
<body>
<table class="dataintable" id='table22'>
<tbody><tr>
&nb...
閱讀全文
http://www.ej-technologies.com/products/exe4j/overview.html
window.open(....);
this.focus(); self.opener = this; self.close();
There are two javascript ways to view web site in full screen mode in IE:
1. window.open('http://www.sina.com.cn','','fullscreen')
Note: If view the page remotely, this way will ineffective, and you can use the second one instead.
2. var wsh=new ActiveXObject("wscript.shell");
wsh.run("iexplore -k http://www.google.com");
問題描述:使用ie6導出excel表正常,但是在IE7 下總是報錯:“ Automation server can't create
object javascript”。
1. In Internet Explorer > Tools > Internet Options > Security > Custom Level
2. Enabling or prompting "Initializing and Script Activex controls not marked as safe"
3.IE7對環(huán)境的設(shè)置特別嚴格,常用到的有兩部分,一個是安全里面的“internet”設(shè)置,一個是“信任站點”的設(shè)置。
1>需要把站點加入信任站點列表;
2>設(shè)置“信任站點”項的“自定義級別”,啟用“對未標記為可安全執(zhí)行 ActiveX控件初始化并執(zhí)行腳本”即可。
|
#2
|
|
The children of a TabNavigator aren't
created until they're needed. In your case, only the contents of the
first tab are actually created, because they're part of what's needed
when the TabNavigator is first displayed. The contents of the second tab
won't be instantiated until they need to be displayed, which is when
the second tab is clicked on. That's why that error is being thrown
until you click on the second tab. This process of only instantiating
components as they are needed is called deferred instantiation.
To force the contents of the other tabs to be instantiated, try changing
the creationPolicy property of the TabNavigator to be "all". This will
cause all of the different tabs to be instantiated, regardless of having
been clicked on.
In the Flex docs, check out Container.creationPolicy for more details.
ActionScript Code:
<mx:TabNavigator creationPolicy="all">
|
W3C DOM Compatibility - CSS
From: http://www.quirksmode.org/dom/w3c_css.html#access
From:http://martybugs.net/articles/print.cgi
Web Page Printability With CSS
author: Martin
"mpot" Pot
date: 7 January 2005
Introduction
This article describes how to use CSS media types to make your website
much more
printer-friendly.
An overview of CSS media types is given, and sample HTML and CSS code is
provided,
detailing how to implement CSS media types for improving printability.
Why?
Most webpages do not print very well, with large amounts of the printed
page being wasted with
banners, navigation menus, advertising, and other unnecessary content.
When attempting to print out the main text of a webpage, you often have
to resort to
copying the text into Word or another editor, and then printing it.
Some websites make use of a link at the bottom of the page, linking to a
"printable version"
of the same page. However, this requires additional effort on the part
of the web developer.
There is a much easier way to make your pages print better, and that's
via the use of
CSS media types.
For example, all content on
MartyBugs.Net
has been designed to be
printer-friendly.
When printing pages from this site
using a modern browser, elements such as the left menu column and the
right column (where used)
will be hidden, thus ensuring there's more room on the printed page for
the main content.
|
page as displayed on a 1024x768 screen
|
The image above shows how one of the pages on this website would be
displayed on a
computer screen, at a resolution of 1024x768.
|
|
|
printed page,
no print optimisation
|
|
printed page,
optimised for printing
|
The left image above shows how the same page will look when printed, if
all the page content is printed.
Notice how little room there is in the centre of the page for the main
content.
The right image above shows the same page, but the navigation and other
content on the left and right
hand sides of the page is not printed. CSS media types have been used
to hide this content when
the page is printed.
CSS Media Types
The primary aim of the CSS media types is to allow the web-page author
to define different styles for
a page, depending on the media being used to display the page.
CSS 2.1 supports numerous media types, including
all (suitable for all devices),
screen (computer screens),
print (pages viewed on-screen in print-preview mode and printed
pages).
Other less-common media types are also supported, such as braille,
embossed, handheld, projection,
speech, etc, but we won't be discussing any of these.
CSS media types are defined using the rule in
your CSS style-sheet,
or in your in-line CSS style definitions.
For example, to define different font sizes for the
print
and
screen media types, as well as a common
line-height to be used for both,
the CSS definition is as follows:
@media print {
body { font-size: 10pt }
}
@media screen {
body { font-size: 13px }
}
@media screen, print {
body { line-height: 1.2 }
}
The CSS media types allow you to specify different CSS properties for
any element, so it will be
displayed differently on the screen than when printed.
For the purposes of this article, the only thing we're interested in is
to hide some page elements
when the page is printed.
Refer to the
W3C CSS
2.1 Media Definitions
for more details on CSS media types.
Using CSS Media Types
The web pages on this website are all generated on-the-fly, using
server-side Perl templates.
All pages have a number of common elements, namely:
- a banner across the top
- navigation menu on the left side
- main content in the centre
- advertising and other content on the right side
- footer across the bottom
When someone prints out a page from this website, CSS media types are
used to hide a number
of elements on the page, including the navigation menu, advertising, and
the navigation content
in the footer.
To provide a working demonstration of how CSS media types can be used in
this way, a demonstration
web page was coded, using tables to define the banner area across the
top of the page, with
a column down the left-hand side for the navigation menu, a column down
the right-hand side
for other content, and a footer across the bottom of the page.
This layout is one of the most commonly used page layouts on the
internet at the present - hence
my choice to use it as an example.
the example page
Firstly, we define the CSS styles for the page:
<style type="text/css">
@media print {
.noprint { display: none; }
}
</style>
Note that the CSS styles can also be defined using a separate CSS file,
but example page has the CSS
defined in-line for simplicity (and to keep the example to a single
file).
The above CSS definition is defining a style called
noprint,
and will only
be applied to printed content. Setting the
display
property to
none means any content using this CSS style
will not be displayed
when printed, but will be displayed for all other media types.
There are a number of components on this page that we don't want
printed, namely the columns on the
left-hand side and on the right-hand side.
The
noprint style is applied to the table
cells holding this content,
thus ensuring they won't be visible when the page is printed.
<table border='1' cellpadding='4' cellspacing='0' width='100%' >
<tr height='60'><td colspan='3'>
banner place-holder
</td></tr>
<tr><td width='150' valign='top' class='noprint'>
left-side content place-holder
</td><td>
<b>main content</b>
[snip!]
</td><td width='150' valign='top' class='noprint'>
right-side content place-holder
</td></tr><tr><td colspan='3'>
footer content place-holder
</td></tr>
</table>
This will result in the columns on the left and right-hand sides being
hidden when the page
is printed, thus providing more space on the printed page for the
content itself.
Note that this style needs to be applied to the table cells themselves,
and not just to the content
in these table cells, else the (empty) cells will still show up on the
printed copy.
Testing Your CSS
The easiest way to test CSS styles for print media is to use a web
browser which has print preview
capabilities.
The print preview will give you a fairly accurate representation of how
the page will look
when it is printed, and is a much more efficient way to test your media
styles, rather than
actually printing out pages on a printer.
Most popular web browsers should support print preview functionality.
The
FireFox
browser has print preview functionality, although it lacks any
zoom/unzoom capabilities.
As an alternative to using print preview, you can print the web page to a
PDF file.
There are numerous (costly, freeware, and anywhere in between) software
packages for
doing this.
I recommend using the freeware and open-source
PDFCreator,
which is
a Windows printer driver which allows you to create PDFs from any
Windows application, just by
selecting the PDFCreator driver as the virtual printer from that
application.
Also be sure to use the
W3C's
free
CSS
Validation Service to
check your CSS definitions.
References
http://support.microsoft.com/kb/973904
Let me fix it myself
To unregister the mswrd632 converter yourself, edit the registry as follows:
- Click Start, click Run, type regedit, and then click OK.
- Locate and then click the following registry subkey:
- For 32-bit versions of Windows:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Text Converters\Import\MSWord6.wpc
- For 64-bit versions of Windows:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Text Converters\Import\MSWord6.wpc
- On the Edit menu, click Delete.
- Click Yes.
- Exit Registry Editor.
This change will effectively unregister the converter and disable it for third-party applications and for Microsoft Office. Microsoft Office will use its own text converters to open these kinds of files.
The user was running Office 2007 and getting this error. After doing some research, we came across a few possible solutions. In this post, I’ll list them out here.
Method 1 – Unregister Text Converter
Basically, in Windows XP SP2 and above and Windows Server 2003 SP1 and above, if you have a plain text file or another kind of file that is not a Microsoft Word file, but has a .doc extension, you will get this error.
This can also happen if you are opening a really old document created by Word for Windows 6.0 or Word 97 documents. In this case, you can disable the mswrd632 converter so you don’t get this error. The files will then be opened by the Microsoft Office text converters.
You can unregister this converter by going to Start, then run and typing regedit. Then navigate to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Text Converters\Import\MSWord6.wpc

Right-click on the MSWord6.wpc key in the left hand pane and choose Delete. If you have a Word 97 document, you should still be able to open it in Word 2003 or 2007. However, you will not be able to open these files in WordPad anymore. You’ll get an error like:
Cannot load Word for Windows 6.0 files
If you really have to use WordPad to open Word 6.0/95 files, you can re-enable the Word 6.0/95 for Windows and Macintosh to RFT converter. Open the registry and go to the following keys:
For 32-bit versions of Windows
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ Applets\Wordpad
For Microsoft Windows on Windows 64 (WOW) mode
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\ CurrentVersion\Applets\Wordpad
If the Wordpad key is not there in the left-hand pane, create it. After that, create a new DWORD value in the right-pane called AllowConversion and give it a value of 1.
Method 2 – Copy the MSWrd632.wpc File
The other way to solve this issue is to copy the MSWrd632.wpc file from another computer to the computer having problems.
The only issue with this is that it is less secure and makes your computer vulnerable to a possible security hack, so don’t do this unless you really have to or that computer is not connected to the Internet.
You can usually find this file in the following path:
C:\Program Files\Common Files\Microsoft Shared\TextConv\
That’s about it! If you are still having this problem, post a comment here and I’ll try to help! Enjoy!
詳解COM Add In的LoadBehavior及其妙用
http://blog.csdn.net/v_jzho/archive/2007/10/06/1813080.aspx
基于Visual Studio 2003/2005的Office插件開發(fā)FAQ
http://blog.csdn.net/tonyqus/archive/2007/02/24/1513256.aspx
There are several ways to deploy an assembly into the global assembly
cache:
1) Use an installer designed to work with the global assembly cache. This
is the preferred option for installing assemblies into the global assembly
cache
2) Use a developer tool called the Global Assembly Cache tool (Gacutil.exe)
provided by the .NET Framework SDK.
3) Use Windows Explorer to drag and drop assemblies into the cache.
4) use install shield. (注意:installshield里只有msi等幾個類型的項目支持這個)
From:http://bytes.com/topic/net/answers/109942-deploy-assembly-gac
http://www.microsoft.com/downloads/details.aspx?familyid=59DAEBAA-BED4-4282-A28C-B864D8BFA513&displaylang=en
http://msdn.microsoft.com/en-us/library/15s06t57(VS.80).aspx
The 'AllOtherFiles' is an entry automatically created when you check the GlobalAssemblyCache predefined folder. After you add in your file(s), perform the following steps:
1. Right-click "Destination Computer"
2. Check "Show Components"
3. Expand the [GlobalAssemblyCache] tree.
4. Delete the "AllOtherFiles" entry.
正則表達式(regular expression)
關(guān)鍵字:
正則表達式,Regular Expression
作者:笑容
發(fā)表于:2004年05月03日
最后更新:2005年01月17日
19:54
版權(quán)聲明:使用創(chuàng)作公用版權(quán)協(xié)議
引用地址:<a
>正則表達式(regular
expression)</a>
NAV: 笑容的八小時外 / 笑容的八小時外資料索引
如何創(chuàng)建一個網(wǎng)站 (HOW TO:
Initiate a website) Red Hat Enterprise
Linux 介紹
前言
正則表達式是煩瑣的,但是強大的,學會之后的應(yīng)用會讓你除了提高效率外,會給你帶來絕對的成就感。只要認真去閱讀這些資料,加上應(yīng)用的時候進行一定的參考,掌握正則表達式不是問題。
索引
1._引子
2._正則表達式的歷史
3._正則表達式定義
3.1_普通字符
3.2_非打印字符
3.3_特殊字符
3.4_限定符
3.5_定位符
3.6_選擇
3.7_后向引用
4._各種操作符的運算優(yōu)先級
5._全部符號解釋
6._部分例子
7._正則表達式匹配規(guī)則
7.1_基本模式匹配
7.2_字符簇
7.3_確定重復出現(xiàn)
目前,正則表達式已經(jīng)在很多軟件中得到廣泛的應(yīng)用,包括*nix(Linux,
Unix等),HP等操作系統(tǒng),PHP,C#,Java等開發(fā)環(huán)境,以及很多的應(yīng)用軟件中,都可以看到正則表達式的影子。
正則表達式的使用,可以通過簡單的辦法來實現(xiàn)強大的功能。為了簡單有效而又不失強大,造成了正則表達式代碼的難度較大,學習起來也不是很容易,所以需要付出一些努力才行,入門之后參照一定的參考,使用起來還是比較簡單有效的。
例子: ^.+@.+""..+$
這樣的代碼曾經(jīng)多次把我自己給嚇退過。可能很多人也是被這樣的代碼給嚇跑的吧。繼續(xù)閱讀本文將讓你也可以自由應(yīng)用這樣的代碼。
注意:這里的第7部分跟前面的內(nèi)容看起來似乎有些重復,目的是把前面表格里的部分重新描述了一次,目的是讓這些內(nèi)容更容易理解。
正則表達式的“祖先”可以一直上溯至對人類神經(jīng)系統(tǒng)如何工作的早期研究。Warren
McCulloch 和 Walter Pitts 這兩位神經(jīng)生理學家研究出一種數(shù)學方式來描述這些神經(jīng)網(wǎng)絡(luò)。
1956 年, 一位叫 Stephen Kleene 的數(shù)學家在 McCulloch 和 Pitts
早期工作的基礎(chǔ)上,發(fā)表了一篇標題為“神經(jīng)網(wǎng)事件的表示法”的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱為“正則集的代數(shù)”的表達式,因此采用“正則表達式”這個術(shù)語。
隨后,發(fā)現(xiàn)可以將這一工作應(yīng)用于使用 Ken Thompson 的計算搜索算法的一些早期研究,Ken Thompson 是 Unix
的主要發(fā)明人。正則表達式的第一個實用應(yīng)用程序就是 Unix 中的 qed 編輯器。
如他們所說,剩下的就是眾所周知的歷史了。從那時起直至現(xiàn)在正則表達式都是基于文本的編輯器和搜索工具中的一個重要部分。
正則表達式(regular
expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。
- 列目錄時, dir *.txt或ls
*.txt中的*.txt就不是一個正則表達式,因為這里*與正則式的*的含義是不同的。
正則表達式是由普通字符(例如字符 a 到
z)以及特殊字符(稱為元字符)組成的文字模式。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。
由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數(shù)字,所有標點符號以及一些符號。
字符 |
含義 |
"cx |
匹配由x指明的控制字符。例如, "cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z
或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。 |
"f |
匹配一個換頁符。等價于 "x0c 和 "cL。 |
"n |
匹配一個換行符。等價于 "x0a 和 "cJ。 |
"r |
匹配一個回車符。等價于 "x0d 和 "cM。 |
"s |
匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ "f"n"r"t"v]。 |
"S |
匹配任何非空白字符。等價于 [^ "f"n"r"t"v]。 |
"t |
匹配一個制表符。等價于 "x09 和 "cI。 |
"v |
匹配一個垂直制表符。等價于 "x0b 和
"cK。 |
所謂特殊字符,就是一些有特殊含義的字符,如上面說的"*.txt"中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉(zhuǎn)義,即在其前加一個"。ls
"*.txt。正則表達式有以下特殊字符。
特別字符 |
說明 |
$ |
匹配輸入字符串的結(jié)尾位置。如果設(shè)置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配
'"n' 或 '"r'。要匹配 $ 字符本身,請使用 "$。 |
( ) |
標記一個子表達式的開始和結(jié)束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用 "( 和
")。 |
* |
匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 "*。 |
+ |
匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 "+。 |
. |
匹配除換行符 "n之外的任何單字符。要匹配 .,請使用 "。 |
[ |
標記一個中括號表達式的開始。要匹配 [,請使用 "[。 |
? |
匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用
"?。 |
" |
將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉(zhuǎn)義符。例如, 'n' 匹配字符
'n'。'"n' 匹配換行符。序列 '""' 匹配 """,而 '"(' 則匹配 "("。 |
^ |
匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^
字符本身,請使用 "^。 |
{ |
標記限定符表達式的開始。要匹配 {,請使用 "{。 |
| |
指明兩項之間的一個選擇。要匹配 |,請使用 "|。 |
- 構(gòu)造正則表達式的方法和創(chuàng)建數(shù)學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結(jié)合在一起來創(chuàng)建更大的表達式。正則表達式的組件可以是單個的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。
限定符用來指定正則表達式的一個給定組件必須要出現(xiàn)多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
*、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的后面加上一個?就可以實現(xiàn)非貪婪或最小匹配。
正則表達式的限定符有:
字符 |
描述 |
* |
匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。*
等價于{0,}。 |
+ |
匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配
"z"。+ 等價于 {1,}。 |
? |
匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does"
中的"do" 。? 等價于 {0,1}。 |
{n} |
n 是一個非負整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的
'o',但是能匹配 "food" 中的兩個 o。 |
{n,} |
n 是一個非負整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配
"foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。 |
{n,m} |
m 和 n 均為非負整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m
次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于
'o?'。請注意在逗號和兩個數(shù)之間不能有空格。 |
用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結(jié)束,"b描述單詞的前或后邊界,"B表示非單詞邊界。
不能對定位符使用限定符。
用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關(guān)的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內(nèi)的正則表達式模式的位置來匹配搜索字符串,后者為負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。
對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關(guān)匹配存儲到一個臨時緩沖區(qū)中,所捕獲的每個子匹配都按照在正則表達式模式中從左至右所遇到的內(nèi)容存儲。存儲子匹配的緩沖區(qū)編號從
1 開始,連續(xù)編號直至最大 99 個子表達式。每個緩沖區(qū)都可以使用 '"n' 訪問,其中 n
為一個標識特定緩沖區(qū)的一位或兩位十進制數(shù)。
可以使用非捕獲元字符 '?:', '?=', or '?!' 來忽略對相關(guān)匹配的保存。
相同優(yōu)先級的從左到右進行運算,不同優(yōu)先級的運算先高后低。各種操作符的優(yōu)先級從高到低如下:
操作符 |
描述 |
" |
轉(zhuǎn)義符 |
(), (?:), (?=), [] |
圓括號和方括號 |
*, +, ?, {n}, {n,}, {n,m} |
限定符 |
^, $, "anymetacharacter |
位置和順序 |
| |
“或”操作 |
字符 |
描述 |
" |
將下一個字符標記為一個特殊字符、或一個原義字符、或一個 向后引用、或一個八進制轉(zhuǎn)義符。例如,'n'
匹配字符 "n"。'"n' 匹配一個換行符。序列 '""' 匹配 """ 而 ""(" 則匹配 "("。 |
^ |
匹配輸入字符串的開始位置。如果設(shè)置了 RegExp 對象的 Multiline 屬性,^ 也匹配
'"n' 或 '"r' 之后的位置。 |
$ |
匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp 對象的 Multiline 屬性,$ 也匹配 '"n'
或 '"r' 之前的位置。 |
* |
匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。*
等價于{0,}。 |
+ |
匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配
"z"。+ 等價于 {1,}。 |
? |
匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does"
中的"do" 。? 等價于 {0,1}。 |
{n} |
n 是一個非負整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的
'o',但是能匹配 "food" 中的兩個 o。 |
{n,} |
n 是一個非負整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配
"foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。 |
{n,m} |
m 和 n 均為非負整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m
次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于
'o?'。請注意在逗號和兩個數(shù)之間不能有空格。 |
? |
當該字符緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m})
后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串 "oooo",'o+?'
將匹配單個 "o",而 'o+' 將匹配所有 'o'。 |
. |
匹配除 ""n" 之外的任何單個字符。要匹配包括 '"n' 在內(nèi)的任何字符,請使用象 '[."n]'
的模式。 |
(pattern) |
匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的 Matches
集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 '"(' 或
'")'。 |
(?:pattern) |
匹配 pattern 但不獲取匹配結(jié)果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用
"或" 字符 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries'
更簡略的表達式。 |
(?=pattern) |
正向預查,在任何匹配 pattern
的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配
"Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的
"Windows"。預查不消耗字符,也就是說,在一個匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。 |
(?!pattern) |
負向預查,在任何不匹配 pattern
的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配
"Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的
"Windows"。預查不消耗字符,也就是說,在一個匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始 |
x|y |
匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配
"zood" 或 "food"。 |
[xyz] |
字符集合。匹配所包含的任意一個字符。例如, '[abc]' 可以匹配 "plain" 中的
'a'。 |
[^xyz] |
負值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain"
中的'p'。 |
[a-z] |
字符范圍。匹配指定范圍內(nèi)的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z'
范圍內(nèi)的任意小寫字母字符。 |
[^a-z] |
負值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到
'z' 范圍內(nèi)的任意字符。 |
"b |
匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er"b' 可以匹配"never" 中的
'er',但不能匹配 "verb" 中的 'er'。 |
"B |
匹配非單詞邊界。'er"B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的
'er'。 |
"cx |
匹配由 x 指明的控制字符。例如, "cM 匹配一個 Control-M 或回車符。x 的值必須為
A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。 |
"d |
匹配一個數(shù)字字符。等價于 [0-9]。 |
"D |
匹配一個非數(shù)字字符。等價于 [^0-9]。 |
"f |
匹配一個換頁符。等價于 "x0c 和 "cL。 |
"n |
匹配一個換行符。等價于 "x0a 和 "cJ。 |
"r |
匹配一個回車符。等價于 "x0d 和 "cM。 |
"s |
匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ "f"n"r"t"v]。 |
"S |
匹配任何非空白字符。等價于 [^ "f"n"r"t"v]。 |
"t |
匹配一個制表符。等價于 "x09 和 "cI。 |
"v |
匹配一個垂直制表符。等價于 "x0b 和 "cK。 |
"w |
匹配包括下劃線的任何單詞字符。等價于'[A-Za-z0-9_]'。 |
"W |
匹配任何非單詞字符。等價于 '[^A-Za-z0-9_]'。 |
"xn |
匹配 n,其中 n 為十六進制轉(zhuǎn)義值。十六進制轉(zhuǎn)義值必須為確定的兩個數(shù)字長。例如,'"x41' 匹配
"A"。'"x041' 則等價于 '"x04' & "1"。正則表達式中可以使用 ASCII 編碼。. |
"num |
匹配 num,其中 num 是一個正整數(shù)。對所獲取的匹配的引用。例如,'(.)"1'
匹配兩個連續(xù)的相同字符。 |
"n |
標識一個八進制轉(zhuǎn)義值或一個向后引用。如果 "n 之前至少 n 個獲取的子表達式,則 n
為向后引用。否則,如果 n 為八進制數(shù)字 (0-7),則 n 為一個八進制轉(zhuǎn)義值。 |
"nm |
標識一個八進制轉(zhuǎn)義值或一個向后引用。如果 "nm 之前至少有 nm 個獲得子表達式,則 nm
為向后引用。如果 "nm 之前至少有 n 個獲取,則 n 為一個后跟文字 m 的向后引用。如果前面的條件都不滿足,若 n 和 m 均為八進制數(shù)字 (0-7),則
"nm 將匹配八進制轉(zhuǎn)義值 nm。 |
"nml |
如果 n 為八進制數(shù)字 (0-3),且 m 和 l 均為八進制數(shù)字 (0-7),則匹配八進制轉(zhuǎn)義值
nml。 |
"un |
匹配 n,其中 n 是一個用四個十六進制數(shù)字表示的 Unicode 字符。例如, "u00A9
匹配版權(quán)符號 (?)。 |
正則表達式 |
說明 |
/"b([a-z]+) "1"b/gi |
一個單詞連續(xù)出現(xiàn)的位置 |
/("w+):"/"/([^/:]+)(:"d*)?([^# ]*)/ |
將一個URL解析為協(xié)議、域、端口及相對路徑 |
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ |
定位章節(jié)的位置 |
/[-a-z]/ |
A至z共26個字母再加一個-號。 |
/ter"b/ |
可匹配chapter,而不能terminal |
/"Bapt/ |
可匹配chapter,而不能aptitude |
/Windows(?=95 |98 |NT )/ |
可匹配Windows95或Windows98或WindowsNT,當找到一個匹配后,從Windows后面開始進行下一次的檢索匹配。 |
7.1
基本模式匹配
一切從最基本的開始。模式,是正規(guī)表達式最基本的元素,它們是一組描述字符串特征的字符。模式可以很簡單,由普通的字符串組成,也可以非常復雜,往往用特殊的字符表示一個范圍內(nèi)的字符、重復出現(xiàn),或表示上下文。例如:
^once
這個模式包含一個特殊的字符^,表示該模式只匹配那些以once開頭的字符串。例如該模式與字符串"once upon a time"匹配,與"There
once was a man from NewYork"不匹配。正如如^符號表示開頭一樣,$符號用來匹配那些以給定模式結(jié)尾的字符串。
bucket$
這個模式與"Who kept all of this cash in a
bucket"匹配,與"buckets"不匹配。字符^和$同時使用時,表示精確匹配(字符串與模式一樣)。例如:
^bucket$
只匹配字符串"bucket"。如果一個模式不包括^和$,那么它與任何包含該模式的字符串匹配。例如:模式
once
與字符串
There once was a man from NewYork
Who kept all of his cash in a
bucket.
是匹配的。
在該模式中的字母(o-n-c-e)是字面的字符,也就是說,他們表示該字母本身,數(shù)字也是一樣的。其他一些稍微復雜的字符,如標點符號和白字符(空格、制表符等),要用到轉(zhuǎn)義序列。所有的轉(zhuǎn)義序列都用反斜杠(")打頭。制表符的轉(zhuǎn)義序列是:"t。所以如果我們要檢測一個字符串是否以制表符開頭,可以用這個模式:
^"t
類似的,用"n表示“新行”,"r表示回車。其他的特殊符號,可以用在前面加上反斜杠,如反斜杠本身用""表示,句號.用".表示,以此類推。
7.2
字符簇
在INTERNET的程序中,正規(guī)表達式通常用來驗證用戶的輸入。當用戶提交一個FORM以后,要判斷輸入的電話號碼、地址、EMAIL地址、信用卡號碼等是否有效,用普通的基于字面的字符是不夠的。
所以要用一種更自由的描述我們要的模式的辦法,它就是字符簇。要建立一個表示所有元音字符的字符簇,就把所有的元音字符放在一個方括號里:
[AaEeIiOoUu]
這個模式與任何元音字符匹配,但只能表示一個字符。用連字號可以表示一個字符的范圍,如:
[a-z] //匹配所有的小寫字母
[A-Z] //匹配所有的大寫字母
[a-zA-Z] //匹配所有的字母
[0-9]
//匹配所有的數(shù)字
[0-9"."-] //匹配所有的數(shù)字,句號和減號
[ "f"r"t"n] //匹配所有的白字符
同樣的,這些也只表示一個字符,這是一個非常重要的。如果要匹配一個由一個小寫字母和一位數(shù)字組成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3"
或"b52"的話,用這個模式:
^[a-z][0-9]$
盡管[a-z]代表26個字母的范圍,但在這里它只能與第一個字符是小寫字母的字符串匹配。
前面曾經(jīng)提到^表示字符串的開頭,但它還有另外一個含義。當在一組方括號里使用^是,它表示“非”或“排除”的意思,常常用來剔除某個字符。還用前面的例子,我們要求第一個字符不能是數(shù)字:
^[^0-9][0-9]$
這個模式與"&5"、"g7"及"-2"是匹配的,但與"12"、"66"是不匹配的。下面是幾個排除特定字符的例子:
[^a-z] //除了小寫字母以外的所有字符
[^"""/"^] //除了(")(/)(^)之外的所有字符
[^"""']
//除了雙引號(")和單引號(')之外的所有字符
特殊字符"."
(點,句號)在正規(guī)表達式中用來表示除了“新行”之外的所有字符。所以模式"^.5$"與任何兩個字符的、以數(shù)字5結(jié)尾和以其他非“新行”字符開頭的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一個“新行”的字符串。
PHP的正規(guī)表達式有一些內(nèi)置的通用字符簇,列表如下:
字符簇 含義
[[:alpha:]] 任何字母
[[:digit:]] 任何數(shù)字
[[:alnum:]] 任何字母和數(shù)字
[[:space:]] 任何白字符
[[:upper:]] 任何大寫字母
[[:lower:]] 任何小寫字母
[[:punct:]] 任何標點符號
[[:xdigit:]] 任何16進制的數(shù)字,相當于[0-9a-fA-F]
7.3
確定重復出現(xiàn)
到現(xiàn)在為止,你已經(jīng)知道如何去匹配一個字母或數(shù)字,但更多的情況下,可能要匹配一個單詞或一組數(shù)字。一個單詞有若干個字母組成,一組數(shù)字有若干個單數(shù)組成。跟在字符或字符簇后面的花括號({})用來確定前面的內(nèi)容的重復出現(xiàn)的次數(shù)。
字符簇 含義
^[a-zA-Z_]$ 所有的字母和下劃線
^[[:alpha:]]{3}$ 所有的3個字母的單詞
^a$ 字母a
^a{4}$ aaaa
^a{2,4}$ aa,aaa或aaaa
^a{1,3}$ a,aa或aaa
^a{2,}$
包含多于兩個a的字符串
^a{2,} 如:aardvark和aaab,但apple不行
a{2,}
如:baad和aaa,但Nantucket不行
"t{2} 兩個制表符
.{2} 所有的兩個字符
這些例子描述了花括號的三種不同的用法。一個數(shù)字,{x}的意思是“前面的字符或字符簇只出現(xiàn)x次”;一個數(shù)字加逗號,{x,}的意思是“前面的內(nèi)容出現(xiàn)x或更多的次數(shù)”;兩個用逗號分隔的數(shù)字,{x,y}表示“前面的內(nèi)容至少出現(xiàn)x次,但不超過y次”。我們可以把模式擴展到更多的單詞或數(shù)字:
^[a-zA-Z0-9_]{1,}$ //所有包含一個以上的字母、數(shù)字或下劃線的字符串
^[0-9]{1,}$ //所有的正數(shù)
^"-{0,1}[0-9]{1,}$ //所有的整數(shù)
^"-{0,1}[0-9]{0,}".{0,1}[0-9]{0,}$ //所有的小數(shù)
最后一個例子不太好理解,是嗎?這么看吧:與所有以一個可選的負號("-{0,1})開頭(^)、跟著0個或更多的數(shù)字([0-9]{0,})、和一個可選的小數(shù)點(".{0,1})再跟上0個或多個數(shù)字([0-9]{0,}),并且沒有其他任何東西($)。下面你將知道能夠使用的更為簡單的方法。
特殊字符"?"與{0,1}是相等的,它們都代表著:“0個或1個前面的內(nèi)容”或“前面的內(nèi)容是可選的”。所以剛才的例子可以簡化為:
^"-?[0-9]{0,}".?[0-9]{0,}$
特殊字符"*"與{0,}是相等的,它們都代表著“0個或多個前面的內(nèi)容”。最后,字符"+"與
{1,}是相等的,表示“1個或多個前面的內(nèi)容”,所以上面的4個例子可以寫成:
^[a-zA-Z0-9_]+$ //所有包含一個以上的字母、數(shù)字或下劃線的字符串
^[0-9]+$ //所有的正數(shù)
^"-?[0-9]+$
//所有的整數(shù)
^"-?[0-9]*".?[0-9]*$ //所有的小數(shù)
當然這并不能從技術(shù)上降低正規(guī)表達式的復雜性,但可以使它們更容易閱讀。
參考文獻:
JScript 和 VBScript 正則表達式
微軟MSDN上的例子(英文):
- Scanning for HREFS
- Provides an example that searches an input string and prints
out all the href="..." values and their locations in the string.
- Changing Date Formats
- Provides an example that replaces dates of the form mm/dd/yy
with dates of the form dd-mm-yy.
- Extracting URL Information
- Provides an example that extracts a protocol and port number
from a string containing a URL. For example,
"http://www.contoso.com:8080/letters/readme.html" returns "http:8080".
- Cleaning an Input String
- provides an example that strips invalid non-alphanumeric
characters from a string.
- Confirming Valid E-Mail Format
- Provides an example that you can use to verify that a string is
in valid e-mail format
|
正則表達式(regular
expression)對象包含一個正則表達式模式(pattern)。它具有用正則表達式模式去匹配或代替一個串(string)中特定字符(或字符集合)的屬性(properties)和方法(methods)。
要為一個單獨的正則表達式添加屬性,可以使用正則表達式構(gòu)造函數(shù)(constructor
function),無論何時被調(diào)用的預設(shè)置的正則表達式擁有靜態(tài)的屬性(the predefined RegExp object has static
properties that are set whenever any regular expression is used,
我不知道我翻得對不對,將原文列出,請自行翻譯)。
- 創(chuàng)建:
一個文本格式或正則表達式構(gòu)造函數(shù)
文本格式: /pattern/flags
正則表達式構(gòu)造函數(shù): new
RegExp("pattern"[,"flags"]);
- 參數(shù)說明:
pattern -- 一個正則表達式文本
flags -- 如果存在,將是以下值:
g: 全局匹配
i:
忽略大小寫
gi: 以上組合
[注意] 文本格式的參數(shù)不用引號,而在用構(gòu)造函數(shù)時的參數(shù)需要引號。如:/ab+c/i new
RegExp("ab+c","i")是實現(xiàn)一樣的功能。在構(gòu)造函數(shù)中,一些特殊字符需要進行轉(zhuǎn)意(在特殊字符前加""")。如:re = new
RegExp("""w+")
正則表達式中的特殊字符
字符 |
含意 |
" |
做為轉(zhuǎn)意,即通常在"""后面的字符不按原來意義解釋,如/b/匹配字符"b",當b前面加了反斜桿后/"b/,轉(zhuǎn)意為匹配一個單詞的邊界。
-或-
對正則表達式功能字符的還原,如"*"匹配它前面元字符0次或多次,/a*/將匹配a,aa,aaa,加了"""后,/a"*/將只匹配"a*"。
|
^ |
匹配一個輸入或一行的開頭,/^a/匹配"an A",而不匹配"An a" |
$ |
匹配一個輸入或一行的結(jié)尾,/a$/匹配"An a",而不匹配"an A" |
* |
匹配前面元字符0次或多次,/ba*/將匹配b,ba,baa,baaa |
+ |
匹配前面元字符1次或多次,/ba*/將匹配ba,baa,baaa |
? |
匹配前面元字符0次或1次,/ba*/將匹配b,ba |
(x) |
匹配x保存x在名為$1...$9的變量中 |
x|y |
匹配x或y |
{n} |
精確匹配n次 |
{n,} |
匹配n次以上 |
{n,m} |
匹配n-m次 |
[xyz] |
字符集(character set),匹配這個集合中的任一一個字符(或元字符) |
[^xyz] |
不匹配這個集合中的任何一個字符 |
["b] |
匹配一個退格符 |
"b |
匹配一個單詞的邊界 |
"B |
匹配一個單詞的非邊界 |
"cX |
這兒,X是一個控制符,/"cM/匹配Ctrl-M |
"d |
匹配一個字數(shù)字符,/"d/ = /[0-9]/ |
"D |
匹配一個非字數(shù)字符,/"D/ = /[^0-9]/ |
"n |
匹配一個換行符 |
"r |
匹配一個回車符 |
"s |
匹配一個空白字符,包括"n,"r,"f,"t,"v等 |
"S |
匹配一個非空白字符,等于/[^"n"f"r"t"v]/ |
"t |
匹配一個制表符 |
"v |
匹配一個重直制表符 |
"w |
匹配一個可以組成單詞的字符(alphanumeric,這是我的意譯,含數(shù)字),包括下劃線,如["w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
|
"W |
匹配一個不可以組成單詞的字符,如["W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。 |
|
說了這么多了,我們來看一些正則表達式的實際應(yīng)用的例子:
E-mail地址驗證:
function test_email(strEmail) {
var myReg =
/^[_a-z0-9]+@([_a-z0-9]+".)+[a-z0-9]{2,3}$/;
if(myReg.test(strEmail))
return true;
return false;
}
HTML代碼的屏蔽
function
mask_HTMLCode(strInput) {
var myReg = /<("w+)>/;
return
strInput.replace(myReg, "<$1>");
}
正則表達式對象的屬性及方法
預定義的正則表達式擁有有以下靜態(tài)屬性:input, multiline,
lastMatch, lastParen, leftContext,
rightContext和$1到$9。其中input和multiline可以預設(shè)置。其他屬性的值在執(zhí)行過exec或test方法后被根據(jù)不同條件賦以不同的值。許多屬性同時擁有長和短(perl風格)的兩個名字,并且,這兩個名字指向同一個值。(JavaScript模擬perl的正則表達式)
正則表達式對象的屬性
屬性 |
含義 |
$1...$9 |
如果它(們)存在,是匹配到的子串 |
$_ |
參見input |
$* |
參見multiline |
$& |
參見lastMatch |
$+ |
參見lastParen |
$` |
參見leftContext |
$' |
參見rightContext |
constructor |
創(chuàng)建一個對象的一個特殊的函數(shù)原型 |
global |
是否在整個串中匹配(bool型) |
ignoreCase |
匹配時是否忽略大小寫(bool型) |
input |
被匹配的串 |
lastIndex |
最后一次匹配的索引 |
lastParen |
最后一個括號括起來的子串 |
leftContext |
最近一次匹配以左的子串 |
multiline |
是否進行多行匹配(bool型) |
prototype |
允許附加屬性給對象 |
rightContext |
最近一次匹配以右的子串 |
source |
正則表達式模式 |
lastIndex |
最后一次匹配的索引
|
|
正則表達式對象的方法
方法 |
含義 |
compile |
正則表達式比較 |
exec |
執(zhí)行查找 |
test |
進行匹配 |
toSource |
返回特定對象的定義(literal representing),其值可用來創(chuàng)建一個新的對象。重載Object.toSource方法得到的。
|
toString |
返回特定對象的串。重載Object.toString方法得到的。 |
valueOf |
返回特定對象的原始值。重載Object.valueOf方法得到 |
|
例子
<script language = "JavaScript">
var myReg = /(w+)s(w+)/;
var
str = "John Smith";
var newstr = str.replace(myReg, "$2, $1");
document.write(newstr);
</script>
將輸出"Smith, John"
〓簡介〓
字符意義:對于字符,通常表示按字面意義,指出接著的字符為特殊字符,不作解釋。
例如:/b/匹配字符'b',通過在b
前面加一個反斜杠,也就是/b/,則該字符變成特殊字符,表示匹配一個單詞的分界線。或者:對于幾個字符,通常說明是特殊的,指出緊接著的字符不是特殊的,而應(yīng)該按字面解釋。例如:*是一個特殊字符,匹配任意個字符(包括0個字符);例如:/a*/意味匹配0個或多個a。為了匹配字面上的*,在a前面加一個反斜杠;例如:/a*/匹配'a*'。
〓正文〓
字符
意義:對于字符,通常表示按字面意義,指出接著的字符為特殊字符,不作解釋。
例如:/b/匹配字符'b',通過在b
前面加一個反斜杠,也就是/b/,則該字符變成特殊字符,表示
匹配一個單詞的分界線。
或者:
對于幾個字符,通常說明是特殊的,指出緊接著的字符不是特殊的,而應(yīng)該按字面解釋。
例如:*是一個特殊字符,匹配任意個字符(包括0個字符);例如:/a*/意味匹配0個或多個a。
為了匹配字面上的*,在a前面加一個反斜杠;例如:/a*/匹配'a*'。
字符^
意義:表示匹配的字符必須在最前邊。
例如:/^A/不匹配"an A,"中的'A',但匹配"An A."中最前面的'A'。
字符$
意義:與^類似,匹配最末的字符。
例如:/t$/不匹配"eater"中的't',但匹配"eat"中的't'。
字符*
意義:匹配*前面的字符0次或n次。
例如:/bo*/匹配"A ghost booooed"中的'boooo'或"A bird
warbled"中的'b',但不匹配"A goat g
runted"中的任何字符。
字符+
意義:匹配+號前面的字符1次或n次。等價于{1,}。
例如:/a+/匹配"candy"中的'a'和"caaaaaaandy."中的所有'a'。
字符?
意義:匹配?前面的字符0次或1次。
例如:/e?le?/匹配"angel"中的'el'和"angle."中的'le'。
字符.
意義:(小數(shù)點)匹配除換行符外的所有單個的字符。
例如:/.n/匹配"nay, an apple is on the
tree"中的'an'和'on',但不匹配'nay'。
字符(x)
意義:匹配'x'并記錄匹配的值。
例如:/(foo)/匹配和記錄"foo
bar."中的'foo'。匹配子串能被結(jié)果數(shù)組中的素[1], ..., [n] 返
回,或被RegExp對象的屬性$1, ..., $9返回。
字符x|y
意義:匹配'x'或者'y'。
例如:/green|red/匹配"green apple"中的'green'和"red
apple."中的'red'。
字符{n}
意義:這里的n是一個正整數(shù)。匹配前面的n個字符。
例如:/a{2}/不匹配"candy,"中的'a',但匹配"caandy,"
中的所有'a'和"caaandy."中前面的兩個
'a'。
字符{n,}
意義:這里的n是一個正整數(shù)。匹配至少n個前面的字符。
例如:/a{2,}不匹配"candy"中的'a',但匹配"caandy"中的所有'a'和"caaaaaaandy."中的所有'a'
字符{n,m}
意義:這里的n和m都是正整數(shù)。匹配至少n個最多m個前面的字符。
例如:/a{1,3}/不匹配"cndy"中的任何字符,但匹配 "candy,"中的'a',"caandy," 中的前面兩個
'a'和"caaaaaaandy"中前面的三個'a',注意:即使"caaaaaaandy" 中有很多個'a',但只匹配前面的三
個'a'即"aaa"。
字符[xyz]
意義:一字符列表,匹配列出中的任一字符。你可以通過連字符-指出一個字符范圍。
例如:[abcd]跟[a-c]一樣。它們匹配"brisket"中的'b'和"ache"中的'c'。
字符[^xyz]
意義:一字符補集,也就是說,它匹配除了列出的字符外的所有東西。 你可以使用連字符-指出一
字符范圍。
例如:[^abc]和[^a-c]等價,它們最早匹配"brisket"中的'r'和"chop."中的'h'。
字符[b]
意義:匹配一個空格(不要與b混淆)
字符b
意義:匹配一個單詞的分界線,比如一個空格(不要與[b]混淆)
例如:/bnw/匹配"noonday"中的'no',/wyb/匹配"possibly yesterday."中的'ly'。
字符B
意義:匹配一個單詞的非分界線
例如:/wBn/匹配"noonday"中的'on',/yBw/匹配"possibly
yesterday."中的'ye'。
字符cX
意義:這里的X是一個控制字符。匹配一個字符串的控制字符。
例如:/cM/匹配一個字符串中的control-M。
字符d
意義:匹配一個數(shù)字,等價于[0-9]。
例如:/d/或/[0-9]/匹配"B2 is the suite
number."中的'2'。
字符D
意義:匹配任何的非數(shù)字,等價于[^0-9]。
例如:/D/或/[^0-9]/匹配"B2 is the suite
number."中的'B'。
字符f
意義:匹配一個表單符
字符n
意義:匹配一個換行符
字符r
意義:匹配一個回車符
字符s
意義:匹配一個單個white空格符,包括空格,tab,form feed,換行符,等價于[ fnrtv]。
例如:/sw*/匹配"foo bar."中的' bar'。
字符S
意義:匹配除white空格符以外的一個單個的字符,等價于[^ fnrtv]。
例如:/S/w*匹配"foo
bar."中的'foo'。
字符t
意義:匹配一個制表符
字符v
意義:匹配一個頂頭制表符
字符w
意義:匹配所有的數(shù)字和字母以及下劃線,等價于[A-Za-z0-9_]。
例如:/w/匹配"apple,"中的'a',"$5.28,"中的'5'和"3D."中的'3'。
字符W
意義:匹配除數(shù)字、字母外及下劃線外的其它字符,等價于[^A-Za-z0-9_]。
例如:/W/或者/[^$A-Za-z0-9_]/匹配"50%."中的'%'。
字符n
意義:這里的n是一個正整數(shù)。匹配一個正則表達式的最后一個子串的n的值(計數(shù)左圓括號)。
例如:/apple(,)sorange1/匹配"apple, orange, cherry, peach."中的'apple, orange',下面
有一個更加完整的例子。
注意:如果左圓括號中的數(shù)字比n指定的數(shù)字還小,則n取下一行的八進制escape作為描述。
字符ooctal和xhex
意義:這里的ooctal是一個八進制的escape值,而xhex是一個十六進制的escape值,允許在一個正則表達式中嵌入ASCII碼。
內(nèi)存模型 (memory model)
內(nèi)存模型描述的是程序中各變量(實例域、靜態(tài)域和數(shù)組元素)之間的關(guān)系,以及在實際計算機系統(tǒng)中將變量存儲到內(nèi)存和從內(nèi)存取出變量這樣的低層細節(jié).
不同平臺間的處理器架構(gòu)將直接影響內(nèi)存模型的結(jié)構(gòu).
在C或C++中, 可以利用不同操作平臺下的內(nèi)存模型來編寫并發(fā)程序. 但是, 這帶給開發(fā)人員的是, 更高的學習成本.
相比之下, java利用了自身虛擬機的優(yōu)勢, 使內(nèi)存模型不束縛于具體的處理器架構(gòu), 真正實現(xiàn)了跨平臺.
(針對hotspot jvm, jrockit等不同的jvm, 內(nèi)存模型也會不相同)
內(nèi)存模型的特征:
a, Visibility 可視性 (多核,多線程間數(shù)據(jù)的共享)
b, Ordering 有序性 (對內(nèi)存進行的操作應(yīng)該是有序的)
java 內(nèi)存模型
(
java memory model
)
根據(jù)Java Language Specification中的說明, jvm系統(tǒng)中存在一個主內(nèi)存(Main Memory或Java Heap Memory),Java中所有變量都儲存在主存中,對于所有線程都是共享的。
每條線程都有自己的工作內(nèi)存(Working Memory),工作內(nèi)存中保存的是主存中某些變量的拷貝,線程對所有變量的操作都是在工作內(nèi)存中進行,線程之間無法相互直接訪問,變量傳遞均需要通過主存完成。
其中, 工作內(nèi)存里的變量, 在多核處理器下, 將大部分儲存于處理器高速緩存中, 高速緩存在不經(jīng)過內(nèi)存時, 也是不可見的.
jmm怎么體現(xiàn) 可視性(Visibility) ?
在jmm中, 通過并發(fā)線程修改變量值, 必須將線程變量同步回主存后, 其他線程才能訪問到.
jmm怎么體現(xiàn) 有序性(Ordering) ?
通過java提供的同步機制或volatile關(guān)鍵字, 來保證內(nèi)存的訪問順序.
緩存一致性(cache coherency)
什么是緩存一致性?
它是一種管理多處理器系統(tǒng)的高速緩存區(qū)結(jié)構(gòu),其可以保證數(shù)據(jù)在高速緩存區(qū)到內(nèi)存的傳輸中不會丟失或重復。(來自wikipedia)
舉例理解:
假如有一個處理器有一個更新了的變量值位于其緩存中,但還沒有被寫入主內(nèi)存,這樣別的處理器就可能會看不到這個更新的值.
解決緩存一致性的方法?
a, 順序一致性模型:
要求某處理器對所改變的變量值立即進行傳播, 并確保該值被所有處理器接受后, 才能繼續(xù)執(zhí)行其他指令.
b, 釋放一致性模型: (類似jmm cache coherency)
允許處理器將改變的變量值延遲到釋放鎖時才進行傳播.
jmm緩存一致性模型 - "happens-before ordering(先行發(fā)生排序)"
一般情況下的示例程序:
x = 0;
y = 0;
i = 0;
j = 0;
// thread A
y = 1;
x = 1;
// thread B
i = x;
j = y;
在如上程序中, 如果線程A,B在無保障情況下運行, 那么i,j各會是什么值呢?
答案是, 不確定. (00,01,10,11都有可能出現(xiàn))
這里沒有使用java同步機制, 所以 jmm 有序性和可視性 都無法得到保障.
happens-before ordering(
先行發(fā)生排序)
如何避免這種情況?
排序原則已經(jīng)做到:
a,
在程序順序中,
線程中的每一個操作, 發(fā)生在當前操作后面將要出現(xiàn)的每一個操作之前.
b, 對象監(jiān)視器的解鎖發(fā)生在等待獲取對象鎖的線程之前.
c, 對volitile關(guān)鍵字修飾的變量寫入操作, 發(fā)生在對該變量的讀取之前.
d,
對一個線程的 Thread.start() 調(diào)用 發(fā)生在啟動的線程中的所有操作之前.
e, 線程中的所有操作 發(fā)生在從這個線程的 Thread.join()成功返回的所有其他線程之前.
為了實現(xiàn)
happends-before ordering原則, java及jdk提供的工具:
a, synchronized關(guān)鍵字
b, volatile關(guān)鍵字
c, final變量
d, java.util.concurrent.locks包(since jdk 1.5)
e, java.util.concurrent.atmoic包(since jdk 1.5)
...
使用了happens-before ordering的例子:
(1) 獲取對象監(jiān)視器的鎖(lock)
(2) 清空工作內(nèi)存數(shù)據(jù), 從主存復制變量到當前工作內(nèi)存, 即同步數(shù)據(jù) (read and load)
(3) 執(zhí)行代碼,改變共享變量值 (use and assign)
(4) 將工作內(nèi)存數(shù)據(jù)刷回主存 (store and write)
(5) 釋放對象監(jiān)視器的鎖 (unlock)
注意: 其中4,5兩步是同時進行的.
這邊最核心的就是第二步, 他同步了主內(nèi)存,即前一個線程對變量改動的結(jié)果,可以被當前線程獲知!(利用了happens-before ordering原則)
對比之前的例子
如果多個線程同時執(zhí)行一段未經(jīng)鎖保護的代碼段,很有可能某條線程已經(jīng)改動了變量的值,但是其他線程卻無法看到這個改動,依然在舊的變量值上進行運算,最終導致不可預料的運算結(jié)果。
經(jīng)典j2ee設(shè)計模式Double-Checked Locking失效問題
雙重檢查鎖定失效問題,一直是JMM無法避免的缺陷之一.了解DCL失效問題, 可以幫助我們深入JMM運行原理.
要展示DCL失效問題, 首先要理解一個重要概念- 延遲加載(lazy loading).
非單例的單線程延遲加載示例:
class Foo
{
private Resource res = null;
public Resource getResource()
{
// 普通的延遲加載
if (res == null)
res = new Resource();
return res;
}
}
非單例的
多線程延遲加載示例:
Class Foo
{
Private Resource res = null;
Public synchronized
Resource getResource()
{
// 獲取實例操作使用同步方式, 性能不高
If (res == null) res = new Resource();
return res;
}
}
非單例的
DCL多線程延遲加載示例:
Class Foo
{
Private Resource res = null;
Public Resource getResource()
{
If (res == null)
{
//只有在第一次初始化時,才使用同步方式.
synchronized(this)
{
if(res == null)
{
res = new Resource();
}
}
}
return res;
}
}
Double-Checked Locking看起來是非常完美的。但是很遺憾,根據(jù)Java的語言規(guī)范,上面的代碼是不可靠的。
出現(xiàn)上述問題, 最重要的2個原因如下:
1, 編譯器優(yōu)化了程序指令, 以加快cpu處理速度.
2, 多核cpu動態(tài)調(diào)整指令順序, 以加快并行運算能力.
問題出現(xiàn)的順序:
1, 線程A, 發(fā)現(xiàn)對象未實例化, 準備開始實例化
2, 由于編譯器優(yōu)化了程序指令, 允許對象在構(gòu)造函數(shù)未調(diào)用完前, 將
共享變量的引用指向
部分構(gòu)造的對象, 雖然對象未完全實例化, 但已經(jīng)不為null了.
3, 線程B, 發(fā)現(xiàn)部分構(gòu)造的對象已不是null, 則直接返回了該對象.
不過, 一些著名的開源框架, 包括jive,lenya等也都在使用DCL模式, 且未見一些極端異常.
說明, DCL失效問題的出現(xiàn)率還是比較低的.
接下來就是性能與穩(wěn)定之間的選擇了?
DCL的替代
Initialize-On-Demand
:
public class Foo {
// 似有靜態(tài)內(nèi)部類, 只有當有引用時, 該類才會被裝載
private static class LazyFoo {
public static Foo foo = new Foo();
}
public static Foo getInstance() {
return LazyFoo.foo;
}
}
維基百科的DCL解釋:
http://en.wikipedia.org/wiki/Double-checked_locking
DCL的完美解決方案:
http://www.theserverside.com/patterns/thread.tss?thread_id=39606
總結(jié):
多線程編程, 針對有寫操作的變量, 必須 保證其所有引用點與主存中數(shù)據(jù)一致(考慮采用同步或volatile)
.
Executor
提供了管理終止的方法,以及可為跟蹤一個或多個異步任務(wù)執(zhí)行狀況而生成 Future
的方法。
可以關(guān)閉 ExecutorService,這將導致其停止接受新任務(wù)。關(guān)閉后,執(zhí)行程序?qū)⒆詈蠼K止,這時沒有任務(wù)在執(zhí)行,也沒有任務(wù)在等待執(zhí)行,并且無法提交新任務(wù)。
通過創(chuàng)建并返回一個可用于取消執(zhí)行和/或等待完成的 Future
,方法 submit 擴展了基本方法 Executor.execute(java.lang.Runnable)
。方法 invokeAny 和 invokeAll 是批量執(zhí)行的最常用形式,它們執(zhí)行任務(wù)集合,然后等待至少一個,或全部任務(wù)完成(可使用 ExecutorCompletionService
類來編寫這些方法的自定義變體)。
Executors
類提供了用于此包中所提供的執(zhí)行程序服務(wù)的工廠方法。
用法示例
下面給出了一個網(wǎng)絡(luò)服務(wù)的簡單結(jié)構(gòu),這里線程池中的線程作為傳入的請求。它使用了預先配置的
Executors.newFixedThreadPool(int)
工廠方法:
class NetworkService {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void serve() {
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request
}
}
壓縮不僅僅可以提高用戶的下載速度,同時還可以加密代碼,下面說下一個常用的js壓縮方法:
首先使用dojo的工具shrinksafe(http://shrinksafe.dojotoolkit.org/)壓縮一下,dojo的這個
工具會去掉注釋,他的壓縮不是簡單的替換變量,而是利用了mozilla的一個工具,對js解析后才壓縮,確保壓縮后的代碼不會出錯。
dojo壓縮后,并不會減少太多,下一步可以使用http://javascriptcompressor.com/這個站點進行更高層次的壓縮,可惜只能登陸這個站點再壓縮,只能將你的js代碼復制的他的文本框,然后等他的壓縮輸出
經(jīng)過這2步,你的js會變得既安全,文件又小
關(guān)于JSP頁面中的pageEncoding和contentType兩種屬性的區(qū)別:
pageEncoding是jsp文件本身的編碼
contentType的charset是指服務(wù)器發(fā)送給客戶端時的內(nèi)容編碼
JSP要經(jīng)過兩次的“編碼”,第一階段會用pageEncoding,第二階段會用utf-8至utf-8,第三階段就是由Tomcat出來的網(wǎng)頁,
用的是contentType。Phontol.com
第一階段是jsp編譯成.java,它會根據(jù)pageEncoding的設(shè)定讀取jsp,結(jié)果是由指定的編碼方案翻譯成統(tǒng)一的UTF-8
JAVA源碼(即.java),如果pageEncoding設(shè)定錯了,或沒有設(shè)定,出來的就是中文亂碼。Phontol.com
第二階段是由JAVAC的JAVA源碼至java
byteCode的編譯,不論JSP編寫時候用的是什么編碼方案,經(jīng)過這個階段的結(jié)果全部是UTF-8的encoding的java源碼。Phontol.com
JAVAC用UTF-8的encoding讀取java源碼,編譯成UTF-8
encoding的二進制碼(即.class),這是JVM對常數(shù)字串在二進制碼(java encoding)內(nèi)表達的規(guī)范。Phontol.com
第三階段是Tomcat(或其的application
container)載入和執(zhí)行階段二的來的JAVA二進制碼,輸出的結(jié)果,也就是在客戶端見到的,這時隱藏在階段一和階段二的參數(shù)contentType就發(fā)揮了功效
contentType的設(shè)定.
pageEncoding 和contentType的預設(shè)都是 ISO8859-1. 而隨便設(shè)定了其中一個,
另一個就跟著一樣了(TOMCAT4.1.27是如此). 但這不是絕對的, 這要看各自JSPC的處理方式.
而pageEncoding不等于contentType, 更有利亞洲區(qū)的文字 CJKV系JSP網(wǎng)頁的開發(fā)和展示, (例pageEncoding=GB2312
不等于 contentType=utf-8)。
在Tomcat中如果在jsp中設(shè)定了pageEncoding,則contentType也跟著設(shè)定成相同的編碼了,但是在resion中就不是,resin中還會用默認的,這點通過查看編譯后的類servlet java文件就可以看到這一點,而問題恰恰就出在這里,所以,在jsp中,如果是在resin下最好還是明確的單獨設(shè)定這2個屬性。
jsp文件不像.java,.java在被編譯器讀入的時候默認采用的是操作系統(tǒng)所設(shè)定的locale所對應(yīng)的編碼,比如中國大陸就是GBK,臺灣就是BIG5或者MS950。Phontol.com而一般我們不管是在記事本還是在ue中寫代碼,如果沒有經(jīng)過特別轉(zhuǎn)碼的話,寫出來的都是本地編碼格式的內(nèi)容。Phontol.com所以編譯器采用的方法剛好可以讓虛擬機得到正確的資料。Phontol.com
但是jsp文件不是這樣,它沒有這個默認轉(zhuǎn)碼過程,但是指定了pageEncoding就可以實現(xiàn)正確轉(zhuǎn)碼了。Phontol.com
舉個例子:
<%@ page contentType="text/html;charset=utf-8" %>
|
大都會打印出亂碼,因為輸入的“你好”是gbk的,但是服務(wù)器是否正確抓到“你好”不得而知。Phontol.com
但是如果更改為
<%@ page contentType="text/html;charset=utf-8" pageEncoding="GBK"%>
|
這樣就服務(wù)器一定會是正確抓到“你好”了。Phontol.com
首先,在linux上安裝perl-Mail-Sendmail-0.79-1.0.rh9.rf.noarch.rpm
perl 代碼如下:
#!/usr/bin/perl
use Mail::Sendmail;
$delay = 1;
$f_list="list.txt";
$line = 0;#skip the column title line
my $subject="xxx";
open(FILE,$f_list) || die "Can not open list file\n";
while(<FILE>){
chomp;
$line=$line+1;
next if($line==1);
($email,$passwd,$username,$yonghuming) = split(/,/);
%mail = (
from => 'xxx@xxx.com',
to => $email,
subject => $subject,
'content-type' => 'text/html; charset="gbk"',
);
$mail{body} = <<END_OF_BODY;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>個人郵箱登陸</title>
<style type="text/css">
<!--
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
-->
</style>
<link href="images/css.css" rel="stylesheet" type="text/css">
<style type="text/css">
<!--
.style1 {font-size: 13px}
.style3 {color: #0066CC}
.style4 {color: #FF0000}
-->
</style>
</head>
<body>
<table width="60%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="10" valign="bottom"><hr width="100%" size="10" color="#3399FF">test</td>
</tr>
</table>
</body>
</html>
END_OF_BODY
sendmail(%mail) || print "Error: $Mail::Sendmail::error\n";
sleep($delay);
}
close(FILE);
list file 內(nèi)容格式:
xx@163.com,xdf.com,xxx,xxx
在firefox3下Components.classes 是不允許直接調(diào)用的,需要加上如下那句粗體的語句才可以
<script>
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref("dom.allow_scripts_to_close_windows", true);
</script>
在chomal.manifest里如下設(shè)定,注意黃色部分,很關(guān)鍵
content sample chrome/content/
xpcnativewrappers=no
overlay chrome://browser/content/browser.xul chrome://sample/content/sample.xul
調(diào)用方式:
window.content.document.getElementById('sssddd').onclick();
參考如下連接
http://developer.mozilla.org/En/Safely_accessing_content_DOM_from_chrome
xpcnativewrappers
http://developer.mozilla.org/en/Chrome_Registration
<style type="text/css" media="all">
div,img{margin: 0;padding: 0;border: 0;}
#content{width: 303px;height: 404px;background: #F63;color: #000;font: 12px Arial,Helvetica,sans-serif;position: relative;}
#content div{position: absolute;left: 0;bottom: 0;}
</style>
</head>
<body>
<div id="content">
<div>底端對齊 </div>
</div>
select max(a.num) A,max(b.num) B,max(c.num) C,tttt.name from tttt
left join (select * from tttt where abc='C') c on c.abc=tttt.abc and c.name=tttt.name
left join (select * from tttt where abc='B') b on b.abc=tttt.abc and b.name=tttt.name
left join (select * from tttt where abc='A') a on a.abc=tttt.abc and a.name=tttt.name
group by name
很多朋友在深入的接觸 JAVA 語言后就會發(fā)現(xiàn)這樣兩個詞:反射 (Reflection) 和內(nèi)省 (Introspector) ,經(jīng)常搞不清楚這到底是怎么回事,在什么場合下應(yīng)用以及如何使用?今天把這二者放在一起介紹,因為它們二者是相輔相成的。
反射
相對而言,反射比內(nèi)省更容易理解一點。用一句比較白的話來概括,反射就是讓你可以通過名稱來得到對象 ( 類,屬性,方法 ) 的技術(shù)。例如我們可以通過類名來生成一個類的實例;知道了方法名,就可以調(diào)用這個方法;知道了屬性名就可以訪問這個屬性的值。
還是寫兩個例子讓大家更直觀的了解反射的使用方法:
引用
//通過類名來構(gòu)造一個類的實例
Class cls_str = Class.forName( "java.lang.String" );
// 上面這句很眼熟,因為使用過 JDBC 訪問數(shù)據(jù)庫的人都用過 J
Object str = cls_str.newInstance();
// 相當于 String str = new String();
//通過方法名來調(diào)用一個方法
String methodName = "length" ;
Method m = cls_str.getMethod(methodName, null );
System.out.println( "length is " + m.invoke(str, null ));
// 相當于 System.out.println(str.length());
上面的兩個例子是比較常用方法。看到上面的例子就有人要發(fā)問了:為什么要這么麻煩呢?本來一條語句就完成的事情干嗎要整這么復雜?沒錯,在上面的例子中確實沒有必要這么麻煩。不過你想像這樣一個應(yīng)用程序,它支持動態(tài)的功能擴展,也就是說程序不重新啟動但是可以自動加載新的功能,這個功能使用一個具體類來表示。首先我們必須為這些功能定義一個接口類,然后我們要求所有擴展的功能類必須實現(xiàn)我指定的接口,這個規(guī)定了應(yīng)用程序和可擴展功能之間的接口規(guī)則,但是怎么動態(tài)加載呢?我們必須讓應(yīng)用程序知道要擴展的功能類的類名,比如是 test.Func1 ,當我們把這個類名 ( 字符串 ) 告訴應(yīng)用程序后,它就可以使用我們第一個例子的方法來加載并啟用新的功能。這就是類的反射,請問你有別的選擇嗎?
關(guān)于方法的反射建議大家看我的另外一篇文章《 利用 Turbine 的事件映射來擴展 Struts 的功能 》,地址是: http://www.javayou.com/article/CSDN/extend_struts.html 。這篇文章詳細介紹了如果通過反射來擴展 Struts 框架的功能。
內(nèi)省
內(nèi)省是 Java 語言對 Bean 類屬性、事件的一種缺省處理方法。例如類 A 中有屬性 name, 那我們可以通過 getName,setName 來得到其值或者設(shè)置新的值。通過 getName/setName 來訪問 name 屬性,這就是默認的規(guī)則。 Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,通過這些 API 可以使你不需要了解這個規(guī)則(但你最好還是要搞清楚),這些 API 存放于包 java.beans 中。
一般的做法是通過類 Introspector 來獲取某個對象的 BeanInfo 信息,然后通過 BeanInfo 來獲取屬性的描述器( PropertyDescriptor ),通過這個屬性描述器就可以獲取某個屬性對應(yīng)的 getter/setter 方法,然后我們就可以通過反射機制來調(diào)用這些方法。下面我們來看一個例子,這個例子把某個對象的所有屬性名稱和值都打印出來:
引用
/*
* Created on 2004-6-29
*/
package demo;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
/**
* 內(nèi)省演示例子
* @author liudong
*/
public class IntrospectorDemo {
String name;
public static void main(String[] args) throws Exception{
IntrospectorDemo demo = new IntrospectorDemo();
demo.setName( "Winter Lau" );
// 如果不想把父類的屬性也列出來的話,
// 那 getBeanInfo 的第二個參數(shù)填寫父類的信息
BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
PropertyDescriptor[] props = bi.getPropertyDescriptors();
for ( int i=0;i<props.length;i++){
System.out.println(props[i].getName()+ "=" +
props[i].getReadMethod().invoke(demo, null ));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
}
Web 開發(fā)框架 Struts 中的 FormBean 就是通過內(nèi)省機制來將表單中的數(shù)據(jù)映射到類的屬性上,因此要求 FormBean 的每個屬性要有 getter/setter 方法。但也并不總是這樣,什么意思呢?就是說對一個 Bean 類來講,我可以沒有屬性,但是只要有 getter/setter 方法中的其中一個,那么 Java 的內(nèi)省機制就會認為存在一個屬性,比如類中有方法 setMobile ,那么就認為存在一個 mobile 的屬性,這樣可以方便我們把 Bean 類通過一個接口來定義而不用去關(guān)心具體實現(xiàn),不用去關(guān)心 Bean 中數(shù)據(jù)的存儲。比如我們可以把所有的 getter/setter 方法放到接口里定義,但是真正數(shù)據(jù)的存取則是在具體類中去實現(xiàn),這樣可提高系統(tǒng)的擴展性。
總結(jié)
將 Java 的反射以及內(nèi)省應(yīng)用到程序設(shè)計中去可以大大的提供程序的智能化和可擴展性。有很多項目都是采取這兩種技術(shù)來實現(xiàn)其核心功能,例如我們前面提到的 Struts ,還有用于處理 XML 文件的 Digester 項目,其實應(yīng)該說幾乎所有的項目都或多或少的采用這兩種技術(shù)。在實際應(yīng)用過程中二者要相互結(jié)合方能發(fā)揮真正的智能化以及高度可擴展性。
另外,以下是SUN的java doc 對
Introspector的解釋:
- public class Introspector
- extends Object
The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.
For each of those three kinds of information, the Introspector will separately analyze the bean's class and superclasses looking for either explicit or implicit information and use that information to build a BeanInfo object that comprehensively describes the target bean.
For each class "Foo", explicit information may be available if there exists a corresponding "FooBeanInfo" class that provides a non-null value when queried for the information. We first look for the BeanInfo class by taking the full package-qualified name of the target bean class and appending "BeanInfo" to form a new class name. If this fails, then we take the final classname component of this name, and look for that class in each of the packages specified in the BeanInfo package search path.
Thus for a class such as "sun.xyz.OurButton" we would first look for a BeanInfo class called "sun.xyz.OurButtonBeanInfo" and if that failed we'd look in each package in the BeanInfo search path for an OurButtonBeanInfo class. With the default search path, this would mean looking for "sun.beans.infos.OurButtonBeanInfo".
If a class provides explicit BeanInfo about itself then we add that to the BeanInfo information we obtained from analyzing any derived classes, but we regard the explicit information as being definitive for the current class and its base classes, and do not proceed any further up the superclass chain.
If we don't find explicit BeanInfo on a class, we use low-level reflection to study the methods of the class and apply standard design patterns to identify property accessors, event sources, or public methods. We then proceed to analyze the class's superclass and add in the information from it (and possibly on up the superclass chain).
Because the Introspector caches BeanInfo classes for better performance, take care if you use it in an application that uses multiple class loaders. In general, when you destroy a ClassLoader
that has been used to introspect classes, you should use the Introspector.flushCaches
or Introspector.flushFromCaches
method to flush all of the introspected classes out of the cache.
For more information about introspection and design patterns, please consult the JavaBeans specification.
FileInputStream 和 FileReader(頭ho暈
的)
FileReader 會做編碼轉(zhuǎn)換,F(xiàn)ileInputStream會忠實于原始文件數(shù)據(jù)。任何形式的Reader都會涉及編碼。
BufferedInputStream和BufferedOutputStream
BufferedInputStream:
添加了功能,即緩沖輸入和支持 mark 和 reset 方法的能力。創(chuàng)建 BufferedInputStream
時即創(chuàng)建了一個內(nèi)部緩沖區(qū)數(shù)組。讀取或跳過流中的各字節(jié)時,必要時可根據(jù)所包含的輸入流再次填充該內(nèi)部緩沖區(qū),一次填充多個字節(jié)。mark
操作記錄輸入流中的某個點,reset 操作導致在從所包含的輸入流中獲取新的字節(jié)前,再次讀取自最后一次 mark 操作以來所讀取的所有字節(jié)。
BufferedOutputStream:該類實現(xiàn)緩沖的輸出流。通過設(shè)置這種輸出流,應(yīng)用程序就可以將各個字節(jié)寫入基礎(chǔ)輸出流中,而不必為每次字節(jié)寫入調(diào)用基礎(chǔ)系統(tǒng)。
BufferedReader和FileReader
BufferedReader :由Reader類擴展而來,提供通用的緩沖方式文本讀取,而且提供了很實用的readLine,讀取分行文本很適合,BufferedReader是針對Reader的,不直接針對文件,也不是只針對文件讀取。
FileReader
是由java.io.InputStreamReade擴展來的,是針對文件讀取的。實際使用時往往用 BufferedReader
bufferedreader = new BufferedReader(new
FileReader("test.conf"));先建立一個文件reader,再用BufferedReader讀。
FileInputStream和Reader
FileInputStream:
擴展自java.io.InputStream,InputStream提供的是字節(jié)流的讀取,而非文本讀取,這是和Reader類的根本區(qū)別。用
Reader讀取出來的是char數(shù)組或者String ,使用InputStream讀取出來的是byte數(shù)組。
Reader:Reader
類及其子類提供的字符流的讀取char(16位),InputStream及其子類提供字節(jié)流的讀取byte(8位),所以FileReader類是將文
件按字符流的方式讀取,F(xiàn)ileInputStream則按字節(jié)流的方式讀取文件,BufferedReader的作用是提供緩沖,
InputStreamReader可以將讀如stream轉(zhuǎn)換成字符流方式(即reader)是reader和stream之間的橋梁
BufferedInputStream和BufferedOutputStream的一個例子
import java.io.*;
public class BufferedStreamDemo...{
public static void main(String[] args)...{
try...{
byte[] data=new byte[1];
File srcFile=new File("BufferedStreamDemo.java");
File desFile=new File("BufferedStreamDemo.txt");
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(desFile));
System.out.println("復制文件: "+srcFile.length()+"字節(jié)");
while(bufferedInputStream.read(data)!=-1)...{
bufferedOutputStream.write(data);
}
//將緩沖區(qū)中的數(shù)據(jù)全部寫出
bufferedOutputStream.flush();
System.out.println("復制完成");
//顯示輸出BufferedStreamDemo.txt文件的內(nèi)容
bufferedInputStream =new BufferedInputStream(new FileInputStream(new File("BufferedStreamDemo.txt")));
while(bufferedInputStream.read(data)!=-1)...{
String str=new String(data);
System.out.print(str);
}
bufferedInputStream.close();
bufferedOutputStream.close();
}catch(ArrayIndexOutOfBoundsException e)...{
System.out.println("using: java useFileStream src des");
e.printStackTrace();
}catch(IOException e)...{
e.printStackTrace();
}
}
}
select distinct item.reportoid, item.lineoid, item.accountoid, sun.amount, mon.amount, tue.amount, wes.amount, thur.amount, fri.amount, sat.amount
from expenseitem item
left join (select reportoid, accountoid, lineoid, amount, itemDate from expenseitem
where itemDate = '2007-11-04' ) sun
on item.reportoid = sun.reportoid and
item.accountoid = sun.accountoid and
item.lineoid = sun.lineoid and
item.itemDate = sun.itemDate
left join (select reportoid, accountoid, lineoid, amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 1) ) mon
on item.reportoid = mon.reportoid and
item.accountoid = mon.accountoid and
item.lineoid = mon.lineoid and
item.itemDate = mon.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 2)) tue
on item.reportoid = tue.reportoid and
item.accountoid = tue.accountoid and
item.lineoid = tue.lineoid and
item.itemDate = tue.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 3) ) wes
on item.reportoid = wes.reportoid and
item.accountoid = wes.accountoid and
item.lineoid = wes.lineoid and
item.itemDate = wes.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 4) ) thur
on item.reportoid = thur.reportoid and
item.accountoid = thur.accountoid and
item.lineoid = thur.lineoid and
item.itemDate = thur.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 5) ) fri
on item.reportoid = fri.reportoid and
item.accountoid = fri.accountoid and
item.lineoid = fri.lineoid and
item.itemDate = fri.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 6) ) sat
on item.reportoid = sat.reportoid and
item.accountoid = sat.accountoid and
item.lineoid = sat.lineoid and
item.itemDate = sat.itemDate
where item.reportoid = 3712
order by reportoid, accountoid;
SELECT REVERSE('abc') AS Expr1
SELECT ascii('c') AS Expr1 取asc碼
select DATE_ADD(date('2008-01-01'),INTERVAL days DAY) days from (select 0 days union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 10 union select 11 union select 12 union select 13 union select 14 union select 15 union select 16 union select 17 union select 18 union select 19 union select 20 union select 21 union select 22 union select 23 union select 24 union select 25 union select 26 union select 27 union select 28 union select 29 union select 30 union select 31) as b
http://www.tutorialspoint.com/wsdl/index.htm
http://www.tutorialspoint.com/
通過使用某種協(xié)議進行通信來完成分布式事務(wù),被稱為
兩段式提交。從名字上看,您可能已經(jīng)知道有兩個階段:
- 第一個階段,即預提交:
- 事務(wù)協(xié)調(diào)器給每個事務(wù)管理器發(fā)送準備操作的信號。
- 事務(wù)管理器將操作(通常是數(shù)據(jù)更新)步驟(或細節(jié))寫入事務(wù)日志。如果失敗,事務(wù)管理器使用這些步驟重復操作。
- 事務(wù)管理器本地創(chuàng)建事務(wù)并通知資源管理器對資源(例如,數(shù)據(jù)庫或消息服務(wù)器)執(zhí)行操作。
- 資源管理器執(zhí)行操作并向事務(wù)管理器報告成功(準備提交信號)或失敗(準備回滾)。
- 資源管理器等待事務(wù)管理器進一步的指令。
- 事務(wù)管理器向事務(wù)協(xié)調(diào)器報告成功或失敗。
- 第二階段,即提交階段:在第二階段中,第一階段的結(jié)果將傳送給所有事務(wù)管理器。如果任何事務(wù)管理器報告失敗,所有的事務(wù)參與者都必須回滾。
- 事務(wù)協(xié)調(diào)器讓所有事務(wù)管理器提交(或回滾)。
- 所有事務(wù)管理器將提交或回滾信息傳遞給其資源管理器。
- 資源管理器將成功或失敗提示返回給事務(wù)管理器。
- 事務(wù)管理器向事務(wù)協(xié)調(diào)器報告成功或失敗。
【IT168 技術(shù)文檔】很多人對二級緩存都不太了解,或者是有錯誤的認識,我一直想寫一篇文章介紹一下hibernate的二級緩存的,今天終于忍不住了。
我的經(jīng)驗主要來自hibernate2.1版本,基本原理和3.0、3.1是一樣的,請原諒我的頑固不化。
hibernate的session提供了一級緩存,每個session,對同一個id進行兩次load,不會發(fā)送兩條sql給數(shù)據(jù)庫,但是session關(guān)閉的時候,一級緩存就失效了。
二級緩存是SessionFactory級別的全局緩存,它底下可以使用不同的緩存類庫,比如ehcache、oscache等,需要設(shè)置hibernate.cache.provider_class,我們這里用ehcache,在2.1中就是
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
如果使用查詢緩存,加上
hibernate.cache.use_query_cache=true
緩存可以簡單的看成一個Map,通過key在緩存里面找value。
Class的緩存
對于一條記錄,也就是一個PO來說,是根據(jù)ID來找的,緩存的key就是ID,value是POJO。無論list,load還是
iterate,只要讀出一個對象,都會填充緩存。但是list不會使用緩存,而iterate會先取數(shù)據(jù)庫select
id出來,然后一個id一個id的load,如果在緩存里面有,就從緩存取,沒有的話就去數(shù)據(jù)庫load。假設(shè)是讀寫緩存,需要設(shè)置:
<cache usage="read-write"/>
如果你使用的二級緩存實現(xiàn)是ehcache的話,需要配置ehcache.xml
<cache
name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false"
timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true"
/>
其中eternal表示緩存是不是永遠不超時,timeToLiveSeconds是緩存中每個元素(這里也就是一個POJO)的超時時間,如果
eternal="false",超過指定的時間,這個元素就被移走了。timeToIdleSeconds是發(fā)呆時間,是可選的。當往緩存里面put
的元素超過500個時,如果overflowToDisk="true",就會把緩存中的部分數(shù)據(jù)保存在硬盤上的臨時文件里面。
每個需要緩存的class都要這樣配置。如果你沒有配置,hibernate會在啟動的時候警告你,然后使用defaultCache的配置,這樣多個class會共享一個配置。
當某個ID通過hibernate修改時,hibernate會知道,于是移除緩存。
這樣大家可能會想,同樣的查詢條件,第一次先list,第二次再iterate,就可以使用到緩存了。實際上這是很難的,因為你無法判斷什么時候是第一
次,而且每次查詢的條件通常是不一樣的,假如數(shù)據(jù)庫里面有100條記錄,id從1到100,第一次list的時候出了前50個id,第二次
iterate的時候卻查詢到30至70號id,那么30-50是從緩存里面取的,51到70是從數(shù)據(jù)庫取的,共發(fā)送1+20條sql。所以我一直認為
iterate沒有什么用,總是會有1+N的問題。
(題外話:有說法說大型查詢用list會把整個結(jié)果集裝入內(nèi)存,很慢,而iterate只select
id比較好,但是大型查詢總是要分頁查的,誰也不會真的把整個結(jié)果集裝進來,假如一頁20條的話,iterate共需要執(zhí)行21條語句,list雖然選擇
若干字段,比iterate第一條select
id語句慢一些,但只有一條語句,不裝入整個結(jié)果集hibernate還會根據(jù)數(shù)據(jù)庫方言做優(yōu)化,比如使用mysql的limit,整體看來應(yīng)該還是
list快。)
如果想要對list或者iterate查詢的結(jié)果緩存,就要用到查詢緩存了
一個b好的介紹w3c的網(wǎng)站。
http://www.w3school.com.cn
http://webservices.ctocio.com.cn/wsjavtec/62/7690562.shtml
通常,你需要獲得當前日期和計算一些其他的日期,例如,你的程序可能需要判斷一個月的第一天或者最后一天。你們大部分人大概都知道怎樣把日期進行分割
(年、月、日等),然后僅僅用分割出來的年、月、日等放在幾個函數(shù)中計算出自己所需要的日期!在這篇文 章里,我將告訴你如何使用DATEADD和
DATEDIFF函數(shù)來計算出在你的程序中可能你要用到的一些不同日期。
在使用本文中的例子之前,你必須注意以下的問題。大部
分可能不是所有例子在不同的機器上執(zhí)行的結(jié)果可能不一樣,這完全由哪一天是一個星期的第一天這個設(shè)置決定。第一天(DATEFIRST)設(shè)定決定了你的系
統(tǒng)使用哪一天作為一周的第一天。所有以下的例 子都是以星期天作為一周的第一天來建立,也就是第一天設(shè)置為7。假如你的第一天設(shè)置不一樣,你可能需要調(diào)整
這些例子,使它和不同的第一天設(shè)置相符合。你可以通過@@DATEFIRST函數(shù)來檢查第一天設(shè)置。
為了理解這些例子,
我們先復習一下DATEDIFF和DATEADD函數(shù)。DATEDIFF函數(shù)計算兩個日期之間的小時、天、周、月、年等時間間隔總數(shù)。DATEADD函數(shù)
計算一個日期通過給時間間隔加減來獲得一個新的日期。要了解更多的DATEDI FF和DATEADD函數(shù)以及時間間隔可以閱讀微軟聯(lián)機幫助。
使用DATEDIFF和DATEADD函數(shù)來計算日期,和本來從當前日期轉(zhuǎn)換到你需要的日期的考慮方法有點不同。你必須從時間間隔這個方面來考慮。比
如,從當前日期到你要得到的日期之間有多少時間間隔,或者,從今天到某一天(比如1900-1-1)之間有多少時間間隔,等等。理解怎樣著眼于時間間隔有
助于你輕松的理解我的不同的日期計算例子。
一個月的第一天
第一個例子,我將告訴你如何從當前日期去這個月的最后一天。請注意:這個例子以及這篇文章中的其他例子都將只使用DATEDIFF和DATEADD函數(shù)來計算我們想要的日期。每一個例子都將通過計算但前的時間間隔,然后進行加減來得到想要計算的日期。
這是計算一個月第一天的SQL 腳本:
SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
我們把這個語句分開來看看它是如何工作的。最核心的函數(shù)是getdate(),大部分人都知道這個是返回當前的日期和時間的函數(shù)。下一個執(zhí)行的函數(shù)
DATEDIFF(mm,0,getdate())是計算當前日期和“1900-01-01 00:00:00.000”這個日期之間的月數(shù)。記住:時期
和時間變量和毫秒一樣是從“1900-01-01 00:00:00.000”開始計算的。這就是為什么你可以在DATEDIFF函數(shù)中指定第一個時間表
達式為“0”。下一個函數(shù)是DATEADD,增加當前日期到“1900-01-01”的月數(shù)。通過增加預定義的日期“1900-01-01”和當前日期的
月數(shù),我們可以獲得這個月的第一天。另外,計算出來的日期的時間部分將會是“00:00:00.000”。
這個計算的技巧是先計算當前日期到“1900-01-01”的時間間隔數(shù),然后把它加到“1900-01-01”上來獲得特殊的日期,這個技巧可以用來計算很多不同的日期。下一個例子也是用這個技巧從當前日期來產(chǎn)生不同的日期。
本周的星期一
這里我是用周(wk)的時間間隔來計算哪一天是本周的星期一。
SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)
一年的第一天
現(xiàn)在用年(yy)的時間間隔來顯示這一年的第一天。
SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)
季度的第一天
假如你要計算這個季度的第一天,這個例子告訴你該如何做。
SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)
當天的半夜
曾經(jīng)需要通過getdate()函數(shù)為了返回時間值截掉時間部分,就會考慮到當前日期是不是在半夜。假如這樣,這個例子使用DATEDIFF和DATEADD函數(shù)來獲得半夜的時間點。
SELECT DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)
深入DATEDIFF和DATEADD函數(shù)計算
你可以明白,通過使用簡單的DATEDIFF和DATEADD函數(shù)計算,你可以發(fā)現(xiàn)很多不同的可能有意義的日期。
目前為止的所有例子只是僅僅計算當前的時間和“1900-01-01”之間的時間間隔數(shù)量,然后把它加到“1900-01-01”的時間間隔上來計算出
日期。假定你修改時間間隔的數(shù)量,或者使用不同的時間間隔來調(diào)用DATEADD函數(shù),或者減去時間間隔而不是增加,那么通過這些小的調(diào)整你可以發(fā)現(xiàn)和多不
同的日期。
這里有四個例子使用另外一個DATEADD函數(shù)來計算最后一天來分別替換DATEADD函數(shù)前后兩個時間間隔。
上個月的最后一天
這是一個計算上個月最后一天的例子。它通過從一個月的最后一天這個例子上減去3毫秒來獲得。有一點要記住,在Sql Server中時間是精確到3毫秒。這就是為什么我需要減去3毫秒來獲得我要的日期和時間。
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))
計算出來的日期的時間部分包含了一個Sql Server可以記錄的一天的最后時刻(“23:59:59:997”)的時間。
去年的最后一天
連接上面的例子,為了要得到去年的最后一天,你需要在今年的第一天上減去3毫秒。
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
本月的最后一天
現(xiàn)在,為了獲得本月的最后一天,我需要稍微修改一下獲得上個月的最后一天的語句。修改需要給用DATEDIFF比較當前日期和“1900-01-01”
返回的時間間隔上加1。通過加1個月,我計算出下個月的第一天,然后減去3毫秒,這樣就計算出了這個月的最后一天。這是計算本月最后一天的SQL腳本。
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))
本年的最后一天
你現(xiàn)在應(yīng)該掌握這個的做法,這是計算本年最后一天腳本
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。
本月的第一個星期一
好了,現(xiàn)在是最后一個例子。這里我要計算這個月的第一個星期一。這是計算的腳本。
select DATEADD(wk, DATEDIFF(wk,0,
dateadd(dd,6-datepart(day,getdate()),getdate())
), 0)
在這個例子里,我使用了“本周的星期一”的腳本,并作了一點點修改。修改的部分是把原來腳本中“getdate()”部分替換成計算本月的第6天,在計算中用本月的第6天來替換當前日期使得計算可以獲得這個月的第一個星期一。
總結(jié)
我希望這些例子可以在你用DATEADD和DATEDIFF函數(shù)計算日期時給你一點啟發(fā)。通過使用這個計算日期的時間間隔的數(shù)學方法,我發(fā)現(xiàn)為了顯示兩
個日期之間間隔的有用歷法是有價值的。注意,這只是計算出這些日期的一種方法。要牢記,還有很多方法 可以得到相同的計算結(jié)果。假如你有其他的方法,那很
不錯,要是你沒有,我希望這些例子可以給你一些啟發(fā),當你要用DATEADD和DATEDIFF函數(shù)計算你程序可能要用到的日期時。
附錄,其他日期處理方法
1)去掉時分秒
declare @ datetime
set @ = getdate() --’2003-7-1 10:00:00’
SELECT @,DATEADD(day, DATEDIFF(day,0,@), 0)
2)顯示星期幾
select datename(weekday,getdate())
3)如何取得某個月的天數(shù)
declare @m int
set @m=2 --月份
select datediff(day,’2003-’+cast(@m as varchar)+’-15’ ,’2003-’+cast(@m+1 as varchar)+’-15’)
另外,取得本月天數(shù)
select datediff(day,cast(month(GetDate()) as varchar)+’-’+cast(month(GetDate()) as varchar)+’-15’ ,cast(month(GetDate()) as varchar)+’-’+cast(month(GetDate())+1 as varchar)+’-15’)
或者使用計算本月的最后一天的腳本,然后用DAY函數(shù)區(qū)最后一天
SELECT Day(dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0)))
4)判斷是否閏年:
SELECT case day(dateadd(mm, 2, dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)))) when 28 then ’平年’ else ’閏年’ end
或者
select case datediff(day,datename(year,getdate())+’-02-01’,dateadd(mm,1,datename(year,getdate())+’-02-01’))
when 28 then ’平年’ else ’閏年’ end
5)一個季度多少天
declare @m tinyint,@time smalldatetime
select @m=month(getdate())
select @m=case when @m between 1 and 3 then 1
when @m between 4 and 6 then 4
when @m between 7 and 9 then 7
else 10 end
select @time=datename(year,getdate())+’-’+convert(varchar(10),@m)+’-01’
select datediff(day,@time,dateadd(mm,3,@time))
The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application. The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed.
The container must guarantee that servlets marked with lower integers
are loaded before servlets marked with higher integers. The container
may choose the order of loading of servlets with the same
load-on-start-up value.
SOA現(xiàn)在正熱得"燙手"。
對于SOA,目前我聽到有兩種說法:一種講它是"顛覆性的革命架構(gòu)",一種是"謹慎觀望"。但無疑,SOA最近幾年發(fā)展得非常快,各主要軟件廠商紛紛高調(diào)跟進,關(guān)于SOA的報道可以說是不絕于耳。對"SOA熱",程序員們有的興奮和期待,有的則感到困惑,最近我在金蝶中間件于廣州、上海等城市舉行的"Java俱樂部"上和程序員們交流時,他們或是以一種朝圣者的表情說:"以前面向?qū)ο蟮募夹g(shù)過時了,SOA時代來了",或者一再懇切地追問我:"SOA到底是什么?作用是什么?"
那么,SOA是什么?到底能解決什么問題、解決得怎樣?我們和客戶都準備好了嗎?我給出的答案是"Just Processing,SOA-現(xiàn)在進行中"。
SOA到底是什么?
SOA(Service-Oriented Architecture)的定義是面向服務(wù)的架構(gòu),就是說將軟件按照功能設(shè)計成一個個服務(wù),這些服務(wù)用標準的方式定義接口、并通過標準的協(xié)議進行調(diào)用。SOA所定義的接口和調(diào)用方式是獨立于編程語言和運行平臺的,廣義上講SOA可以基于不同的底層技術(shù)實現(xiàn),比如CORBA和Web Services。但CORBA由于過于復雜和臃腫已很少使用,所以目前所說的SOA絕大多數(shù)是基于Web Services技術(shù)實現(xiàn)。在Web Services的實現(xiàn)方式下,SOA服務(wù)的接口用XML進行定義。
在SOA架構(gòu)下,軟件開發(fā)從業(yè)務(wù)流程分析開始,使用組件化業(yè)務(wù)建模的方法識別和分析各種業(yè)務(wù)模型,將各種實踐融入其中,在這個基礎(chǔ)上建立用例,用例直接產(chǎn)生BPEL,這些BPEL則可以被融入一個服務(wù)整合框架中,其描述了各種服務(wù)的信息,從而把ESB上的各個模塊統(tǒng)一起來,形成一個巨大的服務(wù)倉。
這樣,SOA甚至是所有軟件人員的一個夢:將中間層再進行抽離,在中間層作一個跨技術(shù)架構(gòu)的元數(shù)據(jù)和業(yè)務(wù)邏輯,使之成為跨技術(shù)架構(gòu)的、可長期繼承、并不斷積累的企業(yè)業(yè)務(wù)庫和最寶貴的信息資產(chǎn),也就是面向服務(wù)的組件庫,而且這個服務(wù)組件庫也可以被其它企業(yè)復用,且不依賴于任何一種技術(shù)架構(gòu)。夸張一點說,如果所有軟件企業(yè)都使用SOA架構(gòu),那么世界軟件業(yè)將會發(fā)生徹底的改變。顯然,這樣一個框架不是一種產(chǎn)品,也不僅僅是一種技術(shù),而是一種解決問題的方法論。
SOA可能應(yīng)用的兩個場景及現(xiàn)有問題
那么,SOA要解決的問題是什么?我認為,從技術(shù)本質(zhì)上講,SOA可能應(yīng)用于兩個場景:第一種是業(yè)務(wù)互通互聯(lián);第二種是封閉交易系統(tǒng),即將元數(shù)據(jù)和業(yè)務(wù)邏輯抽離,形成可復用。舉個例子,在第一種場景中,當不同企業(yè)之間的業(yè)務(wù)需要相互調(diào)用,這時就可能采用SOA技術(shù);在第二種場景中,在企業(yè)內(nèi)部需要將系統(tǒng)進行遷移時,利用SOA技術(shù)定義的原有數(shù)據(jù)和業(yè)務(wù)流程,可以很快完成。
無疑,SOA是一個偉大的思想,它試圖定義一個大家(各種軟件廠商)都"認"的、都"遵循"的法則,大家都使用這樣的方法來進行互聯(lián)互通,從而實現(xiàn)無界限的聯(lián)通,以及服務(wù)組件庫的繼承和復用,解放無效和重復勞動。打一個不那么恰當?shù)谋扔鳎拖袢祟惖恼Z言一樣。SOA或許就像《圣經(jīng)》中那個著名的"通天塔"的故事:人們用同一種語言交流產(chǎn)生的威力是如此之大,以至于他們在巴比倫幾乎要修成一個"通天塔",直達上帝所在的天庭。
但是,在SOA應(yīng)用的兩個場景中,現(xiàn)存的問題同樣也是明顯的:
第一種場景:業(yè)務(wù)互聯(lián)互通,就是應(yīng)用系統(tǒng)互聯(lián)。業(yè)務(wù)互聯(lián),與其說是技術(shù)問題,不如講是業(yè)務(wù)問題,例如ERP、CRM的異步整合,數(shù)據(jù)層面整合都不能很好將兩個系統(tǒng)整合,SOA僅僅是一種實現(xiàn)工具之一,整合效果并不會好不到那里去。我們可以說,在沒有其他選項之前,SOA是一種最"不壞"的方式,但它并不能解決所有的問題,實際上EAI的牽涉面很廣,而我們知道,有些問題并不是單純靠技術(shù)就能解決的。
第二種場景:封閉交易系統(tǒng),缺點是性能慢,而且基于Web Services的交易沒有形成明確的規(guī)范。使用XML作信息交互比較慢是大家都承認的,性能問題將對SOA的發(fā)展造在一定的阻力。同時SOA規(guī)范本身沒有完善,比如Transaction規(guī)范還在不斷完善,而且Web Service多年來收效甚微。總的來說,SOA現(xiàn)在還處在一個發(fā)展階段,很多標準還在制定,不同廠商間還存在不兼容的現(xiàn)象,因此SOA還不能說已經(jīng)是一個成熟的技術(shù),還需要時間的檢驗,還在"進行中"。當然,金蝶中間件作為JCP組織成員,也會推動SOA規(guī)范在J2EE平臺上的實現(xiàn)。
中國用戶的現(xiàn)實選擇之惑
在憧憬SOA技術(shù)可能帶來的前景之余,我們不得不回過頭來冷靜地說:SOA和我們大家的共同客戶――中國企業(yè)還有距離。
中國信息化進程與歐美不同,大量的基礎(chǔ)業(yè)務(wù)系統(tǒng)還沒建立起來,整合需求并不如想象的那么大。從我們對客戶的了解,發(fā)現(xiàn)很少有客戶有SOA的需求。簡單地總結(jié)就是,互通無基礎(chǔ),以新建系統(tǒng)為主,需求并不強烈。而歐美市場大量業(yè)務(wù)系統(tǒng)已建立起來需要整合,從這個角度講,SOA是適用于他們的。同時,在成功案例極少的前提下,SOA還處于培育期,新建封閉交易系統(tǒng)使用SOA技術(shù)還是有一定風險的。
一項新技術(shù)需要市場的消化,大型企業(yè)出于保護企業(yè)投資,不會輕易地轉(zhuǎn)移到新的技術(shù)平臺;而即使像J2EE這樣成熟的技術(shù)經(jīng)過了這么多年的發(fā)展,也不敢說占有統(tǒng)治地位的市場份額。SOA還需要整個IT界的用戶和供應(yīng)商共同促進。
中國信息化需要什么樣的技術(shù)架構(gòu)、能夠接受什么樣的成本價位?這不僅僅是我們的客戶需要考慮,我們軟件廠商要比客戶考慮得更清楚、更進一步。在這個充滿變數(shù)的激烈競爭市場,只有冷靜務(wù)實才能生存、發(fā)展。
From:http://blog.csdn.net/Apusicyuan/archive/2007/03/16/1531424.aspx
解析SOA十大設(shè)計原則 公共接口要明確界限
作者: 佚名, 出處:CSDN, 責任編輯: 包春林,
2008-04-23 05:00
日前國外網(wǎng)站報道介紹了面向服務(wù)架構(gòu)(SOA)的基本原則,提出了公共接口與內(nèi)部實現(xiàn)要有明確界限等原則。雖然這些原則并不是絕對的真理,但可作為一個應(yīng)用開發(fā)參考。
一、明確的邊界
通過跨越定義明確的邊界進行顯式消息傳遞,服務(wù)得以彼此交互。有時候,跨越服務(wù)邊界可能要耗費很大的成本,這要視地理、信任或執(zhí)行因素而定。邊界是指服務(wù)的公共接口與其內(nèi)部專用實現(xiàn)之間的界線。服務(wù)的邊界通過 WSDL 發(fā)布,可能包括說明特定服務(wù)之期望的聲明。
二、服務(wù)共享和約和架構(gòu),不是類
服務(wù)交互應(yīng)當只以服務(wù)的策略、架構(gòu)和基于合約的行為為基礎(chǔ)。服務(wù)的合約通常使用 WSDL 定義,而服務(wù)聚合的合約則可以使用 BPEL 定義(進而,對聚合的每個服務(wù)使用 WSDL)。服務(wù)使用者將依靠服務(wù)的合約來調(diào)用服務(wù)及與服務(wù)交互。鑒于這種依賴性,服務(wù)合約必須長期保持穩(wěn)定。在利用 XML 架構(gòu) (xsd:any) 和 SOAP 處理模型(可選標頭)的可擴展性的同時,合約的設(shè)計應(yīng)盡可能明確。
三、策略驅(qū)動
盡管它往往被認為是最不為人所了解的原則,但對于實現(xiàn)靈活的 Web 服務(wù),它或許是最有力的。單純依靠 WSDL 無法交流某些業(yè)務(wù)交互要求。可以使用策略表達式將結(jié)構(gòu)兼容性(交流的內(nèi)容)與語義兼容性(如何交流消息或者將消息交流給誰)分隔開來。
四、自治
服務(wù)是獨立進行部署、版本控制和管理的實體。開發(fā)人員應(yīng)避免對服務(wù)邊界之間的空間進行假設(shè),因為此空間比邊界本身更容易改變。
五、采用可傳輸?shù)膮f(xié)議格式,而不是API
通常,服務(wù)提供商基于某種傳輸協(xié)議(例如HTTP)提供服務(wù),而服務(wù)消費者只能通過另一種不同的協(xié)議(比如MQ)通信。因此,也許需要在服務(wù)提供商與消費者之間建立一座異步起動同步運行的連接橋梁,超越HTTP和Java Messaging Service消息服務(wù)(JMS)等協(xié)議.從技術(shù)角度講,Java Messaging Service消息服務(wù)(JMS)并不是一種傳輸協(xié)議,而是一組供應(yīng)商中立(vendor-neutral)的通信APIs。
六、面向文檔
消息被構(gòu)造為“純文本的”XML文檔(換句話說,數(shù)據(jù)的格式只對XML有意義)。 消息通常用于傳輸業(yè)務(wù)文檔,比如購買訂單、發(fā)票和提單。這種交互類型與同步消息排隊系統(tǒng)的兼容性很好,比如MQ Series、MSMQ、JMS、TIBCO、IMS等等。
七、松耦合
服務(wù)之間要求最小的依賴性,只要求它們之間能夠相互知曉。
八、符合標準
當通過Web的服務(wù)實現(xiàn)時,最原始的(基本的)面向服務(wù)的架構(gòu)(SOA)的模型僅僅提供了很低程度上的關(guān)于可靠性、安全性以及事務(wù)管理的標準化機制。第二代的技術(shù)條件和框架,如WS-ReliableMessaging規(guī)范、 WS-Security規(guī)范和WS-Coordination規(guī)范 (與WS-AtomicTransaction規(guī)范和WS-BusinessActivity規(guī)范相聯(lián)系),它們試圖以工業(yè)標準的方式定位存在的缺陷。
九、獨立軟件供應(yīng)商
向SOA的轉(zhuǎn)變正在深刻改變了經(jīng)濟現(xiàn)實。客戶們會期待更合理的費用以及不必重新進行投資就能改進業(yè)務(wù)的能力。因此,獨立軟件供應(yīng)商沒有選擇,只能使自己的業(yè)務(wù)更加靈活,以期讓自己的客戶也變得同樣靈活。于是,面向服務(wù)不僅是簡單的在現(xiàn)有的、緊耦合的、復雜的、不靈活的以及非組件化的業(yè)務(wù)功能上添加基于標準的接口。更重要的是,為了兌現(xiàn)SOA的承諾,獨立軟件供應(yīng)商必須改變他們構(gòu)建、打包、銷售、交付、管理和支持自身產(chǎn)品的方式。
十、元數(shù)據(jù)驅(qū)動
開發(fā)元數(shù)據(jù)本身并不是元數(shù)據(jù)驅(qū)動應(yīng)用程序的本意。使用元數(shù)據(jù)來驅(qū)動服務(wù)在系統(tǒng)邊界的傳播是一個更為正確的方法。
一個事務(wù)處理的屬性有:Required,RequiresNew,Mandatory,NotSupported,Supports,Never.
1、Required:當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法,這個方法執(zhí)行客戶端的事務(wù)處理;當客戶端沒有啟動一個事務(wù)處理,則EJB容器在執(zhí)行這個方法之前啟動一個新的事務(wù)處理.
2、RequiresNew:當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法時,容器管理器做如下操作:
(1) 懸掛客戶端的事務(wù)處理;
(2) 開始一個新的事務(wù)處理;
(3) 調(diào)用方法;
(4) 當方法結(jié)束,恢復客戶端的事物處理.
當客戶端沒有啟動一個事務(wù)處理,容器管理器在執(zhí)行這個方法之前啟動一個新的事務(wù)處理.
3、Mandatory: 當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法,這個方法在客戶端的事務(wù)處理范圍內(nèi)被執(zhí)行; 當客戶端沒有啟動一個事務(wù)處理,容器管理器將會拋錯(TransactionRequiredException);
4、NotSupported: 當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法,容器管理器在調(diào)用方法之前終止客戶端的事務(wù)處理,當方法執(zhí)行完,再恢復客戶端的事務(wù)處理; 當客戶端沒有啟動一個事務(wù)處理,容器管理器在調(diào)用方法時不啟動事務(wù)處理.
5、Supports: 當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法,在運行方法時執(zhí)行客戶端的事務(wù)處理; 當客戶端沒有啟動一個事務(wù)處理,容器管理器在調(diào)用方法時不啟動事務(wù)處理.
6、Never: 當客戶端運行一個事務(wù)處理并調(diào)用EJB的一個方法,容器管理器將拋出一個錯誤(RemoteException); 當客戶端沒有啟動一個事務(wù)處理,容器管理器在調(diào)用方法時不啟動事務(wù)處理.
在jbuilder中,缺省是Required;
第一個ejb可以是 Required,這個ejb調(diào)用的那個ejb方法如果想在一個
事務(wù)上下文中,我覺得可能采用Mandatory,方式比較好。如果它們不在一個事務(wù)上下文中,就會拋錯(TransactionRequiredException),是一個上下文,就沒有問題
幾乎每個做過Web開發(fā)的人都問過,到底元素的ID和Name有什么區(qū)別阿?為什么有了ID還要有Name呢?而同樣我們也可以得到最classical的答案:ID就像是一個人的身份證號碼,而Name就像是他的名字,ID顯然是唯一的,而Name是可以重復的。
上周我也遇到了ID和Name的問題,在頁面里輸入了一個input type="hidden",只寫了一個ID='SliceInfo',賦值后submit,在后臺用Request.Params["SliceInfo"]卻怎么也去不到值。后來恍然大悟因該用Name來標示,于是在input里加了個Name='SliceInfo',就一切ok了。
第一段里對于ID和Name的解答說的太籠統(tǒng)了,當然那個解釋對于ID來說是完全對的,它就是Client端HTML元素的Identity。而Name其實要復雜的多,因為Name有很多種的用途,所以它并不能完全由ID來代替,從而將其取消掉。
具體用途有:
用途1: 作為可與服務(wù)器交互數(shù)據(jù)的HTML元素的服務(wù)器端的標示,比如input、select、textarea、和button等。我們可以在服務(wù)器端根據(jù)其Name通過Request.Params取得元素提交的值。
用途2: HTML元素Input type='radio'分組,我們知道radio button控件在同一個分組類,check操作是mutex的,同一時間只能選中一個radio,這個分組就是根據(jù)相同的Name屬性來實現(xiàn)的。
用途3: 建立頁面中的錨點,我們知道link是獲得一個頁面超級鏈接,如果不用href屬性,而改用Name,如:,我們就獲得了一個頁面錨點。
用途4: 作為對象的Identity,如Applet、Object、Embed等元素。比如在Applet對象實例中,我們將使用其Name來引用該對象。
用途5: 在IMG元素和MAP元素之間關(guān)聯(lián)的時候,如果要定義IMG的熱點區(qū)域,需要使用其屬性usemap,使usemap="#name"(被關(guān)聯(lián)的MAP元素的Name)。
用途6: 某些特定元素的屬性,如attribute,和param。例如為Object定義參數(shù)
顯然這些用途都不是能簡單的使用ID來代替掉的,所以HTML元素的ID和Name的卻別并不是身份證號碼和姓名這樣的區(qū)別,它們更本就是不同作用的東西。
當然HTML元素的Name屬性在頁面中也可以起那么一點ID的作用,因為在DHTML對象樹中,我們可以使用document.getElementsByName來獲取一個包含頁面中所有指定Name元素的對象數(shù)組。
在這里順便說一下,要是頁面中有n(n>1)個HTML元素的ID都相同了怎么辦?在DHTML對象中怎么引用他們呢?如果我們使用ASPX頁面,這樣的情況是不容易發(fā)生的,因為aspnet進程在處理aspx頁面時根本就不允許有ID非唯一,這是頁面會被拋出異常而不能被正常的render。要是不是動態(tài)頁面,我們硬要讓ID重復那IE怎么搞呢?
這個時候我們還是可以繼續(xù)使用document.getElementById獲取對象,只不過我們只能獲取ID重復的那些對象中在HTML Render時第一個出現(xiàn)的對象。而這時重復的ID會在引用時自動變成一個數(shù)組,ID重復的元素按Render的順序依次存在于數(shù)組中。
程序題:我想啟動一個線程執(zhí)行特定的任務(wù),任務(wù)的具體執(zhí)行內(nèi)容定義在TheRunnable類中(實現(xiàn)了java.lang.Runnable接口):
TheRunnable theRunnable = new TheRunnable();
以下哪個語句可用于啟動theRunnable任務(wù)線程:_____
a) theRunnable.run();
b) theRunnable.start();
c) Thread thread = new Thread(theRunnable); thread.run();
d) Thread thread = new Thread(theRunnable); thread.start();
前言
全國青少年信息學(計算機)奧林匹克競賽常常要用到許多經(jīng)典算法,比如約瑟夫問題、螺旋方陣、漢諾塔、八皇后問題等,而 螺旋方陣問題是其中較為常用的一種。這類問題的算法分析對于計算機圖形學、解析幾何中的相關(guān)問題都有一定的啟發(fā)性。盡管現(xiàn)有算法已取得了令人振奮的成績, 但依然具有一定的片面性,或者說過于復雜。實際上,這個問題有不同的解決算法,鑒于這個問題具有一定的典型性,本文針對信息學奧林匹克競賽這一問題進行了 全面系統(tǒng)的分析、歸納,從不同的角度對這個問題的算法進行分析并通過程序?qū)崿F(xiàn)。使讀者對這個問題在算法選擇上有更大的余地,從而避免算法的單一性,同時對 于類似相關(guān)問題的解決也有一定的啟發(fā)和幫助。
2 問題的描述與分析
關(guān)于螺旋方陣的輸出主要是指將一些數(shù)據(jù)或符號按照一定的順序輸出到計算機的屏幕上或者是輸出到一個指定的文件中去,輸出的幾種常見情況如下圖(為簡單起見,以輸出5階的數(shù)字螺旋方陣為例):
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
1 16 15 14 13
2 17 24 25 12
3 18 25 23 11
4 19 20 21 10
5 6 7 8 9
21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13
21 20 19 18 17
22 7 6 5 16
23 8 1 4 15
24 9 2 3 14
25 10 11 12 13
圖1由外及里順時針;圖2由外及里逆時針;圖3由里及外順時針;圖4由里及外逆時針
在實際應(yīng)用中,輸出的內(nèi)容可以不盡相同。在上面的圖1至圖4中,按螺旋順序輸出的數(shù)顯然有一定的規(guī)律,而實際輸出的順序往往不是按照螺旋順序,通常是將上圖中的數(shù)據(jù)按行(或按列)輸出,因此這類問題的關(guān)鍵在于如何將有規(guī)律的數(shù)據(jù)與實際輸出時的先后順序?qū)?yīng)起來。下面采用不同的算法來實現(xiàn)。
3 采用不同算法解決螺旋方陣的輸出
3.1非遞歸算法
3.1.1 “海龜”算法(順時針,由外及里)
參照海龜行走的做法,用一對變量A,B模擬海龜頭的方向,根據(jù)屏幕坐標的特點,A、B的取值和“海龜頭”方向有這樣的關(guān)系:(0,1)表示向右;(0, -1)表示向左;(-1,0)表示向上;(1,0)表示向下;用另一對變量X,Y模擬海龜位置,“海龜”每前進一步,它的新位置即為X=X+A,Y=Y+B;要海龜向右轉(zhuǎn),就改變A、B的值,根據(jù)數(shù)學知識可以得出具體的變換公式是:C=A;A=B;B=-C。下面用自然語言對算法進行描述:讓海龜先走n步,然后右轉(zhuǎn),再走n-1步,再右轉(zhuǎn),再走n-1步,再右轉(zhuǎn),再走n-2步,再右轉(zhuǎn),再走n-2步……如此類推,直到海龜前進的步數(shù)為0時停止;而每當“海龜”前進1步,就在它位置上顯示一個數(shù)字,那么前進n步即重復執(zhí)行“X:=X+A,Y:=Y+B”語句n次。但如何讓下兩個循環(huán)的重復次數(shù)都為n-1呢?解決的方法是:循環(huán)n次后,讓n的值減少0.5,然后再轉(zhuǎn)回執(zhí)行同樣的循環(huán)。擴展到顯示n位數(shù),則須留n列的位置,也就是說,海龜水平方向每次得前進n步,才有足夠的位置顯示大一點的數(shù)字方陣,需把Y=Y+B改成Y=Y+n*B就行了。“海龜”算法的優(yōu)點是簡潔清晰。
3.1.2 “分割”算法(逆時針,由外及里)
設(shè)螺旋方陣對應(yīng)的一般二維數(shù)組如下:
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
圖5
按逆時針方向從外向內(nèi),一層層給下標變量賦值,由于階數(shù)n的任意性,需考慮以下幾個問題:層數(shù)k與階數(shù)n的關(guān)系式,n由用戶輸入,k根據(jù)n來計算;定義變量value,賦值時讓其自增;分析每層矩形四條邊元素的下標變化規(guī)律,將方陣元素按逆時針方向分成四個部分:方陣左半邊(三列),方陣下半邊(二行),方陣右半邊(兩列),方陣上半邊(二行)。
具體算法思想:以5階方陣為例,可判斷 k=[(n+1)/2]=3,用循環(huán)控制產(chǎn)生的層數(shù),語句為for(k=0,k <(n+1)/2;k++)。
Step1:找出方陣左半邊列規(guī)律:列下標正好是層數(shù)k的值,行下標在第一列從0變到4,第二列從1變到3,在第三列從2變到2,故推導出n階螺旋方陣左半邊由外到內(nèi)的列循環(huán)結(jié)構(gòu):for(i=k;i <n-k;i++) mat[i][k]=value++;此循環(huán)執(zhí)行一次,產(chǎn)生一列元素,循環(huán)執(zhí)行的次數(shù)由外循環(huán)來控制。
Step2:找出方陣下半邊行規(guī)律:行下標從4變到3,每層取值為n―k―1;列下標由外到內(nèi)第一行從1變到4(a40已產(chǎn)生),第二行(a30 、a31已產(chǎn)生)從2變到3,第三行只有一個元素a22,故推導出n階螺旋方陣下半邊行循環(huán)結(jié)構(gòu):for(i=k+1;i <n-k;i++) mat[n-k-1][i]=value++;
Step3:找出方陣右半邊列規(guī)律:行下標第一列從3變化到0(a44已產(chǎn)生),第二列從2變到1(a43、a33、a03已產(chǎn)生),可推斷行的初值為n-k-2;列下標沒變化,兩列的下標分別為4、3,故推斷出右半邊的列可由下列循環(huán)結(jié)構(gòu)完成:for(i=n-k-2;i >=k;i--) mat[i][n-k-1]=value++;
Step4:找出方陣上半邊行規(guī)律:已經(jīng)產(chǎn)生了的元素不能再重新賦值,而行下標可用層次k來表示,列下標與右半邊行下標變化規(guī)律一樣,由此推斷出上半邊的行可由下列循環(huán)結(jié)構(gòu)完成:for(i=n-k-2;i >k;i--) mat[k][i]=value++。
當k取一個值時,以上四個循環(huán)依序各產(chǎn)生一列或一行元素,由此產(chǎn)生一層元素,當k在變化范圍[0…(n+1)/2]內(nèi)依次取值時,四個循環(huán)輪流執(zhí)行,一個數(shù)字螺旋方陣就這樣生成了。
3.2 遞歸算法
分析圖五容易看出,當由外及里順時針旋轉(zhuǎn)時,最外層數(shù)據(jù)輸出后,內(nèi)層的圖形只不過是層數(shù)減少了,即問題的規(guī)模變小了,但問題的性質(zhì)沒有發(fā)生變化,新問題和原問題仍然可以采用相同的解法。所以這一問題完全可以采用遞歸的方法來求解。具體的算法描述如下。
Step1:初始化。把需要輸出的數(shù)據(jù)放入一維數(shù)組,設(shè)為b[1..n*n]。因為是n階方陣,所以全部元素共有n2個,輸出b[1]到b[n*n]的順序是方陣順時針旋轉(zhuǎn)的順序。
Step2:把b數(shù)組中的每個元素放入到二維數(shù)組a[i][j](圖5)中去,如b[1]放入a[0][0]中,b[2]放入a[0][1]中,……,b[6]放入a[1][4]中……,其它元素依次放入。
Step3:按行輸出數(shù)組元素a[i][j]即可。
上述算法中,難點在于如何將b數(shù)組放入到a[i][j]數(shù)組對應(yīng)的分量中去。為此,對step2進行求精并使用遞歸來解決。具體做法:將數(shù)組a初始化為0。設(shè)置變量direction作為方向標志。當direction為1、2、3、4時,分別表示向右、向下、向左、向上。并編寫如下的遞歸子程序walk(x,y,direction,k)。其中參數(shù)x,y表示數(shù)組的下標。k是計數(shù)器。當 k>n*n 為遞歸出口。
case direction of
{right } 1: if到右邊界then 向下拐 else 向右輸出;
{down} 2: if到下邊界 then 向左拐 else 向下輸出;
{left} 3: if到左邊界 then 向上拐 else 向左輸出;
{up} 4: if 到上邊界 then 向右拐 else 向上輸出。
end;{end case}
3.3 算法實現(xiàn)
限于篇幅,本文僅給出遞歸算法的主要程序段(pascal語言)
procedure walk(x,y,direction,k:integer);
begin
if k>n*n then 按行輸出a數(shù)組;
a[x,y]:=b[k];
case direction of
{right}1: if (y=n) or (a[x,y+1]<>0) then walk(x+1,y,2,k+1) else walk(x,y+1,1,k+1);
{down}2: if (x=n) or (a[x+1,y]<>0) then walk(x,y-1,3,k+1) else walk(x+1,y,2,k+1);
{left} 3: if (y=1) or (a[x,y-1]<>0) then walk(x-1,y,4,k+1) else walk(x,y-1,3,k+1);
{up} 4: if (x=1) or (a[x-1,y]<>0) then walk(x,y+1,1,k+1) else walk(x-1,y,4,k+1)
end;
begin{main}
fillchar(a,sizeof(a),0);
writeln('please input a integer for n:');
readln(n);
walk(1,1,1,1);
end.{end main}
4 結(jié)束語
關(guān)于螺旋方陣的輸出算法主要有上述幾種,其他幾種方陣的輸出,可以仿照上述的算法分析加以實現(xiàn)。相對而言,遞 歸算法較為簡潔,但是時間復雜度要高一些,對于輸出高階螺旋方陣時,時間很長。另外在空間復雜度方面,采用數(shù)組這種數(shù)據(jù)結(jié)構(gòu),顯然有一定的局限性,如果使 用鏈表來存儲,將會盡可能地避免空間不足的現(xiàn)象。另外,上述問題也可以使用一個模板式的子程序來完成,這時要求輸入的參數(shù)要包括:從外還是從里螺旋、順時 針還是逆時針,起點坐標等參數(shù),對于從里向外螺旋時,還要考慮螺旋方陣的階數(shù)是奇數(shù)還是偶數(shù),分別給予不同的處理。
本篇文章來源于 義烏信息技術(shù)教研網(wǎng) 原文鏈接:http://www.ywhs.net/itedu/html/aosaifudao/mingshifudao/20071125/47.html
Java最初是在瀏覽器和客戶端機器中粉墨登場的。當時,很多人質(zhì)疑它是否適合做服務(wù)器端的開發(fā)。現(xiàn)在,隨著對Java2平臺企業(yè)版(J2EE)第三方支持的增多,Java被廣泛接納為開發(fā)企業(yè)級服務(wù)器端解決方案的首選平臺之一。
J2EE平臺由一整套服務(wù)(Services)、應(yīng)用程序接口(APIs)和協(xié)議構(gòu)成,它對開發(fā)基于Web的多層應(yīng)用提供了功能支持。
在本文中我將解釋支撐J2EE的13種核心技術(shù):JDBC, JNDI, EJBs, RMI, JSP, Java servlets, XML, JMS, Java IDL, JTS, JTA, JavaMail 和 JAF,同時還將描述在何時、何處需要使用這些技術(shù)。當然,我還要介紹這些不同的技術(shù)之間是如何交互的。
此外,為了讓您更好地感受J2EE的真實應(yīng)用,我將在WebLogic應(yīng)用服務(wù)器,來自BEA Systems公司的一種廣為應(yīng)用的產(chǎn)品環(huán)境下來介紹這些技術(shù)。不論對于WebLogic應(yīng)用服務(wù)器和J2EE的新手,還是那些想了解J2EE能帶來什么好處的項目管理者和系統(tǒng)分析員,相信本文一定很有參考價值。
宏觀印象: 分布式結(jié)構(gòu)和J2EE
過去,二層化應(yīng)用 -- 通常被稱為client/server應(yīng)用 -- 是大家談?wù)摰淖疃嗟摹T诤芏嗲闆r下,服務(wù)器提供的惟一服務(wù)就是數(shù)據(jù)庫服務(wù)。在這種解決方案中,客戶端程序負責數(shù)據(jù)訪問、實現(xiàn)業(yè)務(wù)邏輯、用合適的樣式顯示結(jié)果、彈出預設(shè)的用戶界面、接受用戶輸入等。client/server結(jié)構(gòu)通常在第一次部署的時候比較容易,但難于升級或改進,而且經(jīng)常基于某種專有的協(xié)議,通常是某種數(shù)據(jù)庫協(xié)議。它使得重用業(yè)務(wù)邏輯和界面邏輯非常困難。更重要的是,在Web時代,二層化應(yīng)用通常不能體現(xiàn)出很好的伸縮性,因而很難適應(yīng)Internet的要求。
Sun設(shè)計J2EE的部分起因就是想解決二層化結(jié)構(gòu)的缺陷。于是,J2EE定義了一套標準來簡化N層企業(yè)級應(yīng)用的開發(fā)。它定義了一套標準化的組件,并為這些組件提供了完整的服務(wù)。J2EE還自動為應(yīng)用程序處理了很多實現(xiàn)細節(jié),如安全、多線程等。
用J2EE開發(fā)N層應(yīng)用包括將二層化結(jié)構(gòu)中的不同層面切分成許多層。一個N層化應(yīng)用A能夠為以下的每種服務(wù)提供一個分開的層:
顯示:在一個典型的Web應(yīng)用中,客戶端機器上運行的瀏覽器負責實現(xiàn)用戶界面。
動態(tài)生成顯示: 盡管瀏覽器可以完成某些動態(tài)內(nèi)容顯示,但為了兼容不同的瀏覽器,這些動態(tài)生成工作應(yīng)該放在Web服務(wù)器端進行,使用JSP、Servlets,或者XML(可擴展標記語言)和(可擴展樣式表語言)。
業(yè)務(wù)邏輯:業(yè)務(wù)邏輯適合用Session EJBs(后面將介紹)來實現(xiàn)。
數(shù)據(jù)訪問:數(shù)據(jù)訪問適合用Entity EJBs(后面將介紹)和JDBC來實現(xiàn)。
后臺系統(tǒng)集成: 同后臺系統(tǒng)的集成可能需要用到許多不同的技術(shù),至于何種最佳需要根據(jù)后臺系統(tǒng)的特征而定。
您可能開始詫異:為什么有這么多的層?事實上,多層方式可以使企業(yè)級應(yīng)用具有很強的伸縮性,它允許每層專注于特定的角色。例如,讓Web服務(wù)器負責提供頁面,應(yīng)用服務(wù)器處理應(yīng)用邏輯,而數(shù)據(jù)庫服務(wù)器提供數(shù)據(jù)庫服務(wù)。
由于J2EE建立在Java2平臺標準版(J2SE)的基礎(chǔ)上,所以具備了J2SE的所有優(yōu)點和功能。包括“編寫一次,到處可用”的可移植性、通過JDBC訪問數(shù)據(jù)庫、同原有企業(yè)資源進行交互的CORBA技術(shù),以及一個經(jīng)過驗證的安全模型。在這些基礎(chǔ)上,J2EE又增加了對EJB(企業(yè)級Java組件)、Java servlets、Java服務(wù)器頁面(JSPs)和XML技術(shù)的支持。
分布式結(jié)構(gòu)與WebLogic應(yīng)用服務(wù)器
J2EE提供了一個框架--一套標準API--用于開發(fā)分布式結(jié)構(gòu)的應(yīng)用,這個框架的實際實現(xiàn)留給了第三方廠商。部分廠商只是專注于整個J2EE架構(gòu)中的的特定組件,例如Apache的Tomcat提供了對JSP和servlets的支持,BEA系統(tǒng)公司則通過其WebLogic應(yīng)用服務(wù)器產(chǎn)品為整個J2EE規(guī)范提供了一個較為完整的實現(xiàn)。
WebLogic服務(wù)器已使建立和部署伸縮性較好的分布式應(yīng)用的過程大為簡化。WebLogic和J2EE代你處理了大量常規(guī)的編程任務(wù),包括提供事務(wù)服務(wù)、安全領(lǐng)域、可靠的消息、名字和目錄服務(wù)、數(shù)據(jù)庫訪問和連接池、線程池、負載平衡和容錯處理等。
通過以一種標準、易用的方式提供這些公共服務(wù),象WebLogic服務(wù)器這樣的產(chǎn)品造就了具有更好伸縮性和可維護性的應(yīng)用系統(tǒng),使其為大量的用戶提供了增長的可用性。
J2EE技術(shù)
在接下來的部分里,我們將描述構(gòu)成J2EE的各種技術(shù),并且了解WebLogic服務(wù)器是如何在一個分布式應(yīng)用中對它們進行支持的。最常用的J2EE技術(shù)應(yīng)該是JDBC、JNDI、EJB、JSP和servlets,對這些我們將作更仔細的考察。
Java Database Connectivity (JDBC)
JDBC API以一種統(tǒng)一的方式來對各種各樣的數(shù)據(jù)庫進行存取。和ODBC一樣,JDBC為開發(fā)人員隱藏了不同數(shù)據(jù)庫的不同特性。另外,由于JDBC建立在Java的基礎(chǔ)上,因此還提供了數(shù)據(jù)庫存取的平臺獨立性。
JDBC定義了4種不同的驅(qū)動程序,現(xiàn)分述如下:
類型 1: JDBC-ODBC Bridge
在JDBC出現(xiàn)的初期,JDBC-ODBC橋顯然是非常有實用意義的,通過JDBC-ODBC橋,開發(fā)人員可以使用JDBC來存取ODBC數(shù)據(jù)源。不足的是,他需要在客戶端安裝ODBC驅(qū)動程序,換句話說,必須安裝Microsoft Windows的某個版本。使用這一類型你需要犧牲JDBC的平臺獨立性。另外,ODBC驅(qū)動程序還需要具有客戶端的控制權(quán)限。
類型 2: JDBC-native driver bridge
JDBC本地驅(qū)動程序橋提供了一種JDBC接口,它建立在本地數(shù)據(jù)庫驅(qū)動程序的頂層,而不需要使用ODBC。 JDBC驅(qū)動程序?qū)?shù)據(jù)庫的API從標準的JDBC調(diào)用轉(zhuǎn)換為本地調(diào)用。使用此類型需要犧牲JDBC的平臺獨立性,還要求在客戶端安裝一些本地代碼。
類型 3: JDBC-network bridge
JDBC網(wǎng)絡(luò)橋驅(qū)動程序不再需要客戶端數(shù)據(jù)庫驅(qū)動程序。它使用網(wǎng)絡(luò)上的中間服務(wù)器來存取數(shù)據(jù)庫。這種應(yīng)用使得以下技術(shù)的實現(xiàn)有了可能,這些技術(shù)包括負載均衡、連接緩沖池和數(shù)據(jù)緩存等。由于第3種類型往往只需要相對更少的下載時間,具有平臺獨立性,而且不需要在客戶端安裝并取得控制權(quán),所以很適合于Internet上的應(yīng)用。
類型 4: Pure Java driver
第4種類型通過使用一個純Java數(shù)據(jù)庫驅(qū)動程序來執(zhí)行數(shù)據(jù)庫的直接訪問。此類型實際上在客戶端實現(xiàn)了2層結(jié)構(gòu)。要在N-層結(jié)構(gòu)中應(yīng)用,一個更好的做法是編寫一個EJB,讓它包含存取代碼并提供一個對客戶端具有數(shù)據(jù)庫獨立性的服務(wù)。
WebLogic服務(wù)器為一些通常的數(shù)據(jù)庫提供了JDBC驅(qū)動程序,包括Oracle, Sybase, Microsoft SQL Server以及Informix。它也帶有一種JDBC驅(qū)動程序用于Cloudscape,這是一種純Java的DBMS,WebLogic服務(wù)器中帶有該數(shù)據(jù)庫的評估版本。
以下讓我們看一個實例。
JDBC實例
在這個例子中我們假定你已經(jīng)在Cloudscape中建立了一個PhoneBook數(shù)據(jù)庫,并且包含一個表,名為 CONTACT_TABLE ,它帶有2個字段:NAME 和 PHONE。 開始的時候先裝載Cloudscape JDBC driver,并請求 driver manager得到一個對PhoneBook Cloudscape數(shù)據(jù)庫的連接。通過這一連接,我們可以構(gòu)造一個 Statement 對象并用它來執(zhí)行一個簡單的SQL查詢。最后,用循環(huán)來遍歷結(jié)果集的所有數(shù)據(jù),并用標準輸出將NAME和PHONE字段的內(nèi)容進行輸出。
創(chuàng)建新表:
create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
根據(jù)已有的表創(chuàng)建新表:
A:create table tab_new like tab_old
B:create table tab_new as select col1,col2… from tab_old definition only
actionMessage怎么能保存到session中哪!!太占用服務(wù)器資源了。防止刷新比較好的辦法是利用token來解決就可以了阿:
就你的情況來看我給你舉個例子
在Action中的add方法中,我們需要將Token值明確的要求保存在頁面中,只需增加一條語句:saveToken(request);,如下所示:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//前面的處理省略
saveToken(request);
//轉(zhuǎn)發(fā)到需要錄入信息的頁面
return mapping.findForward("add");
}
在Action的insert方法中,我們根據(jù)表單中的Token值與服務(wù)器端的Token值比較,如下所示:
//處理信息錄入的action
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
// 表單不是重復提交正常執(zhí)行
} else {
//表單重復提交
saveToken(request);
//給客戶端提示錯誤,當然這里也就是你把ActionMessages保存到request范圍內(nèi),然后forward到錯誤頁面
}
}
執(zhí)行的流程:add(Action)->信息錄入頁面(jsp)->insert(Action)
綜上,其實你選擇重定向到頁面無非就是為了讓request失效保證不能重復提交,而恰恰你的錯誤信息又是保存到了request范圍內(nèi)了,所以呵呵出現(xiàn)問題了,利用token來解決這個問題吧
了,至于token我再lz解釋一下:
Struts的Token機制能夠很好的解決表單重復提交的問題,基本原理是:服務(wù)器端在處理到達的請求之前,會將請求中包含的令牌值與保存在當前用戶會話中的令牌值進行比較,看是否匹配。在處理完該請求后,且在答復發(fā)送給客戶端之前,將會產(chǎn)生一個新的令牌,該令牌除傳給客戶端以外,也會將用戶會話中保存的舊的令牌進行替換。這樣如果用戶回退到剛才的提交頁面并再次提交的話,客戶端傳過來的令牌就和服務(wù)器端的令牌不一致,從而有效地防止了重復提交的發(fā)生。
這時其實也就是兩點,第一:你需要在請求中有這個令牌值,請求中的令牌值如何保存,其實就和我們平時在頁面中保存一些信息是一樣的,通過隱藏字段來保存,保存的形式如: 〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,這個value是TokenProcessor類中的generateToken()獲得的,是根據(jù)當前用戶的session id和當前時間的long值來計算的。第二:在客戶端提交后,我們要根據(jù)判斷在請求中包含的值是否和服務(wù)器的令牌一致,因為服務(wù)器每次提交都會生成新的Token,所以,如果是重復提交,客戶端的Token值和服務(wù)器端的Token值就會不一致。
http://www.oracle.com/technology/sample_code/tech/java/codesnippet/webservices/attachment/index.html
http://www.ibm.com/developerworks/xml/library/x-tippass.html