spring boot封装HttpClient的示例代码

最近使用到了HttpClient,看了一下官方文档:HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused for multiple request executions,翻译过来的意思就是:HttpClient的实现是线程安全的,可以重用相同的实例来执行多次请求。遇到这种描述的话,我们就应该想到,需要对HttpClient来进行封装了。由于是使用的spring boot,所以下面来结合spring boot来封装HttpClient。

一、Request retry handler(请求重试处理)

为了使自定义异常机制生效,需要实现HttpRequestRetryHandler接口,代码如下:

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.protocol.HttpContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 

/**
 * 描述:HttpClient的重试处理机制
 */
@Configuration
public class MyhttpRequestRetryHandler { 

  @Value("${httpclient.config.retryTime}")// 此处建议采用@ConfigurationProperties(prefix="httpclient.config")方式,方便复用
  private int retryTime; 

  @Bean
  public HttpRequestRetryHandler httpRequestRetryHandler() {
    // 请求重试
    final int retryTime = this.retryTime;
    return new HttpRequestRetryHandler() {
      public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
        // Do not retry if over max retry count,如果重试次数超过了retryTime,则不再重试请求
        if (executionCount >= retryTime) {
          return false;
        }
        // 服务端断掉客户端的连接异常
        if (exception instanceof NoHttpResponseException) {
          return true;
        }
        // time out 超时重试
        if (exception instanceof InterruptedIOException) {
          return true;
        }
        // Unknown host
        if (exception instanceof UnknownHostException) {
          return false;
        }
        // Connection refused
        if (exception instanceof ConnectTimeoutException) {
          return false;
        }
        // SSL handshake exception
        if (exception instanceof SSLException) {
          return false;
        }
        HttpClientContext clientContext = HttpClientContext.adapt(context);
        HttpRequest request = clientContext.getRequest();
        if (!(request instanceof HttpEntityEnclosingRequest)) {
          return true;
        }
        return false;
      }
    };
  }
}

二、Pooling connection manager(连接池管理)

PoolingHttpClientConnectionManager用来管理客户端的连接池,并且可以为多个线程的请求提供服务,代码如下:

import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
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 MyPoolingHttpClientConnectionManager {
  /**
   * 连接池最大连接数
   */
  @Value("${httpclient.config.connMaxTotal}")
  private int connMaxTotal = 20; 

  /**
   *
   */
  @Value("${httpclient.config.maxPerRoute}")
  private int maxPerRoute = 20; 

    /**
   * 连接存活时间,单位为s
   */
   @Value("${httpclient.config.timeToLive}")
   private int timeToLive = 60; 

    @Bean
  public PoolingHttpClientConnectionManager poolingClientConnectionManager(){
    PoolingHttpClientConnectionManager poolHttpcConnManager = new PoolingHttpClientConnectionManager(60, TimeUnit.SECONDS);
    // 最大连接数
    poolHttpcConnManager.setMaxTotal(this.connMaxTotal);
    // 路由基数
    poolHttpcConnManager.setDefaultMaxPerRoute(this.maxPerRoute);
    return poolHttpcConnManager;
  }
}

注意:当HttpClient实例不再需要并且即将超出范围时,重要的是关闭其连接管理器,以确保管理器保持活动的所有连接都被关闭,并释放由这些连接分配的系统资源

上面PoolingHttpClientConnectionManager类的构造函数如下:

public PoolingHttpClientConnectionManager(final long timeToLive, final TimeUnit tunit) {
    this(getDefaultRegistry(), null, null ,null, timeToLive, tunit);
  } 

private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
    return RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", SSLConnectionSocketFactory.getSocketFactory())
        .build();
  } 

在PoolingHttpClientConnectionManager的配置中有两个最大连接数量,分别控制着总的最大连接数量和每个route的最大连接数量。如果没有显式设置,默认每个route只允许最多2个connection,总的connection数量不超过20。这个值对于很多并发度高的应用来说是不够的,必须根据实际的情况设置合适的值,思路和线程池的大小设置方式是类似的,如果所有的连接请求都是到同一个url,那可以把MaxPerRoute的值设置成和MaxTotal一致,这样就能更高效地复用连接

特别注意:想要复用一个connection就必须要让它占有的系统资源得到正确释放,释放方法如下:

如果是使用outputStream就要保证整个entity都被write out,如果是inputStream,则再最后要记得调用inputStream.close()。或者使用EntityUtils.consume(entity)或EntityUtils.consumeQuietly(entity)来让entity被完全耗尽(后者不抛异常)来做这一工作。EntityUtils中有个toString方法也很方便的(调用这个方法最后也会自动把inputStream close掉的,但是在实际的测试过程中,会导致连接没有释放的现象),不过只有在可以确定收到的entity不是特别大的情况下才能使用。如果没有让整个entity被fully consumed,则该连接是不能被复用的,很快就会因为在连接池中取不到可用的连接超时或者阻塞在这里(因为该连接的状态将会一直是leased的,即正在被使用的状态)。所以如果想要复用connection,一定一定要记得把entity fully consume掉,只要检测到stream的eof,是会自动调用ConnectionHolder的releaseConnection方法进行处理的

三、Connection keep alive strategy(保持连接策略)

HTTP规范没有指定持久连接可能和应该保持存活多久。一些HTTP服务器使用非标准的Keep-Alive标头来向客户端通信它们打算在服务器端保持连接的时间段(以秒为单位)。HttpClient可以使用这些信息。如果响应中不存在Keep-Alive头,HttpClient会假定连接可以无限期地保持活动。然而,一般使用的许多HTTP服务器都配置为在一段不活动状态之后删除持久连接,以便节省系统资源,而不会通知客户端。如果默认策略过于乐观,则可能需要提供自定义的保持活动策略,代码如下:

import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 描述:连接保持策略
 * @author chhliu
 */
@Configuration
public class MyconnectionKeepAliveStrategy { 

  @Value("${httpclient.config.keepAliveTime}")
  private int keepAliveTime = 30; 

  @Bean("connectionKeepAliveStrategy")
  public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
    return new ConnectionKeepAliveStrategy() { 

      public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
        // Honor 'keep-alive' header
        HeaderElementIterator it = new BasicHeaderElementIterator(
            response.headerIterator(HTTP.CONN_KEEP_ALIVE));
        while (it.hasNext()) {
          HeaderElement he = it.nextElement();
          String param = he.getName();
          String value = he.getValue();
          if (value != null && param.equalsIgnoreCase("timeout")) {
            try {
              return Long.parseLong(value) * 1000;
            } catch (NumberFormatException ignore) {
            }
          }
        }
        return 30 * 1000;
      }
    };
  }
}

注意:长连接并不使用于所有的情况,尤其现在的系统,大都是部署在多台服务器上,且具有负载均衡的功能,如果我们在访问的时候,一直保持长连接,一旦那台服务器挂了,就会影响客户端,同时也不能充分的利用服务端的负载均衡的特性,反而短连接更有利一些,这些需要根据具体的需求来定,而不是一言概括。

四、HttpClient proxy configuration(代理配置)

用来配置代理,代码如下:

import org.apache.http.HttpHost;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 描述:HttpClient代理
 * @author chhliu
 */
@Configuration
public class MyDefaultProxyRoutePlanner {
  // 代理的host地址
  @Value("${httpclient.config.proxyhost}")
  private String proxyHost; 

  // 代理的端口号
  @Value("${httpclient.config.proxyPort}")
  private int proxyPort = 8080; 

  @Bean
  public DefaultProxyRoutePlanner defaultProxyRoutePlanner(){
    HttpHost proxy = new HttpHost(this.proxyHost, this.proxyPort);
    return new DefaultProxyRoutePlanner(proxy);
  }
}

HttpClient不仅支持简单的直连、复杂的路由策略以及代理。HttpRoutePlanner是基于http上下文情况下,客户端到服务器的路由计算策略,一般没有代理的话,就不用设置这个东西。这里有一个很关键的概念—Route:在HttpClient中,一个Route指 运行环境机器->目标机器host的一条线路,也就是如果目标url的host是同一个,那么它们的route也是一样的

五、RequestConfig

用来设置请求的各种配置,代码如下:

import org.apache.http.client.config.RequestConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRequestConfig {
  @Value("${httpclient.config.connectTimeout}")
  private int connectTimeout = 2000; 

  @Value("${httpclient.config.connectRequestTimeout}")
  private int connectRequestTimeout = 2000; 

  @Value("${httpclient.config.socketTimeout}")
  private int socketTimeout = 2000;
  @Bean
  public RequestConfig config(){
    return RequestConfig.custom()
        .setConnectionRequestTimeout(this.connectRequestTimeout)
        .setConnectTimeout(this.connectTimeout)
        .setSocketTimeout(this.socketTimeout)
        .build();
  }
}

RequestConfig是对request的一些配置。里面比较重要的有三个超时时间,默认的情况下这三个超时时间都为0(如果不设置request的Config,会在execute的过程中使用HttpClientParamConfig的getRequestConfig中用默认参数进行设置),这也就意味着无限等待,很容易导致所有的请求阻塞在这个地方无限期等待。这三个超时时间为:

a、connectionRequestTimeout—从连接池中取连接的超时时间

这个时间定义的是从ConnectionManager管理的连接池中取出连接的超时时间, 如果连接池中没有可用的连接,则request会被阻塞,最长等待connectionRequestTimeout的时间,如果还没有被服务,则抛出ConnectionPoolTimeoutException异常,不继续等待。

b、connectTimeout—连接超时时间

这个时间定义了通过网络与服务器建立连接的超时时间,也就是取得了连接池中的某个连接之后到接通目标url的连接等待时间。发生超时,会抛出ConnectionTimeoutException异常。

c、socketTimeout—请求超时时间

这个时间定义了socket读数据的超时时间,也就是连接到服务器之后到从服务器获取响应数据需要等待的时间,或者说是连接上一个url之后到获取response的返回等待时间。发生超时,会抛出SocketTimeoutException异常。

六、实例化HttpClient

通过实现FactoryBean来实例化HttpClient,代码如下:

import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * 描述:HttpClient客户端封装
 */
@Service("httpClientManagerFactoryBen")
public class HttpClientManagerFactoryBen implements FactoryBean<CloseableHttpClient>, InitializingBean, DisposableBean { 

  /**
   * FactoryBean生成的目标对象
   */
  private CloseableHttpClient client; 

  @Autowired
  private ConnectionKeepAliveStrategy connectionKeepAliveStrategy; 

  @Autowired
  private HttpRequestRetryHandler httpRequestRetryHandler; 

  @Autowired
  private DefaultProxyRoutePlanner proxyRoutePlanner; 

  @Autowired
  private PoolingHttpClientConnectionManager poolHttpcConnManager; 

  @Autowired
  private RequestConfig config; 

    // 销毁上下文时,销毁HttpClient实例
  @Override
  public void destroy() throws Exception {
         /*
      * 调用httpClient.close()会先shut down connection manager,然后再释放该HttpClient所占用的所有资源,
      * 关闭所有在使用或者空闲的connection包括底层socket。由于这里把它所使用的connection manager关闭了,
      * 所以在下次还要进行http请求的时候,要重新new一个connection manager来build一个HttpClient,
      * 也就是在需要关闭和新建Client的情况下,connection manager不能是单例的.
      */
        if(null != this.client){
      this.client.close();
      }
  } 

  @Override// 初始化实例
  public void afterPropertiesSet() throws Exception {
         /*
     * 建议此处使用HttpClients.custom的方式来创建HttpClientBuilder,而不要使用HttpClientBuilder.create()方法来创建HttpClientBuilder
     * 从官方文档可以得出,HttpClientBuilder是非线程安全的,但是HttpClients确实Immutable的,immutable 对象不仅能够保证对象的状态不被改变,
     * 而且还可以不使用锁机制就能被其他线程共享
     */
         this.client = HttpClients.custom().setConnectionManager(poolHttpcConnManager)
        .setRetryHandler(httpRequestRetryHandler)
        .setKeepAliveStrategy(connectionKeepAliveStrategy)
        .setRoutePlanner(proxyRoutePlanner)
        .setDefaultRequestConfig(config)
        .build();
  } 

    // 返回实例的类型
  @Override
  public CloseableHttpClient getObject() throws Exception {
    return this.client;
  } 

  @Override
  public Class<?> getObjectType() {
    return (this.client == null ? CloseableHttpClient.class : this.client.getClass());
  } 

    // 构建的实例为单例
  @Override
  public boolean isSingleton() {
    return true;
  } 

}

七、增加配置文件

# 代理的host
httpclient.config.proxyhost=xxx.xx.xx.xx
# 代理端口
httpclient.config.proxyPort=8080
# 连接超时或异常重试次数
httpclient.config.retryTime=3
# 长连接保持时间,单位为s
httpclient.config.keepAliveTime=30
# 连接池最大连接数
httpclient.config.connMaxTotal=20
httpclient.config.maxPerRoute=20
# 连接超时时间,单位ms
httpclient.config.connectTimeout=2000
# 请求超时时间
httpclient.config.connectRequestTimeout=2000
# sock超时时间
httpclient.config.socketTimeout=2000
# 连接存活时间,单位s
httpclient.config.timeToLive=60

八、测试

测试代码如下:

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; 

import javax.annotation.Resource; 

import org.apache.http.Consts;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; 

@RunWith(SpringRunner.class)
@SpringBootTest
public class HttpClientManagerFactoryBenTest {
    // 注入HttpClient实例
    @Resource(name = "httpClientManagerFactoryBen")
  private CloseableHttpClient client; 

  @Test
  public void test() throws ClientProtocolException, IOException, InterruptedException{
    ExecutorService service = Executors.newFixedThreadPool(2);
    for(int i=0; i<10; i++){
      service.submit(new Runnable() { 

        @Override
        public void run() {
          System.out.println("the current thread is:"+Thread.currentThread().getName());
                    HttpEntity entity = null;
                    try {
            HttpGet get = new HttpGet("https://localhost:8080/testjson");
            // 通过httpclient的execute提交 请求 ,并用CloseableHttpResponse接受返回信息
            CloseableHttpResponse response = client.execute(get);
            System.out.println("client object:"+client);
                        entity = response.getEntity();
                        System.out.println("============"+EntityUtils.toString(entity, Consts.UTF_8)+"=============");
                        EntityUtils.consumeQuietly(entity);// 释放连接
                    } catch (ClientProtocolException e) {
            e.printStackTrace();
          } catch (ParseException e) {
            e.printStackTrace();
          } catch (IOException e) {
            e.printStackTrace();
          } finally{
                        if(null != entity){// 释放连接
                EntityUtils.consumeQuietly(entity);
               }
                    }
                }
      });
    }
    Thread.sleep(60000);
  }
}

通过上面的几个步骤,就基本上完成了对HttpClient的封装,如果需要更细致的话,可以按照上面的思路,逐步完善,将HttpClient封装成HttpClientTemplate,因为CloseableHttpClient内部使用了回调机制,和JdbcTemplate,或者是RedisTemplate类似,直到可以以spring boot starter的方式提供服务。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • spring boot中使用http请求的示例代码
  • 详解Spring Boot 定制HTTP消息转换器
  • springboot添加https服务器的方法
  • 详解SpringBoot初始教程之Tomcat、Https配置以及Jetty优化
  • Spring boot自定义http反馈状态码详解
  • 详解在Spring Boot中使用Https
(0)

相关推荐

  • 详解SpringBoot初始教程之Tomcat、Https配置以及Jetty优化

    1.介绍 在SpringBoot的Web项目中,默认采用的是内置Tomcat,当然也可以配置支持内置的jetty,内置有什么好处呢? 1. 方便微服务部署. 2. 方便项目启动,不需要下载Tomcat或者Jetty 在目前的公司已经把内置的Jetty部署到了线上项目中,目前来说并无太大问题,内置就算有一些性能损失,但是通过部署多台机器, 其实也能够很轻松的解决这样的问题,内置容器之后其实是方便部署和迁移的. 1.1 优化策略 针对目前的容器优化,目前来说没有太多地方,需要考虑如下几个点 线程数

  • spring boot中使用http请求的示例代码

    因为项目需求,需要两个系统之间进行通信,经过一番调研,决定使用http请求. 服务端没有什么好说的,本来就是使用web 页面进行访问的,所以spring boot启动后,controller层的接口就自动暴露出来了,客户端通过调用对应的url即可,所以这里主要就客户端. 首先我自定义了一个用来处理http 请求的工具类DeviceFactoryHttp,既然是url访问,那就有两个问题需要处理,一个请求服务的url,和请求服务端的参数,客户端的消息头请求服务的url:请求服务端url我定义的是跟

  • Spring boot自定义http反馈状态码详解

    前言 最近在开发一些http server类型程序,通过spring boot构建一些web程序,这些web程序之间通过http进行数据访问.共享,如下图, 假设现在client发起一次保存数据的请求到server,server可能会返回如下类似的数据 { "status":1, "message":"xxxxxx" } 然后client通过解析json获得status来判断当前的请求操作是否成功,开发过程中通过都是这么做的,但是这样在restf

  • 详解Spring Boot 定制HTTP消息转换器

    在构建RESTful数据服务过程中,我们定义了controller.repositories,并用一些注解修饰它们,但是到现在为止我们还没执行过对象的转换--将java实体对象转换成HTTP的数据输出流.Spring Boot底层通过HttpMessageConverters依靠Jackson库将Java实体类输出为JSON格式.当有多个转换器可用时,根据消息对象类型和需要的内容类型选择最适合的转换器使用. 在SpringMVC源码剖析之消息转换器HttpMessageConverter一文中,

  • 详解在Spring Boot中使用Https

    本文介绍如何在Spring Boot中,使用Https提供服务,并将Http请求自动重定向到Https. Https证书 巧妇难为无米之炊,开始的开始,要先取得Https证书.你可以向证书机构申请证书,也可以自己制作根证书. 创建Web配置类 在代码中创建一个使用了Configuration注解的类,就像下面这段代码一样: @Configuration public class WebConfig { //Bean 定义... } 配置Https 在配置类中添加EmbeddedServletCo

  • springboot添加https服务器的方法

    什么是https 要说https我们得先说SSL(Secure Sockets Layer,安全套接层),这是一种为网络通信提供安全及数据完整性的一种安全协议,SSL在网络传输层对网络连接进行加密.SSL协议可以分为两层:SSL记录协议(SSL Record Protocol),它建立在可靠的传输协议如TCP之上,为高层协议提供数据封装.压缩.加密等基本功能支持:SSL握手协议(SSL Handshake Protocol),它建立在SSL记录协议之上,用于在实际数据传输开始之前,通信双方进行身

  • spring boot封装HttpClient的示例代码

    最近使用到了HttpClient,看了一下官方文档:HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused for multiple request executions,翻译过来的意思就是:HttpClient的实现是线程安全的,可以重用相同的实例来执行多次请求.遇到这种描述的话,我们就应该想到,需要对H

  • spring boot整合Swagger2的示例代码

    Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化RESTful风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步.Swagger 让部署管理和使用功能强大的API从未如此简单. 1.代码示例 1).在pom.xml文件中引入Swagger2 <dependency> <groupId>io.springfox</groupId> <artifa

  • Spring Boot集成Kafka的示例代码

    本文介绍了Spring Boot集成Kafka的示例代码,分享给大家,也给自己留个笔记 系统环境 使用远程服务器上搭建的kafka服务 Ubuntu 16.04 LTS kafka_2.12-0.11.0.0.tgz zookeeper-3.5.2-alpha.tar.gz 集成过程 1.创建spring boot工程,添加相关依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu

  • Spring boot配置 swagger的示例代码

    为什么使用Swagger 在实际开发中我们作为后端总是给前端或者其他系统提供接口,每次写完代码之后不可避免的都需要去写接口文档,首先写接口文档是一件繁琐的事,其次由接口到接口文档需要对字段.甚至是排版等.再加上如果我们是为多个系统提供接口时可能还需要按照不同系统的要求去书写文档,那么有没有一种方式让我们在开发阶段就给前端提供好接口文档,甚至我们可以把生成好的接口文档暴露出去供其他系统调用,那么这样我只需要一份代码即可. Spring boot配置 swagger 1.导入maven依赖 <!--

  • 使用Spring Boot集成FastDFS的示例代码

    这篇文章我们介绍如何使用Spring Boot将文件上传到分布式文件系统FastDFS中. 这个项目会在上一个项目的基础上进行构建. 1.pom包配置 我们使用Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0. <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>

  • Spring boot集成RabbitMQ的示例代码

    RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术.排队指的是应用程序通过 队列来通信.队列的使用除去了接收和发送应用程序同时执行的要求. AMQP就是一个协议

  • Spring Boot实战之发送邮件示例代码

    一.邮件服务简介 邮件服务在互联网早期就已经出现,如今已成为人们互联网生活中必不可少的一项服务.那么邮件服务是怎么工作的呢?如下给出邮件发送与接收的典型过程: 1.发件人使用SMTP协议传输邮件到邮件服务器A: 2.邮件服务器A根据邮件中指定的接收者,投送邮件至相应的邮件服务器B: 3.收件人使用POP3协议从邮件服务器B接收邮件. SMTP(Simple Mail Transfer Protocol)是电子邮件(email)传输的互联网标准,定义在RFC5321,默认使用端口25: POP3(

  • Spring Boot 自定义starter的示例代码

    SpringBoot 个人感觉特点: 1)众多库的集合(各种Starter),方便快速构建应用系统. 2)自动配置spring(通过AutoConfiguration机制),简化配置,也方便扩展新的Starter. 3)内嵌web容器,无需WAR部署. 创建一个用maven构建的springboot项目 pom文件配置如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht

  • spring boot mybatis枚举映射示例代码

    前言 在mybatis和mybatis plus里,如果你的实体字段是一个枚举类型,而在数据表里是整型,这时在存储时需要进行处理,默认情况下,会把枚举的元素名称拼接到SQL语句里,而由于数据表是int类型,所以在插入等操作时,就会出现异常! 添加枚举处理器 MappedTypes(value = {YesOrNo.class}) public class UniversalEnumHandler<E extends Enum<E> & BaseEnum> extends B

  • spring boot aop 记录方法执行时间代码示例

    本文研究的主要是spring boot aop 记录方法执行时间的实现代码,具体如下. 为了性能调优,需要先统计出来每个方法的执行时间,直接在方法前后log输出太麻烦,可以用AOP来加入时间统计 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency&

随机推荐