欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java HttpClient-Restful工具各種請求高度封裝提煉及總結(jié)

 更新時間:2022年10月28日 09:23:46   作者:極光雨雨  
這篇文章主要介紹了Java HttpClient-Restful工具各種請求高度封裝提煉及總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

總思路

總的工具要求底層完全可復用的代碼全部提煉,也就是不通類型(GET, POST, DELETE, PUT 等等)請求的決定性公共步驟其實是可以提煉出來的。

即 一個請求,請求頭一定會有,請求路徑一定會有,發(fā)起請求一定會有,返回處理一定會有。

但同時由于請求頭內(nèi)容可能會有不同的要求或者加密方式,所以需要將相關(guān)加工過程放到基礎(chǔ)工具類之外,保證調(diào)用基礎(chǔ)工具類時只執(zhí)行所有請求都需要的的步驟,不帶有特殊處理。

這里主要使用的都是 org.apache.http 已包裝的 httpClient ,項目中進一步將各種類型的請求做進一步提煉和封裝。

從最底層開始說明

RestfulService

基礎(chǔ) RestfulService 工具代碼可以參考如下:

個別說明加入到注釋中或示例代碼結(jié)尾

......
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class MyRestfulService {

    private static xxxLogger = new xxxLog(MyRestfulService .class);
    // 所有請求都由 httpClient.execute()  方式發(fā)出
    private CloseableHttpClient httpClient;
    
    // 由于 httpClient 也存在自定義各種屬性,所以這里也作為一個定義的參數(shù)
    // 通過構(gòu)造方法傳入外側(cè)定義的  CloseableHttpClient
    public MyRestfulService(CloseableHttpClient client) {
        this.httpClient = client;
    }

	// 一般的GET 請求
    public String jsonGet(String url, final NameValuePair[] headerParams) throws IOException, XxxxException {
        URI uri = URI.create(url);
        HttpGet get = new HttpGet(uri);
        this.addHeaders(headerParams, get);
        CloseableHttpResponse response = httpClient.execute(get);
        return this.parseResponseData(response, url);
    }

    // Get請求 獲取文件某字符串開頭的
    public String fileGetLine(String url, final NameValuePair[] headerParams, String head) throws IOException,
            XxxxException {
        URI uri = URI.create(url);
        HttpGet get = new HttpGet(uri);
        this.addHeaders(headerParams, get);
        CloseableHttpResponse response = httpClient.execute(get);
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
            String output;
            while ((output = br.readLine()) != null) {
                if (output.contains(head) && Objects.equals(output.split("=")[0], head)) {
                    return output;
                }
            }
            return null;
        } catch (Exception e) {
            logger.error("Failed to get rest response", e);
            // 為自定義異常類型
            throw new XxxxException(ExceptionType.XXXXXX);
        } finally {
            if (br != null) {
                br.close();
            }
            response.close();
        }
    }

    // 攜帶請求體即 Body 的GET 請求 其中  HttpGetWithEntity 需要自定義到文件中 稍后給出示例
    public String jsonGetWithBody(String url, final NameValuePair[] headerParams, String requestBody)
            throws IOException, XxxxException {
        URI uri = URI.create(url);
        HttpGetWithEntity get = new HttpGetWithEntity(uri);
        this.addHeaders(headerParams, get);

        StringEntity input = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
        get.setEntity(input);
        CloseableHttpResponse response = httpClient.execute(get);
        return this.parseResponseData(response, url);
    }
	
	// 普通的POST 請求
    public String jsonPost(String url, final NameValuePair[] headerParams, String requestBody)
            throws IOException, XxxxException {
        HttpPost post = new HttpPost(url);
        this.addHeaders(headerParams, post);
        
        if (requestBody != null) {
            StringEntity input = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
            post.setEntity(input);
        }
        CloseableHttpResponse response = httpClient.execute(post);
        return this.parseResponseData(response, url);
    }

	// 普通 put 請求
    public String jsonPut(String url, final NameValuePair[] headerParams, String requestBody)
            throws IOException, XxxxException {
        HttpPut put = new HttpPut(url);
        this.addHeaders(headerParams, put);
        StringEntity input = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
        put.setEntity(input);
        CloseableHttpResponse response = httpClient.execute(put);
        return this.parseResponseData(response, url);
    }

	// 一般的DELETE 請求
    public String jsonDelete(String url, final NameValuePair[] headerParams) throws IOException, XxxxException {
        HttpDelete delete = new HttpDelete(url);
        this.addHeaders(headerParams, delete);
        CloseableHttpResponse response = null;
        response = httpClient.execute(delete);
        return this.parseResponseData(response, url);
    }

	// 攜帶請求體的DELETE 請求 HttpDeleteWithBody
    public String jsonDeleteWithBody(String url, final NameValuePair[] headerParams, String requestBody)
            throws IOException, XxxxException {
        HttpDeleteWithBody delete = new HttpDeleteWithBody(url);
        this.addHeaders(headerParams, delete);
        StringEntity input = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
        delete.setEntity(input);
        CloseableHttpResponse response = null;
        response = httpClient.execute(delete);
        return this.parseResponseData(response, url);
    }

	// 文件類傳入 上傳
    public String uploadFile(String url, final NameValuePair[] headerParams, HttpEntity multipartEntity)
            throws IOException, XxxxException {
        HttpPost post = new HttpPost(url);
        post.setEntity(multipartEntity);
        post.addHeader(HttpHeaders.CONTENT_TYPE, post.getEntity().getContentType().getValue());
        if (headerParams != null) {
            for (NameValuePair nameValuePair : headerParams) {
                post.addHeader(nameValuePair.getName(), nameValuePair.getValue());
            }
        }
        return this.parseResponseData(httpClient.execute(post), url);
    }

	// 數(shù)據(jù)結(jié)果轉(zhuǎn)換
    private String parseResponseData(CloseableHttpResponse response, String url) throws IOException,
            XxxxException {
        BufferedReader br = null;
        try {
        	// 編碼轉(zhuǎn)義結(jié)果
            br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));
            StringBuilder sbuilder = new StringBuilder();
            String output;
            while ((output = br.readLine()) != null) {
                sbuilder.append(output);
            }
            logger.debug("MyRestfulService Request-URL: " + url + "; response: " + response.toString() + "; data:" + sbuilder + "}");
            int statusCode = response.getStatusLine().getStatusCode();
            // 200 可用已有常量替代 HTTP 本身有提供
            if (statusCode != 200) {
                logger.info("Failed to get restful response, http error code = " + statusCode);
            }
            return sbuilder.toString();
        } catch (Exception e) {
            logger.error("Failed to get rest response", e);
            // 自定義異常
            throw new XxxxException(ExceptionType.XXXXXXX);
        } finally {
            if (br != null) {
                br.close();
            }
            response.close();
        }
    }

	// 公用 添加自定義請求頭信息
    private void addHeaders(final NameValuePair[] headerParams, HttpRequestBase requestBase) {
        if (headerParams != null) {
            for (int i = 0; i < headerParams.length; i++) {
                NameValuePair nameValuePair = headerParams[i];
                requestBase.addHeader(nameValuePair.getName(), nameValuePair.getValue());
            }
        }
        this.addCommonHeader(requestBase);
    }

	// 公用 添加公共請求頭或公共操作
    private void addCommonHeader(HttpRequestBase method) {
    	// 去除個別屬性
        if (method.containsHeader("Content-Length")) {
            method.removeHeaders("Content-Length");
        }
    	// 沒有則添加
        if (!method.containsHeader("Content-Type")) {
            method.addHeader("Content-Type", "application/json;charset=utf-8");
        }
		
		// 強制更新或添加
        method.setHeader("accept", "application/json,text/plain,text/html");
    }
    
    // 文件下載
	public String downloadFile(String url, OutputStream outputStream,NameValuePair[] headerParams)
            throws IOException, DXPException {
        HttpGet httpget = new HttpGet(url);
        this.addHeaders(headerParams, httpget);
        CloseableHttpResponse execute = httpClient.execute(httpget);
        if(null != execute && execute.containsHeader("Content-Disposition")){
            HttpEntity entity = execute.getEntity();
            if (entity != null ) {
                entity.writeTo(outputStream);
            }
        }else {
            return this.parseResponseData(execute, url);
        }
        return null;
    }

	// httpClient 對應的get set 方法
    public CloseableHttpClient getHttpClient() {
        return this.httpClient;
    }

    public void setHttpClient(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }
}

上面

HttpDeleteWithBody 定義:

import java.net.URI;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;

public class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {

    public static final String METHOD_NAME = "DELETE";

    public HttpDeleteWithBody(final String uri) {
        super();
        setURI(URI.create(uri));
    }

    public HttpDeleteWithBody(final URI uri) {
        super();
        setURI(uri);
    }

    public HttpDeleteWithBody() {
        super();
    }

    public String getMethod() {
        return METHOD_NAME;
    }
}

上面 HttpGetWithBody:

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;

public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {

    private static final String METHOD_NAME = "GET";

    public HttpGetWithEntity() {
        super();
    }

    public HttpGetWithEntity(final URI uri) {
        super();
        setURI(uri);
    }

    HttpGetWithEntity(final String uri) {
        super();
        setURI(URI.create(uri));
    }

    @Override
    public String getMethod() {
        return METHOD_NAME;
    }
}

具體來源其實就是照抄 源碼 httppost POST 的結(jié)構(gòu)

然后換個名字以及屬性名即可完成請求體的攜帶

NameValuePair[]

示例中用到了大量的 NameValuePair[] 其,內(nèi)部結(jié)構(gòu)類似于 Map 但內(nèi)部屬性為name, value。

實際也可以使用 Map 來替代這種存儲結(jié)構(gòu), NameValuePair 也是 org.apache.http 內(nèi)部提供的類。

工具類上一層

其他調(diào)用者。用于處理特殊的請求頭信息,拼接請求參數(shù)以及請求路徑等內(nèi)容

并構(gòu)建使用的 CloseableHttpClient 傳入工具類。

示例:

某一 上層 Service 的內(nèi)容示例:

......
......
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service("XXXRestfulService")
public class XXXRestfulService implements IXxxRestfulService {
    private static final XXXLog xxxLog = new XXXLog(XXXRestfulService .class);

    private static int maxConnPerHost = 20;
    private static int maxTotalConn = 20;
    /**
     * 數(shù)據(jù)讀取超時時間
     */
    private static int soTimeout = 30000;
    /**
     * http連接超時時間
     */
    private static int connectionTimeout = 10000;
    /**
     * 連接管理器超時時間
     */
    private static int connectionManagerTimeout = 10000;

	// 基礎(chǔ)工具類對象聲明
    private MyRestfulService restService;

    private CloseableHttpClient createHttpClient() {
        CloseableHttpClient httpClient = null;
        try {
            @SuppressWarnings("deprecation") ConnectionConfig cConfig =
                    ConnectionConfig.custom().setCharset(StandardCharsets.UTF_8).build();
            SocketConfig config = SocketConfig.custom().setSoTimeout(soTimeout).build();
            RequestConfig defaultRequestConfig =
                    RequestConfig.custom().setExpectContinueEnabled(true).setCookieSpec(CookieSpecs.DEFAULT)
                            .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
                            .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
                            .setConnectionRequestTimeout(connectionManagerTimeout).setConnectTimeout(connectionTimeout)
                            .setSocketTimeout(soTimeout).build();
            httpClient = HttpClientBuilder.create().setMaxConnPerRoute(maxConnPerHost).setMaxConnTotal(maxTotalConn)
                    .setSSLHostnameVerifier(new NoopHostnameVerifier())
                    .setDefaultRequestConfig(RequestConfig.copy(defaultRequestConfig).build())
                    .setDefaultConnectionConfig(cConfig).setDefaultSocketConfig(config).build();
        } catch (Exception e) {
            xxxLog.error("Create Http Client Failed", e);
        }

        return httpClient;
    }

	// 類初始化時執(zhí)行的方法
    @PostConstruct
    public void initProperties() {
        try {
            CloseableHttpClient client = this.createHttpClient();
            this.restService = new MyRestfulService(client);
        } catch (Exception e) {
            xxxLog.error("Failed To Init DataFillRestfulService", e);
        }
    }

	// 關(guān)閉資源,如果每次都重新請求則也可以放到工具類內(nèi)每次請求完成都關(guān)閉
    @PreDestroy   // @PreDestroy 實際 Servlet 被銷毀前調(diào)用的方法
    public void destroy() {
        try {
            CloseableHttpClient httpclient = restService.getHttpClient();
            httpclient.close();
        } catch (IOException e) {
            xxxLog.error("Failed To Destroy HttpClient", e);
        }
    }

	// 對請求頭內(nèi)容的特殊處理
    private NameValuePair[] getBaseHeaders(String methodName, String urlStr) {
    // 對請求頭內(nèi)容的特殊處理  若沒有則直接添加到 返回值 NameValuePair[] 數(shù)組即可
        ............
    }

	// 如果需要URL編碼則可以使用該方法
    private String encodeHeader(String value) throws UnsupportedEncodingException {
        if (StringUtils.isEmpty(value)) {
            return value;
        }
        return URLEncoder.encode(value, "UTF-8");
    }

	// 拼接實際請求路徑
	// XXXXConfig 可以作為一個類專門加載配置文件中的一些有關(guān)的地址信息等
    public String getRequestUrl(String actionUrl) {
        return XXXXConfig.getXxxxServer() + actionUrl;
    }


    @Override
    public String get(final String actionUrl, Map<String, String> map) {
    	String requestUrl = getRequestUrl(actionUrl);
        // 傳入實際地址等 調(diào)用基礎(chǔ)工具類請求
        .....
    }

    @Override
    public String post(final String actionUrl, final String jsonBody) {
    	String requestUrl = getRequestUrl(actionUrl);
        // 傳入實際地址等 調(diào)用基礎(chǔ)工具類請求
        .....
    }

    @Override
    public String delete(final String actionUrl) {
    	String requestUrl = getRequestUrl(actionUrl);
        // 傳入實際地址等 調(diào)用基礎(chǔ)工具類請求
        .....
    }
}

可以看的出,上層工具類先聲明了 工具類對象 然后在當前類初始化時完成了對當前Service請求自己 httpClient 的相關(guān)創(chuàng)建以及配置的賦值,并將該對象 傳遞給工具類,使得調(diào)用工具類時依舊使用的是自己創(chuàng)建的那一個對象。

并通過一般的工具類將需要的配置文件的信息加載后,直接在該類中引用。完成請求信息的拼接。

由于不同的產(chǎn)品間的請求頭要求信息可能不同,所以需要自己額外處理請求頭相關(guān)信息。

這里其實還是在封裝部分內(nèi)容,使得業(yè)務(wù)請求調(diào)用時進一步簡化。

一些工具類特殊的傳入如下示例:

文件上傳方式

public String uploadFile(String url, final NameValuePair[] headerParams, HttpEntity multipartEntity)

中 HttpEntity 中加入文件的方式

		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        builder.setCharset(StandardCharsets.UTF_8);
        builder.addBinaryBody("file", inputStream, ContentType.DEFAULT_BINARY, fileName);

		builder.build();   // 最終可以到的 想要的 HttpEntity 攜帶文件內(nèi)容

其中 inputStreamInputStream 類型的文件輸入流, fileName 為 String 文件名;

獲取文件流

public String downloadFile(String url, OutputStream outputStream,NameValuePair[] headerParams)

獲得請求中的文件流,則需要傳入 OutputStream 類型的 輸出流對象 outputStream。

再上一層的業(yè)務(wù)調(diào)用

業(yè)務(wù)層處則通過直接定義指定的方法和入?yún)?,在?nèi)部直接寫入請求映射路徑,并要求傳入指定參數(shù)完成業(yè)務(wù)封裝,類似于:

	@Override
    public XxxxxxxDTO<XXX> getXxxxList(XxxxxListRequest request,
                                               String xxx, String xxxx) throws XXXException {
        String url = "/xxxx/api/xxxx/xxxx/list";
        String result = XxxxxRestfulService.post(url, JsonUtil.getJsonStr(request), xxx, xxxx);
        // 對 result 進行轉(zhuǎn)化 轉(zhuǎn)為自定義類或者Map 等返回
        return ......;
    }

這樣在外部調(diào)用該業(yè)務(wù)方法時需要感知的只有入?yún)ⅲ渌麕缀醺兄坏?,與一般的方法差別幾乎沒有

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論