
Hibernate支持第三方的連接池,官方推薦的連接池是C3P0,Proxool,以及DBCP。在配置連接池時需要注意的有三點:
一、Apche的DBCP在Hibernate2中受支持,但在Hibernate3中已經不再推薦使用,官方的解釋是這個連接池存在缺陷。如果你因為某種原因需要在Hibernate3中使用DBCP,建議采用JNDI方式。
二、默認情況下(即沒有配置連接池的情況下),Hibernate會采用內建的連接池。但這個連接池性能不佳,且存在諸多BUG,因此官方也只是建議僅在開發環境下使用。
三、Hibernate2和Hibernate3的命名空間有所變化。例如,配置C3P0時的provider_class有Hibernate2環境下使用net.sf.hibernate.connection.C3P0ConnectionProvider,在Hibernate3環境下使用org.hibernate.connection.C3P0ConnectionProvider。
下面是Hibernate環境下幾種常見的連接池配置,都是以連接MySQl為例。
<!-- JDBC驅動程序 -->
<property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/struts?useUnicode=true
& characterEncoding=GBK</property>
<!-- 數據庫用戶名 -->
<property name="connection.username">root</property>
<!-- 數據庫密碼 -->
<property name="connection.password">8888</property>
上面的一段配置,在c3p0和dbcp中,都是必需的,因為hibernate會根據上述的配置來生成connections,再交給c3p0或dbcp管理。但是proxool則不能,可以讓proxool自身來生成連接,這在下面再講。
從網上google了一下,發現大致有三種可以實施的解決方案:
1、使用hibernate自帶的連接池;
2、使用c3po包的連接池功能;
3、使用dbcp包的連接池功能;
4、使用Proxool包的連接池功能;
5、使用JNDI連接池
第一種方案,Hibernate默認連接池,就是在myeclipse產生的hibernate.cfg.xml中添加一個屬性:
<property name="connection.pool_size">20</property>
第二種方案是:C3P0
只需在hibernate.cfg.xml中加入
<property name="c3p0.min_size">2</property>
<property name="c3p0.max_size">10</property>
<property name="c3p0.timeout">1800</property>
<property name="c3p0.acquireRetryAttempts">4</property>
<property name="c3p0.acquireIncrement">1</property>
<property name="c3p0.idleConnectionTestPeriod">36000</property>
<property name="c3p0.initialPoolSize">2</property>
<property name="c3p0.maxPoolSize">10</property>
<property name="c3p0.maxIdleTime">1200</property>
<property name="c3p0.maxStatements">30</property>
<property name="c3p0.minPoolSize">2</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
還有在classespath中加入c3p0-0.8.4.5.jar
第三種方案是:dbcp
在hibernate.cfg.xml中加入
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<property name="dbcp.maxWait">60000</property>
<property name="dbcp.maxIdle">10</property>
<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">60000</property>
<property name="dbcp.ps.maxIdle">10</property>
還有在classespath中加入commons-pool-1.2.jar 和commons-dbcp-1.2.1.jar.
第四種方案是:Proxool
建立一個Proxool.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- the proxool configuration can be embedded within your own application’s.
Anything outside the "proxool" tag is ignored. -->
<something-else-entirely>
<proxool>
<alias>
mysql
</alias>
<driver-url>
jdbc:mysql://localhost:3306/jackdemo
</driver-url>
<driver-class>
com.mysql.jdbc.Driver
</driver-class>
<driver-properties>
<property name="user" value="root" />
<property name="password" value="jack" />
</driver-properties>
<house-keeping-sleep-time>
60000
</house-keeping-sleep-time>
<proxool.simultaneous-build-throttle>
100
</proxool.simultaneous-build-throttle>
<prototype-count>
2
</prototype-count>
<maximum-connection-count>
100
</maximum-connection-count>
<minimum-connection-count>
10
</minimum-connection-count>
</proxool>
</something-else-entirely>
現在來看下配置的意思:
<alias>配置連接池的別名;
<driver-url>和寫JDBC連接數據庫時的URL一樣。
<driver-class>和寫JDBC連接數據庫時的Driver一樣。
<driver-properies>就是連接數據庫時的用戶名和密碼。
<house-keeping-sleep-time>proxool自動偵察各個連接狀態的時間間隔(毫秒),偵察到空閑的連接就馬上回收,超時的銷毀
<prototype-count>最少保持的空閑連接數
<maximum-connection-count>最大連接數。
<minimum-connection-count>最小連接數。
以下是在Hibernate配置文件中對連接池的配置:
<?xml version=’1.0’ encoding=’UTF-8’?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- proxool連接池加載的類-->
<property name="hibernate.connection.provider_class">
org.hibernate.connection.ProxoolConnectionProvider
</property>
<!--連接池的別名,即配置連接池時起的別名-->
<property name="hibernate.proxool.pool_alias">
mysql
</property>
<!--連接池文件的地址-->
<property name="hibernate.proxool.xml">
config/proxool/proxool.xml
</property>
<!--是否將運行期生成的SQL輸出到日志以供調試-->
<property name="show_sql">true</property>
<mapping resource="com/jack/ssh/demo/bo/City.hbm.xml" />
<mapping resource="com/jack/ssh/demo/bo/Province.hbm.xml" />
</session-factory>
</hibernate-configuration>
第五種方案是:JNDI連接池。數據源已經由應用服務配置好(如Web服務器),Hibernate需要做的只是通過JNDI名查找到此數據源。應用服務器將連接池對外顯示為JNDI綁定數據源,它是javax.jdbc.Datasource類的一個實例。只要配置一個Hibernate文件,如:
hibernate.connection.datasource = java:/comp/env/jdbc/portal //JNDI名
hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_loopup_class = org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.MySQLDialect。
一、Apche的DBCP在Hibernate2中受支持,但在Hibernate3中已經不再推薦使用,官方的解釋是這個連接池存在缺陷。如果你因為某種原因需要在Hibernate3中使用DBCP,建議采用JNDI方式。
二、默認情況下(即沒有配置連接池的情況下),Hibernate會采用內建的連接池。但這個連接池性能不佳,且存在諸多BUG,因此官方也只是建議僅在開發環境下使用。
三、Hibernate2和Hibernate3的命名空間有所變化。例如,配置C3P0時的provider_class有Hibernate2環境下使用net.sf.hibernate.connection.C3P0ConnectionProvider,在Hibernate3環境下使用org.hibernate.connection.C3P0ConnectionProvider。
下面是Hibernate環境下幾種常見的連接池配置,都是以連接MySQl為例。
<!-- JDBC驅動程序 -->
<property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/struts?useUnicode=true
& characterEncoding=GBK</property>
<!-- 數據庫用戶名 -->
<property name="connection.username">root</property>
<!-- 數據庫密碼 -->
<property name="connection.password">8888</property>
上面的一段配置,在c3p0和dbcp中,都是必需的,因為hibernate會根據上述的配置來生成connections,再交給c3p0或dbcp管理。但是proxool則不能,可以讓proxool自身來生成連接,這在下面再講。
從網上google了一下,發現大致有三種可以實施的解決方案:
1、使用hibernate自帶的連接池;
2、使用c3po包的連接池功能;
3、使用dbcp包的連接池功能;
4、使用Proxool包的連接池功能;
5、使用JNDI連接池
第一種方案,Hibernate默認連接池,就是在myeclipse產生的hibernate.cfg.xml中添加一個屬性:
<property name="connection.pool_size">20</property>
第二種方案是:C3P0
只需在hibernate.cfg.xml中加入
<property name="c3p0.min_size">2</property>
<property name="c3p0.max_size">10</property>
<property name="c3p0.timeout">1800</property>
<property name="c3p0.acquireRetryAttempts">4</property>
<property name="c3p0.acquireIncrement">1</property>
<property name="c3p0.idleConnectionTestPeriod">36000</property>
<property name="c3p0.initialPoolSize">2</property>
<property name="c3p0.maxPoolSize">10</property>
<property name="c3p0.maxIdleTime">1200</property>
<property name="c3p0.maxStatements">30</property>
<property name="c3p0.minPoolSize">2</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
還有在classespath中加入c3p0-0.8.4.5.jar
第三種方案是:dbcp
在hibernate.cfg.xml中加入
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<property name="dbcp.maxWait">60000</property>
<property name="dbcp.maxIdle">10</property>
<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">60000</property>
<property name="dbcp.ps.maxIdle">10</property>
還有在classespath中加入commons-pool-1.2.jar 和commons-dbcp-1.2.1.jar.
第四種方案是:Proxool
建立一個Proxool.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- the proxool configuration can be embedded within your own application’s.
Anything outside the "proxool" tag is ignored. -->
<something-else-entirely>
<proxool>
<alias>
mysql
</alias>
<driver-url>
jdbc:mysql://localhost:3306/jackdemo
</driver-url>
<driver-class>
com.mysql.jdbc.Driver
</driver-class>
<driver-properties>
<property name="user" value="root" />
<property name="password" value="jack" />
</driver-properties>
<house-keeping-sleep-time>
60000
</house-keeping-sleep-time>
<proxool.simultaneous-build-throttle>
100
</proxool.simultaneous-build-throttle>
<prototype-count>
2
</prototype-count>
<maximum-connection-count>
100
</maximum-connection-count>
<minimum-connection-count>
10
</minimum-connection-count>
</proxool>
</something-else-entirely>
現在來看下配置的意思:
<alias>配置連接池的別名;
<driver-url>和寫JDBC連接數據庫時的URL一樣。
<driver-class>和寫JDBC連接數據庫時的Driver一樣。
<driver-properies>就是連接數據庫時的用戶名和密碼。
<house-keeping-sleep-time>proxool自動偵察各個連接狀態的時間間隔(毫秒),偵察到空閑的連接就馬上回收,超時的銷毀
<prototype-count>最少保持的空閑連接數
<maximum-connection-count>最大連接數。
<minimum-connection-count>最小連接數。
以下是在Hibernate配置文件中對連接池的配置:
<?xml version=’1.0’ encoding=’UTF-8’?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- proxool連接池加載的類-->
<property name="hibernate.connection.provider_class">
org.hibernate.connection.ProxoolConnectionProvider
</property>
<!--連接池的別名,即配置連接池時起的別名-->
<property name="hibernate.proxool.pool_alias">
mysql
</property>
<!--連接池文件的地址-->
<property name="hibernate.proxool.xml">
config/proxool/proxool.xml
</property>
<!--是否將運行期生成的SQL輸出到日志以供調試-->
<property name="show_sql">true</property>
<mapping resource="com/jack/ssh/demo/bo/City.hbm.xml" />
<mapping resource="com/jack/ssh/demo/bo/Province.hbm.xml" />
</session-factory>
</hibernate-configuration>
第五種方案是:JNDI連接池。數據源已經由應用服務配置好(如Web服務器),Hibernate需要做的只是通過JNDI名查找到此數據源。應用服務器將連接池對外顯示為JNDI綁定數據源,它是javax.jdbc.Datasource類的一個實例。只要配置一個Hibernate文件,如:
hibernate.connection.datasource = java:/comp/env/jdbc/portal //JNDI名
hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_loopup_class = org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.MySQLDialect。
Name Lession Mark
Amy Chinese 89
Amy Math 59
Amy History 87
Amy Japanese 77
Alan Math 54
Alan Chinese 83
Alan History 86
Alan Japanese 76
Bruce History 83
Bruce Math 58
Bruce Japanese 82
Alisa Math 59
1. 請查詢出學生出姓名mark<60
2. 請查詢每門學科中存在有一門不及格的學生姓名
3. 請查詢出各科總分排行前三名的學生姓名和成績(包含并列)
4. 請查詢出每門科目中前三名的學生姓名和科目(包含并列的)
Amy Chinese 89
Amy Math 59
Amy History 87
Amy Japanese 77
Alan Math 54
Alan Chinese 83
Alan History 86
Alan Japanese 76
Bruce History 83
Bruce Math 58
Bruce Japanese 82
Alisa Math 59
1. 請查詢出學生出姓名mark<60
2. 請查詢每門學科中存在有一門不及格的學生姓名
3. 請查詢出各科總分排行前三名的學生姓名和成績(包含并列)
4. 請查詢出每門科目中前三名的學生姓名和科目(包含并列的)
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id=scriptmain name=scriptmain codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="560" height="176">
<param name="movie" value="/images/bcastr.swf?bcastr_xml_url=/pages/web/xml/bcastr.xml" />
<param name="quality" value="high" />
<param name=scale value=noscale />
<param name="LOOP" value="false" />
<param name="menu" value="false" />
<param name="wmode" value="transparent" />
<embed src="/images/bcastr.swf?bcastr_xml_url=/pages/web/xml/bcastr.xml" width="560" height="176" loop="false" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" salign="T" name="scriptmain" menu="false" wmode="transparent"></embed>
</object>
<?xml version="1.0" encoding="utf-8"?>
<bcaster autoPlayTime="5">
<item item_url="flash圖片" link="鏈接路徑" >
</item>
<item item_url="flash圖片" link="鏈接路徑" >
</item>
</bcaster>
<param name="movie" value="/images/bcastr.swf?bcastr_xml_url=/pages/web/xml/bcastr.xml" />
<param name="quality" value="high" />
<param name=scale value=noscale />
<param name="LOOP" value="false" />
<param name="menu" value="false" />
<param name="wmode" value="transparent" />
<embed src="/images/bcastr.swf?bcastr_xml_url=/pages/web/xml/bcastr.xml" width="560" height="176" loop="false" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" salign="T" name="scriptmain" menu="false" wmode="transparent"></embed>
</object>
<?xml version="1.0" encoding="utf-8"?>
<bcaster autoPlayTime="5">
<item item_url="flash圖片" link="鏈接路徑" >
</item>
<item item_url="flash圖片" link="鏈接路徑" >
</item>
</bcaster>
困擾我多年的sql語句執行順序今天終于在網上找到了
1. 先where 后select
2. 先where 再group 再having 后select
3. 先where 再group 再having 再order 后select
4. 先join 再where 后select
例:select top 3 name from student group by name order by sum(mark) desc
(查詢班上總分排名前三的學生姓名)
開心啦,開心!
1. 先where 后select
2. 先where 再group 再having 后select
3. 先where 再group 再having 再order 后select
4. 先join 再where 后select
例:select top 3 name from student group by name order by sum(mark) desc
(查詢班上總分排名前三的學生姓名)
開心啦,開心!
1,load()方法從來就是假定數據在數據庫中是存在的,在使用時如果不存在則會拋出ObjectNotFoundException;而get()方法不會假定數據在數據庫中存在,如果不存在則返回null
2,load()方法返回的是實體類的代理類,因此load()可以使用延遲加載策略來加載對象
get()方法返回的不一定是實體類,可能是代理類,因為get()方法如果在session緩存(一級緩存)中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那么返回的還是原先的代理對象,而不是實體類對象。
3,load()方法查詢數據時會先從session緩存(一級緩存)中查找,如果沒有找到則會創建代理類,該代理類僅僅初始化了OID屬性,當第一次訪問其他屬性值時,則會依次從二級緩存-->數據庫查找,直到找到數據,最后將所有屬性值賦給代理類。而get()方法則會直接按照一級緩存-->二級緩存-->數據庫的順序查找。
看到網上的全都是復制的,而且錯誤不少,怎么就沒有人修正一下呢?
2,load()方法返回的是實體類的代理類,因此load()可以使用延遲加載策略來加載對象
get()方法返回的不一定是實體類,可能是代理類,因為get()方法如果在session緩存(一級緩存)中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那么返回的還是原先的代理對象,而不是實體類對象。
3,load()方法查詢數據時會先從session緩存(一級緩存)中查找,如果沒有找到則會創建代理類,該代理類僅僅初始化了OID屬性,當第一次訪問其他屬性值時,則會依次從二級緩存-->數據庫查找,直到找到數據,最后將所有屬性值賦給代理類。而get()方法則會直接按照一級緩存-->二級緩存-->數據庫的順序查找。
看到網上的全都是復制的,而且錯誤不少,怎么就沒有人修正一下呢?
HTTP頭中一般斷點下載時才用到Range和Content-Range實體頭,
Range用戶請求頭中,指定第一個字節的位置和最后一個字節的位置,如(Range:200-300)
Content-Range用于響應頭
請求下載整個文件:
***********************************
GET /test.rar HTTP/1.1
Connection: close
Host: 116.1.219.219
Range: bytes=0-100
***********************************
Range頭域可以請求實體的一個或者多個子范圍,Range的值為0表示第一個字節,也就是Range計算字節數是從0開始的
表示頭500個字節:bytes=0-499
表示第二個500字節:bytes=500-999
表示最后500個字節:bytes=-500
表示500字節以后的范圍:bytes=500-
第一個和最后一個字節:bytes=0-0,-1
同時指定幾個范圍:bytes=500-600,601-999
一般正?;貞?
***********************************
HTTP/1.1 206 OK
Content-Length: 801
Content-Type: application/octet-stream
Content-Location: http://www.onlinedown.net/hj_index.htm
Content-Range: bytes 0-100/2350 //2350:文件總大小
Last-Modified: Mon, 16 Feb 2009 16:10:12 GMT
Accept-Ranges: bytes
ETag: "d67a4bc5190c91:512"
Server: Microsoft-IIS/6.0
Date: Wed, 18 Feb 2009 07:55:26 GMT
***********************************
注意:如果用戶的請求中含有range ,則服務器的相應代碼為206。
206 - Partial Content 客戶發送了一個帶有Range頭的GET請求,服務器完成了它(HTTP 1.1新)。
Range用戶請求頭中,指定第一個字節的位置和最后一個字節的位置,如(Range:200-300)
Content-Range用于響應頭
請求下載整個文件:
***********************************
GET /test.rar HTTP/1.1
Connection: close
Host: 116.1.219.219
Range: bytes=0-100
***********************************
Range頭域可以請求實體的一個或者多個子范圍,Range的值為0表示第一個字節,也就是Range計算字節數是從0開始的
表示頭500個字節:bytes=0-499
表示第二個500字節:bytes=500-999
表示最后500個字節:bytes=-500
表示500字節以后的范圍:bytes=500-
第一個和最后一個字節:bytes=0-0,-1
同時指定幾個范圍:bytes=500-600,601-999
一般正?;貞?
***********************************
HTTP/1.1 206 OK
Content-Length: 801
Content-Type: application/octet-stream
Content-Location: http://www.onlinedown.net/hj_index.htm
Content-Range: bytes 0-100/2350 //2350:文件總大小
Last-Modified: Mon, 16 Feb 2009 16:10:12 GMT
Accept-Ranges: bytes
ETag: "d67a4bc5190c91:512"
Server: Microsoft-IIS/6.0
Date: Wed, 18 Feb 2009 07:55:26 GMT
***********************************
注意:如果用戶的請求中含有range ,則服務器的相應代碼為206。
206 - Partial Content 客戶發送了一個帶有Range頭的GET請求,服務器完成了它(HTTP 1.1新)。
最近我們公司的jsp網站要和另一家公司的asp網站做通訊,之間通過xml傳遞信息
現假如我們公司是A,對方公司是B,如果A發送一條信息給B,B必須反饋一條信息表示是否執行成功。這里有兩種模式可以使用,
第一:A、B把對方都當做服務器進行消息發送
第二:A相當于瀏覽器、B相當于服務器,A發送一個消息給B,B直接返回給A信息。
下面我們來看看這兩種方式分別怎么實現?
第一種:
1、A(a.jsp)的代碼:
StringBuffer sb=new StringBuffer("<?xml version=\"1.0\" encoding=\"GBK\"?>");
sb.append("<User>");
sb.append("<HEAD>");
sb.append("<SUCCESS></SUCCESS>");
sb.append("</HEAD>");
sb.append("<BODY>");
sb.append("<MOBILE></MOBILE>");
sb.append("<NAME></NAME>");
sb.append("<SEX></SEX>");
sb.append("</BODY>");
sb.append("</User>");
URL url = new URL("B服務器的接收路徑");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "text/xml;charset=gbk");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Length", String.valueOf(xml.length()));
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(sb.toString().getBytes());
os.flush();
os.close();
2、B服務器接收到A的請求后,也以類似于1(當然asp中的代碼我不知道怎么寫)將反饋信息發送到A的指定路徑(b.jsp)
3、A(b.jsp)接收B的反饋信息:
InputStream is=request.getInputStream();
第二種:
1、A(a.jsp)的代碼
StringBuffer sb=new StringBuffer("<?xml version=\"1.0\" encoding=\"GBK\"?>");
sb.append("<User>");
sb.append("<HEAD>");
sb.append("<SUCCESS></SUCCESS>");
sb.append("</HEAD>");
sb.append("<BODY>");
sb.append("<MOBILE></MOBILE>");
sb.append("<NAME></NAME>");
sb.append("<SEX></SEX>");
sb.append("</BODY>");
sb.append("</User>");
URL url = new URL("B服務器的接收路徑");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "text/xml;charset=gbk");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Length", String.valueOf(xml.length()));
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(sb.toString().getBytes());
os.flush();
os.close();
2、B接收到A(a.jsp)服務器的代碼后用
byte[] byts = new byte[Request.InputStream.Length];
Request.InputStream.Read(byts,0,byts.Length);
然后用Response.OutputStream.write()返回信息
3、A(a.jsp)接收B服務器的反饋信息(和1的代碼同在a.jsp中,并且就接著1代碼的后面)
if(conn.getResponseCode()==200){
String line=null;
String body="";
is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
body += line;
}
conn.disconnect();
}
其中訪問一個頁面主要用到了HttpURLConnection這個類,當然還有其它幾種方式可以使用,具體請參見我的文章http://www.aygfsteel.com/vickzhu/archive/2008/11/12/240013.html
現假如我們公司是A,對方公司是B,如果A發送一條信息給B,B必須反饋一條信息表示是否執行成功。這里有兩種模式可以使用,
第一:A、B把對方都當做服務器進行消息發送
第二:A相當于瀏覽器、B相當于服務器,A發送一個消息給B,B直接返回給A信息。
下面我們來看看這兩種方式分別怎么實現?
第一種:
1、A(a.jsp)的代碼:
StringBuffer sb=new StringBuffer("<?xml version=\"1.0\" encoding=\"GBK\"?>");
sb.append("<User>");
sb.append("<HEAD>");
sb.append("<SUCCESS></SUCCESS>");
sb.append("</HEAD>");
sb.append("<BODY>");
sb.append("<MOBILE></MOBILE>");
sb.append("<NAME></NAME>");
sb.append("<SEX></SEX>");
sb.append("</BODY>");
sb.append("</User>");
URL url = new URL("B服務器的接收路徑");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "text/xml;charset=gbk");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Length", String.valueOf(xml.length()));
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(sb.toString().getBytes());
os.flush();
os.close();
2、B服務器接收到A的請求后,也以類似于1(當然asp中的代碼我不知道怎么寫)將反饋信息發送到A的指定路徑(b.jsp)
3、A(b.jsp)接收B的反饋信息:
InputStream is=request.getInputStream();
第二種:
1、A(a.jsp)的代碼
StringBuffer sb=new StringBuffer("<?xml version=\"1.0\" encoding=\"GBK\"?>");
sb.append("<User>");
sb.append("<HEAD>");
sb.append("<SUCCESS></SUCCESS>");
sb.append("</HEAD>");
sb.append("<BODY>");
sb.append("<MOBILE></MOBILE>");
sb.append("<NAME></NAME>");
sb.append("<SEX></SEX>");
sb.append("</BODY>");
sb.append("</User>");
URL url = new URL("B服務器的接收路徑");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "text/xml;charset=gbk");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Length", String.valueOf(xml.length()));
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(sb.toString().getBytes());
os.flush();
os.close();
2、B接收到A(a.jsp)服務器的代碼后用
byte[] byts = new byte[Request.InputStream.Length];

然后用Response.OutputStream.write()返回信息
3、A(a.jsp)接收B服務器的反饋信息(和1的代碼同在a.jsp中,并且就接著1代碼的后面)
if(conn.getResponseCode()==200){
String line=null;
String body="";
is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
body += line;
}
conn.disconnect();
}
其中訪問一個頁面主要用到了HttpURLConnection這個類,當然還有其它幾種方式可以使用,具體請參見我的文章http://www.aygfsteel.com/vickzhu/archive/2008/11/12/240013.html
錯誤代碼:
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
錯誤原因:
OpenSessionInViewFilter在getSession的時候,會把獲取回來的session的flush mode 設為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過后再解除該sessionFactory的綁定,最后closeSessionIfNecessary根據該session是否已和transaction綁定來決定是否關閉session。在這個過程中,若HibernateTemplate 發現自當前session有不是readOnly的transaction,就會獲取到FlushMode.AUTO Session,使方法擁有寫權限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉為Flush.AUTO,擁有insert,update,delete操作權限,如果沒有transaction,并且沒有另外人為地設flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction保護的方法有寫權限,沒受保護的則沒有。
參考文章:
http://calvin.blog.javascud.org/post/46.htm
解決辦法:
采用spring的事務聲明,使方法受transaction控制
<bean id="baseTransaction"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="proxyTargetClass" value="true"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userService" parent="baseTransaction">
<property name="target">
<bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
</property>
</bean>
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
錯誤原因:
OpenSessionInViewFilter在getSession的時候,會把獲取回來的session的flush mode 設為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過后再解除該sessionFactory的綁定,最后closeSessionIfNecessary根據該session是否已和transaction綁定來決定是否關閉session。在這個過程中,若HibernateTemplate 發現自當前session有不是readOnly的transaction,就會獲取到FlushMode.AUTO Session,使方法擁有寫權限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉為Flush.AUTO,擁有insert,update,delete操作權限,如果沒有transaction,并且沒有另外人為地設flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction保護的方法有寫權限,沒受保護的則沒有。
參考文章:
http://calvin.blog.javascud.org/post/46.htm
解決辦法:
采用spring的事務聲明,使方法受transaction控制
<bean id="baseTransaction"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="proxyTargetClass" value="true"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userService" parent="baseTransaction">
<property name="target">
<bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
</property>
</bean>
暫時發現了兩種靜態頁包含靜態頁的方法
1、<object style="border:0px" type="text/x-scriptlet" data="test.html" width=100% height=1000></object>
2、<iframe src="" frameborder="0"></iframe>
第一種可以解決大部分問題,不過第二種如果你的a頁面包含b頁面,b頁面中的鏈接都是在b頁面本頁打開的話,b鏈接的頁面就不會在a主窗體顯示
1、<object style="border:0px" type="text/x-scriptlet" data="test.html" width=100% height=1000></object>
2、<iframe src="" frameborder="0"></iframe>
第一種可以解決大部分問題,不過第二種如果你的a頁面包含b頁面,b頁面中的鏈接都是在b頁面本頁打開的話,b鏈接的頁面就不會在a主窗體顯示