Browse Source

云燕2次提供最新代码

15810770710@163.com 4 years ago
parent
commit
e1d95155a9

+ 15 - 0
pom.xml

@@ -63,6 +63,21 @@
             <artifactId>logstash-logback-encoder</artifactId>
             <version>5.0</version>
         </dependency>
+        <dependency>
+            <groupId>info.aspirecn.cloud.yysj</groupId>
+            <artifactId>cloud-yysj-commons-lang</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.2.1</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 34 - 0
src/main/java/info/aspirecn/cloud/yysj/constants/CommonConstant.java

@@ -0,0 +1,34 @@
+package info.aspirecn.cloud.yysj.constants;
+
+/**
+ * @author xusonglin
+ * @version V1.0
+ **/
+public class CommonConstant {
+    //签名算法HmacSha256
+    public static final String HMAC_SHA256 = "HmacSHA256";
+    //编码UTF-8
+    public static final String ENCODING = "UTF-8";
+    //UserAgent
+    public static final String USER_AGENT = "demo/aliyun/java";
+    //换行符
+    public static final String LF = "\n";
+    //串联符
+    public static final String SPE1 = ",";
+    //示意符
+    public static final String SPE2 = ":";
+    //连接符
+    public static final String SPE3 = "&";
+    //赋值符
+    public static final String SPE4 = "=";
+    //问号符
+    public static final String SPE5 = "?";
+    //默认请求超时时间,单位毫秒
+    public static final int DEFAULT_TIMEOUT = 1000;
+    //参与签名的系统Header前缀,只有指定前缀的Header才会参与到签名中
+    public static final String CA_HEADER_TO_SIGN_PREFIX_SYSTEM = "X-Ca-";
+    //JSON类型Content-Type
+    public static final String CONTENT_TYPE_JSON = "application/json; charset=UTF-8";
+    //POST
+    public static final String POST = "POST";
+}

+ 35 - 0
src/main/java/info/aspirecn/cloud/yysj/constants/HttpHeader.java

@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package info.aspirecn.cloud.yysj.constants;
+
+/**
+ * HTTP头常量
+ */
+public class HttpHeader {
+    //请求Header Accept
+    public static final String HTTP_HEADER_ACCEPT = "Accept";
+    //请求Body内容MD5 Header
+    public static final String HTTP_HEADER_CONTENT_MD5 = "Content-MD5";
+    //请求Header Content-Type
+    public static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
+    //请求Header UserAgent
+    public static final String HTTP_HEADER_USER_AGENT = "User-Agent";
+    //请求Header Date
+    public static final String HTTP_HEADER_DATE = "Date";
+}

+ 35 - 0
src/main/java/info/aspirecn/cloud/yysj/constants/SystemHeader.java

@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package info.aspirecn.cloud.yysj.constants;
+
+/**
+ * 系统HTTP头常量
+ */
+public class SystemHeader {
+    //签名Header
+    public static final String X_CA_SIGNATURE = "X-Ca-Signature";
+    //所有参与签名的Header
+    public static final String X_CA_SIGNATURE_HEADERS = "X-Ca-Signature-Headers";
+    //请求时间戳
+    public static final String X_CA_TIMESTAMP = "X-Ca-Timestamp";
+    //请求放重放Nonce,15分钟内保持唯一,建议使用UUID
+    public static final String X_CA_NONCE = "X-Ca-Nonce";
+    //APP KEY
+    public static final String X_CA_KEY = "X-Ca-Key";
+}

+ 0 - 25
src/main/java/info/aspirecn/cloud/yysj/entity/CommonResponseObject.java

@@ -1,25 +0,0 @@
-package info.aspirecn.cloud.yysj.entity;
-
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * @author xusonglin
- * @version V1.0
- **/
-@Data
-public class CommonResponseObject implements Serializable {
-
-    private int code;
-    private int resultCode;
-    private Object resultBody;
-    private int isCharge;
-    private int feeCount;
-    private int jfFree;
-    private int jflx;
-    private String resultDesc;
-    private int ifSuccessAsyn;
-    private String asynResultBody;
-    private boolean cacheLogSign;
-}

+ 27 - 0
src/main/java/info/aspirecn/cloud/yysj/entity/VehicleTrajectoryParamObject.java

@@ -0,0 +1,27 @@
+package info.aspirecn.cloud.yysj.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author xusonglin
+ * @version V1.0
+ **/
+@Data
+public class VehicleTrajectoryParamObject implements Serializable {
+    private static final long serialVersionUID = -1729801929068765654L;
+
+    // 车牌号
+    private String vehicleNumber;
+    // 车牌颜色
+    private String vehiclePlateColorCode;
+    // 收货日期 YYYYMMDDhhmmss
+    private String goodsReceiptDateTime;
+    // 收货地址的国家行政区划代码
+    private String receiptCountrySubdivisionCode;
+    // 发货日期 YYYYMMDDhhmmss
+    private String despatchActualDateTime;
+    // 发货地址的国家行政区划代码
+    private String loadingCountrySubdivisionCode;
+}

+ 77 - 0
src/main/java/info/aspirecn/cloud/yysj/entity/VehicleTrajectoryRequest.java

@@ -0,0 +1,77 @@
+package info.aspirecn.cloud.yysj.entity;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Request
+ */
+@Data
+@NoArgsConstructor
+public class VehicleTrajectoryRequest {
+    public VehicleTrajectoryRequest(String host, String path, String appKey, String appSecret, int timeout) {
+        this.host = host;
+        this.path = path;
+        this.appKey = appKey;
+        this.appSecret = appSecret;
+        this.timeout = timeout;
+    }
+
+    /**
+     * (必选)Host
+     */
+    private String host;
+
+    /**
+     * (必选)Path
+     */
+    private String path;
+
+    /**
+     * (必选)APP KEY
+     */
+    private String appKey;
+
+    /**
+     * (必选)APP密钥
+     */
+    private String appSecret;
+
+    /**
+     * (必选)超时时间,单位毫秒,设置零默认使用com.aliyun.apigateway.demo.constant.Constants.DEFAULT_TIMEOUT
+     */
+    private int timeout;
+
+    /**
+     * (可选) HTTP头
+     */
+    private Map<String, String> headers;
+
+    /**
+     * (可选) Querys
+     */
+    private Map<String, String> querys;
+
+    /**
+     * (可选)表单参数
+     */
+    private Map<String, String> bodys;
+
+    /**
+     * (可选)字符串Body体
+     */
+    private String stringBody;
+
+    /**
+     * (可选)字节数组类型Body体
+     */
+    private byte[] bytesBody;
+
+    /**
+     * (可选)自定义参与签名Header前缀
+     */
+    private List<String> signHeaderPrefixList;
+}

+ 82 - 0
src/main/java/info/aspirecn/cloud/yysj/entity/VehicleTrajectoryResponse.java

@@ -0,0 +1,82 @@
+package info.aspirecn.cloud.yysj.entity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class VehicleTrajectoryResponse {
+    private int statusCode;
+    private String contentType;
+    private String requestId;
+    private String errorMessage;
+    private Map<String, String> headers;
+    private String body;
+
+    public VehicleTrajectoryResponse() {
+
+    }
+
+	public int getStatusCode() {
+		return statusCode;
+	}
+
+	public void setStatusCode(int statusCode) {
+		this.statusCode = statusCode;
+	}
+
+	public String getContentType() {
+		return contentType;
+	}
+
+	public void setContentType(String contentType) {
+		this.contentType = contentType;
+	}
+
+	public String getRequestId() {
+		return requestId;
+	}
+
+	public void setRequestId(String requestId) {
+		this.requestId = requestId;
+	}
+
+	public String getErrorMessage() {
+		return errorMessage;
+	}
+
+	public void setErrorMessage(String errorMessage) {
+		this.errorMessage = errorMessage;
+	}
+
+	public Map<String, String> getHeaders() {
+		return headers;
+	}
+
+	public String getHeader(String key) {
+		if (null != headers) {
+			return headers.get(key);
+		} else {
+			return null;
+		}
+	}
+
+	public void setHeaders(Map<String, String> headers) {
+		this.headers = headers;
+	}
+
+	public void setHeader(String key, String value) {
+		if (null == this.headers) {
+			this.headers = new HashMap<String, String>();
+		}
+		this.headers.put(key, value);
+	}
+
+	public String getBody() {
+		return body;
+	}
+
+	public void setBody(String body) {
+		this.body = body;
+	}
+
+
+}

+ 2 - 2
src/main/java/info/aspirecn/cloud/yysj/service/CarService.java

@@ -1,6 +1,6 @@
 package info.aspirecn.cloud.yysj.service;
 
-import info.aspirecn.cloud.yysj.entity.CommonResponseObject;
+import info.aspirecn.cloud.yysj.commons.lang.CommonResponseObject;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -8,7 +8,7 @@ import javax.servlet.http.HttpServletRequest;
  * @author xusonglin
  * @version V1.0
  **/
-public interface CarService {
+public interface VehicleService {
     /**
      * 车辆历史轨迹(接百度)
      * @param request

+ 2 - 2
src/main/java/info/aspirecn/cloud/yysj/service/CarServiceImpl.java

@@ -1,6 +1,6 @@
 package info.aspirecn.cloud.yysj.service;
 
-import info.aspirecn.cloud.yysj.entity.CommonResponseObject;
+import info.aspirecn.cloud.yysj.commons.lang.CommonResponseObject;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -12,7 +12,7 @@ import javax.servlet.http.HttpServletRequest;
  **/
 @Slf4j
 @Service
-public class CarServiceImpl implements CarService{
+public class VehicleServiceImpl implements VehicleService{
     @Override
     public CommonResponseObject carHistoricalTrajectoryQueryByBaidu(HttpServletRequest request, String customBody, int outTime) {
         CommonResponseObject responseObject = new CommonResponseObject();

+ 118 - 0
src/main/java/info/aspirecn/cloud/yysj/util/MessageDigestUtil.java

@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package info.aspirecn.cloud.yysj.util;
+
+import info.aspirecn.cloud.yysj.constants.CommonConstant;
+import org.apache.commons.codec.binary.Base64;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 消息摘要工具
+ */
+public class MessageDigestUtil {
+    /**
+     * 先进行MD5摘要再进行Base64编码获取摘要字符串
+     *
+     * @param str
+     * @return
+     */
+    public static String base64AndMD5(String str) {
+        if (str == null) {
+            throw new IllegalArgumentException("inStr can not be null");
+        }
+        return base64AndMD5(toBytes(str));
+    }
+
+    /**
+     * 先进行MD5摘要再进行Base64编码获取摘要字符串
+     *
+     * @return
+     */
+    public static String base64AndMD5(byte[] bytes) {
+        if (bytes == null) {
+            throw new IllegalArgumentException("bytes can not be null");
+        }
+        try {
+            final MessageDigest md = MessageDigest.getInstance("MD5");
+            md.reset();
+            md.update(bytes);
+            final Base64 base64 = new Base64();
+            final byte[] enbytes = base64.encode(md.digest());
+            return new String(enbytes);
+        } catch (final NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException("unknown algorithm MD5");
+        }
+    }
+
+    /**
+     * UTF-8编码转换为ISO-9959-1
+     *
+     * @param str
+     * @return
+     */
+    public static String utf8ToIso88591(String str) {
+        if (str == null) {
+            return str;
+        }
+
+        try {
+            return new String(str.getBytes("UTF-8"), "ISO-8859-1");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * ISO-9959-1编码转换为UTF-8
+     *
+     * @param str
+     * @return
+     */
+    public static String iso88591ToUtf8(String str) {
+        if (str == null) {
+            return str;
+        }
+
+        try {
+            return new String(str.getBytes("ISO-8859-1"), "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * String转换为字节数组
+     *
+     * @param str
+     * @return
+     */
+    private static byte[] toBytes(final String str) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            return str.getBytes(CommonConstant.ENCODING);
+        } catch (final UnsupportedEncodingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+}

+ 95 - 0
src/main/java/info/aspirecn/cloud/yysj/util/PostUtil.java

@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package info.aspirecn.cloud.yysj.util;
+
+import info.aspirecn.cloud.yysj.constants.CommonConstant;
+import info.aspirecn.cloud.yysj.constants.HttpHeader;
+import info.aspirecn.cloud.yysj.entity.VehicleTrajectoryRequest;
+import info.aspirecn.cloud.yysj.entity.VehicleTrajectoryResponse;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 调用示例
+ * 请替换APP_KEY,APP_SECRET,HOST,CUSTOM_HEADERS_TO_SIGN_PREFIX为真实配置
+ */
+public class PostUtil {
+	//网关的host地址
+	public static String HOST = "https://gateway.logink.cn";
+
+
+    /**
+     * HTTP POST 字符串
+     *
+     * @throws Exception
+     */
+    public static VehicleTrajectoryResponse postString(String URL, String BODY, String APP_KEY, String APP_SECRET,
+                                                       Integer outTime) throws Exception {
+    	System.out.println("Request:");
+    	System.out.println("Url: " + URL);
+    	String PATH = URL.substring(HOST.length(), URL.length());
+        Map<String, String> headers = new HashMap<String, String>();
+        //(必填)根据期望的Response内容类型设置
+        headers.put(HttpHeader.HTTP_HEADER_ACCEPT, CommonConstant.CONTENT_TYPE_JSON);
+        //(可选)Body MD5,服务端会校验Body内容是否被篡改,建议Body非Form表单时添加此Header
+        headers.put(HttpHeader.HTTP_HEADER_CONTENT_MD5, MessageDigestUtil.base64AndMD5(BODY));
+        //(POST/PUT请求必选)请求Body内容格式
+        headers.put(HttpHeader.HTTP_HEADER_CONTENT_TYPE, CommonConstant.CONTENT_TYPE_JSON);
+        //(非必填)用户自定义的header字段,用户自己决定是否参与签名,如果参与签名,将相关header信息设置如下
+        headers.put("a-header1", "header1Value");
+        headers.put("b-header2", "header2Value");
+
+        List<String> CUSTOM_HEADERS_TO_SIGN_PREFIX = new ArrayList<String>();
+        CUSTOM_HEADERS_TO_SIGN_PREFIX.add("a-header1");
+        CUSTOM_HEADERS_TO_SIGN_PREFIX.add("a-header2");
+
+
+        VehicleTrajectoryRequest request = new VehicleTrajectoryRequest(HOST,
+        		PATH, APP_KEY, APP_SECRET, outTime);
+        request.setHeaders(headers);
+        request.setSignHeaderPrefixList(CUSTOM_HEADERS_TO_SIGN_PREFIX);
+
+        //(非必填)根据api描述,如果有需要传递的参数,设置请求的query
+        Map<String, String> querys = new HashMap<String, String>();
+        querys.put("a-query1", "query1Value");
+        querys.put("b-query2", "query2Value");
+        request.setQuerys(querys);
+
+        request.setStringBody(BODY);
+
+        //调用服务端
+        HttpUtil.httpPost(request.getHost(), request.getPath(),
+                request.getTimeout(),
+                request.getHeaders(),
+                request.getQuerys(),
+                request.getStringBody(),
+                request.getSignHeaderPrefixList(),
+                request.getAppKey(), request.getAppSecret());
+
+        VehicleTrajectoryResponse response = Client.execute(request);
+        System.out.println("Body: " + BODY);
+        System.out.println("");
+        System.out.println("Response: ");
+        return response;
+    }
+
+}

+ 227 - 0
src/main/java/info/aspirecn/cloud/yysj/util/SignUtil.java

@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package info.aspirecn.cloud.yysj.util;
+
+import info.aspirecn.cloud.yysj.constants.CommonConstant;
+import info.aspirecn.cloud.yysj.constants.HttpHeader;
+import info.aspirecn.cloud.yysj.constants.SystemHeader;
+import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * 签名工具
+ */
+public class SignUtil {
+
+    /**
+     * 计算签名
+     *
+     * @param secret APP密钥
+     * @param method HttpMethod
+     * @param path
+     * @param headers
+     * @param querys
+     * @param bodys
+     * @param signHeaderPrefixList 自定义参与签名Header前缀
+     * @return 签名后的字符串
+     */
+    public static String sign(String secret, String method, String path,
+    							Map<String, String> headers,
+    							Map<String, String> querys,
+    							Map<String, String> bodys,
+    							List<String> signHeaderPrefixList) {
+        try {
+            Mac hmacSha256 = Mac.getInstance(CommonConstant.HMAC_SHA256);
+            byte[] keyBytes = secret.getBytes(CommonConstant.ENCODING);
+            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, CommonConstant.HMAC_SHA256));
+
+            return new String(Base64.encodeBase64(
+                    hmacSha256.doFinal(buildStringToSign(method, path, headers, querys, bodys, signHeaderPrefixList)
+                            .getBytes(CommonConstant.ENCODING))),
+                    CommonConstant.ENCODING);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 构建待签名字符串
+     * @param method
+     * @param path
+     * @param headers
+     * @param querys
+     * @param bodys
+     * @param signHeaderPrefixList
+     * @return
+     */
+    private static String buildStringToSign(String method, String path,
+    										Map<String, String> headers,
+    										Map<String, String> querys,
+    										Map<String, String> bodys,
+                                            List<String> signHeaderPrefixList) {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append(method.toUpperCase()).append(CommonConstant.LF);
+        if (null != headers) {
+        	if (null != headers.get(HttpHeader.HTTP_HEADER_ACCEPT)) {
+                sb.append(headers.get(HttpHeader.HTTP_HEADER_ACCEPT));
+            }
+        	sb.append(CommonConstant.LF);
+        	if (null != headers.get(HttpHeader.HTTP_HEADER_CONTENT_MD5)) {
+                sb.append(headers.get(HttpHeader.HTTP_HEADER_CONTENT_MD5));
+            }
+            sb.append(CommonConstant.LF);
+            if (null != headers.get(HttpHeader.HTTP_HEADER_CONTENT_TYPE)) {
+                sb.append(headers.get(HttpHeader.HTTP_HEADER_CONTENT_TYPE));
+            }
+            sb.append(CommonConstant.LF);
+            if (null != headers.get(HttpHeader.HTTP_HEADER_DATE)) {
+                sb.append(headers.get(HttpHeader.HTTP_HEADER_DATE));
+            }
+        }
+        sb.append(CommonConstant.LF);
+        sb.append(buildHeaders(headers, signHeaderPrefixList));
+        sb.append(buildResource(path, querys, bodys));
+
+        return sb.toString();
+    }
+
+    /**
+     * 构建待签名Path+Query+BODY
+     *
+     * @param path
+     * @param querys
+     * @param bodys
+     * @return 待签名
+     */
+    private static String buildResource(String path, Map<String, String> querys, Map<String, String> bodys) {
+    	StringBuilder sb = new StringBuilder();
+
+    	if (!StringUtils.isBlank(path)) {
+    		sb.append(path);
+        }
+        Map<String, String> sortMap = new TreeMap<String, String>();
+        if (null != querys) {
+        	for (Map.Entry<String, String> query : querys.entrySet()) {
+        		if (!StringUtils.isBlank(query.getKey())) {
+        			sortMap.put(query.getKey(), query.getValue());
+                }
+        	}
+        }
+
+        if (null != bodys) {
+        	for (Map.Entry<String, String> body : bodys.entrySet()) {
+        		if (!StringUtils.isBlank(body.getKey())) {
+        			sortMap.put(body.getKey(), body.getValue());
+                }
+        	}
+        }
+
+        StringBuilder sbParam = new StringBuilder();
+        for (Map.Entry<String, String> item : sortMap.entrySet()) {
+    		if (!StringUtils.isBlank(item.getKey())) {
+    			if (0 < sbParam.length()) {
+    				sbParam.append(CommonConstant.SPE3);
+    			}
+    			sbParam.append(item.getKey());
+    			if (!StringUtils.isBlank(item.getValue())) {
+    				sbParam.append(CommonConstant.SPE4).append(item.getValue());
+    			}
+            }
+    	}
+        if (0 < sbParam.length()) {
+        	sb.append(CommonConstant.SPE5);
+        	sb.append(sbParam);
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 构建待签名Http头
+     *
+     * @param headers 请求中所有的Http头
+     * @param signHeaderPrefixList 自定义参与签名Header前缀
+     * @return 待签名Http头
+     */
+    private static String buildHeaders(Map<String, String> headers, List<String> signHeaderPrefixList) {
+    	StringBuilder sb = new StringBuilder();
+
+    	if (null != signHeaderPrefixList) {
+    		signHeaderPrefixList.remove(SystemHeader.X_CA_SIGNATURE);
+    		signHeaderPrefixList.remove(HttpHeader.HTTP_HEADER_ACCEPT);
+    		signHeaderPrefixList.remove(HttpHeader.HTTP_HEADER_CONTENT_MD5);
+    		signHeaderPrefixList.remove(HttpHeader.HTTP_HEADER_CONTENT_TYPE);
+    		signHeaderPrefixList.remove(HttpHeader.HTTP_HEADER_DATE);
+    		Collections.sort(signHeaderPrefixList);
+    		if (null != headers) {
+    			Map<String, String> sortMap = new TreeMap<String, String>();
+    			sortMap.putAll(headers);
+    			StringBuilder signHeadersStringBuilder = new StringBuilder();
+    			for (Map.Entry<String, String> header : sortMap.entrySet()) {
+                    if (isHeaderToSign(header.getKey(), signHeaderPrefixList)) {
+                    	sb.append(header.getKey());
+                    	sb.append(CommonConstant.SPE2);
+                        if (!StringUtils.isBlank(header.getValue())) {
+                        	sb.append(header.getValue());
+                        }
+                        sb.append(CommonConstant.LF);
+                        if (0 < signHeadersStringBuilder.length()) {
+                        	signHeadersStringBuilder.append(CommonConstant.SPE1);
+                        }
+                        signHeadersStringBuilder.append(header.getKey());
+                    }
+                }
+    			headers.put(SystemHeader.X_CA_SIGNATURE_HEADERS, signHeadersStringBuilder.toString());
+    		}
+    	}
+
+        return sb.toString();
+    }
+
+    /**
+     * Http头是否参与签名 return
+     */
+    private static boolean isHeaderToSign(String headerName, List<String> signHeaderPrefixList) {
+        if (StringUtils.isBlank(headerName)) {
+            return false;
+        }
+
+        if (headerName.startsWith(CommonConstant.CA_HEADER_TO_SIGN_PREFIX_SYSTEM)) {
+            return true;
+        }
+
+        if (null != signHeaderPrefixList) {
+            for (String signHeaderPrefix : signHeaderPrefixList) {
+                if (headerName.equalsIgnoreCase(signHeaderPrefix)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+}