亚洲卡一卡2卡三卡4麻豆,亚洲一区二区三区成人网站,亚洲人成图片小说网站http://www.tkk7.com/agun/category/30011.html激情成就夢想,努力創(chuàng)造未來zh-cnSat, 03 Nov 2012 20:44:16 GMTSat, 03 Nov 2012 20:44:16 GMT60java web 導(dǎo)出excel http://www.tkk7.com/agun/archive/2012/11/03/390722.htmlagunagunSat, 03 Nov 2012 04:45:00 GMThttp://www.tkk7.com/agun/archive/2012/11/03/390722.htmlhttp://www.tkk7.com/agun/comments/390722.htmlhttp://www.tkk7.com/agun/archive/2012/11/03/390722.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/390722.htmlhttp://www.tkk7.com/agun/services/trackbacks/390722.html看到這個標(biāo)題,會很疑問,java導(dǎo)出excel 有很多文章呀,都知道怎么用呀,呵呵,我也是這么認(rèn)為,我們常用的就是jxl 或者poi ,現(xiàn)在jxl 代碼不在更新不支持2007,一般都采用poi 進(jìn)行excel的操作,今天在看系統(tǒng)(架構(gòu)struts+ spring+ hibernate),需要做一個excel導(dǎo)出,一個簡單的方法,這個方法只適用于excel簡單的導(dǎo)出,直接通過輸出的頁面,然后設(shè)置頁面為輸出流的文件格式,這樣當(dāng)action轉(zhuǎn)向到j(luò)sp頁面的時候,直接就是將頁面輸出。

 

jsp頁面的代碼:

Java代碼 復(fù)制代碼
  1. <%@ page language="java" pageEncoding="UTF8"%>   
  2. <html:html locale="true">   
  3.     <head>      
  4.         <title>LogExport</title>   
  5.         <meta http-equiv="pragma" content="no-cache">   
  6.         <meta http-equiv="cache-control" content="no-cache">   
  7.         <meta http-equiv="expires" content="0">   
  8.         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">   
  9.         <%   
  10.           response.setCharacterEncoding("UTF-8");   
  11.           response.setContentType("application/vnd.ms-excel;");      
  12.           response.setHeader("Content-Disposition""attachment;filename=\""+new String("Log.xls".getBytes(),"ISO-8859-1")+"\"");   
  13.         %>     
  14.     </head>   
  15.     <body>   
  16.         <form action="/Action_export.do">   
  17.             <table width="100%" border="1" cellspacing="0" cellpadding="0" id="datagrid">   
  18.                 <thead>   
  19.                     <tr class="HeaderStyle" style="font-weight: normal;">   
  20.                         <th>用戶</th>   
  21.                         <th>姓名</th>   
  22.                         <th>日期</th>   
  23.                         <th>登錄IP</th>   
  24.                         <th>主機(jī)名</th>   
  25.                         <th colspan="3">   
  26.                          <table width='100%'  border="1" cellspacing="3" cellpadding="0" frame='void' >    
  27.                                 <tr><td colspan="3" style='background:transparent;' align="center">操作信息</td></tr>   
  28.                                 <tr style='background:transparent;'>   
  29.                                     <td width="40px" align="center">操作</td>   
  30.                                     <td width="100px" align="center">標(biāo)題</td>   
  31.                                     <td align="center">擴(kuò)展信息</td>   
  32.                                 </tr>   
  33.                             </table>   
  34.                         </th>   
  35.                     </tr>   
  36.                 </thead>   
  37.                 <jsp:include page="common.jsp" flush="true" />   
  38.             </table>   
  39.         </form>   
  40.     </body>   
  41. </html:html>  


agun 2012-11-03 12:45 發(fā)表評論
]]>
list合并單元格http://www.tkk7.com/agun/archive/2011/10/17/361437.htmlagunagunMon, 17 Oct 2011 06:44:00 GMThttp://www.tkk7.com/agun/archive/2011/10/17/361437.htmlhttp://www.tkk7.com/agun/comments/361437.htmlhttp://www.tkk7.com/agun/archive/2011/10/17/361437.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/361437.htmlhttp://www.tkk7.com/agun/services/trackbacks/361437.html

1,在今天整理代碼的時候,發(fā)現(xiàn)原來的一段代碼,前臺合并單元格。

 

需要在后端,原來的列表基礎(chǔ)上,再增加一層。

Java代碼 復(fù)制代碼
  1. List<CASEListVO> list2 = super.doFind(hql.toString(), params.toArray(), currPage, pageSize);   
  2.    ArrayList<List<CASEListVO>> linkedList = new ArrayList<List<CASEListVO>>();   
  3. List<String> keyList = new ArrayList<String>();   
  4. for (CASEListVO vo : list2)   
  5. {   
  6.    String key = vo.getItemCode();   
  7.    List<CASEListVO> tempList = new ArrayList<CASEListVO>();   
  8.    if (keyList.indexOf(key) == -1)   
  9.    {   
  10.       keyList.add(key);   
  11.    }   
  12.    else  
  13.    {   
  14.       continue;   
  15.    }   
  16.    for (CASEListVO vo1 : list2)   
  17.    {   
  18.       if (vo1.getItemCode().endsWith(key))   
  19.       {   
  20.          tempList.add(vo1);   
  21.       }   
  22.    }   
  23.    linkedList.add(tempList);   
  24. }   
  25. page.setList(linkedList);//返回的列表  

 頁面上操作,struts2

Html代碼 復(fù)制代碼
  1. <s:iterator value="page" id="list">  
  2.                 <c:forEach var="recordList" items="${list}" varStatus="varStatus">  
  3.                     <c:forEach var="record" items="${recordList}" varStatus="status">  
  4.                         <tr>  
  5.                             <td>  
  6.                                 <input name="selectIds" type="checkbox" value="${record.ltVo.listTmpId}"  
  7.                                     oldValue="${record.estTmpId }" />  
  8.                             </td>  
  9.                             ${status.index }--   
  10.                             <%=((List) pageContext.getAttribute("recordList")).size()%>  
  11.                             <c:if test="${status.index eq 0}">  
  12.                                 <td rowspan="<%=((List) pageContext.getAttribute("recordList")).size()%>" style="width: 240px;text-align: center;">  
  13.                                     ${record.listName}   
  14.                                 </td>  
  15.                             </c:if>  
  16.                             <td style="text-align: center;width:200px;">  
  17.                                 ${record.itemCode}   
  18.                             </td>  
  19.                             <td style="text-align: center;width: 200px;">  
  20.                                 ${record.projectName}   
  21.                             </td>  
  22.                             <td style="text-align: right;width: 200px">  
  23.                                 <fmt:formatNumber value="${record.rate}" pattern="##0.00" />  
  24.                             </td>  
  25.                         </tr>  
  26.                     </c:forEach>  
  27.                 </c:forEach>  
  28.             </s:iterator>  

 

這樣根據(jù)code在頁面上就會顯示分組合并單元格的效果。



agun 2011-10-17 14:44 發(fā)表評論
]]>
hibernate lazyhttp://www.tkk7.com/agun/archive/2011/08/12/356365.htmlagunagunFri, 12 Aug 2011 05:17:00 GMThttp://www.tkk7.com/agun/archive/2011/08/12/356365.htmlhttp://www.tkk7.com/agun/comments/356365.htmlhttp://www.tkk7.com/agun/archive/2011/08/12/356365.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/356365.htmlhttp://www.tkk7.com/agun/services/trackbacks/356365.html今天項目組有要使用的hibernate lazy的,我一直對這種lazy的方式是不贊成使用的,所以我的項目組內(nèi)是明確不能使lazy,包括true和false當(dāng)然hibernate 默認(rèn)的模式是true ,但是在程序中我們是可以控制,當(dāng)然如果不做配置話,也無法在前端使用,其實在項目中,用到lazy的時候并不是特別多(個人觀點),大部分的數(shù)據(jù)都是明確的要在后臺查詢出來的。用lazy也并不復(fù)雜,在web.xml中配置

Xml代碼 復(fù)制代碼
  1. <filter>  
  2.     <filter-name>hibernateFilter</filter-name>  
  3.     <filter-class>  
  4.         org.springframework.orm.hibernate3.support.OpenSessionInViewFilter   
  5.     </filter-class>  
  6.     <init-param>  
  7.         <param-name>singleSession</param-name>  
  8.         <param-value>false</param-value>  
  9.     </init-param>  
  10. </filter>  
  11.   
  12. <filter-mapping>  
  13.     <filter-name>hibernateFilter</filter-name>  
  14.     <url-pattern>*.do</url-pattern>  
  15. </filter-mapping>  

 

就可以使用延遲加載了,spring通過filter的方式對綁定hibernate session 到request的線程中。

that binds a Hibernate Session to the thread for the entire processing of the request

 

剛開始我是把上面這段配置隨便放到web.xml中,一致不成功總報session 關(guān)閉,不起作用,最后查了一下,我把這個filter放到了struts的filter之上,就可以了。

 

 

說明FlushMode有五種屬性

1 NEVEL  

已經(jīng)廢棄了,被MANUAL取代了


2 MANUAL

spring3.x中的opensessioninviewfilter已經(jīng)將默認(rèn)的FlushMode設(shè)置為MANUAL了;
如果FlushMode是MANUAL或NEVEL,在操作過程中hibernate會將事務(wù)設(shè)置為readonly,所以在
增加、刪除或修改操作過程中會出現(xiàn)如下錯誤
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;
解決辦法網(wǎng)上有很多;
1 配置事務(wù),spring會讀取事務(wù)中的各種配置來覆蓋hibernate的session中的FlushMode;
2 先編程式修改FlushMode,比如session.setFlushMode(FlushMode.AUTO); 這樣hibernate就會自動去除readonly限制;
3 直接修改opensessioninviewfilter過濾器的配置,配置過濾器的時候配置
<filter>
      
<filter-name>openSession</filter-name>
      
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      
<init-param>
          
<param-name>flushMode</param-name>
          
<param-value>AUTO</param-value>
      
</init-param>
  
</filter>

3 AUTO

設(shè)置成auto之后,當(dāng)程序進(jìn)行查詢、提交事務(wù)或者調(diào)用session.flush()的時候,都會使緩存和數(shù)據(jù)庫進(jìn)行同步,也就是刷新數(shù)據(jù)庫

4 COMMIT

提交事務(wù)或者session.flush()時,刷新數(shù)據(jù)庫;查詢不刷新


5 ALWAYS

每次進(jìn)行查詢、提交事務(wù)、session.flush()的時候都會刷數(shù)據(jù)庫
這里需要說一下和AUTO的區(qū)別,當(dāng)hibernate緩存中的對象被改動之后,會被標(biāo)記為臟數(shù)據(jù)(即與數(shù)據(jù)庫不同步了)。當(dāng)session設(shè)置為FlushMode.AUTO時,hibernate在進(jìn)行查詢的時候會判斷緩存中的數(shù)據(jù)是否為臟數(shù)據(jù),是則刷數(shù)據(jù)庫,不是則不刷,而always是直接刷新,不進(jìn)行任何判斷。很顯然auto比always要高效得多。

 



agun 2011-08-12 13:17 發(fā)表評論
]]>
struts2 泛型 Hibernatehttp://www.tkk7.com/agun/archive/2011/05/08/349767.htmlagunagunSun, 08 May 2011 01:20:00 GMThttp://www.tkk7.com/agun/archive/2011/05/08/349767.htmlhttp://www.tkk7.com/agun/comments/349767.htmlhttp://www.tkk7.com/agun/archive/2011/05/08/349767.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/349767.htmlhttp://www.tkk7.com/agun/services/trackbacks/349767.html今天在整理代碼的時候,我的Action 和 DAO基類都是使用的泛型:如Action<T> DAO<T>。

 

我用的是Struts2基類代碼,如下

Java代碼 復(fù)制代碼 收藏代碼
  1. public abstract class BaseStrutsAction extends ActionSupport implements ModelDriven<BaseStrutsForm>   
  2. {   
  3.    public static final Logger log = Logger.getLogger(BaseStrutsAction.class);   
  4.   
  5. }  

 先說一下:

一,struts2的ModelDriven (下面來源網(wǎng)絡(luò))

 

可以根據(jù)Action屬性的不同將它分為兩類:Field-Driven(屬性驅(qū)動) Action和Model-Driven(模型驅(qū)動) Action。
一、Field-Driven(屬性驅(qū)動)Action,Action擁有自己的屬性,這些屬性一般是Java的基本類型。表單字段直接和Action的屬性 對應(yīng)。

二、實現(xiàn)了modelDriven接口可以在action中直接獲得例如User對象,它會將Object getModel()取得的User放到ValueStack中。可以理解為將這個User的屬性追加到Action中。它主要是作用是實現(xiàn)類似 Struts的FormBean功能。

在struts2中,提供了一種直接使用領(lǐng)域?qū)ο蟮姆绞剑褪亲宎ction實現(xiàn)com.opensymphony.xwork2.ModelDriven接口,ModelDriven讓你可以直接操作應(yīng)用程序中的領(lǐng)域?qū)ο螅试S你在web層和業(yè)務(wù)層使用相同的對象。

ModelDriven接口只有一個方法

        public Object getModel() {
return null;
}

該方法返回一個用于接收用戶輸入數(shù)據(jù)的對象模型,在這個模型對象中的屬性可以直接通過(屬性名)userName來訪問,而不需要使用(對象名.屬 性名)user.userName這種格式來訪問了,在action也不需要對對象提供getter和setter方法了,但是必須要在action中進(jìn) 行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;
}

//這里是實現(xiàn)接口方法

@Override
public User getModel() {
// TODO Auto-generated method stub

//別忘記了,要把返回值寫上哦
return user;
}
}

這樣一個ModelDriven就實現(xiàn)完畢了

和屬性驅(qū)動的Action有很大的區(qū)別,下面一一列舉:

(1)模型驅(qū)動的Action必須實現(xiàn)ModelDriven接口,而且要提供相應(yīng)的泛型,這里當(dāng)然就是具體使用的Java Bean了。

(2)實現(xiàn)ModelDriven的getModel方法,其實就是簡單的返回泛型的一個對象。

(3)在Action提供一個泛型的私有對象,這里就是定義一個User的user對象,并提供相應(yīng)的getter與setter。

好了,上面的三件事做完之后,Action就會去自動調(diào)用User的setter將表單中的name屬性的值賦給User中的屬性。而Action的后續(xù)處理的Jsp頁面后者是Servlet就可以使用user對象了。

到底是用屬性驅(qū)動和是模型驅(qū)動呢?

這個問題困擾了很多Struts2的初學(xué)者,我這里提供一些建議:

(1)請你統(tǒng)一整個系統(tǒng)中的Action使用的驅(qū)動模型,即要么都是用屬性驅(qū)動,要么都是用模型驅(qū)動。

(2)如果你的DB中的持久層的對象與表單中的屬性都是一一對應(yīng)的話,那么就使用模型驅(qū)動吧,畢竟看起來代碼要整潔得多。

(3)如果表單的屬性不是一一對應(yīng)的話,那么就應(yīng)該使用屬性驅(qū)動,否則,你的系統(tǒng)就必須提供兩個Bean,一個對應(yīng)表單提交的數(shù)據(jù),另一個用與持久層。

二,持久層基類 HibernateDao

 

代碼如:

Java代碼 復(fù)制代碼 收藏代碼
  1. public class HibernateDao<T, PK extends Serializable>  {   
  2.     /**  
  3.      * 用于Dao層子類的構(gòu)造函數(shù).  
  4.      * 通過子類的泛型定義取得對象類型Class.  
  5.      * eg.  
  6.      * public class UserDao extends HibernateDao<User, Long>{  
  7.      * }  
  8.      */  
  9.     public HibernateDao() {   
  10.         super();   
  11.     }  

 

上面的代碼,基類沒有使用HibernateDaoSupport,我們需要自己引入SessionFactory。

持久層基類,一般Spring的Hibernate ORM 框架帶來了方便的HibernateDaoSupport類,你的DAO類可以繼承它:

  public class DaoHibernate extends HibernateDaoSupport {

  .................

  }

  如果你選擇這種設(shè)計,就需要動態(tài)注入SessionFactory而HibernateDaoSupport包含這個屬性.這個類提供了一個方便的方法getHibernateTemplate(); 就能得到HibernateTemplate的一個實例.它也有g(shù)etSession()和releaseSession,以便于你應(yīng)為某些原因而不使用HibernateTempate的情況下執(zhí)行Hibernate操作。

  HibernateDaoSupport提供了基于AOP事務(wù)的自動處理,程序員完全可以不用理會事務(wù)的開始與提交。在JDBC中一個Connection對象使用一個事務(wù),那么在Hibernate中一個事務(wù)肯定要關(guān)聯(lián)一個SessionFactory了,然而這個SessionFactory卻沒有在DAO中體現(xiàn)。其實主要的原因是HibernateDaoSupport類已經(jīng)默默地做了封裝的工作,它用一個setSessionFactory方法將SessionFactory進(jìn)行注入,所以繼承自HibernateDaoSupport類的DAO都會具有SessionFactory的屬性,從而可以通過SessionFactory創(chuàng)建Session實例操作數(shù)據(jù)庫。

 

如果使用像 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);
 }

最后在網(wǎng)上找到了解決方案,可以使用泛型public class HibernateDao<T, PK extends Serializable>基類了。

Java代碼 復(fù)制代碼 收藏代碼
  1. abstract public class BaseHibernateEntityDao<T> extends HibernateDaoSupport {   
  2.  private Class<T> entityClass;   
  3.  public BaseHibernateEntityDao() {   
  4.         <SPAN style="COLOR: #000000">entityClass =(Class<T>) ((ParameterizedType) getClass()   
  5.                                 .getGenericSuperclass()).getActualTypeArguments()[0];</SPAN>   
  6.     }   
  7.  public T get(Serializable id) {   
  8.         T o = (T) getHibernateTemplate().get(entityClass, id);   
  9. }   
  10. }  

重點這句: entityClass =(Class<T>) ((ParameterizedType) getClass()
                                .getGenericSuperclass()).getActualTypeArguments()[0];



agun 2011-05-08 09:20 發(fā)表評論
]]>
Cookie 和 Sessionhttp://www.tkk7.com/agun/archive/2010/12/04/339792.htmlagunagunSat, 04 Dec 2010 04:14:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339792.htmlhttp://www.tkk7.com/agun/comments/339792.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339792.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339792.htmlhttp://www.tkk7.com/agun/services/trackbacks/339792.html一、cookie機(jī)制和session機(jī)制的區(qū)別
*************************************************************************************
具體來說cookie機(jī)制采用的是在客戶端保持狀態(tài)的方案,而session機(jī)制采用的是在服務(wù)器端保持狀態(tài)的方案。
同時我們也看到,由于才服務(wù)器端保持狀態(tài)的方案在客戶端也需要保存一個標(biāo)識,所以session
機(jī)制可能需要借助于cookie機(jī)制來達(dá)到保存標(biāo)識的目的,但實際上還有其他選擇
*************************************************************************************

二、會話cookie和持久cookie的區(qū)別
*************************************************************************************
如果不設(shè)置過期時間,則表示這個cookie生命周期為瀏覽器會話期間,只要關(guān)閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽會話期的cookie被稱為會話cookie。會話cookie一般不保存在硬盤上而是保存在內(nèi)存里。
  如果設(shè)置了過期時間,瀏覽器就會把cookie保存到硬盤上,關(guān)閉后再次打開瀏覽器,這些cookie依然有效直到超過設(shè)定的過期時間。
  存儲在硬盤上的cookie可以在不同的瀏覽器進(jìn)程間共享,比如兩個IE窗口。而對于保存在內(nèi)存的cookie,不同的瀏覽器有不同的處理方式。
*************************************************************************************

三、如何利用實現(xiàn)自動登錄
*************************************************************************************
  當(dāng)用戶在某個網(wǎng)站注冊后,就會收到一個惟一用戶ID的cookie。客戶后來重新連接時,這個
用戶ID會自動返回,服務(wù)器對它進(jìn)行檢查,確定它是否為注冊用戶且選擇了自動登錄,從而使用戶務(wù)需給出明確的用戶名和密碼,就可以訪問服務(wù)器上的資源。
*************************************************************************************

四、如何根據(jù)用戶的愛好定制站點
*************************************************************************************
  網(wǎng)站可以使用cookie記錄用戶的意愿。對于簡單的設(shè)置,網(wǎng)站可以直接將頁面的設(shè)置存儲在cookie中完成定制。然而對于更復(fù)雜的定制,網(wǎng)站只需僅將一個惟一的標(biāo)識符發(fā)送給用戶,由服務(wù)器端的數(shù)據(jù)庫存儲每個標(biāo)識符對應(yīng)的頁面設(shè)置。
*************************************************************************************

五、cookie的發(fā)送
*************************************************************************************
1.創(chuàng)建Cookie對象
2.設(shè)置最大時效
3.將Cookie放入到HTTP響應(yīng)報頭
如果你創(chuàng)建了一個cookie,并將他發(fā)送到瀏覽器,默認(rèn)情況下它是一個會話級別的cookie:存儲在瀏覽器的內(nèi)存中,用戶退出瀏覽器之后被刪除。如果你希望瀏覽器將該cookie存儲在磁盤上,則
需要使用maxAge,并給出一個以秒為單位的時間。將最大時效設(shè)為0則是命令瀏覽器刪除該cookie。
發(fā)送cookie需要使用HttpServletResponse的addCookie方法,將cookie插入到一個Set-Cookie HTTP請求報頭中。由于這個方法并不修改任何之前指定的Set-Cookie報頭,而是創(chuàng)建新的報頭,因此我們將這個方法稱為是addCookie,而非setCookie。同樣要記住響應(yīng)報頭必須在任何文檔內(nèi)容發(fā)送到客戶端之前設(shè)置。

六、cookie的讀取
*************************************************************************************
1.調(diào)用request.getCookie
要獲取有瀏覽器發(fā)送來的cookie,需要調(diào)用HttpServletRequest的getCookies方法,這個調(diào)用返回Cookie對象的數(shù)組,對應(yīng)由HTTP請求中Cookie報頭輸入的值。
2.對數(shù)組進(jìn)行循環(huán),調(diào)用每個cookie的getName方法,直到找到感興趣的cookie為止
 cookie與你的主機(jī)(域)相關(guān),而非你的servlet或JSP頁面。因而,盡管你的servlet可能只發(fā)送了單個cookie,你也可能會得到許多不相關(guān)的cookie。
例如:
  String cookieName = “userID”;
    Cookie cookies[] = request.getCookies();
    if (cookies!=null){
        for(int i=0;i<cookies.length;i++){
    Cookie cookie = cookies[i];
    if (cookieName.equals(cookie.getName())){
        doSomethingWith(cookie.getValue());
}
}
}
*************************************************************************************

七、如何使用cookie檢測初訪者
*************************************************************************************
A.調(diào)用HttpServletRequest.getCookies()獲取Cookie數(shù)組
B.在循環(huán)中檢索指定名字的cookie是否存在以及對應(yīng)的值是否正確
C.如果是則退出循環(huán)并設(shè)置區(qū)別標(biāo)識
D.根據(jù)區(qū)別標(biāo)識判斷用戶是否為初訪者從而進(jìn)行不同的操作
*************************************************************************************

八、使用cookie檢測初訪者的常見錯誤
*************************************************************************************
不能僅僅因為cookie數(shù)組中不存在在特定的數(shù)據(jù)項就認(rèn)為用戶是個初訪者。如果cookie數(shù)組為null,客戶可能是一個初訪者,也可能是由于用戶將cookie刪除或禁用造成的結(jié)果。
但是,如果數(shù)組非null,也不過是顯示客戶曾經(jīng)到過你的網(wǎng)站或域,并不能說明他們曾經(jīng)訪問過你的servlet。其它servlet、JSP頁面以及非Java Web應(yīng)用都可以設(shè)置cookie,依據(jù)路徑的設(shè)置,其中的任何cookie都有可能返回給用戶的瀏覽器。
正確的做法是判斷cookie數(shù)組是否為空且是否存在指定的Cookie對象且值正確。
*************************************************************************************

九、使用cookie屬性的注意問題
*************************************************************************************
  屬性是從服務(wù)器發(fā)送到瀏覽器的報頭的一部分;但它們不屬于由瀏覽器返回給服務(wù)器的報頭。 
  因此除了名稱和值之外,cookie屬性只適用于從服務(wù)器輸出到客戶端的cookie;服務(wù)器端來自于瀏覽器的cookie并沒有設(shè)置這些屬性。 
  因而不要期望通過request.getCookies得到的cookie中可以使用這個屬性。這意味著,你不能僅僅通過設(shè)置cookie的最大時效,發(fā)出它,在隨后的輸入數(shù)組中查找適當(dāng)?shù)腸ookie,讀取它的值,修改它并將它存回Cookie,從而實現(xiàn)不斷改變的cookie值。
*************************************************************************************

十、如何使用cookie記錄各個用戶的訪問計數(shù)
*************************************************************************************
1.獲取cookie數(shù)組中專門用于統(tǒng)計用戶訪問次數(shù)的cookie的值
2.將值轉(zhuǎn)換成int型
3.將值加1并用原來的名稱重新創(chuàng)建一個Cookie對象
4.重新設(shè)置最大時效
5.將新的cookie輸出
*************************************************************************************

十一、session在不同環(huán)境下的不同含義
*************************************************************************************
session,中文經(jīng)常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話是從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個session。
然而當(dāng)session一詞與網(wǎng)絡(luò)協(xié)議相關(guān)聯(lián)時,它又往往隱含了“面向連接”和/或“保持狀態(tài)”這樣兩個含義。
  session在Web開發(fā)環(huán)境下的語義又有了新的擴(kuò)展,它的含義是指一類用來在客戶端與服務(wù)器端之間保持狀態(tài)的解決方案。有時候Session也用來指這種解決方案的存儲結(jié)構(gòu)。
*************************************************************************************

十二、session的機(jī)制
*************************************************************************************
  session機(jī)制是一種服務(wù)器端的機(jī)制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)(也可能就是使用散列表)來保存信息。
但程序需要為某個客戶端的請求創(chuàng)建一個session的時候,服務(wù)器首先檢查這個客戶端的請求里是否包含了一個session標(biāo)識-稱為session id,如果已經(jīng)包含一個session id則說明以前已經(jīng)為此客戶創(chuàng)建過session,服務(wù)器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個,這種情況可能出現(xiàn)在服務(wù)端已經(jīng)刪除了該用戶對應(yīng)的session對象,但用戶人為地在請求的URL后面附加上一個JSESSION的參數(shù))。
如果客戶請求不包含session id,則為此客戶創(chuàng)建一個session并且生成一個與此session相關(guān)聯(lián)的session id,這個session id將在本次響應(yīng)中返回給客戶端保存。
*************************************************************************************

十三、保存session id的幾種方式
*************************************************************************************
A.保存session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規(guī)則把這個標(biāo)識發(fā)送給服務(wù)器。
B.由于cookie可以被人為的禁止,必須有其它的機(jī)制以便在cookie被禁止時仍然能夠把session id傳遞回服務(wù)器,經(jīng)常采用的一種技術(shù)叫做URL重寫,就是把session id附加在URL路徑的后面,附加的方式也有兩種,一種是作為URL路徑的附加信息,另一種是作為查詢字符串附加在URL后面。網(wǎng)絡(luò)在整個交互過程中始終保持狀態(tài),就必須在每個客戶端可能請求的路徑后面都包含這個session id。
C.另一種技術(shù)叫做表單隱藏字段。就是服務(wù)器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務(wù)器。
*************************************************************************************

十四、session什么時候被創(chuàng)建
*************************************************************************************
一個常見的錯誤是以為session在有客戶端訪問時就被創(chuàng)建,然而事實是直到某server端程序(如Servlet)調(diào)用HttpServletRequest.getSession(true)這樣的語句時才會被創(chuàng)建。
*************************************************************************************

十五、session何時被刪除
*************************************************************************************
session在下列情況下被刪除:
A.程序調(diào)用HttpSession.invalidate()
B.距離上一次收到客戶端發(fā)送的session id時間間隔超過了session的最大有效時間
C.服務(wù)器進(jìn)程被停止

再次注意關(guān)閉瀏覽器只會使存儲在客戶端瀏覽器內(nèi)存中的session cookie失效,不會使服務(wù)器端的session對象失效。
*************************************************************************************

十六、URL重寫有什么缺點
*************************************************************************************
   對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL。每個引用你的站點的URL,以及那些返回給用戶的URL(即使通過間接手段,比如服務(wù)器重定向中的Location字段)都要添加額外的信息。
   這意味著在你的站點上不能有任何靜態(tài)的HTML頁面(至少靜態(tài)頁面中不能有任何鏈接到站點動態(tài)頁面的鏈接)。因此,每個頁面都必須使用servlet或JSP動態(tài)生成。即使所有的頁面都動態(tài)生成,如果用戶離開了會話并通過書簽或鏈接再次回來,會話的信息都會丟失,因為存儲下來的鏈接含有錯誤的標(biāo)識信息-該URL后面的SESSION ID已經(jīng)過期了。  
*************************************************************************************

十七、使用隱藏的表單域有什么缺點
*************************************************************************************
    僅當(dāng)每個頁面都是有表單提交而動態(tài)生成時,才能使用這種方法。單擊常規(guī)的<A HREF..>超文本鏈接并不產(chǎn)生表單提交,因此隱藏的表單域不能支持通常的會話跟蹤,只能用于一系列特定的操作中,比如在線商店的結(jié)賬過程
*************************************************************************************

十八、會話跟蹤的基本步驟
*************************************************************************************
1.訪問與當(dāng)前請求相關(guān)的會話對象
2.查找與會話相關(guān)的信息
3.存儲會話信息
4.廢棄會話數(shù)據(jù)
*************************************************************************************

十九、getSession()/getSession(true)、getSession(false)的區(qū)別
*************************************************************************************
getSession()/getSession(true):當(dāng)session存在時返回該session,否則新建一個session并返回該對象
getSession(false):當(dāng)session存在時返回該session,否則不會新建session,返回null
*************************************************************************************

二十、如何將信息于會話關(guān)聯(lián)起來
*************************************************************************************
  setAttribute會替換任何之前設(shè)定的值;如果想要在不提供任何代替的情況下移除某個值,則應(yīng)使用removeAttribute。這個方法會觸發(fā)所有實現(xiàn)了HttpSessionBindingListener接口的值的valueUnbound
方法。
*************************************************************************************

二十一、會話屬性的類型有什么限制嗎
*************************************************************************************
通常會話屬性的類型只要是Object就可以了。除了null或基本類型,如int,double,boolean。
如果要使用基本類型的值作為屬性,必須將其轉(zhuǎn)換為相應(yīng)的封裝類對象
*************************************************************************************

二十二、如何廢棄會話數(shù)據(jù)
*************************************************************************************
A.只移除自己編寫的servlet創(chuàng)建的數(shù)據(jù):
   調(diào)用removeAttribute(“key”)將指定鍵關(guān)聯(lián)的值廢棄
B.刪除整個會話(在當(dāng)前Web應(yīng)用中):
   調(diào)用invalidate,將整個會話廢棄掉。這樣做會丟失該用戶的所有會話數(shù)據(jù),而非僅僅由我們
servlet或JSP頁面創(chuàng)建的會話數(shù)據(jù)
C.將用戶從系統(tǒng)中注銷并刪除所有屬于他(或她)的會話
   調(diào)用logOut,將客戶從Web服務(wù)器中注銷,同時廢棄所有與該用戶相關(guān)聯(lián)的會話(每個Web應(yīng)用至多一個)。這個操作有可能影響到服務(wù)器上多個不同的Web應(yīng)用
*************************************************************************************

二十三、使用isNew來判斷用戶是否為新舊用戶的錯誤做法
*************************************************************************************
public boolean isNew()方法如果會話尚未和客戶程序(瀏覽器)發(fā)生任何聯(lián)系,則這個方法返回true,這一般是因為會話是新建的,不是由輸入的客戶請求所引起的。
但如果isNew返回false,只不過是說明他之前曾經(jīng)訪問該Web應(yīng)用,并不代表他們曾訪問過我們的servlet或JSP頁面。
因為session是與用戶相關(guān)的,在用戶之前訪問的每一個頁面都有可能創(chuàng)建了會話。因此isNew為false只能說用戶之前訪問過該Web應(yīng)用,session可以是當(dāng)前頁面創(chuàng)建,也可能是由用戶之前訪問過的頁面創(chuàng)建的。
正確的做法是判斷某個session中是否存在某個特定的key且其value是否正確
*************************************************************************************

二十四、Cookie的過期和Session的超時有什么區(qū)別
*************************************************************************************
會話的超時由服務(wù)器來維護(hù),它不同于Cookie的失效日期。首先,會話一般基于駐留內(nèi)存的cookie
不是持續(xù)性的cookie,因而也就沒有截至日期。即使截取到JSESSIONID cookie,并為它設(shè)定一個失效日期發(fā)送出去。瀏覽器會話和服務(wù)器會話也會截然不同。
*************************************************************************************

二十五、session cookie和session對象的生命周期是一樣的嗎
*************************************************************************************
當(dāng)用戶關(guān)閉了瀏覽器雖然session cookie已經(jīng)消失,但session對象仍然保存在服務(wù)器端
*************************************************************************************

二十六、是否只要關(guān)閉瀏覽器,session就消失了
*************************************************************************************
程序一般都是在用戶做log off的時候發(fā)個指令去刪除session,然而瀏覽器從來不會主動在關(guān)閉之前通知服務(wù)器它將要被關(guān)閉,因此服務(wù)器根本不會有機(jī)會知道瀏覽器已經(jīng)關(guān)閉。服務(wù)器會一直保留這個會話對象直到它處于非活動狀態(tài)超過設(shè)定的間隔為止。
之所以會有這種錯誤的認(rèn)識,是因為大部分session機(jī)制都使用會話cookie來保存session id,而關(guān)閉瀏覽器后這個session id就消失了,再次連接到服務(wù)器時也就無法找到原來的session。
如果服務(wù)器設(shè)置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發(fā)出的HTTP請求報頭,把原來的session id發(fā)送到服務(wù)器,則再次打開瀏覽器仍然能夠找到原來的session。
恰恰是由于關(guān)閉瀏覽器不會導(dǎo)致session被刪除,迫使服務(wù)器為session設(shè)置了一個失效時間,當(dāng)距離客戶上一次使用session的時間超過了這個失效時間時,服務(wù)器就可以認(rèn)為客戶端已經(jīng)停止了活動,才會把session刪除以節(jié)省存儲空間。
  由此我們可以得出如下結(jié)論:
  關(guān)閉瀏覽器,只會是瀏覽器端內(nèi)存里的session cookie消失,但不會使保存在服務(wù)器端的session對象消失,同樣也不會使已經(jīng)保存到硬盤上的持久化cookie消失。
*************************************************************************************


二十七、打開兩個瀏覽器窗口訪問應(yīng)用程序會使用同一個session還是不同的session
*************************************************************************************
通常session cookie是不能跨窗口使用的,當(dāng)你新開了一個瀏覽器窗口進(jìn)入相同頁面時,系統(tǒng)會賦予你一個新的session id,這樣我們信息共享的目的就達(dá)不到了。
此時我們可以先把session id保存在persistent cookie中(通過設(shè)置session的最大有效時間),然后在新窗口中讀出來,就可以得到上一個窗口的session id了,這樣通過session cookie和persistent cookie的結(jié)合我們就可以實現(xiàn)了跨窗口的會話跟蹤。
*************************************************************************************

二十八、如何使用會話顯示每個客戶的訪問次數(shù)
*************************************************************************************
由于客戶的訪問次數(shù)是一個整型的變量,但session的屬性類型中不能使用int,double,boolean等基本類型的變量,所以我們要用到這些基本類型的封裝類型對象作為session對象中屬性的值
  但像Integer是一種不可修改(Immutable)的數(shù)據(jù)結(jié)構(gòu):構(gòu)建后就不能更改。這意味著每個請求都必須創(chuàng)建新的Integer對象,之后使用setAttribute來代替之前存在的老的屬性的值。例如:
HttpSession session = request.getSession();
SomeImmutalbeClass value = (SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
if (value= =null){
    value = new SomeImmutableClass(…); // 新創(chuàng)建一個不可更改對象
}else{
    value = new SomeImmutableClass(calculatedFrom(value)); // 對value重新計算后創(chuàng)建新的對象
}
session.setAttribute(“someIdentifier”,value); // 使用新創(chuàng)建的對象覆蓋原來的老的對象
*************************************************************************************

二十九、如何使用會話累計用戶的數(shù)據(jù)
*************************************************************************************
使用可變的數(shù)據(jù)結(jié)構(gòu),比如數(shù)組、List、Map或含有可寫字段的應(yīng)用程序?qū)S械臄?shù)據(jù)結(jié)構(gòu)。通過這種方式,除非首次分配對象,否則不需要調(diào)用setAttribute。例如

HttpSession session = request.getSession();
SomeMutableClass value = (SomeMutableClass)session.getAttribute(“someIdentifier”);
if(value = = null){
    value = new SomeMutableClass(…);
    session.setAttribute(“someIdentifier”,value);
}else{
    value.updateInternalAttribute(…);     // 如果已經(jīng)存在該對象則更新其屬性而不需重新設(shè)置屬性
}
*************************************************************************************

三十、不可更改對象和可更改對象在會話數(shù)據(jù)更新時的不同處理
*************************************************************************************
不可更改對象因為一旦創(chuàng)建之后就不能更改,所以每次要修改會話中屬性的值的時候,都需要
調(diào)用setAttribute(“someIdentifier”,newValue)來代替原有的屬性的值,否則屬性的值不會被更新
可更改對象因為其自身一般提供了修改自身屬性的方法,所以每次要修改會話中屬性的值的時
候,只要調(diào)用該可更改對象的相關(guān)修改自身屬性的方法就可以了。這意味著我們就不需要調(diào)
用setAttribute方法了
*************************************************************************************



agun 2010-12-04 12:14 發(fā)表評論
]]>
spring 常識2http://www.tkk7.com/agun/archive/2010/12/04/339788.htmlagunagunSat, 04 Dec 2010 03:52:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339788.htmlhttp://www.tkk7.com/agun/comments/339788.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339788.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339788.htmlhttp://www.tkk7.com/agun/services/trackbacks/339788.html1, Spring bean 定義

spring bean 定義可能包含大量的配置信息,包括容器相關(guān)的信息(比如初始化方法,靜態(tài)工廠方法

等)、構(gòu)造函數(shù)參數(shù)、屬性等。如果兩個bean之間的配置信息大同小異,可采用bean的繼承來減少重

復(fù)配置工作。子bean定義可以從父bean定義繼承部分配置。它也可覆蓋一些配置,或者添加一些配置

。使用繼承配置可以節(jié)省很多輸入工作,實際上就是一種模板形式。

spring中事務(wù)配置中就有這樣例子,為了使用事務(wù)只要父配置了事務(wù)代理就可以了,所有需要事務(wù)的

bean只要繼承父就可以了。說到這個就在多說幾句,父bean通常不需要實例化的,而僅僅作為子bean

定的的模板使用;而ApplicationContext默認(rèn)預(yù)初始化所有的singleton bean。為了阻止父bean被預(yù)

初始化,可以使用abstract屬性設(shè)置父bean為抽象bean。容器會忽略所有的抽象bean定義,預(yù)初始化

時不初始化抽象bean

 

2, spring 事務(wù)管理

傳統(tǒng)的J2EE開發(fā)者對事務(wù)管理可能采用兩種策略

(1),全局事務(wù):全局事務(wù)通常由應(yīng)用服務(wù)器管理,使用JTA。全局事務(wù)可跨越多個事務(wù)性的資源,保證

在多個事務(wù)性資源間跨越時資源一致性。
(2),局部事務(wù):局部事務(wù)和特定資源相關(guān),如,一個和JDBC鏈接關(guān)聯(lián)的事務(wù)。該事務(wù)盡能保證對該

JDBC連接數(shù)據(jù)庫的一致性,對局部事務(wù),應(yīng)用服務(wù)器不需要參與事務(wù)管理,不能保證跨越多個資源的

事務(wù)正確性。

 

3,編程式事務(wù)

Spring 提供兩種編程式的事務(wù)管理

 

(1)使用TransactionTemplate事務(wù)管理

(2)直接使用一個PlatformTransactionManager實現(xiàn)類管理事務(wù)。

 

兩種編程式的事務(wù)都不需要與特定的事務(wù)API耦合,第一種更符合Spring模板式的編程模型,因此通常推薦采用第一種方式,第二種非常類似于JTA的UserTransaction的API編程,區(qū)別是減少了異常處理。

 

 

 

4,聲明式事務(wù)

Spring的聲明式事務(wù)是通過面向切面(AOP)實現(xiàn)。

(1)使用聲明式事務(wù)管理

通常,通過TransactionPoxyFactoryBean為目標(biāo)Bean生成Spring事務(wù)代理。當(dāng)bean實例的方法需要事務(wù)管理時,采用TransactionPoxyFactoryBean來自目標(biāo)bean生成事務(wù)代理。每個TransactionPoxyFactoryBean為一個具體的目標(biāo)bean生成代理對象,代理對象的方法改寫了目標(biāo)bean的方法,就是在目標(biāo)bean的方法執(zhí)行之前加入開始事務(wù),在目標(biāo)bean方法結(jié)束之后提交事務(wù),遇到指定異常回滾事務(wù)

 

    定義事務(wù)代理bean模板

Xml代碼 復(fù)制代碼
  1. <bean id="txProxyTemplate" abstract="true"  
  2.     class="<SPAN style="COLOR: #ff0000">org.springframework.transaction.interceptor.TransactionProxyFactoryBean</SPAN>">  
  3.     <property name="transactionManager">  
  4.         <ref bean="transactionManager" />  
  5.     </property>  
  6.     <property name="transactionAttributes">  
  7.         <props>  
  8.             <prop key="trans_*">PROPAGATION_REQUIRED</prop>  
  9.             <prop key="query*">  
  10.                 PROPAGATION_REQUIRED,readOnly,-Exception   
  11.             </prop>  
  12.             <prop key="find*">  
  13.                 PROPAGATION_REQUIRED,readOnly,-Exception   
  14.             </prop>  
  15.             <prop key="load*">  
  16.                 PROPAGATION_REQUIRED,readOnly,-Exception   
  17.             </prop>  
  18.             <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>  
  19.         </props>  
  20.     </property>  
  21. </bean>  

 

 

(2)根據(jù)BeanName自動創(chuàng)建事務(wù)代理

如果同一個應(yīng)用中有很多目標(biāo)bean需要生成事務(wù)代理,當(dāng)然可以為每個目標(biāo)bean額外配置一個TransactionPoxyFactoryBean bean.這樣做的缺點是,配置文件相當(dāng)臃腫而且難以維護(hù),此時可以考慮使用自動事務(wù)代理。自動事務(wù)代理的思路是,當(dāng)ApplicationContext初始化完成后,由上下文中的某個bean"后處理"每個目標(biāo)bean,為這些目標(biāo)bean生成事務(wù)代理。

能為目標(biāo)bean執(zhí)行"后處理"的bean必須實現(xiàn)BeanFactoryPostProcessor接口,ApplicationContext完成初始化后,會自動初始化所有實現(xiàn)BeanFactoryPostProcessor接口的bean,并且讓它“后處理”其他bean.Spring提供BeanFactoryPostProcessor的實現(xiàn)類BeanNameAutoPoxyCreatorBeanNameAutoPoxyCreator可以用來處理ApplicationContext中其他bean,方法是通過名稱來識別,并且把他們用事務(wù)代理包裝起來。BeanNameAutoPoxyCreator生成的事務(wù)代理,和使用TransactionPoxyFactoryBean生成的事務(wù)代理基本一致。

 

    定義事務(wù)攔截bean

Xml代碼 復(fù)制代碼
  1.  <bean id="transactionInterceptor"  
  2.   class="<SPAN style="COLOR: #ff0000">org.springframework.transaction.interceptor.TransactionInterceptor</SPAN>">  
  3.   <property name="transactionManager" ref="TransactionManager" />  
  4.      
  5.   <property name="transactionAttributes">  
  6.    <props>  
  7.     <prop key="create*">  
  8.      PROPAGATION_REQUIRED,-Exception   
  9.     </prop>  
  10.     <prop key="delete*">  
  11.      PROPAGATION_REQUIRED,-Exception   
  12.     </prop>    
  13.     <prop key="update*">  
  14.      PROPAGATION_REQUIRED,-Exception   
  15.     </prop>           
  16.     <prop key="get*">PROPAGATION_REQUIRED</prop>  
  17.    </props>  
  18.   </property>  
  19.  </bean>  
Xml代碼 復(fù)制代碼
  1.  <bean  
  2.   class="<SPAN style="COLOR: #ff0000">org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator</SPAN>">  
  3.   <property name="beanNames">  
  4.    <value>*Service</value>  
  5.   </property>  
  6.   <property name="interceptorNames">  
  7.    <list>  
  8.     <value>transactionInterceptor</value>  
  9.    </list>  
  10.   </property>  
  11.  </bean>   

 

次配置關(guān)鍵在兩個bean

TransactionInterceptor

BeanNameAutoProxyCreator

 

(3)基于注釋式事務(wù)代理配置



agun 2010-12-04 11:52 發(fā)表評論
]]>
spring 常識1http://www.tkk7.com/agun/archive/2010/12/04/339787.htmlagunagunSat, 04 Dec 2010 03:50:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339787.htmlhttp://www.tkk7.com/agun/comments/339787.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339787.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339787.htmlhttp://www.tkk7.com/agun/services/trackbacks/339787.html1,實例化bean
就Spring IoC容器而言,bean定義基本上描述了創(chuàng)建一個或多個實際bean對象的內(nèi)容。當(dāng)需要的時候,容器會從bean定義列表中取得一個指定的bean定義,并根據(jù)bean定義里面的配置元數(shù)據(jù)使用反射機(jī)制來創(chuàng)建一個實際的對象。因此這一節(jié)將講解如何告知Spring IoC容器我們將要實例化的對象的類型以及如何實例化對象。

當(dāng)采用XML描述配置元數(shù)據(jù)時,將通過<bean/>元素的class屬性來指定實例化對象的類型。class 屬性 (對應(yīng)BeanDefinition實例的Class屬性)通常是必須的(不過也有兩種例外的情形,“使用實例工廠方法實例化”和“bean定義的繼承”)。class屬性主要有兩種用途:在大多數(shù)情況下,容器將直接通過反射調(diào)用指定類的構(gòu)造器來創(chuàng)建bean(這有點等類似于在Java代碼中使用new操作符);在極少數(shù)情況下,容器將調(diào)用類的靜態(tài)工廠方法來創(chuàng)建bean實例,class屬性將用來指定實際具有靜態(tài)工廠方法的類(至于調(diào)用靜態(tài)工廠方法創(chuàng)建的對象類型是當(dāng)前class還是其他的class則無關(guān)緊要)。

2, 延遲初始化bean
ApplicationContext實現(xiàn)的默認(rèn)行為就是在啟動時將所有singleton bean提前進(jìn)行實例化。提前實例化意味著作為初始化過程的一部分,ApplicationContext實例會創(chuàng)建并配置所有的singleton bean。通常情況下這是件好事,因為這樣在配置中的任何錯誤就會即刻被發(fā)現(xiàn)(否則的話可能要花幾個小時甚至幾天)。

有時候這種默認(rèn)處理可能并不是你想要的。如果你不想讓一個singleton bean在ApplicationContext實現(xiàn)在初始化時被提前實例化,那么可以將bean設(shè)置為延遲實例化。一個延遲初始化bean將告訴IoC 容器是在啟動時還是在第一次被用到時實例化。

在XML配置文件中,延遲初始化將通過<bean/>元素中的lazy-init屬性來進(jìn)行控制。例如:

<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>
當(dāng)ApplicationContext實現(xiàn)加載上述配置時,設(shè)置為lazy的bean將不會在ApplicationContext啟動時提前被實例化,而not.lazy卻會被提前實例化。

需要說明的是,如果一個bean被設(shè)置為延遲初始化,而另一個非延遲初始化的singleton bean依賴于它,那么當(dāng)ApplicationContext提前實例化singleton bean時,它必須也確保所有上述singleton 依賴bean也被預(yù)先初始化,當(dāng)然也包括設(shè)置為延遲實例化的bean。因此,如果Ioc容器在啟動的時候創(chuàng)建了那些設(shè)置為延遲實例化的bean的實例,你也不要覺得奇怪,因為那些延遲初始化的bean可能在配置的某個地方被注入到了一個非延遲初始化singleton bean里面。

在容器層次中通過在<beans/>元素上使用'default-lazy-init'屬性來控制延遲初始化也是可能的。如下面的配置:
<beans default-lazy-init="true">
    <!-- no beans will be eagerly pre-instantiated... -->
</beans>


3,自動裝配(autowire)協(xié)作者
Spring IoC容器可以自動裝配(autowire)相互協(xié)作bean之間的關(guān)聯(lián)關(guān)系。因此,如果可能的話,可以自動讓Spring通過檢查BeanFactory中的內(nèi)容,來替我們指定bean的協(xié)作者(其他被依賴的bean)。由于autowire可以針對單個bean進(jìn)行設(shè)置,因此可以讓有些bean使用autowire,有些bean不采用。autowire的方便之處在減少或者消除屬性或構(gòu)造器參數(shù)的設(shè)置,這樣可以給我們的配置文件減減肥![2] 在xml配置文件中,autowire一共有五種類型,可以在<bean/>元素中使用autowire屬性指定:

Table 3.2. Autowiring modes

模式 說明

    no 不使用自動裝配。必須通過ref元素指定依賴,這是默認(rèn)設(shè)置。由于顯式指定協(xié)作者可以使配置更靈活、更清晰,因此對于較大的部署配置,推薦采用該設(shè)置。而且在某種程度上,它也是系統(tǒng)架構(gòu)的一種文檔形式。
 
    byName 根據(jù)屬性名自動裝配。此選項將檢查容器并根據(jù)名字查找與屬性完全一致的bean,并將其與屬性自動裝配。例如,在bean定義中將autowire設(shè)置為by name,而該bean包含master屬性(同時提供setMaster(..)方法),Spring就會查找名為master的bean定義,并用它來裝配給master屬性。
 
    byType 如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。如果存在多個該類型的bean,那么將會拋出異常,并指出不能使用byType方式進(jìn)行自動裝配。若沒有找到相匹配的bean,則什么事都不發(fā)生,屬性也不會被設(shè)置。如果你不希望這樣,那么可以通過設(shè)置dependency-check="objects"讓Spring拋出異常。
 
    constructor 與byType的方式類似,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)。如果在容器中沒有找到與構(gòu)造器參數(shù)類型一致的bean,那么將會拋出異常。
 
    autodetect 通過bean類的自省機(jī)制(introspection)來決定是使用constructor還是byType方式進(jìn)行自動裝配。如果發(fā)現(xiàn)默認(rèn)的構(gòu)造器,那么將使用byType方式。
 

如果直接使用property和constructor-arg注入依賴的話,那么將總是覆蓋自動裝配。而且目前也不支持簡單類型的自動裝配,這里所說的簡單類型包括基本類型、String、Class以及簡單類型的數(shù)組(這一點已經(jīng)被設(shè)計,將考慮作為一個功能提供)。自動裝配還可以與依賴檢查結(jié)合使用,這樣依賴檢查將在自動裝配完成之后被執(zhí)行。

理解自動裝配的優(yōu)缺點是很重要的。其中優(yōu)點包括:

自動裝配能顯著減少配置的數(shù)量。不過,采用bean模板(見這里)也可以達(dá)到同樣的目的。

自動裝配可以使配置與java代碼同步更新。例如,如果你需要給一個java類增加一個依賴,那么該依賴將被自動實現(xiàn)而不需要修改配置。因此強(qiáng)烈推薦在開發(fā)過程中采用自動裝配,而在系統(tǒng)趨于穩(wěn)定的時候改為顯式裝配的方式。

自動裝配的一些缺點:

盡管自動裝配比顯式裝配更神奇,但是,正如上面所提到的,Spring會盡量避免在裝配不明確的時候進(jìn)行猜測,因為裝配不明確可能出現(xiàn)難以預(yù)料的結(jié)果,而且Spring所管理的對象之間的關(guān)聯(lián)關(guān)系也不再能清晰的進(jìn)行文檔化。

對于那些根據(jù)Spring配置文件生成文檔的工具來說,自動裝配將會使這些工具沒法生成依賴信息。

如果采用by type方式自動裝配,那么容器中類型與自動裝配bean的屬性或者構(gòu)造函數(shù)參數(shù)類型一致的bean只能有一個,如果配置可能存在多個這樣的bean,那么就要考慮采用顯式裝配了。

盡管使用autowire沒有對錯之分,但是能在一個項目中保持一定程度的一致性是最好的做法。例如,通常情況下如果沒有使用自動裝配,那么僅自動裝配一個或兩個bean定義可能會引起開發(fā)者的混淆。



agun 2010-12-04 11:50 發(fā)表評論
]]>
Ehcache分布式緩存http://www.tkk7.com/agun/archive/2010/12/04/339786.htmlagunagunSat, 04 Dec 2010 03:49:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339786.htmlhttp://www.tkk7.com/agun/comments/339786.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339786.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339786.htmlhttp://www.tkk7.com/agun/services/trackbacks/339786.htmlEhcache分布式緩存也是我一直比較較關(guān)注的,以前用過oscache的分布式緩存。在網(wǎng)上看到了相關(guān)文章記錄下來。

 

Ehcache支持的分布式緩存支持有三種RMI,JGroups,JMS

 

這里介紹下MRI和JGrpups兩種方式,Ehcache使用版本為1.5.0,關(guān)于ehcache的其他信息請參考http://ehcache.sourceforge.net/EhcacheUserGuide.html,關(guān)于jgroups的信息請參考http://www.jgroups.org/manual/html_single/index.html

 

原始文章 http://www.javaeye.com/topic/335623



agun 2010-12-04 11:49 發(fā)表評論
]]>
Ehcache緩存配置http://www.tkk7.com/agun/archive/2010/12/04/339785.htmlagunagunSat, 04 Dec 2010 03:46:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339785.htmlhttp://www.tkk7.com/agun/comments/339785.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339785.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339785.htmlhttp://www.tkk7.com/agun/services/trackbacks/339785.html閱讀全文

agun 2010-12-04 11:46 發(fā)表評論
]]>
Web Serviceshttp://www.tkk7.com/agun/archive/2010/12/04/339784.htmlagunagunSat, 04 Dec 2010 03:45:00 GMThttp://www.tkk7.com/agun/archive/2010/12/04/339784.htmlhttp://www.tkk7.com/agun/comments/339784.htmlhttp://www.tkk7.com/agun/archive/2010/12/04/339784.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/339784.htmlhttp://www.tkk7.com/agun/services/trackbacks/339784.htmlweb 服務(wù)是通過標(biāo)準(zhǔn)的web協(xié)議可以訪問的一個應(yīng)用程序組件。

它是一種可以接收從internet 或者internet 上的其他系統(tǒng)傳遞過來的請求的輕量級獨立的通信技術(shù)。這種技術(shù)允許網(wǎng)絡(luò)上的所有系統(tǒng)進(jìn)行交互。

 

j2ee平臺是圍繞web服務(wù)來構(gòu)架的,其中的技術(shù)和web服務(wù)相關(guān)的有JAX-RCP 、Web Service、SAAJ 、JAXR 、EJB 、JAC 等,其中Web Services for J2EE 是WEB服務(wù)總框架,JAX-RCP是J2EE的WEB服務(wù)的核心技術(shù),SAAJ為處理帶附件的SOAP消息提供了JAVA編程API.

 

在J2EE平臺中,要開發(fā)WEB服務(wù)可以使用兩種技術(shù),一種基于XML遠(yuǎn)程調(diào)用的技術(shù)-JAX-RCP,另外一個基于XML的消息發(fā)送技術(shù)-JAXM.

 

這里主要針對JAX-RCP 詳細(xì)說一下。

 

JAX-RCP( JAVA API FOR XMLBASED RCP) 是一種遠(yuǎn)程方法調(diào)用(或者說遠(yuǎn)程過程調(diào)用),那么它和其他遠(yuǎn)程方法調(diào)用(RPC,COM,CORBA RMI)有什么區(qū)別呢

 

綜合比較長遠(yuǎn)的遠(yuǎn)程方法調(diào)用技術(shù),他們有以下共性。

 

1,在客戶端和服務(wù)端有通用的編程接口。

 

2,在客戶端STUB,在服務(wù)端有SKELETON.

 

3,客戶端和服務(wù)端有專門的協(xié)議進(jìn)行數(shù)據(jù)傳輸。

 

對于通用接口的描述,比如CORBA 有IDL OF CORBA ,JAVA RMI 有JAVA RMI INTERFACE IN RMI ,對于基于XML的RPC 來說,IDL 就是WSDL。那么對于XML-RPC來說,這個結(jié)構(gòu)中“傳輸協(xié)議”當(dāng)然是SAOP,SOAP消息是將以傳輸文本為基礎(chǔ)的協(xié)議(HTTP,SMTP FTP)作為載體來使用的。也就是說,SOAP消息的傳輸建立在HTTP SMTP FTP之上。

 

 JAX-RCP的客戶端調(diào)用方法:

 

1,基于STUB

2,動態(tài)代理

3,動態(tài)調(diào)用



agun 2010-12-04 11:45 發(fā)表評論
]]>
hibernate查詢(1)http://www.tkk7.com/agun/archive/2010/02/24/313818.htmlagunagunWed, 24 Feb 2010 08:56:00 GMThttp://www.tkk7.com/agun/archive/2010/02/24/313818.htmlhttp://www.tkk7.com/agun/comments/313818.htmlhttp://www.tkk7.com/agun/archive/2010/02/24/313818.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/313818.htmlhttp://www.tkk7.com/agun/services/trackbacks/313818.html相信越來越多的web開發(fā)者,在持久層都采用了hibernate。hibernate 可以大大提高開發(fā)效率,同時對應(yīng)項目的移植也有好處,但是同樣也存在問題,大家在使用hibernate的時候很少去關(guān)心效率問題,但是這個就是一個打的問題,好多項目不成功就是項目中沒有對hibernate熟悉的人,大家就是會簡單的使用,所以再有些細(xì)節(jié)上的東西我們開發(fā)人員沒有注意。

 

   就拿hibernate來說吧,他支持hql查詢,在我們組裝sql語句時,需要注意幾個問題:
   1、要查詢當(dāng)然離不開數(shù)據(jù)庫,我們建表時,默認(rèn)的主鍵都是索引,這里要注意的就是關(guān)于建立單個索引和復(fù)合索引了。

      具體的索引的hibernate中也是適用,我發(fā)現(xiàn)好多人用hibernate就很少提到索引這個概念了(用ibatis自己寫sql就會關(guān)注索引字段,這個還是可以的額)

      索引的引用規(guī)則都是適用的:
      介紹下:單個索引就是出現(xiàn)索引字段作為條件就應(yīng)用 ;
              復(fù)合索引(假設(shè)是2個字段的復(fù)合索引),出現(xiàn)復(fù)合索引的第一個字段作為條件就應(yīng)用;
              出現(xiàn)復(fù)合索引的2個字段作為條件,這應(yīng)用,如果沒有出現(xiàn)復(fù)合索引的第一個字段則不應(yīng)用;
      由此我們需要為我們的數(shù)據(jù)庫建立索引,記住復(fù)合索引是有順序的 。
     
      影響我們建立索引的條件還有就是業(yè)務(wù)(這個很重要) ,舉個例子:如果有2個查詢條件(性別、所在部門),倘若我們要建立符合索引,
      那么我們應(yīng)該將"所在部門"字段放在前面,"性別"放在后面,主要是因為,如果某個地方的查詢條件只有"所在部門",也可以起作用。另外要注意,如果查詢索引字段參與函數(shù)計算和like等,那么索引也不起作用。
  2、 在我們寫查詢代碼時,盡量對應(yīng)各個表的已經(jīng)存在索引寫查詢條件
      [第一個查詢條件盡量是單個索引,或者是復(fù)合索引的第一個字段]  。
  3、還有就是大家再拼裝查詢語句時,傳入的查詢條件值盡量不要直接寫在查詢語句中,而是要以參數(shù)的方式提供即使用綁定參數(shù)
     這樣,系統(tǒng)多次調(diào)用統(tǒng)一個查詢時(比如:select * from TestVO where code = ?   [不要寫為  select * from TestVO where code = 'aaaa']) ,
     條件值都是以參數(shù)的方式提供的,這樣,多次查詢雖然參數(shù)值不一樣,但查詢語句相同,數(shù)據(jù)庫只有第一次才對查詢語句進(jìn)行編譯,
     以后則不在編譯,所以性能會有提升。
     用參數(shù)的方式還有一個好處是:如果你不是使用
     Criteria criteria = openSession().createCriteria(**PO.class);
     criteria.add(Restrictions.like( "name",convertDBString(name) ));
     的方式,而是使用hibernate的hql的話,那么如果參數(shù)值為中文會有問題,用參數(shù)可以解決這個問題。

注: 使用綁定參數(shù)的優(yōu)勢:
  我們?yōu)槭裁匆褂媒壎麉?shù)?任何一個事物的存在都是有其價

值的,具體到綁定參數(shù)對于HQL查詢來說,主要有以下兩個主要優(yōu)勢:
  ①、 可以利用數(shù)據(jù)庫實施性能優(yōu)化,因為對Hibernate來說在底層

使用的是PrepareStatement來完成查詢,因此對于語法相同參數(shù)不同的

SQL語句,可以充分利用預(yù)編譯SQL語句緩存,從而提升查詢效率。
  ②、 可以防止SQL Injection安全漏洞的產(chǎn)生:



agun 2010-02-24 16:56 發(fā)表評論
]]>
servlet線程安全問題分析(網(wǎng)上整理)http://www.tkk7.com/agun/archive/2009/03/02/257297.htmlagunagunMon, 02 Mar 2009 02:53:00 GMThttp://www.tkk7.com/agun/archive/2009/03/02/257297.htmlhttp://www.tkk7.com/agun/comments/257297.htmlhttp://www.tkk7.com/agun/archive/2009/03/02/257297.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/257297.htmlhttp://www.tkk7.com/agun/services/trackbacks/257297.html
Servlet/JSP技術(shù)和ASP、PHP等相比,由于其多線程運行而具有很高的執(zhí)行效率。由于Servlet/JSP默認(rèn)是以多線程模式執(zhí)行的,所以,在編寫代碼時需要非常細(xì)致地考慮多線程的安全性問題。然而,很多人編寫Servlet/JSP程序時并沒有注意到多線程安全性的問題,這往往造成編寫的程序在少量用戶訪問時沒有任何問題,而在并發(fā)用戶上升到一定值時,就會經(jīng)常出現(xiàn)一些莫明其妙的問題。

  Servlet的多線程機(jī)制
 
  Servlet體系結(jié)構(gòu)是建立在Java多線程機(jī)制之上的,它的生命周期是由Web容器負(fù)責(zé)的。當(dāng)客戶端第一次請求某個Servlet時,Servlet容器將會根據(jù)web.xml配置文件實例化這個Servlet類。當(dāng)有新的客戶端請求該Servlet時,一般不會再實例化該Servlet類,也就是有多個線程在使用這個實例。Servlet容器會自動使用線程池等技術(shù)來支持系統(tǒng)的運行,如圖1所示。


圖1 Servlet線程池

  這樣,當(dāng)兩個或多個線程同時訪問同一個Servlet時,可能會發(fā)生多個線程同時訪問同一資源的情況,數(shù)據(jù)可能會變得不一致。所以在用Servlet構(gòu)建的Web應(yīng)用時如果不注意線程安全的問題,會使所寫的Servlet程序有難以發(fā)現(xiàn)的錯誤。

  Servlet的線程安全問題

  Servlet的線程安全問題主要是由于實例變量使用不當(dāng)而引起的,這里以一個現(xiàn)實的例子來說明。

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); //為了突出并發(fā)問題,在這設(shè)置一個延時
} Catch (Interrupted Exception e){}
output.println("用戶名:"+Username+"<BR>");
}
}

  該Servlet中定義了一個實例變量output,在service方法將其賦值為用戶的輸出。當(dāng)一個用戶訪問該Servlet時,程序會正常的運行,但當(dāng)多個用戶并發(fā)訪問時,就可能會出現(xiàn)其它用戶的信息顯示在另外一些用戶的瀏覽器上的問題。這是一個嚴(yán)重的問題。為了突出并發(fā)問題,便于測試、觀察,我們在回顯用戶信息時執(zhí)行了一個延時的操作。假設(shè)已在web.xml配置文件中注冊了該Servlet,現(xiàn)有兩個用戶a和b同時訪問該Servlet(可以啟動兩個IE瀏覽器,或者在兩臺機(jī)器上同時訪問),即同時在瀏覽器中輸入:

  a: http://localhost: 8080/servlet/ConcurrentTest? Username=a

  b: http://localhost: 8080/servlet/ConcurrentTest? Username=b

  如果用戶b比用戶a回車的時間稍慢一點,將得到如圖2所示的輸出:


圖2 a用戶和b用戶的瀏覽器輸出

  從圖2中可以看到,Web服務(wù)器啟動了兩個線程分別處理來自用戶a和用戶b的請求,但是在用戶a的瀏覽器上卻得到一個空白的屏幕,用戶a的信息顯示在用戶b的瀏覽器上。該Servlet存在線程不安全問題。下面我們就從分析該實例的內(nèi)存模型入手,觀察不同時刻實例變量output的值來分析使該Servlet線程不安全的原因。

  Java的內(nèi)存模型JMM(Java Memory Model)JMM主要是為了規(guī)定了線程和內(nèi)存之間的一些關(guān)系。根據(jù)JMM的設(shè)計,系統(tǒng)存在一個主內(nèi)存(Main Memory),Java中所有實例變量都儲存在主存中,對于所有線程都是共享的。每條線程都有自己的工作內(nèi)存(Working Memory),工作內(nèi)存由緩存和堆棧兩部分組成,緩存中保存的是主存中變量的拷貝,緩存可能并不總和主存同步,也就是緩存中變量的修改可能沒有立刻寫到主存中;堆棧中保存的是線程的局部變量,線程之間無法相互直接訪問堆棧中的變量。根據(jù)JMM,我們可以將論文中所討論的Servlet實例的內(nèi)存模型抽象為圖3所示的模型。


圖3 Servlet實例的JMM模型

  下面根據(jù)圖3所示的內(nèi)存模型,來分析當(dāng)用戶a和b的線程(簡稱為a線程、b線程)并發(fā)執(zhí)行時,Servlet實例中所涉及變量的變化情況及線程的執(zhí)行情況,如圖4所示。

調(diào)度時刻 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線程終止。
                  圖4 Servlet實例的線程調(diào)度情況

  從圖4中可以清楚的看到,由于b線程對實例變量output的修改覆蓋了a線程對實例變量output的修改,從而導(dǎo)致了用戶a的信息顯示在了用戶b的瀏覽器上。如果在a線程執(zhí)行輸出語句時,b線程對output的修改還沒有刷新到主存,那么將不會出現(xiàn)圖2所示的輸出結(jié)果,因此這只是一種偶然現(xiàn)象,但這更增加了程序潛在的危險性。
設(shè)計線程安全的Servlet

  通過上面的分析,我們知道了實例變量不正確的使用是造成Servlet線程不安全的主要原因。下面針對該問題給出了三種解決方案并對方案的選取給出了一些參考性的建議。

  1、實現(xiàn) SingleThreadModel 接口

  該接口指定了系統(tǒng)如何處理對同一個Servlet的調(diào)用。如果一個Servlet被這個接口指定,那么在這個Servlet中的service方法將不會有兩個線程被同時執(zhí)行,當(dāng)然也就不存在線程安全的問題。這種方法只要將前面的Concurrent Test類的類頭定義更改為:

Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
…………
}

  2、同步對共享數(shù)據(jù)的操作

  使用synchronized 關(guān)鍵字能保證一次只有一個線程可以訪問被保護(hù)的區(qū)段,在本論文中的Servlet可以通過同步塊操作來保證線程的安全。同步后的代碼如下:

…………
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>");
}
}
}

  3、避免使用實例變量

  本實例中的線程安全問題是由實例變量造成的,只要在Servlet里面的任何方法里面都不使用實例變量,那么該Servlet就是線程安全的。

  修正上面的Servlet代碼,將實例變量改為局部變量實現(xiàn)同樣的功能,代碼如下:

……
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");
……
}
}

  對上面的三種方法進(jìn)行測試,可以表明用它們都能設(shè)計出線程安全的Servlet程序。但是,如果一個Servlet實現(xiàn)了SingleThreadModel接口,Servlet引擎將為每個新的請求創(chuàng)建一個單獨的Servlet實例,這將引起大量的系統(tǒng)開銷。SingleThreadModel在Servlet2.4中已不再提倡使用;同樣如果在程序中使用同步來保護(hù)要使用的共享的數(shù)據(jù),也會使系統(tǒng)的性能大大下降。這是因為被同步的代碼塊在同一時刻只能有一個線程執(zhí)行它,使得其同時處理客戶請求的吞吐量降低,而且很多客戶處于阻塞狀態(tài)。另外為保證主存內(nèi)容和線程的工作內(nèi)存中的數(shù)據(jù)的一致性,要頻繁地刷新緩存,這也會大大地影響系統(tǒng)的性能。所以在實際的開發(fā)中也應(yīng)避免或最小化 Servlet 中的同步代碼;在Serlet中避免使用實例變量是保證Servlet線程安全的最佳選擇。從Java 內(nèi)存模型也可以知道,方法中的臨時變量是在棧上分配空間,而且每個線程都有自己私有的棧空間,所以它們不會影響線程的安全。

  小結(jié)

  Servlet的線程安全問題只有在大量的并發(fā)訪問時才會顯現(xiàn)出來,并且很難發(fā)現(xiàn),因此在編寫Servlet程序時要特別注意。線程安全問題主要是由實例變量造成的,因此在Servlet中應(yīng)避免使用實例變量。如果應(yīng)用程序設(shè)計無法避免使用實例變量,那么使用同步來保護(hù)要使用的實例變量,但為保證系統(tǒng)的最佳性能,應(yīng)該同步可用性最小的代碼路徑。
同時因為struts也是通過servlet來實現(xiàn)的,因為Struts的Action被設(shè)計為線程不安全的,所以也涉及到這個問題,所以也使用同樣的方法來解決!

agun 2009-03-02 10:53 發(fā)表評論
]]>
有關(guān)web效率http://www.tkk7.com/agun/archive/2008/03/18/186927.htmlagunagunTue, 18 Mar 2008 02:10:00 GMThttp://www.tkk7.com/agun/archive/2008/03/18/186927.htmlhttp://www.tkk7.com/agun/comments/186927.htmlhttp://www.tkk7.com/agun/archive/2008/03/18/186927.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/186927.htmlhttp://www.tkk7.com/agun/services/trackbacks/186927.html1)web開發(fā)的特點是是:沒有太復(fù)雜的技術(shù)難點,一切在于迅速的把握需求,其實這正式敏捷開發(fā)的要旨所在,一切都可以非常快速的建立,非常快速的重構(gòu),我們的開發(fā)工具,底層庫和框架,包括搜索引擎和web文檔提供的幫助,都提我們供給了敏捷的能力。

2)此外,相應(yīng)的,最有效率的交流方式必須留給web開發(fā),那就是face2face(面對面),不要太擔(dān)心你的設(shè)計不能被完備的文檔所保留下來,他們會以交流,代碼和小卡片的方式保存下來

3)人的因素會更加重要,無論是對用戶的需求,還是開發(fā)人員的素質(zhì)。

另:有關(guān)web效率,有著名的14條規(guī)則,由yahoo性能效率小組所總結(jié),并廣為流傳。業(yè)已出現(xiàn)相關(guān)插件(YSlow),14 rules列在下面:

1. Make Fewer HTTP Requests

減少http請求次數(shù)

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

3. Add an Expires Header

在下載的cssjsimage組件里增加過期時間

4. Gzip Components

(對下載的組件進(jìn)行壓縮)

毫無疑問,對站點內(nèi)容進(jìn)行壓縮是一個比較常用的 Web 優(yōu)化手段.但是并不一定都能達(dá)到理想的效果.原因在于 mod-gzip 模塊不但消耗服務(wù)器端 CPU資源,也消耗客戶端 CPU資源. 而且, mod_gzip 壓縮文件后創(chuàng)建的臨時文件是放到磁盤上的,這也會給磁盤 IO帶來嚴(yán)重的問題.

Flickr 采用的是 Httpd 2.x 以后支持的 mod_deflate 模塊.壓縮操作都在內(nèi)存中進(jìn)行.mod_deflate Httpd 1.x 是不可用的, 不過可以通過創(chuàng)建 RAM盤的方式來間接提高性能.

當(dāng)然, mod_gzip 到也不是一無是處, 對于預(yù)壓縮的文件, 還是有好處的. 而且, 采用壓縮的時候,也要注意策略. 圖片文件壓縮就沒什么必要了(Flickr 上圖像多, 而且壓縮得不到什么好處). Flickr 只對JavaScript CSS進(jìn)行壓縮. mod_gzip 新一點的版本能夠自動通過配置 mod_gzip_update_static 選項自動處理預(yù)壓縮的文件. Cal 也指出這個特性在一些舊版本的瀏覽器上會出問題.

壓縮的另一個主要手段是內(nèi)容的壓縮. 針對 JavaScript 可以進(jìn)行通過減少注釋、合并空格、使用緊湊的語法等小技巧(Google 的所有腳本都非常難讀,而且非常緊湊,思想類似).當(dāng)然,經(jīng)過這樣處理的 JavaScript 可能帶了很多括號不容易解析,Flickr 使用了 Dojo Compressor 來構(gòu)建解析樹。Dojo Compressor 開銷很低,而且對于最終用戶是透明的. JavaScript 的處理方法介紹過,CSS 處理則相對簡單.通過簡單的正則表達(dá)式替換(比如把多個空格替換為一個空格符), 最高可以獲得 50% 的壓縮比。

5. Put CSS at the Top

css文件盡可能放在頁面的最上面

· Move Scripts to the Bottom

js文件盡可能放在頁面的最下面

6Put JS components as close to the bottom of the page as possible.

js文件盡可能放在頁面的最下面)

7Avoid CSS Expressions

(在css文件中慎用表達(dá)式)

8Make JavaScript and CSS External

(在外部包含jscss文件)

9Reduce DNS Lookups

(減少請求中域名的解析次數(shù))

10Minify JavaScript

js代碼壓縮)

11Avoid doing redirects.

(避免重定向)

12Remove Duplicates Scripts

(避免請求重復(fù)的js文件)

13Configure ETags

(配置好ETag

Flickr 的開發(fā)者充分利用了 Http 1.1 規(guī)范定義的 Etag 與 Last-Modified 機(jī)制 來提高 Caching 的效率. 值得注意的是,Cal 介紹了一個在負(fù)載均衡條件下的 e-Tag 小技巧. 即可以設(shè)定 Apache 通過文件調(diào)整時間與文件大小獲得 E-Tag ,而默認(rèn)情況下, Apache 是通過文件節(jié)點獲取 e-Tag 的。當(dāng)然,這也不是很完美,因為會影響 if-modified-since

但是有的網(wǎng)站的e-Tag,如yahoo,其產(chǎn)生規(guī)則是基于節(jié)點的。相同的cssjs腳本在不同節(jié)點服務(wù)器上的e-Tag不同,所以如果有n個服務(wù)器,那么瀏覽器獲得304應(yīng)答消息的概率是1/n

14Make Ajax Cacheable

(緩存Ajax請求)

以下幾點是新增的準(zhǔn)則,還沒有正式公布,所以大家要注意,

15Flush the Header

(先發(fā)送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.

16Split Static Content Across Multiple Hostnames

(把較大的靜態(tài)文件分割成不同域的請求)

If you have many (10 or more) components downloaded from a single hostname, it might be better to split those across two hostnames.

17Reduce the Size of Cookies

(不要讓Cookie內(nèi)容過大)

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.

18Host Static Content on a Different Top-Level Domain

(把靜態(tài)文件放在不同的頂級域名下)

19Minify CSS

Css代碼壓縮)

20Use 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

21Avoid IFrames

(盡量避免使用IFrame

Don’t use SRC (set it via JS instead). Each IFrame takes 20-50ms, even if it contains nothing

22Optimize images

(優(yōu)化圖片)



agun 2008-03-18 10:10 發(fā)表評論
]]>
quartz在spring中的使用http://www.tkk7.com/agun/archive/2008/03/17/186689.htmlagunagunMon, 17 Mar 2008 01:29:00 GMThttp://www.tkk7.com/agun/archive/2008/03/17/186689.htmlhttp://www.tkk7.com/agun/comments/186689.htmlhttp://www.tkk7.com/agun/archive/2008/03/17/186689.html#Feedback1http://www.tkk7.com/agun/comments/commentRss/186689.htmlhttp://www.tkk7.com/agun/services/trackbacks/186689.html(1)在spring 中的配置bean

(1)在spring 中的配置bean
<bean id="methodInvokingJobDetail"
    class
="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    
<property name="targetObject">
        
<ref bean="quartzTest" />--指定請求的bean的對象
    
</property>
    
<property name="targetMethod">
        
<value>quartzTimer</value>--指定對象中的方法
    
</property>
</bean>
<bean id="cronTrigger"
    class
="org.springframework.scheduling.quartz.CronTriggerBean">
    
<property name="jobDetail">
        
<ref bean="methodInvokingJobDetail" />
    
</property>
    
<property name="cronExpression">
        
<value>0 25 17,12,20 * * ?</value>--定時控制操作
    
</property>
</bean>
<bean
    
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    
<property name="triggers">
        
<list>
            
<ref local="cronTrigger" />
        
</list>
    
</property>
</bean>

 

(2)定時控制--定時的格式(網(wǎng)上總結(jié))

一個Cron-表達(dá)式是一個由六至七個字段組成由空格分隔的字符串,其中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   , - * /

 '*' 字符可以用于所有字段,在“分”字段中設(shè)為"*"表示"每一分鐘"的含義。

'?' 字符可以用在“日”和“周幾”字段. 它用來指定 '不明確的值'. 這在你需要指定這兩個字段中的某一個值而不是另外一個的時候會被用到。在后面的例子中可以看到其含義。

'-' 字符被用來指定一個值的范圍,比如在“小時”字段中設(shè)為"10-12"表示"10點到12點".

 ',' 字符指定數(shù)個值。比如在“周幾”字段中設(shè)為"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".

'/' 字符用來指定一個值的的增加幅度. 比如在“秒”字段中設(shè)置為"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"則表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相當(dāng)于指定從0秒開始. 每個字段都有一系列可以開始或結(jié)束的數(shù)值。對于“秒”和“分”字段來說,其數(shù)值范圍為0到59,對于“小時”字段來說其為0到23, 對于“日”字段來說為0到31, 而對于“月”字段來說為1到12。"/"字段僅僅只是幫助你在允許的數(shù)值范圍內(nèi)從開始"第n"的值。 因此 對于“月”字段來說"7/6"只是表示7月被開啟而不是“每六個月”, 請注意其中微妙的差別。

'L'字符可用在“日”和“周幾”這兩個字段。它是"last"的縮寫, 但是在這兩個字段中有不同的含義。例如,“日”字段中的"L"表示"一個月中的最后一天" —— 對于一月就是31號對于二月來說就是28號(非閏年)。而在“周幾”字段中, 它簡單的表示"7" or "SAT",但是如果在“周幾”字段中使用時跟在某個數(shù)字之后, 它表示"該月最后一個星期×" —— 比如"6L"表示"該月最后一個周五"。當(dāng)使用'L'選項時,指定確定的列表或者范圍非常重要,否則你會被結(jié)果搞糊涂的。

'W' 可用于“日”字段。用來指定歷給定日期最近的工作日(周一到周五) 。比如你將“日”字段設(shè)為"15W",意為: "離該月15號最近的工作日"。因此如果15號為周六,觸發(fā)器會在14號即周五調(diào)用。如果15號為周日, 觸發(fā)器會在16號也就是周一觸發(fā)。如果15號為周二,那么當(dāng)天就會觸發(fā)。然而如果你將“日”字段設(shè)為"1W", 而一號又是周六, 觸發(fā)器會于下周一也就是當(dāng)月的3號觸發(fā),因為它不會越過當(dāng)月的值的范圍邊界。'W'字符只能用于“日”字段的值為單獨的一天而不是一系列值的時候。

'L'和'W'可以組合用于“日”字段表示為'LW',意為"該月最后一個工作日"。

'#' 字符可用于“周幾”字段。該字符表示“該月第幾個周×”,比如"6#3"表示該月第三個周五( 6表示周五而"#3"該月第三個)。再比如: "2#1" = 表示該月第一個周一而 "4#5" = 該月第五個周三。注意如果你指定"#5"該月沒有第五個“周×”,該月是不會觸發(fā)的。

'C' 字符可用于“日”和“周幾”字段,它是"calendar"的縮寫。 它表示為基于相關(guān)的日歷所計算出的值(如果有的話)。如果沒有關(guān)聯(lián)的日歷, 那它等同于包含全部日歷。“日”字段值為"5C"表示"日歷中的第一天或者5號以后",“周幾”字段值為"1C"則表示"日歷中的第一天或者周日以后"。

對于“月份”字段和“周幾”字段來說合法的字符都不是大小寫敏感的。

下面是一些完整的例子:
表達(dá)式   含義
"0 0 12 * * ?"   每天中午十二點觸發(fā)
"0 15 10 ? * *"   每天早上10:15觸發(fā)
"0 15 10 * * ?"   每天早上10:15觸發(fā)
"0 15 10 * * ? *"   每天早上10:15觸發(fā)
"0 15 10 * * ? 2005"   2005年的每天早上10:15觸發(fā)
"0 * 14 * * ?"   每天從下午2點開始到2點59分每分鐘一次觸發(fā)
"0 0/5 14 * * ?"   每天從下午2點開始到2:55分結(jié)束每5分鐘一次觸發(fā)
"0 0/5 14,18 * * ?"   每天的下午2點至2:55和6點至6點55分兩個時間段內(nèi)每5分鐘一次觸發(fā)
"0 0-5 14 * * ?"   每天14:00至14:05每分鐘一次觸發(fā)
"0 10,44 14 ? 3 WED"   三月的每周三的14:10和14:44觸發(fā)
"0 15 10 ? * MON-FRI"   每個周一、周二、周三、周四、周五的10:15觸發(fā)
"0 15 10 15 * ?"   每月15號的10:15觸發(fā)
"0 15 10 L * ?"   每月的最后一天的10:15觸發(fā)
"0 15 10 ? * 6L"   每月最后一個周五的10:15觸發(fā)
"0 15 10 ? * 6L"   每月最后一個周五的10:15觸發(fā)
"0 15 10 ? * 6L 2002-2005"   2002年至2005年的每月最后一個周五的10:15觸發(fā)
"0 15 10 ? * 6#3"   每月的第三個周五的10:15觸發(fā)



agun 2008-03-17 09:29 發(fā)表評論
]]>
spring ApplicationContext簡單研究http://www.tkk7.com/agun/archive/2008/03/11/185269.htmlagunagunTue, 11 Mar 2008 01:57:00 GMThttp://www.tkk7.com/agun/archive/2008/03/11/185269.htmlhttp://www.tkk7.com/agun/comments/185269.htmlhttp://www.tkk7.com/agun/archive/2008/03/11/185269.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/185269.htmlhttp://www.tkk7.com/agun/services/trackbacks/185269.htmlspring 研究裝載配置文件

1,研究spring webApplicationContext初始化。spring 如何初始化。
spring 有兩種方法,一個是ContextLoaderListener這個Listerner,另一個是ContextLoaderServlet這個Servlet,這兩個方法都是在web應(yīng)用啟動的時候來初始化WebApplicationContext,ContextLoader是一個工具類,用來初始化WebApplicationContext,其主要方法就是initWebApplicationContext,ContextLoader是把WebApplicationContext(XmlWebApplicationContext是默認(rèn)實現(xiàn)類)放在了ServletContext中,ServletContext也是一個“容器”,也是一個類似Map的結(jié)構(gòu),而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,我們?nèi)绻褂肳ebApplicationContext則需要從ServletContext取出,Spring提供了一WebApplicationContextUtils類,可以方便的取出WebApplicationContext,只要把ServletContext傳入就可以了。

2,研究通過使用ApplicationContext對spring 進(jìn)行初始化。

初始化流程,在初始化的時候,新增一個加載servlet ,這個serlvet負(fù)責(zé)初始化。AppContextLoader 提供了初始化applicationContext的方法,
通過定義ClassPathXmlApplicationContext 來加載spring 配置文件。裝載配置文件。
并把裝載的ApplicationContext文件放在servletContext中作為全局變量來使用。在使用ClassPathXmlApplicationContext 則需要從ServletContext取出.



agun 2008-03-11 09:57 發(fā)表評論
]]>
httpclient (2)http://www.tkk7.com/agun/archive/2008/01/29/178365.htmlagunagunTue, 29 Jan 2008 06:55:00 GMThttp://www.tkk7.com/agun/archive/2008/01/29/178365.htmlhttp://www.tkk7.com/agun/comments/178365.htmlhttp://www.tkk7.com/agun/archive/2008/01/29/178365.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/178365.htmlhttp://www.tkk7.com/agun/services/trackbacks/178365.html根據(jù)以上步驟,我們來編寫用GET方法來取得某網(wǎng)頁內(nèi)容的代碼。

  • 大部分情況下 HttpClient 默認(rèn)的構(gòu)造函數(shù)已經(jīng)足夠使用。
    HttpClient httpClient = new HttpClient();
                    

  • 創(chuàng)建GET方法的實例。在GET方法的構(gòu)造函數(shù)中傳入待連接的地址即可。用GetMethod將會自動處理轉(zhuǎn)發(fā)過程,如果想要把自動處理轉(zhuǎn)發(fā)過程去掉的話,可以調(diào)用方法setFollowRedirects(false)。
    GetMethod getMethod = new GetMethod("http://www.ibm.com/");
                    

  • 調(diào)用實例httpClient的executeMethod方法來執(zhí)行g(shù)etMethod。由于是執(zhí)行在網(wǎng)絡(luò)上的程序,在運行executeMethod方法的時候,需要處理兩個異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是在構(gòu)造getMethod的時候傳入的協(xié)議不對,比如不小心將"http"寫成"htp",或者服務(wù)器端返回的內(nèi)容不正常等,并且該異常發(fā)生是不可恢復(fù)的;第二種異常一般是由于網(wǎng)絡(luò)原因引起的異常,對于這種異常 (IOException),HttpClient會根據(jù)你指定的恢復(fù)策略自動試著重新執(zhí)行executeMethod方法。HttpClient的恢復(fù)策略可以自定義(通過實現(xiàn)接口HttpMethodRetryHandler來實現(xiàn))。通過httpClient的方法setParameter設(shè)置你實現(xiàn)的恢復(fù)策略,本文中使用的是系統(tǒng)提供的默認(rèn)恢復(fù)策略,該策略在碰到第二類異常的時候?qū)⒆詣又卦?次。executeMethod返回值是一個整數(shù),表示了執(zhí)行該方法后服務(wù)器返回的狀態(tài)碼,該狀態(tài)碼能表示出該方法執(zhí)行是否成功、需要認(rèn)證或者頁面發(fā)生了跳轉(zhuǎn)(默認(rèn)狀態(tài)下GetMethod的實例是自動處理跳轉(zhuǎn)的)等。
    //設(shè)置成了默認(rèn)的恢復(fù)策略,在發(fā)生異常時候?qū)⒆詣又卦?次,在這里你也可以設(shè)置成自定義的恢復(fù)策略
                    getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                    new DefaultHttpMethodRetryHandler());
                    //執(zhí)行g(shù)etMethod
                    int statusCode = client.executeMethod(getMethod);
                    if (statusCode != HttpStatus.SC_OK) {
                    System.err.println("Method failed: " + getMethod.getStatusLine());
                    }
                    

  • 在返回的狀態(tài)碼正確后,即可取得內(nèi)容。取得目標(biāo)地址的內(nèi)容有三種方法:第一種,getResponseBody,該方法返回的是目標(biāo)的二進(jìn)制的byte流;第二種,getResponseBodyAsString,這個方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據(jù)系統(tǒng)默認(rèn)的編碼方式,所以返回的String值可能編碼類型有誤,在本文的"字符編碼"部分中將對此做詳細(xì)介紹;第三種,getResponseBodyAsStream,這個方法對于目標(biāo)地址中有大量數(shù)據(jù)需要傳輸是最佳的。在這里我們使用了最簡單的getResponseBody方法。
    byte[] responseBody = method.getResponseBody();
                    

  • 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接。
    method.releaseConnection();
                    

  • 處理內(nèi)容。在這一步中根據(jù)你的需要處理內(nèi)容,在例子中只是簡單的將內(nèi)容打印到控制臺。
    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) {
            //構(gòu)造HttpClient的實例
            HttpClient httpClient = new HttpClient();
            //創(chuàng)建GET方法的實例
            GetMethod getMethod = new GetMethod("http://www.ibm.com");
            //使用系統(tǒng)提供的默認(rèn)的恢復(fù)策略
            getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
            new DefaultHttpMethodRetryHandler());
            try {
            //執(zhí)行g(shù)etMethod
            int statusCode = httpClient.executeMethod(getMethod);
            if (statusCode != HttpStatus.SC_OK) {
            System.err.println("Method failed: "
            + getMethod.getStatusLine());
            }
            //讀取內(nèi)容
            byte[] responseBody = getMethod.getResponseBody();
            //處理內(nèi)容
            System.out.println(new String(responseBody));
            } catch (HttpException e) {
            //發(fā)生致命的異常,可能是協(xié)議不對或者返回的內(nèi)容有問題
            System.out.println("Please check your provided http address!");
            e.printStackTrace();
            } catch (IOException e) {
            //發(fā)生網(wǎng)絡(luò)異常
            e.printStackTrace();
            } finally {
            //釋放連接
            getMethod.releaseConnection();
            }
            }
            }
            

POST方法

根據(jù)RFC2616,對POST的解釋如下:POST方法用來向目的服務(wù)器發(fā)出請求,要求它接受被附在請求后的實體,并把它當(dāng)作請求隊列(Request-Line)中請求URI所指定資源的附加新子項。POST被設(shè)計成用統(tǒng)一的方法實現(xiàn)下列功能:

  • 對現(xiàn)有資源的注釋(Annotation of existing resources)
  • 向電子公告欄、新聞組,郵件列表或類似討論組發(fā)送消息
  • 提交數(shù)據(jù)塊,如將表單的結(jié)果提交給數(shù)據(jù)處理過程
  • 通過附加操作來擴(kuò)展數(shù)據(jù)庫

調(diào)用HttpClient中的PostMethod與GetMethod類似,除了設(shè)置PostMethod的實例與GetMethod有些不同之外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不同的地方,并以登錄清華大學(xué)BBS為例子進(jìn)行說明。

  • 構(gòu)造PostMethod之前的步驟都相同,與GetMethod一樣,構(gòu)造PostMethod也需要一個URI參數(shù),在本例中,登錄的地址是http://www.newsmth.net/bbslogin2.php。在創(chuàng)建了PostMethod的實例之后,需要給method實例填充表單的值,在BBS的登錄表單中需要有兩個域,第一個是用戶名(域名叫id),第二個是密碼(域名叫passwd)。表單中的域用類NameValuePair來表示,該類的構(gòu)造函數(shù)第一個參數(shù)是域名,第二參數(shù)是該域的值;將表單所有的值設(shè)置到PostMethod中用方法setRequestBody。另外由于BBS登錄成功后會轉(zhuǎn)向另外一個頁面,但是HttpClient對于要求接受后繼服務(wù)的請求,比如POST和PUT,不支持自動轉(zhuǎn)發(fā),因此需要自己對頁面轉(zhuǎn)向做處理。具體的頁面轉(zhuǎn)向處理請參見下面的"自動轉(zhuǎn)向"部分。代碼如下:
    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);
                    // 執(zhí)行postMethod
                    int statusCode = httpClient.executeMethod(postMethod);
                    // HttpClient對于要求接受后繼服務(wù)的請求,象POST和PUT等不能自動處理轉(zhuǎn)發(fā)
                    // 301或者302
                    if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
                    statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                    // 從頭中取出轉(zhuǎn)向的地址
                    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;
                    }
                    



agun 2008-01-29 14:55 發(fā)表評論
]]>
httpclient (1) http://www.tkk7.com/agun/archive/2008/01/29/178362.htmlagunagunTue, 29 Jan 2008 06:50:00 GMThttp://www.tkk7.com/agun/archive/2008/01/29/178362.htmlhttp://www.tkk7.com/agun/comments/178362.htmlhttp://www.tkk7.com/agun/archive/2008/01/29/178362.html#Feedback0http://www.tkk7.com/agun/comments/commentRss/178362.htmlhttp://www.tkk7.com/agun/services/trackbacks/178362.html

最近用到了HttpClient ,搜集的資料:

HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。本文首先介紹 HTTPClient,然后根據(jù)作者實際工作經(jīng)驗給出了一些常見問題的解決方法。

HttpClient簡介

HTTP 協(xié)議可能是現(xiàn)在 Internet 上使用得最多、最重要的協(xié)議了,越來越多的 Java 應(yīng)用程序需要直接通過 HTTP 協(xié)議來訪問網(wǎng)絡(luò)資源。雖然在 JDK 的 java.net 包中已經(jīng)提供了訪問 HTTP 協(xié)議的基本功能,但是對于大部分應(yīng)用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。HttpClient 已經(jīng)應(yīng)用在很多的項目中,比如 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient,更多使用 HttpClient 的應(yīng)用可以參見http://wiki.apache.org/jakarta-httpclient/HttpClientPowered。HttpClient 項目非常活躍,使用的人還是非常多的。目前 HttpClient 版本是在 2005.10.11 發(fā)布的 3.0 RC4 。




HttpClient 功能介紹

以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細(xì)的功能可以參見 HttpClient 的主頁。

  • 實現(xiàn)了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
  • 支持自動轉(zhuǎn)向
  • 支持 HTTPS 協(xié)議
  • 支持代理服務(wù)器等

下面將逐一介紹怎樣使用這些功能。首先,我們必須安裝好 HttpClient。




HttpClient 基本功能的使用

GET 方法

使用 HttpClient 需要以下 6 個步驟:

1. 創(chuàng)建 HttpClient 的實例

2. 創(chuàng)建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構(gòu)造函數(shù)中傳入待連接的地址

3. 調(diào)用第一步中創(chuàng)建好的實例的 execute 方法來執(zhí)行第二步中創(chuàng)建好的 method 實例

4. 讀 response

5. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接

6. 對得到后的內(nèi)容進(jìn)行處理



agun 2008-01-29 14:50 發(fā)表評論
]]>
主站蜘蛛池模板: 亚洲影院天堂中文av色| 久久久久久久久久免免费精品 | 91嫩草私人成人亚洲影院| 自拍偷自拍亚洲精品偷一| 24小时在线免费视频| 国产精品亚洲高清一区二区| 亚洲 欧洲 自拍 另类 校园| 国产一区二区免费| 亚洲高清视频一视频二视频三| 亚洲乱码卡三乱码新区| 久久国产精品国产自线拍免费| 午夜国产大片免费观看| 国产精品亚洲片夜色在线| 在线观看免费av网站| 国产亚洲欧洲Aⅴ综合一区| 国产精品亚洲色婷婷99久久精品| 日本XXX黄区免费看| 亚洲高清视频在线观看| 久久不见久久见免费影院www日本| 国产a级特黄的片子视频免费| 亚洲一区无码中文字幕乱码| 久久久久国产精品免费网站| 国产偷国产偷亚洲清高动态图 | 亚洲视频在线免费观看| 国产日韩久久免费影院 | 久久成人国产精品免费软件| 亚洲av综合avav中文| 一个人看的www免费在线视频| 日本一道一区二区免费看| 亚洲六月丁香婷婷综合| 免费看片在线观看| 亚洲黄色免费观看| 99视频免费播放| 久久精品国产亚洲AV麻豆不卡| 国产乱妇高清无乱码免费| 2022中文字字幕久亚洲| 成人免费网站久久久| 全亚洲最新黄色特级网站 | 国产成人午夜精品免费视频| 亚洲精品国产手机| 24小时日本韩国高清免费|