筆記

          way

          2010年12月3日

          最近在網上看到的相關材料都比較陳舊,也太簡略,參看了一下其他人的內容,針對Hive2.1.1做點分享:
          1)下載apache-hive-2.1.1-bin.tar.gz

          2)解壓縮,下面的命令行如啟動報錯,請自行查略Hive啟動配置

          3)啟動hiveserver2 (非必須,使用jdbc訪問的時候才使用)
          bin目錄下
          hive --service hiveserver2 -p10001來啟動hiveserver2 服務(默認為10000端口)
          nohup hive --service hiverserver2 -p10001可以在后臺跑
          4)hive腳本運行流程
          bin目錄下,使用命令方法為:
          ./hive <parameters> --service serviceName <service parameters>
          舉例:hive --debug :
             查看bin/hive文件
          流程中會判斷$1=‘--debug’則$DEBUG=‘--debug’
           
          if [ "$DEBUG" ]; then
            if [ "$HELP" ]; then //如還有--help,就會執行debug_help方法。
              debug_help
              exit 0
            else
              get_debug_params "$DEBUG"
              export HADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS $HIVE_MAIN_CLIENT_DEBUG_OPTS"http://設置HIVE_MAIN_CLIENT_DEBUG_OPTS的參數中加入debug相應參數
            fi
          fi
          if [ "$SERVICE" = "" ] ; then
            if [ "$HELP" = "_help" ] ; then
              SERVICE="help"
            else
              SERVICE="cli"     //默認賦值cli
            fi
          fi
          這個shell腳本很多變量應該是在其他sh文件中定義,其中$SERVICE_LIST就是其他很多sh文件的最開始形成的:export SERVICE_LIST="${SERVICE_LIST}${THISSERVICE} "
          hive腳本最后的$TORUN "$@" ,默認情況下TORUN其實就是cli,即執行/ext/cli.sh腳本,該腳本中主要是調用/ext/util/execHiveCmd.sh 來執行最后的CliDriver。
           【shell腳本中的$*,$@和$#
          舉例說:
          腳本名稱叫test.sh 入參三個: 1 2 3
          運行test.sh 1 2 3后
          $*為"1 2 3"(一起被引號包住)
          $@為"1" "2" "3"(分別被包住)
          $#為3(參數數量)
          即exec $HADOOP jar ${HIVE_LIB}/$JAR $CLASS $HIVE_OPTS "$@" //1
          其中:
          $HADOOP=$HADOOP_HOME/bin/hadoop 【hive腳本中定義HADOOP=$HADOOP_HOME/bin/hadoop】
          $CLASS=org.apache.hadoop.hive.cli.CliDriver【傳入的第一個參數,在cli.sh中有定義】
          hadoop腳本(2.7.3為例)中最終會執行:
          # Always respect HADOOP_OPTS and HADOOP_CLIENT_OPTS
              HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
              #make sure security appender is turned off
              HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.security.logger=${HADOOP_SECURITY_LOGGER:-INFO,NullAppender}"
           
              export CLASSPATH=$CLASSPATH
              exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS "$@" //2
          hive的debug參數就是在啟動hive腳本時放到HADOOP_OPTS中的
          1和2處結合可得到最終的運行命令,查看一下運行結果:ps -ef|grep CliDriver

            /usr/java/jdk1.8.0_101/bin/java -Xmx256m -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=.. -Dhadoop.log.file=hadoop.log -Dhadoop.home.dir=.. -Dhadoop.id.str=root -Dhadoop.root.logger=INFO,console -Djava.library.path=.. -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Xmx512m -Dproc_hivecli -XX:+UseParallelGC -agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=-Dlog4j.configurationFile=hive-log4j2.properties -Djava.util.logging.config.file=..
            
          -Dhadoop.security.logger=INFO,NullAppender org.apache.hadoop.util.RunJar /yuxh/app/apache-hive-2.*/lib/hive-cli-2.*.jar org.apache.hadoop.hive.cli.CliDriver
          posted @ 2017-03-29 16:01 yuxh 閱讀(1591) | 評論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2015-09-23 21:14 yuxh 閱讀(4419) | 評論 (0)編輯 收藏
          appfuse3.5使用Hibernate4.3.6, 而Hibernate日志框架使用了jboss-logging,想在后臺打出sql的參數一直無法生效。
          檢查配置文件,框架里面的兩個配置文件,src/test/resources/log4j2.xml(單元測試時配置),src/main/resources/log4j2.xml(運行時配置)
          搞清log4j2的配置后,各種修改(主要是
            <Logger name="org.hibernate.SQL" level="trace"/>
            <Logger name="org.hibernate.type" level="trace"/>)
          用junit測試任然無法打印出真實參數。根據這些實踐,確定log4j2是使用無誤生效的,只是org.hibernate這部分的logger一直未起效
          參考國內外網站,一直無人回答hibernate4的這個問題,有人指出這部分Hibernate官方文檔只是提了一句,一直未更新相關內容。最后有人提到應該是 jboss-logging 的LoggerProviders這個類的問題,看實現對log4j2已經做支持。最后發現 jboss-logging使用的是3.2.0.beta,對比相關類的源代碼,更改為3.2.0.Final,生效!

          P.S 把這個問題提交給Appfuse官網,issue APF-1478,作者標志為4.0版本修復。
          posted @ 2015-07-22 14:11 yuxh 閱讀(298) | 評論 (0)編輯 收藏
          新電腦裝上eclipse4.4.2,導入maven項目之后,依賴庫總是有很多錯誤。最后搜索到可能是eclipse的bug(據說是JAVA_HOME沒有正確傳遞),查看到eclipse默認的是安裝的jre目錄,修改到jdk目錄下,依賴問題解決。
          不過目前版本仍然沒有解決pom文件的“Plugin execution not covered by lifecycle configuration”錯誤,暫時忽略不管吧。
          posted @ 2015-06-02 10:27 yuxh 閱讀(332) | 評論 (0)編輯 收藏
          本打算繼承一個API中的Parent類(Parent繼承自GrandParent類),重寫其中的service方法,copy了Parent的service方法。不過發現Parent的service中也有super.service方法。當時考慮直接調用GrandParent的service方法。。。未遂(包括反射也不行)。正好看到老外寫的一篇文章,翻譯:
          在Son類里面寫一個test方法:
          public void test() {
           
          super.test();
           
          this.test();
          }
          反編譯之后:
          public void test()
              {
              
          //    0    0:aload_0         
              
          //    1    1:invokespecial   #2   <Method void Parent.test()>
              
          //    2    4:aload_0         
              
          //    3    5:invokevirtual   #3   <Method void test()>
              
          //    4    8:return          
              }
          使用ASM可以完成對GrandParent方法的調用
          public class GrandParent {
              
          public void test() {
                      System.out.println(
          "test of GrandParent");
              }
          }

          public class Parent extends GrandParent{
              
          public void test() {
                  System.out.println(
          "test of Parent");
              }
          }

          public class Son extends Parent{
              
          public void test() {
                  System.out.println(
          "test of Son");
              }
          }
          調用Son實例的test方法只會執行Son的test方法。而ASM可以修改class,先寫一個Example類繼承Son,重寫test方法

           1 import java.io.FileOutputStream;
           2  
           3 import org.objectweb.asm.ClassWriter;
           4 import org.objectweb.asm.MethodVisitor;
           5 import org.objectweb.asm.Opcodes;
           6  
           7 public class ASMByteCodeManipulation extends ClassLoader implements Opcodes {
           8  
           9  public static void main(String args[]) throws Exception {
          10   ClassWriter cw = new ClassWriter(0);
          11   cw.visit(V1_1, ACC_PUBLIC, "Example"null"Son"null);
          12  
          13   // creates a MethodWriter for the (implicit) constructor
          14   MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>""()V"null,null);
          15   mw.visitVarInsn(ALOAD, 0);
          16   mw.visitMethodInsn(INVOKESPECIAL, "Son""<init>""()V");
          17   mw.visitInsn(RETURN);
          18   mw.visitMaxs(11);
          19   mw.visitEnd();
          20  
          21   // creates a MethodWriter for the 'test' method
          22   mw = cw.visitMethod(ACC_PUBLIC, "test""()V"nullnull);
          23   mw.visitFieldInsn(GETSTATIC, "java/lang/System""out","Ljava/io/PrintStream;");
          24   mw.visitLdcInsn("test of AI3");
          25   mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream""println",
          26     "(Ljava/lang/String;)V");
          27   //Call test() of GrandParent
          28   mw.visitVarInsn(ALOAD, 0);
          29   mw.visitMethodInsn(INVOKESPECIAL, "GrandParent""test""()V");
          30   //Call test() of GrandParent
          31   mw.visitVarInsn(ALOAD, 0);
          32   mw.visitMethodInsn(INVOKESPECIAL, "Parent""test""()V");
          33   //Call test() of GrandParent
          34   mw.visitVarInsn(ALOAD, 0);
          35   mw.visitMethodInsn(INVOKESPECIAL, "Son""test""()V");
          36   mw.visitInsn(RETURN);
          37   mw.visitMaxs(21);
          38   mw.visitEnd();
          39  
          40   byte[] code = cw.toByteArray();
          41   FileOutputStream fos = new FileOutputStream("Example.class");
          42   fos.write(code);
          43   fos.close();
          44  
          45   ASMByteCodeManipulation loader = new ASMByteCodeManipulation();
          46   Class<?> exampleClass = loader.defineClass("Example", code, 0,
          47     code.length);
          48   Object obj = exampleClass.newInstance();
          49   exampleClass.getMethod("test"null).invoke(obj, null);
          50  
          51  }
          52 }
          輸出:
          test of AI3
          test of GrandParent
          test of Parent
          test of Son
          看看怎樣實現的,11行定義一個新的類Example繼承Son。22行,Example重寫test方法,先打印“test of AI3”,再分別在29、32、35行調用GrandParent、Parent、Son的test方法。
           main方法中,45行創建Example的實例,再用反射調他的test方法。
          使用invokespecial這種方式也有局限,只能從子類調用。否則報錯:
          Exception in thread "main" java.lang.VerifyError: (class: Example, method: test1 signature: (LAI2;)V) Illegal use of nonvirtual function call
          posted @ 2012-05-31 11:23 yuxh 閱讀(2057) | 評論 (0)編輯 收藏
          使用Google calendar v3 API的時候,大量發現Builder使用。比如Credential類,查了查Builder模式的講解,始終感覺代碼的實現和標準定義不太相同。最后發現這種實現方式是《Effective java 2nd》中的一種實現(Item 2: Consider a builder when faced with many constructor parameters)。靜態工廠和構造器都有一個通病:對于存在大量可選構造參數的對象,擴展性不好。經典的解決方案是提供多個構造函數,第一個構造函數只有必須的參數,第二個構造函數除了必須參數還有一個可選參數,第三個除了必須參數還有兩個可選參數。。。這樣下去知道最后一個可選參數出現(telescoping constructor)。這種方案的問題是,當構建對象的時候很容易把其中兩個參數的位置放反。。。。(難發現的bug)
          另一種解決方案是JavaBean 模式,先調用無參構造函數再調用各個set方法來組裝對象。這種方案的問題是不能強制一致性。如果沒有set某些必須的參數的話,對象可能處于不一致(
          inconsistent)的狀態(難發現的bug)。另外一個缺點是JavaBean模式不能讓類immutable,需要程序員額外工作保證線程安全。
          第三種方式就是Builder設計模式。這種方式混合了telescoping constructor模式的安全性和JavaBean模式的可讀性。客戶端調用有所有必填參數的構造器(或靜態工廠),得到一個builder對象。然后調用builder對象的方法去set各個選填參數。最后調用無參的build方法產生一個immutable的對象實例。immutable對象有非常多優點而且可能很有用。builder的set方法都是返回builder本身,所以調用也是可以chained。如:
            GoogleCredential credentialNew = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                              .setJsonFactory(JSON_FACTORY).setClientSecrets(clientSecrets)
                              .addRefreshListener(
          new CredentialStoreRefreshListener(userID, new DBCredentialStore())).build()
                              .setAccessToken(accessToken).setRefreshToken(refreshToken)
          客戶端代碼很好寫,更重要的是易讀。Builder模式模擬了在Ada和Python語言里的命名可選參數(named optional parameters)。
          同時Builder類設置為static也是對Item 22:Favor static member classes over nonstatic的實踐
          posted @ 2012-05-30 17:44 yuxh 閱讀(398) | 評論 (0)編輯 收藏
          以典型的客戶端-服務器端授權為例
          一 基本流程
          使用Google Calendar v3 ,如果以servlet作為代理,可以使用官方示例,自己寫一個類A.java繼承AbstractAuthorizationCodeServlet類,這個類主要用于跳轉到google提供的授權頁面,如果用戶同意授權,則根據A類中的URL(這個必須和注冊的google 回調路徑相同,比如oauth_callback否則報錯)重定向到B類,B.java 繼承AbstractAuthorizationCodeCallbackServlet類,這個訪問路徑類似http://www.example.com/oauth_callback?code=ABC1234。這里我配置oauth_callback為servlet的訪問路徑,B類中的
          onSuccess方法將根據獲得的access Token(這是根據傳過來的code獲得的)做業務操作。

          二 需要參數的情況
          有些業務需要用戶傳參數,直接傳參數給A,再試圖在B中獲取是不行的!B類中只能獲取某些固定的參數,如code。要想傳用戶參數,我們可以在A中先獲取,把幾個參數組裝為json格式字符串(還可以繼續base64編碼),把這個字符串作為state的值,再重定向到授權頁面,同意后state參數可以傳到B類,取值解析json字符串(或先base64解碼),得到參數。
          由于API中AuthorizationCodeRequestUrl有處理state的方法,而AbstractAuthorizationCodeServlet已經直接封裝,為了使用setState,直接在A類中繼承HttpServlet重寫service方法,復制大部分AbstractAuthorizationCodeServlet的內容,稍作修改:
          resp.sendRedirect(flow.newAuthorizationUrl().setState(json).setRedirectUri(redirectUri).build());

          三 關于refresh token
          默認情況下,用戶授權之后token會有一個小時的有效期,之后你可以通過refresh token再重新獲取token。所以,如果不需要用戶再次授權,可以在第一次,保存好token、refresh token、ExpirationTime。實例中用了JDO來實現,自己如果使用數據庫保存,可類似寫一個類實現CredentialStore類。使用的時候,現在數據庫中取出,再創建credential,如:
                      GoogleCredential credentialNew = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                              .setJsonFactory(JSON_FACTORY).setClientSecrets(clientSecrets)
                              .addRefreshListener(new CredentialStoreRefreshListener(userID, new DBCredentialStore())).build()
                              .setAccessToken(accessToken).setRefreshToken(refreshToken)
                              .setExpirationTimeMilliseconds(expirationTimeMilliseconds);
          在無效的情況下,Listener會自動去用refresh token請求。
          posted @ 2012-05-08 11:40 yuxh 閱讀(954) | 評論 (0)編輯 收藏
          json格式經常需要用到,google提供了一個處理json的項目:GSON,能很方便的處理轉換java對象和JSON表達。他不需要使用annotation,也不需要對象的源代碼就能使用。
          以字符串為例介紹:
          1 。構造json 字符串
            例如要傳送json格式的字符串
                  String appID = req.getParameter("appID");
                  String userID  = req.getParameter("userID");
                  Map map = new HashMap();
                  map.put("appID", appID);
                  map.put("userID", userID);
                  Gson gson = new Gson();
                  String state = gson.toJson(map);
          2.解析json字符串
                    JsonParser jsonparer = new JsonParser();//初始化解析json格式的對象
                    String state = req.getParameter("state");
                    String appID = jsonparer.parse(state).getAsJsonObject().get("appID").getAsString();
                    String userID = jsonparer.parse(state).getAsJsonObject().get("userID").getAsString();
          posted @ 2012-05-08 10:23 yuxh 閱讀(2146) | 評論 (1)編輯 收藏
          通用協調時(UTC, Universal Time Coordinated),格林尼治平均時(GMT, Greenwich Mean Time) 由于歷史原因,這兩個時間是一樣的。
          北京時區是東八區,領先UTC八個小時,在電子郵件信頭的Date域記為+0800。
          轉換中,最重要的公式就是:
          UTC + 時區差 = 本地時間
              public static Calendar convertToGmt(Calendar cal) {
                  Date date 
          = cal.getTime();
                  TimeZone tz 
          = cal.getTimeZone();

                  System.out.println(
          "input calendar has date [" + date + "]");

                  
          // Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
                  long msFromEpochGmt = date.getTime();

                  
          // gives you the current offset in ms from GMT at the current date
                  int offsetFromUTC = tz.getOffset(msFromEpochGmt);
                  System.out.println(
          "offset is " + offsetFromUTC);

                  
          // create a new calendar in GMT timezone, set to this date and add the offset     
                  Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
                  Calendar utcCal 
          = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

                  gmtCal.setTime(date);
                  //根據東西時區,選擇offsetFromUTC為正或負數
                  gmtCal.add(Calendar.MILLISECOND, offsetFromUTC);

                  utcCal.setTime(date);
                  utcCal.add(Calendar.MILLISECOND, offsetFromUTC);

                  System.out.println(
          "Created GMT cal with date [" + gmtCal.getTime()
                          
          + "==" + utcCal.getTime() + "]");
                  
          return gmtCal;
              }
          posted @ 2012-03-15 23:08 yuxh 閱讀(1652) | 評論 (0)編輯 收藏
          Andriod 到3.2版本為止,webview方式下使用<input type="file" />點擊后都沒有反應。實際上頂層是有隱含的接口沒實現的,可以自己重寫這個方法來實現。以phonegap為例:

          public class App extends DroidGap {
              
          private ValueCallback<Uri> mUploadMessage;
              
          private final static int FILECHOOSER_RESULTCODE = 1;

              
          /** Called when the activity is first created. */
              @Override
              
          public void onCreate(Bundle savedInstanceState) {
                  
          super.onCreate(savedInstanceState);
                  
          super.init();
                  
          // WebView wv = new WebView(this);
                  
          // wv.setWebViewClient(new WebViewClient());
                  this.appView.setWebChromeClient(new CordovaChromeClient(App.this) {
                      
          // For Android 3.0+
                      public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                          mUploadMessage 
          = uploadMsg;
                          Intent i 
          = new Intent(Intent.ACTION_GET_CONTENT);
                          i.addCategory(Intent.CATEGORY_OPENABLE);
                          i.setType(
          "image/*");
                          App.
          this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
                      }

                      
          // The undocumented magic method override
                      
          // Eclipse will swear at you if you try to put @Override here
                      public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                          mUploadMessage 
          = uploadMsg;
                          Intent i 
          = new Intent(Intent.ACTION_GET_CONTENT);
                          i.addCategory(Intent.CATEGORY_OPENABLE);
                          i.setType(
          "image/*");
                          App.
          this.startActivityForResult(Intent.createChooser(i, "File Chooser"), App.FILECHOOSER_RESULTCODE);
                      }
                  });

                  
          // setContentView(wv);
                  super.loadUrl("file:///android_asset/www/login.html");
              }

              @Override
              
          protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
                  
          if (requestCode == FILECHOOSER_RESULTCODE) {
                      
          if (null == mUploadMessage)
                          
          return;
                      Uri result 
          = intent == null || resultCode != RESULT_OK ? null : intent.getData();
                      mUploadMessage.onReceiveValue(result);
                      mUploadMessage 
          = null;
                  }
              }
          }
          如果直接的webview方式,extends WebChromeClient即可。 參考:http://stackoverflow.com/questions/5907369/file-upload-in-webview
          posted @ 2012-03-12 12:54 yuxh 閱讀(5335) | 評論 (1)編輯 收藏
          weather.jsp:
          <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
          <%@ page import="java.io.*,java.net.*"%>
          <%
              StringBuffer sbf 
          = new StringBuffer();
              
          //Access the page
              try {
                
          //如果網絡設置了代理
                  System.setProperty("http.proxyHost""xxx");
                  System.setProperty(
          "http.proxyPort""80");
                  URL url 
          = new URL("http://www.google.com/ig/api?weather=london");
                  URLConnection urlConn 
          = url.openConnection();

                  BufferedReader in 
          = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
                  String inputLine;
                  
          while ((inputLine = in.readLine()) != null)
                      sbf.append(inputLine);
                  in.close();
                  System.out.println(
          "last="+sbf.toString());
              } 
          catch (MalformedURLException e) {
                  System.out.println(
          "MalformedURLException"+e);
              } 
          catch (IOException e) {
                  System.out.println(
          "IOException"+e);
              }
          %><%=sbf.toString()%>
          前臺js部分:

                  var childData   = function(selector, arg)
                  {
                          
          return selector.find(arg).attr('data');
                   }
                  $.ajax({
                      type : 
          "GET",
                      data : 
          "where=" ,
                      url : 
          "weather.jsp",
                      success : 
          function(data) {
                          console.debug('data
          ='+data);
                          forecast 
          = $(data).find('forecast_information');
                          cCondition 
          = $(data).find('current_conditions');

                          city 
          = childData(forecast, 'city');
                          
          if (city != undefined) {
                              date 
          = childData(forecast, 'forecast_date');

                              condition 
          = childData(cCondition, 'condition');
                              tempC 
          = childData(cCondition, 'temp_c');
                              humidity 
          = childData(cCondition, 'humidity');
                              icon 
          = childData(cCondition, 'icon');
                              $('#city').text(city);
                              $('#date').text(date);
                              $('#condition').text(condition);
                              $('#tempC').html(tempC 
          + '&deg; C');
                              $('#humidity').text(humidity);
                              $('#icon').attr({
                                  'src' : 'http:
          //www.google.com' + icon
                              });
                              $('#data').stop().show('fast');
                          } 
          else {
                              $('#error').stop().show('fast');
                          }
                      }
                  });
          posted @ 2012-02-22 08:58 yuxh 閱讀(239) | 評論 (0)編輯 收藏

          1. Code first approach:可能不能完全發揮框架和web services的能量,但能完成目標。減少了學習曲線,不用非常透徹了解web services概念,只要對某個框架有一定了解就能完成任務。
          2.Contract first approach:根據服務先寫WSDL文件,寫好之后使用框架的工具把WSDL轉換為依賴框架的代碼。

          一  介紹

          當客戶端調用你的web service的時候,他會發送一個消息過來(可能是soap 消息),如:

          <foo:concatRequest>
          <s1>abc</s1>
          <s2>123</s2>
          </foo:concatRequest>

          這時候如果有一個轉換器把這個soap消息轉換成java對象,然后調用你提供的java對象(方法)的話將會是非常方便的。幾個最流行的庫就是充當了這種轉換器功能,比如CXF, Axis2 , Metro (jdk6自帶的有)。

          手動創建WSDL文件比較容易出錯,可以使用eclipse進行可視化編輯。

          二 生成服務代碼

          像CXF這樣的 web service庫可以創建轉換器把進來的SOAP 消息轉換為Java對象,然后作為參數傳給方法。生成這些代碼,只需創建一個main:

          1 CXF方式:

          public static void main(String[] args) { WSDLToJava.main(new String[] { "-server", "-d", "src/main/java", "src/main/resources/SimpleService.wsdl" }); System.out.println("Done!"); }

          運行后會生成service endpoint interface(SEI),我們再寫一個類(比如SimpleServiceImpl)來實現這個接口,寫入自己的業務。還會生成傳入消息對應的java對象。同時生成一個服務器類:

          public class SimpleService_P1_Server { protected SimpleService_P1_Server() throws Exception { System.out.println("Starting Server"); Object implementor = new SimpleServiceImpl(); String address = "http://localhost:8080/ss/p1"; Endpoint.publish(address, implementor); } public static void main(String args[]) throws Exception { new SimpleService_P1_Server(); System.out.println("Server ready..."); Thread.sleep(5 * 60 * 1000); System.out.println("Server exiting"); System.exit(0); } }

          運行這個類你的web service就可以服務了。

          2 Axis2 方式

          用類似的寫main方法,或者配置eclipse的axis2插件可生成:在WSDL文件上,右鍵->web service->generate java bean skeleton

          界面的上半部分針對服務端,可以根據需要調整生成的級別,下半部分是生成客戶端。具體的級別可參考eclipse的幫助文檔。一路下一步,最后根據命名空間生成包路徑的文件,里面有XXSkeletonInterface.java 文件(如果生成的時候選擇了生成接口的話),還有一個XXSkeleton實現了這個接口,也是我們需要修改這部分代碼完成我們業務的地方。實際上有一個XXMessageReceiverInOut.java的類接收請求的消息,并調用XXSkeletonInterface。使用eclipse的axis2插件的時候,會自動在web-inf文件夾下生成service\xx(你的wsdl服務名),這下面還要一個meta-inf文件夾裝有wsd文件和一個services.xml配置文件。services.xml文件可配置包括XXMessageReceiverInOut類在內的選項。

          二 生成客戶端代碼

          為了調用這些web service,同樣可以用CXF這些庫來生成在客戶端運行的轉換器(稱為service stub)。當調用stub里的方法的時候,他會把你的數據/對象 轉換為正確的XML格式,然后發送給真正的web service。當他收到響應的時候,又會把XML轉回Java。

          1 CXF 方式

          和生成服務器端類似,使用方法

          WSDLToJava.main(new String[] {
          "-client",
          "-d", "src/main/java",
          "src/main/resources/SimpleService.wsdl" });

          運行后會生成客戶端代碼:

          public final class SimpleService_P1_Client { private static final QName SERVICE_NAME = new QName("http://ttdev.com/ss", "SimpleService"); private SimpleService_P1_Client() {} public static void main(String args[]) throws Exception { URL wsdlURL = SimpleService_Service.WSDL_LOCATION; if (args.length > 0) { File wsdlFile = new File(args[0]); try { if (wsdlFile.exists()) { wsdlURL = wsdlFile.toURI().toURL(); } else { wsdlURL = new URL(args[0]); } } catch (MalformedURLException e) { e.printStackTrace(); } } SimpleService_Service ss = new SimpleService_Service(wsdlURL, SERVICE_NAME); SimpleService port = ss.getP1(); { System.out.println("Invoking concat..."); com.ttdev.ss.ConcatRequest _concat_parameters = null; java.lang.String _concat__return = port.concat(_concat_parameters); System.out.println("concat.result=" + _concat__return); } System.exit(0); } }

          SimpleService_Service是創建的service stub,他模擬了客戶端的服務。我們需要修改這個類中的_concat_parameters部分,加入參數:

          com.ttdev.ss.ConcatRequest _concat_parameters = new ConcatRequest();
          _concat_parameters.setS1("abc");
          _concat_parameters.setS2("123");

          現在就可以運行客戶端代碼了。SEI中有一些注解,可以修改,不細說。

           

          2 Axis2 方式
          和生成服務端類似,利用eclipse插件直接生成,包路徑類似,有一個XXStub類,這個類里面有包括請求和應答消息在內的內部類。使用的時候,先對請求消息參數類按業務需求賦值,最后調用Stub的請求方法。可以使用Stub的構造函數指定目標endpoint。

           

          posted @ 2011-10-24 00:26 yuxh 閱讀(404) | 評論 (0)編輯 收藏

          有兩種SOAP message風格,documentRPC,他們定義了SOAP message body的格式。使用document風格時(包括wrapped和unwrapped),在wsdl中有一個非空的types部分,這個部分用XML Schema language定義了web service要用到的類型。wsgen工具從SIB(有SEI就足夠了)中生成與XSD對應的java類。用java代碼生成WSDL文件的時候需要一些java類,wsgen工具可以生成這些Java類,生成的這些java類被稱為wsgen artifacts,底層的JWS類庫會用到這些類,特別是JAX-B系列的包,會用來轉換(marshal)java類實例(that is, Java in-memory objects)為XML類型的XML實例(滿足XML Schema document的XML文檔實例),

          The inverse operation is used to convert (unmarshal) an XML document instance to an in-memory
          object, an object of a Java type or a comparable type in some other language。因此wsgen工具生成的artifacts,支持了Java為基礎的web service的互操作性。JAX-B類庫提供了Java和XSD類型轉換的底層支持。

          For the most part, the wsgen utility can be used without our bothering to inspect the artifacts that it produces. For the most part, JAX-B remains unseen infrastructure.

          wsgen artifacts實際上是wsdl message的數據類型,他們和XML Schema type綁定,每個message的XML Schema types從這些java類型得來的。注:在當前的jdk1.6.24中,已經融入wsgen自動生成的過程,不需手動調用。

          wsgen工具可用來生成wsdl文件,如:% wsgen -cp "." -wsdl ch01.ts.TimeServerImpl 。這為TimeServer服務生成了wsdl。用wsgen生成的wsdl和通過訪問發布的服務生成的wsdl 有個很大的區別:wsgen生成的沒有endpoint,因為這個URL是在發布服務的時候決定的。其他地方兩個wsdl是相同的。

          wsimport(以前叫wsdl2java和 java2wsdl更形象)工具可使用WSDL生成用來幫助寫客戶端的artifacts .

          1 先契約再編碼方式
          一個例子:得到一個tempConvert.wsdl文件,使用命令 wsimport -keep -p ch02.tc tempConvert.wsdl ,命令根據wsdl的portType生成一個SEI類,把SEI的interface換為class,再把方法改為實現就可變為SIB。把該SIB發布,再使用命令wsimport -keep -p clientTC http://localhost:5599/tc?wsdl,來生成客戶端輔助類
          2 編碼優先
          服務被發布之后,會自動生成WSDL供客戶端使用。然而,使用annotations可以控制WSDL或WSDL-generated artifacts的生成。

          posted @ 2011-10-08 21:47 yuxh 閱讀(581) | 評論 (0)編輯 收藏

          來自

          http://stackoverflow.com/questions/1099300/whats-the-difference-between-getpath-getabsolutepath-and-getcanonicalpath

          C:\temp\file.txt" - this is a path, an absolute path, a canonical path

          .\file.txt This is a path, It's not an absolute path nor canonical path.

          C:\temp\myapp\bin\..\\..\file.txt This is a path, and an absolute path, it's not a canonical path

          Canonical path is always an absolute path.

          Converting from a path to a canonical path makes it absolute (通常會處理改變當前目錄,所以像. ./file.txt 變為c:/temp/file.txt). The canonical path of a file just "purifies" the path, 去除和解析類似“ ..\” and resolving symlinks(on unixes)

          In short:

          • getPath() gets the path string that the File object was constructed with, and it may be relative current directory.
          • getAbsolutePath() gets the path string after resolving it against the current directory if it's relative, resulting in a fully qualified path.
          • getCanonicalPath() gets the path string after resolving any relative path against current directory, and removes any relative pathing (. and ..), and any file system links to return a path which the file system considers the canonical means to reference the file system object to which it points.

          Also, each of this has a File equivalent which returns the corresponding File object.

          The best way I have found to get a feel for things like this is to try them out:

          import java.io.File;
          public class PathTesting {
                  public static void main(String [] args) {
                          File f = new File("test/.././file.txt");
                          System.out.println(f.getPath());
                          System.out.println(f.getAbsolutePath());
                          try {
                                  System.out.println(f.getCanonicalPath());
                          }
                          catch(Exception e) {}
                  }
          }

          Your output will be something like:

          test\..\.\file.txt
          C:\projects\sandbox\trunk\test\..\.\file.txt
          C:\projects\sandbox\trunk\file.txt

          So, getPath() gives you the path based on the File object, which may or may not be relative; getAbsolutePath() gives you an absolute path to the file; and getCanonicalPath() gives you the unique absolute path to the file. Notice that there are a huge number of absolute paths that point to the same file, but only one canonical path.

          When to use each? Depends on what you're trying to accomplish, but if you were trying to see if two Files are pointing at the same file on disk, you could compare their canonical paths.
          posted @ 2011-06-24 13:42 yuxh 閱讀(506) | 評論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2011-06-15 14:47 yuxh 閱讀(897) | 評論 (0)編輯 收藏

          DTDs

          Introduced as part of the XML 1.0 specification, DTDs are the oldest constraint model around in the XML world. They're simply to use, but this simplicity comes at a price: DTDs are inflexible, and offer you little for data type validation as well.

          XML Schema (XSD)

          XML Schema is the W3C's anointed successor to DTDs. XML Schemas are literally orders of magnitude more flexible than DTDs, and offer an almost dizzying array of support for various data types. However, just as DTDs were simple and limited, XML Schemas are flexible, complex, and (some would argue) bloated. It takes a lot of work to write a good schema, even for 50- or 100-line XML documents. For this reason, there's been a lot of dissatisfaction with XML Schema, even though they are widely being used.

          [prefix]:[element name]
          元素:
          root元素必須包含所有文檔中的元素,只能有一個root元素。元素名只能以下劃線或字母開頭,不能有空格,區分大小寫。開元素必須有對應閉元素(也有類似html的簡寫,如<img src="/images/xml.gif" />)。文檔由DTD或schema來限制它是否合格。
          屬性:
          什么時候用屬性?基本原則:多個值的數據用元素,單值的數據用元素。如果數據有很多值或者比較長,數據最可能屬于元素。他主要被當作文本,容<rss:author>Doug Hally</rss:author> <journal:author>Neil Gaiman</journal:author>易搜索,好用。比如一本書的章節描述。然而如果數據主要作為單值處理的話,最好作為屬性。如果搞不清楚,可以安全的使用元素。
          命名空間Namespaces:
          xml的命名空間是一種用一個特定的URI來關聯XML文檔里的一個或多個元素的方法。意味著元素是由名字和命名空間一起來識別的。許多復雜的XML文件里,同一個名字會有多個用途。比如,一個RSS feed有一個作者,這個作者同時是每個日記的。雖然這些數據都用author元素來表示,但他們不應該被當作同一個類型的數據。命名空間很好的解決了這個問題,命名空間說明書要求一個前綴和唯一的URI聯合起來區分不同命名空間里的元素。如http://www.neilgaiman.com/entries作為URI,聯合前綴journal用來表示日志相關的元素。
          <rdf:RDF xmlns:rss="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:journal="http://www.neilgaiman.com/entries">,然后就可使用了:
          <rss:author>Doug Hally</rss:author> <journal:author>Neil Gaiman</journal:author>實際上在使用命名空間前綴的時候再定義也可以的:
          <rss:author xmlns:rss="http://www.w3.org/1999/02/22-rdf-syntax-ns#">Doug Hally</rss:author>
          如果名字沒有命名空間,不代表在默認命名空間中,而是xml處理器以在任何命名空間以外方式解釋他。要聲明默認命名空間的話就不用后面冒號部分,如<Insured xmlns="使用的一些術語:
          • The name of a namespace (such as http://www.ibm.com/software) is the namespace URI.

          • The element or attribute name can include a prefix and a colon (as in prod:Quantity). A name in that form is called a qualified name, or QName, and the identifier that follows the colon is called a local name. If a prefix is not in use, neither is the colon, and the QName and local name are identical.

          • An XML identifier (such as a local name) that has no colon is sometimes called an NCName. (The NC comes from the phrase no colon.)

          Entity references:
          用來處理轉義字符,語法是& [entity name] ;XML解析器碰到這種entity reference,就會用對應的值替換掉他。如&lt;(<),&gt;(>),&amp;(&),&quot;("),&apos;(')。注意entity reference是用戶可定義的。比如多處用到版權提示,自己定義后以后更改就方便了:<ora:copyright>&OReillyCopyright;</ora:copyright>。除了用來表示數據中的復雜或特殊字符外,entity reference還會有更多用途。

          不解析的數據
          當傳輸大量數據給應用且不用xml解析的時候,CDATA就有用了。當大量的字符需要用entity reference轉義的時候,或空格必須保留的時候,使用CDATA。<![CDATA[….]]>

          posted @ 2011-03-24 09:05 yuxh 閱讀(317) | 評論 (0)編輯 收藏
          轉自http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm,把csv文件按分隔符切割后放在數組中。
          // This will parse a delimited string into an array of arrays. 
             // The default delimiter is the comma, but this

          // can be overriden in the second argument.
              CSVToArray:function(strData, strDelimiter){
           
                  
          // Check to see if the delimiter is defined. If not,
                  // then default to comma.
                  strDelimiter = (strDelimiter || ",");
                  
          // Create a regular expression to parse the CSV values.
                  var objPattern = new RegExp(
                      (
                          
          // Delimiters.
                          "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
           
                          
          // Quoted fields.
                          "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
           
                          
          // Standard fields.
                          "([^\"\\" + strDelimiter + "\\r\\n]*))"
                      ),
                      
          "gi"
                      );
           
           
                  // Create an array to hold our data. Give the array
                  // a default empty first row.
                  var arrData = [[]];
           
                  // Create an array to hold our individual pattern
                  // matching groups.
                  var arrMatches = null;
           
           
                  // Keep looping over the regular expression matches
                  // until we can no longer find a match.
                  while (arrMatches = objPattern.exec( strData )){
           
                      // Get the delimiter that was found.
                      var strMatchedDelimiter = arrMatches[ 1 ];
           
                      // Check to see if the given delimiter has a length
                      // (is not the start of string) and if it matches
                      // field delimiter. If id does not, then we know
                      // that this delimiter is a row delimiter.
                      if (
                          strMatchedDelimiter.length &&
                          (strMatchedDelimiter != strDelimiter)
                          ){
           
                          // Since we have reached a new row of data,
                          // add an empty row to our data array.
                          arrData.push( [] );
                      }
           
           
                      // Now that we have our delimiter out of the way,
                      // let's check to see which kind of value we
                      // captured (quoted or unquoted).
                      if (arrMatches[ 2 ]){
           
                          // We found a quoted value. When we capture
                          // this value, unescape any double quotes.
                          var strMatchedValue = arrMatches[ 2 ].replace(
                              new RegExp( 
          "\"\"""g" ),
                              
          "\""
                              );
           
                      }
           else {
           
                          
          // We found a non-quoted value.
                          var strMatchedValue = arrMatches[ 3 ];
                      }

           
           
                      
          // Now that we have our value string, let's add
                      // it to the data array.
                      arrData[ arrData.length - 1 ].push( strMatchedValue );
                  }
           
                  
          // Return the parsed data.
                  return( arrData );
              }
          posted @ 2010-12-03 09:06 yuxh 閱讀(1157) | 評論 (0)編輯 收藏

          導航

          <2010年12月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          統計

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          收藏夾

          博客

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 巴青县| 辽阳县| 英超| 手机| 台前县| 永和县| 亳州市| 宁陵县| 平陆县| 方正县| 封丘县| 合肥市| 鄂尔多斯市| 江门市| 盐边县| 桑植县| 安阳县| 库伦旗| 澳门| 奈曼旗| 磐安县| 满洲里市| 瑞金市| 双江| 乡城县| 凤阳县| 台北市| 保靖县| 阳城县| 色达县| 涿鹿县| 咸宁市| 河北省| 会昌县| 营山县| 观塘区| 中西区| 永新县| 昌邑市| 原阳县| 旌德县|