HttpRequester 类有构造方法,通过构造方法,加载http请求的参数。
public HttpRequester(int connectionRequestTimeout, int connectionTimeout, int socketTimeout, String defaultCharset, String proxyServer,HttpClientContext httpClientContext) {
super();
init(connectionRequestTimeout, connectionTimeout, socketTimeout, defaultCharset, proxyServer,httpClientContext);
}
private void init(
int connectionRequestTimeout ,int connectionTimeout ,int socketTimeout
, String defaultCharset ,String proxyServer , HttpClientContext httpClientContext
){
this.httpClient = HttpClients.createDefault();
Builder requestBuilder = RequestConfig.custom();
requestBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
requestBuilder.setConnectTimeout(connectionTimeout);
requestBuilder.setSocketTimeout(socketTimeout);
if (StringUtils.isNotBlank(proxyServer)) {
requestBuilder.setProxy(HttpHost.create(proxyServer));
}
this.requestConfig = requestBuilder.build();
this.responseHandler = new DefaultResponseHandler(Charset.forName(defaultCharset));
this.httpClientContext = httpClientContext;
}
其中,需要有验证用户账号密码的代码,JAVA代码如下:
UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials("XXX", "123456");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST,AuthScope.ANY_PORT),usernamePasswordCredentials);
HttpClientContext httpClientContext = HttpClientContext.create();
httpClientContext.setCredentialsProvider(credentialsProvider);
以上JAVA代码,用spring配置bean方式实现。
此时,spring 配置构造方法为:
<bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
<constructor-arg type="String" value="UTF-8" />
<constructor-arg type="String"><null/></constructor-arg>
<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
<!-- 待完善 -->
</constructor-arg>
</bean>
注:
- type为String时,可以省略不写。
- 配置参数数量要与构造函数的参数数量保持一致(构造函数有多个,不同数量对应不同构造函数,因此可以写多个配置,通过id来区分不同的配置的JAVA类)。
- <null/>表示为空值。
- Spring通过构造方法注入的四种方式
-
第一种方法:根据索引赋值,索引都是以0开头的:
<constructor-arg index="0" value="3500" />
-
第二种方法:根据所属类型传值(根据顺序排的)
<constructor-arg type="java.lang.Double" value="3500" />
-
第三种方法:根据参数的名字传值
<constructor-arg name="salary" value="3500" />
-
第四种方法:直接传值(根据顺序排的)
<constructor-arg value="3500" />
-
继续:
查看类HttpClientContext,有工厂方法create,创建HttpClientContext对象
public static HttpClientContext adapt(final HttpContext context) {
if (context instanceof HttpClientContext) {
return (HttpClientContext) context;
} else {
return new HttpClientContext(context);
}
}
public static HttpClientContext create() {
return new HttpClientContext(new BasicHttpContext());
}
public HttpClientContext(final HttpContext context) {
super(context);
}
public HttpClientContext() {
super();
}
然后配置更新如下:
<bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
<constructor-arg type="String" value="UTF-8" />
<constructor-arg type="String"><null/></constructor-arg>
<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
<!-- 待完善 -->
</bean>
</constructor-arg>
</bean>
继续,查看JAVA代码如下:
HttpClientContext httpClientContext = HttpClientContext.create();
httpClientContext.setCredentialsProvider(credentialsProvider);
需要有credentialsProvider参数,该参数在HttpClientContext里面可以通过get set获取,代码如下:
public CredentialsProvider getCredentialsProvider() {
return getAttribute(CREDS_PROVIDER, CredentialsProvider.class);
}
public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
setAttribute(CREDS_PROVIDER, credentialsProvider);
}
然后配置更新如下:
<bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
<constructor-arg type="String" value="UTF-8" />
<constructor-arg type="String"><null/></constructor-arg>
<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
<property name="credentialsProvider">
<!-- 待完善 -->
</property>
</bean>
</constructor-arg>
</bean>
继续,查看JAVA代码如下:
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
继续,查看BasicCredentialsProvider如下:
public class BasicCredentialsProvider implements CredentialsProvider {
private final ConcurrentHashMap<AuthScope, Credentials> credMap;
public BasicCredentialsProvider() {
super();
this.credMap = new ConcurrentHashMap<AuthScope, Credentials>();
}
@Override
public void setCredentials(
final AuthScope authscope,
final Credentials credentials) {
Args.notNull(authscope, "Authentication scope");
credMap.put(authscope, credentials);
}
private static Credentials matchCredentials(
final Map<AuthScope, Credentials> map,
final AuthScope authscope) {
// see if we get a direct hit
Credentials creds = map.get(authscope);
if (creds == null) {
// Nope.
// Do a full scan
int bestMatchFactor = -1;
AuthScope bestMatch = null;
for (final AuthScope current: map.keySet()) {
final int factor = authscope.match(current);
if (factor > bestMatchFactor) {
bestMatchFactor = factor;
bestMatch = current;
}
}
if (bestMatch != null) {
creds = map.get(bestMatch);
}
}
return creds;
}
@Override
public Credentials getCredentials(final AuthScope authscope) {
Args.notNull(authscope, "Authentication scope");
return matchCredentials(this.credMap, authscope);
}
发现无法通过get set或者构造方式等方式加载credentialsProvider。
因此,新建JAVA类,代码如下(可以通过工厂方式注入该bean):
public class CredentialsProviders {
public final static CredentialsProvider createUsernamePasswordCredentialsProvider(String username, String password,String authScopeHost,int authScopePort) {
UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(username, password);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
if(StringUtils.isBlank(authScopeHost)){
authScopeHost = AuthScope.ANY_HOST;
}
if(authScopePort < 0){
authScopePort = AuthScope.ANY_PORT;
}
credentialsProvider.setCredentials(new AuthScope(authScopeHost,authScopePort),
usernamePasswordCredentials);
return credentialsProvider;
}
public final static CredentialsProvider createUsernamePasswordCredentialsProvider(String username, String password) {
return createUsernamePasswordCredentialsProvider(username, password,AuthScope.ANY_HOST,AuthScope.ANY_PORT);
}
}
然后配置更新如下:
<bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
<constructor-arg type="String" value="UTF-8" />
<constructor-arg type="String"><null/></constructor-arg>
<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
<property name="credentialsProvider">
<bean class="com.champion.common.util.http.CredentialsProviders"
factory-method="createUsernamePasswordCredentialsProvider">
<constructor-arg value="${svn.username}" />
<constructor-arg value="${svn.password}" />
</bean>
</property>
</bean>
</constructor-arg>
</bean>
自此,通过spring配置实现用户账号密码验证http请求的功能已经实现。