一周的忙碌过后又到了愉快的周末,又开始了作为小白的成长之旅。
作为一个资深的中转部门,什么最重要呢,当然是curl了,调用其他地方的接口,获取数据,然后进行处理。
所以今天的目标就是实现curl了!
在pom.xml将加入下面内容
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.51</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> 复制代码
配置properties文件
#最大连接数 http.maxTotal = 100 #并发数 http.defaultMaxPerRoute = 20 #创建连接的最长时间 http.connectTimeout=1000 #从连接池中获取到连接的最长时间 http.connectionRequestTimeout=500 #数据传输的最长时间 http.socketTimeout=10000 http.validateAfterInactivity=1000 复制代码
新增HttpClientConfiguration.java
package com.example.demo.controller; import org.apache.http.client.config.RequestConfig; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HttpClientConfiguration { @Value("${http.maxTotal}") private Integer maxTotal; @Value("${http.defaultMaxPerRoute}") private Integer defaultMaxPerRoute; @Value("${http.connectTimeout}") private Integer connectTimeout; @Value("${http.connectionRequestTimeout}") private Integer connectionRequestTimeout; @Value("${http.socketTimeout}") private Integer socketTimeout; @Value("${http.validateAfterInactivity}") private Integer validateAfterInactivity; @Bean public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager(){ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(maxTotal); connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); connectionManager.setValidateAfterInactivity(validateAfterInactivity); return connectionManager; } @Bean public HttpClientBuilder httpClientBuilder(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager){ HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); return httpClientBuilder; } @Bean public CloseableHttpClient closeableHttpClient(HttpClientBuilder httpClientBuilder){ return httpClientBuilder.build(); } @Bean public RequestConfig.Builder builder(){ RequestConfig.Builder builder = RequestConfig.custom(); return builder.setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout) .setSocketTimeout(socketTimeout); } @Bean public RequestConfig requestConfig(RequestConfig.Builder builder){ return builder.build(); } } 复制代码
新增HttpClient.java
package com.example.demo.controller; import com.alibaba.fastjson.JSONObject; import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; 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.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Map; @Component public class HttpClient { public static final String DEFAULT_CHARSET = "UTF-8"; @Autowired private CloseableHttpClient closeableHttpClient; @Autowired private RequestConfig config; /** * 用于JSON格式的API调用 * * @param url url地址 * @param requestParameter 请求参数 * @param clazz 接口返回值的类型 * @return * @throws Exception */ public <T> T doGet(String url, Map<String, Object> requestParameter, Class<T> clazz) throws Exception { String responseJson = this.doGet(url, requestParameter); T response = JSONObject.parseObject(responseJson, clazz); return response; } public String doGet(String url, Map<String, Object> requestParameter) throws Exception { URIBuilder uriBuilder = new URIBuilder(url); if (requestParameter != null) { for (Map.Entry<String, Object> entry : requestParameter.entrySet()) { uriBuilder.setParameter(entry.getKey(), entry.getValue().toString()); } } return this.doGet(uriBuilder.build().toString()); } public String doGet(String url) throws Exception { HttpGet httpGet = new HttpGet(url); httpGet.setConfig(config); httpGet.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); CloseableHttpResponse response = this.closeableHttpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { throw new Exception("api request exception, http reponse code:" + statusCode); } return EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET); } public <T> T doPost(String url, Map<String, Object> requestParameter, Class<T> clazz) throws Exception { HttpResponse httpResponse = this.doPost(url, requestParameter); int statusCode = httpResponse.getCode(); if (statusCode != HttpStatus.SC_OK) { throw new Exception("api request exception, http reponse code:" + statusCode); } T response = JSONObject.parseObject(httpResponse.getBody(), clazz); return response; } public HttpResponse doPost(String url, Map<String, Object> requestParameter) throws Exception { HttpPost httpPost = new HttpPost(url); httpPost.setConfig(config); httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); if (requestParameter != null) { String requestBody = JSONObject.toJSONString(requestParameter); StringEntity postEntity = new StringEntity(requestBody, "UTF-8"); httpPost.setEntity(postEntity); } CloseableHttpResponse response = this.closeableHttpClient.execute(httpPost); // 对请求的响应进行简单的包装成自定义的类型 return new HttpResponse(response.getStatusLine().getStatusCode(), EntityUtils.toString( response.getEntity(), DEFAULT_CHARSET)); } public HttpResponse doPost(String url) throws Exception { return this.doPost(url, null); } /** * 封住请求的响应码和响应的内容 */ public class HttpResponse { /** * http status */ private Integer code; /** * http response content */ private String body; public HttpResponse() { } public HttpResponse(Integer code, String body) { this.code = code; this.body = body; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } } } 复制代码
CurlController.java 里面实现两个接口,一个是get方式的,一个是post方式的。
package com.example.demo.controller; import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController public class CurlController { @Autowired private HttpClient httpClient; @RequestMapping("/curlBaidu") public String curlBaidu() throws Exception { return httpClient.doGet("http://www.baidu.com"); } @RequestMapping("/curlLocation") public String curlLocation() throws Exception { Map<String, Object> name = new HashMap<>(); name.put("name", "caohaoyu"); name.put("name2", "chy"); HttpClient.HttpResponse httpResult = httpClient.doPost("http://localhost:8080/helloByParam", name); String body = httpResult.getBody(); JSONObject jsonObject = JSONObject.parseObject(body); return jsonObject.getString("data"); } } 复制代码
在原有的HelloController.java修改helloByParam接口,接收post传输过来的数据并直接返回。
@RequestMapping("/helloByParam") public String helloByParam(@RequestBody JSONObject jsonObject) { JSONObject result = new JSONObject(); result.put("msg", "ok"); result.put("code", "0"); result.put("data", jsonObject); return result.toJSONString(); } 复制代码
get实现结果:
post实现结果:
圆满完成简单版curl的实现!
java是强类型的,这点对于写惯了php这种弱类型的人来说一开始确实还是有点别扭的。不过编辑器还是挺好用的,以后慢慢适应吧。
还有就是java对调用方式也比较严格,需要注意。不能像php简单的 $_REQUEST
来同时支持post和get。