基于springboot的httpclient封装

发布时间:2019-03-13
技术:springboot2.0 + httpclient4.5.5 + maven3.0.1

概述

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。而HttpClient是可以支持http相关协议的工具包,它有如下功能: 1.实现了所有的http方法(GET,POST,PUT,HEAD 等) 2.支持自动转向 3.支持 HTTPS 协议 4.支持代理服务器等

详细

一、使用场景

目前C/S还是B/S结构的应用程序, HTTP 应该是最为广泛使用的协议了。在 Java 平台上,Java 标准库提供了 一个HttpURLConnection 类来支持 HTTP 通讯。不过 HttpURLConnection 本身的 API 不够友好,所提供的功能也有限。httpClien是一个实现http协议很多操作功能的组件,并且它支持 HTTP 协议最新的版本和建议,现在Android已经成功的集成了HttpClient。另外,最新由Square 公司开源的 OkHttp 据说能提供更高效率的http连接,支持GZIP 压缩和 HTTP 响应缓存功能,在原理上应该是大同小异的。

二、httpclient的使用步骤


利用httpclient去访问接口的步骤一般是:

1. 创建HttpClient对象。2. 构造Http 请求对象。3. 执行HttpClient对象的execute方法,将Http请求对象作为该方法的参数。4. 读取execute方法返回的HttpResponse结果并解析。5、释放连接。整个过程是不是与我们平时在浏览器上访问类似呢。唯一区别是不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。在以上代码中,httpclient的初始化没有看到任何参数设置,其实是在它的构造函数里调用了接口,并设置了默认值,如下包含协议版本、客户端引擎、cookie策略等,如果要自己设置,可以通过它的成员变量httpClientParams对象进行设置。


1、关于重定向。

 http多种状态已经在HttpStatus这个类中定义好,其中重定向 根据RFC2616中对自动转向的定义,主要有两种:301和302。301表示永久的移走(Moved Permanently),当返回的是301,则表示请求的资源已经被移到一个固定的新地方,任何向该地址发起请求都会被转到新的地址上。302表示暂时的转向,比如在服务器端的servlet程序调用了sendRedirect方法,则在客户端就会得到一个302的代码,这时服务器返回的头信息中location的值就是sendRedirect转向的目标地址。如果是get方式请求,httpclient是自动帮你重定向并拿到响应信息,也可以通过设置method.setFollowRedirects(false)不自动转。post的请求是不能自动跳转的,需要从头部信息中拿到Location(可能是相对路径)因此需要对location返回的值做一些处理才可以发起向新地址的请求。

2、字符编码

客户端发送的数据多样,最终所有数据都是通过最底层的物理层面的电信号来传递,首部字段content-type 说明了实体主体内对象的媒体类型,即服务器通过contentType来知道这个是什么样子的数据。客户端在拿到服务器返回的数据后,根据头部设置的可接收媒体类型进行内容协商,返回最适合的资源。对于有中文的请求,为避免出现乱码,最好设置content-type。在上部分的代码截图,大家可以看到,如果我们自己不设置contentType 那么默认会采用ISO的方式进行传输,那么如果与你实际的编码方式不一致的话,服务器就会拿到一个乱码,从而无法正常的响应。可以通过上面代码进行设置,也可以通过method.setRequestHeader("Content-Type", " application/json; charset=UTF-8")来进行设置

 

3、cookie

httpclient默认的cookie策略是RFC_2109其中可以通过去更改。请求过程中可以通过sendHead 把cookie放入头部,并传到后端进行访问。

 

三、代码实现


  1. 在pom文件引入httpclient相关的jar包

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.8</version>
		</dependency>
			
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpasyncclient</artifactId>
		</dependency>
		<!-- <dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpasyncclient</artifactId>
			<version>4.1</version>
		</dependency> -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>


 2.创建httpclient模拟请求接口

/**
	 * 模拟请求
	 * 
	 * @param url		资源地址
	 * @param paraMap	参数列表
	 * @param encoding	编码
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws KeyManagementException 
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 */
	public static String send(String url, Map<String,String> paraMap,String encoding) throws KeyManagementException, NoSuchAlgorithmException, ClientProtocolException, IOException {
		String body = "";

		SSLContext sslcontext = createIgnoreVerifySSL();
		
        // 设置协议http和https对应的处理socket链接工厂的对象
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(sslcontext))
            .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

        //创建自定义的httpclient对象
		CloseableHttpClient client = HttpClients.createDefault();
		
		//创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);
		
		//装填参数
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		if(paraMap!=null){
			for (Entry<String, String> entry : paraMap.entrySet()) {
				nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		//设置参数到请求对象中
		httpPost.setEntity(new UrlEncodedFormEntity(nvps, encoding));

		System.out.println("请求地址:"+url);
		System.out.println("请求参数:"+nvps.toString());
		
		//设置header信息
		//指定报文头【Content-type】、【User-Agent】
		httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
		httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
		
		//执行请求操作,并拿到结果(同步阻塞)
		CloseableHttpResponse response = client.execute(httpPost);
		//获取结果实体
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			//按指定编码转换结果实体为String类型
			body = EntityUtils.toString(entity, encoding);
		}
		EntityUtils.consume(entity);
		//释放链接
		response.close();
        return body;
	}


3.模拟请求接口

	@Test
	public void testPost() throws KeyManagementException, NoSuchAlgorithmException, ClientProtocolException, IOException {
		
		
		String testUrl = "http://localhost:8080/test";
		
		Map<String, String> paraMap = new HashMap();
		paraMap.put("name", "lilei");
		paraMap.put("age", "8");

		String body = HttpClientUtil.send(testUrl, paraMap, "utf-8");
		System.out.println("请求响应结果:");
		System.out.println(body);
		System.out.println("-----------------------------------");
	}


四、代码演示

image.png


image.png


五、代码结构

image.png


六、小结

基本上使用httpclient过程中,主要操作的类有:httpclient,getMethod,postMethod,httpClientParams,httpConnectionManager这几个。详见以下的类图。

 HttpClient代表了一个http的客户端,HttpConnectionManager是用来管理HttpConnection 的,HttpConnection代表了一个http连接,所以HttpConnectionManager其实质上也就是一个http连接池,管理这些 http连接(和数据库连接池一个道理)。HttpMethod代表了一个Http方法,一个HttpClient可以运行多个HttpMethod(实 质上,httpclient执行一个HttpMethod时,会从connectionmanager那里获取一个httpconnection,在此 connection上执行该method,执行完该method后,让method 释放该httpconnection,从而将该httpconnection返回给connectionmanager,以便供后续的method使 用)所以在httpclient连接后资源释放问题很重要,就跟我们用database connection要释放资源一样。


本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
手机上随时阅读、收藏该文章 ?请扫下方二维码