2008年10月20日
#
http://www.iteye.com/topic/930648
RBAC(Role-Based Access Control,基于角色的訪問控制),就是用戶通過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權限。這樣,就構造成“用戶-角色-權限”的授權模型。在這種模型中,用戶與角色之間,角色與權限之間,一般者是多對多的關系。(如下圖)

角色是什么?可以理解為一定數量的權限的集合,權限的載體。例如:一個論壇系統,“超級管理員”、“版主”都是角色。版主可管理版內的帖子、可管理版內的用戶等,這些是權限。要給某個用戶授予這些權限,不需要直接將權限授予用戶,可將“版主”這個角色賦予該用戶。
當用戶的數量非常大時,要給系統每個用戶逐一授權(授角色),是件非常煩瑣的事情。這時,就需要給用戶分組,每個用戶組內有多個用戶。除了可給用戶授權外,還可以給用戶組授權。這樣一來,用戶擁有的所有權限,就是用戶個人擁有的權限與該用戶所在用戶組擁有的權限之和。(下圖為用戶組、用戶與角色三者的關聯關系)

在應用系統中,權限表現成什么?對功能模塊的操作,對上傳文件的刪改,菜單的訪問,甚至頁面上某個按鈕、某個圖片的可見性控制,都可屬于權限的范疇。有些權限設計,會把功能操作作為一類,而把文件、菜單、頁面元素等作為另一類,這樣構成“用戶-角色-權限-資源”的授權模型。而在做數據表建模時,可把功能操作和資源統一管理,也就是都直接與權限表進行關聯,這樣可能更具便捷性和易擴展性。(見下圖)

請留意權限表中有一列“權限類型”,我們根據它的取值來區分是哪一類權限,如“MENU”表示菜單的訪問權限、“OPERATION”表示功能模塊的操作權限、“FILE”表示文件的修改權限、“ELEMENT”表示頁面元素的可見性控制等。
這樣設計的好處有二。其一,不需要區分哪些是權限操作,哪些是資源,(實際上,有時候也不好區分,如菜單,把它理解為資源呢還是功能模塊權限呢?)。其二,方便擴展,當系統要對新的東西進行權限控制時,我只需要建立一個新的關聯表“權限XX關聯表”,并確定這類權限的權限類型字符串。
這里要注意的是,權限表與權限菜單關聯表、權限菜單關聯表與菜單表都是一對一的關系。(文件、頁面權限點、功能操作等同理)。也就是每添加一個菜單,就得同時往這三個表中各插入一條記錄。這樣,可以不需要權限菜單關聯表,讓權限表與菜單表直接關聯,此時,須在權限表中新增一列用來保存菜單的ID,權限表通過“權限類型”和這個ID來區分是種類型下的哪條記錄。
到這里,RBAC權限模型的擴展模型的完整設計圖如下:

隨著系統的日益龐大,為了方便管理,可引入角色組對角色進行分類管理,跟用戶組不同,角色組不參與授權。例如:某電網系統的權限管理模塊中,角色就是掛在區局下,而區局在這里可當作角色組,它不參于權限分配。另外,為方便上面各主表自身的管理與查找,可采用樹型結構,如菜單樹、功能樹等,當然這些可不需要參于權限分配。
http://developer.51cto.com/art/200907/136668.htmspring 中已經提供了很好的實現,所以這又省去了很多的功夫,接下來看看
iBATIS是如何支持
Clob和blob的。
iBATIS提供了TypeHandler接口,用于處理數據類型,基本的實現類為BaseTypeHandler
在spring 中,提供了AbstractLobTypeHandler作為基礎類,并且提供了相應的模版方法,所有的工作由LobHandler處理。
BlobByteArrayTypeHandler 主要用于處理blob類型數據,使用byte[]來映射相應的Blob
ClobStringTypeHandler 用于處理Clob類型數據,使用字符串來映射Clob
有一點需要注意的是,AbstractLobTypeHandler中實現了事務支持,需要用來釋放相應的資源,所以一定需要在事務環境中進行。
下面是一個簡單的例子:
- public class Food {
- private String content;
-
- private String id;
-
- private byte[] image;
-
- private String name;
- ...
- }
xml如下:說明一下,在resultMap中可以通過typeHandler來指定具體的handler.在inline變量中,可以通過handler來定義相應的typeHandler
- ﹤sqlMap namespace="Food"﹥
-
- ﹤typeAlias alias="Food" type="org.esoft.hdb.bo.Food"/﹥
- ﹤resultMap id="foodResult" class="Food"﹥
- ﹤result property="id" column="C_ID"/﹥
- ﹤result property="name" column="C_NAME"/﹥
- ﹤result property="content" column="C_content"
- typeHandler="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/﹥
- ﹤result property="image" column="C_image"
- typeHandler="org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler"/﹥
- ﹤/resultMap﹥
- ﹤sql id="foodFragment"﹥select C_ID,C_NAME,C_CONTENT,C_IMAGE from T_FOOD﹤/sql﹥
- ﹤select id="getAll" resultMap="foodResult"﹥
- ﹤include refid="foodFragment"/﹥
- ﹤/select﹥
- ﹤select id="selectById" parameterClass="string" resultMap="foodResult"﹥
- ﹤include refid="foodFragment"/﹥ where C_ID=#id#﹤/select﹥
-
- ﹤insert id="insert" parameterClass="Food"﹥ insert into T_FOOD ( C_ID,
- C_NAME,C_CONTENT, C_IMAGE) values ( #id#,
- #name#,#content,handler=org.springframework.orm.ibatis.support.ClobStringTypeHandler#,
- #image,handler=org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler#)
- ﹤/insert﹥
-
- ﹤update id="update" parameterClass="Food"﹥ update T_FOOD set C_NAME = #name#,
- C_CONTENT =
- #content,handler=org.springframework.orm.ibatis.support.ClobStringTypeHandler#,
- C_IMAGE =
- #image,handler=org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler#
- where C_ID = #id# ﹤/update﹥
-
- ﹤delete id="deleteById" parameterClass="string"﹥ delete from T_FOOD where C_ID = #id#
- ﹤/delete﹥
-
- ﹤/sqlMap﹥
-
-
- public interface FoodService {
-
-
- void save(Food food);
- Food get(String id);
- /**
- * @param food
- */
- void update(Food food);
- }
-
- public class FoodServiceImpl implements FoodService {
- private FoodDAO foodDAO;
-
- private DaoCreator creator;
-
- public void setCreator(DaoCreator creator) {
- this.creator = creator;
- }
-
- protected FoodDAO getFoodDAO() {
- if (foodDAO == null) {
- foodDAO = (FoodDAO) creator.createDao(FoodDAO.class, Food.class);
- }
- return foodDAO;
- }
-
- public Food get(String id) {
- return getFoodDAO().get(id);
- }
- public void save(Food food) {
- getFoodDAO().save(food);
- }
- public void update(Food food) {
- getFoodDAO().update(food);
- }
-
- }
-
- spring xml 配置:
-
- 。。。
- ﹤bean id="lobHandler"
- class="org.springframework.jdbc.support.lob.DefaultLobHandler"/﹥
-
- ﹤bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager"﹥
- ﹤property name="dataSource" ref="dataSource"/﹥
- ﹤/bean﹥
-
- ﹤bean id="sqlMapClient"
- class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"﹥
- ﹤property name="dataSource" ref="dataSource"/﹥
- ﹤property name="configLocation"﹥
- ﹤value﹥SqlMapConfig.xml﹤/value﹥
- ﹤/property﹥
- ﹤property name="lobHandler" ref="lobHandler"/﹥
- ﹤/bean﹥
-
- ﹤bean id="daoCreate" class="org.esoft.hdb.ibatis.IbatisDaoCreator"﹥
- ﹤property name="sqlMapClient" ref="sqlMapClient"/﹥
- ﹤/bean﹥
-
- ﹤bean id="foodService" class="org.esoft.hdb.service.FoodServiceImpl"﹥
- ﹤property name="creator" ref="daoCreate"/﹥
- ﹤/bean﹥
-
-
- ﹤aop:config﹥
- ﹤aop:pointcut id="foodServiceMethods"
- expression="execution(* org.esoft.hdb.service.FoodService.*(..))"/﹥
- ﹤aop:advisor advice-ref="txAdvice" pointcut-ref="foodServiceMethods"/﹥
- ﹤/aop:config﹥
- ﹤tx:advice id="txAdvice" transaction-manager="transactionManager"﹥
- ﹤tx:attributes﹥
- ﹤tx:method name="*" propagation="REQUIRED"/﹥
- ﹤/tx:attributes﹥
- ﹤/tx:advice﹥
簡單的測試:
- save :
- Food food = new Food();
- food.setPk("1");
- food.setName("food1");
- BufferedInputStream in = new BufferedInputStream(getClass()
- .getResourceAsStream("/1.gif"));
- byte[] b = FileCopyUtils.copyToByteArray(in);
- food.setImage(b);
- in = new BufferedInputStream(getClass().getResourceAsStream(
- "/hibernate.cfg.xml"));
- b = FileCopyUtils.copyToByteArray(in);
- food.setContent(new String(b));
- foodService.save(food);
- update:
- Food food = foodService.get("1");
- BufferedInputStream in = new BufferedInputStream(getClass()
- .getResourceAsStream("/jdbc.properties"));
- byte[] b = FileCopyUtils.copyToByteArray(in);
- food.setContent(new String(b));
- foodService.update(food);
- food = foodService.get("1");
- assertNotNull(food.getImage());
select sess.sid,
sess.serial#,
lo.oracle_username,
lo.os_user_name,
ao.object_name,
lo.locked_mode
from v$locked_object lo,
dba_objects ao,
v$session sess
where ao.object_id = lo.object_id and lo.session_id = sess.SID;獲得未提交的事物的列表和基礎信息
然后根據 sessionID和serial#號強制關閉事物:
ALTER SYSTEM KILL SESSION '9,108';
--'9,108'為sessionID和serial#號,逗號分開
http://www.javaeye.com/topic/37302
類與類之間的關系對于理解面向對象具有很重要的作用,以前在面試的時候也經常被問到這個問題,在這里我就介紹一下。
類與類之間存在以下關系:
(1)泛化(Generalization)
(2)關聯(Association)
(3)依賴(Dependency)
(4)聚合(Aggregation)
UML圖與應用代碼例子:
1.泛化(Generalization)
[泛化]
表示類與類之間的繼承關系,接口與接口之間的繼承關系,或類對接口的實現關系。一般化的關系是從子類指向父類的,與繼承或實現的方法相反。
[具體表現]
父類 父類實例=new 子類()
[UML圖](圖1.1)


圖1.1 Animal類與Tiger類,Dog類的泛化關系
[代碼表現]
- class Animal{}
- class Tiger extends Animal{}
- public class Test
- {
- public void test()
- {
- Animal a=new Tiger();
- }
- }
2.依賴(Dependency)
[依賴]
對于兩個相對獨立的對象,當一個對象負責構造另一個對象的實例,或者依賴另一個對象的服務時,這兩個對象之間主要體現為依賴關系。
[具體表現]
依賴關系表現在局部變量,方法的參數,以及對靜態方法的調用
[現實例子]
比如說你要去擰螺絲,你是不是要借助(也就是依賴)螺絲刀(Screwdriver)來幫助你完成擰螺絲(screw)的工作
[UML表現](圖1.2)

圖1.2 Person類與Screwdriver類的依賴關系
[代碼表現]
- public class Person{
-
- public void screw(Screwdriver screwdriver){
- screwdriver.screw();
- }
- }
3.關聯(Association)
[關聯]
對于兩個相對獨立的對象,當一個對象的實例與另一個對象的一些特定實例存在固定的對應關系時,這兩個對象之間為關聯關系。
[具體表現]
關聯關系是使用實例變量來實現
[現實例子]
比如客戶和訂單,每個訂單對應特定的客戶,每個客戶對應一些特定的訂單;再例如公司和員工,每個公司對應一些特定的員工,每個員工對應一特定的公司
[UML圖] (圖1.3)

圖1.3 公司和員工的關聯關系
[代碼表現]
- public class Company{
- private Employee employee;
- public Employee getEmployee(){
- return employee;
- }
- public void setEmployee(Employee employee){
- this.employee=employee;
- }
-
- public void run(){
- employee.startWorking();
- }
- }
(4)聚合(Aggregation)
[聚合]
當對象A被加入到對象B中,成為對象B的組成部分時,對象B和對象A之間為聚集關系。聚合是關聯關系的一種,是較強的關聯關系,強調的是整體與部分之間的關系。
[具體表現]
與關聯關系一樣,聚合關系也是通過實例變量來實現這樣關系的。關聯關系和聚合關系來語法上是沒辦法區分的,從語義上才能更好的區分兩者的區別。
[關聯與聚合的區別]
(1)關聯關系所涉及的兩個對象是處在同一個層次上的。比如人和自行車就是一種關聯關系,而不是聚合關系,因為人不是由自行車組成的。
聚合關系涉及的兩個對象處于不平等的層次上,一個代表整體,一個代表部分。比如電腦和它的顯示器、鍵盤、主板以及內存就是聚集關系,因為主板是電腦的組成部分。
(2)對于具有聚集關系(尤其是強聚集關系)的兩個對象,整體對象會制約它的組成對象的生命周期。部分類的對象不能單獨存在,它的生命周期依賴于整體類的對象的生命周期,當整體消失,部分也就隨之消失。比如張三的電腦被偷了,那么電腦的所有組件也不存在了,除非張三事先把一些電腦的組件(比如硬盤和內存)拆了下來。
[UML圖](圖1.4)

圖1.3 電腦和組件的聚合關系
[代碼表現]
- public class Computer{
- private CPU cpu;
- public CPU getCPU(){
- return cpu;
- }
- public void setCPU(CPU cpu){
- this.cpu=cpu;
- }
-
- public void start(){
-
- cpu.run();
- }
- }
在快捷方式屬性-目標里加入 -vm "%JAVA_HOME%/jre/bin/javaw.exe"
Oracle 10g Express Edition是Oracle專門為小型用戶提供的免費版本。Oracle XE十分小巧,安裝簡單,可供第三方軟件開發商部署較小的應用。
不過Oracle XE目前的beta2缺省安裝的字符集是WE8MSWIN1252,不是中文字符集,并且不能通過直接運行 alter database character set ZHS16GBK ; 來修改,因為ZHS16GBK不是缺省字符集的超集。過去流傳很廣的直接修改sys用戶下的PROPS$表的方法,也會給字符集的變更留下很多潛在的問題.
不過在安裝完Oracle XE后,可以在sqlplus(即Oracle XE的run SQL command line)中, 進行如下的操作來修改字符集:
connect system/oracle9i as sysdba
shutdown immediate
startup mount
alter system enable restricted session ;
alter system set JOB_QUEUE_PROCESSES=0;
alter system set AQ_TM_PROCESSES=0;
alter database open ;
alter database character set internal_use ZHS16GBK ;
shutdown immediate
startup
這樣字符集的修改就完成了
摘自紅色黑客聯盟(www.7747.net) 原文:http://www.7747.net/px/200902/34068.html
在數據庫服務器上運行 sqlplus system/password@xe (其中 system 是數據庫用戶無需改變;password 是數據庫密碼應指定為實際密碼;xe 是數據庫實例名稱) ,然后執行:
alter system set session_cached_cursors=200 scope=spfile;
alter system set session_max_open_files=200 scope=spfile;
alter system set sessions=20 scope=spfile;
alter system set license_max_sessions=200 scope=spfile;
alter system set license_sessions_warning=200 scope=spfile;
alter system set processes=200 scope=spfile;
執行后,重啟 Oracle XE 數據庫實例即可。要重啟 Oracle XE 數據庫實例:
1. 如安裝于 Windows 上,先運行 net stop oracleservicexe,再運行 net start oracleservicexe 即可。也可通過“服務”管理控制臺重啟 OracleServiceXE 服務。
2. 如安裝于 Linux 上,先運行 /etc/init.d/oracle-xe start,再運行 /etc/init.d/oracle-xe stop 即可。
此時,可以支持 179 個額外的連接會話。
選擇“運行SQL命令”,進入如下提示符
SQL>
首先連接到服務器
connect 用戶名/密碼
登陸后輸入如下命令:
sql 代碼
1.call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),'/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()',8081));
其中8081是修改后的端口,可以任意。
這樣你就不會與Tomcat的默認端口沖突了,方便開發。
ftp服務占用2100端口,更改命令是:
sql 代碼
1.call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get() , '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()', 2111));
1. 把插件文件直接覆蓋到eclipse目錄里
2. 使用link文件,就是把插件存放到任一的地方(例如/eclipse/MyPuls),然后 在eclipse的文件夾里新建一個links的文件,在里面添加一些后追名為.link的文件(例如emfPlugins.link)結構是這樣的:
/eclipse/
links/
emfPlugins.link
webtools.link
updateManager.link
...
...
link文件的里包含這樣一條 “path=D:\\JavaDev\\plugins\\vssplugin”這個路徑就是插件的存放路徑。
3. 使用eclipse自帶的圖形界面的插件安裝方法:選擇Help > Software Updates > Manager Configuration
在選擇Add > Extension Location 找到你要安裝插件的目錄就可以了。強烈推薦這種方法,優點很多比如可以方便的添加刪除,也不用自己寫link文件!
備注:Eclipse插件的目錄結構
/eclipse-plugins/
eclipse/
.eclipseextension
features/
plugins/
第2、3種方法所指向的目錄都指的是"eclipse"目錄,
如果用第3種方法,在eclipse這個目錄下必須有文件.eclipseextension,如果你下的插件沒有這個文件,那就隨便eclipse安裝目錄下的那個文件靠過去就行了!只有有這么個文件就可以了,內容沒什么用,主要是一些版本信息!例如:
id=org.eclipse.platform name=Eclipse Platformversion=3.3.1
創建XMLHtttRequest對象(針對mozilla,IE8,FF,IE5,IE5.5,IE6,IE7)
//2、創建XMLHttpRequest對象
//這其實是XMLHttpReqest對象使用最復雜的一步
//針對IE和其他類型瀏覽器建立這個對象的不同方式寫不同的代碼
if(window.XMLHttpRequest){
//針對firefox,mozillaz,opera,IE7,IE8
xmlhttp = new XMLHttpRequest();
//用于修復某些Mozillaz瀏覽器bug
if(xmlhttp.overrideMimeType)
{
xmlhttp.overrideMimeType("text/xml");
}
}
else if(window.ActiveXObject){
//針對IE6,IE5.5,IE5
//兩個都可以創建XMLHttpRequest對象,保存在js數組中
var activeName=["MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
//var activeName= ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.5.0', //'MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0', //'MSXML2.XMLHTTP','Microsoft.XMLHTTP'];
for(var i =0;i<activeName.length;i++)
{//取出一個控件名來創建XMLHttpRequest對象,創建成功就終止循環,如果創建失敗可以繼續創建
//可以拋出異常,繼續創建
try{
xmlhttp= new ActiveXObject(activeName[i]);
break;
}catch(e){
}
}
}
//確認XMLHttpRequest對象已經創建成功
if(!xmlhttp)
{
alert("XmlHttpRequest創建失敗");
return;
}
//3、注冊回調函數,函數名后面不要加括號
//如果加了括號,就變成了調用函數,會把函數的返回值發揮給xmlhttp,沒有達到我們的目的
xmlhttp.onreadystatechange=callback;
//4、設置連接信息
//第一個參數設置http請求方式,主要是get和post兩種方式
//第二個參數是uri地址
//第三個參數表示異步交互還是同步交互方式,true表示異步,false表示同步
xmlhttp.open("GET","/JQuery/servlet/AjaxServlet?name="+username,true);
//5、發送數據開始和服務器端交互
//同步方式下,send這句話會在服務器端的數據回來后,才執行完
//異步方式下,send會立即執行完
xmlhttp.send(null);
}
//5、寫回調函數
//回調函數
function callback(){
//接收相應的相應數據
//判斷交互狀態已經完成
if(xmlhttp.readyState ==4)
{
//判斷http的交互狀態
if(xmlhttp.status == 200)
{
//獲取服務器端返回的數據
//獲取服務器端純文本數據
var responseText = xmlhttp.responseText;
//將數據顯示在頁面上
//通過dom獲取div元素節點
var divNode =document.getElementById("result");
//設置元素節點的html內容
divNode.innerHTML=responseText;
}
}
1,<meta name="Robots" contect="all|none|index|noindex|follow|nofollow"> 默認是all
其中的屬性說明如下:
設定為all:文件將被檢索,且頁面上的鏈接可以被查詢;
設定為none:文件將不被檢索,且頁面上的鏈接不可以被查詢;
設定為index:文件將被檢索;
設定為follow:頁面上的鏈接可以被查詢;
設定為noindex:文件將不被檢索,但頁面上的鏈接可以被查詢;
設定為nofollow:文件將不被檢索,頁面上的鏈接可以被查詢。
2,revisit-after (重訪)
<META name="revisit-after" CONTENT="7 days" >
通知搜索引擎多少天訪問一次
其他的:
<META NAME="GENERATOR" CONTENT="Macromedia Dreamweaver MX">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<Meta http-equiv="Content-Language" Content="zh-CN">
<Meta http-equiv="Refresh" Content="5; Url=http://hi.baidu.com/pihi">
<Meta http-equiv="Expires" Content="Wed, 26 Feb 1997 08:21:57 GMT">
<meta http-equiv="cache-control" content="no-cache">
<META name="keywords" content="關鍵字">
<meta name="description" content="描述">
<meta name="author" content="作者">
<meta name="build" content="日期">
<meta name="coprright" content="版權">
<meta name="reply-to" content="email">
<meta name="robots" content="all">
<meta http-equiv="Page-Enter" content="RevealTrans (Duration=3, Transition=23)">
<meta http-equiv="Page-Exit" content="RevealTrans (Duration=3, Transition=23)">
<link rel="shortcut icon" href="favicon.ico">
------------------------------------------------------------------------------------------------------------
meta標簽分兩大部分:HTTP標題信息(HTTP-EQUIV)和頁面描述信息(NAME)。
1、Content-Type和Content-Language (顯示字符集的設定)
說明:設定頁面使用的字符集,用以說明主頁制作所使用的文字已經語言,瀏覽器會根據此來調用相應的字符集顯示page內容。
注意: 該meta標簽定義了HTML頁面所使用的字符集為GB2132,就是國標漢字碼。如果將其中的“charset=GB2312”替換成“BIG5”,則該頁面所用的字符集就是繁體中文Big5碼。當你瀏覽一些國外的站點時,IE瀏覽器會提示你要正確顯示該頁面需要下載xx語支持。這個功能就是通過讀取HTML頁面Meta標簽的Content-Type屬性而得知需要使用哪種字符集顯示該頁面的。如果系統里沒有裝相應的字符集,則IE就提示下載。其他的語言也對應不同的charset,比如日文的字符集是“iso-2022-jp ”,韓文的是“ks_c_5601”。
Charset選項:ISO-8859-1(英文)、BIG5、UTF-8、SHIFT-Jis、Euc、Koi8-2、us-ascii, x-mac-roman, iso-8859-2, x-mac-ce, iso-2022-jp, x-sjis, x-euc-jp,euc-kr, iso-2022-kr, gb2312, gb_2312-80, x-euc-tw, x-cns11643-1,x-cns11643-2等字符集;Content-Language的Content還可以是:EN、FR等語言代碼。
2、Refresh (刷新)
3、Expires (期限)
說明:指定網頁在緩存中的過期時間,一旦網頁過期,必須到服務器上重新調閱。
注意:必須使用GMT的時間格式,或直接設為0(數字表示多少時間后過期)。
4、Pragma (cach模式)
說明:禁止瀏覽器從本地機的緩存中調閱頁面內容。
注意:網頁不保存在緩存中,每次訪問都刷新頁面。這樣設定,訪問者將無法脫機瀏覽。
5、Set-Cookie (cookie設定)
說明:瀏覽器訪問某個頁面時會將它存在緩存中,下次再次訪問時就可從緩存中讀取,以提高速度。當你希望訪問者每次都刷新你廣告的圖標,或每次都刷新你的計數器,就要禁用緩存了。通常HTML文件沒有必要禁用緩存,對于ASP等頁面,就可以使用禁用緩存,因為每次看到的頁面都是在服務器動態生成的,緩存就失去意義。如果網頁過期,那么存盤的cookie將被刪除。
用法:<Meta http-equiv="Set-Cookie" Content="cookievalue=xxx; expires=Wednesday,
21-Oct-98 16:14:21 GMT; path=/">
注意:必須使用GMT的時間格式。
6、Window-target (顯示窗口的設定)
說明:強制頁面在當前窗口以獨立頁面顯示。
用法:<Meta http-equiv="Widow-target" Content="_top">
注意:這個屬性是用來防止別人在框架里調用你的頁面。Content選項:_blank、_top、_self、_parent。
7、Pics-label (網頁RSAC等級評定)
說明:在IE的Internet選項中有一項內容設置,可以防止瀏覽一些受限制的網站,而網站的限制級
別就是通過該參數來設置的。
用法:<META http-equiv="Pics-label" Contect=
"(PICS-1.1'http://www.rsac.org/ratingsv01.html'
I gen comment 'RSACi North America Sever' by 'inet@microsoft.com'
for 'http://www.microsoft.com' on '1997.06.30T14:21-0500' r(n0 s0 v0 l0))">
注意:不要將級別設置的太高。RSAC的評估系統提供了一種用來評價Web站點內容的標準。用戶可以設置Microsoft Internet Explorer(IE3.0以上)來排除包含有色情和暴力內容的站點。上面這個例子中的HTML取自Microsoft的主頁。代碼中的(n 0 s 0 v 0 l 0)表示該站點不包含不健康內容。級別的評定是由RSAC,即美國娛樂委員會的評級機構評定的,如果你想進一步了解RSAC評估系統的等級內容,或者你需要評價自己的網站,可以訪問RSAC的站點:http://www.rsac.org/。
8、Page-Enter、Page-Exit (進入與退出)
說明:這個是頁面被載入和調出時的一些特效。
用法:<Meta http-equiv="Page-Enter" Content="blendTrans(Duration=0.5)">
<Meta http-equiv="Page-Exit" Content="blendTrans(Duration=0.5)">
注意:blendTrans是動態濾鏡的一種,產生漸隱效果。另一種動態濾鏡RevealTrans也可以用于頁面進入與退出效果:
<Meta http-equiv="Page-Enter" Content="revealTrans(duration=x, transition=y)">
<Meta http-equiv="Page-Exit" Content="revealTrans(duration=x, transition=y)">
Duration 表示濾鏡特效的持續時間(單位:秒)
Transition 濾鏡類型。表示使用哪種特效,取值為0-23。
0 矩形縮小
1 矩形擴大
2 圓形縮小
3 圓形擴大
4 下到上刷新
5 上到下刷新
6 左到右刷新
7 右到左刷新
8 豎百葉窗
9 橫百葉窗
10 錯位橫百葉窗
11 錯位豎百葉窗
12 點擴散
13 左右到中間刷新
14 中間到左右刷新
15 中間到上下
16 上下到中間
17 右下到左上
18 右上到左下
19 左上到右下
20 左下到右上
21 橫條
22 豎條
23 以上22種隨機選擇一種
9、MSThemeCompatible (XP主題)
說明:是否在IE中關閉 xp 的主題
用法:<Meta http-equiv="MSThemeCompatible" Content="Yes">
注意:關閉 xp 的藍色立體按鈕系統顯示樣式,從而和win2k 很象。
10、IE6 (頁面生成器)
說明:頁面生成器generator,是ie6
用法:<Meta http-equiv="IE6" Content="Generator">
注意:用什么東西做的,類似商品出廠廠商。
11、Content-Script-Type (腳本相關)
說明:這是近來W3C的規范,指明頁面中腳本的類型。
用法:<Meta http-equiv="Content-Script-Type" Content="text/javascript">
★NAME變量
name是描述網頁的,對應于Content(網頁內容),以便于搜索引擎機器人查找、分類(目前幾乎所有的搜索引擎都使用網上機器人自動查找meta值來給網頁分類)。
name的value值(name="")指定所提供信息的類型。有些值是已經定義好的。例如description(說明)、keyword(關鍵字)、refresh(刷新)等。還可以指定其他任意值,如:creationdate(創建日期) 、
document ID(文檔編號)和level(等級)等。
name的content指定實際內容。如:如果指定level(等級)為value(值),則Content可能是beginner(初級)、intermediate(中級)、advanced(高級)。
1、Keywords (關鍵字)
說明:為搜索引擎提供的關鍵字列表
用法:<Meta name="Keywords" Content="關鍵詞1,關鍵詞2,關鍵詞3,關鍵詞4,……">
注意:各關鍵詞間用英文逗號“,”隔開。META的通常用處是指定搜索引擎用來提高搜索質量的關鍵詞。當數個META元素提供文檔語言從屬信息時,搜索引擎會使用lang特性來過濾并通過用戶的語言優先參照來顯示搜索結果。例如:
<Meta name="Kyewords" Lang="EN" Content="vacation,greece,sunshine">
<Meta name="Kyewords" Lang="FR" Content="vacances,grè:ce,soleil">
2、Description (簡介)
說明:Description用來告訴搜索引擎你的網站主要內容。
用法:<Meta name="Description" Content="你網頁的簡述">
注意:
3、Robots (機器人向導)
說明:Robots用來告訴搜索機器人哪些頁面需要索引,哪些頁面不需要索引。Content的參數有all、none、index、noindex、follow、nofollow。默認是all。
用法:<Meta name="Robots" Content="All|None|Index|Noindex|Follow|Nofollow">
注意:許多搜索引擎都通過放出robot/spider搜索來登錄網站,這些robot/spider就要用到meta元素的一些特性來決定怎樣登錄。
all:文件將被檢索,且頁面上的鏈接可以被查詢;
none:文件將不被檢索,且頁面上的鏈接不可以被查詢;(和 "noindex, no follow" 起相同作用)
index:文件將被檢索;(讓robot/spider登錄)
follow:頁面上的鏈接可以被查詢;
noindex:文件將不被檢索,但頁面上的鏈接可以被查詢;(不讓robot/spider登錄)
nofollow:文件將不被檢索,頁面上的鏈接可以被查詢。(不讓robot/spider順著此頁的連接往下探找)
4、Author (作者)
說明:標注網頁的作者或制作組
用法:<Meta name="Author" Content="張三,abc@sina.com">
注意:Content可以是:你或你的制作組的名字,或Email
5、Copyright (版權)
說明:標注版權
用法:<Meta name="Copyright" Content="本頁版權歸Zerospace所有。All Rights Reserved">
注意:
6、Generator (編輯器)
說明:編輯器的說明
用法:<Meta name="Generator" Content="PCDATA|FrontPage|">
注意:Content="你所用編輯器"
7、revisit-after (重訪)
說明:
用法:<META name="revisit-after" CONTENT="7 days" >
PostgreSQL支持管理員直接手動安裝數據庫,給用戶提供了更大的方便。
1. 在PostgreSQL官方網站上下載免安裝二進制的包,名字類似于postgresql-*.*.*.*-binaries-no-installer.tar.gz之類的。
下載到本地,解壓到某路徑PATH下。
2. 在PATH目錄中創建data文件夾,用于存放數據。
3. 開始-->運行-->cmd 進入命令行。并cd到PATH\bin目錄下執行下面的命令用來初始化數據庫:
PATH\bin> initdb.exe -D PATH\data -E UTF8 --locale=C
4. 將pgsql注冊為windows服務,便于操作和控制:
PATH\bin> pg_ctl.exe register -D PATH\data -N pgsql
其中-N參數用來設置pgsql作為windows服務的名稱。
5. 啟動和關閉數據庫,在命令行下:
> net start pgsql (開啟數據庫)
> net stop pgsql (關閉數據庫)
注:為避免以后可能發生的亞州大字符集的亂碼問題,統一使用UTF8編碼。
需要一個非管理員帳號來運行PostgreSQL?
當一個駭客通過軟件的缺陷獲得了侵入一臺計算機的入口時,她獲得的是這個程序運行所用用戶帳號的對應權限。由于我們無法預知PostgreSQL中是否還存在這樣的bug,所以我們強制使用一個非管理員的服務帳號來最小化潛在的駭客利用此類漏洞對系統進行破壞的風險。這樣的設置已是Unix界的慣例做法,同時在Windows世界中,Microsoft以及其他供應商也開始采用這樣的做法來改進他們系統的安全性。補充: 自PostgreSQL 8.2發行后,從管理帳號啟動變得可行。PostgreSQL 8.2及后續版本會在啟動后不可撤銷地放棄管理權限,從而保證了當極端不可能事件,當PostgreSQL受到入侵時,系統的安全性。
<script type="text/javascript">
//** iframe自動適應頁面 **//
//輸入你希望根據頁面高度自動調整高度的iframe的名稱的列表
//用逗號把每個iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一個窗體,則不用逗號。
//定義iframe的ID
var iframeids=["test"]
//如果用戶的瀏覽器不支持iframe是否將iframe隱藏 yes 表示隱藏,no表示不隱藏
var iframehide="yes"
function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自動調整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids[i]);
if (dyniframe[i] && !window.opera)
{
dyniframe[i].style.display="block"
if (dyniframe[i].contentDocument && dyniframe[i].contentDocument.body.offsetHeight) //如果用戶的瀏覽器是NetScape
dyniframe[i].height = dyniframe[i].contentDocument.body.offsetHeight;
else if (dyniframe[i].Document && dyniframe[i].Document.body.scrollHeight) //如果用戶的瀏覽器是IE
dyniframe[i].height = dyniframe[i].Document.body.scrollHeight;
}
}
//根據設定的參數來處理不支持iframe的瀏覽器的顯示問題
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
}
}
}
if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>
使用的時候只要貼在<head></head>里面就可以
歡迎各位大俠加入IT精英俱樂部(QQ群:11672321)
一、使用mod_jk.so方式
1.無集群方式
1)下載、安裝Apache2.2.11,Tomcat6.0.20略
2)下載mod_jk-1.2.28-httpd-2.2.3.so改名為mod_jk.so放到%APACHE_HOME%\modules下(不改名會出錯,不知道為什么)
3)打開%APACHE_HOME%\conf\httpd.conf,找到最末一個Include節點,加入mod-jk_nocluster.conf
4)在%APACHE_HOME%\conf\新建mod-jk_nocluster.conf,加入以下內容:
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers_nocluster.properties
JkLogFile logs/mod_jk_nocluster.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /* ajp13
#關掉主機Lookup,如果為on,很影響性能,可以有10多秒鐘的延遲。
HostnameLookups Off
5)在%APACHE_HOME%\conf\新建workers_nocluster.properties,加入以下內容:
worker.list=ajp13
worker.maintain=60
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1
6)啟動Apache,tomcat,在地址欄輸入http://localhost看到tomcat畫面成功了
2.使用集群(以兩個tomcat為例)
1)、2)同上
3)打開%APACHE_HOME%\conf\httpd.conf,找到最末一個Include節點,更改mod-jk_nocluster.conf為mod-jk_cluster.conf
4)在%APACHE_HOME%\conf\新建mod-jk_cluster.conf,加入以下內容:
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers_cluster.properties
JkLogFile logs/mod_jk_cluster.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /* controller
HostnameLookups Off
5)在%APACHE_HOME%\conf\新建workers_cluster.properties,加入以下內容:
worker.list = controller,tomcat1,tomcat2 #server 列表
#========tomcat1========
worker.tomcat1.port=18109 #ajp13 端口號,在tomcat下server.xml配置,默認8009
worker.tomcat1.host=localhost #tomcat的主機地址,如不為本機,請填寫ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor = 1 #server的加權比重,值越高,分得的請求越多
#worker.tomcat1.redirect=tomcat2 #是在cluster環境之下,當tomcat1掛點或無回應,jk會將request導向這個指令指定的其他worker作處理。
#========tomcat2========
worker.tomcat2.port=18209 #ajp13 端口號,在tomcat下server.xml配置,默認8009
worker.tomcat2.host=localhost #tomcat的主機地址,如不為本機,請填寫ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor = 1 #server的加權比重,值越高,分得的請求越多
#worker.tomcat2.activation=disabled #
#========controller,負載均衡控制器========
worker.controller.type=lb
worker.controller.balanced_workers=tomcat1,tomcat2 #指定分擔請求的tomcat
worker.controller.sticky_session=1
6)修改tomcat1配置文件server.xml,tomcat2配置修改地方同tomcat1,僅需注意相關端口號,在同一臺服務器上時不能重復
以下列出需修改節點地方:
#默認為8005
<Server port="8105" shutdown="SHUTDOWN">
#默認8080,此處可根據需求修改線程并發等
<Connector port="8180" ...>
#默認8009,
<Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />
#name可為Standalone
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="6">
<Manager
className="org.apache.catalina.ha.session.BackupManager"
expireSessionsOnShutdown="false" notifyListenersOnReplication="true"
mapSendOptions="6" />
<!--
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
-->
<Channel
className="org.apache.catalina.tribes.group.GroupChannel">
<Membership
className="org.apache.catalina.tribes.membership.McastService"
mcastBindAddress="127.0.0.1" #安裝了VPN、svn等,會導致綁定失敗需加上此句
address="228.0.0.4" port="45564"
frequency="500" dropTime="3000" />
<Receiver
className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto" port="4001" selectorTimeout="100" maxThreads="6" />
<Sender
className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport
className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
</Sender>
<Interceptor
className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
<Interceptor
className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" />
<Interceptor
className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor" />
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;" />
<ClusterListener
className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>
在<Host>節點加入
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/xxx/"
deployDir="/tmp/war-deploy/xxx/"
watchDir="/tmp/war-listen/xxx/"
watchEnabled="false"/>
7)將Web應用打成war包放到每一個webapps下,確保web.xml中加了
<display-name>xxx<display-name>
<distributable />
或者直接放到tomcat的web.xml中
至此mod-jk.so方式全配好了,啟動服務就OK了!
待續Apache新增的配置方式。。。。。。
1.安裝Apache-httpd-2.2.11
2.下載svn-win32-1.6.3.zip for Apache-httpd-2.2.11,解壓到某個目錄
3.添加環境變量%SVN_HOME%,修改%PATH%,增加%SVN_HOME%\bin
4.新建空目錄x:\Respository\test\
5.進入命令行:svnadmin create --fs-type fsfs x:\Respository\test\
6.進入x:\Respository\test\conf\svnserve.conf
去掉注釋
auth-access = write
password-db = passwd
在本目錄passwd文件中新建用戶 xxx = xxx
7.新增服務
sc create svnservice binPath= "%SVN_HOME%\bin\svnserve.exe --service -r x:\Respository" displayname= "SVNService" depend= Tcpip start= auto
刪除服務運行"sc delete svnservice"
8.復制%SVN_HOME%\bin中的文件mod_dav_svn.so和mod_authz_svn.so到%APACHE_HOME%\modules目錄,
復制%SVN_HOME%\bin\libdb44.dll、libeay32.dll、 ssleay32.dll到%APACHE_HOME%\bin
9.%APACHE_HOME%\conf\httd.conf做如下修改:
去掉以下行的注釋(將開頭的#刪除):
#LoadModule dav_fs_module modules/mod_dav_fs.so
#LoadModule dav_module modules/mod_dav.so
在LoadModule節的最后添加以下兩行:
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
在文件末尾加入:
<Location /svn>
DAV svn
SVNParentPath x:\Respository
AuthType Basic
AuthName "Subversion repositories"
AuthUserFile x:\Respository\conf\passwd
#AuthzSVNAccessFile x:\Respository\conf\authz
Require valid-user
</Location>
可是現在啟動不了Apache ,那位大俠能幫幫我,網上找了好多都試過了還是不行
<script language="javascript">
var oPopup=null; //彈出菜單
var popWidth=110; //彈出菜單的寬度
var popHeight=140; //彈出菜單的高度
var curRow=null; //記錄彈出菜單最后指向的行
function init(){
oPopup = window.createPopup();
var oPopBody = oPopup.document.body;
//設置菜單樣式
oPopBody.style.backgroundColor = "scrollbar";
oPopBody.style.border = "2px solid";
oPopBody.style.borderColor = "buttonhighlight buttonshadow buttonshadow buttonhighlight"
var strHTML=""
strHTML+='<table oncontextmenu="return false;" onselectstart="return false;" id="tbMenu" ';
strHTML+=' style="cursor:default; width:100%; height:100%;font-size:12px;" border=0 cellpadding=0 cellspacing=2>';
//在這里擴展菜單的選項start
strHTML+='<tr operation="edit"><td> 編輯</td></tr>';
strHTML+='<tr operation="refresh"><td> 刷新</td></tr>';
strHTML+='<tr operation="addrowup"><td> 添加新行(上)</td></tr>';
strHTML+='<tr operation="addrowdown"><td> 添加新行(下)</td></tr>';
strHTML+='<tr operation="delrow"><td> 刪除該行</td></tr>';
strHTML+='<tr operation="moveup"><td> 向上移動一行</td></tr>';
strHTML+='<tr operation="movedown"><td> 向下移動一行</td></tr>';
//在這里擴展菜單的選項end
strHTML+='</table>';
oPopBody.innerHTML=strHTML;
var tb = oPopup.document.getElementById("tbMenu");
var rs=tb.rows;
for(var i=0;i<rs.length;i++){
var row=rs[i];
addEvent(row);
}
}
function showMenu(){
var e=window.event;
var src=e.srcElement;
oPopup.show(window.event.clientX, window.event.clientY, popWidth, popHeight, document.body);
window.event.returnValue=false;
}
function addEvent(row){
row.attachEvent("onmouseover",function(){selRow(row)});
row.attachEvent("onclick",function(){onEvent(row)});
}
function selRow(src){
if(curRow!=null){ curRow.style.backgroundColor="scrollbar"; curRow.style.color="black";}
curRow=src; curRow.style.backgroundColor="midnightblue"; curRow.style.color="white";
}
function onEvent(src){
oPopup.hide();
switch(src.operation){
//在這里為菜單項的點擊事件添加處理方法
//本示例的方法只供參考,沒有實現
case "edit": example(src.operation); break;
case "refresh": example(src.operation); break;
case "addrowup": example(src.operation); break;
case "addrowdown": example(src.operation); break;
case "delrow": example(src.operation); break;
case "moveup": example(src.operation); break;
case "movedown": example(src.operation); break;
default: return;
}
src.style.backgroundColor="scrollbar";
src.style.color="black";
curRow=null;
}
function example(str){
alert("您選擇了"+str+"操作!");
}
</script>
<body onload="init();showMenu()">
</body>
我們在數據庫插入一條數據的時候,經常是需要返回插入這條數據的主鍵。但是數據庫供應商之間生成主鍵的方式都不一樣。
有些是預先生成(pre-generate)主鍵的,如Oracle和PostgreSQL;有些是事后生成(post-generate)主鍵的,如MySQL和SQL Server。但是不管是哪種方式,我們都可以用iBATIS的節點來獲取語句所產生的主鍵。
例子如下:
xml 代碼
<insert id="insertProduct-ORACLE" parameterClass="product">
<selectKey resultClass="int" type="pre" keyProperty="Id" >
SELECT YOURPKSEQUENCE.NEXTVAL AS VALUE FROM DUAL
<selectKey>
insert into PRODUCT (PRD_ID,PRD_DESCRIPTION) values (#id#,#description#)
<insert>
<insert id="insertProduct-MS-SQL" parameterClass="product">
insert into PRODUCT (PRD_DESCRIPTION) values (#description#)
<selectKey resultClass="int" type="post" keyProperty="id" >
select @@IDENTITY as value
<selectKey>
<insert>
<insert id="insertProduct-MYSQL" parameterClass="product">
insert into PRODUCT (PRD_DESCRIPTION) values (#description#)
<selectKey resultClass="int" type="post" keyProperty="id" >
select LAST_INSERT_ID() as value
<selectKey>
<insert>
alter database datafile 'D:\DevTools\Oracle\oradata\ora92\USERS01.DBF' offline drop;
alter database open;
在Oracle9i中執行下面的SQL重建exu81rls視圖即可。
CREATE OR REPLACE view exu81rls
(objown,objnam,policy,polown,polsch,polfun,stmts,chkopt,enabled,spolicy)
AS select u.name, o.name, r.pname, r.pfschma, r.ppname, r.pfname,
decode(bitand(r.stmt_type,1), 0,'', 'SELECT,')
|| decode(bitand(r.stmt_type,2), 0,'', 'INSERT,')
|| decode(bitand(r.stmt_type,4), 0,'', 'UPDATE,')
|| decode(bitand(r.stmt_type,8), 0,'', 'DELETE,'),
r.check_opt, r.enable_flag,
DECODE(BITAND(r.stmt_type, 16), 0, 0, 1)
from user$ u, obj$ o, rls$ r
where u.user# = o.owner#
and r.obj# = o.obj#
and (uid = 0 or
uid = o.owner# or
exists ( select * from session_roles where role='SELECT_CATALOG_ROLE')
)
/
grant select on sys.exu81rls to public;
/
-- Change the HTTP/WEBDAV port from 8080 to 8081
SQL> call dbms_xdb.cfg_update(updateXML( dbms_xdb.cfg_get() ,
'/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()'
8081))
/
-- Change the FTP port from 2100 to 2111
SQL> call dbms_xdb.cfg_update(updateXML( dbms_xdb.cfg_get() ,
'/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()' , 2111))
SQL> COMMIT;
SQL> EXEC dbms_xdb.cfg_refresh
@echo off
if '%1=='## goto ENVSET
rem 要啟動的類名
SET CLSNAME=com.main
rem 設定CLSPATH
SET CLSPATH=.
FOR %%c IN (.\lib\*.jar) DO CALL %0 ## %%c
rem 運行
GOTO RUN
:RUN
java -cp %CLSPATH% %CLSNAME%
goto END
:ENVSET
set CLSPATH=%CLSPATH%;%2
goto END
:END
在query的時候加上binary,select * from usertest where username like binary '%夏%'
一、同步問題提出
線程的同步是為了防止多個線程訪問一個數據對象時,對數據造成的破壞。
例如:兩個線程ThreadA、ThreadB都操作同一個對象Foo對象,并修改Foo對象上的數據。
public class Foo {
private int x = 100;
public int getX() {
return x;
}
public int fix(int y) {
x = x - y;
return x;
}
}
public class MyRunnable implements Runnable {
private Foo foo = new Foo();
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread ta = new Thread(r, "Thread-A");
Thread tb = new Thread(r, "Thread-B");
ta.start();
tb.start();
}
public void run() {
for (int i = 0; i < 3; i++) {
this.fix(30);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 當前foo對象的x值= " + foo.getX());
}
}
public int fix(int y) {
return foo.fix(y);
}
}
運行結果:
Thread-A : 當前foo對象的x值= 40
Thread-B : 當前foo對象的x值= 40
Thread-B : 當前foo對象的x值= -20
Thread-A : 當前foo對象的x值= -50
Thread-A : 當前foo對象的x值= -80
Thread-B : 當前foo對象的x值= -80
Process finished with exit code 0
從結果發現,這樣的輸出值明顯是不合理的。原因是兩個線程不加控制的訪問Foo對象并修改其數據所致。
如果要保持結果的合理性,只需要達到一個目的,就是將對Foo的訪問加以限制,每次只能有一個線程在訪問。這樣就能保證Foo對象中數據的合理性了。
在具體的Java代碼中需要完成一下兩個操作:
把競爭訪問的資源類Foo變量x標識為private;
同步哪些修改變量的代碼,使用synchronized關鍵字同步方法或代碼。
二、同步和鎖定
1、鎖的原理
Java中每個對象都有一個內置鎖
當程序運行到非靜態的synchronized同步方法上時,自動獲得與正在執行代碼類的當前實例(this實例)有關的鎖。獲得一個對象的鎖也稱為獲取鎖、鎖定對象、在對象上鎖定或在對象上同步。
當程序運行到synchronized同步方法或代碼塊時才該對象鎖才起作用。
一個對象只有一個鎖。所以,如果一個線程獲得該鎖,就沒有其他線程可以獲得鎖,直到第一個線程釋放(或返回)鎖。這也意味著任何其他線程都不能進入該對象上的synchronized方法或代碼塊,直到該鎖被釋放。
釋放鎖是指持鎖線程退出了synchronized同步方法或代碼塊。
關于鎖和同步,有一下幾個要點:
1)、只能同步方法,而不能同步變量和類;
2)、每個對象只有一個鎖;當提到同步時,應該清楚在什么上同步?也就是說,在哪個對象上同步?
3)、不必同步類中所有的方法,類可以同時擁有同步和非同步方法。
4)、如果兩個線程要執行一個類中的synchronized方法,并且兩個線程使用相同的實例來調用方法,那么一次只能有一個線程能夠執行方法,另一個需要等待,直到鎖被釋放。也就是說:如果一個線程在對象上獲得一個鎖,就沒有任何其他線程可以進入(該對象的)類中的任何一個同步方法。
5)、如果線程擁有同步和非同步方法,則非同步方法可以被多個線程自由訪問而不受鎖的限制。
6)、線程睡眠時,它所持的任何鎖都不會釋放。
7)、線程可以獲得多個鎖。比如,在一個對象的同步方法里面調用另外一個對象的同步方法,則獲取了兩個對象的同步鎖。
8)、同步損害并發性,應該盡可能縮小同步范圍。同步不但可以同步整個方法,還可以同步方法中一部分代碼塊。
9)、在使用同步代碼塊時候,應該指定在哪個對象上同步,也就是說要獲取哪個對象的鎖。例如:
public int fix(int y) {
synchronized (this) {
x = x - y;
}
return x;
}
當然,同步方法也可以改寫為非同步方法,但功能完全一樣的,例如:
public synchronized int getX() {
return x++;
}
與
public int getX() {
synchronized (this) {
return x;
}
}
效果是完全一樣的。
三、靜態方法同步
要同步靜態方法,需要一個用于整個類對象的鎖,這個對象是就是這個類(XXX.class)。
例如:
public static synchronized int setName(String name){
Xxx.name = name;
}
等價于
public static int setName(String name){
synchronized(Xxx.class){
Xxx.name = name;
}
}
四、如果線程不能不能獲得鎖會怎么樣
如果線程試圖進入同步方法,而其鎖已經被占用,則線程在該對象上被阻塞。實質上,線程進入該對象的的一種池中,必須在哪里等待,直到其鎖被釋放,該線程再次變為可運行或運行為止。
當考慮阻塞時,一定要注意哪個對象正被用于鎖定:
1、調用同一個對象中非靜態同步方法的線程將彼此阻塞。如果是不同對象,則每個線程有自己的對象的鎖,線程間彼此互不干預。
2、調用同一個類中的靜態同步方法的線程將彼此阻塞,它們都是鎖定在相同的Class對象上。
3、靜態同步方法和非靜態同步方法將永遠不會彼此阻塞,因為靜態方法鎖定在Class對象上,非靜態方法鎖定在該類的對象上。
4、對于同步代碼塊,要看清楚什么對象已經用于鎖定(synchronized后面括號的內容)。在同一個對象上進行同步的線程將彼此阻塞,在不同對象上鎖定的線程將永遠不會彼此阻塞。
五、何時需要同步
在多個線程同時訪問互斥(可交換)數據時,應該同步以保護數據,確保兩個線程不會同時修改更改它。
對于非靜態字段中可更改的數據,通常使用非靜態方法訪問。
對于靜態字段中可更改的數據,通常使用靜態方法訪問。
如果需要在非靜態方法中使用靜態字段,或者在靜態字段中調用非靜態方法,問題將變得非常復雜。已經超出SJCP考試范圍了。
六、線程安全類
當一個類已經很好的同步以保護它的數據時,這個類就稱為“線程安全的”。
即使是線程安全類,也應該特別小心,因為操作的線程是間仍然不一定安全。
舉個形象的例子,比如一個集合是線程安全的,有兩個線程在操作同一個集合對象,當第一個線程查詢集合非空后,刪除集合中所有元素的時候。第二個線程也來執行與第一個線程相同的操作,也許在第一個線程查詢后,第二個線程也查詢出集合非空,但是當第一個執行清除后,第二個再執行刪除顯然是不對的,因為此時集合已經為空了。
看個代碼:
public class NameList {
private List nameList = Collections.synchronizedList(new LinkedList());
public void add(String name) {
nameList.add(name);
}
public String removeFirst() {
if (nameList.size() > 0) {
return (String) nameList.remove(0);
} else {
return null;
}
}
}
public class Test {
public static void main(String[] args) {
final NameList nl = new NameList();
nl.add("aaa");
class NameDropper extends Thread{
public void run(){
String name = nl.removeFirst();
System.out.println(name);
}
}
Thread t1 = new NameDropper();
Thread t2 = new NameDropper();
t1.start();
t2.start();
}
}
雖然集合對象
private List nameList = Collections.synchronizedList(new LinkedList());
是同步的,但是程序還不是線程安全的。
出現這種事件的原因是,上例中一個線程操作列表過程中無法阻止另外一個線程對列表的其他操作。
解決上面問題的辦法是,在操作集合對象的NameList上面做一個同步。改寫后的代碼如下:
public class NameList {
private List nameList = Collections.synchronizedList(new LinkedList());
public synchronized void add(String name) {
nameList.add(name);
}
public synchronized String removeFirst() {
if (nameList.size() > 0) {
return (String) nameList.remove(0);
} else {
return null;
}
}
}
這樣,當一個線程訪問其中一個同步方法時,其他線程只有等待。
七、線程死鎖
死鎖對Java程序來說,是很復雜的,也很難發現問題。當兩個線程被阻塞,每個線程在等待另一個線程時就發生死鎖。
還是看一個比較直觀的死鎖例子:
public class DeadlockRisk {
private static class Resource {
public int value;
}
private Resource resourceA = new Resource();
private Resource resourceB = new Resource();
public int read() {
synchronized (resourceA) {
synchronized (resourceB) {
return resourceB.value + resourceA.value;
}
}
}
public void write(int a, int b) {
synchronized (resourceB) {
synchronized (resourceA) {
resourceA.value = a;
resourceB.value = b;
}
}
}
}
假設read()方法由一個線程啟動,write()方法由另外一個線程啟動。讀線程將擁有resourceA鎖,寫線程將擁有resourceB鎖,兩者都堅持等待的話就出現死鎖。
實際上,上面這個例子發生死鎖的概率很小。因為在代碼內的某個點,CPU必須從讀線程切換到寫線程,所以,死鎖基本上不能發生。
但是,無論代碼中發生死鎖的概率有多小,一旦發生死鎖,程序就死掉。有一些設計方法能幫助避免死鎖,包括始終按照預定義的順序獲取鎖這一策略。已經超出SCJP的考試范圍。
八、線程同步小結
1、線程同步的目的是為了保護多個線程反問一個資源時對資源的破壞。
2、線程同步方法是通過鎖來實現,每個對象都有切僅有一個鎖,這個鎖與一個特定的對象關聯,線程一旦獲取了對象鎖,其他訪問該對象的線程就無法再訪問該對象的其他非同步方法。
3、對于靜態同步方法,鎖是針對這個類的,鎖對象是該類的Class對象。靜態和非靜態方法的鎖互不干預。一個線程獲得鎖,當在一個同步方法中訪問另外對象上的同步方法時,會獲取這兩個對象鎖。
4、對于同步,要時刻清醒在哪個對象上同步,這是關鍵。
5、編寫線程安全的類,需要時刻注意對多個線程競爭訪問資源的邏輯和安全做出正確的判斷,對“原子”操作做出分析,并保證原子操作期間別的線程無法訪問競爭資源。
6、當多個線程等待一個對象鎖時,沒有獲取到鎖的線程將發生阻塞。
7、死鎖是線程間相互等待鎖鎖造成的,在實際中發生的概率非常的小。真讓你寫個死鎖程序,不一定好使,呵呵。但是,一旦程序發生死鎖,程序將死掉。
測試通過的版本如下:
Eclipse:3.3.2
jdk:1.6
junit:3.8
ant:1.7(1.7之前的版本好像還不提供mail功能。。。)
<!-- JUnit build script using ant 1.7 -->
<project name="JunitTestProject" default="mail" basedir=".">
<property name="app.name" value="JunitTestProject" />
<property name="build.dir" value="bin" />
<!-- ====================" path define " ================================ -->
<path id="cobertura.classpath">
<fileset dir="lib/coberture">
<include name="cobertura.jar" />
<include name="*.jar" />
</fileset>
</path>
<!-- ====================" cobertura task define " Target ================================ -->
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />
<!-- ==================== "clean " Target ================================ -->
<target name="clean">
<available property="junit.present" classname="junit.framework.TestCase" />
<delete dir="${build.dir}" quiet="true" />
<delete file="report" quiet="true" />
</target>
<!-- ==================== "copy xml resource " Target ================================ -->
<target name="copyxml" depends="clean">
<copy todir="${build.dir}/testcases">
<fileset dir="WEB-INF" />
</copy>
</target>
<!-- ==================== "compile src" Target ================================ -->
<target name="compile" depends="copyxml">
<mkdir dir="${build.dir}" />
<javac srcdir="src" destdir="${build.dir}" debug="yes">
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="**/*.java" />
</javac>
<javac srcdir="WEB-INF" destdir="${build.dir}">
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="*.jsp" />
</javac>
</target>
<!-- ==================== jar" Target ================================ -->
<target name="jar" depends="compile">
<mkdir dir="dist/lib" />
<jar jarfile="dist/lib/${app.name}.jar" basedir="${build.dir}" includes="com/**" />
</target>
<!-- ==================== compile test src" Target ================================ -->
<target name="compiletests" depends="jar">
<mkdir dir="${build.dir}/testcases" />
<javac srcdir="test" destdir="${build.dir}/testcases" >
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
<fileset dir="dist/lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="**/*.java" />
</javac>
</target>
<!-- ==================== instrumented" Target ================================ -->
<target name="instrumented" depends="compiletests">
<cobertura-instrument todir="bin/instrumented-classes">
<ignore regex="org.apache.log4j.*" />
<fileset dir="bin">
<include name="com/**/*.class" />
</fileset>
</cobertura-instrument>
</target>
<!-- ==================== junit-test" Target ================================ -->
<target name="runtests" depends="instrumented">
<mkdir dir="report" />
<property name="tests" value="*Test" />
<junit printsummary="yes" haltonerror="yes" haltonfailure="yes" fork="yes">
<formatter type="plain" usefile="false" />
<formatter type="xml" />
<batchtest todir="report">
<fileset dir="test">
<include name="**/${tests}.java" />
<exclude name="**/ConfigTest.java" />
</fileset>
</batchtest>
<!--
Note the classpath order: instrumented classes are before the
original (uninstrumented) classes. This is important.
-->
<classpath location="bin/instrumented-classes" />
<!--
src classpath
-->
<classpath location="bin" />
<!--
The instrumented classes reference classes used by the
Cobertura runtime, so Cobertura and its dependencies
must be on your classpath.
-->
<classpath refid="cobertura.classpath" />
<!--
test case class path define
-->
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
<pathelement location="bin/testcases" />
</classpath>
</junit>
</target>
<!-- ==================== junit-report" Target ================================ -->
<target name="report" depends="runtests">
<mkdir dir="report/html" />
<junitreport todir="report">
<fileset dir="report">
<include name="TEST-*.xml" />
</fileset>
<report todir="report/html" />
</junitreport>
</target>
<!-- ==================== "coverage-report" Target ================================ -->
<target name="coverage-report" depends="report">
<cobertura-report format="html" destdir="cobertura" >
<fileset dir="src">
<include name="**/*.java" />
</fileset>
</cobertura-report>
<echo>The execution of coverage-report is complete. Coverage Reports are available in /${coverage-report}</echo>
</target>
<!-- ==================== "make file to zip" Target ================================ -->
<target name="make_data_zip" depends="coverage-report">
<tstamp>
<format property="date" pattern="yyyy-MM-dd HH-mm" />
</tstamp>
<jar jarfile="dist/lib/cobertura${date}.zip" basedir="cobertura" />
<jar jarfile="dist/lib/report${date}.zip" basedir="report" excludes="*.xml"/>
</target>
<!-- ==================== "mail" Target ================================ -->
<target name="mail" depends="make_data_zip">
<!-- <taskdef name="mail" classname="org.apache.tools.ant.taskdefs.optional.mail.MimeMail"/> -->
<tstamp/>
<mail messageMimeType="text/html"
messageFile="message.txt"
tolist="bpcjy@hotmail.com"
mailhost="mailsvr or mail IPAddress"
subject="JUnit Test Results: ${TODAY}"
from="bpcjy@hotmail.com">
<fileset dir=".">
<include name="dist/lib/*.zip"/>
</fileset>
</mail>
</target>
</project>
struts2.0:(6)
lib/antlr-2.7.6.jar
lib/struts2-core-2.0.14.jar
lib/struts2-spring-plugin-2.0.14.jar
lib/freemarker-2.3.8.jar
lib/ognl-2.6.11.jar
lib/xwork-2.0.7.jar
(注意單用時必須還要用lib/commons-logging-1.0.4.jar)
spring2.5:(10)
dist/modules/spring-aop.jar
dist/modules/spring-beans.jar
dist/modules/spring-context.jar
dist/modules/spring-context-support.jar
dist/modules/spring-core.jar
dist/modules/spring-jdbc.jar
dist/modules/spring-orm.jar
dist/modules/spring-tx.jar
dist/modules/spring-web.jar
dist/modules/spring-webmvc-struts.jar
hibernate3.2:(10)
hibernate3.jar
lib/asm.jar
lib/asm-attrs.jar
lib/cglib-2.1.3.jar
lib/commons-collections-2.1.1.jar
lib/commons-logging-1.0.4.jar
lib/dom4j-1.6.1.jar
lib/ehcache-1.2.3.jar
lib/jta.jar
lib/xml-apis.jar
其它jar:(6)
servlet.jar
sqljdbc.jar
jsonplugin-0.30.jar(jsonplugin-0.30于6月6號發布,修復了一直很頭疼的cglib序列化問題)
serializer.jar
xalan.jar
(Xalan是將可擴展標記語言(XML)轉換為超文本鏈接標識語言(HTML)或其它類型XML文檔的規范,添加操作XML的jar,一般要添加xalan.jar、serializer.jar這兩個包,如有特殊需求可將下載的所有jar全部添加
(下載地址:http://apache.seekmeup.com/xml/xalan-j里面的一個xalan-j_2_7_0-bin.zip))
xercesImpl.jar
( 實現解析XML文件的功能很方便,我們可以通過下載第三方的一些工具包如xml-apis.jar和xercesImpl.jar 等.Xerces是一個與可擴展標記語言(XML)兼容的語法分析器。Xerces分析器可處理Java和C++,它采用互聯網聯盟XML、文件對象...Xerces-C是用可移植的C++子集編寫的XML分析器。Xerces-C允許對XML數據進行讀寫操作)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> ĵ</title>
<style>
body {
margin: 7px;
font:12px Verdana, Arial, Helvetica, sans-serif;
}
* {
list-style-type: none;
margin: 0px;
padding: 0px;
border: thin none;
}
#nav {
position: absolute;
font-size: 9px;
opacity: 0.8;
}
#nav a {
display: block;
width: 100px;
height: 15px;
padding: 3px 5px 12px;
background: #666;
color: #fff;
text-decoration: none;
}
#nav a:hover {
background: #333;
}
#nav li {
width: 120px;
height:30px;
overflow:hidden;
background: #ccc;
padding-bottom: 3px;
}
#nav ul {
position: absolute;
margin-left: 110px;
margin-top: -30px;
}
html>body #nav ul {
margin-left: 119px;
margin-top: -39px;
}
#nav ul {
display: none;
}
#nav li.show ul {
display: block;
}
#nav li.show li ul {
display: none;
}
#nav li li.show ul {
display: block;
}
</style>
<script language="javascript" type="text/javascript">
function menuFix() {
var sfEls = document.getElementById("nav").getElementsByTagName("li");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=(this.className.length>0? " ": "") + "show";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp("( ?|^)show\\b"), "");
}
}
}
window.onload=menuFix;
</script>
</head>
<body>
<ul id="nav">
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a>.</li>
<li><a href="#">nav item</a>.</li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
</ul>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0049)http://vip.5d.cn/flood/myjs/htm/menu/coolmenu.htm -->
<HTML><HEAD><TITLE>下滑菜單</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2900.2802" name=GENERATOR>
<META content=FrontPage.Editor.Document name=ProgId>
<STYLE type=text/css>.menubar {
BORDER-RIGHT: 1px outset; BORDER-TOP: 1px outset; BACKGROUND: #0099cc; BORDER-LEFT: 1px outset; WIDTH: 100px; CURSOR: default; COLOR: yellow; BORDER-BOTTOM: 1px outset; POSITION: absolute; TOP: 10px; HEIGHT: 20px
}
.menu {
BORDER-RIGHT: 2px outset; PADDING-RIGHT: 15px; BORDER-TOP: white 2px outset; DISPLAY: none; PADDING-LEFT: 15px; BACKGROUND: yellow; PADDING-BOTTOM: 15px; BORDER-LEFT: 2px outset; WIDTH: 140px; PADDING-TOP: 15px; BORDER-BOTTOM: 2px outset; POSITION: absolute; TOP: 30px
}
.menu A {
COLOR: blue; TEXT-DECORATION: none
}
.menu A:hover {
COLOR: #00ffff
}
</STYLE>
<SCRIPT language=javascript>
function menuControl(show)
{
window.event.cancelBubble=true;
var objID=event.srcElement.id;
var index=objID.indexOf("_");
var mainID=objID.substring(0,index);
var numID=objID.substring(index+1,objID.length);
if(mainID=="menubar")
{
if(show==1)
{
eval("showMenu("+"menu_"+numID+")");
}
else
{
eval("hideMenu("+"menu_"+numID+")");
}
}
}
var nbottom=0,speed=1;
function displayMenu(obj)
{
obj.style.clip="rect(0 100% "+nbottom+"% 0)";
nbottom+=speed;
if(nbottom<=100)
{
timerID=setTimeout("displayMenu("+obj.id+"),70");
}
else clearTimeout(timerID);
}
function showMenu(obj)
{
obj.style.display="block";
obj.style.clip="rect(0 0 0 0)";
nbottom=5;
displayMenu(obj);
}
function hideMenu(obj)
{
nbottom=0;
obj.style.display="none";
}
function keepMenu(obj)
{
obj.style.display="block";
}
</SCRIPT>
</HEAD>
<BODY>
<TABLE style="FONT-SIZE: 15px" cellSpacing=0 cellPadding=0 width=400 border=0>
<TBODY>
<TR>
<TD width="20%">
<DIV class=menubar id=menubar_1 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>教育網站 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_2 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>電腦網站 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_3 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>免費郵件 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_4 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>其它網站 </DIV></TD></TR>
<TR>
<TD width="20%">
<DIV class=menu id=menu_1 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
>重慶民政學校</A><BR><A
>重慶大學</A><BR><A
>重慶交通學院</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_2 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
>天極網</A><BR><A
>電腦愛好者</A><BR><A
>上網雜志</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_3 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
>163電子郵件</A><BR><A
>首都在線</A><BR><A
>21CN電子郵件</A><BR><A
>炎皇在線</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_4 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
>搜狐</A><BR><A
>雅虎</A><BR><A
>搜索客</A><BR><A
>新浪網</A><BR><A
>遠航網站</A>
</DIV></TD></TR></TBODY></TABLE></SCRIPT></BODY></HTML>
用過struts1.x的人都知道,標簽庫有html、bean、logic、tiles,
而struts2.0里的標簽卻沒有分類,只用在jsp頭文件加上
<%@ taglib prefix="s" uri="/struts-tags" %>
就能使用struts2.0的標簽庫
下面就介紹下每個標簽的用法(有錯請指正):
A:
<s:a href=""></s:a>-----超鏈接,類似于html里的<a></a>
<s:action name=""></s:action>-----執行一個view里面的一個action
<s:actionerror/>-----如果action的errors有值那么顯示出來
<s:actionmessage/>-----如果action的message有值那么顯示出來
<s:append></s:append>-----添加一個值到list,類似于list.add();
<s:autocompleter></s:autocompleter>-----自動完成<s:combobox>標簽的內容,這個是ajax
B:
<s:bean name=""></s:bean>-----類似于struts1.x中的,JavaBean的值
C:
<s:checkbox></s:checkbox>-----復選框
<s:checkboxlist list=""></s:checkboxlist>-----多選框
<s:combobox list=""></s:combobox>-----下拉框
<s:component></s:component>-----圖像符號
D:
<s:date/>-----獲取日期格式
<s:datetimepicker></s:datetimepicker>-----日期輸入框
<s:debug></s:debug>-----顯示錯誤信息
<s:div></s:div>-----表示一個塊,類似于html的<div></div>
<s:doubleselect list="" doubleName="" doubleList=""></s:doubleselect>-----雙下拉框
E:
<s:if test=""></s:if>
<s:elseif test=""></s:elseif>
<s:else></s:else>-----這3個標簽一起使用,表示條件判斷
F:
<s:fielderror></s:fielderror>-----顯示文件錯誤信息
<s:file></s:file>-----文件上傳
<s:form action=""></s:form>-----獲取相應form的值
G:
<s:generator separator="" val=""></s:generator>----和<s:iterator>標簽一起使用
H:
<s:head/>-----在<head></head>里使用,表示頭文件結束
<s:hidden></s:hidden>-----隱藏值
I:
<s:i18n name=""></s:i18n>-----加載資源包到值堆棧
<s:include value=""></s:include>-----包含一個輸出,servlet或jsp頁面
<s:inputtransferselect list=""></s:inputtransferselect>-----獲取form的一個輸入
<s:iterator></s:iterator>-----用于遍歷集合
L:
<s:label></s:label>-----只讀的標簽
M:
<s:merge></s:merge>-----合并遍歷集合出來的值
O:
<s:optgroup></s:optgroup>-----獲取標簽組
<s:optiontransferselect doubleList="" list="" doubleName=""></s:optiontransferselect>-----左右選擇框
P:
<s:param></s:param>-----為其他標簽提供參數
<s:password></s:password>-----密碼輸入框
<s:property/>-----得到'value'的屬性
<s:push value=""></s:push>-----value的值push到棧中,從而使property標簽的能夠獲取value的屬性
R:
<s:radio list=""></s:radio>-----單選按鈕
<s:reset></s:reset>-----重置按鈕
S:
<s:select list=""></s:select>-----單選框
<s:set name=""></s:set>-----賦予變量一個特定范圍內的值
<s:sort comparator=""></s:sort>-----通過屬性給list分類
<s:submit></s:submit>-----提交按鈕
<s:subset></s:subset>-----為遍歷集合輸出子集
T:
<s:tabbedPanel id=""></s:tabbedPanel>-----表格框
<s:table></s:table>-----表格
<s:text name=""></s:text>-----I18n文本信息
<s:textarea></s:textarea>-----文本域輸入框
<s:textfield></s:textfield>-----文本輸入框
<s:token></s:token>-----攔截器
<s:tree></s:tree>-----樹
<s:treenode label=""></s:treenode>-----樹的結構
U:
<s:updownselect list=""></s:updownselect>-----多選擇框
<s:url></s:url>-----創建url
@echo off
setlocal enabledelayedexpansion //設置延遲環境變量擴充
set JAVA=%JAVA_HOME%\bin\java //java命令
set OPTS=-Xms512M -Xmx512M -Xss128k -XX:+AggressiveOpts -XX:+UseParallelGC -XX:NewSize=64M //jvm參數
set LIBPATH=..\lib //**jar包所在的目錄
set CONFIG=..\etc //properties文件目錄
set ENGINE=main.jar //主函數類的包
set CP=%CONFIG%;%ENGINE%; //classpath
set MAIN=net.blogjava.Main //main class
//循環加載jar包
for /f %%i in ('dir /b %LIBPATH%\*.jar^|sort') do (
set CP=!CP!%LIBPATH%\%%i;
)
echo ===============================================================================
echo.
echo Engine Startup Environment
echo.
echo JAVA: %JAVA%
echo.
echo CONFIG: %CONFIG%
echo.
echo JAVA_OPTS: %OPTS%
echo.
echo CLASSPATH: %CP%
echo.
echo ===============================================================================
echo.
%JAVA% %OPTS% -cp %CP% %MAIN% //運行
www.findjar.com
findjar是一個JAR 文件搜索引擎,通過findjar可以搜索與下載jar文件以及class文件。
JAR是一種把許多文件聚合到一個文件的與平臺無關一種文件格式。許多個用Java編寫的applet以及它們所需要的組件(.class文件,圖片,聲音和其他資源文件)能夠被打包到一個JAR文件中。java可以提供豐富的交互行為,在支持圖文,多媒體方面做的比較優秀,比較普遍的應用于支持Java的手機,比如游戲JAR文件,電子書JAR文件。findjar的數據庫中目前已有16100多JAR 文件包含了將近200萬的 classes,輸入你想要的class或JAR文件名進行搜索,然后下載你想要的文件即可。
<id name="id" type="java.lang.Long" unsaved-value="0">
<column name="ID" precision="10" scale="0" />
<generator class="sequence" >//改為native也不行
加上它 <param name="sequence">sequence名字</param>
</generator>
</id>
安裝oracle后修改了機器名稱,OracleOraHome92TNSListener服務起不來
只需要修改兩個文件
$ORACLE_HOME $\network\admin\listener.ora和tnsnames.ora這兩個文件
將舊的機器名改為新的就可以了
如何更改服務中MySQL的可執行文件路徑
錯誤現象:MySQL開始是安裝在D盤,后來因其他原因卸掉后又重新安裝到E盤,發現不能通過“net start mysql”啟動。查看管理工具中"服務"中MySQL的屬性后發現,可執行文件路徑仍是D:\mysql\bin\...現在怎么樣更改,或者怎么從服務項去掉MySQL?
解決方法:到注冊表里HKEY_LOCAL_MECHINE---SYSTEM ---CurrentControlSet 更改查找MySQL項值,然后改路徑。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
可以在注冊表搜索“D:\mysql\bin\”,然后將其改成正確的路徑“E:\mysql\bin\”。
安裝了Oracle之后eclipse、tomcat不能啟動問題解決:在環境變量里把PATH里Oracle自帶的JRE去掉
一. .properties 文件的形式
# 以下為服務器、數據庫信息
dbPort = localhost
databaseName = mydb
dbUserName = root
dbPassword = root
# 以下為數據庫表信息
dbTable = mytable
# 以下為服務器信息
ip = 192.168.0.9
在上面的文件中我們假設該文件名為: test.properties 文件。其中 # 開始的一行為注釋信息;在等號“ = ”左邊的我們稱之為 key ;等號“ = ”右邊的我們稱之為 value 。(其實就是我們常說的鍵 - 值對) key 應該是我們程序中的變量。而 value 是我們根據實際情況配置的。
二. JDK 中的 Properties 類 Properties 類存在于胞 Java.util 中,該類繼承自 Hashtable ,它提供了幾個主要的方法:
1. getProperty ( String key) , 用指定的鍵在此屬性列表中搜索屬性。也就是通過參數 key ,得到 key 所對應的 value。
2. load ( InputStream inStream) ,從輸入流中讀取屬性列表(鍵和元素對)。通過對指定的文件(比如說上面的 test.properties 文件)進行裝載來獲取該文件中的所有鍵 - 值對。以供 getProperty ( String key) 來搜索。
3. setProperty ( String key, String value) ,調用 Hashtable 的方法 put 。他通過調用基類的put方法來設置 鍵 - 值對。
4. store ( OutputStream out, String comments) , 以適合使用 load 方法加載到 Properties 表中的格式,將此 Properties 表中的屬性列表(鍵和元素對)寫入輸出流。與 load 方法相反,該方法將鍵 - 值對寫入到指定的文件中去。
5. clear () ,清除所有裝載的 鍵 - 值對。該方法在基類中提供。
有了以上幾個方法我們就可以對 .properties 文件進行操作了!
三.代碼實例
package configuration;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/** *//**
* 讀取properties文件
* @author Qutr
*
*/
public class Configuration
...{
private Properties propertie;
private FileInputStream inputFile;
private FileOutputStream outputFile;
/** *//**
* 初始化Configuration類
*/
public Configuration()
...{
propertie = new Properties();
}
/** *//**
* 初始化Configuration類
* @param filePath 要讀取的配置文件的路徑+名稱
*/
public Configuration(String filePath)
...{
propertie = new Properties();
try ...{
inputFile = new FileInputStream(filePath);
propertie.load(inputFile);
inputFile.close();
} catch (FileNotFoundException ex) ...{
System.out.println("讀取屬性文件--->失敗!- 原因:文件路徑錯誤或者文件不存在");
ex.printStackTrace();
} catch (IOException ex) ...{
System.out.println("裝載文件--->失敗!");
ex.printStackTrace();
}
}//end ReadConfigInfo(...)
/** *//**
* 重載函數,得到key的值
* @param key 取得其值的鍵
* @return key的值
*/
public String getValue(String key)
...{
if(propertie.containsKey(key))...{
String value = propertie.getProperty(key);//得到某一屬性的值
return value;
}
else
return "";
}//end getValue(...)
/** *//**
* 重載函數,得到key的值
* @param fileName properties文件的路徑+文件名
* @param key 取得其值的鍵
* @return key的值
*/
public String getValue(String fileName, String key)
...{
try ...{
String value = "";
inputFile = new FileInputStream(fileName);
propertie.load(inputFile);
inputFile.close();
if(propertie.containsKey(key))...{
value = propertie.getProperty(key);
return value;
}else
return value;
} catch (FileNotFoundException e) ...{
e.printStackTrace();
return "";
} catch (IOException e) ...{
e.printStackTrace();
return "";
} catch (Exception ex) ...{
ex.printStackTrace();
return "";
}
}//end getValue(...)
/** *//**
* 清除properties文件中所有的key和其值
*/
public void clear()
...{
propertie.clear();
}//end clear();
/** *//**
* 改變或添加一個key的值,當key存在于properties文件中時該key的值被value所代替,
* 當key不存在時,該key的值是value
* @param key 要存入的鍵
* @param value 要存入的值
*/
public void setValue(String key, String value)
...{
propertie.setProperty(key, value);
}//end setValue(...)
/** *//**
* 將更改后的文件數據存入指定的文件中,該文件可以事先不存在。
* @param fileName 文件路徑+文件名稱
* @param description 對該文件的描述
*/
public void saveFile(String fileName, String description)
...{
try ...{
outputFile = new FileOutputStream(fileName);
propertie.store(outputFile, description);
outputFile.close();
} catch (FileNotFoundException e) ...{
e.printStackTrace();
} catch (IOException ioe)...{
ioe.printStackTrace();
}
}//end saveFile(...)
public static void main(String[] args)
...{
Configuration rc = new Configuration("."config"test.properties");//相對路徑
String ip = rc.getValue("ipp");//以下讀取properties文件的值
String host = rc.getValue("host");
String tab = rc.getValue("tab");
System.out.println("ip = " + ip + "ip-test leng = " + "ip-test".length());//以下輸出properties讀出的值
System.out.println("ip's length = " + ip.length());
System.out.println("host = " + host);
System.out.println("tab = " + tab);
Configuration cf = new Configuration();
String ipp = cf.getValue("."config"test.properties", "ip");
System.out.println("ipp = " + ipp);
// cf.clear();
cf.setValue("min", "999");
cf.setValue("max", "1000");
cf.saveFile("."config"save.perperties", "test");
// Configuration saveCf = new Configuration();
// saveCf.setValue("min", "10");
// saveCf.setValue("max", "1000");
// saveCf.saveFile("."config"save.perperties");
}//end main()
}//end class ReadConfigInfo
四.小結 通過上面的例子不難看出,在Java中操作配置文件是非常簡單的。在一個需要用到大量配置信息的模塊或系統里,我們有必要封裝一個專門的類來共使用。通過最后的main函數調用,相信大家可以看出該類的用法。不足指出希望大家多多指點。
Java properties文件的操作
----------------------------------------------------
java中的properties文件是一種配置文件,主要用于表達配置信息,文件類型為*.properties,格式為文本文件,文件的內容是格式是"鍵=值"的格式,在properties文件中,可以用"#"來作注釋,properties文件在Java編程中用到的地方很多,操作很方便。下面是一個操作java properties文件的例子,給出了操作方法和properties文件。從中可以看到如何讀取properties文件,并應用讀取出來的值,是學習操作properties文件的好例子。
一、properties文件
IcisReport.properties
------------------------------------------------------
#################################
# 工商報表應用IcisReport的配置文件 #
# 作者:雷智民 #
# 日期:2006年11月21日 #
#################################
#
# 說明:業務系統TopIcis和報表系統IcisReport是分離的
# 可分開部署到不同的服務器上,也可以部署到同一個服務
# 器上;IcisReprot作為獨立的web應用程序可以使用任何
# 的Servlet容器或者J2EE服務器部署并單獨運行,也可以
# 通過業務系統的接口調用作為業務系統的一個庫來應用.
#
# IcisReport的ip
IcisReport.server.ip=192.168.3.143
# IcisReport的端口
IcisReport.server.port=8080
# IcisReport的上下文路徑
IcisReport.contextPath=/IcisReport
------------------------------------------------------
二、操作properties文件的java方法
下面是一個操作properties文件的方法
/** *//**
* @return 獲取IcisReport報表應用的URL
*/
private String getIcisReportURL() ...{
String icisReportURL = ""; // IcisReport報表應用的URL
String icisReportServerIP = ""; // IcisReport服務器的IP
String icisReportServerPort = ""; // IcisReport服務器的服務端口
String icisReportContextPath = ""; // IcisReport應用的ContextPath
Properties prop = new Properties();
InputStream in;
try ...{
in = getClass().getResourceAsStream("/IcisReport.properties");
prop.load(in);
Set keyValue = prop.keySet();
for (Iterator it = keyValue.iterator(); it.hasNext();) ...{
String key = (String) it.next();
if (key.equals("IcisReport.server.ip")) ...{
icisReportServerIP = (String) prop.get(key);
} else if (key.equals("IcisReport.server.port")) ...{
icisReportServerPort = (String) prop.get(key);
} else if (key.equals("IcisReport.contextPath")) ...{
icisReportContextPath = (String) prop.get(key);
}
}
} catch (Exception e) ...{
log.error("IO讀取出錯,找不到IcisReport.properties!");
}
if (icisReportServerIP.trim().equals("")) ...{
log
.error("請檢查配置文件IcisReport.properties中的IcisReport.server.ip項的值是否正確!");
}
if (icisReportServerPort.trim().equals("")) ...{
log
.error("請檢查配置文件IcisReport.properties中的IcisReport.server.port項的值是否正確!");
}
if (icisReportServerPort.trim().equals("")) ...{
log
.error("請檢查配置文件IcisReport.properties中的IcisReport.server.port項的值是否正確!");
}
icisReportURL = "http://" + icisReportServerIP.trim() + ":"
+ icisReportServerPort.trim() + icisReportContextPath.trim();
log.info("獲取的icisReportURL=" + icisReportURL);
return icisReportURL;
}
總結:java的properties文件需要放到classpath下面,這樣程序才能讀取到,有關classpath實際上就是java類或者庫的存放路徑,在java工程中,properties放到class文件一塊。在web應用中,最簡單的方法是放到web應用的WEB-INF"classes目錄下即可,也可以放在其他文件夾下面,這時候需要在設置classpath環境變量的時候,將這個文件夾路徑加到classpath變量中,這樣也也可以讀取到。在此,你需要對classpath有個深刻理解,classpath絕非系統中刻意設定的那個系統環境變量,WEB-INF"classes其實也是,java工程的class文件目錄也是。
該文章轉載自網絡大本營:http://www.xrss.cn/Dev/JAVA/200761514149.Html