HttpClient简介及使用

一、HttpClient 简介

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

java.net和HttpClient对比:

java.net包提供了通过HTTP访问资源的基本功能,但它缺少足够的灵活性和其它很多应用程序需要的功能。HttpClient通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议,来弥补java.net包的在某些技术上的空白。

HttpClient 所不能做的:

HttpClient 不是一个浏览器。它是一个客户端的 HTTP 通信实现库。HttpClient 的目标是发送和接收HTTP 报文。HttpClient 不会去处理内容,执行嵌入在 HTML页面中的javascript 代码,猜测内容类型,如果没有明确设置,否则不会重新格式化请求/重定向URI,或其它和HTTP通信无关的功能。

HttpClient的主要功能:

  • 实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
  • 支持 HTTPS 协议
  • 支持代理服务器(Nginx等)等
  • 支持自动(跳转)转向
  • ……

二、HttpClient使用方法

环境说明:Eclipse、JDK1.8、SpringBoot

HttpClient依赖:

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.5</version>
        </dependency>
        <dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
			<version>4.5.5</version>
		</dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

使用方法:

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

  • 创建HttpClient对象。
  • 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
  • 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
  • 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
  • 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
  • 释放连接。无论执行方法是否成功,都必须释放连接

测试方法:在这里新建了两个Controller分别为HelloController和WorldController,其中HelloController有网页直接请求访问,其具体访问方法中使用HttpClient工具类去请求WorldController从而到达测试的的目的。

1、Get方式无参数测试

HttpClient工具类:

/**
	 * HttpClien---get方式无参数测试
	 */
	public static String doGet(String url) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//创建Get请求实例
		HttpGet httpGet = new HttpGet(url);
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			//客户端执行发送Get请求
			response = httpClient.execute(httpGet);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Get无参请求测试
	 * @return
	 */
	@RequestMapping("/doGet")
	public String doGet() {
		return HttpClientsUtil.doGet("http://localhost:8080/doGetWorld");
	}

WorldController:

/**
	 * Get无参请求测试
	 * @return
	 */
	@RequestMapping("/doGetWorld")
	public String doGetWorld() {
		System.err.println("Get无参请求测试");
		return "Get!!!";
	}

控制台打印结果:

Get无参请求测试
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:Get!!!

2、Get方式带参数测试(路径+参数拼接方式一)

HttpClient工具类:

/**
	 * get方式带参数测试(路径+参数拼接方式一)
	 */
	public static String doParamsGet(String url,Map<String,String> paramMap) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//创建Get请求实例
		HttpGet httpGet = new HttpGet();
		//装填参数
		List<NameValuePair> httpParams = setHttpParams(paramMap);
		//编码(统一为utf-8)
		String param = URLEncodedUtils.format(httpParams, "UTF-8");
		//设置路径
		httpGet.setURI(URI.create(url+"?"+param));
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			// 配置信息
			RequestConfig config = RequestConfig.custom()
			// 设置连接超时时间(单位毫秒
				.setConnectTimeout(5000)
				// 设置请求超时时间(单位毫秒)
				.setConnectionRequestTimeout(5000)
				// socket读写超时时间(单位毫秒)
				.setSocketTimeout(5000)
				// 设置是否允许重定向(默认为true)
				.setRedirectsEnabled(true)
				.build();
			// 将上面的配置信息 运用到这个Get请求里
			httpGet.setConfig(config);
			//客户端执行发送Get请求
			response = httpClient.execute(httpGet);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

    //装填参数
	public static List<NameValuePair> setHttpParams(Map<String,String> paramMap){
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		Set<Entry<String,String>> set = paramMap.entrySet();
		for(Entry<String, String> entry:set) {
			list.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
		}
		return list;
	}

HelloController:

/**
	 * Get带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doParamsGet")
	public String doParamsGet() {
		String url = "http://localhost:8080/doParamsGetWorld";
		
		Map<String,String> map = new HashMap<String,String>();
		map.put("name", "阿呆");
		
		Map<String,String> uriMap = new HashMap<String,String>();
		uriMap.put("http", "http");
		uriMap.put("localhost", "localhost");
		uriMap.put("port", "8080");
		uriMap.put("path", "/doParamsGetWorld");
		return HttpClientsUtil.doParamsGet(url,map);
	}

WorldController:

/**
	 * Get带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doParamsGetWorld")
	public String doParamsGetWorld(HttpServletRequest request) {
		String name=request.getParameter("name");
		System.err.println("Get带参数请求测试:"+name);
		return name;
	}

控制台打印结果:

Get带参数请求测试:阿呆
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:阿呆

 

3、Get方式带参数测试(路径+参数拼接方式二)

HttpClient工具类:

/**
	 * get方式带参数测试(路径+参数拼接方式二)
	 */
	public static String doParamsGet(Map<String,String> uriMap,Map<String,String> paramMap) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//装填参数
		List<NameValuePair> httpParams = setHttpParams(paramMap);
		//路径及参数拼接
		URI uri = null;
		try {
			uri = new URIBuilder().setScheme(uriMap.get("http")).setHost(uriMap.get("localhost"))
			          .setPort(Integer.parseInt(uriMap.get("port"))).setPath(uriMap.get("path"))
			          .setParameters(httpParams).build();
		} catch (URISyntaxException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//创建Get请求实例
		HttpGet httpGet = new HttpGet(uri);
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			// 配置信息
			RequestConfig config = RequestConfig.custom()
			// 设置连接超时时间(单位毫秒
				.setConnectTimeout(5000)
				// 设置请求超时时间(单位毫秒)
				.setConnectionRequestTimeout(5000)
				// socket读写超时时间(单位毫秒)
				.setSocketTimeout(5000)
				// 设置是否允许重定向(默认为true)
				.setRedirectsEnabled(true)
				.build();
			// 将上面的配置信息 运用到这个Get请求里
			httpGet.setConfig(config);
			//客户端执行发送Get请求
			response = httpClient.execute(httpGet);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

	/**
	 * Get带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doParamsGet")
	public String doParamsGet() {
		String url = "http://localhost:8080/doParamsGetWorld";
		
		Map<String,String> map = new HashMap<String,String>();
		map.put("name", "阿呆");
		
		Map<String,String> uriMap = new HashMap<String,String>();
		uriMap.put("http", "http");
		uriMap.put("localhost", "localhost");
		uriMap.put("port", "8080");
		uriMap.put("path", "/doParamsGetWorld");
		return HttpClientsUtil.doParamsGet(uriMap,map);
	}

WorldController:

/**
	 * Get带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doParamsGetWorld")
	public String doParamsGetWorld(HttpServletRequest request) {
		String name=request.getParameter("name");
		System.err.println("Get带参数请求测试:"+name);
		return name;
	}

控制台打印结果:

Get带参数请求测试:阿呆
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:阿呆

 

4、Post方式无参数测试

HttpClient工具类:

/**
	 * Post无参请求测试
	 * @return
	 */
	public static String doPost(String url) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//创建Post请求实例
		HttpPost httpPost = new HttpPost(url);
		// 响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			//客户端执行发送Post请求
			response = httpClient.execute(httpPost);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
			
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Post无参请求测试
	 * @return
	 */
	@RequestMapping("/doPost")
	public String doPost() {
		return HttpClientsUtil.doPost("http://localhost:8080/doPostWorld");
	}

WorldController:

/**
	 * Post无参请求测试
	 * @return
	 */
	@RequestMapping(value = "/doPostWorld",method = RequestMethod.POST)
	public String doGetPost() {
		System.err.println("Post无参请求测试");
		return "Post!!!";
	}

控制台打印结果:

Post无参请求测试
响应状态为:HTTP/1.1 200 
响应内容长度为:7
响应内容为:Post!!!

 

5、Post方式带参数测试(普通参数)

HttpClient工具类:

/**
	 * Post方式带参数测试(普通参数)
	 */
	public static String doParamsPost(String url,Map<String,String> paramMap) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//装填参数
		List<NameValuePair> httpParams = setHttpParams(paramMap);
//方式一:		
//		//创建Post请求实例
//		HttpPost httpPost = new HttpPost();
//		//编码(统一为utf-8)
//		String param = URLEncodedUtils.format(httpParams, "UTF-8");
//		//设置路径
//		httpPost.setURI(URI.create(url+"?"+param));
//方式二:
		//创建Post请求实例
		HttpPost httpPost = new HttpPost(url);
		//编码(统一为utf-8)
		UrlEncodedFormEntity param = null;
		try {
			 param = new UrlEncodedFormEntity(httpParams, "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//通过setEntity()设置参数给post
        httpPost.setEntity(param);
        
        
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			// 配置信息
			RequestConfig config = RequestConfig.custom()
			// 设置连接超时时间(单位毫秒
				.setConnectTimeout(5000)
				// 设置请求超时时间(单位毫秒)
				.setConnectionRequestTimeout(5000)
				// socket读写超时时间(单位毫秒)
				.setSocketTimeout(5000)
				// 设置是否允许重定向(默认为true)
				.setRedirectsEnabled(true)
				.build();
			// 将上面的配置信息 运用到这个Post请求里
			httpPost.setConfig(config);
			//客户端执行发送Post请求
			response = httpClient.execute(httpPost);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Post带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doParamsPost")
	public String doParamsPost() {
		String url = "http://localhost:8080/doParamsPostWorld";
		Map<String,String> map = new HashMap<String,String>();
		map.put("name", "阿美");
		
		return HttpClientsUtil.doParamsPost(url,map);
	}

WorldController:

/**
	 * Post带参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/doParamsPostWorld",method = RequestMethod.POST)
	public String doParamsPostWorld(HttpServletRequest request) {
		String name=request.getParameter("name");
		System.err.println("Post带参数请求测试:"+name);
		return name;
	}

控制台打印结果:

Post带参数请求测试:阿美
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:阿美

 

6、Post方式带参数测试(对象作为参数)

HttpClient工具类:

/**
	 * Post方式带参数测试(对象作为参数)
	 */
	public static String doParamsPost(String url,User user) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//创建Post请求实例
		HttpPost httpPost = new HttpPost(url);
		// 利用阿里的fastjson,将Object转换为json字符串
		String jsonString = JSON.toJSONString(user);
		//编码(统一为utf-8)
		StringEntity entity = new StringEntity(jsonString, "UTF-8");
		// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
		httpPost.setEntity(entity);
		//设置请求头
		httpPost.setHeader("Content-Type", "application/json;charset=utf8");
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			//客户端执行发送Post请求
			response = httpClient.execute(httpPost);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Post对象作为参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doObjParamsPost")
	public String doObjParamsPost() {
		String url = "http://localhost:8080/doObjParamsPostWorld";
		User user = new User("阿梅","女",18);
		System.out.println(user);
		return HttpClientsUtil.doParamsPost(url,user);
	}

WorldController:

/**
	 * Post对作为参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/doObjParamsPostWorld",method = RequestMethod.POST)
	public String doObjParamsPostWorld(@RequestBody User user) {
		System.err.println("Post带参数请求测试:"+user);
		return user.getName();
	}

控制台打印结果:

User [name=阿梅, sex=女, age=18]
Post带参数请求测试:User [name=阿梅, sex=女, age=18]
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:阿梅

 

7、Post方式带参数测试(普通参数和对象作为参数)

HttpClient工具类:

/**
	 * Post方式带参数测试(普通参数和对象作为参数)
	 */
	public static String doParamsPost(String url,User user,Map<String,String> paramMap) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();		
		//装填参数
		List<NameValuePair> httpParams = setHttpParams(paramMap);
		//创建Post请求实例
		HttpPost httpPost = new HttpPost();
		//编码(统一为utf-8)
		String param = URLEncodedUtils.format(httpParams, "UTF-8");
		//设置路径
		httpPost.setURI(URI.create(url+"?"+param));
		// 利用阿里的fastjson,将Object转换为json字符串
		String jsonString = JSON.toJSONString(user);
		//编码(统一为utf-8)
		StringEntity entity = new StringEntity(jsonString, "UTF-8");
		// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
		httpPost.setEntity(entity);
		//设置请求头
		httpPost.setHeader("Content-Type", "application/json;charset=utf8");
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			//客户端执行发送Post请求
			response = httpClient.execute(httpPost);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Post普通参数和对象作为参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/paramsPost")
	public String paramsPost() {
		String url = "http://localhost:8080/paramsPostWorld";
		Map<String,String> map = new HashMap<String,String>();
		map.put("name", "阿美");
		User user = new User("阿梅","女",18);
		return HttpClientsUtil.doParamsPost(url,user,map);
	}

WorldController:

/**
	 * Post对象和普通参数作为参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/paramsPostWorld",method = RequestMethod.POST)
	public String paramsPostWorld(@RequestBody User user,HttpServletRequest request) {
		System.err.println("Post带参数请求测试:"+user);
		String name=request.getParameter("name");
		System.err.println("Post带参数请求测试:"+name);
		return user.getName();
	}

控制台打印结果:

 

8、 Post文件作为参数测试

HttpClient工具类:

/**
	 * Post文件作为参数测试
	 * @param paramMap
	 * @return
	 */
	public static String doFileParamPost(String url,LinkedList<String> list,Map<String,String> paramMap) {
		//创建HttpClient客户端对象
		CloseableHttpClient httpClient = HttpClients.createDefault();		
		//创建Post请求实例
		HttpPost httpPost = new HttpPost(url);
		//响应模型
		CloseableHttpResponse response = null;
		//响应内容
		String responseContent = null;
		try {
			//创建MultipartEntityBuilder对象
			MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
			String filesKey = "files";
			//添加文件
			for(int i = 0;i < list.size();i++) {
			    //防止服务端收到的文件名乱码。 我们这里可以先将文件名URLEncode,然后服务端拿到文件名时在URLDecode。就能避免乱码问题。
		        //文件名其实是放在请求头的Content-Disposition里面进行传输的,如其值为form-data; name="files"; filename="头像.jpg
				multipartEntityBuilder.addBinaryBody(filesKey, new File(list.get(i)),ContentType.DEFAULT_BINARY, URLEncoder.encode(new File(list.get(i)).getName(), "utf-8"));
			}
			//其它参数(注:自定义contentType,设置UTF-8是为了防止服务端拿到的参数出现乱码)
			ContentType contentType = ContentType.create("text/plain", Charset.forName("UTF-8"));
			//装填参数
			Set<Entry<String,String>> set = paramMap.entrySet();
			for(Entry<String, String> entry:set) {
				multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue(), contentType);
			}
			HttpEntity build = multipartEntityBuilder.build();
			//将参数放在请求体
			httpPost.setEntity(build);
			//客户端执行发送Post请求
			response = httpClient.execute(httpPost);
			// 从响应模型中获取响应实体
			HttpEntity httpEntity = response.getEntity();
			System.out.println("响应状态为:" + response.getStatusLine());
			if (httpEntity != null) {
				//主动设置响应编码,防止乱码
				responseContent =  EntityUtils.toString(httpEntity,StandardCharsets.UTF_8);
				System.out.println("响应内容长度为:" + httpEntity.getContentLength());
				System.out.println("响应内容为:" +responseContent);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

HelloController:

/**
	 * Post普通参数和文件作为参数请求测试
	 * @param request
	 * @return
	 */
	@RequestMapping("/doFileParamPost")
	public String doFileParamPost() {
		String url = "http://localhost:8080/doFileParamPostWorld";
		Map<String,String> map = new HashMap<String,String>();
		map.put("name", "阿美");
		LinkedList<String> list = new LinkedList<String>();
		list.add("D:\\serverFile\\img\\46-389349.jpg");
		list.add("D:\\serverFile\\img\\4ef0c75785b434523c029d0890c1ac93.jpg");
		return HttpClientsUtil.doFileParamPost(url,list,map);
	}

WorldController:

/**
	 * Post文件和普通参数作为参数请求测试
	   * 多文件可以使用数组MultipartFile[]或集合List<MultipartFile>来接收
	   * 单文件可以直接使用MultipartFile来接收
	   * 注意:这里只是测试了httpClient的上传功能,服务端的接收没有做出处理
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/doFileParamPostWorld",method = RequestMethod.POST)
	public String doFileParamPostWorld(
			@RequestParam("name") String name,
			@RequestParam("files") List<MultipartFile> multipartFiles) {
		
		System.err.println("Post文件请求测试:"+name);
		//遍历文件打印文件信息
		for(MultipartFile mf:multipartFiles) {
			String FileName = mf.getOriginalFilename();
			if(FileName != null) {
				try {
					//防止中文乱码
					//在传文件时将文件名URLEncode,然后在这里获取文件名时URLDecode避免中文乱码
					URLDecoder.decode(FileName, "UTF-8");
					System.out.println("文件名:"+FileName);
					System.out.println("文件大小:"+mf.getSize()*1.0/1024+"KB");
					System.out.println("ContentType:"+mf.getContentType());
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return name;
	}

控制台打印结果:

Post文件请求测试:阿美
文件名:46-389349.jpg
文件大小:507.6357421875KB
ContentType:application/octet-stream
文件名:4ef0c75785b434523c029d0890c1ac93.jpg
文件大小:430.494140625KB
ContentType:application/octet-stream
响应状态为:HTTP/1.1 200 
响应内容长度为:6
响应内容为:阿美

 

参考链接:https://blog.csdn.net/justry_deng/article/details/81042379

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值