<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    在路上

    路上有驚慌,路上有理想

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      28 Posts :: 1 Stories :: 10 Comments :: 0 Trackbacks

    2012年4月18日 #

    1.linux安裝字體
       以微軟雅黑為例,找到msyh.ttf ,copy至下面的文件夾
       usr/share/fonts/msyh
      執(zhí)行命令:fc-cache -fv
      重啟jvm即可
    2.drawString 部分代碼
    private static BufferedImage drawString(int type, boolean isWhite,
                int width, int height, String price, Font font_money, Font font,
                Graphics2D g2d, Rectangle2D bounds, Rectangle2D bounds_money) {
             BufferedImage image;
             //透明背景
              image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);  
             g2d.dispose();  
             g2d = image.createGraphics();  
             //反鋸齒字體
             g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
             if(!isWhite){
                 //非白字
                 g2d.setColor(new Color(236,0,137));  
             }else{
                 //白字
                 g2d.setColor(new Color(255,255,255));  
             }
             //字體居中
             double y = (height - bounds.getHeight()) / 2;      
             double ascent = -bounds.getY();      
             double baseY = y + ascent;      

             g2d.setStroke(new BasicStroke(1));  
             g2d.setFont(font_money);
             g2d.drawString(FONT_RMB_CHAR, -2, (int)baseY);  
             g2d.setFont(font);
             g2d.drawString(price, (int)bounds_money.getWidth()-4, (int)baseY);
             g2d.dispose();
             return image;
        }
    3.如果需要根據(jù)字符串的長度生成圖片的寬度,可以使用如下方法
     Rectangle2D bounds = font.getStringBounds(price, context);
     width = (int)(bounds.getWidth();

    4.批量生成,使用java自帶的線程池,并使用CompletionService,目的是在線程處理結(jié)束后得到生成成功的ProductId
          public boolean generateImagesBatch(){
              boolean flag=true;
              ExecutorService exec = Executors.newFixedThreadPool(8);
               CompletionService<CallBack> completionService=
                        new ExecutorCompletionService<CallBack>(exec);
              long startTime=System.currentTimeMillis();
                  String sql="select productId,price from prod";
                List<Map> skuList = this.cmsJdbcTemplate.queryForList(sql);
                for(Map map:skuList){
                    String prodId=((BigDecimal)map.get("productId")).toString();
                    double price=((BigDecimal)map.get("price")).doubleValue();
                    completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.ONE,false));               
                    completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.TWO,false));            }
                long endTime=System.currentTimeMillis()-startTime;
                log.info("query db time>>>>>>>>>>>>>>"+endTime/1000);
                
                Future<CallBack> future;
                int count=skuList.size()*6;
                log.info("generateImagesBatch count:"+count);
                try {
                    while(count>0){
                        future = completionService.take();
                        CallBack callBack = future.get();
                        if(null!=callBack){
                            count--; log.info("generateImagesBatch prod id:"+callBack.getSuccesMessage());                    }
                    }
                endTime=System.currentTimeMillis()-startTime;
                log.info("create images time>>>>>>>>>>>>>>"+endTime/1000);
                log.info("generateImagesBatch success!");
                flag=true;
                } catch (ExecutionException e) {
                    flag=false;
                    log.error("generateImagesBatch fail::ExecutionException::"+e.getMessage());
                } catch (InterruptedException e) {
                    flag=false;
                    log.error("generateImagesBatch fail::InterruptedException::"+e.getMessage());
                }finally{
                    exec.shutdown();
                }
                return flag;
          }
    posted @ 2012-04-18 11:35 阮步兵 閱讀(1860) | 評論 (0)編輯 收藏

    2010年12月15日 #

    以下只是一些概念


    1.SemaphoreCountDownLatch
     
    Semaphore 可用于控制特定資源請求(線程/操作)數(shù)量
     
    CountDownLatch 在功能上類似于Semaphore。區(qū)別是,Semaphore允許一次一個線程的話,CountDownLatch可以允許多個線程在特定的時間一起執(zhí)行。

    2.CAS操作
      根據(jù)英文直譯其實可以理解其含義,compare and set.

      CAS 操作包含三個操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。CAS 認(rèn)為位置 V 應(yīng)該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現(xiàn)在的值即可通常將 CAS 用于同步的方式是從地址 V 讀取值 A,執(zhí)行多步計算來獲得新值 B,然后使用 CAS 將 V 的值從 A 改為 B。如果 V 處的值尚未同時更改,則 CAS 操作成功。

    3.ABA問題

      因為在更改 V 之前,CAS 主要詢問“V 的值是否仍為 A”,所以在第一次讀取 V 以及對 V 執(zhí)行 CAS 操作之前,如果將值從 A 改為 B,然后再改回 A,會使基于 CAS 的算法混亂。在這種情況下,CAS 操作會成功,但是在一些情況下,結(jié)果可能不是您所預(yù)期的。這類問題稱為 ABA 問題

    4.原子操作

       A與B兩個操作。從執(zhí)行A的線程看,當(dāng)其他線程執(zhí)行B時,要么B全部執(zhí)行完成,要么一點都不執(zhí)行。這樣A與B互為原子操作。要保證數(shù)據(jù)狀態(tài)的一致性,要在單一的原子操作中更新所有相關(guān)聯(lián)的狀態(tài)。

    5.可見性
     
       在單線程環(huán)境下,讀寫操作都在一個線程內(nèi)完成,不存在可見性問題。但是,當(dāng)讀與寫操作不在同一個線程內(nèi)時,就需要有可見性的要求——即可變的共享變量對所有線程都是可見的。

    6.重排序

        JVM實現(xiàn)中,線程內(nèi)部維持順序化語義。如果程序的最終結(jié)果等同于它在嚴(yán)格的順序化環(huán)境下的結(jié)果,那么指令的執(zhí)行順序就可能與代碼的順序不一致。這個過程通過叫做指令的重排序。比如Java存儲模型允許編譯器重排序操作指令,在寄存器中緩存數(shù)值,還允許CPU重排序,并在處理器的緩存中緩存數(shù)值。

       當(dāng)然,在沒有同步的多線程情況下,編譯器,處理器,運行時安排操作的執(zhí)行順序可能完全出人意料。

    7.內(nèi)部鎖

      每個Java對象都可以隱士的扮演一個用于同步的鎖的角色。比如synchronized(object){},執(zhí)行線程進(jìn)入synchronized塊 之前自動獲得鎖。無論是正確執(zhí)行或是拋出異常,最終都會釋放該鎖。內(nèi)部鎖是一種互斥鎖(mutex)——至多只有一個線程可以擁有鎖。JDK中有該鎖的實 現(xiàn)。

    8.鎖與內(nèi)存

       鎖不僅僅是關(guān)于同步與互斥,也是關(guān)于內(nèi)存可見性的。為了保證所有線程都能訪問共享變量的最新值,讀和寫的線程必須使用公用的鎖進(jìn)行同步。

    9.鎖與volatile

       加鎖可以保證可見性與原子性,volatile只能保證可見性。

    10.happen-before法則

      Java存儲模型有一個happens-before原則,就是如果動作B要看到動作A的執(zhí)行結(jié)果(無論A/B是否在同一個線程里面執(zhí)行),那么A/B就需要滿足happens-before關(guān)系。比如一個對象構(gòu)造函數(shù)的結(jié)束happens-before與該對象的finalizer的開始


    參考:https://www.ibm.com/developerworks/cn/java/j-jtp11234/

         http://www.ibm.com/developerworks/cn/java/j-5things5.html

         http://www.tkk7.com/xylz/archive/2010/07/03/325168.html

        《Java 并發(fā)編程實踐》

    posted @ 2010-12-15 18:18 阮步兵 閱讀(1741) | 評論 (0)編輯 收藏

    2010年12月10日 #

    BTrace是一個實時監(jiān)控工具,使用了java agent jvm attach技術(shù),可以在product的情況下實時監(jiān)控線上程序的運行情況。另,有插件可與visualVM一起使用。
    不多說了,具體的可見:http://kenai.com/projects/btrace

    下面介紹幾個Helloworld示例:
    主要使用了btrace命令:btrace [pid] class

    pid可由jps命令快速查詢

    1.監(jiān)控方法輸入?yún)?shù):
     @OnMethod(
                    clazz="com.btrace.Person",
                    method="/set.*/"
                )
                public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
                    println(pcn);
                    println(pmn);
                    printArray(args);
                }

    執(zhí)行btract命令
    后臺輸出:
    com.btrace.Person
    setId
    [1, ]……

    2.監(jiān)控方法返回值
      @OnMethod(
                     clazz="com.btrace.Person",
                     method="/get.*/",
                     location=@Location(Kind.RETURN)
                   )  
         public static void defineclass(@Return String cl) {
               println(Strings.strcat("getValue ", cl));
               Threads.jstack();
           }
    執(zhí)行btract命令
    后臺輸出:
    getValue gum
    com.btrace.TestThread.main(TestThread.java:23)

    3.監(jiān)控jvm內(nèi)存使用情況
      @OnTimer(4000)
        public static void printMem() {
            println("Heap:");
            println(heapUsage());
            println("Non-Heap:");
            println(nonHeapUsage());
        }
    執(zhí)行btract命令
    后臺輸出:
    Heap:
    init = 268435456(262144K) used = 26175176(25561K) committed = 251658240(245760K)
     max = 492175360(480640K)
    Non-Heap:
    init = 12746752(12448K) used = 5892104(5754K) committed = 13598720(13280K) max =
     100663296(98304K)
    4.監(jiān)控方法執(zhí)行時間
       @TLS private static long startTime;
       
        @OnMethod(clazz="com.btrace.Person",method="setId")
        public static void onCall(){
            println("enter this method");
            startTime=timeMillis();
        }
       
        @OnMethod(clazz="com.btrace.Person",method="setId",location=@Location(Kind.RETURN))
        public static void onReturn(){
            println("method end!");
            println(strcat("Time taken ms",str(timeMillis()-startTime)));
        }
      后臺輸出:
       enter this method
       method end!
       Time taken ms0
    5.監(jiān)控Thread start
     @OnMethod(
            clazz="java.lang.Thread",
            method="start"
        )
        public static void func() {
            println("about to start a thread!");
        }
    后臺輸出:about to start a thread!
    posted @ 2010-12-10 18:30 阮步兵 閱讀(3759) | 評論 (1)編輯 收藏

    2010年12月9日 #

         摘要: 1.注意auto_increment mysql5.0在高并發(fā)下(每天近2億)插入單表數(shù)據(jù)出現(xiàn)了死鎖(偶現(xiàn)),查了下相關(guān)文檔,發(fā)現(xiàn)是因為采用了auto-increment的主鍵帶來的問題,造成Table級的死鎖。 原因:對于auto_increment字段,innodb會在內(nèi)存里保存一個計數(shù)器用來記錄auto_increment的值,當(dāng)插入一個新行數(shù)據(jù)時,就會用一個表鎖來鎖住這個計數(shù)器,所以會...  閱讀全文
    posted @ 2010-12-09 12:56 阮步兵 閱讀(1660) | 評論 (2)編輯 收藏

    2010年11月11日 #

    一.限制設(shè)計——從結(jié)構(gòu)上說,是利用封裝技術(shù),保證某一時刻只有一個活動訪問某個對象。

    方式主要三類,方法限制、線程限制和對象內(nèi)限制

    方法限制:

       1.方法內(nèi)部限制:采用局部變量方式

       2.方法間傳遞限制:

             a.調(diào)用者copy:比如print(p) 可以改為print(new Point(p));

             b.接收者copy:Point p=new Point(p.x,p.y);

             c.標(biāo)量參數(shù):print(int x,int y);d.print(p.x,p.y);

    線程限制:

         1.最簡單的方法是將所有可變對象都放在一個線程內(nèi)執(zhí)行

                   public display(){

                             new Thread(){

                                      public void run(){//do something here}

                          }.start()

                    }

          2.線程私有成員變量

             最直接的辦法是利用現(xiàn)有類:ThreadLocal.

            當(dāng)然你可以利用Thread.currentThread()自己實現(xiàn)一個類似功能的類,但Thread.currentThread有限制,就是對特定線程的一類。

            而ThreadLocal則擺脫了這樣的限制。而且在線程內(nèi)對ThreadLocal私有變量的讀寫不需要同步。

    對象限制

           在前面兩種方法都不能做到對對象的限制訪問時,你就不得不使用鎖。但同時,也可以對對象內(nèi)部及不同部分的訪問進(jìn)行結(jié)構(gòu)上的限制。

         1.適配器模式

          比如 class Point{

                     public double x;

                     public double y;

                     public synchronized double getX(){};

                    //……

          }

        采用對象限制的設(shè)計方式,會將synchronized 鎖移除到一個其他對象里,這樣就解脫了Point.

         like this

               class SychPoint {

                     private final Point point=new Point();

                    public synchronized double getX(){point.x}

             }

        class Point{

                     public double x;

                     public double y;

                     public double getX(){};

          }

        說白了就是采用適配器模式,改變了一下原來類的結(jié)構(gòu)。java.util.Collection framework 里面就是使用這種策略組織起集合類的同步。

       2.子類化

           將鎖延遲到子類實現(xiàn),這里將不再羅嗦。

    二.同步設(shè)計

         使用鎖的注意事項

           1.有些入口鎖在只有少數(shù)線程訪問的情況下,可以很好的工作,開銷并不大。但是當(dāng)并發(fā)量變大,競爭加劇,開銷也變大,系統(tǒng)的性能會隨之下降。大多數(shù)線程會把大部分時間浪費在等待上。系統(tǒng)出現(xiàn)了延遲,限制了并發(fā)系統(tǒng)的優(yōu)越性。

           2.使用太多的鎖,會增加系統(tǒng)負(fù)擔(dān),以及不可料的情況發(fā)生,比如死鎖。

           3.只用一把鎖來保護(hù)一個功能的多個方面會導(dǎo)致資源競爭。

           4.長時間持有鎖,會帶來性能問題和異常處理的復(fù)雜。

           5.有時候加鎖并不一定能保證得到我們想要的結(jié)果。

        對付以上這些問題,沒有什么最佳策略,大都需要去權(quán)衡各個方面的利弊來進(jìn)行設(shè)計。寫多線程的程序,前期的設(shè)計比后期維護(hù)更為重要。

        初期的設(shè)計原則,

            1.減少同步

                 a.用戶可以接受陳舊數(shù)據(jù),可以拿掉同步,使用volatile

                 b.用戶在得到非法數(shù)據(jù)時,只要能得到提示就夠了,可以使用double-check方法。

                    在不同步時check一次,再在同步狀態(tài)在check一次。這么做的意義在于縮小鎖使用范圍,在第一次check不滿足的情況,跳出方法,那么鎖也就用不到了。

                 c.只對維護(hù)狀態(tài)部分加鎖:當(dāng)對象的某個同步方法是比較耗時的操作,那么鎖持有的時間就越長,而僅僅是為了保持一個狀態(tài)是,可以采用openCall的方式,減少持有鎖時間。

                                  public sychronized void updateState(){}

                                  public void readFile(){

                                          updateState();//持有鎖

                                        file.read();

                                   }

                   如上,這種方式的前提是程序不需要同步一個方法中無狀態(tài)的部分。如果整個方法都需要鎖,那這種方式就不適用了.

                D.能使用同步塊,就不需同步整個方法。

         2.分解同步:

            分解類

                將鎖拆分到輔助類中

            分解鎖

               如果不愿分解類,可以設(shè)計分解鎖

                        private static Object lock1 = new Object();

                       private static Object  lock2 = new Object();

                      synchronize(lock1){}

                      synchronized(lock2){}

                  在jdk 5.0之后的并發(fā)包里,已有可重入鎖供使用。

              隔離成員變量

                  Person的age,income等屬性都需要同步處理,以保證并發(fā)修改時,可以設(shè)計一些同步的int,Double等類型(util.concurrent已提供類似的類),將鎖交給輔助類去處理。起到隔離作用.

     

    posted @ 2010-11-11 17:47 阮步兵 閱讀(1744) | 評論 (0)編輯 收藏

    2010年11月3日 #

    Java 內(nèi)存模型

    JVM系統(tǒng)中存在一個主內(nèi)存(Main Memory),Java中所有變量都儲存在主存中,對于所有線程都是共享的。每條線程都有自己的工作內(nèi)存(Working Memory),工作內(nèi)存中保存的是主存中某些變量的拷貝,線程對所有變量的操作都是在工作內(nèi)存中進(jìn)行,線程之間無法相互直接訪問,變量傳遞均需要通過主存完成。

    模型的規(guī)則:

    1.原子性:保證程序得到成員變量(非局部變量)的值或者是初始值,又或者是某線程修改后的,絕對不是多個線程混亂修改后的。

    2.可見性(共享內(nèi)存的數(shù)據(jù)):什么情況下,寫入成員變量的值對讀取該變量的值是可見的?

         A.寫操作釋放了同步鎖,讀操作獲得了同步鎖

               原理:釋放鎖的時候強(qiáng)制線程把所使用的工作內(nèi)存中的值刷新到主存,獲得鎖的時候從主存重新裝載值。

               p.s.鎖只被同步塊和方法中的操作占有,但卻控制了執(zhí)行該操作的線程的所有成員變量。

         B.如果一個成員變量為volatile,那么在寫線程做存儲操作前,寫入這個成員變量的數(shù)據(jù)會在主存中刷新,并對其他線程可見。讀線程每次使用這個成員變量前都要重新從主存讀數(shù)據(jù)。

         C.如果一個線程訪問一個對象的成員變量,讀到的值為初始值或者另一個線程修改后的值。

            p.s. 不要對引用未完全創(chuàng)建好的對象。

                   如果一個類可以被子類化,那么在構(gòu)造函數(shù)里啟動一個線程是非常危險的

         D.當(dāng)一個線程結(jié)束后,所有的寫入數(shù)據(jù)都會被刷新到主存。

              p.s.同一個線程的不同方法之間傳遞對象的引用,永遠(yuǎn)不會有可見性問題

       存儲模型保證:如果上面的操作都會發(fā)生,那么一個線程對一個成員變量的更新最終對另一個線程是可見的。

    3.順序化(內(nèi)存操作的順序):什么情況下,一個線程的操作可以是無序的?順序化的問題主要圍繞和讀寫有關(guān)的賦值語句的執(zhí)行順序。

       如果采用同步機(jī)制,那不用多說,順序化可以保證。

       當(dāng)沒有同步機(jī)制時,存儲模型所做的保證是難以相信的。在多線程環(huán)境下,存儲模型是難以保證一定正確的。

      只有當(dāng)滿足下面的三個原則,順序化才得以保證。

       A.從線程執(zhí)行方法的角度看,如果指令都是串行執(zhí)行的,那么順序可以保證

       B.保證同步方法或塊的順序執(zhí)行

       C.使用volatile定義成員變量

    線程執(zhí)行過程中,存儲模型與鎖的關(guān)系:

    (1) 獲取對象的鎖

    (2) 清空工作內(nèi)存數(shù)據(jù), 從主存復(fù)制變量到當(dāng)前工作內(nèi)存, 即同步數(shù)據(jù)

    (3) 執(zhí)行代碼,改變共享變量值

    (4) 將工作內(nèi)存數(shù)據(jù)刷回主存

    (5) 釋放對象的鎖

    最后介紹一下volatile關(guān)鍵字

         volatile定義的成員變量可以保證可見性和順序化,但不保證原子性。比如count++。
         *比如把一個變量聲明為volatile,并不能保證這個變量引用的非volatile數(shù)據(jù)的可見性。比如volatile string[10](數(shù)組)

         正確使用volatile的前提條件

         a.對變量的寫操作不依賴于當(dāng)前值

         b.不要和其他成員變量遵守不變約束。見*處的解釋

        volatile的應(yīng)用

         a.狀態(tài)標(biāo)志

            volatile boolean shutdownFlag;

           public void shutdown() { shutdownFlag= true; }
           public void doWork() {
           while (!shutdownFlag) {
            // do something
             }

         b.假設(shè)一個后臺線程可能會每隔幾秒讀取一次數(shù)據(jù)庫里的合同金額,并更新至 volatile 變量。然后,其他線程可以讀取這個變量,從而隨時能夠看到最新的金額。 比較廣泛應(yīng)用在統(tǒng)計類的系統(tǒng)中。

    參考文檔:

    http://www.cs.umd.edu/~pugh/java/memoryModel/

    http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

    《Java并發(fā)編程:設(shè)計原則與模式》

    posted @ 2010-11-03 17:56 阮步兵 閱讀(1455) | 評論 (0)編輯 收藏

    2010年10月28日 #

    1.迭代問題

      多線程環(huán)境下,迭代容易引起問題,如

      for(int i=0;i<v.size();i++){System.out.println(v.get(i))}

     解決辦法之一:

         客戶端加鎖

         for(int i=0;true;i++){

                       Sychronzied(v){

                                if(i<v.size()){

                                     System.out.println(v.get(i)

                                 }

                   }

    },當(dāng)然這種也有問題,一旦程序可以重新設(shè)置元素位置,也會出錯。

    幸好有一種比較安全的辦法: copy遍歷對象

       Sychronzied(v){

                            Object v_clone= copy(v);

                   }

         iterateV(v_clone);

    2.Singleton

       單例習(xí)慣的方式,采用延時初始化,

       public static A getInstance(){

                       if(null==instance){

                         instance=new A();

                    }

                 return instance

       }

      在多線程模式下,需要加鎖,來保證同步Sychronized(object){}。

    如果初始化對象并不占用太多資源,其實沒有必要加鎖,畢竟同步也是很耗資源的。取消延時初始化,priavte static final instance=new A();

    3.順序化資源

       順序化資源是避免死鎖的簡單的方式。

       死鎖:T1時間,線程A 擁有objA的鎖,請求objB的鎖。線程B擁有objB的鎖,請求objA的鎖。

     如: System.identityHashCode(objA)<System.identityHashCode(objB)

     或者:public sychronized add(A a){sychronized(a){//do something}}

    4.wait and notify

    為了防止等待-通知機(jī)制出現(xiàn)race condition,需要加sychronized

    race condition:objA在被wait之前已經(jīng)被另一線程objB 給notify 了, 之后的wait 會永久停止,并導(dǎo)致deadlock(死鎖),當(dāng)然,如果你確認(rèn)可以控制wait-notify很好,就不需要加了

    posted @ 2010-10-28 11:45 阮步兵 閱讀(2002) | 評論 (0)編輯 收藏

    2010年10月12日 #


    1.@Entity 標(biāo)識實體
    2.@Table (name = "tableName") //指定物理表

    @Table(name="tbl_sky",
        uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})}//唯一性約束
    )

    3.@Embeddable 被聲明的類可以嵌入其他實體中
    public class Address {
       private String street1;//persistent
       public String getStreet1() { return street1; }
       public void setStreet1() { this.street1 = street1; }
       private hashCode; //not persistent
    }
    @Embedded 在實體中嵌入一個類型:常用的像名字,地址之類的
    另,使用@AttributeOverrides標(biāo)識覆蓋原類中的屬性取值,因為原實體可能引用的是其他字段。
     @Embedded
        @AttributeOverrides( {
                @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),
                @AttributeOverride(name="name", column = @Column(name="bornCountryName") )
        } )
    Country bornIn;

    例子:
    @Entity

    class User {
      @EmbeddedId
      @AttributeOverride(name="firstName", column=@Column(name="fld_firstname")
      UserId id;
      Integer age;
    }
    @Embeddable
    class UserId implements Serializable {//此處Serializable是必須的
      String firstName;
      String lastName;
    }

    4.@Access(AcessType.PROPERTY)
    必須定義getter/setter方法才能實現(xiàn)持久化
    還有另一種取值:AcessType.FILED,可以不定義getter/setter方法,也能實現(xiàn)持久化
    此annotation也可以定義字段。

    5.主鍵:
       A.單鍵
        @Id
        @GeneratedValue (generator = "identity")
        @GenericGenerator (name = "identity", strategy = "identity")
        或者
        @javax.persistence.SequenceGenerator(
        name="SEQ_STORE",
        sequenceName="my_sequence")
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
        其中:
         strategy取值為:
         AUTO - either identity column, sequence or table depending on the underlying DB
         TABLE - table holding the id
         IDENTITY - identity column
         SEQUENCE - sequence
       B.復(fù)合組鍵
        @Entity
     class Customer {
      @EmbeddedId CustomerId id;
      boolean preferredCustomer;
      @MapsId("userId")//user.id與customerId.userId 使用相同的值
      @JoinColumns({
        @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
        @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
      })
      @OneToOne User user;
    }


    @Embeddable
    class CustomerId implements Serializable {
      UserId userId;
      String customerNumber;
    }


    @Entity
    class User {
      @EmbeddedId UserId id;
      Integer age;
    }

    @Embeddable
    class UserId implements Serializable {
      String firstName;
      String lastName;
    }
         

    6.字段設(shè)置:
    @Column(
        name="columnName";
        boolean un(2)ique() default false;
        boolean nu(3)llable() default true;
        boolean in(4)sertable() default true;
        boolean up(5)datable() default true;
        String col(6)umnDefinition() default "";
        String tab(7)le() default "";
        int length(8)() default 255;
        int precis(9)ion() default 0; // decimal precision
        int scale((10)) default 0; // decimal scale
    @Transient 非持久化字段
    @Basic 持久化字段
    @Basic(fetch = FetchType.LAZY) basic 用于定義property的fetch屬性
    @Enumerated(EnumType.STRING) 標(biāo)識enum persisted as String in database
    @Lob  blob clob字段
    @Formula("obj_length * obj_height * obj_width")//自定義輸出
    public long getObjectVolume()

    7.Mapping關(guān)系
    A.一對多或者一對一:
     @OneToOne(cascade = CascadeType.ALL) 一對一關(guān)系,級聯(lián)關(guān)系為all
     @PrimaryKeyJoinColumn或者
     指定關(guān)聯(lián)外鍵
     @JoinColumn(name="passport_fk")
     Passport passport,
     一對一的另一端只需@OneToOne(mappedBy = "passport"),passport為前一個實體聲明的名字


    @OneToMany(fetch = FetchType.LAZY , mappedBy = "adProduct")
    @Cascade(value = {CascadeType.ALL,CascadeType.DELETE_ORPHAN})

    @OrderBy(value = "id")  //排序
    B.多對一:
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name="adPosition_id",nullable=false)   
       

    8.Fetch and Lazy
    AnnotationsLazyFetch
    @[One|Many]ToOne](fetch=FetchType.LAZY) @LazyToOne(PROXY) @Fetch(SELECT)
    @[One|Many]ToOne](fetch=FetchType.EAGER) @LazyToOne(FALSE) @Fetch(JOIN)
    @ManyTo[One|Many](fetch=FetchType.LAZY) @LazyCollection(TRUE) @Fetch(SELECT)
    @ManyTo[One|Many](fetch=FetchType.EAGER) @LazyCollection(FALSE) @Fetch(JOIN)

    9.Cascade

    10.緩存

    緩存的注釋寫法如下,加在Entity的java類上:

    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

    緩存的方式有四種,分別為:

    • CacheConcurrencyStrategy.NONE
    • CacheConcurrencyStrategy.READ_ONLY,只讀模式,在此模式下,如果對數(shù)據(jù)進(jìn)行更新操作,會有異常;
    • CacheConcurrencyStrategy.READ_WRITE,讀寫模式在更新緩存的時候會把緩存里面的數(shù)據(jù)換成一個鎖,其它事務(wù)如果去取相應(yīng)的緩存數(shù)據(jù),發(fā)現(xiàn)被鎖了直接就去數(shù)據(jù)庫查詢;
    • CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,不嚴(yán)格的讀寫模式則不會對緩存數(shù)據(jù)加鎖;
    • CacheConcurrencyStrategy.TRANSACTIONAL,事務(wù)模式指緩存支持事務(wù),當(dāng)事務(wù)回滾時,緩存也能回滾,只支持JTA環(huán)境。


    11.No-Annotation 字段:

          If the property is of a single type, it is mapped as @Basic

          Otherwise, if the type of the property is annotated as @Embeddable, it is mapped as @Embedded

          Otherwise, if the type of the property is Serializable, it is mapped as @Basic in a column holding the object in its serialized version

          Otherwise, if the type of the property is java.sql.Clob or java.sql.Blob, it is mapped as @Lob with the appropriate LobType
    posted @ 2010-10-12 16:52 阮步兵 閱讀(3232) | 評論 (0)編輯 收藏

    2010年9月27日 #

    1.J2EE安全性介紹

    說明性的安全性:通過安全結(jié)構(gòu)描述的方式來代表應(yīng)用程序的安全需求,安全結(jié)構(gòu)一般包括安全角色,訪問控制和驗證要求等。在j2ee平臺中部署描述符充 當(dāng)了說明的安全性的主要工具。部署描述符是組件開發(fā)者和應(yīng)用程序部署者或應(yīng)用程序組裝者之間的交流工具。應(yīng)用程序的開發(fā)者用它來表示應(yīng)用中的安全需求,應(yīng)用程序部署者或應(yīng)用程序組裝者將安全角色與部署環(huán)境中的用戶和組映射起來。

    在程序運行時容器從部署描述符中提取出相應(yīng)的安全策略,然后容器根據(jù)安全策略執(zhí)行安全驗證。說明的安全性不需要開發(fā)人員編寫任何安全相關(guān)的代碼,一切都是通過配置部署描述符來完成的。

    可編程的安全性: 可編程的安全性在說明性的安全性的基礎(chǔ)上,使安全敏感的應(yīng)用可以通過調(diào)用被容器提供的API來對安全作出決斷。這在說明性的安全性不足以滿足企業(yè)的安全模型的情況是非常有用的。比如J2ee在servlet HttpServletRequest interface中各提供兩個方法:
    isUserInRole (HttpServletRequest)——判斷用戶角色
    getUserPrincipal (HttpServletRequest) ——獲得用戶認(rèn)證信息principal
    另外,就是用戶自定義登錄認(rèn)證,而不是使用J2EE的部署描述符里面的定義(三種登錄認(rèn)證類型)。

    2.基于J2EE的認(rèn)證與授權(quán)

    提到安全性,就不能不說到兩個概念:認(rèn)證與授權(quán)。

    認(rèn)證是用戶或計算設(shè)備用來驗證身份的過程。授權(quán)是根據(jù)請求用戶的身份允許訪問和操作一段敏感軟件的過程。 這兩個概念密不可分。沒有授權(quán), 就無需知道用戶的身份。沒能認(rèn)證,就不可能區(qū)分可信和不可信用戶, 更不可能安全地授權(quán)訪問許多系統(tǒng)部分。


    因為之前的項目100% web方式,所以本文只討論web應(yīng)用的認(rèn)證和授權(quán)。


    A.認(rèn)證方式:
    Web客戶端通常通過http協(xié)議來請求web服務(wù)器端的資源,這些web資源通常包括html網(wǎng)頁、jsp(java server page)文件、java servlet和其他一些二進(jìn)制或多媒體文件。在企業(yè)環(huán)境中,企業(yè)的某些資源往往要求只允許某些人訪問,有些資源甚至是機(jī)密的或安全敏感的。因此對企業(yè)中 各種web資源進(jìn)行訪問控制是十分必要的。為了滿足企業(yè)中的不同安全級別和客戶化的需求,J2EE提供了三種基于web客戶端的認(rèn)證方式:

    HTTP基本認(rèn)證(HTTP Basic Authentication)
    HTTP基本驗證 是HTTP協(xié)議所支持的驗證機(jī)制。這種驗證機(jī)制使用用戶的用戶名和密碼作為驗證信息。Web客戶端從用戶獲取用戶名和密碼,然后傳遞他們給web服務(wù) 器,web服務(wù)器在指定的區(qū)域(realm)中驗證用戶。但需要注意的是,這種驗證方法是不夠安全的。因為這種驗證方法并不對用戶密碼進(jìn)行加密,而只是對密碼進(jìn)行基本的base64的編碼。而且目標(biāo)web服務(wù)器對用戶來說也是非驗證過的。不能保證用戶訪問到的web服務(wù)器就是用戶希望訪問的。

    基于表單的認(rèn)證(Form-Based Authentication)
    基于表單的驗證 使系統(tǒng)開發(fā)者可以自定義用戶的登陸頁面和報錯頁面。這種驗證方法與基本HTTP的驗證方法的唯一區(qū)別就在于它可以根據(jù)用戶的要求制定登陸和出錯頁面。基于 表單的驗證方法同樣具有與基本HTTP驗證類似的不安全的弱點。用戶在表單中填寫用戶名和密碼,而后密碼以明文形式在網(wǎng)路中傳遞,如果在網(wǎng)路的某一節(jié)點將 此驗證請求截獲,在經(jīng)過反編碼很容易就可以獲取用戶的密碼。因此在使用基本HTTP的驗證方式和基于表單的驗證方法時,一定確定這兩種方式的弱點對你的應(yīng) 用是可接受的。

    基于客戶端證書的認(rèn)證(Client-Certificate Authentication)
    基于客戶端證書的驗證方式要比上面兩種方式更安全。它通過HTTPS(HTTP over SSL)來保證驗證的安全性。安全套接層(Secure Sockets Layer)為驗證過程提供了數(shù)據(jù)加密,服務(wù)器端認(rèn)證,信息真實性等方面的安全保證。在此驗證方式中,客戶端必須提供一個公鑰證書,你可以把這個公鑰證書 看作是你的數(shù)字護(hù)照。公鑰證書也稱數(shù)字證書,它是被稱作證書授權(quán)機(jī)構(gòu)(CA)-一個被信任的組織頒發(fā)的。這個數(shù)字證書必須符合X509公鑰體系結(jié)構(gòu) (PKI)的標(biāo)準(zhǔn)。如果你指定了這種驗證方式,Web服務(wù)器將使用客戶端提供的數(shù)字證書來驗證用戶的身份。 

    B.授權(quán)模型:

    代碼授權(quán)(Code Authorization)
    j2ee產(chǎn)品通過java 2 安全模型來限制特定J2SE的類和方法的執(zhí)行,以保護(hù)和確保操作系統(tǒng)的安全。

    調(diào)用者授權(quán)(Caller Authorization) ——這個是我們常用的方式
    安全角色:安全角色是具有相同安全屬性的邏輯組。比如是admin,Supervisor等。

    用戶和組:用戶和組是在實際系統(tǒng)環(huán)境下的用戶和用戶的集合。它們對應(yīng)者現(xiàn)實當(dāng)中的人和群體。

    訪問控制:訪問控制可以確保安全角色只能訪問已授予它安全權(quán)限的授權(quán)對象。授權(quán)對象包括EJB的遠(yuǎn)程方法、web資源(html網(wǎng)頁,jsp/servlet和多媒體或二進(jìn)制文件)等。在j2ee中訪問控制在應(yīng)用程序描述文件中與安全角色關(guān)聯(lián)起來。

    映射:通過映射應(yīng)用程序的系統(tǒng)管理員將實際系統(tǒng)環(huán)境中的用戶與安全角色聯(lián)系起來,從而是實際的用戶擁有對企業(yè)資源訪問的適當(dāng)授權(quán)。 


    C.部署描述符安全性相關(guān)介紹:

    安全約束——定義那些資源是受約束訪問的,以及認(rèn)證通過后的授權(quán)范圍
    <security-constraint>                                //安全約束部分
    <web-resource-collection>                         //受約束的web資源集
    <web-resource-name>WRCollection</web-resource-name>  //資源集名
    <url-pattern>/webtest.jsp</url-pattern>                  //資源的url表達(dá)式
    <http-method>GET</http-method>                     //受約束的資源操作方法
    <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>                                    //對安全角色授權(quán)
    <role-name>user</role-name>                        //安全角色名
    </auth-constraint>
    <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
    </security-constraint>
    定義安全角色 <security-role> <description>this is a user</description> <role-name>user</role-name> </security-role>
    基本的HTTP認(rèn)證方式——使用不多
    <login-config> //驗證方式設(shè)置 <auth-method>BASIC</auth-method> //使用基本的HTTP驗證方式 <realm-name></realm-name> </login-config>
    基于表單的認(rèn)證方式——使用較多
    <login-config> <auth-method>FORM</auth-method> //使用基于表單的驗證方式 <realm-name>Default</realm-name> //使用缺省的安全域 <form-login-config> <form-login-page>/login.html</form-login-page> //定義登陸頁面 <form-error-page>/error.html</form-error-page> //定義出錯頁面 </form-login-config> </login-config>
    基于證書的認(rèn)證方式——與CA用戶數(shù)據(jù)中心一起使用
    <login-config> <auth-method>CLIENT-CERT</auth-method>
    </login-config>
    注:后兩種均在項目中應(yīng)用過。
    以上三種認(rèn)證方式都屬于配置式登錄認(rèn)證。
    還有一種是程序性(編程式)的登錄認(rèn)證,即通過web application自身進(jìn)行驗證,比較典型的是利用過濾器代理操作。
    比如開源的acegi,使用它你將無需再web.xml里配置如此多的東西(當(dāng)然,也多了許多acegi的配置)。

    參考 http://www.ibm.com/developerworks/cn/java/l-j2eeSecurity/
         企業(yè)級Java安全性——構(gòu)建安全的J2EE應(yīng)用

    posted @ 2010-09-27 11:52 阮步兵 閱讀(954) | 評論 (0)編輯 收藏

    2010年9月25日 #

    對于做軟件的人來說,唯一不變的就是變化。此為行業(yè)真理。而對于復(fù)雜業(yè)務(wù)系統(tǒng)的邏輯組件的定義不得不多考慮一下業(yè)務(wù)的可擴(kuò)展性,來應(yīng)對客戶的變化。選擇Rule Engine是一個不錯的方案。

    Drools 是用 Java 語言編寫的開放源碼規(guī)則引擎。Drools 允許使用聲明方式表達(dá)業(yè)務(wù)邏輯。可以使用非 XML 的本地語言編寫規(guī)則(這點很重要,本人之前曾用過自己公司的一套業(yè)務(wù)規(guī)則組件,無論是編寫還是調(diào)試都很麻煩),從而便于學(xué)習(xí)和理解。并且,還可以將 Java 代碼直接嵌入到規(guī)則文件中,使Drools 更加吸引人。簡單的概括,就是簡單使用,易于理解。而且它是免費的。

    1.rule文件:
    rule "rule name"  
        no-loop
        when
          customer : Customer( state == CustomerState.UNCENSORED )     
        then
            customer.setState(CustomerState.AUDITING);
            CustomerTask task=new CustomerTask();
            Post law=userService.getPostByPostCode(Constants.PostCode.ROOT_LAW);
            task.setAuditorPost(law);
            task.setEntityState(CustomerState.AUDITING);
            task.setEntityId(customer.getId());
            task.setEntityCode(String.valueOf(customer.getId()));
            task.setEntityType(Customer.class.getSimpleName());
            task.setTitle(customer.getName()+" test");
            taskService.assignmentTask(task);
            logger.info("CustomerTask Submit auditorTitle:" + task.getAuditorTitle());
    end

    這里面有個狀態(tài)的條件判斷state == CustomerState.UNCENSORED ,then 關(guān)鍵字后面的便是符合條件的處理邏輯,只要是java程度都可以看懂,比xml類的rule文件好懂了許多。

    接下來
    語法說明:


    文件頭部分:
    package drools.java.demo;定義包名,等同于命名空間
    import drools.java.demo.Machine;導(dǎo)入java類
    global java.util.List myGlobalList;此關(guān)鍵字讓規(guī)則引擎知道,myGlobalList對象應(yīng)該可以從規(guī)則中訪問.
    function:
    類似于公用方法的抽象,如下定義后,各個同一文件下的rule都可以使用
    function void setTestsDueTime(Machine machine, int numberOfDays) {
        setDueTime(machine, Calendar.DATE, numberOfDays);
    }
    rule:定義了一個規(guī)則

    rule "<name>"
    <attribute>*
    when
    <conditional element>*
    then
    <action>*
    end




    <name> 即rule的名字標(biāo)識

    <attribute>:

    常用的屬性:
    no-loop :true 條件結(jié)果更改后,修改此條件且定義為no-loop:true的規(guī)則不會再重新執(zhí)行。
    lock-on-active:true 可以看作是no-loop的加強(qiáng)版,當(dāng)條件結(jié)果更改后,不但修改此條件的規(guī)則不會重新執(zhí)行,文件中的任何規(guī)則(其 active-lock 屬性被設(shè)為 true)不會重新執(zhí)行。
    salience:100 使用它可以讓規(guī)則執(zhí)行引擎知道應(yīng)該啟動規(guī)則的結(jié)果語句的順序。具有最高顯著值的規(guī)則的結(jié)果語句首先執(zhí)行;具有第二高顯著值的規(guī)則的結(jié)果語句第二執(zhí)行,依此類推。當(dāng)您需要讓規(guī)則按預(yù)定義順序啟動時,這一點非常重要。

    其他屬性的解釋請見http://downloads.jboss.com/drools/docs/5.1.1.34858.FINAL/drools-expert/html_single/index.html#d0e2607

    when:填寫條件的地方,比如:
    Cheese( type == "stilton", price < 10, age == "mature" )或

    Cheese( type == "stilton" && price < 10, age == "mature" )

    then:業(yè)務(wù)規(guī)則的地方,略。

    2.用法

    規(guī)則文件定義好后,就該是怎么使用它了


    如上圖,file rule定義好后,就該是如何使用它了。最重要的兩個類RuleBase和WorkingMemory

    下面是一個example:
    public class RulesEngine {
        private RuleBase rules;
        private boolean debug = false;
        public RulesEngine(String rulesFile) throws RulesEngineException {
            super();
            try {
                // Read in the rules source file
                Reader source = new InputStreamReader(RulesEngine.class
                        .getResourceAsStream("../../rules/" + rulesFile));

                // Use package builder to build up a rule package
                PackageBuilder builder = new PackageBuilder();

                // This will parse and compile in one step
                builder.addPackageFromDrl(source);

                // Get the compiled package
                Package pkg = builder.getPackage();

                // Add the package to a rulebase (deploy the rule package).
                rules = RuleBaseFactory.newRuleBase();
                rules.addPackage(pkg);

            } catch (Exception e) {
                throw new RulesEngineException(
                        "Could not load/compile rules file: " + rulesFile, e);
            }
        }
        public RulesEngine(String rulesFile, boolean debug)
                throws RulesEngineException {
            this(rulesFile);
            this.debug = debug;
        }
        public void executeRules(WorkingEnvironmentCallback callback) {
            WorkingMemory workingMemory = rules.newStatefulSession();
            if (debug) {
                workingMemory
                        .addEventListener(new DebugWorkingMemoryEventListener());
            }
            callback.initEnvironment(workingMemory);
            workingMemory.fireAllRules();
        }
    }
    RulesEngine構(gòu)造方法演示了如何去讀入一個rule文件,并構(gòu)建了一個RuleBase對象(RuleBase 是一個包含了rule文件的所有規(guī)則的集合)
    executeRules方法定義了如何使用規(guī)則文件中定義的那些內(nèi)容,用RuleBase構(gòu)建一個WorkingMemory對象,再執(zhí)行fireAllRules()方法。
    WorkingMemory 代表了與rulebase鏈接的session會話,也可以看作是工作內(nèi)存空間。如果你要向內(nèi)存中插入一個對象可以調(diào)用insert()方法,同理,更新一個對象使用update()方法。WorkingMemory還有一個setGlobal()方法,用來設(shè)置規(guī)則內(nèi)可以引用的對象(相當(dāng)于規(guī)則的全局變量)。

    3.小技巧

      可以一次把所有的rule文件都載入內(nèi)存中存放,這樣就不用每次執(zhí)行都讀取文件。
      如果規(guī)則文件被修改,也可以用過一個方法來判斷是否需要重新載入rule文件
      比如:根據(jù)文件的最后修改時間,與內(nèi)存中對應(yīng)對象的時間做比較
    public boolean hasChange(List<RuleFile> ruleFileList){
            for(RuleFile ruleFile:ruleFileList){
                if(!ruleFile.getLastModifyTime().equals(ruleFileMap.get(ruleFile.getFileName()).getLastModifyTime())){
                    return true;
                }
            }
            return false;
        }

    注:具體的helloWorld 請見http://www.ibm.com/developerworks/cn/java/j-drools/#listing12,比我說得好多了。
    posted @ 2010-09-25 17:48 阮步兵 閱讀(5254) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 一级毛片a免费播放王色| 免费h成人黄漫画嘿咻破解版| 有码人妻在线免费看片| 亚洲国产精品专区| 亚洲精品中文字幕无码蜜桃| 日韩高清免费观看| 最近高清中文字幕无吗免费看| 2022国内精品免费福利视频| 亚洲国产午夜精品理论片在线播放 | 91成人免费福利网站在线| 亚洲av无码专区在线观看亚| 亚洲精品一区二区三区四区乱码| 亚洲欧洲无码AV电影在线观看| 全部免费毛片在线| 成年午夜视频免费观看视频| 青娱乐免费视频在线观看| 免费A级毛片无码视频| 男人天堂免费视频| 国产日韩久久免费影院| 日韩免费高清一级毛片| 亚洲老熟女五十路老熟女bbw | 国产偷伦视频免费观看| 国产免费黄色无码视频 | 国产片免费在线观看| 成人毛片免费观看视频在线| 一本岛高清v不卡免费一三区| 久久久精品免费视频| 国产性生大片免费观看性| 国产精品美女久久久免费 | 日本特黄特色aa大片免费| 天天看免费高清影视| 日本精品人妻无码免费大全| 四虎最新永久免费视频| 91短视频免费在线观看| 国产情侣激情在线视频免费看| 日本最新免费网站| 免费A级毛片无码无遮挡内射| 大学生一级毛片免费看| 成人毛片18岁女人毛片免费看| 成年女人毛片免费视频| 国产成人aaa在线视频免费观看|