在路上

          路上有驚慌,路上有理想

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            28 Posts :: 1 Stories :: 10 Comments :: 0 Trackbacks

          2010年9月27日 #

          1.linux安裝字體
             以微軟雅黑為例,找到msyh.ttf ,copy至下面的文件夾
             usr/share/fonts/msyh
            執行命令: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.如果需要根據字符串的長度生成圖片的寬度,可以使用如下方法
           Rectangle2D bounds = font.getStringBounds(price, context);
           width = (int)(bounds.getWidth();

          4.批量生成,使用java自帶的線程池,并使用CompletionService,目的是在線程處理結束后得到生成成功的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 阮步兵 閱讀(1861) | 評論 (0)編輯 收藏

          以下只是一些概念


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

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

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

          3.ABA問題

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

          4.原子操作

             A與B兩個操作。從執行A的線程看,當其他線程執行B時,要么B全部執行完成,要么一點都不執行。這樣A與B互為原子操作。要保證數據狀態的一致性,要在單一的原子操作中更新所有相關聯的狀態。

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

          6.重排序

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

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

          7.內部鎖

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

          8.鎖與內存

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

          9.鎖與volatile

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

          10.happen-before法則

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


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

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

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

              《Java 并發編程實踐》

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

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

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

          pid可由jps命令快速查詢

          1.監控方法輸入參數:
           @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);
                      }

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

          2.監控方法返回值
            @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();
                 }
          執行btract命令
          后臺輸出:
          getValue gum
          com.btrace.TestThread.main(TestThread.java:23)

          3.監控jvm內存使用情況
            @OnTimer(4000)
              public static void printMem() {
                  println("Heap:");
                  println(heapUsage());
                  println("Non-Heap:");
                  println(nonHeapUsage());
              }
          執行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.監控方法執行時間
             @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.監控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 阮步兵 閱讀(3762) | 評論 (1)編輯 收藏

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

          一.限制設計——從結構上說,是利用封裝技術,保證某一時刻只有一個活動訪問某個對象。

          方式主要三類,方法限制、線程限制和對象內限制

          方法限制:

             1.方法內部限制:采用局部變量方式

             2.方法間傳遞限制:

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

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

                   c.標量參數:print(int x,int y);d.print(p.x,p.y);

          線程限制:

               1.最簡單的方法是將所有可變對象都放在一個線程內執行

                         public display(){

                                   new Thread(){

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

                                }.start()

                          }

                2.線程私有成員變量

                   最直接的辦法是利用現有類:ThreadLocal.

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

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

          對象限制

                 在前面兩種方法都不能做到對對象的限制訪問時,你就不得不使用鎖。但同時,也可以對對象內部及不同部分的訪問進行結構上的限制。

               1.適配器模式

                比如 class Point{

                           public double x;

                           public double y;

                           public synchronized double getX(){};

                          //……

                }

              采用對象限制的設計方式,會將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(){};

                }

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

             2.子類化

                 將鎖延遲到子類實現,這里將不再羅嗦。

          二.同步設計

               使用鎖的注意事項

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

                 2.使用太多的鎖,會增加系統負擔,以及不可料的情況發生,比如死鎖。

                 3.只用一把鎖來保護一個功能的多個方面會導致資源競爭。

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

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

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

              初期的設計原則,

                  1.減少同步

                       a.用戶可以接受陳舊數據,可以拿掉同步,使用volatile

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

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

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

                                        public sychronized void updateState(){}

                                        public void readFile(){

                                                updateState();//持有鎖

                                              file.read();

                                         }

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

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

               2.分解同步:

                  分解類

                      將鎖拆分到輔助類中

                  分解鎖

                     如果不愿分解類,可以設計分解鎖

                              private static Object lock1 = new Object();

                             private static Object  lock2 = new Object();

                            synchronize(lock1){}

                            synchronized(lock2){}

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

                    隔離成員變量

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

           

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

          Java 內存模型

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

          模型的規則:

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

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

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

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

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

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

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

                  p.s. 不要對引用未完全創建好的對象。

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

               D.當一個線程結束后,所有的寫入數據都會被刷新到主存。

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

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

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

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

             當沒有同步機制時,存儲模型所做的保證是難以相信的。在多線程環境下,存儲模型是難以保證一定正確的。

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

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

             B.保證同步方法或塊的順序執行

             C.使用volatile定義成員變量

          線程執行過程中,存儲模型與鎖的關系:

          (1) 獲取對象的鎖

          (2) 清空工作內存數據, 從主存復制變量到當前工作內存, 即同步數據

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

          (4) 將工作內存數據刷回主存

          (5) 釋放對象的鎖

          最后介紹一下volatile關鍵字

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

               正確使用volatile的前提條件

               a.對變量的寫操作不依賴于當前值

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

              volatile的應用

               a.狀態標志

                  volatile boolean shutdownFlag;

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

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

          參考文檔:

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

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

          《Java并發編程:設計原則與模式》

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

          1.迭代問題

            多線程環境下,迭代容易引起問題,如

            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)

                                       }

                         }

          },當然這種也有問題,一旦程序可以重新設置元素位置,也會出錯。

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

             Sychronzied(v){

                                  Object v_clone= copy(v);

                         }

               iterateV(v_clone);

          2.Singleton

             單例習慣的方式,采用延時初始化,

             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

          為了防止等待-通知機制出現race condition,需要加sychronized

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

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


          1.@Entity 標識實體
          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標識覆蓋原類中的屬性取值,因為原實體可能引用的是其他字段。
           @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方法才能實現持久化
          還有另一種取值:AcessType.FILED,可以不定義getter/setter方法,也能實現持久化
          此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.復合組鍵
              @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.字段設置:
          @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) 標識enum persisted as String in database
          @Lob  blob clob字段
          @Formula("obj_length * obj_height * obj_width")//自定義輸出
          public long getObjectVolume()

          7.Mapping關系
          A.一對多或者一對一:
           @OneToOne(cascade = CascadeType.ALL) 一對一關系,級聯關系為all
           @PrimaryKeyJoinColumn或者
           指定關聯外鍵
           @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,只讀模式,在此模式下,如果對數據進行更新操作,會有異常;
          • CacheConcurrencyStrategy.READ_WRITE,讀寫模式在更新緩存的時候會把緩存里面的數據換成一個鎖,其它事務如果去取相應的緩存數據,發現被鎖了直接就去數據庫查詢;
          • CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,不嚴格的讀寫模式則不會對緩存數據加鎖;
          • CacheConcurrencyStrategy.TRANSACTIONAL,事務模式指緩存支持事務,當事務回滾時,緩存也能回滾,只支持JTA環境。


          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 阮步兵 閱讀(3236) | 評論 (0)編輯 收藏

          1.J2EE安全性介紹

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

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

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

          2.基于J2EE的認證與授權

          提到安全性,就不能不說到兩個概念:認證與授權。

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


          因為之前的項目100% web方式,所以本文只討論web應用的認證和授權。


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

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

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

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

          B.授權模型:

          代碼授權(Code Authorization)
          j2ee產品通過java 2 安全模型來限制特定J2SE的類和方法的執行,以保護和確保操作系統的安全。

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

          用戶和組:用戶和組是在實際系統環境下的用戶和用戶的集合。它們對應者現實當中的人和群體。

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

          映射:通過映射應用程序的系統管理員將實際系統環境中的用戶與安全角色聯系起來,從而是實際的用戶擁有對企業資源訪問的適當授權。 


          C.部署描述符安全性相關介紹:

          安全約束——定義那些資源是受約束訪問的,以及認證通過后的授權范圍
          <security-constraint>                                //安全約束部分
          <web-resource-collection>                         //受約束的web資源集
          <web-resource-name>WRCollection</web-resource-name>  //資源集名
          <url-pattern>/webtest.jsp</url-pattern>                  //資源的url表達式
          <http-method>GET</http-method>                     //受約束的資源操作方法
          <http-method>POST</http-method>
          </web-resource-collection>
          <auth-constraint>                                    //對安全角色授權
          <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認證方式——使用不多
          <login-config> //驗證方式設置 <auth-method>BASIC</auth-method> //使用基本的HTTP驗證方式 <realm-name></realm-name> </login-config>
          基于表單的認證方式——使用較多
          <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>
          基于證書的認證方式——與CA用戶數據中心一起使用
          <login-config> <auth-method>CLIENT-CERT</auth-method>
          </login-config>
          注:后兩種均在項目中應用過。
          以上三種認證方式都屬于配置式登錄認證。
          還有一種是程序性(編程式)的登錄認證,即通過web application自身進行驗證,比較典型的是利用過濾器代理操作。
          比如開源的acegi,使用它你將無需再web.xml里配置如此多的東西(當然,也多了許多acegi的配置)。

          參考 http://www.ibm.com/developerworks/cn/java/l-j2eeSecurity/
               企業級Java安全性——構建安全的J2EE應用

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

          主站蜘蛛池模板: 康保县| 潢川县| 行唐县| 连云港市| 喀喇| 米林县| 金平| 麻栗坡县| 开远市| 防城港市| 衡阳市| 扶绥县| 呼伦贝尔市| 红桥区| 广西| 台山市| 铜陵市| 海晏县| 巫溪县| 来安县| 贡觉县| 德清县| 仁布县| 永清县| 章丘市| 申扎县| 北京市| 娱乐| 闽侯县| 宜川县| 西林县| 大化| 八宿县| 罗城| 紫阳县| 息烽县| 澎湖县| 体育| 海口市| 荥经县| 丹棱县|