Je ne sais pas ce que j'ai fait, alors j'écrirai ce que j'ai changé.
** Prend en charge les changements d'interface majeurs de Java apache HttpClient 4.3 (@mychaelstyle) ** https://qiita.com/mychaelstyle/items/e02b3011d1e71bfa26c5 ** Demande avec authentification BASIC (@sh_kawakami) au site HTTPS avec CloseableHttpClient d'Apache httpclient ** https://qiita.com/sh_kawakami/items/bf6d1397851cccd134b2 ** Il semble que l'interface de httpclient a considérablement changé depuis la version 4.3 (@sakito) ** https://qiita.com/sakito/items/6366015dbbc4a88d56fc What does setDefaultMaxPerRoute and setMaxTotal mean in HttpClient? Colonne de réponse de https://stackoverflow.com/questions/30689995/what-does-setdefaultmaxperroute-and-setmaxtotal-mean-in-httpclient
JDK 1.8.162 httpclient 4.5.4
pom.xml
pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
J'ai regardé autour de moi comme si je n'avais jamais été aidé par la liste obsolète
―― Série 3.x https://hc.apache.org/httpclient-3.x/apidocs/deprecated-list.html ―― Série 4.x http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/deprecated-list.html
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/index.html
Puisqu'il s'agit d'un guide pour passer de 3.x à 4.0, il peut changer à nouveau lorsqu'il atteint 4,5. http://debuguide.blogspot.jp/2013/01/quick-guide-for-migration-of-commons.html
―― Série 3.x https://hc.apache.org/httpclient-3.x/apidocs/constant-values.html ―― Série 4.x http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/constant-values.html
before.java
HttpClient client = new HttpClient();
Utilisons Builder! Il paraît que. Si vous n'avez à penser à rien, ci-dessous.
after.java
HttpClient client = HttpClients.createDefault();
Cependant, cela peut ne pas être très pratique car vous devez passer les paramètres de connexion au moment de la génération.
GetMethod→HttpGet PostMethod→HttpPost Classe parent HttpMethod → HttpRequestBase Changer pour
C'était comme ça avant
before.java
PostMethod post = new PostMethod(url);
post.setRequestEntity(Définir quelque chose);
int responseCode = client.executeMethod(post);
if (responseCode == 200) {
Reader reader = new InputStreamReader(
httpMethod.getResponseBodyAsStream(), httpMethod.getResponseCharSet());
//Traitement ultérieur
} else {
//La gestion des erreurs
}
Ça a beaucoup changé et ça ressemble à ça. Mais maintenant que c'est clair, cela peut être plus facile à comprendre.
after.java
HttpPost post = new HttpPost(url);
//Définissez celui qui correspond au corps de la requête
post.setEntity(Définir quelque chose);
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
int responseCode = statusLine.getStatusCode();
if (responseCode == HttpStatus.SC_OK) {
Reader reader = new InputStreamReader(
response.getEntity().getContent(), Charset.forName("UTF-8"));
//Traitement ultérieur
} else {
//La gestion des erreurs
}
J'avais l'habitude de le faire comme ça.
before.java
Credentials credentials = new UsernamePasswordCredentials(this.username, this.password);
AuthScope scope = new AuthScope(host, port, this.realm);
client.getState().setCredentials(scope, credentials);
Il semble que vous devriez utiliser CredentialsProvider. (Merci à @sh_kawakami!)
after.java
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(baseUrl.getHost(),baseUrl.getPort()),
new UsernamePasswordCredentials(username, password));
//Je le définirai lors de la création d'une instance
HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build();
Il semble que la classe d'entité soit maintenant BasicNameValuePair. Il semble qu'il soit simplement divisé par "=", donc je prie pour que le comportement ne change pas comme avant. Mais le passeur est parti! !! !! Comme je l'ai vu, il semble qu'il ne puisse être défini qu'avec le constructeur. Si vous souhaitez toujours utiliser setter, vous devez hériter de NameValuePair et créer votre propre classe.
Ajoutons-le nous-mêmes
//en-tête d'hôte
httpMethod.addHeader("Host", uri.getHost());
Se produit lorsque la taille de la réponse est différente de celle du Body s'il existe un en-tête Content-Length. Cela ne se produit pas sans l'en-tête Content-Length (bien que cela ressemble à une violation RFC) Par exemple, cela se produit lorsque la réponse est comme ça. Eh bien, aujourd'hui, je pense que Content-Length est automatiquement calculé et renvoyé par le serveur sans autorisation, donc je pense que cela ne se produira probablement pas, mais pour diverses raisons, je ne fais pas confiance à l'en-tête de la réponse, donc: suer:
HTTP/1.1 200 OK
Content-Type: text/html; charset=Shift_JIS
Content-Length: 3000
<html>
<head><title>Hoge</title>
</head>
<body>test
</body>
</html>
org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 3000; received: 124
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:178)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:148)
La cause est ici
java:org.apache.http.impl.io.ContentLengthInputStream.java
/**
* Does standard {@link InputStream#read(byte[], int, int)} behavior, but
* also notifies the watcher when the contents have been consumed.
*
* @param b The byte array to fill.
* @param off Start filling at this position.
* @param len The number of bytes to attempt to read.
* @return The number of bytes read, or -1 if the end of content has been
* reached.
*
* @throws java.io.IOException Should an error occur on the wrapped stream.
*/
@Override
public int read (final byte[] b, final int off, final int len) throws java.io.IOException {
if (closed) {
throw new IOException("Attempted read from closed stream.");
}
if (pos >= contentLength) {
return -1;
}
int chunk = len;
if (pos + len > contentLength) {
chunk = (int) (contentLength - pos);
}
final int count = this.in.read(b, off, chunk);
if (count == -1 && pos < contentLength) {
throw new ConnectionClosedException(
"Premature end of Content-Length delimited message body (expected: "
+ contentLength + "; received: " + pos);
}
if (count > 0) {
pos += count;
}
return count;
}
Je n'ai pas encore trouvé de solution.
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <hostname> doesn't match any of the subject alternative names:
Il semble que le nom d'hôte soit vérifié par défaut. La partie pertinente est ici
java:org.apache.http.conn.ssl.SSLConnectionSocketFactory.java#verifyHostname
if (!this.hostnameVerifier.verify(hostname, session)) {
final Certificate[] certs = session.getPeerCertificates();
final X509Certificate x509 = (X509Certificate) certs[0];
final List<SubjectName> subjectAlts = DefaultHostnameVerifier.getSubjectAltNames(x509);
throw new SSLPeerUnverifiedException("Certificate for <" + hostname + "> doesn't match any " +
"of the subject alternative names: " + subjectAlts);
}
Étant donné que vérifier ne doit renvoyer que true, il semble qu'une instance de la classe NoopHostnameVerifier devrait être utilisée. Désactiver la vérification du certificat SSL et la vérification du nom d'hôte dans Apache HttpComponents / Client Chapter 2. Connection management 2.7.4. Hostname verification Dans mon cas, je ne configure pas SSLContext ou SSLConnectionSocketFactory directement dans httpclient, mais je l'implémente en le définissant dans ConnectionManager. À ce point. Cela ressemble donc à ce qui suit.
public static PoolingHttpClientConnectionManager createConnectionManager() {
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}
).build();
} catch (Exception e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslsf)
.build();
return new PoolingHttpClientConnectionManager(registry);
}
DefaultHttpRequestRetryHandler d'Apache HttpClient ne réessaye pas sur ConnectTimeoutException http://kntmr.hatenablog.com/entry/2016/12/09/150615 Use of non-ascii credentials not working in httpclient 4.3.x https://stackoverflow.com/questions/27955067/use-of-non-ascii-credentials-not-working-in-httpclient-4-3-x
Recommended Posts