jsp頁面的代碼:
1,在今天整理代碼的時候,發現原來的一段代碼,前臺合并單元格。
需要在后端,原來的列表基礎上,再增加一層。
頁面上操作,struts2
這樣根據code在頁面上就會顯示分組合并單元格的效果。
就可以使用延遲加載了,spring通過filter的方式對綁定hibernate session 到request的線程中。
that binds a Hibernate Session to the thread for the entire processing of the request
剛開始我是把上面這段配置隨便放到web.xml中,一致不成功總報session 關閉,不起作用,最后查了一下,我把這個filter放到了struts的filter之上,就可以了。
說明FlushMode有五種屬性
1 NEVEL
2 MANUAL
3 AUTO
4 COMMIT
5 ALWAYS
我用的是Struts2基類代碼,如下
先說一下:
一,struts2的ModelDriven (下面來源網絡)
可以根據Action屬性的不同將它分為兩類:Field-Driven(屬性驅動) Action和Model-Driven(模型驅動) Action。
一、Field-Driven(屬性驅動)Action,Action擁有自己的屬性,這些屬性一般是Java的基本類型。表單字段直接和Action的屬性 對應。
二、實現了modelDriven接口可以在action中直接獲得例如User對象,它會將Object getModel()取得的User放到ValueStack中。可以理解為將這個User的屬性追加到Action中。它主要是作用是實現類似 Struts的FormBean功能。
在struts2中,提供了一種直接使用領域對象的方式,就是讓action實現com.opensymphony.xwork2.ModelDriven接口,ModelDriven讓你可以直接操作應用程序中的領域對象,允許你在web層和業務層使用相同的對象。
ModelDriven接口只有一個方法
public Object getModel() {
return null;
}
該方法返回一個用于接收用戶輸入數據的對象模型,在這個模型對象中的屬性可以直接通過(屬性名)userName來訪問,而不需要使用(對象名.屬 性名)user.userName這種格式來訪問了,在action也不需要對對象提供getter和setter方法了,但是必須要在action中進 行new操作
如下
// ModelDriven要使用泛型哦
public class LoginAction extends ActionSupport implements ModelDriven<User>{
private static final long serialVersionUID = -6434128483294080524L;
//這里必須要new
private User user=new User();
public String login() throws Exception {
// TODO Auto-generated method stub
return SUCCESS;
}
//這里是實現接口方法
@Override
public User getModel() {
// TODO Auto-generated method stub
//別忘記了,要把返回值寫上哦
return user;
}
}
這樣一個ModelDriven就實現完畢了
和屬性驅動的Action有很大的區別,下面一一列舉:
(1)模型驅動的Action必須實現ModelDriven接口,而且要提供相應的泛型,這里當然就是具體使用的Java Bean了。
(2)實現ModelDriven的getModel方法,其實就是簡單的返回泛型的一個對象。
(3)在Action提供一個泛型的私有對象,這里就是定義一個User的user對象,并提供相應的getter與setter。
好了,上面的三件事做完之后,Action就會去自動調用User的setter將表單中的name屬性的值賦給User中的屬性。而Action的后續處理的Jsp頁面后者是Servlet就可以使用user對象了。
到底是用屬性驅動和是模型驅動呢?
這個問題困擾了很多Struts2的初學者,我這里提供一些建議:
(1)請你統一整個系統中的Action使用的驅動模型,即要么都是用屬性驅動,要么都是用模型驅動。
(2)如果你的DB中的持久層的對象與表單中的屬性都是一一對應的話,那么就使用模型驅動吧,畢竟看起來代碼要整潔得多。
(3)如果表單的屬性不是一一對應的話,那么就應該使用屬性驅動,否則,你的系統就必須提供兩個Bean,一個對應表單提交的數據,另一個用與持久層。
二,持久層基類 HibernateDao
代碼如:
上面的代碼,基類沒有使用HibernateDaoSupport,我們需要自己引入SessionFactory。
持久層基類,一般Spring的Hibernate ORM 框架帶來了方便的HibernateDaoSupport類,你的DAO類可以繼承它:
public class DaoHibernate extends HibernateDaoSupport {
.................
}
如果你選擇這種設計,就需要動態注入SessionFactory而HibernateDaoSupport包含這個屬性.這個類提供了一個方便的方法getHibernateTemplate(); 就能得到HibernateTemplate的一個實例.它也有getSession()和releaseSession,以便于你應為某些原因而不使用HibernateTempate的情況下執行Hibernate操作。
HibernateDaoSupport提供了基于AOP事務的自動處理,程序員完全可以不用理會事務的開始與提交。在JDBC中一個Connection對象使用一個事務,那么在Hibernate中一個事務肯定要關聯一個SessionFactory了,然而這個SessionFactory卻沒有在DAO中體現。其實主要的原因是HibernateDaoSupport類已經默默地做了封裝的工作,它用一個setSessionFactory方法將SessionFactory進行注入,所以繼承自HibernateDaoSupport類的DAO都會具有SessionFactory的屬性,從而可以通過SessionFactory創建Session實例操作數據庫。
如果使用像 public class HibernateDao<T, PK extends Serializable> 這樣的泛型基類就會有問題,可以拿個T代表任意類型,Java的泛型拿不到T.class,就無法得到類對象, 如下面的clazz,
public T get(final PK id) {
Assert.notNull(id, "id不能為空");
return (T) getSession().load(clazz, id);
}
最后在網上找到了解決方案,可以使用泛型public class HibernateDao<T, PK extends Serializable>基類了。
重點這句: entityClass =(Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
spring bean 定義可能包含大量的配置信息,包括容器相關的信息(比如初始化方法,靜態工廠方法
等)、構造函數參數、屬性等。如果兩個bean之間的配置信息大同小異,可采用bean的繼承來減少重
復配置工作。子bean定義可以從父bean定義繼承部分配置。它也可覆蓋一些配置,或者添加一些配置
。使用繼承配置可以節省很多輸入工作,實際上就是一種模板形式。
spring中事務配置中就有這樣例子,為了使用事務只要父配置了事務代理就可以了,所有需要事務的
bean只要繼承父就可以了。說到這個就在多說幾句,父bean通常不需要實例化的,而僅僅作為子bean
定的的模板使用;而ApplicationContext默認預初始化所有的singleton bean。為了阻止父bean被預
初始化,可以使用abstract屬性設置父bean為抽象bean。容器會忽略所有的抽象bean定義,預初始化
時不初始化抽象bean。
2, spring 事務管理
傳統的J2EE開發者對事務管理可能采用兩種策略
(1),全局事務:全局事務通常由應用服務器管理,使用JTA。全局事務可跨越多個事務性的資源,保證
在多個事務性資源間跨越時資源一致性。
(2),局部事務:局部事務和特定資源相關,如,一個和JDBC鏈接關聯的事務。該事務盡能保證對該
JDBC連接數據庫的一致性,對局部事務,應用服務器不需要參與事務管理,不能保證跨越多個資源的
事務正確性。
3,編程式事務
Spring 提供兩種編程式的事務管理
(1)使用TransactionTemplate事務管理
(2)直接使用一個PlatformTransactionManager實現類管理事務。
兩種編程式的事務都不需要與特定的事務API耦合,第一種更符合Spring模板式的編程模型,因此通常推薦采用第一種方式,第二種非常類似于JTA的UserTransaction的API編程,區別是減少了異常處理。
4,聲明式事務
Spring的聲明式事務是通過面向切面(AOP)實現。
(1)使用聲明式事務管理
通常,通過TransactionPoxyFactoryBean為目標Bean生成Spring事務代理。當bean實例的方法需要事務管理時,采用TransactionPoxyFactoryBean來自目標bean生成事務代理。每個TransactionPoxyFactoryBean為一個具體的目標bean生成代理對象,代理對象的方法改寫了目標bean的方法,就是在目標bean的方法執行之前加入開始事務,在目標bean方法結束之后提交事務,遇到指定異常回滾事務。
定義事務代理bean模板
(2)根據BeanName自動創建事務代理
如果同一個應用中有很多目標bean需要生成事務代理,當然可以為每個目標bean額外配置一個TransactionPoxyFactoryBean bean.這樣做的缺點是,配置文件相當臃腫而且難以維護,此時可以考慮使用自動事務代理。自動事務代理的思路是,當ApplicationContext初始化完成后,由上下文中的某個bean"后處理"每個目標bean,為這些目標bean生成事務代理。
能為目標bean執行"后處理"的bean必須實現BeanFactoryPostProcessor接口,ApplicationContext完成初始化后,會自動初始化所有實現BeanFactoryPostProcessor接口的bean,并且讓它“后處理”其他bean.Spring提供BeanFactoryPostProcessor的實現類BeanNameAutoPoxyCreator,BeanNameAutoPoxyCreator可以用來處理ApplicationContext中其他bean,方法是通過名稱來識別,并且把他們用事務代理包裝起來。BeanNameAutoPoxyCreator生成的事務代理,和使用TransactionPoxyFactoryBean生成的事務代理基本一致。
定義事務攔截bean
次配置關鍵在兩個bean
TransactionInterceptor
BeanNameAutoProxyCreator
(3)基于注釋式事務代理配置
當采用XML描述配置元數據時,將通過<bean/>元素的class屬性來指定實例化對象的類型。class 屬性 (對應BeanDefinition實例的Class屬性)通常是必須的(不過也有兩種例外的情形,“使用實例工廠方法實例化”和“bean定義的繼承”)。class屬性主要有兩種用途:在大多數情況下,容器將直接通過反射調用指定類的構造器來創建bean(這有點等類似于在Java代碼中使用new操作符);在極少數情況下,容器將調用類的靜態工廠方法來創建bean實例,class屬性將用來指定實際具有靜態工廠方法的類(至于調用靜態工廠方法創建的對象類型是當前class還是其他的class則無關緊要)。
2, 延遲初始化bean
ApplicationContext實現的默認行為就是在啟動時將所有singleton bean提前進行實例化。提前實例化意味著作為初始化過程的一部分,ApplicationContext實例會創建并配置所有的singleton bean。通常情況下這是件好事,因為這樣在配置中的任何錯誤就會即刻被發現(否則的話可能要花幾個小時甚至幾天)。
有時候這種默認處理可能并不是你想要的。如果你不想讓一個singleton bean在ApplicationContext實現在初始化時被提前實例化,那么可以將bean設置為延遲實例化。一個延遲初始化bean將告訴IoC 容器是在啟動時還是在第一次被用到時實例化。
在XML配置文件中,延遲初始化將通過<bean/>元素中的lazy-init屬性來進行控制。例如:
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true">
<!-- various properties here... -->
</bean>
<bean name="not.lazy" class="com.foo.AnotherBean">
<!-- various properties here... -->
</bean>
當ApplicationContext實現加載上述配置時,設置為lazy的bean將不會在ApplicationContext啟動時提前被實例化,而not.lazy卻會被提前實例化。
需要說明的是,如果一個bean被設置為延遲初始化,而另一個非延遲初始化的singleton bean依賴于它,那么當ApplicationContext提前實例化singleton bean時,它必須也確保所有上述singleton 依賴bean也被預先初始化,當然也包括設置為延遲實例化的bean。因此,如果Ioc容器在啟動的時候創建了那些設置為延遲實例化的bean的實例,你也不要覺得奇怪,因為那些延遲初始化的bean可能在配置的某個地方被注入到了一個非延遲初始化singleton bean里面。
在容器層次中通過在<beans/>元素上使用'default-lazy-init'屬性來控制延遲初始化也是可能的。如下面的配置:
<beans default-lazy-init="true">
<!-- no beans will be eagerly pre-instantiated... -->
</beans>
3,自動裝配(autowire)協作者
Spring IoC容器可以自動裝配(autowire)相互協作bean之間的關聯關系。因此,如果可能的話,可以自動讓Spring通過檢查BeanFactory中的內容,來替我們指定bean的協作者(其他被依賴的bean)。由于autowire可以針對單個bean進行設置,因此可以讓有些bean使用autowire,有些bean不采用。autowire的方便之處在減少或者消除屬性或構造器參數的設置,這樣可以給我們的配置文件減減肥![2] 在xml配置文件中,autowire一共有五種類型,可以在<bean/>元素中使用autowire屬性指定:
Table 3.2. Autowiring modes
模式 說明
no 不使用自動裝配。必須通過ref元素指定依賴,這是默認設置。由于顯式指定協作者可以使配置更靈活、更清晰,因此對于較大的部署配置,推薦采用該設置。而且在某種程度上,它也是系統架構的一種文檔形式。
byName 根據屬性名自動裝配。此選項將檢查容器并根據名字查找與屬性完全一致的bean,并將其與屬性自動裝配。例如,在bean定義中將autowire設置為by name,而該bean包含master屬性(同時提供setMaster(..)方法),Spring就會查找名為master的bean定義,并用它來裝配給master屬性。
byType 如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。如果存在多個該類型的bean,那么將會拋出異常,并指出不能使用byType方式進行自動裝配。若沒有找到相匹配的bean,則什么事都不發生,屬性也不會被設置。如果你不希望這樣,那么可以通過設置dependency-check="objects"讓Spring拋出異常。
constructor 與byType的方式類似,不同之處在于它應用于構造器參數。如果在容器中沒有找到與構造器參數類型一致的bean,那么將會拋出異常。
autodetect 通過bean類的自省機制(introspection)來決定是使用constructor還是byType方式進行自動裝配。如果發現默認的構造器,那么將使用byType方式。
如果直接使用property和constructor-arg注入依賴的話,那么將總是覆蓋自動裝配。而且目前也不支持簡單類型的自動裝配,這里所說的簡單類型包括基本類型、String、Class以及簡單類型的數組(這一點已經被設計,將考慮作為一個功能提供)。自動裝配還可以與依賴檢查結合使用,這樣依賴檢查將在自動裝配完成之后被執行。
理解自動裝配的優缺點是很重要的。其中優點包括:
自動裝配能顯著減少配置的數量。不過,采用bean模板(見這里)也可以達到同樣的目的。
自動裝配可以使配置與java代碼同步更新。例如,如果你需要給一個java類增加一個依賴,那么該依賴將被自動實現而不需要修改配置。因此強烈推薦在開發過程中采用自動裝配,而在系統趨于穩定的時候改為顯式裝配的方式。
自動裝配的一些缺點:
盡管自動裝配比顯式裝配更神奇,但是,正如上面所提到的,Spring會盡量避免在裝配不明確的時候進行猜測,因為裝配不明確可能出現難以預料的結果,而且Spring所管理的對象之間的關聯關系也不再能清晰的進行文檔化。
對于那些根據Spring配置文件生成文檔的工具來說,自動裝配將會使這些工具沒法生成依賴信息。
如果采用by type方式自動裝配,那么容器中類型與自動裝配bean的屬性或者構造函數參數類型一致的bean只能有一個,如果配置可能存在多個這樣的bean,那么就要考慮采用顯式裝配了。
盡管使用autowire沒有對錯之分,但是能在一個項目中保持一定程度的一致性是最好的做法。例如,通常情況下如果沒有使用自動裝配,那么僅自動裝配一個或兩個bean定義可能會引起開發者的混淆。
Ehcache支持的分布式緩存支持有三種RMI,JGroups,JMS
這里介紹下MRI和JGrpups兩種方式,Ehcache使用版本為1.5.0,關于ehcache的其他信息請參考http://ehcache.sourceforge.net/EhcacheUserGuide.html,關于jgroups的信息請參考http://www.jgroups.org/manual/html_single/index.html。
原始文章 http://www.javaeye.com/topic/335623
它是一種可以接收從internet 或者internet 上的其他系統傳遞過來的請求的輕量級獨立的通信技術。這種技術允許網絡上的所有系統進行交互。
j2ee平臺是圍繞web服務來構架的,其中的技術和web服務相關的有JAX-RCP 、Web Service、SAAJ 、JAXR 、EJB 、JAC 等,其中Web Services for J2EE 是WEB服務總框架,JAX-RCP是J2EE的WEB服務的核心技術,SAAJ為處理帶附件的SOAP消息提供了JAVA編程API.
在J2EE平臺中,要開發WEB服務可以使用兩種技術,一種基于XML遠程調用的技術-JAX-RCP,另外一個基于XML的消息發送技術-JAXM.
這里主要針對JAX-RCP 詳細說一下。
JAX-RCP( JAVA API FOR XMLBASED RCP) 是一種遠程方法調用(或者說遠程過程調用),那么它和其他遠程方法調用(RPC,COM,CORBA RMI)有什么區別呢
綜合比較長遠的遠程方法調用技術,他們有以下共性。
1,在客戶端和服務端有通用的編程接口。
2,在客戶端STUB,在服務端有SKELETON.
3,客戶端和服務端有專門的協議進行數據傳輸。
對于通用接口的描述,比如CORBA 有IDL OF CORBA ,JAVA RMI 有JAVA RMI INTERFACE IN RMI ,對于基于XML的RPC 來說,IDL 就是WSDL。那么對于XML-RPC來說,這個結構中“傳輸協議”當然是SAOP,SOAP消息是將以傳輸文本為基礎的協議(HTTP,SMTP FTP)作為載體來使用的。也就是說,SOAP消息的傳輸建立在HTTP SMTP FTP之上。
JAX-RCP的客戶端調用方法:
1,基于STUB
2,動態代理
3,動態調用
就拿hibernate來說吧,他支持hql查詢,在我們組裝sql語句時,需要注意幾個問題:
1、要查詢當然離不開數據庫,我們建表時,默認的主鍵都是索引,這里要注意的就是關于建立單個索引和復合索引了。
具體的索引的hibernate中也是適用,我發現好多人用hibernate就很少提到索引這個概念了(用ibatis自己寫sql就會關注索引字段,這個還是可以的額)
索引的引用規則都是適用的:
介紹下:單個索引就是出現索引字段作為條件就應用 ;
復合索引(假設是2個字段的復合索引),出現復合索引的第一個字段作為條件就應用;
出現復合索引的2個字段作為條件,這應用,如果沒有出現復合索引的第一個字段則不應用;
由此我們需要為我們的數據庫建立索引,記住復合索引是有順序的 。
影響我們建立索引的條件還有就是業務(這個很重要) ,舉個例子:如果有2個查詢條件(性別、所在部門),倘若我們要建立符合索引,
那么我們應該將"所在部門"字段放在前面,"性別"放在后面,主要是因為,如果某個地方的查詢條件只有"所在部門",也可以起作用。另外要注意,如果查詢索引字段參與函數計算和like等,那么索引也不起作用。
2、 在我們寫查詢代碼時,盡量對應各個表的已經存在索引寫查詢條件
[第一個查詢條件盡量是單個索引,或者是復合索引的第一個字段] 。
3、還有就是大家再拼裝查詢語句時,傳入的查詢條件值盡量不要直接寫在查詢語句中,而是要以參數的方式提供即使用綁定參數,
這樣,系統多次調用統一個查詢時(比如:select * from TestVO where code = ? [不要寫為 select * from TestVO where code = 'aaaa']) ,
條件值都是以參數的方式提供的,這樣,多次查詢雖然參數值不一樣,但查詢語句相同,數據庫只有第一次才對查詢語句進行編譯,
以后則不在編譯,所以性能會有提升。
用參數的方式還有一個好處是:如果你不是使用
Criteria criteria = openSession().createCriteria(**PO.class);
criteria.add(Restrictions.like( "name",convertDBString(name) ));
的方式,而是使用hibernate的hql的話,那么如果參數值為中文會有問題,用參數可以解決這個問題。
注: 使用綁定參數的優勢:
我們為什么要使用綁定命名參數?任何一個事物的存在都是有其價
值的,具體到綁定參數對于HQL查詢來說,主要有以下兩個主要優勢:
①、 可以利用數據庫實施性能優化,因為對Hibernate來說在底層
使用的是PrepareStatement來完成查詢,因此對于語法相同參數不同的
SQL語句,可以充分利用預編譯SQL語句緩存,從而提升查詢效率。
②、 可以防止SQL Injection安全漏洞的產生:
![]() 圖1 Servlet線程池 |
Import javax.servlet. *; Import javax.servlet.http. *; Import java.io. *; Public class Concurrent Test extends HttpServlet {PrintWriter output; Public void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username; Response.setContentType ("text/html; charset=gb2312"); Username = request.getParameter ("username"); Output = response.getWriter (); Try {Thread. sleep (5000); //為了突出并發問題,在這設置一個延時 } Catch (Interrupted Exception e){} output.println("用戶名:"+Username+"<BR>"); } } |
![]() 圖2 a用戶和b用戶的瀏覽器輸出 |
![]() 圖3 Servlet實例的JMM模型 |
調度時刻 | a線程 | b線程 |
T1 | 訪問Servlet頁面 | |
T2 | 訪問Servlet頁面 | |
T3 | output=a的輸出username=a休眠5000毫秒,讓出CPU | |
T4 | output=b的輸出(寫回主存)username=b休眠5000毫秒,讓出CPU | |
T5 | 在用戶b的瀏覽器上輸出a線程的username的值,a線程終止。 | |
T6 | 在用戶b的瀏覽器上輸出b線程的username的值,b線程終止。 |
Public class Concurrent Test extends HttpServlet implements SingleThreadModel { ………… } |
………… Public class Concurrent Test extends HttpServlet { ………… Username = request.getParameter ("username"); Synchronized (this){ Output = response.getWriter (); Try { Thread. Sleep (5000); } Catch (Interrupted Exception e){} output.println("用戶名:"+Username+"<BR>"); } } } |
…… Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse Response) throws ServletException, IOException { Print Writer output; String username; Response.setContentType ("text/html; charset=gb2312"); …… } } |
2)此外,相應的,最有效率的交流方式必須留給web開發,那就是face2face(面對面),不要太擔心你的設計不能被完備的文檔所保留下來,他們會以交流,代碼和小卡片的方式保存下來
3)人的因素會更加重要,無論是對用戶的需求,還是開發人員的素質。
另:有關web效率,有著名的14條規則,由yahoo性能效率小組所總結,并廣為流傳。業已出現相關插件(YSlow),14 rules列在下面:
減少http請求次數
Image maps 圖像中增加url可以將多個圖片合為一個,減少http請求。
CSS Sprites 通過css 將圖片引入到頁面中減少頁面請求http 。
Combined files合并文件不如合并多個請求的javascript為一個。減少http請求。
http://developer.yahoo.net/blog/archives/2007/04/rule_1_make_few.html
2. Use a Content Delivery Network
在下載的css、js、image組件里增加過期時間
(對下載的組件進行壓縮)
毫無疑問,對站點內容進行壓縮是一個比較常用的 Web 優化手段.但是并不一定都能達到理想的效果.原因在于 mod-gzip 模塊不但消耗服務器端 CPU資源,也消耗客戶端 CPU資源. 而且, mod_gzip 壓縮文件后創建的臨時文件是放到磁盤上的,這也會給磁盤 IO帶來嚴重的問題.
Flickr 采用的是 Httpd 2.x 以后支持的 mod_deflate 模塊.壓縮操作都在內存中進行.mod_deflate 在 Httpd 1.x 是不可用的, 不過可以通過創建 RAM盤的方式來間接提高性能.
當然, mod_gzip 到也不是一無是處, 對于預壓縮的文件, 還是有好處的. 而且, 采用壓縮的時候,也要注意策略. 圖片文件壓縮就沒什么必要了(Flickr 上圖像多, 而且壓縮得不到什么好處). Flickr 只對JavaScript 和 CSS進行壓縮. mod_gzip 新一點的版本能夠自動通過配置 mod_gzip_update_static 選項自動處理預壓縮的文件. Cal 也指出這個特性在一些舊版本的瀏覽器上會出問題.
壓縮的另一個主要手段是內容的壓縮. 針對 JavaScript 可以進行通過減少注釋、合并空格、使用緊湊的語法等小技巧(Google 的所有腳本都非常難讀,而且非常緊湊,思想類似).當然,經過這樣處理的 JavaScript 可能帶了很多括號不容易解析,Flickr 使用了 Dojo Compressor 來構建解析樹。Dojo Compressor 開銷很低,而且對于最終用戶是透明的. JavaScript 的處理方法介紹過,CSS 處理則相對簡單.通過簡單的正則表達式替換(比如把多個空格替換為一個空格符), 最高可以獲得 50% 的壓縮比。
css文件盡可能放在頁面的最上面
js文件盡可能放在頁面的最下面
6。Put JS components as close to the bottom of the page as possible.
(js文件盡可能放在頁面的最下面)
7。Avoid CSS Expressions
(在css文件中慎用表達式)
8。Make JavaScript and CSS External
(在外部包含js和css文件)
9。Reduce DNS Lookups
(減少請求中域名的解析次數)
10。Minify JavaScript
(js代碼壓縮)
11。Avoid doing redirects.
(避免重定向)
12。Remove Duplicates Scripts
(避免請求重復的js文件)
13。Configure ETags
(配置好ETag)
Flickr 的開發者充分利用了 Http 1.1 規范定義的 Etag 與 Last-Modified 機制 來提高 Caching 的效率. 值得注意的是,Cal 介紹了一個在負載均衡條件下的 e-Tag 小技巧. 即可以設定 Apache 通過文件調整時間與文件大小獲得 E-Tag ,而默認情況下, Apache 是通過文件節點獲取 e-Tag 的。當然,這也不是很完美,因為會影響 if-modified-since 。
但是有的網站的e-Tag,如yahoo,其產生規則是基于節點的。相同的css或js腳本在不同節點服務器上的e-Tag不同,所以如果有n個服務器,那么瀏覽器獲得304應答消息的概率是1/n。
14。Make Ajax Cacheable
(緩存Ajax請求)
以下幾點是新增的準則,還沒有正式公布,所以大家要注意,
15。Flush the Header
(先發送Header里的信息)
We improved the page load times by flushing the apache output buffer after the document HEAD was generated.This had two benefits.
First, the HEAD contains SCRIPT and LINK tags for scripts and stylesheets. By flushing the HEAD, those tags are received and parsed by the browser sooner, and in turn the browser starts downloading those components earlier.
Second, the HEAD is flushed before actually generating the search results. This is a win for any property doing a significant backend computation or especially making one or more backend web service calls.
16。Split Static Content Across Multiple Hostnames
(把較大的靜態文件分割成不同域的請求)
If you have many (10 or more) components downloaded from a single hostname, it might be better to split those across two hostnames.
17。Reduce the Size of Cookies
(不要讓Cookie內容過大)
Reduce the amount of data in the cookie by storing state information on the backend, and abbreviating names and values stored in the cookie. Set expiration dates on your cookies, and make them as short as possible.
18。Host Static Content on a Different Top-Level Domain
(把靜態文件放在不同的頂級域名下)
19。Minify CSS
(Css代碼壓縮)
20。Use GET for XHR
(有XHR時使用GET請求)
Iain Lamb did a deep study of how using POST for XMLHttpRequests is inefficient, especially in IE. His recommendation: “If the amount of data you have to send to the server is small (less than 2k), I suggest you design your webservice / client application to use GET rather than POST。
21。Avoid IFrames
(盡量避免使用IFrame)
Don’t use SRC (set it via JS instead). Each IFrame takes 20-50ms, even if it contains nothing
22。Optimize images
(優化圖片)
(2)定時控制--定時的格式(網上總結)
一個Cron-表達式是一個由六至七個字段組成由空格分隔的字符串,其中6個字段是必須的而一個是可選的,如下:
字段名 | 允許的值 | 允許的特殊字符 | ||
---|---|---|---|---|
秒 |
0-59 |
, - * / |
||
分 |
0-59 |
, - * / |
||
小時 |
0-23 |
, - * / |
||
日 |
1-31 |
, - * ? / L W C |
||
月 |
1-12 or JAN-DEC |
, - * / |
||
周幾 |
1-7 or SUN-SAT |
, - * ? / L C # |
||
年 (可選字段) |
empty, 1970-2099 |
, - * / |
'*' 字符可以用于所有字段,在“分”字段中設為"*"表示"每一分鐘"的含義。
'?' 字符可以用在“日”和“周幾”字段. 它用來指定 '不明確的值'. 這在你需要指定這兩個字段中的某一個值而不是另外一個的時候會被用到。在后面的例子中可以看到其含義。
'-' 字符被用來指定一個值的范圍,比如在“小時”字段中設為"10-12"表示"10點到12點".
',' 字符指定數個值。比如在“周幾”字段中設為"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".
'/' 字符用來指定一個值的的增加幅度. 比如在“秒”字段中設置為"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"則表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相當于指定從0秒開始. 每個字段都有一系列可以開始或結束的數值。對于“秒”和“分”字段來說,其數值范圍為0到59,對于“小時”字段來說其為0到23, 對于“日”字段來說為0到31, 而對于“月”字段來說為1到12。"/"字段僅僅只是幫助你在允許的數值范圍內從開始"第n"的值。 因此 對于“月”字段來說"7/6"只是表示7月被開啟而不是“每六個月”, 請注意其中微妙的差別。
'L'字符可用在“日”和“周幾”這兩個字段。它是"last"的縮寫, 但是在這兩個字段中有不同的含義。例如,“日”字段中的"L"表示"一個月中的最后一天" —— 對于一月就是31號對于二月來說就是28號(非閏年)。而在“周幾”字段中, 它簡單的表示"7" or "SAT",但是如果在“周幾”字段中使用時跟在某個數字之后, 它表示"該月最后一個星期×" —— 比如"6L"表示"該月最后一個周五"。當使用'L'選項時,指定確定的列表或者范圍非常重要,否則你會被結果搞糊涂的。
'W' 可用于“日”字段。用來指定歷給定日期最近的工作日(周一到周五) 。比如你將“日”字段設為"15W",意為: "離該月15號最近的工作日"。因此如果15號為周六,觸發器會在14號即周五調用。如果15號為周日, 觸發器會在16號也就是周一觸發。如果15號為周二,那么當天就會觸發。然而如果你將“日”字段設為"1W", 而一號又是周六, 觸發器會于下周一也就是當月的3號觸發,因為它不會越過當月的值的范圍邊界。'W'字符只能用于“日”字段的值為單獨的一天而不是一系列值的時候。
'L'和'W'可以組合用于“日”字段表示為'LW',意為"該月最后一個工作日"。
'#' 字符可用于“周幾”字段。該字符表示“該月第幾個周×”,比如"6#3"表示該月第三個周五( 6表示周五而"#3"該月第三個)。再比如: "2#1" = 表示該月第一個周一而 "4#5" = 該月第五個周三。注意如果你指定"#5"該月沒有第五個“周×”,該月是不會觸發的。
'C' 字符可用于“日”和“周幾”字段,它是"calendar"的縮寫。 它表示為基于相關的日歷所計算出的值(如果有的話)。如果沒有關聯的日歷, 那它等同于包含全部日歷。“日”字段值為"5C"表示"日歷中的第一天或者5號以后",“周幾”字段值為"1C"則表示"日歷中的第一天或者周日以后"。
對于“月份”字段和“周幾”字段來說合法的字符都不是大小寫敏感的。
下面是一些完整的例子:
表達式 | 含義 | |
---|---|---|
"0 0 12 * * ?" |
每天中午十二點觸發 |
|
"0 15 10 ? * *" |
每天早上10:15觸發 |
|
"0 15 10 * * ?" |
每天早上10:15觸發 |
|
"0 15 10 * * ? *" |
每天早上10:15觸發 |
|
"0 15 10 * * ? 2005" |
2005年的每天早上10:15觸發 |
|
"0 * 14 * * ?" |
每天從下午2點開始到2點59分每分鐘一次觸發 | |
"0 0/5 14 * * ?" |
每天從下午2點開始到2:55分結束每5分鐘一次觸發 | |
"0 0/5 14,18 * * ?" |
每天的下午2點至2:55和6點至6點55分兩個時間段內每5分鐘一次觸發 | |
"0 0-5 14 * * ?" |
每天14:00至14:05每分鐘一次觸發 | |
"0 10,44 14 ? 3 WED" |
三月的每周三的14:10和14:44觸發 | |
"0 15 10 ? * MON-FRI" |
每個周一、周二、周三、周四、周五的10:15觸發 | |
"0 15 10 15 * ?" |
每月15號的10:15觸發 | |
"0 15 10 L * ?" |
每月的最后一天的10:15觸發 | |
"0 15 10 ? * 6L" |
每月最后一個周五的10:15觸發 | |
"0 15 10 ? * 6L" |
每月最后一個周五的10:15觸發 | |
"0 15 10 ? * 6L 2002-2005" |
2002年至2005年的每月最后一個周五的10:15觸發 | |
"0 15 10 ? * 6#3" |
每月的第三個周五的10:15觸發 |
1,研究spring webApplicationContext初始化。spring 如何初始化。
spring 有兩種方法,一個是ContextLoaderListener這個Listerner,另一個是ContextLoaderServlet這個Servlet,這兩個方法都是在web應用啟動的時候來初始化WebApplicationContext,ContextLoader是一個工具類,用來初始化WebApplicationContext,其主要方法就是initWebApplicationContext,ContextLoader是把WebApplicationContext(XmlWebApplicationContext是默認實現類)放在了ServletContext中,ServletContext也是一個“容器”,也是一個類似Map的結構,而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,我們如果要使用WebApplicationContext則需要從ServletContext取出,Spring提供了一WebApplicationContextUtils類,可以方便的取出WebApplicationContext,只要把ServletContext傳入就可以了。
2,研究通過使用ApplicationContext對spring 進行初始化。
初始化流程,在初始化的時候,新增一個加載servlet ,這個serlvet負責初始化。AppContextLoader 提供了初始化applicationContext的方法,
通過定義ClassPathXmlApplicationContext 來加載spring 配置文件。裝載配置文件。
并把裝載的ApplicationContext文件放在servletContext中作為全局變量來使用。在使用ClassPathXmlApplicationContext 則需要從ServletContext取出.
HttpClient httpClient = new HttpClient(); |
GetMethod getMethod = new GetMethod("http://www.ibm.com/"); |
//設置成了默認的恢復策略,在發生異常時候將自動重試3次,在這里你也可以設置成自定義的恢復策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); //執行getMethod int statusCode = client.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + getMethod.getStatusLine()); } |
byte[] responseBody = method.getResponseBody(); |
method.releaseConnection(); |
System.out.println(new String(responseBody)); |
下面是程序的完整代碼,這些代碼也可在附件中的test.GetSample中找到。
package test; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; public class GetSample{ public static void main(String[] args) { //構造HttpClient的實例 HttpClient httpClient = new HttpClient(); //創建GET方法的實例 GetMethod getMethod = new GetMethod("http://www.ibm.com"); //使用系統提供的默認的恢復策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); try { //執行getMethod int statusCode = httpClient.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + getMethod.getStatusLine()); } //讀取內容 byte[] responseBody = getMethod.getResponseBody(); //處理內容 System.out.println(new String(responseBody)); } catch (HttpException e) { //發生致命的異常,可能是協議不對或者返回的內容有問題 System.out.println("Please check your provided http address!"); e.printStackTrace(); } catch (IOException e) { //發生網絡異常 e.printStackTrace(); } finally { //釋放連接 getMethod.releaseConnection(); } } } |
根據RFC2616,對POST的解釋如下:POST方法用來向目的服務器發出請求,要求它接受被附在請求后的實體,并把它當作請求隊列(Request-Line)中請求URI所指定資源的附加新子項。POST被設計成用統一的方法實現下列功能:
調用HttpClient中的PostMethod與GetMethod類似,除了設置PostMethod的實例與GetMethod有些不同之外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不同的地方,并以登錄清華大學BBS為例子進行說明。
String url = "http://www.newsmth.net/bbslogin2.php"; PostMethod postMethod = new PostMethod(url); // 填入各個表單域的值 NameValuePair[] data = { new NameValuePair("id", "youUserName"), new NameValuePair("passwd", "yourPwd") }; // 將表單的值放入postMethod中 postMethod.setRequestBody(data); // 執行postMethod int statusCode = httpClient.executeMethod(postMethod); // HttpClient對于要求接受后繼服務的請求,象POST和PUT等不能自動處理轉發 // 301或者302 if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 從頭中取出轉向的地址 Header locationHeader = postMethod.getResponseHeader("location"); String location = null; if (locationHeader != null) { location = locationHeader.getValue(); System.out.println("The page was redirected to:" + location); } else { System.err.println("Location field value is null."); } return; } |
最近用到了HttpClient ,搜集的資料:
HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。本文首先介紹 HTTPClient,然后根據作者實際工作經驗給出了一些常見問題的解決方法。
HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程序需要直接通過 HTTP 協議來訪問網絡資源。雖然在 JDK 的 java.net 包中已經提供了訪問 HTTP 協議的基本功能,但是對于大部分應用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。HttpClient 已經應用在很多的項目中,比如 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient,更多使用 HttpClient 的應用可以參見http://wiki.apache.org/jakarta-httpclient/HttpClientPowered。HttpClient 項目非常活躍,使用的人還是非常多的。目前 HttpClient 版本是在 2005.10.11 發布的 3.0 RC4 。
![]() ![]() |
以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。
下面將逐一介紹怎樣使用這些功能。首先,我們必須安裝好 HttpClient。
![]() ![]() |
使用 HttpClient 需要以下 6 個步驟:
1. 創建 HttpClient 的實例
2. 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址
3. 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例
4. 讀 response
5. 釋放連接。無論執行方法是否成功,都必須釋放連接
6. 對得到后的內容進行處理