2)解壓縮,下面的命令行如啟動報錯,請自行查略Hive啟動配置
-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
用junit測試任然無法打印出真實參數。根據這些實踐,確定log4j2是使用無誤生效的,只是org.hibernate這部分的logger一直未起效
P.S 把這個問題提交給Appfuse官網,issue APF-1478,作者標志為4.0版本修復。
JAVA_HOME沒有正確傳遞
),查看到eclipse默認的是安裝的jre目錄,修改到jdk目錄下,依賴問題解決。不過目前版本仍然沒有解決pom文件的“Plugin execution not covered by lifecycle configuration”錯誤,暫時忽略不管吧。
在Son類里面寫一個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
}
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");
}
}
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(1, 1);
19 mw.visitEnd();
20
21 // creates a MethodWriter for the 'test' method
22 mw = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
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(2, 1);
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 GrandParent
test of Parent
test of Son
使用invokespecial這種方式也有局限,只能從子類調用。否則報錯:
.setJsonFactory(JSON_FACTORY).setClientSecrets(clientSecrets)
.addRefreshListener(new CredentialStoreRefreshListener(userID, new DBCredentialStore())).build()
.setAccessToken(accessToken).setRefreshToken(refreshToken)
同時Builder類設置為static也是對Item 22:Favor static member classes over nonstatic的實踐
一 基本流程
使用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類中的
二 需要參數的情況
有些業務需要用戶傳參數,直接傳參數給A,再試圖在B中獲取是不行的!B類中只能獲取某些固定的參數,如code。要想傳用戶參數,我們可以在A中先獲取,把幾個參數組裝為json格式字符串(還可以繼續base64編碼),把這個字符串作為state的值,再重定向到授權頁面,同意后state參數可以傳到B類,取值解析json字符串(或先base64解碼),得到參數。
由于API中AuthorizationCodeRequestUrl有處理state的方法,而AbstractAuthorizationCodeServlet已經直接封裝,為了使用setState,直接在A類中繼承HttpServlet重寫service方法,復制大部分AbstractAuthorizationCodeServlet的內容,稍作修改:
三 關于refresh token
默認情況下,用戶授權之后token會有一個小時的有效期,之后你可以通過refresh token再重新獲取token。所以,如果不需要用戶再次授權,可以在第一次,保存好token、refresh token、ExpirationTime。實例中用了JDO來實現,自己如果使用數據庫保存,可類似寫一個類實現CredentialStore類。使用的時候,現在數據庫中取出,再創建credential,如:
.setJsonFactory(JSON_FACTORY).setClientSecrets(clientSecrets)
.addRefreshListener(new CredentialStoreRefreshListener(userID, new DBCredentialStore())).build()
.setAccessToken(accessToken).setRefreshToken(refreshToken)
.setExpirationTimeMilliseconds(expirationTimeMilliseconds);
在無效的情況下,Listener會自動去用refresh token請求。
以字符串為例介紹:
1 。構造json 字符串
例如要傳送json格式的字符串
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);
String state = req.getParameter("state");
String appID = jsonparer.parse(state).getAsJsonObject().get("appID").getAsString();
String userID = jsonparer.parse(state).getAsJsonObject().get("userID").getAsString();
UTC + 時區差 = 本地時間
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);
utcCal.setTime(date);
utcCal.add(Calendar.MILLISECOND, offsetFromUTC);
System.out.println("Created GMT cal with date [" + gmtCal.getTime()
+ "==" + utcCal.getTime() + "]");
return gmtCal;
}
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;
}
}
}
<%@ 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部分:
{
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 + '° C');
$('#humidity').text(humidity);
$('#icon').attr({
'src' : 'http://www.google.com' + icon
});
$('#data').stop().show('fast');
} else {
$('#error').stop().show('fast');
}
}
});
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中有一些注解,可以修改,不細說。
有兩種SOAP message風格,document 和RPC,他們定義了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的生成。
來自
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.
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.
Files
are pointing at the same file on disk, you could compare their canonical paths.