文档章节

RabbitMQ(5)-使用场景及简单实现Hello World!

你我他有个梦
 你我他有个梦
发布于 2015/12/20 15:21
字数 2658
阅读 343
收藏 3

一.单发送单接收

1.使用场景:

简单的发送与接收,没有特别的处理。

2.producer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class OneProducer {
    
  private final static String QUEUE_NAME = "queue_one";

  public static void main(String[] argv) throws Exception {
                
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang129");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    /**
     * 参数:
      queue the name of the queue
      durable true if we are declaring a durable queue (the queue will survive a server restart)
      exclusive true if we are declaring an exclusive queue (restricted to this connection)
      autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use)
      arguments other properties (construction arguments) for the queue
   */
    channel.queueDeclare(QUEUE_NAME, true, false, false, null);
    String message = "Hello World!";
    /**
     * 参数:
      exchange the exchange to publish the message to
      routingKey the routing key
      props other properties for the message - routing headers etc
      body the message body
     */
    channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
    System.out.println(" [x] Sent '" + message + "'");
    
    channel.close();
    connection.close();
  }
}

3.consumer:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

import java.util.HashMap;
import java.util.Map;

public class OneConsumer {
       private final static String QUEUE_NAME = "queue_one";

       public static void main(String[] argv) throws Exception {
      //连接服务器
       ConnectionFactory factory = new ConnectionFactory();
      factory.setHost("liuzhaoqiang128");
      factory.setUsername("admin");
      factory.setPassword("admin");
      factory.setPort(5672);
       Connection connection = factory.newConnection();
      //建立consumer与服务器之间的channel
       Channel channel = connection.createChannel();
      //定义queue
       channel.queueDeclare(QUEUE_NAME, true, false, false, null);
       System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
       
       QueueingConsumer consumer = new QueueingConsumer(channel);
      //设置consumer的优先级,数字越大代表接收消息的优先级越高,
      // 如果不设置优先级,发送多条消息时,cosumer端启动时间越长的接收消息的优先级越高
      Map<String, Object> args = new HashMap<String, Object>();
      args.put("x-priority", 10);
       /**
        * 参数:
         queue the name of the queue
         autoAck true if the server should consider messages acknowledged once delivered; false if the server should expect explicit acknowledgements
         callback an interface to the consumer object
        */

       channel.basicConsume(QUEUE_NAME, true, args,consumer);
       
       while (true) {
         QueueingConsumer.Delivery delivery = consumer.nextDelivery();
         String message = new String(delivery.getBody());
         System.out.println(" [x] Received '" + message + "'");
       }
     }
}

二.单发送多接收

1.使用场景:

一个发送端,多个接收端,如分布式的任务派发。为了保证消息发送的可靠性,不丢失消息,使消息持久化了。同时为了防止接收端在处理消息时down掉,只有在消息处理完成后才发送ack消息。

2.producer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;

public class Producer {
  
  private static final String QUEUE_NAME = "queue_one";

  public static void main(String[] argv) throws Exception {
    //连接服务器
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang129");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    //创建producer与服务器之间的channel
    Channel channel = connection.createChannel();
    //声明queue
    channel.queueDeclare(QUEUE_NAME, true, false, false, null);
    channel.confirmSelect().protocolMethodName();
    System.out.println("confirm发送确认消息:"+channel.confirmSelect().protocolMethodId());
    for(int i=0;i<10;i++){
       String message = getMessage(argv)+i;
       //消息持久化
       channel.basicPublish( "", QUEUE_NAME,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message.getBytes());
       System.out.println(" [x] Sent '" + message + "'");
    }
    Thread.sleep(100000);
    channel.close();
    connection.close();
  }
    
  private static String getMessage(String[] strings){
    if (strings.length < 1)
      return "Hello World!";
    return joinStrings(strings, " ");
  }  
  
  private static String joinStrings(String[] strings, String delimiter) {
    int length = strings.length;
    if (length == 0) return "";
    StringBuilder words = new StringBuilder(strings[0]);
    for (int i = 1; i < length; i++) {
      words.append(delimiter).append(strings[i]);
    }
    return words.toString();
  }
}
发送端和场景1不同点:

1、使Queue的durable的属性为true,即使消息队列durable
2、使用MessageProperties.PERSISTENT_TEXT_PLAIN使消息durable

3.consumer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class Consumer {

   private static final String TASK_QUEUE_NAME = "queue_one";

   public static void main(String[] argv) throws Exception {

      ConnectionFactory factory = new ConnectionFactory();
      factory.setHost("liuzhaoqiang129");
      factory.setUsername("admin");
      factory.setPassword("admin");
      factory.setPort(5672);
      Connection connection = factory.newConnection();
      Channel channel = connection.createChannel();

      channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
      System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

      channel.basicQos(1);

      QueueingConsumer consumer = new QueueingConsumer(channel);
      channel.basicConsume(TASK_QUEUE_NAME, false, consumer);

      while (true) {
         QueueingConsumer.Delivery delivery = consumer.nextDelivery();
         String message = new String(delivery.getBody());

         System.out.println(" [x] Received '" + message + "'");
         doWork(message);
         System.out.println(" [x] Done");

         channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
      }
   }

   private static void doWork(String task) throws InterruptedException {
      for (char ch : task.toCharArray()) {
         if (ch == '.')
            Thread.sleep(1000);
      }
   }
}
接收端和场景1不同点:
1、使用TASK_QUEUE_NAME声明消息队列,并使消息队列durable
2、在使用channel.basicConsume接收消息时使autoAck为false,即不自动会发ack,由channel.basicAck()在消息处理完成后发送消息。
3、使用了channel.basicQos(1)保证在接收端一个消息没有处理完时不会接收另一个消息,即接收端发送了ack后才会接收下一个消息。在这种情况下发送端会尝试把消息发送给下一个not busy的接收端。

三.publish/subscribe

1.使用场景:

发布订阅模式,发送端发送的是广播消息,多个接收端接收

2.producer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class ProducerPublish {

  private static final String EXCHANGE_NAME = "logs";

  public static void main(String[] argv) throws Exception {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang128");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.exchangeDeclare(EXCHANGE_NAME, "fanout");

    String message = getMessage(argv);

    channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
    System.out.println(" [x] Sent '" + message + "'");

    channel.close();
    connection.close();
  }
  
  private static String getMessage(String[] strings){
    if (strings.length < 1)
            return "info: Hello World!";
    return joinStrings(strings, " ");
  }
  
  private static String joinStrings(String[] strings, String delimiter) {
    int length = strings.length;
    if (length == 0) return "";
    StringBuilder words = new StringBuilder(strings[0]);
    for (int i = 1; i < length; i++) {
        words.append(delimiter).append(strings[i]);
    }
    return words.toString();
  }
}

发送消息到一个名为“logs”的exchange上,使用“fanout”方式发送,即广播消息,不需要使用queue,发送端不需要关心谁接收。

3.consumer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class ConsumerSubcribe {

  private static final String EXCHANGE_NAME = "logs";

  public static void main(String[] argv) throws Exception {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang128");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
    String queueName = channel.queueDeclare().getQueue();
    channel.queueBind(queueName, EXCHANGE_NAME, "");
    
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

    QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(queueName, true, consumer);

    while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());
      System.out.println(" [x] Received '" + message + "'");
    }
  }
}
1、声明名为“logs”的exchange的,方式为"fanout",和发送端一样。
2、channel.queueDeclare().getQueue();该语句得到一个随机名称的Queue,该queue的类型为non-durable、exclusive、auto-delete的,将该queue绑定到上面的exchange上接收消息。
3、注意binding queue的时候,channel.queueBind()的第三个参数Routing key为空,即所有的消息都接收。如果这个值不为空,在exchange type为“fanout”方式下该值被忽略!

四.Routing

1.使用场景:

发送端按routing key发送消息,不同的接收端按不同的routing key接收消息

2.producer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class ProducerRouting {

  private static final String EXCHANGE_NAME = "my-mq-exchange";
  private static final String ROUTING_KEY = "queue_one_key";
  public static void main(String[] argv) throws Exception {
    //连接服务器
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang129");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    //创建producer与服务器之间的channel
    Channel channel = connection.createChannel();
    //声明exchange与type
    channel.exchangeDeclare(EXCHANGE_NAME, "direct",true);

    String message = "Hello World!";
    //为指定的rouking key发布消息
    channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, message.getBytes());
    System.out.println(" [x] Sent '" + ROUTING_KEY + "':'" + message + "'");

    channel.close();
    connection.close();
  }
}

发送端和场景3的区别:
1、exchange的type为direct
2、发送消息的时候加入了routing key

3.consumer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class ConsumerRouting {

  private static final String EXCHANGE_NAME = "my-mq-exchange";
  private static final String ROUTING_KEY = "queue_one_key";
  public static void main(String[] argv) throws Exception {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("liuzhaoqiang128");
    factory.setUsername("admin");
    factory.setPassword("admin");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.exchangeDeclare(EXCHANGE_NAME, "direct",true);
    String queueName = channel.queueDeclare().getQueue();
    System.out.println("queueName....."+queueName);
    channel.queueBind(queueName, EXCHANGE_NAME, ROUTING_KEY);

    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

    QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(queueName, true, consumer);
    while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());
      String routingKey = delivery.getEnvelope().getRoutingKey();

      System.out.println(" [x] Received '" + routingKey + "':'" + message + "'");
    }
  }
}
接收端和场景3的区别:
在绑定queue和exchange的时候使用了routing key,即从该exchange上只接收routing key指定的消息。

五.Topics

1.使用场景:

发送端不只按固定的routing key发送消息,而是按字符串匹配发送,接收端同样如此。

2.producer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class ProducerTopic {

  private static final String EXCHANGE_NAME = "myexchange1";
  private static final String ROUTING_KEY = "foo.*";

  public static void main(String[] argv) {
    Connection connection = null;
    Channel channel = null;
    try {
      ConnectionFactory factory = new ConnectionFactory();
      factory.setHost("liuzhaoqiang129");
      factory.setUsername("admin");
      factory.setPassword("admin");
      factory.setPort(5672);
  
      connection = factory.newConnection();
      channel = connection.createChannel();

      channel.exchangeDeclare(EXCHANGE_NAME, "topic",true);
      String message = getMessage(argv);

      channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, message.getBytes());
      System.out.println(" [x] Sent '" + ROUTING_KEY + "':'" + message + "'");

    }
    catch  (Exception e) {
      e.printStackTrace();
    }
    finally {
      if (connection != null) {
        try {
          connection.close();
        }
        catch (Exception ignore) {}
      }
    }
  }
  
  private static String getRouting(String[] strings){
    if (strings.length < 1)
            return "anonymous.info";
    return strings[0];
  }

  private static String getMessage(String[] strings){ 
    if (strings.length < 2)
            return "Hello World!";
    return joinStrings(strings, " ", 1);
  }
  
  private static String joinStrings(String[] strings, String delimiter, int startIndex) {
    int length = strings.length;
    if (length == 0 ) return "";
    if (length < startIndex ) return "";
    StringBuilder words = new StringBuilder(strings[startIndex]);
    for (int i = startIndex + 1; i < length; i++) {
        words.append(delimiter).append(strings[i]);
    }
    return words.toString();
  }
}

发送端和场景4的区别:
1、exchange的type为topic
2、发送消息的routing key不是固定的单词,而是匹配字符串,如"*.lu.#",*匹配一个单词,#匹配0个或多个单词。

3.consumer:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class ConsumerTopic {

   private static final String EXCHANGE_NAME = "myexchange1";
   private static final String QUEUE_NAME = "queue_one";
   private static final String ROUTING_KEY = "foo.queue";

   public static void main(String[] argv) {
      Connection connection = null;
      Channel channel = null;
      try {
         ConnectionFactory factory = new ConnectionFactory();
         factory.setHost("liuzhaoqiang128");
         factory.setUsername("admin");
         factory.setPassword("admin");
         factory.setPort(5672);

         connection = factory.newConnection();
         channel = connection.createChannel();
         channel.exchangeDeclare(EXCHANGE_NAME, "topic",true);

         channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);
         System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

         QueueingConsumer consumer = new QueueingConsumer(channel);
         channel.basicConsume(QUEUE_NAME, true, consumer);
         while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            String routingKey = delivery.getEnvelope().getRoutingKey();

            System.out.println(" [x] Received '" + routingKey + "':'" + message + "'");
         }
      }
      catch  (Exception e) {
         e.printStackTrace();
      }
      finally {
         if (connection != null) {
            try {
               connection.close();
            }
            catch (Exception ignore) {}
         }
      }
   }
}
接收端和场景4的区别:
1、exchange的type为topic
2、接收消息的routing key不是固定的单词,而是匹配字符串。

六.RPC


1.使用场景:

如果想要在远程机器上获取执行结果,可用RPC

2.执行流程:

1、首先客户端发送一个reply_tocorrention_id的请求,发布到RPC队列中;

2、服务器端处理这个请求,并把处理结果发布到一个回调Queue,Queue的名称应当与reply_to的名称一致

3、客户端从回调Queue中得到先前corrention_id设定的值的处理结果。如果碰到和先前不一样的corrention_id的值,将会忽略而不是抛出异常。

3.常用属性:

  delivery_mode 标记消息是持久性消息还是瞬态信息。在前面的“Work Queue”中我们已经提到过;   

  content_type 用来描述MIME的类型。如把其类型设定为JSON

  reply_to 用于命名一个回调Queue

  correlation_id 用于与相关联的请求的RPC响应.

4.Server:

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
import com.rabbitmq.client.AMQP.BasicProperties;

public class Server
{
    private Connection connection;
    private Channel channel;
    private QueueingConsumer consumer;

    public Server Server(){
        return this;
    }

    public Server init()
            throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("liuzhaoqiang128");
        factory.setUsername("admin");
        factory.setPassword("admin");
        factory.setPort(5672);
        connection = factory.newConnection();
        channel = connection.createChannel();

        channel.exchangeDeclare("rpc", "direct");
        channel.queueDeclare("ping", false, false, false, null);
        channel.queueBind("ping", "rpc", "ping");

        consumer = new QueueingConsumer(channel);
        channel.basicConsume("ping", false, "ping", consumer);

        System.out.println(
                "Waiting for RPC calls..."
        );

        return this;
    }

    public void closeConnection() {
        if (connection != null) {
            try {
                connection.close();
            }
            catch (Exception ignore) {}
        }
    }

    public void serveRequests() {
        while (true) {
            try {

                Delivery delivery = consumer.nextDelivery();
                BasicProperties props = delivery.getProperties();

                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                System.out.println(
                        "Received API call...replying..."
                );

                channel.basicPublish(
                        "",
                        props.getReplyTo(),
                        null,
                        getResponse(delivery).getBytes("UTF-8")
                );

            } catch (Exception e){
                System.out.println(e.toString());
            }
        }
    }

    private String getResponse(Delivery delivery) {
        String response = null;
        try {
            String message = new String(delivery.getBody(), "UTF-8");
            response = "Pong!" +  JSON.parseObject(message).getString("time");
        }
        catch (Exception e){
            System.out.println(e.toString());
            response = "";
        }
        return response;
    }

    public static void main(String[] args) {
        Server server = null;
        try {
            server = new Server();
            server.init().serveRequests();
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            if(server != null) {
                server.closeConnection();
            }
        }
    }
}

5.Client:

import com.rabbitmq.client.*;
import com.rabbitmq.client.QueueingConsumer.Delivery;
import com.rabbitmq.client.AMQP.BasicProperties;
import org.json.JSONStringer;
import org.json.JSONException;

public class Client {

    private Connection connection;
    private Channel channel;
    private String replyQueueName;
    private QueueingConsumer consumer;

    public Client init()
            throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("liuzhaoqiang128");
        factory.setUsername("admin");
        factory.setPassword("admin");
        factory.setPort(5672);
        connection = factory.newConnection();
        channel = connection.createChannel();
        return this;
    }

    public Client setupConsumer()
            throws Exception {
        replyQueueName = channel.queueDeclare().getQueue();
        consumer = new QueueingConsumer(channel);
        channel.basicConsume(replyQueueName, false, consumer);
        return this;
    }

    public String call(String message) throws Exception {
        String response = null;
        channel.basicPublish(
                "rpc",
                "ping",
                getRequestProperties(),
                message.getBytes()
        );

        System.out.println("Sent 'ping' RPC call. Waiting for reply...");

        while (true) {
            Delivery delivery = consumer.nextDelivery();
            response = new String(delivery.getBody(), "UTF-8");
            break;
        }

        return response;
    }

    public void close() throws Exception {
        connection.close();
    }

    private BasicProperties
    getRequestProperties() {
        return new BasicProperties
                .Builder()
                .replyTo(replyQueueName)
                .build();
    }

    public static String createRequest()
            throws JSONException {
        float epoch = System.currentTimeMillis()/1000;
        JSONObject object = new JSONObject();
        object.put("client_name","RPC Client 1.0");
        object.put("time",Float.toString(epoch));
        return JSON.toJSONString(object);
    }

    public static void main(String[] args) {
        Client client = null;
        String response = null;

        try {
            client = new Client();
            client.init().setupConsumer();
            response = client.call(Client.createRequest());
            System.out.println("RPC Reply --- " + response);
        }
        catch  (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (client!= null) {
                try {
                    client.close();
                }
                catch (Exception ignore) {}
            }
        }
    }
}



© 著作权归作者所有

共有 人打赏支持
你我他有个梦

你我他有个梦

粉丝 96
博文 110
码字总数 98858
作品 0
昌平
程序员
RabbitMQ erlang "hello world"

官方文档:http://www.rabbitmq.com/tutorials/tutorial-one-python.html 下文为翻译和erlang客户端的例子 RabbitMQ是一个消息中间件,它主要的思想非常简单:接收和发送消息。你可以把Rabbi...

nao
2015/07/24
0
0
php| 初探 rabbitmq

date: 2018-09-03 21:30:23 title: php| 初探 rabbitmq description: 零零散散折腾了 rabbitmq 几次, 归纳总结一下先 经常看到消息队列( MQ ), 实战中比较少, 说说我的一些粗线的理解: 引入消...

daydaygo
09/05
0
0
消息中间件—RabbitMQ(初探篇)

文章摘要:本篇文章为RabbitMQ的入门文章,不像其他一些程序代码和应用实战性的文章会带着大家从一个“Hello World”的简单例子出发,在该篇幅中主要给大家讲下RabbitMQ消息队列的起源、为何...

癫狂侠
05/23
0
0
RabbitMQ 实战教程(一) Hello World

原文出处:梁桂钊的博客 准备 本教程假定 RabbitMQ 已在标准端口(5672) 的 localhost 上安装并运行。如果使用不同的主机,端口或凭据,连接设置将需要调整。 介绍 RabbitMQ 是一个消息代理...

lianggui
09/29
0
0
RabbitMQ 入门 与 RabbitMQ 在 Spring Boot 中的使用

Message Broker与AMQP简介 Message Broker是一种消息验证、传输、路由的架构模式,其设计目标主要应用于下面这些场景: 消息路由到一个或多个目的地 消息转化为其他的表现方式 执行消息的聚集...

Anur
09/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

SharedPreferences 的使用,commit和apply两个方法的区别

SharedPreferences sp = getSharedPreferences("config",MODE_PRIVATE); //第一个参数:存储文件的名称,第二个参数文件的访问权限,通常MODE_PRIVATE是私有存储 sp.edit().putString("USERNAM...

lanyu96
11分钟前
1
0
02-《Apache Tomcat 9 User Guide》之简介

1.Introduction - 介绍 For administrators and web developers alike, there are some important bits of information you should familiarize yourself with before starting out. This d......

飞鱼说编程
15分钟前
1
0
关于maven的使用,这一篇基本就够了

2.1 关于maven 每一个工具的出现都有其历史意义,而Maven的出现则是开发者对于不同的项目都要有自己的Ant构建文件,而这些文件都各不相同,而且JAR被检入CVS(Concurrent Version System),...

小小明童鞋
17分钟前
13
0
从xtrabackup完整备份恢复单个innodb表

现在大多数同学在线上采取的备份策略都是xtrabackup全备+binlog备份,那么当某天某张表意外的删除那么如何从xtrabackup全备中恢复呢?从mysql 5.6版本开始,支持可移动表空间(Transportable...

IT--小哥
21分钟前
1
0
百度AI攻城狮,用TensorFlow API训练目标检测模型(浣熊超可爱)

今天,人工智能正影响我们生产、生活的方方面面。10月10日,为期三天的2018华为全联接大会在上海拉开帷幕,此次大会以“+智能,见未来”为主题,发布了AI战略及全球领先的全栈全场景AI解决方...

Python唱情歌
22分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部