当前位置: 首页 > news >正文

上海企业网站怎么建设优化一个网站需要多少钱

上海企业网站怎么建设,优化一个网站需要多少钱,如何开发wap网站,东莞网页设计公司排名前言 RabbitMQ作为一款常用的消息中间件#xff0c;在微服务项目中得到大量应用#xff0c;其本身是微服务中的重点和难点#xff0c;有不少概念我自己的也是一知半解#xff0c;本系列博客尝试结合实际应用场景阐述RabbitMQ的应用#xff0c;分析其为什么使用#xff0… 前言 RabbitMQ作为一款常用的消息中间件在微服务项目中得到大量应用其本身是微服务中的重点和难点有不少概念我自己的也是一知半解本系列博客尝试结合实际应用场景阐述RabbitMQ的应用分析其为什么使用并给出怎么用的案例。 本篇博客结合场景来阐述RabbitMQ的几种模式描述了不同模式的应用场景并给出相应的代码。文末有惊喜~ 其他相关的rabbitmq博客文章列表如下 RabbitMQ基础1——生产者消费者模型 RabbitMQ简介 Docker版本的安装配置 RabbitMQ的helloworld 分模块构建 解决大量注册案例 RabbitMQ基础2——发布订阅/fanout模式 topic模式 rabbitmq回调确认 延迟队列死信设计 RabbitMQ的Docker版本安装 延迟插件安装 QQ邮箱和阿里云短信验证码的主题模式发送 目录 前言引出MQ场景1异步处理2解耦3削峰填谷常见的MQ 拆解控制台页面总览页面连接connection队列页面 简单模式工具类建立连接生产者生产消息消费者消费消息进行测试Ack项目中必须false 工作模式一个生产者两个消费者QOS: 限流Tips队列参数怎么变 队列相关参数x-max-lengthx-overflowx-max-length-bytes 发布者订阅模式生产者给fanout交换机发消息消费者1队列q32消费者2队列q321 路由模式生产者发给交换机告诉路由键消费者1根据路由键接收3种消息消费者2根据路由键接收1种消息 主题模式(Topic)生产者主题交换机带路由键消费者1通配符的路由键消费者2统配符 总结 引出 1.MQ消息队列的应用场景几种MQ简单对比 2.分析RabbitMQ的浏览器控制台页面 3.结合场景来阐述RabbitMQ的几种模式描述了不同模式的应用场景并给出相应的代码 MQ场景 Message Queue 消息队列。 有比较大的负载而且这些负载不用立刻马上给程序返回结构可以有一些等待时间。可以用消息队列。 1异步处理 过去的项目大部分都是同步解决问题。 UserinfoService{register(){//典型的同步//插入数据库//发短信//发邮件} } //如果你的操作基本没有任何延时操作或者瓶颈没有压力。那么你没有必要用MQ UserinfoService{register(){//发起的是一个异步请求都不等待对方给我返回的结果//异步插入数据库//异步发短信//异步发邮件} }2解耦 库存有没有可能挂了。或者访问量巨大。因为库存慢导致订单也慢。 解耦。 3削峰填谷 双12的时候叫好早上的8点。秒杀的时候。 有些瞬间服务器压力是超大的过了这个瞬间几乎没有消耗量。 等服务器能够正常的时候我慢慢执行就行了。 常见的MQ MQ的前身就是一个发布者订阅模式。 Kafka RabbitMQ1W/s RocketMQ ActiveMQ Kafka : 10w/S 主要用于日志。 Kafka是由Apache软件基金会开发的一个开源流处理平台由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统它可以处理消费者在网站中的所有动作流数据。 这种动作网页浏览搜索和其他用户的行动是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop一样的日志数据和离线分析系统但又要求实时处理的限制这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理也是为了通过集群来提供实时的消息。 拆解控制台页面 总览页面 包括刷新时间间隔rabbitmq节点连接端口的信息等 配置可以导出和导入 连接connection 队列页面 包括队列的名字状态准备好的消息数量未确认的消息数量总计消息数量 简单模式 使用的依赖 !-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --dependencygroupIdcom.rabbitmq/groupIdartifactIdamqp-client/artifactIdversion5.7.3/version/dependency工具类建立连接 package com.tianju.config;import com.rabbitmq.client.Connection;import java.io.IOException; import java.util.concurrent.TimeoutException;/*** 建立连接的工具类*/ public class ConnectionFactory {public static Connection createConnection() throws IOException, TimeoutException {com.rabbitmq.client.ConnectionFactory connectionFactory new com.rabbitmq.client.ConnectionFactory();connectionFactory.setHost(192.168.111.130); // http://192.168.111.130/connectionFactory.setPort(5672);connectionFactory.setUsername(admin);connectionFactory.setPassword(123);connectionFactory.setVirtualHost(/demo);// amqp://admin192.168.111.130:5672/return connectionFactory.newConnection();} } 生产者生产消息 package com.tianju.simple;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.tianju.config.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate;import java.io.IOException; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String QUEUE_ORDER queue_order;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列channel.queueDeclare(QUEUE_ORDER,false,false,false,null);// 发送消息指定给哪个队列上发消息for (int i 0; i 100; i) {String msg hello rabbitmq--i;channel.basicPublish(, QUEUE_ORDER, null, msg.getBytes());System.out.println(消息发布成功);}connection.close();} } 消费者消费消息 package com.tianju.simple;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer {private static String QUEUE_ORDER queue_order;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列channel.queueDeclare(QUEUE_ORDER,false,false,false,null);// 队列必须声明如果不存在则自动创建// 声明一个消费者DefaultConsumer defaultConsumer new DefaultConsumer(channel){/*** 回调函数用来接收消息* param consumerTag the iconsumer tag/i associated with the consumer* param envelope packaging data for the message* param properties content header data for the message* param body the message body (opaque, client-specific byte array)字节数组* throws IOException*/public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body); // 收到的信息System.out.println(消费者接收到msg);try {Thread.sleep(3000);// 模拟一个耗时操作} catch (InterruptedException e) {throw new RuntimeException(e);}}};// 表明自己是消费者接收消息/*** autoAck自动确认设置成 true*/channel.basicConsume(QUEUE_ORDER, true, defaultConsumer);} } 进行测试 生产者发送100条消息 消费者进行消费假设突然之间服务宕机了此时消费了4条消息理论上还应该有96条消息 打开控制台页面查看消息全部消失了出现了数据丢失的情况 全部用默认值的情况下如果发生异常则消息全部丢失。 消费者一次性拿到了所有的消息。 Ack项目中必须false 生产者 投递消息》队列 消费者接受》队列 ack: false 必须要手工确认。 消费者接到这个消息的时候 这个消息进入 unack状态。 1手工确认。消息删除。完成 2: 没手工确认断开连接或者超时。 3这个消息重新进入ready状态。等待其他消费者进行消费。 先设置自动ack为false表示需要手工确认然后在消费消息的方法中进行消息的确认。 package com.tianju.simple;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer {private static String QUEUE_ORDER queue_order;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列channel.queueDeclare(QUEUE_ORDER,false,false,false,null);// 队列必须声明如果不存在则自动创建// 声明一个消费者DefaultConsumer defaultConsumer new DefaultConsumer(channel){/*** 回调函数用来接收消息* param consumerTag the iconsumer tag/i associated with the consumer* param envelope packaging data for the message* param properties content header data for the message* param body the message body (opaque, client-specific byte array)字节数组* throws IOException*/public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException {// no work to doString msg new String(body); // 收到的信息System.out.println(消费者接收到msg);try {Thread.sleep(3000);// 模拟一个耗时操作} catch (InterruptedException e) {throw new RuntimeException(e);}// 消费者代码可能有失败消息拿到之后可能还没有处理就宕机了// 消息确认的代码一定在最后一行// long deliveryTag 消息的下标// boolean multiple 是否批量确认channel.basicAck(envelope.getDeliveryTag(),true); // 确认消息批量确认}};// 表明自己是消费者接收消息/*** autoAck自动确认设置成 true* 是否自动确认* false不进行自动确认true自动确认* 消费过程中可能产生异常* 如果产生异常则必须进行消费补偿*/channel.basicConsume(QUEUE_ORDER, false, defaultConsumer); // 接收消息} } 再次模拟宕机的情况一开始消息全部被放到Unack中当宕机时又把消息吐了出来至少消息没有出现丢失的情况。 工作模式 一个生产者两个消费者 两个消费者消费的是同一个队列中的消息。 两个消费者上来后默认是按照平均分配。结果 有人瞬间干完。有人很久都没干完。 QOS: 限流 可以限制你一次拉取几个。 这样两个消费者也能够节省服务器CPU了。 // 创建频道Channel channel connection.createChannel();channel.basicQos(1); /** 1次只能拿1个 **/当消费的速度太慢觉得不够加入其他的消费者。 核心只有一个消息队列。 消息是轮询的方式发送给不同的消费者。 Tips队列参数怎么变 队列的参数发生变化后要删除再添加。 // 创建频道Channel channel connection.createChannel();channel.queueDelete(QUEUE_ORDER); // 先删除旧的队列boolean durable true; // 当前队列中的消息持久化操作重启之后消息还在// 创建队列channel.queueDeclare(QUEUE_ORDER,durable,false,false,null);队列相关参数 x-max-length package com.tianju.work;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String QUEUE_ORDER queue_order;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();channel.queueDelete(QUEUE_ORDER); // 先删除旧的队列boolean durable true; // 当前队列中的消息持久化操作重启之后消息还在Map map new HashMap();map.put(x-max-length, 10); // 设置最大的长度只接受10个// 创建队列channel.queueDeclare(QUEUE_ORDER,durable,false,false,map);// 发送消息指定给哪个队列上发消息for (int i 0; i 1000; i) {String msg hello rabbitmq--i;channel.basicPublish(, QUEUE_ORDER, null, msg.getBytes());System.out.println(消息发布成功);}connection.close();} } How many (ready) messages a queue can contain before it starts to drop them from its head. x-overflow Sets the queue overflow behaviour. This determines what happens to messages when the maximum length of a queue is reached. Valid values are drop-head, reject-publish or reject-publish-dlx. The quorum queue type only supports drop-head and reject-publish. 此时就是前10个了 x-max-length-bytes package com.tianju.work;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String QUEUE_ORDER queue_order;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();channel.queueDelete(QUEUE_ORDER); // 先删除旧的队列boolean durable true; // 当前队列中的消息持久化操作重启之后消息还在Map map new HashMap();map.put(x-max-length, 10); // 设置最大的长度只接受10个map.put(x-overflow, reject-publish); // 拒绝发布变成前10gemap.put(x-max-length-bytes, 4); // 消息的最大字节长度// 创建队列channel.queueDeclare(QUEUE_ORDER,durable,false,false,map);// 发送消息指定给哪个队列上发消息for (int i 0; i 20; i) {String msg 53i;channel.basicPublish(, QUEUE_ORDER, null, msg.getBytes());msg hello rabbitmq--i;channel.basicPublish(, QUEUE_ORDER, null, msg.getBytes());System.out.println(消息发布成功);}connection.close();} } 参数 //创建队列boolean durable true;//当前队列中的消息进行持久化操作 重启之后消息还在Map map new HashMap();map.put(x-max-length,10);//设置队列的最大长度map.put(x-overflow,reject-publish);//设置队列的最大长度 drop headmap.put(x-max-length-bytes,4);//设置消息的最大字节长度 // map.put(x-expires,10000);//超时后直接删除队列channel.queueDeclare(QUQUENAME,durable,false,false,map);发布者订阅模式 工作模式中只有一个队列。两个消费者轮询从同一个队列中取数据。 发布者订阅模式 交换机后面会绑定多个消息队列。每个消息队列都有完整的信息。每个队列后的消费者都会有完整的消息。 交换机就是一个无意识的广播。行为就是扇出. 场景 下订单 1订单的数据入数据库 2发送订单的短信 3 物流 要每个队列都有完整的信息。 生产者给fanout交换机发消息 package com.tianju.publish;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String QUEUE_ORDER queue_order;private static String EXCHANGE pet_exchange;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建交换机channel.exchangeDeclare(EXCHANGE, fanout); // 扇出类型只能用这个for (int i 0; i 100; i) {channel.basicPublish(EXCHANGE, , MessageProperties.TEXT_PLAIN, (hello fanouti).getBytes());}} } 消费者1队列q32 package com.tianju.publish;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer {private static String EXCHANGE pet_exchange;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建交换机channel.exchangeDeclare(EXCHANGE, fanout); // 扇出类型只能用这个channel.queueDeclare(q32, false, false, false, null);channel.queueBind(q32, EXCHANGE, ); // 路由键fanout模式必须为空即使写了是无效的channel.basicConsume(q32, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(消费者1msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 消费者2队列q321 package com.tianju.publish;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer2 {private static String EXCHANGE pet_exchange;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建交换机channel.exchangeDeclare(EXCHANGE, fanout); // 扇出类型只能用这个channel.queueDeclare(q321, false, false, false, null);channel.queueBind(q321, EXCHANGE, ); // 路由键fanout模式必须为空即使写了是无效的channel.basicConsume(q321, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(消费者2msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 路由模式 允许用不同的路由键来接受不同的信息。 队列会接到完整的全部的信息。 日志系统 日志级别 OFF INFO DEBUG ERROR FATAL ALL 如果是致命错误 立刻给运维发短信。 全部信息 放到专门的日志系统 Error: 进行发邮件 生产者发给交换机告诉路由键 package com.tianju.routing;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建交换机channel.exchangeDeclare(EXCHANGE, direct); // 直接交换机String msg this is fatal message;channel.basicPublish(EXCHANGE,fatal, MessageProperties.TEXT_PLAIN,msg.getBytes());msg this is error message;channel.basicPublish(EXCHANGE,error, MessageProperties.TEXT_PLAIN,msg.getBytes());msg this is debug message;channel.basicPublish(EXCHANGE,debug, MessageProperties.TEXT_PLAIN,msg.getBytes());} } 消费者1根据路由键接收3种消息 package com.tianju.routing;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.Calendar; import java.util.concurrent.TimeoutException;public class Consumer {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列// 创建交换机channel.exchangeDeclare(EXCHANGE, direct); // 直接交换机// 队列必须声明如果不存在则自动创建channel.queueDeclare(q58, false, false, false, null);channel.queueBind(q58, EXCHANGE, fatal);channel.queueBind(q58, EXCHANGE, error);channel.queueBind(q58, EXCHANGE, debug);channel.basicConsume(q58, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(消费者1msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 消费者2根据路由键接收1种消息 package com.tianju.routing;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer2 {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列// 创建交换机channel.exchangeDeclare(EXCHANGE, direct); // 直接交换机// 队列必须声明如果不存在则自动创建channel.queueDeclare(q581, false, false, false, null);channel.queueBind(q581, EXCHANGE, fatal);channel.basicConsume(q581, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(消费者1msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 主题模式(Topic) 可以采取通配符模式 * (star) can substitute for exactly one word. # (hash) can substitute for zero or more words.#匹配0个或多个词 *匹配不多不少恰好1个词 举例 item.#能够匹配item.insert.abc 或者 item.insert item.*只能匹配item.insert 场景 京东 无锡河南下订单。退货 总部 收到这个订单 . 无锡分销商也有这个消息 *.wuxi 生产者主题交换机带路由键 package com.tianju.topic;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;/*** 生产者发送消息* 建立连接-- 创建频道 -- 创建队列 -- 发送消息*/ public class Provider {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建交换机channel.exchangeDeclare(EXCHANGE, topic); // 主题模式交换机String msg this is wuxi order;channel.basicPublish(EXCHANGE,order.wuxi, MessageProperties.TEXT_PLAIN,msg.getBytes());msg this is henan order;channel.basicPublish(EXCHANGE,order.henan, MessageProperties.TEXT_PLAIN,msg.getBytes());msg this is wuxi back;channel.basicPublish(EXCHANGE,back.wuxi, MessageProperties.TEXT_PLAIN,msg.getBytes());msg this is henan back;channel.basicPublish(EXCHANGE,back.henan, MessageProperties.TEXT_PLAIN,msg.getBytes());} } 消费者1通配符的路由键 package com.tianju.topic;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列// 创建交换机channel.exchangeDeclare(EXCHANGE, topic); // 主题交换机// 队列必须声明如果不存在则自动创建channel.queueDeclare(q58, false, false, false, null);channel.queueBind(q58, EXCHANGE, *.wuxi); // 意味着无锡的订单和退货都能收到channel.basicConsume(q58, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(无锡仓库msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 消费者2统配符 package com.tianju.topic;import com.rabbitmq.client.*; import com.tianju.config.ConnectionFactory;import java.io.IOException; import java.util.concurrent.TimeoutException;public class Consumer2 {private static String EXCHANGE exchange_58;public static void main(String[] args) throws IOException, TimeoutException {// 建立连接Connection connection ConnectionFactory.createConnection();// 创建频道Channel channel connection.createChannel();// 创建队列// 创建交换机channel.exchangeDeclare(EXCHANGE, topic); // 主题交换机// 队列必须声明如果不存在则自动创建channel.queueDeclare(q581, false, false, false, null);channel.queueBind(q581, EXCHANGE, *.*); // 意味着所有的订单和退货都能收到channel.basicConsume(q581, new DefaultConsumer(channel){public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throws IOException{// no work to doString msg new String(body);System.out.println(总部仓库msg);channel.basicAck(envelope.getDeliveryTag(), false);}});} } 总结 1.MQ消息队列的应用场景几种MQ简单对比 2.分析RabbitMQ的浏览器控制台页面 3.结合场景来阐述RabbitMQ的几种模式描述了不同模式的应用场景并给出相应的代码
http://www.zqtcl.cn/news/562386/

相关文章:

  • 手机销售培训网站wordpress案例插件
  • 滨江道做网站公司wordpress 花瓣网
  • 如何建网站快捷方式软件开发做平台
  • 常见的静态网页深圳罗湖企业网站优化
  • 做网站一天赚多少钱外贸网站建设排名
  • 一个大型网站建设得多少钱百度成都总部
  • 网站制作公司汉狮网络手机版网站优化
  • 铜川做网站logo 图标 设计
  • 如何做网站的注册页面南京宣传片公司有哪些
  • 中国建设机械教育协会网站网站建设中html中关于图片显示的标签有哪些
  • 网站过期后dede减肥网站源码
  • 营销型 手机网站网站建设方案后期服务
  • 怎么做一个个人网站建网站的八个步骤
  • 淘宝导购网站模版上海网站推广软件
  • 做影视网站引流湖北响应式网站建设费用
  • 网站统计cnzz网站空间有哪些
  • 泉州微信网站开发公司wordpress头像解决
  • 湛江网站建设皆选小罗24专业网站建设 福田
  • 厦门哪些做鲜花的网站门户网站开发设计报告
  • asp.net网站设计分工天津网站开发贴吧
  • 做多语言网站教程南宁vi设计公司
  • 百度联盟 网站备案wordpress 吾爱破解
  • 山西省建设厅网站首页网络营销推广为什么效果不好
  • 建材做网站好吗长沙做网站微联讯点不错
  • 建设小型网站分类门户网站系统
  • 文化馆网站数字化建设介绍138ip地址查询网站
  • 卖汽车的网站怎么做的建设服装网站的论文
  • 网络推广哪个网站好网站建设最低多少钱
  • 怎么在自己电脑做网站北京赛车网站开发
  • 门户网站内容wordpress上下页