(三)ClosableHttpClient标准处理流程

三.ClosableHttpClient标准处理流程

有关认证

https://blog.csdn.net/rioalian/article/details/77100633

代码
import org.apache.http.auth.AuthScope
import org.apache.http.auth.UsernamePasswordCredentials
import org.apache.http.client.CredentialsProvider
import org.apache.http.client.config.RequestConfig
import org.apache.http.conn.ssl.DefaultHostnameVerifier
import org.apache.http.conn.ssl.NoopHostnameVerifier
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.conn.ssl.TrustAllStrategy
import org.apache.http.impl.client.BasicCredentialsProvider
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.ssl.SSLContexts
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.io.Resource
import java.security.KeyStore
import javax.net.ssl.SSLContext

	@Configuration
	@ConditionalOnProperty("httpclient.timeout")
	@EnableConfigurationProperties(HttpClientProperties::class)
	class HttpClientConfig(private val properties: HttpClientProperties) {
	
	    @Bean(destroyMethod = "close")
	    fun httpClient(sslContext: SSLContext?,
	                   credentialsProvider: CredentialsProvider?): CloseableHttpClient {
	        val timeout = properties.timeout * 1000
	        val config = RequestConfig.custom()
	                .setConnectTimeout(timeout)
	                .setConnectionRequestTimeout(timeout)
	                .setSocketTimeout(timeout)
	                .build()
	
	        return HttpClientBuilder.create()
	                .setSSLSocketFactory(SSLConnectionSocketFactory(
	                        sslContext ?: SSLContext.getDefault(),
	                        properties.supportedProtocols,
	                        null,
	                        if (properties.verifyHost) DefaultHostnameVerifier() else NoopHostnameVerifier()
	                ))
	                .setDefaultCredentialsProvider(
	                        credentialsProvider ?: BasicCredentialsProvider()
	                )
	                .setDefaultRequestConfig(config).build()
	    }
	
	    @Bean
	    @ConditionalOnProperty("httpclient.clientKeyStore")
	    fun ssLContext(): SSLContext {
	        val trustStore = properties.trustKeyStore?.let { getKeyStore(properties.trustKeyStoreType, it, properties.trustKeyStorePwd!!) }
	        val keyStore = getKeyStore(properties.clientKeyStoreType, properties.clientKeyStore!!, properties.clientKeyStorePwd!!)
	
	        return SSLContexts
	                .custom()
	                .loadTrustMaterial(trustStore, TrustAllStrategy().takeIf { trustStore == null })
	                .loadKeyMaterial(keyStore, properties.clientKeyPwd!!.readText().toCharArray())
	                .build()
	    }
	
	    @Bean
	    @ConditionalOnProperty("httpclient.basicAuthUser")
	    fun getCredentialsProvider(): CredentialsProvider {
	        val provider = BasicCredentialsProvider()
	        val scope = AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM)
	        val credentials = UsernamePasswordCredentials(properties.basicAuthUser, properties.basicAuthPwd)
	        provider.setCredentials(scope, credentials)
	
	        return provider
	    }
	
	    private fun getKeyStore(type: String, keyStorePath: Resource, keyStorePwd: Resource): KeyStore {
	        val keyStore = KeyStore.getInstance(type)
	        keyStore.load(keyStorePath.inputStream, keyStorePwd.readText().toCharArray())
	
	        return keyStore
	    }
	
	}
	
	@ConfigurationProperties("httpclient")
	class HttpClientProperties {
	
	    var timeout = 0
	
	    var clientKeyStore: Resource? = null
	    var clientKeyStorePwd: Resource? = null
	    var clientKeyStoreType = "jks"
	    var clientKeyPwd: Resource? = null
	
	    var trustKeyStore: Resource? = null
	    var trustKeyStorePwd: Resource? = null
	    var trustKeyStoreType = "jks"
	
	    var supportedProtocols: Array<String>? = null
	
	    var basicAuthUser: String? = null
	    var basicAuthPwd: String? = null
	
	    var verifyHost = true
	}

调用

以json形式
@Service
class Api(val svsSign: SvsSign,
              val httpClient: CloseableHttpClient,
              val config: Config) {

    private val logger = LoggerFactory.getLogger(Api::class.java)
    fun <T : Response> execute(request: Request, parseResponse: (String) -> T): T {
        val httpPost = HttpPost(config.host)
        httpPost.entity = StringEntity(Codecs.objToJsonString(RequestPayload(svsSign.signatureRequest(request))), Consts.UTF_8)
        logger.info("send ${request.head.headTranCode} with extRefId: ${request.body.serialNo} request to api:\n ${Codecs.objToJsonString(request)}")
        val httpResponse = httpClient.execute(httpPost)

        val content = EntityUtils.toString(httpResponse.entity)
        logger.info("receive raw response from api\n $content")

        return parseResponse(content)
    }
}
以xml形式
@Component
class Client(private val httpClient: CloseableHttpClient,
                    private val rail: Config.rail) {
    val logger = LoggerFactory.getLogger(this.javaClass)

    fun <T : Response> execute(request: Request, action: ActionType<T>, account: Config.railAccount): Response {
        request.UID = account.userName
        request.PWD = account.pwd
        val signStr = request.getSignStr().plus(account.signatureKey)
        request.rspSign = String(Hex.encodeHex(MessageDigest.getInstance("MD5").digest(signStr.toByteArray(Charsets.US_ASCII)), true))
        val reqBody = MessageTransformer.toXML(request)
        val result = simplePostReq(reqBody, action.name).content
        return MessageTransformer.fromXML<Response>(result, action.elementName, action.responseClass as Class<Response>)
    }

    private fun simplePostReq(content: String, path: String): HttpResult {

        val httpPost = HttpPost(rail.client.url)
        httpPost.setHeader("Content-type", "text/xml;charset=utf-8");
        httpPost.setHeader("SOAPAction", "http://tempuri.org/$path")

        httpPost.entity = StringEntity(content, Charsets.UTF_8)

        var resContent: String?
        var response: HttpResponse?
        try {
            logger.info("\n ****** Sending request to ${rail.client.url} with content ******\n $content")
            response = httpClient.execute(httpPost)
            resContent = EntityUtils.toString(response.entity)

            logger.info("\n ****** Received response ******\n ${getPrettyString(resContent, 2)}")

        } catch (e: Exception) {
            e.printStackTrace()
            throw FailureException(Failure.of("Invoke rail service failed", e.message))
        }

        return HttpResult(response!!.statusLine.statusCode, resContent)
    }

    @Throws(Exception::class)
    private fun getPrettyString(xmlData: String, indent: Int): String {
        val transformerFactory = TransformerFactory.newInstance()
        transformerFactory.setAttribute("indent-number", indent)

        val transformer = transformerFactory.newTransformer()
        transformer.setOutputProperty(OutputKeys.INDENT, "yes")

        val stringWriter = StringWriter()
        val xmlOutput = StreamResult(stringWriter)

        val xmlInput = StreamSource(StringReader(xmlData))
        transformer.transform(xmlInput, xmlOutput)

        return xmlOutput.writer.toString()
    }

    private class HttpResult(var status: Int, var content: String?)

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值