| 知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.netkiller</groupId> <artifactId>example</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> </dependencies> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
package cn.netkiller.httpclient;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.bind.DatatypeConverter;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class HttpClientPost {
public static void main(String[] args) throws ClientProtocolException, IOException, NoSuchAlgorithmException {
// TODO Auto-generated method stub
String url = "http://api.netkiller.cn:8080/api/comment/list.jspx";
String appId = "3175755150424665";
String appKey = "yEjnjoSEOQpOP49od1IexLkyVB4HTi9c";
String contentId = "1103";
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = dateFormat.format(new Date());
String token = DatatypeConverter.printHexBinary(MessageDigest.getInstance("MD5").digest(String.format("%s&%s", appKey, date).getBytes("UTF-8"))).toLowerCase();
CloseableHttpClient httpclient = HttpClients.createDefault();
// appId=3175755150424665&contentId=1103&pageSize=100&timeStamp=2017-08-03
// 10:20:00&token=e1180c0306aff7792c3e25699900dd0d
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("appId", appId));
params.add(new BasicNameValuePair("contentId", contentId));
params.add(new BasicNameValuePair("pageSize", "10"));
params.add(new BasicNameValuePair("timeStamp", date));
params.add(new BasicNameValuePair("token", token));
System.out.println(params.toString());
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, Consts.UTF_8);
System.out.println(urlEncodedFormEntity.toString());
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(urlEncodedFormEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseBody.toString());
response.close();
}
}
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
@SuppressWarnings("deprecation")
public class HTTPREST {
public static void main(String[] args) throws ClientProtocolException, IOException {
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost request = new HttpPost("http://test:123456@api.netkiller.cn/v1/test/create.json");
StringEntity params = new StringEntity("{\"name\":\"neo\", \"nickname\":\"netkiller\"}", "UTF-8");
request.addHeader("content-type", "application/json");
request.addHeader("Accept", "application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
if (response != null) {
String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(responseBody.toString());
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
httpClient.getConnectionManager().shutdown();
}
}
}
有些國內短信運營商發送短信的介面只能接收 GBK 編碼,下面就是一個POST GBK編碼數據的範例。
package api.test.sms;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class SMS {
public SMS() {
// TODO Auto-generated constructor stub
}
public void sendSMS(String mobile, String message) throws ClientProtocolException, IOException {
String url = "http://api.netkiller.cn/sms/v2/send";
SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
String timestamp = sdf.format(Calendar.getInstance().getTime());
CloseableHttpClient httpclient = HttpClients.createDefault();
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("apikey", "2863300994052170feb"));
params.add(new BasicNameValuePair("mobile", mobile));
params.add(new BasicNameValuePair("content", message));
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, "GBK");
System.out.println(urlEncodedFormEntity.toString());
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(urlEncodedFormEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
System.out.println(params.toString());
System.out.println(response.getStatusLine());
System.out.println(responseBody.toString());
response.close();
}
public static void main(String[] args) throws ClientProtocolException, IOException {
// TODO Auto-generated method stub
SMS sms = new SMS();
String message = String.format("您的驗證碼是%s,在%s分鐘內輸入有效。如非本人操作請忽略此短信。", 8888, 10);
sms.sendSMS("13113668800", message);
}
}
環境 Nginx SSL(openssl自頒發),nginx 通過proxy_pass連接 Tomcat
下面是 nginx 配置
server {
listen 443 ssl spdy;
server_name api.netkiller.cn;
ssl_certificate /etc/nginx/ssl/api.netkiller.cn.crt;
ssl_certificate_key /etc/nginx/ssl/api.netkiller.cn.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 60m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
charset utf-8;
access_log /var/log/nginx/api.netkiller.cn.access.log;
error_log /var/log/nginx/api.netkiller.cn.error.log;
location / {
proxy_pass http://127.0.0.1:7000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
}
}
下面是 Java 程序
package cn.netkiller.example;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
public class NginxAndOpenSSLAndTomcatAndHttpclient {
public static void main(String[] args) throws ParseException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(builder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslFactory).build();
HttpGet httpGet = new HttpGet("https://neo:netkiller@api.netkiller.cn/v1/news/today.json");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseBody.toString());
} finally {
response.close();
}
}
}
如果遇到配置問題,可以看一下 《Netkiller Linux Web 手札》
package cn.netkiller.example;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
public class HttpClientSSLPost {
public HttpClientSSLPost() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(builder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslFactory).build();
HttpPost httpPost = new HttpPost("https://neo:YruuUCNXKe@api.netkiller.cn/v1/member/create.json");
httpPost.addHeader("content-type", "application/json");
httpPost.addHeader("Accept", "application/json");
HttpEntity httpEntity = new StringEntity("{\"name\":\"neo\", \"nickname\":\"netkiler\",\"age\":\"18\"}", "UTF-8");
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseBody.toString());
response.close();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
}
}
}
HTTP/2實例
@Test
public void testHttp2() throws URISyntaxException, IOException, InterruptedException {
HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.SECURE)
.version(HttpClient.Version.HTTP_2)
.build()
.sendAsync(HttpRequest.newBuilder()
.uri(new URI("https://http2.akamai.com/demo"))
.GET()
.build(),
HttpResponse.BodyHandler.asString())
.whenComplete((resp,t) -> {
if(t != null){
t.printStackTrace();
}else{
System.out.println(resp.body());
System.out.println(resp.statusCode());
}
}).join();
}
/**
* --add-modules jdk.incubator.httpclient
* @throws IOException
* @throws InterruptedException
* @throws URISyntaxException
*/
@Test
public void testGet() throws IOException, InterruptedException, URISyntaxException {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(new URI("https://www.baidu.com"))
.header("User-Agent", "jdk 9 http client")
.GET()
.build();
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandler.asString());
System.out.println(httpResponse.statusCode());
System.out.println(httpResponse.body());
}
@Test
public void testAsyncGet() throws URISyntaxException, InterruptedException, ExecutionException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://www.baidu.com"))
.GET()
.build();
CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, HttpResponse.BodyHandler.asString());
response.whenComplete((resp,t) -> {
if(t != null){
t.printStackTrace();
}else{
System.out.println(resp.body());
System.out.println(resp.statusCode());
}
}).join();
}
post form
@Test
public void testPostForm() throws URISyntaxException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("http://www.w3school.com.cn/demo/demo_form.asp"))
.header("Content-Type","application/x-www-form-urlencoded")
.POST(HttpRequest.BodyProcessor.fromString("name1=value1&name2=value2"))
.build();
client.sendAsync(request, HttpResponse.BodyHandler.asString())
.whenComplete((resp,t) -> {
if(t != null){
t.printStackTrace();
}else{
System.out.println(resp.body());
System.out.println(resp.statusCode());
}
}).join();
}
這個問題是CN不匹配造成的,日誌如下
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'api.netkiller.cn' does not match the certificate subject provided by the peer (EMAILADDRESS=netkiller@msn.com, CN=netkiller.cn, OU=CF, O=CF, L=Shenzhen, ST=Guangdong, C=CN)
解決方案一:重新做證書
Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:Guangdong Locality Name (eg, city) [Default City]:Shenzhen Organization Name (eg, company) [Default Company Ltd]:CF Organizational Unit Name (eg, section) []:CF Common Name (eg, your name or your server's hostname) []:api.netkiller.cn Email Address []:netkiller@msn.com
解決方案二:是用CN上的域名連結
package cn.netkiller.consul.controller;
import org.apache.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
public TestController() {
// TODO Auto-generated constructor stub
}
@RequestMapping("/health")
public int health() {
return HttpStatus.SC_OK;
}
}