HTTPClient

合集下载

使用HttpClient实现文件的上传下载方法

使用HttpClient实现文件的上传下载方法

使⽤HttpClient实现⽂件的上传下载⽅法1 HTTPHTTP 协议可能是现在 Internet 上使⽤得最多、最重要的协议了,越来越多的 Java 应⽤程序需要直接通过 HTTP 协议来访问⽹络资源。

虽然在 JDK 的 包中已经提供了访问 HTTP 协议的基本功能,但是对于⼤部分应⽤程序来说,JDK 库本⾝提供的功能还不够丰富和灵活。

HttpClient ⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持HTTP 协议最新的版本和建议。

⼀般的情况下我们都是使⽤Chrome或者其他浏览器来访问⼀个WEB服务器,⽤来浏览页⾯查看信息或者提交⼀些数据、⽂件上传下载等等。

所访问的这些页⾯有的仅仅是⼀些普通的页⾯,有的需要⽤户登录后⽅可使⽤,或者需要认证以及是⼀些通过加密⽅式传输,例如HTTPS。

⽬前我们使⽤的浏览器处理这些情况都不会构成问题。

但是⼀旦我们有需求不通过浏览器来访问服务器的资源呢?那该怎么办呢?下⾯以本地客户端发起⽂件的上传、下载为例做个⼩Demo。

HttpClient有两种形式,⼀种是org.apache.http下的,⼀种是mons.httpclient.HttpClient。

2 ⽂件上传⽂件上传可以使⽤两种⽅式实现,⼀种是PostMethod⽅式,⼀种是HttpPost⽅式。

两者的处理⼤同⼩异。

PostMethod是使⽤FileBody将⽂件包装流包装起来,HttpPost是使⽤FilePart将⽂件流包装起来。

在传递⽂件流给服务端的时候,都可以同时传递其他的参数。

2.1 客户端处理2.1.1 PostMethod⽅式将⽂件封装到FilePart中,放⼊Part数组,同时,其他参数可以放⼊StringPart中,这⾥没有写,只是单纯的将参数以setParameter的⽅式进⾏设置。

此处的HttpClient是mons.httpclient.HttpClient。

HttpClient发起请求,将响应结果(header和entity)设置到response中返回

HttpClient发起请求,将响应结果(header和entity)设置到response中返回

HttpClient发起请求,将响应结果(header和entity)设置到response中返回前⾔HttpClient发起请求,将响应结果(header和entity)设置到response中返回package com.graph.oss.config;import java.io.IOException;import ng.reflect.Field;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import mon.base.util.JSONUtils;import org.apache.http.Header;import org.apache.http.HttpEntity;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClientBuilder;import org.springframework.beans.factory.BeanFactory;import org.springframework.web.context.support.WebApplicationContextUtils;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;//import org.apache.tomcat.util.buf.MessageBytes;/*** 对象服务接⼝透传只有⾮控制接⼝(/oss/*)才会进到这个拦截器*/public class ContentInterceptor extends HandlerInterceptorAdapter {private static final String PATH_DELIMITER = "/";private OssServerConfig ossServerConfig;private MinioServerConfig minioServerConfig;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// get配置⽂件beanBeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());ossServerConfig = (OssServerConfig) factory.getBean("ossServerConfig");minioServerConfig = (MinioServerConfig) factory.getBean("minioServerConfig");// get request uri(undertow)String uri = request.getRequestURI();// uri处理(去掉context.api)String api = ossServerConfig.getApi();if (uri.startsWith(api)) {uri = uri.replace(api, PATH_DELIMITER);}// get httpclient responseString minioUrl = minioServerConfig.getEndpoint() + uri;CloseableHttpClient httpClient = HttpClientBuilder.create().build();HttpGet httpGet = new HttpGet(minioUrl);RequestConfig config = RequestConfig.custom().setConnectTimeout(1000).setConnectionRequestTimeout(1000).setSocketTimeout(10 * 1000).build();httpGet.setConfig(config);httpGet.addHeader("content-type", "application/json");CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);ServletOutputStream out = null;try {// 将httpClient响应的header和entity设置到httpServletResponseHeader header = closeableHttpResponse.getFirstHeader("Content-Type");response.setHeader(header.getName(), header.getValue());HttpEntity entity = closeableHttpResponse.getEntity();out = response.getOutputStream();entity.writeTo(out);out.flush();out.close();return false;} catch (IOException e) {e.printStackTrace();}return true;}// 根据Field获得对应的Classprivate Class getClassByName(Class classObject, String name) {Map<Class, List<Field>> fieldMap = new HashMap<>();Class returnClass = null;Class tempClass = classObject;while (tempClass != null) {fieldMap.put(tempClass, Arrays.asList(tempClass.getDeclaredFields())); tempClass = tempClass.getSuperclass();}for (Map.Entry<Class, List<Field>> entry : fieldMap.entrySet()) {for (Field f : entry.getValue()) {if (f.getName().equals(name)) {returnClass = entry.getKey();break;}}}return returnClass;}// 递归遍历⽗类寻找coyoteRequest Fieldprivate Object findCoyoteRequest(Object request) throws Exception {Class a = getClassByName(request.getClass(), "request");Field request1 = a.getDeclaredField("request");request1.setAccessible(true);Object b = request1.get(request);if (getClassByName(b.getClass(), "coyoteRequest") == null) {return findCoyoteRequest(b);} else {return b;}}private String getReqStr(String namespace, String prefix, String name) {Map<String, String> map = new HashMap<>();map.put("namespace", namespace);map.put("prefix", prefix);map.put("fileName", name);return JSONUtils.toJSONString(map);}}感谢。

基于springboot的RestTemplate、okhttp和HttpClient对比

基于springboot的RestTemplate、okhttp和HttpClient对比

基于springboot的RestTemplate、okhttp和HttpClient对⽐1、HttpClient:代码复杂,还得操⼼资源回收等。

代码很复杂,冗余代码多,不建议直接使⽤。

2、RestTemplate:是 Spring 提供的⽤于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的⽅法,能够⼤⼤提⾼客户端的编写效率。

引⼊jar包:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>添加初始化配置(也可以不配,有默认的)--注意RestTemplate只有初始化配置,没有什么连接池package com.itunion.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.ClientHttpRequestFactory;import org.springframework.http.client.SimpleClientHttpRequestFactory;import org.springframework.web.client.RestTemplate;@Configurationpublic class ApiConfig {@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory factory) {return new RestTemplate(factory);}@Beanpublic ClientHttpRequestFactory simpleClientHttpRequestFactory() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();//默认的是JDK提供http连接,需要的话可以//通过setRequestFactory⽅法替换为例如Apache HttpComponents、Netty或//OkHttp等其它HTTP library。

javahttpput请求方式_使用HttpClient发送GETPOSTPUTDe

javahttpput请求方式_使用HttpClient发送GETPOSTPUTDe

javahttpput请求方式_使用HttpClient发送GETPOSTPUTDe在Java中,我们可以使用HttpClient库来发送HTTP请求,包括GET、POST、PUT、DELETE等请求方式。

下面是使用HttpClient发送这些请求的示例代码。

1.发送GET请求:```javapublic class HttpGetExamplepublic static void main(String[] args) throws Exceptionint statusCode = response.getStatusLine(.getStatusCode(;System.out.println("Status Code: " + statusCode);//处理响应数据//...}```2.发送POST请求:```javapublic class HttpPostExamplepublic static void main(String[] args) throws Exception//设置请求体StringEntity requestBody = new StringEntity("request body", "UTF-8");int statusCode = response.getStatusLine(.getStatusCode(;System.out.println("Status Code: " + statusCode);//处理响应数据//...}```3.发送PUT请求:```javapublic class HttpPutExamplepublic static void main(String[] args) throws Exception//设置请求体StringEntity requestBody = new StringEntity("request body", "UTF-8");int statusCode = response.getStatusLine(.getStatusCode(;System.out.println("Status Code: " + statusCode);//处理响应数据//...}```4.发送DELETE请求:```javapublic class HttpDeleteExamplepublic static void main(String[] args) throws Exceptionint statusCode = response.getStatusLine(.getStatusCode(;System.out.println("Status Code: " + statusCode);//处理响应数据//...}```以上代码示例了如何使用HttpClient库发送GET、POST、PUT、DELETE请求,并处理响应数据。

我又踩坑了!如何为HttpClient请求设置Content-Type?

我又踩坑了!如何为HttpClient请求设置Content-Type?

我⼜踩坑了!如何为HttpClient请求设置Content-Type?1. 坑位最近在重构认证代码,认证过程相当常规:POST /open-api/v1/user-info?client_id&timstamp&rd=12345&sign=***&method=hmaccontent-type: application/jsonpayload: { "token":"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74"}平台显⽰:签名校验失败,排查到平台收到的Post Payload并⾮预期,阅读本⽂,解锁正确使⽤Content-Type标头的姿势。

2. 步步为营下⾯是构造HttpClient对象、发起请求的代码:// 初始化HttpClientFactorycontext.Services.AddHttpClient("platform", c =>{c.BaseAddress = new Uri("https:///");c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));})...// 产⽣命名HttpClient,发起请求var client = _clientFactory.CreateClient("platform");var response = await client.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",new StringContent(req.ReqPayload.ToString(),Encoding.UTF8) );平台⽇志显⽰,收到的请求payload:{\"token\":\"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74\"}额,平台收到的JSON数据被转码了,没有识别出JSON?明眼⼈⼀看,HttpClient请求没有设置Content-Type,接收端没有识别出payload是JSON,接收时进⾏了转码,⽣成了错误签名。

springboot使用RestTemplate+httpclient连接池发送http消息

springboot使用RestTemplate+httpclient连接池发送http消息

springboot使⽤RestTemplate+httpclient连接池发送http消息简介1. RestTemplate是spring⽀持的⼀个请求http rest服务的模板对象,性质上有点像jdbcTemplate2. RestTemplate底层还是使⽤的httpclient(org.apache.http.client.HttpClient)发送请求的3. HttpClient可以做连接池,⽽发送消息的⼯具类可以使⽤RestTemplate,所以如果你的项⽬需求http连接池,RestTemplate+httpclient连接池是⼀种不错的⽅式,可以节省开发⼯作,也可以更优雅的使⽤。

配置1. maven依赖<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>2. Java配置类package com.jinjian.rt.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import ponent;@Component@ConfigurationProperties(prefix = "http-pool")@Datapublic class HttpPoolProperties {private Integer maxTotal;private Integer defaultMaxPerRoute;private Integer connectTimeout;private Integer connectionRequestTimeout;private Integer socketTimeout;private Integer validateAfterInactivity;}package com.jinjian.rt.config;import org.apache.http.client.HttpClient;import org.apache.http.client.config.RequestConfig;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.conn.socket.ConnectionSocketFactory;import org.apache.http.conn.socket.PlainConnectionSocketFactory;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.ClientHttpRequestFactory;import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;import org.springframework.web.client.RestTemplate;@Configurationpublic class RestTemplateConfig {@Autowiredprivate HttpPoolProperties httpPoolProperties;@Beanpublic RestTemplate restTemplate() {return new RestTemplate(httpRequestFactory());}@Beanpublic ClientHttpRequestFactory httpRequestFactory() {return new HttpComponentsClientHttpRequestFactory(httpClient());}@Beanpublic HttpClient httpClient() {Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", SSLConnectionSocketFactory.getSocketFactory()).build();PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute());connectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity());RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(httpPoolProperties.getSocketTimeout()) //服务器返回数据(response)的时间,超过抛出read timeout.setConnectTimeout(httpPoolProperties.getConnectTimeout()) //连接上服务器(握⼿成功)的时间,超出抛出connect timeout.setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout())//从连接池中获取连接的超时时间,超时间未拿到可⽤连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for .build();return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();}}3. 使⽤⽅法package com.jinjian.rt.service;import com.jinjian.rt.dto.RuiooResponseEntity;import org.json.JSONException;import org.json.JSONObject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;import java.io.IOException;@Servicepublic class TestService {@Autowiredprivate RestTemplate restTemplate;public void startTest() throws JSONException, IOException {JSONObject jsonObject = new JSONObject();jsonObject.put("first","jinjian");jsonObject.put("second","aaaaaaa");long start = System.currentTimeMillis();//{1} 表⽰第⼀个占位符,也可以填写name,但是这是另⼀个getForEntity重载⽅法//RuiooResponseEntity 为⾃定义dtoResponseEntity<RuiooResponseEntity> entity = restTemplate.getForEntity("http://39.107.104.221/api/test/{1}", RuiooResponseEntity.class, 123);long end = System.currentTimeMillis();long cost = end - start;System.out.println("耗时:"+cost);RuiooResponseEntity body = entity.getBody();body.getData();body.getStatus();body.getMessage();System.out.println("响应体:"+ body);}}。

HttpClient如何设置超时时间

HttpClient如何设置超时时间今天分享⼀个巨坑,就是 HttpClient。

这玩意有多坑呢?就是每个版本都变,近⽇笔者深受其害。

先看⼀下代码,我要发送请求调⽤⼀个c++接⼝。

public static String doPostWithJSON(String url, String json) throws Exception {CloseableHttpClient client = HttpClients.createDefault();HttpPost httpPost = new HttpPost(url);httpPost.setHeader("Content-Type","application/json;charset=UTF-8");StringEntity se = new StringEntity(json, Charset.forName("UTF-8"));se.setContentType("application/json");httpPost.setEntity(se);CloseableHttpResponse response = client.execute(httpPost);HttpEntity entity = response.getEntity();String result = EntityUtils.toString(entity, "UTF-8");return result;}嗯,坑爹的地⽅来了,这个玩意发送请求,没设置超时时间,只要不响应,他能⼀直在这等着,这谁能受得了。

我要加个超时时间。

第⼆个⼤坑来了。

我记得以前设置超时时间是这样的。

client.setConnectionTimeout(10000);client.setTimeout(10000);我发现,特么没这个⽅法。

基于HttpClient上传文件中文名乱码的解决

基于HttpClient上传⽂件中⽂名乱码的解决现象使⽤HttpClient⼯具上传⽂件时,如果⽂件名是中⽂,⽂件名会乱码⽂件名乱码的代码:private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension,File fileToUpload) {MultipartEntityBuilder builder = MultipartEntityBuilder.create();builder.addTextBody("scenarioId", scenarioId.toString());for (String groupId : groupIds) {builder.addTextBody("groupIds", groupId);}builder.addTextBody("extension", extension);builder.addPart("fileToUpload", new FileBody(fileToUpload));builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());builder.addTextBody("isSplit", "false");builder.addTextBody("isRefresh", "false");return builder.build();乱码原因:HttpClient上传⽂件时,会调⽤doWriteTo⽅法,写⼀个输出流,但是在调⽤formatMultipartHeader⽅法时,底层主要有3种不同的实现,3种⽅式的采⽤的字符集不⼀样HttpClient中的doWriteTo⽅法:void doWriteTo(final OutputStream out,final boolean writeContent) throws IOException {final ByteArrayBuffer boundaryEncoded = encode(this.charset, this.boundary);for (final FormBodyPart part: getBodyParts()) {writeBytes(TWO_DASHES, out);writeBytes(boundaryEncoded, out);writeBytes(CR_LF, out);//此处代码主要有3种不同的实现,不同的mode,实现⽅式不⼀样,采⽤的字符集也不同formatMultipartHeader(part, out);writeBytes(CR_LF, out);if (writeContent) {part.getBody().writeTo(out);}writeBytes(CR_LF, out);}writeBytes(TWO_DASHES, out);writeBytes(boundaryEncoded, out);writeBytes(TWO_DASHES, out);writeBytes(CR_LF, out);}其中的formatMultipartHeader⽅法,不同的模式有不同的实现⽅式MultipartEntityBuilderMultipartFormEntity buildEntity() {String boundaryCopy = boundary;if (boundaryCopy == null && contentType != null) {boundaryCopy = contentType.getParameter("boundary");}if (boundaryCopy == null) {boundaryCopy = generateBoundary();}Charset charsetCopy = charset;if (charsetCopy == null && contentType != null) {charsetCopy = contentType.getCharset();}final List<NameValuePair> paramsList = new ArrayList<NameValuePair>(2);paramsList.add(new BasicNameValuePair("boundary", boundaryCopy));if (charsetCopy != null) {paramsList.add(new BasicNameValuePair("charset", ()));}final NameValuePair[] params = paramsList.toArray(new NameValuePair[paramsList.size()]);final ContentType contentTypeCopy = contentType != null ?contentType.withParameters(params) :ContentType.create("multipart/" + DEFAULT_SUBTYPE, params);final List<FormBodyPart> bodyPartsCopy = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) : Collections.<FormBodyPart>emptyList();//此处将mode赋值给modeCopyfinal HttpMultipartMode modeCopy = mode != null ? mode : HttpMultipartMode.STRICT;final AbstractMultipartForm form;//此处根据modeCopy的值不同,构造3种form,每种的字符集都不⼀样,也是产⽣乱码的根源switch (modeCopy) {case BROWSER_COMPATIBLE:form = new HttpBrowserCompatibleMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);break;case RFC6532:form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, bodyPartsCopy);break;default:form = new HttpStrictMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);}return new MultipartFormEntity(form, contentTypeCopy, form.getTotalLength());}public HttpEntity build() {return buildEntity();}BROWSER_COMPATIBLE模式中的formatMultipartHeader⽅法class HttpBrowserCompatibleMultipart extends AbstractMultipartForm {private final List<FormBodyPart> parts;public HttpBrowserCompatibleMultipart(final Charset charset,final String boundary,final List<FormBodyPart> parts) {super(charset, boundary);this.parts = parts;}@Overridepublic List<FormBodyPart> getBodyParts() {return this.parts;}/*** Write the multipart header fields; depends on the style.*/@Overrideprotected void formatMultipartHeader(final FormBodyPart part,final OutputStream out) throws IOException {// For browser-compatible, only write Content-Disposition// Use content charsetfinal Header header = part.getHeader();final MinimalField cd = header.getField(MIME.CONTENT_DISPOSITION);//可以看到此处的字符集采⽤的是设置的字符集writeField(cd, this.charset, out);final String filename = part.getBody().getFilename();if (filename != null) {final MinimalField ct = header.getField(MIME.CONTENT_TYPE);//可以看到此处的字符集采⽤的也是设置的字符集writeField(ct, this.charset, out);}}}RFC6532模式中的formatMultipartHeader⽅法class HttpRFC6532Multipart extends AbstractMultipartForm {private final List<FormBodyPart> parts;public HttpRFC6532Multipart(final Charset charset,final String boundary,final List<FormBodyPart> parts) {super(charset, boundary);this.parts = parts;}@Overridepublic List<FormBodyPart> getBodyParts() {return this.parts;}@Overrideprotected void formatMultipartHeader(final FormBodyPart part,final OutputStream out) throws IOException {// For RFC6532, we output all fields with UTF-8 encoding.final Header header = part.getHeader();for (final MinimalField field: header) {//可以看到此处的字符集默认采⽤UTF8writeField(field, MIME.UTF8_CHARSET, out);}}}默认模式中的formatMultipartHeader⽅法class HttpStrictMultipart extends AbstractMultipartForm {private final List<FormBodyPart> parts;public HttpStrictMultipart(final Charset charset,final String boundary,final List<FormBodyPart> parts) {super(charset, boundary);this.parts = parts;}@Overridepublic List<FormBodyPart> getBodyParts() {return this.parts;}@Overrideprotected void formatMultipartHeader(final FormBodyPart part,final OutputStream out) throws IOException {// For strict, we output all fields with MIME-standard encoding.//从上⾯注释中可以看到,此处的字符集采⽤的是默认字符集即ASCII(下⾯MIME类中可以看到) final Header header = part.getHeader();for (final MinimalField field: header) {writeField(field, out);}}}MIME类public final class MIME {public static final String CONTENT_TYPE = "Content-Type";public static final String CONTENT_TRANSFER_ENC = "Content-Transfer-Encoding";public static final String CONTENT_DISPOSITION = "Content-Disposition";public static final String ENC_8BIT = "8bit";public static final String ENC_BINARY = "binary";/** The default character set to be used, i.e. "US-ASCII" */public static final Charset DEFAULT_CHARSET = Consts.ASCII;/** UTF-8 is used for RFC6532 */public static final Charset UTF8_CHARSET = Consts.UTF_8;}解决⽅法知道乱码产⽣的根源,乱码问题也就好解决了,解决⽅式有两种设置mode为:BROWSER_COMPATIBLE,并设置字符集为UTF8 private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension,File fileToUpload) {MultipartEntityBuilder builder = MultipartEntityBuilder.create();//设置模式为BROWSER_COMPATIBLE,并设置字符集为UTF8builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);builder.setCharset(Charset.forName("UTF-8"));builder.addTextBody("scenarioId", scenarioId.toString());for (String groupId : groupIds) {builder.addTextBody("groupIds", groupId);}builder.addTextBody("extension", extension);builder.addPart("fileToUpload", new FileBody(fileToUpload));builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());builder.addTextBody("isSplit", "false");builder.addTextBody("isRefresh", "false");return builder.build();}设置模式为:RFC6532private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension, File fileToUpload) {MultipartEntityBuilder builder = MultipartEntityBuilder.create();//设置模式为RFC6532builder.setMode(HttpMultipartMode.RFC6532);builder.addTextBody("scenarioId", scenarioId.toString());for (String groupId : groupIds) {builder.addTextBody("groupIds", groupId);}builder.addTextBody("extension", extension);builder.addPart("fileToUpload", new FileBody(fileToUpload));builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());builder.addTextBody("isSplit", "false");builder.addTextBody("isRefresh", "false");return builder.build();}以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

HttpClient接口测试之会话保持

HttpClient接⼝测试之会话保持HttpClient接⼝测试之会话保持HttpClient4.X⾃带会话保持功能,使⽤同⼀个HttpClient未关闭的连接即可保持登陆会话,如果多个HttpClient想要使⽤⼀个登陆会话,则需要保存会话信息,其中⼀种⽅法是使⽤HttpClientContext。

import java.util.ArrayList;import java.util.List;import org.apache.http.HttpEntity;import ValuePair;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.client.protocol.HttpClientContext;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicNameValuePair;import org.apache.http.protocol.BasicHttpContext;import org.apache.http.protocol.HttpContext;import org.apache.http.util.EntityUtils;import org.junit.Test;import com.test.tools.Regular;public class HttpClientTest {String loginUrl = "http://**.***.com/user/login.do";private static HttpContext localContext = new BasicHttpContext();private static HttpClientContext context = HttpClientContext.adapt(localContext);@Testpublic void Test() throws Exception {CloseableHttpClient httpClient = HttpClients.createDefault();try {// 模拟表单List<NameValuePair> params = new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("username", "admin"));params.add(new BasicNameValuePair("password", "admin"));UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");HttpPost httpPost = new HttpPost(loginUrl);httpPost.setEntity(entity);// 将HttpClientContext传⼊execute()中CloseableHttpResponse response = httpClient.execute(httpPost, context);try {HttpEntity responseEntity = response.getEntity();System.out.println(EntityUtils.toString(responseEntity));} finally {response.close();}} finally {httpClient.close();进⼊⾸页设置相同的HttpClientContext正则提取响应信息中的⽤户名通过这种⽅式可以进⾏接⼝测试,也可以加⼊断⾔事务,添加多线程并发进⾏接⼝性能测试。

httpClient远程调用webService

我们将Web Service发布在Tomcat或者其他应用服务器上后,有很多方法可以调用该Web Service,常用的有两种:1、通过浏览器HTTP调用,返回规范的XML文件内容2、通过客户端程序调用,返回结果可自定义格式接下来,我利用Eclipse作为开发工具,演示一个Httpclient调用WebService的简单示例步骤如下:准备工作:用到的jar包有:下载链接(/detail/lanxuezaipiao/5354480)第一步:新建Java Project,项目名称为HttpCallWebService第二步:将所需jar包导入到库中第三步:编写调用class,这里有两种方式调用,即GET方式和POST方式,由于POST 方式较安全,故这里采用POST方式调用;请求数据的构造也有两种方式:静态和动态构造,下面分别介绍这两种方式:注:这里以E邮宝开放的webservice接口为例调用其中一个API函数,而E邮宝的webservice基于SOAP,故请求数据为SOAP格式,大家可根据自己情况进行修改。

静态构造请求数据:package com.http;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import mons.httpclient.HttpClient;import mons.httpclient.HttpException;import mons.httpclient.methods.InputStreamRequestEntity;import mons.httpclient.methods.PostMethod;import mons.httpclient.methods.RequestEntity;public class StaticHttpclientCall {/*** @param args* @throws IOException* @throws HttpException*/public static void main(String[] args) throws HttpException, IOException {// TODO Auto-generated method stubString soapRequestData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+ "<soap12:Envelopexmlns:xsi=\"/2001/XMLSchema-instance\""+ " xmlns:xsd=\"/2001/XMLSchema\""+ " xmlns:soap12=\"/2003/05/soap-envelope\">"+ " <soap12:Body>"+ " <GetAPACShippingPackage xmlns=\"/\">"+ " <GetAPACShippingPackageRequest>"+ " <TrackCode>123</TrackCode>"+ " <Version>123</Version>"+ " <APIDevUserID>123</APIDevUserID>"+ " <APIPassword>123</APIPassword>"+ " <APISellerUserID>123</APISellerUserID>"+ " <MessageID>123</MessageID>"+ " </GetAPACShippingPackageRequest>"+ " </GetAPACShippingPackage>" + "</soap12:Body>"+ " </soap12:Envelope>";System.out.println(soapRequestData);PostMethod postMethod = new PostMethod("/v3/orderservice.asmx?wsdl");// 然后把Soap请求数据添加到PostMethod中byte[] b = soapRequestData.getBytes("utf-8");InputStream is = new ByteArrayInputStream(b, 0, b.length);RequestEntity re = new InputStreamRequestEntity(is, b.length,"application/soap+xml; charset=utf-8");postMethod.setRequestEntity(re);// 最后生成一个HttpClient对象,并发出postMethod请求HttpClient httpClient = new HttpClient();int statusCode = httpClient.executeMethod(postMethod);if(statusCode == 200) {System.out.println("调用成功!");String soapResponseData = postMethod.getResponseBodyAsString();System.out.println(soapResponseData);}else {System.out.println("调用失败!错误码:" + statusCode);}}}动态构造数据:package com.http;import java.io.ByteArrayInputStream;import java.io.InputStream;import java.util.HashMap;import java.util.Map;import java.util.Set;import mons.httpclient.HttpClient;import mons.httpclient.methods.InputStreamRequestEntity;import mons.httpclient.methods.PostMethod;import mons.httpclient.methods.RequestEntity;// 动态构造调用串,灵活性更大public class DynamicHttpclientCall {private String namespace;private String methodName;private String wsdlLocation;private String soapResponseData;public DynamicHttpclientCall(String namespace, String methodName,String wsdlLocation) {space = namespace;this.methodName = methodName;this.wsdlLocation = wsdlLocation;}private int invoke(Map<String, String> patameterMap) throws Exception { PostMethod postMethod = new PostMethod(wsdlLocation);String soapRequestData = buildRequestData(patameterMap);byte[] bytes = soapRequestData.getBytes("utf-8");InputStream inputStream = new ByteArrayInputStream(bytes, 0,bytes.length);RequestEntity requestEntity = new InputStreamRequestEntity(inputStream, bytes.length, "application/soap+xml; charset=utf-8");postMethod.setRequestEntity(requestEntity);HttpClient httpClient = new HttpClient();int statusCode = httpClient.executeMethod(postMethod);soapResponseData = postMethod.getResponseBodyAsString();return statusCode;}private String buildRequestData(Map<String, String> patameterMap) {StringBuffer soapRequestData = new StringBuffer();soapRequestData.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");soapRequestData.append("<soap12:Envelopexmlns:xsi=\"/2001/XMLSchema-instance\""+ " xmlns:xsd=\"/2001/XMLSchema\""+ "xmlns:soap12=\"/2003/05/soap-envelope\">");soapRequestData.append("<soap12:Body>");soapRequestData.append("<" + methodName + " xmlns=\"" + namespace+ "\">");soapRequestData.append("<" + methodName + "Request>");Set<String> nameSet = patameterMap.keySet();for (String name : nameSet) {soapRequestData.append("<" + name + ">" + patameterMap.get(name)+ "</" + name + ">");}soapRequestData.append("</" + methodName + "Request>");soapRequestData.append("</" + methodName + ">");soapRequestData.append("</soap12:Body>");soapRequestData.append("</soap12:Envelope>");return soapRequestData.toString();}/*** @param args* @throws Exception*/public static void main(String[] args) throws Exception {// TODO Auto-generated method stubDynamicHttpclientCall dynamicHttpclientCall = new DynamicHttpclientCall("/", "GetAPACShippingPackage","/v3/orderservice.asmx?wsdl");Map<String, String> patameterMap = new HashMap<String, String>();patameterMap.put("TrackCode", "123");patameterMap.put("Version", "123");patameterMap.put("APIDevUserID", "123");patameterMap.put("APIPassword", "123");patameterMap.put("APISellerUserID", "123");patameterMap.put("MessageID", "123");patameterMap.put("TrackCode", "123");String soapRequestData = dynamicHttpclientCall.buildRequestData(patameterMap);System.out.println(soapRequestData);int statusCode = dynamicHttpclientCall.invoke(patameterMap);if(statusCode == 200) {System.out.println("调用成功!");System.out.println(dynamicHttpclientCall.soapResponseData);}else {System.out.println("调用失败!错误码:" + statusCode);}}}最终运行结果:可见最终返回的也是xml格式的数据,这里数据未进行格式化显示和处理。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

HttpClient 教程 (一) 前言 超文本传输协议(HTTP)也许是当今互联网上使用的最重要的协议了。Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web浏览器范畴,同时,也增加了需要HTTP协议支持的应用程序的数量。

尽管java.net包提供了基本通过HTTP访问资源的功能,但它没有提供全面的灵活性和其它很多应用程序需要的功能。HttpClient就是寻求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议。

为扩展而设计,同时为基本的HTTP协议提供强大的支持,HttpClient组件也许就是构建HTTP客户端应用程序,比如web浏览器,web服务端,利用或扩展HTTP协议进行分布式通信的系统的开发人员的关注点。

1. HttpClient的范围  基于HttpCore[http://hc.apache.org/httpcomponents-core/index.html]的客户端

HTTP运输实现库

 基于经典(阻塞)I/O

 内容无关

2. 什么是HttpClient不能做的

 HttpClient不是一个浏览器。它是一个客户端的HTTP通信实现库。HttpClient的目标是

发送和接收HTTP报文。HttpClient不会去缓存内容,执行嵌入在HTML页面中的javascript代码,猜测内容类型,重新格式化请求/重定向URI,或者其它和HTTP运输无关的功能。

第一章 基础

1.1 执行请求 HttpClient最重要的功能是执行HTTP方法。一个HTTP方法的执行包含一个或多个HTTP请求/HTTP响应交换,通常由HttpClient的内部来处理。而期望用户提供一个要执行的请求对象,而HttpClient期望传输请求到目标服务器并返回对应的响应对象,或者当执行不成功时抛出异常。

很自然地,HttpClient API的主要切入点就是定义描述上述规约的HttpClient接口。 这里有一个很简单的请求执行过程的示例: HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost/"); HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); int l; byte[] tmp = new byte[2048]; while ((l = instream.read(tmp)) != -1) { } }

1.1.1 HTTP请求

所有HTTP请求有一个组合了方法名,请求URI和HTTP协议版本的请求行。 HttpClient支持所有定义在HTTP/1.1版本中的HTTP方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。对于每个方法类型都有一个特殊的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace和HttpOptions。

请求的URI是统一资源定位符,它标识了应用于哪个请求之上的资源。HTTP请求URI包含一个协议模式,主机名称,可选的端口,资源路径,可选的查询和可选的片段。

HttpGet httpget = new HttpGet( "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");

HttpClient提供很多工具方法来简化创建和修改执行URI。 URI也可以编程来拼装:

URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",

"q=httpclient&btnG=Google+Search&aq=f&oq=", null); HttpGet httpget = new HttpGet(uri); System.out.println(httpget.getURI());

输出内容为: http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq= 查询字符串也可以从独立的参数中来生成: List qparams = new ArrayList(); qparams.add(new BasicNameValuePair("q", "httpclient")); qparams.add(new BasicNameValuePair("btnG", "Google Search")); qparams.add(new BasicNameValuePair("aq", "f")); qparams.add(new BasicNameValuePair("oq", null)); URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search", URLEncodedUtils.format(qparams, "UTF-8"), null); HttpGet httpget = new HttpGet(uri); System.out.println(httpget.getURI());

输出内容为: http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=

1.1.2 HTTP响应 HTTP响应是由服务器在接收和解释请求报文之后返回发送给客户端的报文。响应报文的第一行包含了协议版本,之后是数字状态码和相关联的文本段。

HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,

HttpStatus.SC_OK, "OK"); System.out.println(response.getProtocolVersion()); System.out.println(response.getStatusLine().getStatusCode()); System.out.println(response.getStatusLine().getReasonPhrase()); System.out.println(response.getStatusLine().toString());

输出内容为:

HTTP/1.1 200 OK HTTP/1.1 200 OK 1.1.3 处理报文头部

一个HTTP报文可以包含很多描述如内容长度,内容类型等信息属性的头部信息。 HttpClient提供获取,添加,移除和枚举头部信息的方法。

HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,

HttpStatus.SC_OK, "OK"); response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost"); response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\""); Header h1 = response.getFirstHeader("Set-Cookie"); System.out.println(h1); Header h2 = response.getLastHeader("Set-Cookie"); System.out.println(h2); Header[] hs = response.getHeaders("Set-Cookie"); System.out.println(hs.length);

输出内容为:

Set-Cookie: c1=a; path=/; domain=localhost Set-Cookie: c2=b; path="/", c3=c; domain="localhost"

获得给定类型的所有头部信息最有效的方式是使用HeaderIterator接口。

HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost"); response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\""); HeaderIterator it = response.headerIterator("Set-Cookie");

相关文档
最新文档