java架構之路(MQ專題)kafka集群配置和簡單使用

前面我們說了RabbitMQ和RocketMQ的安裝和簡單的使用,這次我們說一下Kafka的安裝配置,後面我會用幾個真實案例來說一下MQ的真實使用場景。天冷了,不願意伸手,最近沒怎麼寫博客了,還請見諒。

一、目標

1.知道什麼是Kafka

2.懂得kafka的單機和集群安裝配置

3.了解內部參數的簡單配置

二、Kafka簡介

 

  Kafka是由Apache軟件基金會開發的一個開源流處理平台,由Scala和Java編寫。Kafka是一種高吞吐量的分佈式發布訂閱消息系統,它可以處理消費者在網站中的所有動作流數據。 這種動作(網頁瀏覽,搜索和其他用戶的行動)是在現代網絡上的許多社會功能的一個關鍵因素。 這些數據通常是由於吞吐量的要求而通過處理日誌和日誌聚合來解決。 對於像Hadoop一樣的日誌數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka的目的是通過Hadoop的并行加載機制來統一線上和離線的消息處理,也是為了通過集群來提供實時的消息。——百度百科

三、Kafka使用場景

  • 日誌收集:一個公司可以用Kafka可以收集各種服務的log,通過kafka以統一接口服務的方式開放給各種consumer,例如hadoop、Hbase、Solr等。
  • 消息系統:解耦和生產者和消費者、緩存消息等。
  • 用戶活動跟蹤:Kafka經常被用來記錄web用戶或者app用戶的各種活動,如瀏覽網頁、搜索、點擊等活動,這些活動信息被各個服務器發布到kafka的topic中,然後訂閱者通過訂閱這些topic來做實時的監控分析,或者裝載到hadoop、數據倉庫中做離線分析和挖掘。
  • 運營指標:Kafka也經常用來記錄運營監控數據。包括收集各種分佈式應用的數據,生產各種操作的集中反饋,比如報警和報告。

四、相關術語

  • Broker

Kafka集群包含一個或多個服務器,這種服務器被稱為broker

  • Topic

每條發布到Kafka集群的消息都有一個類別,這個類別被稱為Topic。

  • Partition

Partition是物理上的概念,每個Topic包含一個或多個Partition.

  • Producer

負責發布消息到Kafka broker

  • Consumer

消息消費者,向Kafka broker讀取消息的客戶端。

  • Consumer Group

每個Consumer屬於一個特定的Consumer Group(可為每個Consumer指定group name,若不指定group name則屬於默認的group)。

五、單機安裝

  1.安裝jdk,輸入yum install -y java-1.8.0-openjdk* 耐心等待即可,安裝完成以後,輸入$ java -version,檢查是否安裝成功。

  2.由於Kafka是基於Zookeeper環境的,我們安裝一下Zookeeper(不安裝也可以,最好配置一下,便於後期理解,建議安裝3.*版本)。我以前寫過Zookeeper的安裝過程,想看的可以去了解一下

  3.輸入wget https://archive.apache.org/dist/kafka/1.1.0/kafka_2.11-1.1.0.tgz 等待下載完成,Kafka現在是0.*,1.*,2.*三個版本,這裏建議使用1.*版本,你也可以下載最新的2.3.1版本,下載方式wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.3.1/kafka_2.12-2.3.1.tgz,這裏說一下,kafka_2.12-2.3.1.tgz前面的2.12是Scala語言版本,後面的2.3.1才是我們的Kafka的版本。官網地址:

4.解壓tar -zxvf kafka_2.11-1.1.0.tgz

5.進入到config目錄下,vim server.properties,我們在123行可以看到Zookeeper的配置如下(不是localhost的自己改一下)

 

6.啟動$ ./bin/kafka-server-start.sh -daemon config/server.properties

7.進入Zookeeper下查看節點信息。

輸入jps看到我們的進程kafka,單機配置成功。

六、集群安裝

  1.重複單機安裝步驟。

  2.修改配置文件,在21行broker.id設置為不同的数字,第一台可以設置0,第二台1,依次類推,在123行 zookeeper.connect寫入Zookeeper集群連接,例如zookeeper.connect=47.105.137.93:2181,114.215.145.41:2181,115.29.151.4:2181。

3.分別啟動三個Kafka。

4.測試集群,創建一個主題./bin/kafka-topics.sh –create –zookeeper  47.105.137.93:2181,114.215.145.41:2181,115.29.151.4:2181  –replication-factor 1 –partitions 1 –topic test

到其它服務器下查看現有主題即可。

七、簡單使用

  1.創建主題 ./bin/kafka-topics.sh –create –zookeeper IP:端口,IP:端口 –replication-factor 副本數 –partitions 分區數 –topic 主題名

   例如:./bin/kafka-topics.sh –create –zookeeper 47.105.137.93:2181,114.215.145.41:2181,115.29.151.4:2181 –replication-factor 1 –partitions 1 –topic xiaocaijishu

  2.查看現有主題 ./bin/kafka-topics.sh –list –zookeeper IP:端口,IP:端口

   例如:./bin/kafka-topics.sh –list –zookeeper 47.105.137.93:2181,114.215.145.41:2181,115.29.151.4:2181

  3.刪除主題 ./bin/kafka-topics.sh –delete –topic xiaocaijishu2 –zookeeper IP:端口,IP:端口

  例如:./bin/kafka-topics.sh –delete –topic xiaocaijishu2 –zookeeper 47.105.137.93:2181,114.215.145.41:2181,115.29.151.4:2181  

   4.發送消息 ./bin/kafka-console-producer.sh –broker-list Kafka服務器IP:9092 –topic 主題名

  例如:./bin/kafka-console-producer.sh –broker-list 47.105.137.93:9092 –topic xiaocaijishu

  5.消費消息./bin/kafka-console-consumer.sh –bootstrap-server Kafka服務器IP:9092 –consumer-property group.id=消費組名稱 –topic 主題名

  例如: ./bin/kafka-console-consumer.sh –bootstrap-server 47.105.137.93:9092 –consumer-property group.id=xiaocaiGroup –topic xiaocaijishu

  6.查看現有消費組 ./bin/kafka-consumer-groups.sh –bootstrap-server Kafka服務器IP:9092 –list

   例如:./bin/kafka-consumer-groups.sh –bootstrap-server 47.105.137.93:9092 –list

 

 

最進弄了一個公眾號,小菜技術,歡迎大家的加入

 

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道大胸女孩都會買什麼款式的內衣呢?d cup內衣,e cup內衣挑選完美致勝推薦

※濃郁的奶香牛軋糖-最好吃的伴手禮,送禮要送進心崁裡!

※專為各大企業長短期商務包車接送的服務

※來台東旅遊不可錯過的,台東必買名產 「池上米、地瓜酥、洛神花」都在”購夠台東“網路商城皆買的到哦!

※2020推薦婚禮錄影台北精選18家專業團隊

※票選台中最佳親子活動.情侶約會必住的一中街住宿,旅遊行程推薦!

※找尋專業廣告設計,價格公道大圖輸出,背板品質佳

《Java多線程面試題》系列-創建線程的三種方法及其區別

1. 創建線程的三種方法及其區別

1.1 繼承Thread類

首先,定義Thread類的子類並重寫run()方法:

package com.zwwhnly.springbootaction.javabase.thread;

public class MyFirstThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.printf("[MyFirstThread]輸出:%d,當前線程名稱:%s\n",
                    i, getName());
        }
    }
}

然後,創建該子類的實例並調用start()方法啟動線程:

package com.zwwhnly.springbootaction.javabase.thread;

public class ThreadTest {
    public static void main(String[] args) {
        System.out.println("主線程開始執行,當前線程名稱:" +
                Thread.currentThread().getName());

        Thread firstThread = new MyFirstThread();
        firstThread.start();

        System.out.println("主線程執行結束,當前線程名稱:" +
                Thread.currentThread().getName());
    }
}

運行結果如下所示:

主線程開始執行,當前線程名稱:main

主線程執行結束,當前線程名稱:main

[MyFirstThread]輸出:0,當前線程名稱:Thread-0

[MyFirstThread]輸出:1,當前線程名稱:Thread-0

[MyFirstThread]輸出:2,當前線程名稱:Thread-0

[MyFirstThread]輸出:3,當前線程名稱:Thread-0

[MyFirstThread]輸出:4,當前線程名稱:Thread-0

從運行結果可以看出以下2個問題:

  1. 程序中存在2個線程,分別為主線程main和自定義的線程Thread-0。
  2. 調用firstThread.start();,run()方法體中的代碼並沒有立即執行,而是異步執行的。

查看Thread類的源碼,可以發現Thread類實現了接口Runnable:

public class Thread implements Runnable {
    // 省略其它代碼
}

這裡是重點,面試常問!

1.2 實現Runnable接口(推薦)

首先,定義Runnable接口的實現類並實現run()方法:

package com.zwwhnly.springbootaction.javabase.thread;

public class MySecondThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.printf("[MySecondThread]輸出:%d,當前線程名稱:%s\n",
                    i, Thread.currentThread().getName());
        }
    }
}

然後,調用Thread類的構造函數創建Thread實例並調用start()方法啟動線程:

package com.zwwhnly.springbootaction.javabase.thread;

public class ThreadTest {
    public static void main(String[] args) {
        Runnable target = new MySecondThread();
        Thread secondThread = new Thread(target);
        secondThread.start();
    }
}

運行結果如下所示:

主線程開始執行,當前線程名稱:main

主線程執行結束,當前線程名稱:main

[MySecondThread]輸出:0,當前線程名稱:Thread-0

[MySecondThread]輸出:1,當前線程名稱:Thread-0

[MySecondThread]輸出:2,當前線程名稱:Thread-0

[MySecondThread]輸出:3,當前線程名稱:Thread-0

[MySecondThread]輸出:4,當前線程名稱:Thread-0

可以看出,使用這種方式和繼承Thread類的運行結果是一樣的。

1.3 實現Callable接口

首先,定義Callable接口的實現類並實現call()方法:

package com.zwwhnly.springbootaction.javabase.thread;

import java.util.Random;
import java.util.concurrent.Callable;

public class MyThirdThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        Thread.sleep(6 * 1000);
        return new Random().nextInt();
    }
}

然後,調用FutureTask類的構造函數創建FutureTask實例:

Callable<Integer> callable = new MyThirdThread();
FutureTask<Integer> futureTask = new FutureTask<>(callable);

最後,調用Thread類的構造函數創建Thread實例並調用start()方法啟動線程:

package com.zwwhnly.springbootaction.javabase.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadTest {
    public static void main(String[] args) {
        System.out.println("主線程開始執行,當前線程名稱:" +
                Thread.currentThread().getName());

        Callable<Integer> callable = new MyThirdThread();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();

        try {
            System.out.println("futureTask.isDone() return:" + futureTask.isDone());

            System.out.println(futureTask.get());

            System.out.println("futureTask.isDone() return:" + futureTask.isDone());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println("主線程執行結束,當前線程名稱:" +
                Thread.currentThread().getName());
    }
}

運行結果如下所示:

主線程開始執行,當前線程名稱:main

futureTask.isDone() return:false

-1193053528

futureTask.isDone() return:true

主線程執行結束,當前線程名稱:main

可以發現,使用Callable接口這種方式,我們可以通過futureTask.get()獲取到線程的執行結果,而之前的2種方式,都是沒有返回值的。

注意事項:調用futureTask.get()獲取線程的執行結果時,主線程會阻塞直到獲取到結果。

阻塞效果如下圖所示:

1.4 區別

以下是重點,面試常問!

  1. Java中,類僅支持單繼承,如果一個類繼承了Thread類,就無法再繼承其它類,因此,如果一個類既要繼承其它的類,又必須創建為一個線程,就可以使用實現Runable接口的方式。
  2. 使用實現Runable接口的方式創建的線程可以處理同一資源,實現資源的共享。
  3. 使用實現Callable接口的方式創建的線程,可以獲取到線程執行的返回值、是否執行完成等信息。

關於第2點,可以通過如下示例來理解。

假如我們總共有10張票(共享的資源),為了提升售票的效率,開了3個線程來售賣,代碼如下所示:

package com.zwwhnly.springbootaction.javabase.thread;

public class SaleTicketThread implements Runnable {
    private int quantity = 10;

    @Override
    public void run() {
        while (quantity > 0) {
            System.out.println(quantity-- + " is saled by " +
                    Thread.currentThread().getName());
        }
    }
}
public static void main(String[] args) {
    Runnable runnable = new SaleTicketThread();
    Thread saleTicketThread1 = new Thread(runnable);
    Thread saleTicketThread2 = new Thread(runnable);
    Thread saleTicketThread3 = new Thread(runnable);

    saleTicketThread1.start();
    saleTicketThread2.start();
    saleTicketThread3.start();
}

因為3個線程都是異步執行的,因此每次的運行結果可能是不一樣,以下列舉2次不同的運行結果。

第1次運行結果:

10 is saled by Thread-0

8 is saled by Thread-0

7 is saled by Thread-0

5 is saled by Thread-0

9 is saled by Thread-1

3 is saled by Thread-1

2 is saled by Thread-1

1 is saled by Thread-1

4 is saled by Thread-0

6 is saled by Thread-2

第2次運行結果:

10 is saled by Thread-0

9 is saled by Thread-0

8 is saled by Thread-0

7 is saled by Thread-0

6 is saled by Thread-0

5 is saled by Thread-0

3 is saled by Thread-0

2 is saled by Thread-0

4 is saled by Thread-2

1 is saled by Thread-1

如果將上面的SaleTicketThread修改成繼承Thread類的方式,就變成了3個線程各自擁有10張票,即變成了30張票,而不是3個線程共享10張票。

2. Thread類start()和run()的區別

2.1 示例

因為實現Runnable接口的優勢,基本上實現多線程都使用的是該種方式,所以我們將之前定義的MyFirstThread也修改為實現Runnable接口的方式:

package com.zwwhnly.springbootaction.javabase.thread;

public class MyFirstThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.printf("[MyFirstThread]輸出:%d,當前線程名稱:%s\n",
                    i, Thread.currentThread().getName());
        }
    }
}

然後仍然沿用之前定義的MyFirstThread、MySecondThread,我們先看下調用start()的效果:

package com.zwwhnly.springbootaction.javabase.thread;

public class ThreadTest {
    public static void main(String[] args) {

        System.out.println("主線程開始執行,當前線程名稱:" +
                Thread.currentThread().getName());

        Thread firstThread = new Thread(new MyFirstThread());

        Runnable target = new MySecondThread();
        Thread secondThread = new Thread(target);

        firstThread.start();
        secondThread.start();

        System.out.println("主線程執行結束,當前線程名稱:" +
                Thread.currentThread().getName());
    }
}

運行結果(注意:多次運行,結果可能不一樣):

主線程開始執行,當前線程名稱:main

[MyFirstThread]輸出:0,當前線程名稱:Thread-0

[MyFirstThread]輸出:1,當前線程名稱:Thread-0

[MySecondThread]輸出:0,當前線程名稱:Thread-1

主線程執行結束,當前線程名稱:main

[MySecondThread]輸出:1,當前線程名稱:Thread-1

[MySecondThread]輸出:2,當前線程名稱:Thread-1

[MySecondThread]輸出:3,當前線程名稱:Thread-1

[MySecondThread]輸出:4,當前線程名稱:Thread-1

[MyFirstThread]輸出:2,當前線程名稱:Thread-0

[MyFirstThread]輸出:3,當前線程名稱:Thread-0

[MyFirstThread]輸出:4,當前線程名稱:Thread-0

可以看出,調用start()方法后,程序中有3個線程,分別為主線程main、Thread-0、Thread-1,而且執行順序不是按順序執行的,存在不確定性。

然後將start()方法修改為run()方法,如下所示:

firstThread.run();
secondThread.run();

此時的運行結果如下所示(多次運行,結果是一樣的):

主線程開始執行,當前線程名稱:main

[MyFirstThread]輸出:0,當前線程名稱:main

[MyFirstThread]輸出:1,當前線程名稱:main

[MyFirstThread]輸出:2,當前線程名稱:main

[MyFirstThread]輸出:3,當前線程名稱:main

[MyFirstThread]輸出:4,當前線程名稱:main

[MySecondThread]輸出:0,當前線程名稱:main

[MySecondThread]輸出:1,當前線程名稱:main

[MySecondThread]輸出:2,當前線程名稱:main

[MySecondThread]輸出:3,當前線程名稱:main

[MySecondThread]輸出:4,當前線程名稱:main

主線程執行結束,當前線程名稱:main

可以看出,調用run()方法后,程序中只有一個主線程,自定義的2個線程並沒有啟動,而且執行順序也是按順序執行的。

1.2 總結

以下是重點,面試常問!

  • run()方法只是一個普通方法,調用之後程序會等待run()方法執行完畢,所以是串行執行,而不是并行執行。
  • start()方法會啟動一個線程,當線程得到CPU資源後會自動執行run()方法體中的內容,實現真正的併發執行。

3. Runnable和Callable的區別

在文章前面的章節中(1.2 實現Runnable接口 和1.3 實現Callable接口),我們了解了如何使用Runnable、Callable接口來創建線程,現在我們分別看下Runable和Callable接口的定義,其中,Runable接口的定義如下所示:

public interface Runnable {
    public abstract void run();
}

Callable接口的定義如下所示:

public interface Callable<V> {
    V call() throws Exception;
}

由此可以看出,Runnable和Callable的區別主要有以下幾點:

  1. Runable的執行方法是run(),Callable的執行方法是call()
  2. call()方法可以拋出異常,run()方法如果有異常只能在內部消化
  3. 實現Runnable接口的線程沒有返回值,實現Callable接口的線程能返回執行結果
  4. 實現Callable接口的線程,可以和FutureTask一起使用,獲取到線程是否完成、線程是否取消、線程執行結果,也可以取消線程的執行。

4. 源碼及參考

源碼地址:,歡迎下載。

如果覺得文章寫的不錯,歡迎關注我的微信公眾號:「申城異鄉人」,所有博客會同步更新。

如果有興趣,也可以添加我的微信:zwwhnly_002,一起交流和探討技術。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣受好評的【機場接送推薦】

※租車接送服務需要另外加價嗎?

※台東人氣名產、台東人氣伴手禮,熱門獨家商品,現貨供應中

※坐月子經驗談-新竹到府坐月子媽媽心得分享與交流

※給婚攝的迎娶婚禮錄影必拍清單,沒拍到您一定會後悔!

※旅遊不求人,帶你掌握小琉球民宿海景攻略

※各類招牌、海報、大圖輸出,急件製作施工!

Flutter之環境配置與項目搭建,React-Native windows環境搭建記錄,React Naive之macOs環境配置記錄(iOS Android)

Flutter之環境配置與項目搭建

一,介紹

1.1,

是一種 易於學習、 易於擴展、並且可以部署到 任何地方 的 應用 編程 語言。並且同時借鑒了Java和JavaScript。Dart在靜態語法方面和Java非常相似,如類型定義、函數聲明、泛型等,而在動態特性方面又和JavaScript很像,如函數式特性、異步支持等。

1.2,

是 Google推出並開源的移動應用開發框架,主打跨平台、高保真、高性能。開發者可以通過 Dart語言開發 App,一套代碼同時運行在 iOS 和 Android平台。 Flutter提供了豐富的組件、接口,開發者可以很快地為 Flutter添加 native擴展。同時 Flutter還使用 Native引擎渲染視圖。

二,開發環境配置

 2.1,安裝Flutter

第一步:配置鏡像

由於在國內訪問Flutter有時可能會受到限制,Flutter官方為中國開發者搭建了臨時鏡像,大家可以將如下環境變量加入到用戶環境變量中:

1 export PUB_HOSTED_URL=https://pub.flutter-io.cn
2 export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

如下圖所示:

第二步:獲取Flutter SDK

去flutter官網下載其最新可用的安裝包,下載地址: ,打開后如圖所示:

    1. 將安裝包zip解壓到你想安裝Flutter SDK的路徑(如:D:\flutter;注意,不要將flutter安裝到需要一些高權限的路徑如C:\Program Files\)。
    2. 在Flutter安裝目錄的flutter文件下找到flutter_console.bat,雙擊運行並啟動flutter命令行,接下來,你就可以在Flutter命令行運行flutter命令了。

第三步:配置環境變量

如果不配置環境變量,在全局環境中是無法使用flutter命令的,轉到 “控制面板>用戶帳戶>用戶帳戶>更改我的環境變量”,在Path下添加D:\flutter\bin條目,保存即可。

第四步:運行 flutter doctor命令

在Flutter命令行運行如下命令來查看是否還需要安裝其它依賴,如果需要,安裝它們:

1 flutter doctor

該命令檢查你的環境並在命令行窗口中显示報告。Dart SDK已經在打包在Flutter SDK里了,沒有必要單獨安裝Dart。安裝完成后再運行flutter doctor命令來驗證是否安裝成功。

 2.2,windows與mac本配置(模擬器)

windows下sdk與jdk配置,可參考

mac本下sdk與jdk配置,可參考

 2.3,編輯器配置

常用編輯器是VS Code,故此這兒主要介紹VS Code的配置,VS Code支持Flutter運行和調試。

安裝flutter插件

    1. 啟動 VS Code。
    2. 調用 View>Command Palette…。
    3. 輸入 ‘install’, 然後選擇 Extensions: Install Extension action。
    4. 在搜索框輸入 flutter ,在搜索結果列表中選擇 ‘Flutter’, 然後點擊 Install。
    5. 選擇 ‘OK’ 重新啟動 VS Code。
    6. 驗證配置
      • 調用 View>Command Palette…
      • 輸入 ‘doctor’, 然後選擇 ‘Flutter: Run Flutter Doctor’ action。
      • 查看“OUTPUT”窗口中的輸出是否有問題

創建Flutter應用

    1. 啟動 VS Code
    2. 調用 View>Command Palette…
    3. 輸入 ‘flutter’, 然後選擇 ‘Flutter: New Project’ action
    4. 輸入 Project 名稱 (如myapp), 然後按回車鍵
    5. 指定放置項目的位置,然後按藍色的確定按鈕
    6. 等待項目創建繼續,並显示main.dart文件

VS Code格式化dart代碼的快捷方式是shift+alt+f

三,項目搭建

第一步:創建Flutter應用

1 flutter create yingqi_flutter

 第二步:底部tab

 Flutter中的路由管理和原生開發類似,無論是Android還是iOS,導航管理都會維護一個路由棧,路由入棧(push)操作對應打開一個新頁面,路由出棧(pop)操作對應頁面關閉操作,而路由管理主要是指如何來管理路由棧。

1  final result =
2         await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
3       return LoginPage();
4     }));
1  Navigator.pop(context, "refresh");
  1 class AppHomeState extends State<AppHome> {
  2   final appBarTitles = ['首頁', '資訊', '產品', '我的'];
  3  
  4   ... 
  5 
  6   int _tabIndex = 0;
  7 
  8   var tabImages;
  9   var _body;
 10   var pages;
 11 
 12   Image getTabImage(path) {
 13     return Image.asset(path, width: 20.0, height: 20.0);
 14   }
 15 
 16   @override
 17   void initState() {
 18     super.initState();
 19 
 20    ...
 21 
 22     });
 23     pages = <Widget>[HomePage(), NewsPage(), ProductPage(), MyPage()];
 24     if (tabImages == null) {
 25       tabImages = [
 26         [
 27           getTabImage('images/ic_nav_news_normal.png'),
 28           getTabImage('images/ic_nav_news_actived.png')
 29         ],
 30         [
 31           getTabImage('images/ic_nav_tweet_normal.png'),
 32           getTabImage('images/ic_nav_tweet_actived.png')
 33         ],
 34         [
 35           getTabImage('images/ic_nav_discover_normal.png'),
 36           getTabImage('images/ic_nav_discover_actived.png')
 37         ],
 38         [
 39           getTabImage('images/ic_nav_my_normal.png'),
 40           getTabImage('images/ic_nav_my_pressed.png')
 41         ]
 42       ];
 43     }
 44   }
 45 
 46   TextStyle getTabTextStyle(int curIndex) {
 47     if (curIndex == _tabIndex) {
 48       return tabTextStyleSelected;
 49     }
 50     return tabTextStyleNormal;
 51   }
 52 
 53   Image getTabIcon(int curIndex) {
 54     if (curIndex == _tabIndex) {
 55       return tabImages[curIndex][1];
 56     }
 57     return tabImages[curIndex][0];
 58   }
 59 
 60   Text getTabTitle(int curIndex) {
 61     return Text(appBarTitles[curIndex], style: getTabTextStyle(curIndex));
 62   }
 63 
 64   @override
 65   Widget build(BuildContext context) {
 66     _body = IndexedStack(
 67       children: pages,
 68       index: _tabIndex,
 69     );
 70     return MaterialApp( 74       home: Scaffold( 80         body: _body,
 81         bottomNavigationBar: CupertinoTabBar(
 82           items: <BottomNavigationBarItem>[
 83             BottomNavigationBarItem(
 84                 icon: getTabIcon(0),
 85                 title: getTabTitle(0)),
 86             BottomNavigationBarItem(
 87                 icon: getTabIcon(1),
 88                 title: getTabTitle(1)),
 89             BottomNavigationBarItem(
 90                 icon: getTabIcon(2),
 91                 title: getTabTitle(2)),
 92             BottomNavigationBarItem(
 93                 icon: getTabIcon(3),
 94                 title: getTabTitle(3)),
 95           ],
 96           currentIndex: _tabIndex,
 97           onTap: (index) {
 98             setState((){
 99               _tabIndex = index;
100             });
101           },
102         ),
103       ),
104     );
105   }
106 }

 第三步:包管理與資源配置

Flutter項目默認的配置文件是pubspec.yaml,包與資源配置,均修改此文件

包配置如下圖所示:

    • dependencies:應用或包依賴的其它包或插件。
    • flutter:flutter相關的配置選項。

http: ^0.12.0就是項目中需要使用外部包配置,使用如下命令即可下載:

1 flutter packages get

資源配置如下圖所示:

 需要使用什麼資源,以圖片中的格式在assets下繼續添加即可。

 第四步:數據緩存

1,在pubspec.yaml文件中,添加如下包:

1   shared_preferences: ^0.4.3

2,數據記錄類

1 import 'package:shared_preferences/shared_preferences.dart';
2 import 'dart:async';
3 
4 class DataUtils {
5 
6 ...
7 
8 }

3,用戶登錄信息操作

 1   static const String SP_USER_NAME = "name";
 2   static const String SP_USER_ID = "userId";
 3   static const String SP_IS_LOGIN = "isLogin";
 4 
 5   // 保存用戶登錄信息,data中包含了token等信息
 6   static saveLoginInfo(Map data) async {
 7     if (data != null) {
 8       SharedPreferences sp = await SharedPreferences.getInstance();
 9       String userId = data['UserId'];
10       await sp.setString(SP_USER_ID, userId);
11       String name = data['Name'];
12       await sp.setString(SP_USER_NAME, name);
13       await sp.setBool(SP_IS_LOGIN, true);
14     }
15   }
16 
17   // 清除登錄信息
18   static clearLoginInfo() async {
19     SharedPreferences sp = await SharedPreferences.getInstance();
20     await sp.setString(SP_USER_ID, "");
21     await sp.setString(SP_USER_NAME, "");
22     await sp.setBool(SP_IS_LOGIN, false);
23   }
24 
25  // 獲取用戶登錄信息
26   static Future<LoginInfo> getLoginInfo() async {
27      SharedPreferences sp = await SharedPreferences.getInstance();
28     bool isLogin = sp.getBool(SP_IS_LOGIN);
29     if (isLogin == null || !isLogin) {
30       return null;
31     }
32     LoginInfo loginInfo = LoginInfo();
33     loginInfo.userId = sp.getString(SP_USER_ID);
34     loginInfo.name = sp.getString(SP_USER_NAME);
35     return loginInfo;
36   }

 下一章->

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※【推薦】婚攝外拍包車,可以租用外景車拍婚紗

※台東必買名產首選都在”購夠台東”

※南部專業嘉義到府坐月子,台南到府坐月子,高雄到府坐月子收費服務資訊懶人包

※棉花糖女孩穿搭g cup內衣,f 罩杯內衣零著感完美包覆

※婚禮影片不NG,婚禮錄影mv精彩重現讓賓客感動熱議

※小琉球民宿套裝行程帶你走遍最夯的行程,浮潛找海龜、知名打卡景點、人氣麻花捲,享受渡假樂趣

※找尋專業廣告設計,價格公道大圖輸出,背板品質佳

Chrome Extension 小試牛刀

 

自從有了Chrome以後,就喜歡上了這個瀏覽器,從此IE 886了。

以前作爬蟲,做登錄,做數據採集,做數據處理等各種功能,後來H5出來后,出現了,除了Session/Cookie 出了Local Storage,暫時還沒有更好的辦法獲取Local Storage。由於處理的數據比較少,所以決定研究一下Chrome Extension。

 

百度了一下Chrome Extension,可以通過Chrome Extension 官網進行學習,簡單上手。網址:

要解決的問題:

公司OA使用了很多年了,其中的流程備案記錄很少關注查看,今天公司通知最近要檢查,確認大家是否都看了,否則會進行處罰。今天要解決的問題就是自動把所有的未查看過的抄送記錄,都確認為已閱讀。

解決方案:

本來可以通過SQL語句,修改數據庫的是否閱讀狀態。這是最近單的方式,但是和Chrome Extension 就沒有關係了。

所以還是通過模擬的方式,通過點擊一個按鈕自動瀏覽本頁的所有標記為未讀的記錄。

操作記錄:

進入流程抄送記錄,點擊【自動瀏覽】開始操作。

 

 

 

 

點擊自動瀏覽后,會自動在該Chrome頁面上打開多個瀏覽器頁簽显示所有未讀的記錄

軟件開發中問題匯總:

怎麼使用Jquery

自動使用Juquery原來,對原生的js是越來越陌生了,寫Js第一件事就是下載一個Jquery用上。

 

 

 

 

在 manifest.json中配置對應的jquery路徑,然後在contentscript.js和background.js中就可以使用Jquery了。

Chrome Extension的圖標怎麼設置呢?

看到上面manifest.json中的icons屬性了嗎?設置上對應的圖標即可。注意大小。

點擊Chrome Extension圖標,展示的頁面

這是一個特別特別簡單的html頁面,只有一個按鈕,最後加了一個index.js的js文件,一定要引用到最後。Js文件主要是對該彈出頁進行操作。

這個插件只有一個動作,就是點擊上面的【自動瀏覽】按鈕。

 

 

點擊【自動瀏覽】按鈕的邏輯

點擊按鈕后,按鈕顏色編成藍色,如果有其他按鈕,則其他按鈕字體顏色為黑色,另外:點擊按鈕后,與當前網頁進行通訊,返回頁面上所有沒有瀏覽記錄的ID,並用【;】分割。

 

處理網頁數據的頁面邏輯

通過jquery查詢當前頁面中所有的未讀記錄,遍歷並把所有的id用【;】分割。

一定要有return true.

 

 

 

寫在最後:

剛開始結束的時候,經歷了各種坎坷,

 

 

由於是Chrome Extension與頁面的數據進行通訊,各種搞不定,現在基本可以通過這個模式化的界面與各種服務、http頁面等進行互操作了。

通過這次Chrome Extension的開發,不僅重新熟悉了各種js,而且最重要的是,以後簡單的爬蟲,再也不用打開vs,吭哧坑成的編程啦。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※全國票選五大台東必買、台東伴手禮最佳商品哪裡買的到?

※月子中心貴鬆鬆,找對到府月嫂省一半,更讓你事半功倍!!

※女孩困擾找不到『i cup內衣』?不必擔心專業內衣網購平台嚨底家

※機場接送服務包括:大陸機場接送以及桃園機場接送服務。

※最美的渡假聖地!享受無敵海景小琉球民宿推薦,旅遊達人,教你怎麼玩~

※嚴選台中火車站周邊熱鬧景點-台中一中住宿優惠!

※各類招牌、海報、大圖輸出,急件製作施工!

機器學習筆記(1) 感知機算法 之 實戰篇

我們在上篇筆記中介紹了感知機的,討論了感知機的由來、工作原理、求解策略、收斂性。這篇筆記中,我們親自動手寫代碼,使用感知機算法解決實際問題。

先從一個最簡單的問題開始,用感知機算法解決OR邏輯的分類。

import numpy as np
import matplotlib.pyplot as plt

x = [0,0,1,1]
y = [0,1,0,1]

plt.scatter(x[0],y[0], color="red",label="negative")
plt.scatter(x[1:],y[1:], color="green",label="positive")

plt.legend(loc="best")
plt.show()

下面我們來定義一個函數,用來判定一個樣本點是否被正確分類了。由於此例中樣本點是二維的,因此權重向量也相應的為二維,可以定義為\(w = (w_1, w_2)\),在Python中可以使用列表來表達,例如w = [0, 0],而樣本到超平面的距離自然就是w[0] * x[0] + w[1] * x[1] +b。下面給出完整的函數。

def decide(data,label,w,b):
    result = w[0] * data[0] + w[1] * data[1] - b
    print("result = ",result)
    if np.sign(result) * label <= 0:
        w[0] += 1 * (label - result) * data[0]
        w[1] += 1 * (label - result) * data[1]
        b += 1 * (label - result)*(-1)
    return w,b

寫完核心函數后,我們還需要寫一個調度函數,這個函數提供遍歷每一個樣本點的功能。

def run(data, label):
    w,b = [0,0],0
    for epoch in range(10):
        for item in zip(data, label):
            dataset,labelset = item[0],item[1]
            w,b = decide(dataset, labelset, w, b)
            print("dataset = ",dataset, ",", "w = ",w,",","b = ",b)
    print(w,b)
data = [(0,0),(0,1),(1,0),(1,1)]
label = [0,1,1,1]
run(data,label)
result =  0
dataset =  (0, 0) , w =  [0, 0] , b =  0
result =  0
dataset =  (0, 1) , w =  [0, 1] , b =  -1
result =  1
dataset =  (1, 0) , w =  [0, 1] , b =  -1
result =  2
dataset =  (1, 1) , w =  [0, 1] , b =  -1
result =  1
dataset =  (0, 0) , w =  [0, 1] , b =  0
result =  1
dataset =  (0, 1) , w =  [0, 1] , b =  0
result =  0
dataset =  (1, 0) , w =  [1, 1] , b =  -1
result =  3
dataset =  (1, 1) , w =  [1, 1] , b =  -1
result =  1
dataset =  (0, 0) , w =  [1, 1] , b =  0
result =  1
dataset =  (0, 1) , w =  [1, 1] , b =  0
result =  1
後面的迭代這裏省略不貼,參數穩定下來,算法已經收斂

下面看一個來自UCI的數據集:PIMA糖尿病數據集,例子來自《機器學習算法視角》第三章

import os
import pylab as pl
import numpy as np
import pandas as pd
os.chdir(r"DataSets\pima-indians-diabetes-database")
pima = np.loadtxt("pima.txt", delimiter=",", skiprows=1)
pima.shape
(768, 9)
indices0 = np.where(pima[:,8]==0)
indices1 = np.where(pima[:,8]==1)
pl.ion()
pl.plot(pima[indices0,0],pima[indices0,1],"go")
pl.plot(pima[indices1,0],pima[indices1,1],"rx")
pl.show()

數據預處理

1.將年齡離散化

pima[np.where(pima[:,7]<=30),7] = 1
pima[np.where((pima[:,7]>30) & (pima[:,7]<=40)),7] = 2
pima[np.where((pima[:,7]>40) & (pima[:,7]<=50)),7] = 3
pima[np.where((pima[:,7]>50) & (pima[:,7]<=60)),7] = 4
pima[np.where(pima[:,7]>60),7] = 5

2.將女性的懷孕次數大於8次的統一用8次代替

pima[np.where(pima[:,0]>8),0] = 8

3.將數據標準化處理

pima[:,:8] = pima[:,:8]-pima[:,:8].mean(axis=0)
pima[:,:8] = pima[:,:8]/pima[:,:8].var(axis=0)

4.切分訓練集和測試集

trainin = pima[::2,:8]
testin = pima[1::2,:8]
traintgt = pima[::2,8:9]
testtgt = pima[1::2,8:9]

定義模型

class Perceptron:
    def __init__(self, inputs, targets):
        # 設置網絡規模
        # 記錄輸入向量的維度,神經元的維度要和它相等
        if np.ndim(inputs) > 1:
            self.nIn = np.shape(inputs)[1]
        else:
            self.nIn = 1
        
        # 記錄目標向量的維度,神經元的個數要和它相等
        if np.ndim(targets) > 1:
            self.nOut = np.shape(targets)[1]
        else:
            self.nOut = 1
        
        # 記錄輸入向量的樣本個數
        self.nData = np.shape(inputs)[0]
        
        # 初始化網絡,這裏加1是為了包含偏置項
        self.weights = np.random.rand(self.nIn + 1, self.nOut) * 0.1 - 0.05
        
    def train(self, inputs, targets, eta, epoch):
        """訓練環節"""
        # 和前面處理偏置項同步地,這裏對輸入樣本加一項-1,與W0相匹配
        inputs = np.concatenate((inputs, -np.ones((self.nData,1))),axis=1)
        
        for n in range(epoch):
            self.activations = self.forward(inputs)
            self.weights -= eta * np.dot(np.transpose(inputs), self.activations - targets)
        return self.weights
    
    def forward(self, inputs):
        """神經網路前向傳播環節"""
        # 計算
        activations = np.dot(inputs, self.weights)
        # 判斷是否激活
        return np.where(activations>0, 1, 0)
    
    def confusion_matrix(self, inputs, targets):
        # 計算混淆矩陣
        inputs = np.concatenate((inputs, -np.ones((self.nData,1))),axis=1)
        outputs = np.dot(inputs, self.weights)
        nClasses = np.shape(targets)[1]
        
        if nClasses == 1:
            nClasses = 2
            outputs = np.where(outputs<0, 1, 0)
        else:
            outputs = np.argmax(outputs, 1)
            targets = np.argmax(targets, 1)
            
        cm = np.zeros((nClasses, nClasses))
        for i in range(nClasses):
            for j in range(nClasses):
                cm[i,j] = np.sum(np.where(outputs==i, 1,0) * np.where(targets==j, 1, 0))
        print(cm)
        print(np.trace(cm)/np.sum(cm))
print("Output after preprocessing of data")
p = Perceptron(trainin,traintgt)
p.train(trainin,traintgt,0.15,10000)
p.confusion_matrix(testin,testtgt)
Output after preprocessing of data
[[ 69.  86.]
 [182.  47.]]
0.3020833333333333

這個案例使用感知機訓練得到的結果比較糟糕,這裏只是作為展示算法的例子。

最後看一個使用感知機算法識別MNIST手寫数字的例子。代碼借鑒了Kaggle上的kernel。

step 1:首先導入所需的包,並且設置好數據所在路徑

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
train = pd.read_csv(r"DataSets\Digit_Recognizer\train.csv", engine="python")
test = pd.read_csv(r"DataSets\Digit_Recognizer\test.csv", engine="python")
print("Training set has {0[0]} rows and {0[1]} columns".format(train.shape))
print("Test set has {0[0]} rows and {0[1]} columns".format(test.shape))
Training set has 42000 rows and 785 columns
Test set has 28000 rows and 784 columns

step 2:數據預處理

  1. 創建label,它的size為 (42000, 1)
  2. 創建training set,size為(42000, 784)
  3. 創建weights,size為(10,784),這可能有點不好理解。我們知道,權重向量是描述神經元的,784是維度,表示一個輸入樣本有784維,相應的與它對接的神經元也要有784維。同時,要記住一個神經元只能輸出一個output,而在数字識別問題中,我們期待的是輸入一個樣本數據,能返回10個数字,然後依概率判斷這個樣本是哪個数字的可能性最大。所以,我們需要10個神經元,這就是(10,784)的來歷。
trainlabels = train.label
trainlabels.shape
(42000,)
traindata = np.asmatrix(train.loc[:,"pixel0":])
traindata.shape
(42000, 784)
weights = np.zeros((10,784))
weights.shape
(10, 784)

這裏可以先看一個樣本,找找感覺。注意原數據是壓縮成了784維的數組,我們需要將它變回28*28的圖片

# 從矩陣中隨便取一行
samplerow = traindata[123:124]
# 重新變成28*28
samplerow = np.reshape(samplerow, (28,28))
plt.imshow(samplerow, cmap="hot")

step 3:訓練

這裏我們對訓練數據集循環若干次,然後重點關注錯誤率曲線

# 先創建一個列表,用來記錄每一輪訓練的錯誤率
errors = []
epoch = 20

for epoch in range(epoch):
    err = 0
    # 對每一個樣本(亦矩陣中的每一行)
    for i, data in enumerate(traindata):
        # 創建一個列表,用來記錄每個神經元輸出的值
        output = []
        # 對每個神經元都做點乘操作,並記錄下輸出值
        for w in weights:
            output.append(np.dot(data, w))
        # 這裏簡單的取輸出值最大者為最有可能的
        guess = np.argmax(output)
        # 實際的值為標籤列表中對應項
        actual = trainlabels[i]
        
        # 如果估計值和實際值不同,則分類錯誤,需要更新權重向量
        if guess != actual:
            weights[guess] = weights[guess] - data
            weights[actual] = weights[actual] + data
            err += 1
    # 計算迭代完42000個樣本之後,錯誤率 = 錯誤次數/樣本個數
    errors.append(err/42000)
x = list(range(20))
plt.plot(x, errors)
[<matplotlib.lines.Line2D at 0x5955c50>]

從圖可以看出,達到15次迭代時,錯誤率已經有上升的趨勢了,開始過擬合了。

感知機是一個非常簡單的算法,以致於很難在真正的場景中使用感知機算法。這裏舉的3個例子,都旨在於動手寫代碼實現這個算法,找找感覺。稍有經驗的讀者想必會好奇:為什麼沒有使用Scikit-Learn這個包,這部分其實是筆者另有計劃,打算結合算法寫Scikit-Learn的源碼解讀筆記。當然,限於個人水平,不一定能解析到精髓,但勉力而為吧。下篇會寫Multi-Layer-Perceptron算法的原理,在那裡我們很容易看到,縱使是簡單的感知機,只要加一個隱層,就能大幅提升其分類能力。另外,也會抽空寫一篇感知機Sklearn源碼解讀的文章。有任何問題,歡迎大家留言討論。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※信用卡的機場接送服務好嗎?

※台北桃園機場接送,網友超推,CP值超高,安全,寬敞又舒適

※想知道台東名產人氣商品是什麼?想知道更多台東知名伴手禮有哪些?

※評選台東伴手禮推薦商品「釋迦 」是台東必買伴手禮之一

※離島好好玩!小琉球必吃美食、必玩景點、最優惠的小琉球民宿套裝行程詳細攻略!

※濃郁的奶香牛軋糖-最好吃的伴手禮,送禮要送進心崁裡!

※找尋專業廣告設計,價格公道大圖輸出,背板品質佳

“水城”威尼斯遇水災恐損失慘重 聖馬可廣場被淹

意大利“水城”威尼斯12日遭遇有記錄以來嚴重程度排第二的水災,市長路易吉·布魯尼亞羅有意宣布緊急狀態,說這場水災恐致慘重損失。

路透社報道,受暴雨和潮汐影響,威尼斯遭洪水侵襲,不少古老的廣場和街道遭水淹沒。當地官員說,12日22時50分,潮水最高水位達到187厘米,僅次於1966年創下的194厘米最高紀錄。

媒體報道,洪水淹沒聖馬可廣場,水深超過1米,鄰近的聖馬可大教堂沒能倖免。不過,不清楚教堂內部的損毀情況。

經由社交媒體發布的視頻显示,威尼斯市內一條主幹道上,洪水像河流一樣涌動;海浪拍打着停泊在岸邊的船隻,洪水漫過石頭鋪成的人行道。

市長布魯尼亞羅說,“187厘米潮水將(給威尼斯)留下不可磨滅的傷痕”。他在社交媒體“推特”發文:形勢嚴峻,我們請求(中央)政府出手相助,代價會很高,這是氣候變化的結果。

意大利多個地區近日經受暴雨襲擊,洪水大面積泛濫,尤其是南部地區。在2019年“歐洲文化之都”馬泰拉,著名的岩洞民居遭洪水淹沒。(陸愛華)

本站聲明:網站內容來源再生能源資訊網http://toptour.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道台北團體制服哪裡比較便宜嗎?

※專業台北團體服訂制、設計一條龍服務!

※住宿攻略懶人包,精選平價舒適一中街住宿,一中街民宿出遊的休息好去處!

※2020票選台東必買 最佳節慶送禮、年節伴手禮,釋迦禮盒,小農禮盒深受國人的青睞!

※各類招牌、海報、大圖輸出,急件製作施工!

法國中央盧瓦爾河谷大區來華推廣 促進中法兩國文旅合作

11月11日,法國中央盧瓦爾河谷大區代表團應中國人民對外友好協會之邀,來華訪問,並就中法兩國文化旅遊深入合作展開會談磋商。

法國盧瓦爾河谷(Val de Loire)於2000年11月30日以“鮮活文化景觀”之名入選聯合國教科文組織世界遺產名錄。這裏的文藝復興時期城堡群的密集呈現屬歐洲絕無僅有,這裏也是人類與環境和諧共存與發展的典範。

活動中,中央盧瓦爾河谷大區旅遊委員會總經理Marc Richet介紹了大區的文藝復興城堡群建築遺產和豐富的花園景觀、享譽世界的美酒、獨一無二的盧瓦爾河騎行攬勝路線,以及大區源遠流長的法式浪漫傳統。昂布瓦茲王家城堡總經理Jean-Louis Sureau和香波堡國家園林副總經理Frédéric Bouilleux分別展示了兩座城堡的卓越風采,及現代高科技手段Histopad 為参觀城堡帶來的創新浸入式觀感體驗。

另據了解,在即將到來的2020年“好味法蘭西”(Go?t de France/Good France)全球法國美食推廣活動中,中央盧瓦爾河谷大區還將領銜法國各地向全球推廣來自大區的優質食材和特色餐點。

本站聲明:網站內容來源再生能源資訊網http://toptour.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

※桃園結婚包套幫你量身打造,最懂待嫁女兒心!

※桃園機場接送24小時待命,專業推薦!

※婚禮影片不NG,婚禮錄影mv精彩重現讓賓客感動熱議

※台北桃園機場接送,網友超推,CP值超高,安全,寬敞又舒適

※新娘必看!桃園自助婚紗推薦名單

※住宿攻略懶人包,精選平價舒適一中街住宿,一中街民宿出遊的休息好去處!

日本天皇巡遊路線,有風景也有故事

今年因為日本新天皇即位,原定10月22日進行的新天皇接受國民祝福的遊行活動——“祝賀御列之儀”推遲到11月10日舉行。天皇400米長的巡遊車隊從皇宮出發,經過二重橋,向櫻田門進發,在兩個地方便於長時間看到車隊,一是青山大道,即赤坂警察署開始到青山一丁目車站之間的約1.3公里的直線道路,二是沒有樹木遮擋的皇居前廣場。車隊目的地是赤坂御所。這一路線與平成時代開啟時天皇的巡遊路線有所不同,避開了高速公路的高架橋下的道路,從而方便更多的民眾站在路邊觀看。

二重橋是指鋼鐵製造的正門鐵橋。正門(江戶城西面的丸大手門)平時是關閉的,只有天皇即位大典和天皇、皇后、皇太后大葬儀式等特別事宜時或外賓來訪時才使用。使用的順序為:皇居前廣場——正門石橋——正門——正門鐵橋——宮殿。裏面的鐵橋在江戶城的西丸下乘橋的位置,早年曾因護城河水深,舊橋較低,所以在橋上再搭一座橋,為上下兩層,所以叫“二重橋”。

鐵橋是明治21年(1888年)替換上去的,所以橋身不是兩層的。二重橋是日本最有歷史感和神秘感的橋樑。

前面的石橋在江戶城的西丸大手橋的位置,石橋是明治20年(1887年)建造的。由於構造為兩個石拱形造型,所以再三地被誤認為“二重橋”。還有一種說法是,“因為外面的石橋和裏面的鐵橋都建造在同一個壕溝上,所以叫二重橋”,這種說法也是錯的。

橋下有護城河,水平如鏡,楊柳依依,景色宜人,是遊客必到之地,它是名副其實的連接民間和皇宮的橋,被公認為皇宮最美之地。

皇居前廣場,又叫皇宮外苑,江戶時代,許多達官顯貴在這兒建私宅。到了明治時代,房屋被政府收回,成為明治政府的兵營。後來伊藤博文命令撤去一切多餘建築物,種上樹木,延續至今成了綠樹成蔭、寬闊宜人的廣場。1947年,皇居前廣場正式向民眾開放。如今,對日本人來說,來到皇居前廣場,就是到了離天皇最近的地方,每年春秋兩次皇宮對一般民眾開放,人們從廣場走過二重橋,進入皇宮。在宮殿前,萬眾歡呼,聆聽天皇的聲音。

皇居前廣場里有個和田倉噴水公園,旁邊還有個免費的休息處和一家時尚餐廳,是遊人休憩、就餐的好地方。廣場里還有一大片松樹林,鬱郁蔥蔥,生機勃發,是東京中心難得的綠色。

連接東京車站和皇居前廣場的是一條寬闊的大道。這條路叫“行幸道路”,天皇到地方巡視,需要乘火車,就先乘車通過這條道路到東京車站。道路兩邊有排列整齊的高大銀杏樹,到了秋天樹恭弘=叶 恭弘金黃,蔚為壯觀。

平日的清晨以及假日,在皇居前廣場可以看到很多跑步運動的人,他們圍繞皇宮慢跑。在東京的中心,有這麼一大片風景秀麗又大氣的公共空間,又能眺望日本皇宮,因此皇居前廣場成為觀光勝地,來自世界各地的遊客在這兒流連忘返。花2000日元,可乘坐馬車在皇宮周邊繞一圈,感受傳統和現代交錯的景緻。

巡遊車隊途經的國會議事堂是1936年建成的,是日本的政治中心,國會在這裏開會議事。建築物是左右對稱的,左邊是眾議院,右邊是參議院。近年,國會議事堂也開放讓民眾参觀,眾議院每日開放参觀,參議院是工作日開放,但是國會開會前一個小時到散會這一時間段是無法参觀的,可以在規定場所拍照,但是不能錄視頻。

本站聲明:網站內容來源再生能源資訊網http://toptour.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

※2020桃園婚紗攝影推薦一流團隊

※婚禮籌備好崩潰!該找婚攝還是婚錄?新人必備教戰守則

※月子中心貴鬆鬆,找對到府月嫂省一半,更讓你事半功倍!!

※台東人氣名產、台東人氣伴手禮,熱門獨家商品,現貨供應中

※新娘必看!桃園自助婚紗推薦名單

古國伊朗的“打開方式”超乎想象 安全與熱情才是伊朗旅遊主旋律

近日,應南方航空公司之邀,環球網旅遊頻道記者來到文明古國伊朗,探尋波斯文明的氣韻軒昂與浪漫文藝。親臨伊朗,記者發現,這座文明古國的“打開方式”與國人的傳統印象大相徑庭。

安全與熱情是赴伊朗旅遊的主旋律 對華免簽后赴伊旅遊中國遊客增長4倍

今年7月16日起,伊朗官方宣布給予持有中華人民共和國普通護照及港、澳特別行政區護照人員赴伊朗旅遊、觀光及商務訪問單方面免簽入境待遇,每次入境可以停留21天。

目前,伊朗只和少數國家互相免簽,如土耳其、敘利亞等,單方面對中國遊客免簽,是一種特殊對待。記者觀察到,此次出行,伊朗並沒有在護照上蓋簽證章或做任何標記,業內人士稱,這是為了避免遊客之後赴美國或以色列等國家受到限制。

“今年7月伊朗對華免簽后,中國遊客赴伊朗旅遊人數增長了4倍。” 從事導遊工作7年的伊朗導遊唐娜告訴記者:“業內有一種說法,只要一個客人在伊朗有愉快的旅程,就將有10個客人來到伊朗”。唐娜認為,得益於普通遊客社交平台上的照片分享與免簽政策的實施,會有越來越多的中國人選擇伊朗為出境游目的地國家。

與刻板印象中的戰亂頻發的景象截然相反,熱情與安全是伊朗旅遊環境的主旋律:記者在伊朗期間,多次親歷伊朗人主動要求同框合影。看見中國面孔,不少伊朗人會面帶善意地微笑甚至用標準的普通話向記者打招呼,並充滿驕傲地向記者介紹當地值得探尋的景區。

由於長期被西方制裁,加之西方媒體的“污名化”和“妖魔化”報道,人們很容易將伊朗與動蕩不安和“核武器”聯繫起來。事實上,根據國際SOS組織發布的2019年旅行風險地圖显示,伊朗境內大部分地區在旅行安全方面屬於“低危險度”。

隨着伊朗對華免簽政策的實施,無疑會有助於構建更加客觀公正的伊朗國家形象。“很多媒體會渲染伊朗是危險國家,但是真正來到伊朗的人都會切身感受到這裏的氛圍,普通遊客會把他們看到的真實的伊朗告訴更多人。”唐娜說。

旅行社醞釀伊朗出境游精品小團 伊朗中文導遊數量持續增加

伊朗副總統兼文化遺產、手工業與旅遊組織主席阿里·阿斯嘎爾·穆內森曾在接受媒體採訪時表示:希望未來四五年內能吸引100萬中國遊客來伊。據伊朗文化遺產、手工藝和旅遊組織統計,2018年3月20日至2019年3月20日,有780萬名外國遊客到訪伊朗,入伊遊客增長了52.5%,其中中國遊客不足10萬。分享中國出境游市場的紅利,是伊朗對中國公民開放免簽的一個重要考量。

記者從各大OTA平台了解到,目前,伊朗出境跟團游8~12天的產品大約在10000元至13000元不等。專門赴伊朗考察路線的旅行社業內人士范先生告訴記者:“此次考察伊朗的印象比預期要好很多,伊朗治安也不錯,因為對華免簽,以後赴伊朗旅遊人數必然會呈現大規模上升趨勢,未來旅行社將會推出更多伊朗的小團產品以吸引更多客戶。”

長期在伊朗工作的劉陽認為:“若持續吸引中國遊客赴伊朗旅遊,除卻免簽政策的實施外,伊朗還需在基礎設施和服務方面進行完善,例如增加中餐館數量、著名景點增加中文導航等。”

“伊朗出境游市場需要更多優質的中文導遊”,劉陽與唐娜不約而同地提到了伊朗中文導遊供不應求的問題。“伊朗的導遊更多是英文講解,領隊用中文翻譯給遊客。”唐娜認為,這種做法很難讓遊客深入了解伊朗的歷史文化與民俗風情。

7年前,伊朗基本沒有任何中文導遊,唐娜留學中國回到伊朗后,負責將英文導遊的解說翻譯給中文遊客。久而久之,唐娜覺得這是一份有趣的工作,於是自學了伊朗著名景區的歷史,成為了一名中文導遊。“我們要讓大家明白,中國遊客將越來越多,中文導遊是十分有必要的。”

如今,越來越多像唐娜一樣會漢語的伊朗歸國留學生正在擔負起中文導遊這一職責。

伊朗人文風情別具一格 中伊友好交流歷史淵源深厚

獨特的地理自然環境和燦爛的波斯文明,賦予了伊朗極為豐富的旅遊資源:伊朗共擁有22處世界文化遺產和2處世界自然遺產。此次伊朗之行,記者從德黑蘭出發,南行至卡尚、伊斯法罕、亞茲德、設拉子,北返至德黑蘭並翻越厄爾布爾士山抵達裏海海濱城市恰盧斯。一路走來,最大的感受是,伊朗旅遊資源極其豐富,人文風情別具一格。

恰如余秋雨在《千年一嘆》中所說:“伊朗土地的主調,有點蒼涼,有點神秘,也有點世俗,一切都被綜合成一種有待擺布的詩意。”這種詩意體現在伊朗境內遍布的無數一眼千年、風格迥異的清真寺內,瀰漫在樹木青蔥、噴泉林立的波斯花園中,也內嵌在金碧輝煌、富麗恢弘的老宅院里。精美絕倫的波斯波利斯建築遺址訴說著阿契美尼德王朝不可一世的鼎盛繁榮;亞茲德古城內拜火教的熊熊聖火延續1400年燃燒不息;酒入豪腸,“伊朗李白”海菲茲在故鄉設拉子吟誦着浪漫與雅緻;而更難能可貴的是,面紗下的波斯女性面龐清秀美麗,她們自信而獨立。

在伊朗首都德黑蘭,記者看到許多商店設有藏紅花專櫃,而伊朗正是全世界最大的藏紅花產地,品質最優的藏紅花一克約8至10美金,還不少中國遊客在網紅藏紅花冰淇淋店打卡留念;在德黑蘭地毯博物館,記者欣賞到無數精美的手工織造波斯地毯,眾所周知,波斯地毯製造工藝享譽世界,而千百年來波斯的工匠們在這一塊塊地毯中織造着波斯的輝煌歷史,也織入了波斯人複雜細膩的情感;在伊斯法罕的伊瑪目廣場四周是皇家大巴扎,各樣式的金銀器皿、琺琅銅胎工藝盤花瓶、手織地毯、駱駝骨細密畫應有盡有……

不僅如此,中伊兩國也有着深厚的友好交流歷史。早在西漢時期,中國使者張騫的副使就曾到訪伊朗;15世紀,中國明代鄭和7次率領龐大船隊遠洋航海,其中3次到達伊朗南部的霍爾木茲地區。在伊朗國家博物館內,記者看見了大量元青花赫然陳列在櫥窗中,而這正印證着中伊兩國古代的友好交流。

隨着“一帶一路”倡議的深入落實,中國和伊朗在政治、經濟和文化等多個領域的合作進一步得到加強,旅遊也將成為中伊兩國友好交流的新紐帶。“中國和伊朗都是文明古國,希望更多的中國人來到伊朗,我們有太多的歷史等待你來傾聽,我們有太多的風光等待你來觀賞。”伊朗人Ahmadi熱情且充滿自信地說。

本站聲明:網站內容來源再生能源資訊網http://toptour.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道真正好吃不黏牙的牛軋糖在哪嗎?

※全國票選五大台東必買、台東伴手禮最佳商品哪裡買的到?

※專業婚禮錄影團隊,用鏡頭記錄人生中值得紀念的一刻!

※婚禮大小事,新人分享高CP值桃園婚紗

※2020票選台東必買 最佳節慶送禮、年節伴手禮,釋迦禮盒,小農禮盒深受國人的青睞!

※桃園機場接送24小時待命,專業推薦!

“雙11”十年 外商也想分杯羹

據德國《商報》報道,去年“雙11”,中國的電商平台賺得盆滿缽滿。西方的著名購物節日望塵莫及。今年,中國人的狂熱購物數據有望再次實現突破。這表明,經濟放緩和貿易摩擦並沒有給中國普通消費者的購物慾造成負擔。報道還指出,許多德國製造商和經銷商尚未好好利用這個機會。

據美國零售媒體《連鎖時代》報道,中國的“雙11”購物節已經成為全球最大的消費盛會之一,美國的零售行業應該擁抱中國的“雙11”活動。報道指出,美國本土有大量了解“雙11”的中國遊客、學生和華人,也開始有更多的商家接入中國的移動支付。這意味着,美國本土有條件加入這一全世界的消費盛會。

2009年,中國電商平台將11月11日定義為“購物狂歡節”,進行打折促銷活動。由此,每年的11月11日成為中國消費者的網購福利日。近幾年,隨着“雙11”的規模與影響力不斷擴大,這一購物節開始得到越來越多外商的關注。

“雙11”購物節能夠發展到如此規模,是中國經濟發展水平不斷提升、中國作為世界第一製造業大國的地位和世界網絡大國的身份完美結合的產物。其中,建構在網絡技術之上的電商,更是在管理、物流、品牌建設等方面發揮了關鍵作用。

隨着“雙11”購物節的影響力不斷提升,越來越多外商開始投入大量精力備戰“雙11”,以期在這場消費盛會中分得一杯羹。中國市場的巨大潛力是“雙11”購物節吸引外商的重要因素。當今的中國市場具有以下特質:規模大,這源於近14億人口的需求;多層次,隨着人民收入水平不斷提高,國內消費不斷升級,消費也在向多層次快速演進;多元化,很多個性化、小眾化的產品銷售也不錯,為商戶的多樣化經營提供了巨大空間。

通過這幾年的發展,“雙11”購物節在中國經濟發展乃至國際貿易中承擔的角色也有了改變。以最近幾年的銷售規模看,“雙11”購物節在一定程度上能夠作為衡量國內消費結構、消費水平和前景預測的一個重要指標。同時,“雙11”購物節對於促進國際貿易尤其是中國的進口貿易具有积極作用,是一個極具價值的品牌。

10年來,“雙11”購物節的規模呈現出持續擴張的態勢。不過,正如經濟運行有周期,購物節體現出來的大眾消費熱潮也不可能無限擴張。因此,接下來,“雙11”購物節的擴張速度會有一定調整。隨着新技術的應用、網絡基礎設施的升級以及電商經營能力的提升,消費者購物的便利性和精準性還會提升。“雙11”作為不可替代的購物狂歡節,未來發展前景依然明朗。

為保證“雙11”購物節的影響力與效益,電商平台與政府都應採取一定措施。電商平台要避免惡性競爭,不能完全依賴低價,更不能虛構原價,採取先漲價后降價的方式進行虛假促銷。電商平台要從產品和服務的質量上下功夫,打造令消費者和商家信賴的平台,實現三方共贏。另外,電商平台也要积極承擔社會責任,做公益事業的積极參与者和樹立良好社會風氣的重要貢獻者。政府要做好監督和服務工作,保障電商平台合法經營,公平競爭,防止“劣幣驅逐良幣”,同時,保障消費者權益,讓消費者真正買到安全可靠、貨真價實的商品。

本站聲明:網站內容來源再生能源資訊網http://toptour.cn/,如有侵權請聯繫我們,我們將及時處理

【其他文章推薦】

※桃園機場租車可以要求甲租乙還服務?

※2020人氣涮嘴零食【牛軋糖】票選為最佳送禮熱賣商品

※省錢度蜜月!想知道哪裡可以找到最優惠的桃園婚紗工作室呢?

※台東人氣名產、台東人氣伴手禮,熱門獨家商品,現貨供應中

※“上班這黨事”節目推薦牛軋糖,辦公涮嘴零食NO.1