国产激情91久久精品导航,精品免费视频一区二区,欧美日韩视频在线第一区http://www.aygfsteel.com/agun/category/30011.html激情成就夢想,努力創造未來zh-cnSat, 03 Nov 2012 20:44:16 GMTSat, 03 Nov 2012 20:44:16 GMT60java web 導出excel http://www.aygfsteel.com/agun/archive/2012/11/03/390722.htmlagunagunSat, 03 Nov 2012 04:45:00 GMThttp://www.aygfsteel.com/agun/archive/2012/11/03/390722.htmlhttp://www.aygfsteel.com/agun/comments/390722.htmlhttp://www.aygfsteel.com/agun/archive/2012/11/03/390722.html#Feedback0http://www.aygfsteel.com/agun/comments/commentRss/390722.htmlhttp://www.aygfsteel.com/agun/services/trackbacks/390722.html看到這個標題,會很疑問,java導出excel 有很多文章呀,都知道怎么用呀,呵呵,我也是這么認為,我們常用的就是jxl 或者poi ,現在jxl 代碼不在更新不支持2007,一般都采用poi 進行excel的操作,今天在看系統(架構struts+ spring+ hibernate),需要做一個excel導出,一個簡單的方法,這個方法只適用于excel簡單的導出,直接通過輸出的頁面,然后設置頁面為輸出流的文件格式,這樣當action轉向到jsp頁面的時候,直接就是將頁面輸出。

 

jsp頁面的代碼:

Java代碼 復制代碼
  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>主機名</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">標題</td>   
  31.                                     <td align="center">擴展信息</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 發表評論
]]>
list合并單元格http://www.aygfsteel.com/agun/archive/2011/10/17/361437.htmlagunagunMon, 17 Oct 2011 06:44:00 GMThttp://www.aygfsteel.com/agun/archive/2011/10/17/361437.htmlhttp://www.aygfsteel.com/agun/comments/361437.htmlhttp://www.aygfsteel.com/agun/archive/2011/10/17/361437.html#Feedback0http://www.aygfsteel.com/agun/comments/commentRss/361437.htmlhttp://www.aygfsteel.com/agun/services/trackbacks/361437.html

1,在今天整理代碼的時候,發現原來的一段代碼,前臺合并單元格。

 

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

Java代碼 復制代碼
  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代碼 復制代碼
  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>  

 

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



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

Xml代碼 復制代碼
  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 關閉,不起作用,最后查了一下,我把這個filter放到了struts的filter之上,就可以了。

 

 

說明FlushMode有五種屬性

1 NEVEL  

已經廢棄了,被MANUAL取代了


2 MANUAL

spring3.x中的opensessioninviewfilter已經將默認的FlushMode設置為MANUAL了;
如果FlushMode是MANUAL或NEVEL,在操作過程中hibernate會將事務設置為readonly,所以在
增加、刪除或修改操作過程中會出現如下錯誤
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;
解決辦法網上有很多;
1 配置事務,spring會讀取事務中的各種配置來覆蓋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

設置成auto之后,當程序進行查詢、提交事務或者調用session.flush()的時候,都會使緩存和數據庫進行同步,也就是刷新數據庫

4 COMMIT

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


5 ALWAYS

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

 



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

 

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

Java代碼 復制代碼 收藏代碼
  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 (下面來源網絡)

 

可以根據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

 

代碼如:

Java代碼 復制代碼 收藏代碼
  1. public class HibernateDao<T, PK extends Serializable>  {   
  2.     /**  
  3.      * 用于Dao層子類的構造函數.  
  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 {

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

  }

  如果你選擇這種設計,就需要動態注入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>基類了。

Java代碼 復制代碼 收藏代碼
  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 發表評論
]]>
Cookie 和 Sessionhttp://www.aygfsteel.com/agun/archive/2010/12/04/339792.htmlagunagunSat, 04 Dec 2010 04:14:00 GMThttp://www.aygfsteel.com/agun/archive/2010/12/04/339792.htmlhttp://www.aygfsteel.com/agun/comments/339792.htmlhttp://www.aygfsteel.com/agun/archive/2010/12/04/339792.html#Feedback0http://www.aygfsteel.com/agun/comments/commentRss/339792.htmlhttp://www.aygfsteel.com/agun/services/trackbacks/339792.html一、cookie機制和session機制的區別
*************************************************************************************
具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。
同時我們也看到,由于才服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session
機制可能需要借助于cookie機制來達到保存標識的目的,但實際上還有其他選擇
*************************************************************************************

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

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

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

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

六、cookie的讀取
*************************************************************************************
1.調用request.getCookie
要獲取有瀏覽器發送來的cookie,需要調用HttpServletRequest的getCookies方法,這個調用返回Cookie對象的數組,對應由HTTP請求中Cookie報頭輸入的值。
2.對數組進行循環,調用每個cookie的getName方法,直到找到感興趣的cookie為止
 cookie與你的主機(域)相關,而非你的servlet或JSP頁面。因而,盡管你的servlet可能只發送了單個cookie,你也可能會得到許多不相關的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.調用HttpServletRequest.getCookies()獲取Cookie數組
B.在循環中檢索指定名字的cookie是否存在以及對應的值是否正確
C.如果是則退出循環并設置區別標識
D.根據區別標識判斷用戶是否為初訪者從而進行不同的操作
*************************************************************************************

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

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

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

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

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

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

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

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

再次注意關閉瀏覽器只會使存儲在客戶端瀏覽器內存中的session cookie失效,不會使服務器端的session對象失效。
*************************************************************************************

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

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

十八、會話跟蹤的基本步驟
*************************************************************************************
1.訪問與當前請求相關的會話對象
2.查找與會話相關的信息
3.存儲會話信息
4.廢棄會話數據
*************************************************************************************

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

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

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

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

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

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

二十五、session cookie和session對象的生命周期是一樣的嗎
*************************************************************************************
當用戶關閉了瀏覽器雖然session cookie已經消失,但session對象仍然保存在服務器端
*************************************************************************************

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


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

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

二十九、如何使用會話累計用戶的數據
*************************************************************************************
使用可變的數據結構,比如數組、List、Map或含有可寫字段的應用程序專有的數據結構。通過這種方式,除非首次分配對象,否則不需要調用setAttribute。例如

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

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



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

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模板

Xml代碼 復制代碼
  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)根據BeanName自動創建事務代理

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

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

 

    定義事務攔截bean

Xml代碼 復制代碼
  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代碼 復制代碼
  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>   

 

次配置關鍵在兩個bean

TransactionInterceptor

BeanNameAutoProxyCreator

 

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



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

當采用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定義可能會引起開發者的混淆。



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

 

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



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

agun 2010-12-04 11:46 發表評論
]]>
Web Serviceshttp://www.aygfsteel.com/agun/archive/2010/12/04/339784.htmlagunagunSat, 04 Dec 2010 03:45:00 GMThttp://www.aygfsteel.com/agun/archive/2010/12/04/339784.htmlhttp://www.aygfsteel.com/agun/comments/339784.htmlhttp://www.aygfsteel.com/agun/archive/2010/12/04/339784.html#Feedback0http://www.aygfsteel.com/agun/comments/commentRss/339784.htmlhttp://www.aygfsteel.com/agun/services/trackbacks/339784.htmlweb 服務是通過標準的web協議可以訪問的一個應用程序組件。

它是一種可以接收從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,動態調用



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

 

   就拿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安全漏洞的產生:



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

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


圖1 Servlet線程池

  這樣,當兩個或多個線程同時訪問同一個Servlet時,可能會發生多個線程同時訪問同一資源的情況,數據可能會變得不一致。所以在用Servlet構建的Web應用時如果不注意線程安全的問題,會使所寫的Servlet程序有難以發現的錯誤。

  Servlet的線程安全問題

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

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

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

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

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


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

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

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


圖3 Servlet實例的JMM模型

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

調度時刻 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實例的線程調度情況

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

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

  1、實現 SingleThreadModel 接口

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

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

  2、同步對共享數據的操作

  使用synchronized 關鍵字能保證一次只有一個線程可以訪問被保護的區段,在本論文中的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代碼,將實例變量改為局部變量實現同樣的功能,代碼如下:

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

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

  小結

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

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

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

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

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

1. Make Fewer HTTP Requests

減少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

3. Add an Expires Header

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

4. Gzip Components

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

毫無疑問,對站點內容進行壓縮是一個比較常用的 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% 的壓縮比。

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文件中慎用表達式)

8Make JavaScript and CSS External

(在外部包含jscss文件)

9Reduce DNS Lookups

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

10Minify JavaScript

js代碼壓縮)

11Avoid doing redirects.

(避免重定向)

12Remove Duplicates Scripts

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

13Configure 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,其產生規則是基于節點的。相同的cssjs腳本在不同節點服務器上的e-Tag不同,所以如果有n個服務器,那么瀏覽器獲得304應答消息的概率是1/n

14Make Ajax Cacheable

(緩存Ajax請求)

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

15Flush 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.

16Split 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.

17Reduce 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.

18Host Static Content on a Different Top-Level Domain

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

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

(優化圖片)



agun 2008-03-18 10:10 發表評論
]]>
quartz在spring中的使用http://www.aygfsteel.com/agun/archive/2008/03/17/186689.htmlagunagunMon, 17 Mar 2008 01:29:00 GMThttp://www.aygfsteel.com/agun/archive/2008/03/17/186689.htmlhttp://www.aygfsteel.com/agun/comments/186689.htmlhttp://www.aygfsteel.com/agun/archive/2008/03/17/186689.html#Feedback1http://www.aygfsteel.com/agun/comments/commentRss/186689.htmlhttp://www.aygfsteel.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)定時控制--定時的格式(網上總結)

一個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觸發



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

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取出.



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

  • 大部分情況下 HttpClient 默認的構造函數已經足夠使用。
    HttpClient httpClient = new HttpClient();
                    

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

  • 調用實例httpClient的executeMethod方法來執行getMethod。由于是執行在網絡上的程序,在運行executeMethod方法的時候,需要處理兩個異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是在構造getMethod的時候傳入的協議不對,比如不小心將"http"寫成"htp",或者服務器端返回的內容不正常等,并且該異常發生是不可恢復的;第二種異常一般是由于網絡原因引起的異常,對于這種異常 (IOException),HttpClient會根據你指定的恢復策略自動試著重新執行executeMethod方法。HttpClient的恢復策略可以自定義(通過實現接口HttpMethodRetryHandler來實現)。通過httpClient的方法setParameter設置你實現的恢復策略,本文中使用的是系統提供的默認恢復策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod返回值是一個整數,表示了執行該方法后服務器返回的狀態碼,該狀態碼能表示出該方法執行是否成功、需要認證或者頁面發生了跳轉(默認狀態下GetMethod的實例是自動處理跳轉的)等。
    //設置成了默認的恢復策略,在發生異常時候將自動重試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());
                    }
                    

  • 在返回的狀態碼正確后,即可取得內容。取得目標地址的內容有三種方法:第一種,getResponseBody,該方法返回的是目標的二進制的byte流;第二種,getResponseBodyAsString,這個方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據系統默認的編碼方式,所以返回的String值可能編碼類型有誤,在本文的"字符編碼"部分中將對此做詳細介紹;第三種,getResponseBodyAsStream,這個方法對于目標地址中有大量數據需要傳輸是最佳的。在這里我們使用了最簡單的getResponseBody方法。
    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();
            }
            }
            }
            

POST方法

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

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

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

  • 構造PostMethod之前的步驟都相同,與GetMethod一樣,構造PostMethod也需要一個URI參數,在本例中,登錄的地址是http://www.newsmth.net/bbslogin2.php。在創建了PostMethod的實例之后,需要給method實例填充表單的值,在BBS的登錄表單中需要有兩個域,第一個是用戶名(域名叫id),第二個是密碼(域名叫passwd)。表單中的域用類NameValuePair來表示,該類的構造函數第一個參數是域名,第二參數是該域的值;將表單所有的值設置到PostMethod中用方法setRequestBody。另外由于BBS登錄成功后會轉向另外一個頁面,但是HttpClient對于要求接受后繼服務的請求,比如POST和PUT,不支持自動轉發,因此需要自己對頁面轉向做處理。具體的頁面轉向處理請參見下面的"自動轉向"部分。代碼如下:
    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;
                    }
                    



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

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

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

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 的主頁。

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

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




HttpClient 基本功能的使用

GET 方法

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

1. 創建 HttpClient 的實例

2. 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址

3. 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例

4. 讀 response

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

6. 對得到后的內容進行處理



agun 2008-01-29 14:50 發表評論
]]>
主站蜘蛛池模板: 密山市| 乌鲁木齐县| 阿克| 盐边县| 台南县| 定州市| 新竹县| 蓬安县| 北海市| 常州市| 建水县| 建昌县| 巴南区| 屏东市| 嵊泗县| 石屏县| 尼勒克县| 长丰县| 唐河县| 玉龙| 平阳县| 南阳市| 渑池县| 廉江市| 巴南区| 洛川县| 米泉市| 青龙| 东莞市| 菏泽市| 阿城市| 正定县| 汉中市| 开封市| 平定县| 扎囊县| 景宁| 鄂温| 柘荣县| 调兵山市| 东方市|