2013中國新能源汽車及電動車展覽會

展會名稱:2013中國新能源汽車及電動車展覽會

展會時間:2013年3月19日-23日

展會地點:中國|北京展覽館

日程: 2013年3月21日-2013年3月23日 展期

主辦單位:中國低碳產業協會 、北京市電動車行業協會、北京市交通委員會、聯合國工業發展組織、國際太陽能技術轉讓中心、中國可再生能源行業協會、北京旺旅展覽展示有限公司

三、 費用明細Details of charges

標準展台(9平米): 7800元

豪華展位(18平米): 18000元

室內光地(36平米起):1000元/平米

室外光地(36平米起):500元/平米

技術交流及產品推介會——讓市場瞭解企業技術及產品的最佳途徑

收費標準:5000元/30分鐘;主辦單位提供場地(150-200人)。

注意:請參展企業於參展前一個月提供產品的相關信息,以供組委會參考並邀請相關專業嘉賓。

四、 參展範圍Exhibition Scope

綠色低碳交通車輛展區:

各類電動自行車、電動三輪車、燃油助力車及殘疾人專用電動車、電動滑板車等特種電動車、各類自行車、摺疊車、童車等

新能源車輛展區:

整 車:電動(混合動力)客車、電動(混合動力)公交車、電動(混合動力)轎車、電動旅遊觀光車、電動高爾夫車,電動吉普車、太陽能電動車、電動客貨車、電動清潔車、電動叉車、電動升降車;氫能源、天然氣等各種新能源、清潔燃料、混合動力車輛;各種低排放、環保節能型汽車

配套電池、配件、零部件和相關技術資料展區

1. 電動車電池及電池維護、電機、充電器、控制器、輪胎、塑殼及其它零配件和維修工具與設備,電動車及自行車用防盜鎖具、報警設備等;

2. 各種動力電池與管理系統:蓄電池,燃料電池及其他能源儲備系統;各種電池生產,檢測,維護設備等;各類廢舊電池回收及三廢處理設備、回收處理技術等;

3. 充電裝置;電機電控系統;儲能裝置等;能源管理系統;充(換)電站設備;充換電池及電池等能源管理系統;加油站擴建充(換)電站、新能源汽車充電技術項目解決方案、智能電網、太陽能、風能互補新能源汽車充電站技術產品;停車場充電設施;充電站(器)電源設備和基礎設施;

4. 電池修復儀等配套輔助產品、各種機械加工、流水線、檢測儀器製造設備和工具等配套設備;

5. 零部件:低排放節能型發動機、混合動力發動機及清潔燃料發動機;整車總線與控制系統;電機電控系統;電力電容器、飛輪、逆變器、電熱泵、電動助力轉向、電動空調、功率模塊、相關檢測、計量、模具設備等。

6. 相關行業媒體軟件出版、培訓、諮詢、施工技術及其他相關材料、工藝、技術等;

特種車輛展區:清障車、環保車輛、改裝車輛等。

五、 組委會聯繫方式/Contact Information

聯繫地址:北京市德外大街西三旗東路金燕龍辦公樓東樓309室

聯繫電話:010-56105081,13366745071

聯繫人:李菲菲,李主任 13341032258

聯繫傳真:010-52214567-7

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

Elasticsearch系列—生產集群的索引管理

概要

索引是我們使用Elasticsearch里最頻繁的部分日常的操作都與索引有關,本篇從運維人員的視角,來玩一玩Elasticsearch的索引操作。

基本操作

在運維童鞋的視角里,索引的日常操作除了CRUD,還是打開關閉、壓縮、alias重置,我們來了解一下。

創建索引

[esuser@elasticsearch02 ~]$curl -XPUT 'http://elasticsearch02:9200/music?pretty' -H 'Content-Type: application/json' -d '
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    },
    "mappings" : {
        "type1" : {
            "properties" : {
                "name" : { "type" : "text" }
            }
        }
    }
}'

{
    "acknowledged": true,
    "shards_acknowledged": true
}

默認情況下,索引創建命令會在每個primary shard的replica shard 開始進行複製后,或者是請求超時之後,返迴響應消息,如上。

acknowledged表示這個索引是否創建成功,shards_acknowledged表明了每個primary shard有沒有足夠數量的replica開始進行複製。

可能這兩個參數會為false,但是索引依然可以創建成功。因為這些參數僅僅是表明在請求超時之前,這兩個操作有沒有成功,也有可能請求超時了,在超時前都沒成功,但是實際上Elasticsearch Server端接收到了消息,並且都執行了,只是響應前還沒來得及執行,所以響應的是false。

刪除索引

curl -XDELETE 'http://elasticsearch02:9200/music?pretty'

查詢索引設置信息

curl -XGET 'http://elasticsearch02:9200/music?pretty'

打開/關閉索引

curl -XPOST 'http://elasticsearch02:9200/music/_close?pretty'
curl -XPOST 'http://elasticsearch02:9200/music/_open?pretty'

如果一個索引關閉了,那麼這個索引就沒有任何的性能開銷了,只要保留這個索引的元數據即可,然後對這個索引的讀寫操作都不會成功。一個關閉的索引可以接着再打開,打開以後會進行shard recovery過程。

如果集群數據定時有備份,在執行恢復的操作之前,必須將待恢復的索引關閉,否則恢復會報失敗。

壓縮索引

我們知道索引的primary shard數量在創建時一旦指定,後期就不能修改了,但是有一個這樣的情況:預估的shard數量在實際生產之後,發現估算得有點高,比如原來設置number_of_shards為8,結果生產上線后發現數據量沒那麼大,我想把這個索引的primary shard壓縮一下,該如何操作呢?

shrink命令的作用就是對索引進行壓縮的,不過有個限制:壓縮后的shard數量必須可以被原來的shard數量整除。如我們的8個primary shard的index可以只能被壓縮成4個,2個,或者1個primary shard的index。

shrink命令的工作流程:
  1. 創建一個跟source index的定義一樣的target index,但是唯一的變化就是primary shard變成了指定的數量。
  2. 將source index的segment file直接用hard-link的方式連接到target index的segment file,如果操作系統不支持hard-link,那麼就會將source index的segment file都拷貝到target index的data dir中,會很耗時。如果用hard-link會很快。
  3. target index進行shard recovery恢復。
案例演示
  1. 我們創建一個number_of_shards為8的索引,名稱為music8
curl -XPUT 'http://elasticsearch02:9200/music8?pretty' -H 'Content-Type: application/json' -d '
{
    "settings" : {
        "index" : {
            "number_of_shards" : 8, 
            "number_of_replicas" : 2 
        }
    },
    "mappings" : {
        "children" : {
            "properties" : {
                "name" : { "type" : "text" }
            }
        }
    }
}'
  1. 在索引內灌點數據進去
  2. 將索引的shard都移到一個node上去,如node1
curl -XPUT 'http://elasticsearch02:9200/music8/_settings?pretty' -H 'Content-Type: application/json' -d '
{
  "settings": {
    "index.routing.allocation.require._name": "node-1", 
    "index.blocks.write": true 
  }
}'

這個過程叫shard copy relocate,使用

`curl -XGET ‘http://elasticsearch02:9200/_cat/recovery?v’

可以查看該過程的進度。

  1. 執行shrink命令,新的索引名稱為music9
curl -XPOST 'http://elasticsearch02:9200/music8/_shrink/music9?pretty' -H 'Content-Type: application/json' -d '
{
  "settings": {
	"index.number_of_shards": 2, 
    "index.number_of_replicas": 1,
    "index.codec": "best_compression" 
  }
}'

執行完成后,可以看到music9的shard數據變化了,並且擁有music8所有的數據。

  1. 將別名指向新的music9索引,客戶端訪問無感知。

rollover索引

我們最常見的日誌索引,需要每天創建一個新的帶日期的索引,但客戶端又使用同一個alias進行寫入,此時可以用rollover命令將alias重置到這個新的索引上。

假設log_write別名已經存在,示例命令:

curl -XPOST 'http://elasticsearch02:9200/log_write/_rollover/log-20120122
-H 'Content-Type: application/json' -d '
{
  "conditions": {
    "max_age":   "1d"
  }
}'

用crontab定時每天執行一次,並且將日期部分用shell腳本進行參數化,這樣每天都創建一個帶日期的索引名字,而客戶端那邊一直使用log_write別名作寫入操作,對日誌系統非常實用。

索引mapping管理

索引的mapping管理是非常基礎的操作,我們可以在創建索引時定義mapping信息,也可以在索引創建成功后執行增加字段操作。

列舉以下幾個常用示例:

查看索引的mapping信息

curl -XGET 'http://elasticsearch02:9200/music/_mapping/children?pretty'

查看索引指定field的mapping信息

curl -XGET 'http://elasticsearch02:9200/music/_mapping/children/field/content?pretty'

創建索引時帶上mapping信息

# 節省篇幅,省略大部分字段
curl -XPUT 'http://elasticsearch02:9200/music?pretty' -H 'Content-Type: application/json' -d ' 
{
  "mappings": {
    "children": {
      "properties": {
        "content": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
		}
      }
    }
  }
}'

為索引增加一個字段name,類型為text

curl -XPUT 'http://elasticsearch02:9200/music/_mapping/children?pretty' -H 'Content-Type: application/json' -d ' 
{
  "properties": {
    "name": {
      "type": "text"
    }
  }
}'

索引別名

客戶端訪問Elasticsearch的索引時,規範化操作都不會直接使用索引名稱,而是使用索引別名,索引別名能夠起到封裝Elasticsearch真實索引的作用,像上面的rollover操作,索引重建操作,別名起到了非常關鍵的作用。

我們來簡單看一下索引的基本操作:

# 創建索引別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
    "actions" : [
        { "add" : { "index" : "music", "alias" : "music_prd" } }
    ]
}'
# 刪除索引別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
    "actions" : [
        { "remove" : { "index" : "music", "alias" : "music_prd" } }
    ]
}'
# 重命名別名:先刪掉后添加
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
    "actions" : [
        { "remove" : { "index" : "music", "alias" : "music_prd" } },
        { "add" : { "index" : "music2", "alias" : "music_prd" } }
    ]
}'
# 多個索引綁定一個別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
    "actions" : [
        { "add" : { "indices" : ["music1", "music2"], "alias" : "music_prd" } }
    ]
}'

索引setting修改

查看索引setting信息:

curl -XGET 'http://elasticsearch02:9200/music/_settings?pretty'

修改setting信息:

curl -XPUT 'http://elasticsearch02:9200/music/_settings?pretty' -H 'Content-Type: application/json' -d '
{
    "index" : {
        "number_of_replicas" : 1
    }
}'

setting最常見的修改項就是replicas的數量,其他的參數修改的場景不是特別多。

索引template

假設我們正在設計日誌系統的索引結構,日誌數據量較大,可能每天創建一個新的索引,索引名稱按日期標記,但別名是同一個,這種場景就比較適合使用index template。

我們舉個示例,先創建一個索引模板:

curl -XPUT 'http://elasticsearch02:9200/_template/template_access_log?pretty' -H 'Content-Type: application/json' -d '
{
  "template": "access-log-*",
  "settings": {
    "number_of_shards": 2
  },
  "mappings": {
    "log": {
      "_source": {
        "enabled": false
      },
      "properties": {
        "host_name": {
          "type": "keyword"
        },
		"thread_name": {
          "type": "keyword"
        },
        "created_at": {
          "type": "date",
          "format": "YYYY-MM-dd HH:mm:ss"
        }
      }
    }
  },
  "aliases" : {
      "access-log" : {}
  }
}'

索引名稱符合”access-log-*”將使用該模板,我們創建一個索引:

curl -XPUT 'http://elasticsearch02:9200/access-log-01?pretty'

查看該索引:

curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'

可以看到如下結構:

[esuser@elasticsearch02 bin]$ curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'
{
  "access-log-01" : {
    "aliases" : {
      "access-log" : { }
    },
    "mappings" : {
      "log" : {
        "_source" : {
          "enabled" : false
        },
        "properties" : {
          "created_at" : {
            "type" : "date",
            "format" : "YYYY-MM-dd HH:mm:ss"
          },
          "host_name" : {
            "type" : "keyword"
          },
          "thread_name" : {
            "type" : "keyword"
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1581373546223",
        "number_of_shards" : "2",
        "number_of_replicas" : "1",
        "uuid" : "N8AHh3wITg-Zh4T6umCS2Q",
        "version" : {
          "created" : "6030199"
        },
        "provided_name" : "access-log-01"
      }
    }
  }
}

說明使用了模板的內容。

當然也有命令可以查看和刪除template:

curl -XGET 'http://elasticsearch02:9200/_template/template_access_log?pretty'

curl -XDELETE 'http://elasticsearch02:9200/_template/template_access_log?pretty'

索引常用查詢

索引操作統計查詢

發生在索引上的所有CRUD操作,Elasticsearch都是會做統計的,而且統計的內容非常翔實,我們可以使用這條命令:

curl -XGET 'http://elasticsearch02:9200/music/_stats?pretty'

內容非常詳細,有好幾百行,從doc的數據和佔用的磁盤字節數,到get、search、merge、translog等底層數據應有盡有。

segment信息查詢

索引下的segment信息,可以使用這條命令進行查詢:

curl -XGET 'http://elasticsearch02:9200/music/_segments?pretty'

內容也同樣挺多,我們摘抄出關鍵的部分做個示例:

"segments" : {
  "_1" : {
    "generation" : 1,
    "num_docs" : 1,
    "deleted_docs" : 0,
    "size_in_bytes" : 7013,
    "memory_in_bytes" : 3823,
    "committed" : true,
    "search" : true,
    "version" : "7.3.1",
    "compound" : true,
    "attributes" : {
      "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
    }
  }
}

這個片段表示名稱為_1的segment的信息。詳細如下:

  • _1:segment的名稱
  • generation:segment的自增長ID
  • num_docs:segment中沒有被刪除的document的數量
  • deleted_docs:segment中被刪除的document數量
  • size_in_bytes:segment佔用的磁盤空間
  • memory_in_bytes:segment會將一些數據緩存在內存中,這個數值就是segment佔用的內存的空間大小
  • committed:segment是否被sync到磁盤上去了
  • search:segment是否可被搜索,如果這個segment已經被sync到磁盤上,但是還沒有進行refresh,值為false
  • version:lucene的版本號
  • compound:true表示lucene已將這個segment所有的文件都merge成了一個文件
shard存儲信息

查看索引下shard的存儲情況,分佈在哪個node上,這條命令還是挺有用處的:

curl -XGET 'http://elasticsearch02:9200/music/_shard_stores?status=green&pretty'

摘抄了一個片段,3表示shard的id:

"3" : {
  "stores" : [
    {
      "A1s1uus7TpuDSiT4xFLOoQ" : {
        "name" : "node-2",
        "ephemeral_id" : "Q3uoxLeJRnWQrw3E2nOq-Q",
        "transport_address" : "192.168.17.137:9300",
        "attributes" : {
          "ml.machine_memory" : "3954196480",
          "rack" : "r1",
          "xpack.installed" : "true",
          "ml.max_open_jobs" : "20",
          "ml.enabled" : "true"
        }
      },
      "allocation_id" : "o-t-AwGZRrWTflYLP030jA",
      "allocation" : "primary"
    },
    {
      "RGw1IXzZR4CeZh9FUrGHDw" : {
        "name" : "node-1",
        "ephemeral_id" : "B1pv6c4TRuu1vQNvL40iPg",
        "transport_address" : "192.168.17.138:9300",
        "attributes" : {
          "ml.machine_memory" : "3954184192",
          "rack" : "r1",
          "ml.max_open_jobs" : "20",
          "xpack.installed" : "true",
          "ml.enabled" : "true"
        }
      },
      "allocation_id" : "SaXqL8igRUmLAoBBQyQNqw",
      "allocation" : "replica"
    }
  ]
},
補充幾個操作
  1. 清空索引緩存

curl -XPOST 'http://elasticsearch02:9200/music/_cache/clear?pretty'

  1. 強制flush

強行將os cache里的數據強制fsync到磁盤上去,同時還會清理掉translog中的日誌

curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'

  1. refresh操作

顯式地刷新索引,讓在自動refresh前的所有操作變成可見

curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'

  1. force merge

強制合併segment file,可以減小segment的數量
curl -XPOST 'http://elasticsearch02:9200/music/_forcemerge?pretty'

以上4個操作,一般是由Elasticsearch自動去執行,非特殊情況下不需要人工干預。

小結

本篇從運維角度簡單介紹了一下索引的一些日常操作與管理,能夠熟練應用的話,可以提升操縱索引的效率。

專註Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公眾號:Java架構社區
可以掃左邊二維碼添加好友,邀請你加入Java架構社區微信群共同探討技術

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

三文搞懂學會Docker容器技術(中)

接着上面一篇:三文搞懂學會Docker容器技術(上)

6,Docker容器

  6.1 創建並啟動容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG…]

–name=”容器新名字”:為容器指定一個名稱;

-i:以交互模式運行容器,通常與-t或者-d同時使用;

-t:為容器重新分配一個偽輸入終端,通常與-i同時使用;

-d: 後台運行容器,並返回容器ID;

-P: 隨機端口映射,容器內部端口隨機映射到主機的端口

-p: 指定端口映射,格式為:主機(宿主)端口:容器端口

 啟動普通容器: docker run –name 別名 鏡像ID  

 啟動交互式容器:  docker run -it –name 別名 鏡像ID   來運行一個容器,取別名,交互模式運行,以及分配一個偽終端

 守護式方式創建並啟動容器

 docker run -di –name 別名 鏡像ID 

執行完命令后,終端依然再宿主機上;

 

啟動容器,並執行/bin/bash命令;

 docker run -it –name 別名 鏡像ID  /bin/bash命令

端口映射;

docker run -it -p 8888:8080 tomcat

docker run -it -P tomcat

  6.2 列出容器

docker ps [OPTIONS]

OPTIONS說明:

-a :显示所有的容器,包括未運行的。

-f :根據條件過濾显示的內容。

–format :指定返回值的模板文件。

-l :显示最近創建的容器。

-n :列出最近創建的n個容器。

–no-trunc :不截斷輸出。

-q :靜默模式,只显示容器編號。

-s :显示總的文件大小。

docker ps 查看正在運行的容器

docker ps -a 查看所有容器

docker ps -n 2  显示最近創建的2個容器

docker ps -f status=exited 查看停止的容器

  6.3 退出容器

exit 容器停止退出

ctrl+P+Q 容器不停止退出

  6.4 進入容器

docker attach 容器ID or 容器名 

  6.5 啟動容器

docker start 容器ID or 容器名

  6.6 重啟容器

docker restart 容器ID or 容器名

  6.7 停止容器

docker stop 容器ID or 容器名

暴力刪除,直接殺掉進程 (不推薦)

docker kill 容器ID or 容器名

  6.8 刪除容器

docker rm 容器ID  

如果刪除正在運行的容器,會報錯,我們假如需要刪除的話,需要強制刪除;

強制刪除docker rm -f 容器ID

刪除多個容器 

docker rm -f 容器ID1  容器ID2 中間空格隔開

刪除所有容器

docker rm -f $(docker ps -qa)

  6.9 宿主機和容器之間文件拷貝

宿主機文件 copy to 容器內

docker cp 需要拷貝的文件或者目錄   容器名稱:容器目錄

容器內 copy to 宿主機

docker cp 容器名稱:容器目錄    宿主機目錄

  6.10 查看容器日誌

$ docker logs [OPTIONS] CONTAINER

  Options:

        –details        显示更多的信息

    -f, –follow         跟蹤實時日誌

        –since string   显示自某個timestamp之後的日誌,或相對時間,如42m(即42分鐘)

        –tail string    從日誌末尾显示多少行日誌, 默認是all

    -t, –timestamps     显示時間戳

        –until string   显示自某個timestamp之前的日誌,或相對時間,如42m(即42分鐘)

(以上了解)

 

鋒哥推薦,簡單粗糙方式,直接去docker容器文件里找;

具體未知:/var/lib/docker/containers/

每個容器對應一堆文件,然後有個log結尾的,就是日誌文件;

我們打開;

很直觀 假如時間長了 日誌文件很大,直接自己操刀處理即可;

  6.11 查看容器進程

docker top 容器ID

 

  6.12 進入容器執行命令

docker exec -it 容器名稱 或者 容器ID 執行命令

直接操作容器,執行完 回到 宿主主機終端;

 我們一般用於 啟動容器里的應用 比如 tomcat nginx redis elasticsearch等等

  6.13 提交運行時容器成為鏡像

docker commit

docker commit -a=’作者’ -m=’備註’ 運行時容器ID 新鏡像名稱

 

  6.14 推送鏡像到hub服務器

我們可以通過docker push命令 把自己本地定製的鏡像推送到Hub服務器,方便全球開發者使用,包括自己;

 

上一講,我們定製了一個鏡像 java1234/tomcat7 tag是1.1

我們把這個鏡像發布到hub服務器;

 

步驟一:

https://hub.docker.com/ 註冊下 得到docker id和密碼

 

步驟二:

我們用docker login登陸hub服務器

 

步驟三:

docker push推送

docker push java1234/tomcat7:1.1

 

推送成功:

登陸 https://hub.docker.com/   點擊 Repositories 菜單

 

已經显示這個鏡像;

點擊:

我們加簡介和描述信息;

點Tags:

我們可以刪除掉;

 

  6.15 推送鏡像到阿里雲

很多時候,中小公司為了方便搭建私有倉庫方便,直接使用穩定的阿里雲鏡像倉庫,方便公司內部業務系統直接拉取鏡像;

步驟一:

進入:https://cr.console.aliyun.com  阿里雲鏡像控制台  需要註冊  用戶名就是你的淘寶或者支付寶 賬號名稱 ,鏡像控制台密碼單獨設置;

步驟二:

進入控制台,我們先創建命名空間,再創建鏡像;

然後我們可以根據阿里雲官方提示說明來進行鏡像遠程登錄,提交,以及拉取操作,簡單易用;

  6.16 查看容器元信息

docker inspect 容器ID

 

 

——————————————————————————————————————————

作者: java1234_小鋒

出處:https://www.cnblogs.com/java688/p/13174646.html

版權:本站使用「CC BY 4.0」創作共享協議,轉載請在文章明顯位置註明作者及出處。

——————————————————————————————————————————

 

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

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

一個非侵入的Go事務管理庫——工作原理

在上一篇文章“一個非侵入的Go事務管理庫——如何使用”中,我講述了如何使用事務庫。有些讀者可能讀過”清晰架構(Clean Architecture)的Go微服務: 事物管理” ,其中描述了事務管理系統的舊版本。那篇文章和本文之間會有一些重疊。因為大多數人可能還沒有讀過那篇文章或者即使讀了也忘記了它的內容。因此為了照顧多數讀者,本文還是從頭開始(假設你沒有讀過前文)。如果你讀過,那你可以直接跳過熟悉的部分。

好的事務庫對於使用它的應用程序是透明的。在Go的“sql”庫中,有兩種類型的數據庫鏈接,“sql.DB”和“sql.Tx”。當你不需要事務支持時,使用“sql.DB”;否則使用“sql.Tx”。為了讓這兩種不同場景共享相同的持久層代碼,我們需要對數據庫鏈接進行一個封裝來同時支持這兩種場景。我從”db transaction in golang” 里得到了這個想法。

數據庫層的接口

數據庫層是事務管理庫中處理數據庫訪問的最低層。應用程序不需要修改該層,只有事務管理庫需要這樣做。

數據庫訪問封裝

下面是可同時支持事務和非事務操作的共享數據庫訪問接口, 它在“gdbc.go”中定義。

// SqlGdbc (SQL Go database connection) is a wrapper for SQL database handler ( can be *sql.DB or *sql.Tx)
// It should be able to work with all SQL data that follows SQL standard.
type SqlGdbc interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	Prepare(query string) (*sql.Stmt, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	// If need transaction support, add this interface
	Transactioner
}

// Transactioner is the transaction interface for database handler
// It should only be applicable to SQL database
type Transactioner interface {
	// Rollback a transaction
	Rollback() error
	// Commit a transaction
	Commit() error
	// TxEnd commits a transaction if no errors, otherwise rollback
	// txFunc is the operations wrapped in a transaction
	TxEnd(txFunc func() error) error

}

它有兩部分。一個是數據庫接口,它包含了常規的數據庫操作,如查詢表、更新表記錄。另一個事務接口,它包含里支持事務所需要的函數,如“提交”和“回滾”。“SqlGdbc”接口是兩者的結合。該接口將用於連接數據庫。

數據庫訪問接口的實現

下面是數據庫訪問接口的代碼實現。它在“sqlConnWrapper.go”文件中。它定義了兩個結構體,“SqlDBTx”是對“sql.DB”的封裝,將被非事務函數使用。“SqlConnTx”是對“sql.Tx”的封裝,將被事務函數使用。

// SqlDBTx is the concrete implementation of sqlGdbc by using *sql.DB
type SqlDBTx struct {
	DB *sql.DB
}

// SqlConnTx is the concrete implementation of sqlGdbc by using *sql.Tx
type SqlConnTx struct {
	DB *sql.Tx
}

func (sdt *SqlDBTx) Exec(query string, args ...interface{}) (sql.Result, error) {
	return sdt.DB.Exec(query, args...)
}

func (sdt *SqlDBTx) Prepare(query string) (*sql.Stmt, error) {
	return sdt.DB.Prepare(query)
}

func (sdt *SqlDBTx) Query(query string, args ...interface{}) (*sql.Rows, error) {
	return sdt.DB.Query(query, args...)
}

func (sdt *SqlDBTx) QueryRow(query string, args ...interface{}) *sql.Row {
	return sdt.DB.QueryRow(query, args...)
}

func (sdb *SqlConnTx) Exec(query string, args ...interface{}) (sql.Result, error) {
	return sdb.DB.Exec(query, args...)
}

func (sdb *SqlConnTx) Prepare(query string) (*sql.Stmt, error) {
	return sdb.DB.Prepare(query)
}

func (sdb *SqlConnTx) Query(query string, args ...interface{}) (*sql.Rows, error) {
	return sdb.DB.Query(query, args...)
}

func (sdb *SqlConnTx) QueryRow(query string, args ...interface{}) *sql.Row {
	return sdb.DB.QueryRow(query, args...)
}

事務接口的實現

下面是“Transactioner”接口的代碼實現,它在文件 “txConn.go”中。我從”database/sql Tx — detecting Commit or Rollback”中得到這個想法。

因為“SqlDBTx”不支持事務,所以它的所有函數都返回“nil”。

// DB doesn't rollback, do nothing here
func (cdt *SqlDBTx) Rollback() error {
	return nil
}

//DB doesnt commit, do nothing here
func (cdt *SqlDBTx) Commit() error {
	return nil
}

// DB doesnt rollback, do nothing here
func (cdt *SqlDBTx) TxEnd(txFunc func() error) error {
	return nil
}

func (sct *SqlConnTx) TxEnd(txFunc func() error) error {
	var err error
	tx := sct.DB

	defer func() {
		if p := recover(); p != nil {
			log.Println("found p and rollback:", p)
			tx.Rollback()
			panic(p) // re-throw panic after Rollback
		} else if err != nil {
			log.Println("found error and rollback:", err)
			tx.Rollback() // err is non-nil; don't change it
		} else {
			log.Println("commit:")
			err = tx.Commit() // if Commit returns error update err with commit err
		}
	}()
	err = txFunc()
	return err
}

func (sct *SqlConnTx) Rollback() error {
	return sct.DB.Rollback()
}

func (sct *SqlConnTx) Commit() error {
	return sct.DB.Commit()
}

持久層的接口

在數據庫層之上是持久層,應用程序使用持久層來訪問數據庫表中的記錄。你需要定義一個函數在本層中實現對事務的支持。下面是持久層的事務接口,它位於“txDataService.go”文件中。

// TxDataInterface represents operations needed for transaction support.
type TxDataInterface interface {
	// EnableTx is called at the end of a transaction and based on whether there is an error, it commits or rollback the
	// transaction.
	// txFunc is the business function wrapped in a transaction
	EnableTx(txFunc func() error) error
}

以下是它的實現代碼。它只是調用下層數據庫中的函數“TxEnd()”,該函數已在數據庫層實現。下面的代碼不是事務庫的代碼(它是本文中惟一的不是事務庫中的代碼),你需要在應用程序中實現它。

func (uds *UserDataSql) EnableTx(txFunc func() error) error {
	return uds.DB.TxEnd(txFunc)
}

獲取數據庫鏈接的代碼

除了我們上面描述的調用接口之外,在應用程序中你還需要先獲得數據庫鏈接。事務庫中有兩個函數可以完成這個任務。

返回”SqlGdbc”接口的函數

函數”Build()”(在”factory.go”中)將返回”SqlGdbc”接口。根據傳入的參數,它講返回滿足”SqlGdbc”接口的結構,如果需要事務支持就是“SqlConnTx”,不需要就是“SqlDBTx”。如果你不需要在應用程序中直接使用數據庫鏈接,那麼調用它是最好的。

// Build returns the SqlGdbc interface. This is the interface that you can use directly in your persistence layer
// If you don't need to cache sql.DB connection, you can call this function because you won't be able to get the sql.DB
// in SqlGdbc interface (if you need to do it, call BuildSqlDB()
func Build(dsc *config.DatabaseConfig) (gdbc.SqlGdbc, error) {
	db, err := sql.Open(dsc.DriverName, dsc.DataSourceName)
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	// check the connection
	err = db.Ping()
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	dt, err := buildGdbc(db, dsc)
	if err != nil {
		return nil, err
	}
	return dt, nil
}

func buildGdbc(sdb *sql.DB,dsc *config.DatabaseConfig) (gdbc.SqlGdbc, error){
	var sdt gdbc.SqlGdbc
	if dsc.Tx {
		tx, err := sdb.Begin()
		if err != nil {
			return nil, err
		}
		sdt = &gdbc.SqlConnTx{DB: tx}
		log.Println("buildGdbc(), create TX:")
	} else {
		sdt = &gdbc.SqlDBTx{sdb}
		log.Println("buildGdbc(), create DB:")
	}
	return sdt, nil
}

返回數據庫鏈接的函數

函數”BuildSqlDB()”(在”factory.go”中)將返回”sql.DB”。它會忽略傳入的事務標識參數。應用程序在調用這個函數獲得數據庫鏈接后,還需要根據事務標識自己生成“SqlConnTx”或“SqlDBTx”。如果你需要在應用程序里緩存”sql.DB”,那麼你必須調用這個函數。

// BuildSqlDB returns the sql.DB. The calling function need to generate corresponding gdbc.SqlGdbc struct based on
// sql.DB in order to use it in your persistence layer
// If you need to cache sql.DB connection, you need to call this function
func BuildSqlDB(dsc *config.DatabaseConfig) (*sql.DB, error) {
	db, err := sql.Open(dsc.DriverName, dsc.DataSourceName)
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	// check the connection
	err = db.Ping()
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	return db, nil

}

局限性

首先,它只支持SQL數據庫的事務。如果你有一個NoSql數據庫,那麼它不支持(大多數NoSql數據庫不支持事務)。

其次,如果你的事務跨越數據庫(例如在不同的微服務之間),那麼它將無法工作。常用的做法是使用“Saga Pattern”。你可以為事務中的每個操作編寫一個補償操作,並在回滾階段逐個執行補償操作。在應用程序中添加“Saga”解決方案並不困難。你可能會問,為什麼不把“Saga”加到事務庫中呢? 這是一個有趣的問題。我覺得還是單獨為“Saga”建一個庫比較合適。

第三,它不支持嵌套事務(Nested Transaction),因此你需要手動確保在代碼中沒有嵌套事務。如果代碼庫不是太複雜,這很容易做到。如果你有一個非常複雜的代碼庫,其中有很多事務和非事務代碼混在一起,那麼你需要一個支持嵌套事務的解決方案。我沒有花時間研究如何添加嵌套事務,但它應該有一定的工作量。如果你對此感興趣,可以從”database/sql: nested transaction or save point support”開始。到目前為止,對於大多數場景,當前的解決方案可能是在代價不大的情況下的最佳方案。

如何擴展庫的功能

“SqlGdbc”接口沒有列出“sql”包中的所有函數,只列出我的應用程序中需要的函數。你可以輕鬆地擴展該接口以包含其他函數。

例如,如果需要將全鏈路跟蹤(詳情請見”Go微服務全鏈路跟蹤詳解”)擴展到數據庫中,則可能需要在上下文中傳遞到數據庫函數中。“sql”庫已經支持具有上下文的數據庫函數。你只需要找到它們並將它們添加到”SqlGdbc”接口中,然後在”sqlConnWrapper “中實現它們。然後在持久層中,需要使用上下文作為參數調用函數。

源碼:

完整源碼: “jfeng45/gtransaction”

索引:

1 “一個非侵入的Go事務管理庫——如何使用”

2 “清晰架構(Clean Architecture)的Go微服務: 事物管理”

3 “db transaction in golang”

4 “database/sql Tx — detecting Commit or Rollback”

5 “Applying the Saga Pattern – GOTO Conference”

6 “database/sql: nested transaction or save point support”

7 “Go微服務全鏈路跟蹤詳解”

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

HTML躬行記(1)——SVG

  <svg>是矢量圖的根元素,通過xmlns屬性聲明命名空間,從而告訴用戶代理標記名稱屬於哪個XML方言。在下面的示例中,為<svg>元素聲明了寬度和高度(默認以像素為單位),其子元素<title>可作為提示,在<desc>中可聲明一段描述性純文本,這兩個元素都不會在頁面中呈現。而<rect>是一個矩形,將被繪製到頁面中。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100">
  <title>SVG example</title>
  <desc>SVG contains a rectangle</desc>
  <rect width="50" height="50" fill="#F60" />
</svg>

  SVG作為一種圖像格式,可以包含在<img>元素內(如下所示)或CSS樣式中(例如background-image屬性)。

<img src="demo.svg" />

一、坐標系統

1)視口

  在SVG中,有一張無限大的畫布,而畫布區域被稱為視口(viewport)。通過<svg>元素的width和height兩個屬性可定義視口的尺寸,視口的原點在其左上角。

  而在視口中,還包含一個坐標系統,由viewBox屬性控制。它能包含四個數值(以逗號或空格分隔),分別是用戶坐標系統的最小橫坐標(x軸)和縱坐標(y軸),以及寬和高。

  下面的兩個<svg>元素,第一個採用了默認的坐標系統,第二個聲明了新的坐標系統,並且寬高比相同,如圖1所示,第二個矩形縮小了。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>

圖 1

  接下來修改兩個最小坐標(如圖2所示),第一個<svg>元素聲明的最小坐標為(20,20),雖然矩形的坐標是(0,0),但是比最小坐標要小,所以就會往左上角偏移;第二個<svg>元素聲明了負數坐標,與前一個正好相反;在第三個<svg>元素中,修改了矩形的坐標,正好在左上角。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="20 20 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="-20 -20 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="20 20 300 200">
  <rect width="50" height="50" fill="#F60" x="20" y="20" />
</svg>

圖 2

2)preserveAspectRatio屬性

  當viewBox屬性中聲明的尺寸與視圖的寬高比不一致時,可以使用preserveAspectRatio屬性指定圖形的縮放比例和對齊方式,語法如下,默認值是“xMidYMid meet”。

preserveAspectRatio: <align> [<meetOrSlice>]

  其中<align>的屬性值由兩個軸(x和y)以及三個位置(min、mid和max)組合而成,如表1所列。

表 1

說明
xMin viewport與viewBox的左側對齊
xMid viewport與viewBox的x軸中點對齊
xMax viewport與viewBox的右側對齊
YMin viewport與viewBox的頂部對齊
YMid viewport與viewBox的y軸中點對齊
YMax viewport與viewBox的底部對齊

  在下面的示例中,由於三個<svg>元素寬高比是3:2,而viewBox的寬高比是3:1,因此矩形會等比縮小。對它們分別應用xMinYMin、xMidYMid和xMinYMax,效果如圖3所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 100" preserveAspectRatio="xMinYMin">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 100" preserveAspectRatio="xMidYMid">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 100" preserveAspectRatio="xMinYMax">
  <rect width="50" height="50" fill="#F60" />
</svg>

圖 3

  注意,因為寬度正好適配,所以對於x軸的對齊方式,效果都是相同的。

  <meetOrSlice>可控製圖形的適配或裁剪,可選的值如表2所列。

表 2

說明
meet 保留圖形的寬高比,並且縮放viewBox以適應viewport
slice 保留圖形的寬高比,並且放大viewBox以覆蓋viewport

  在下面的示例中,兩個矩形的高度比視口要大,對它們分別應用meet和slice,效果如圖4所示,第二個矩形將整個視口給填滿了。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 100" preserveAspectRatio="xMinYMin meet">
  <rect width="150" height="150" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 100" preserveAspectRatio="xMinYMin slice">
  <rect width="150" height="150" fill="#F60" />
</svg>

圖 4

二、形狀

  SVG的基本形狀包括線段(line)、矩形(rect)、圓形(circle)、橢圓(ellipse)、多邊形(polygon)和折線(polyline)。

1)<line>

  線段元素需要指定起止點的坐標,如下所示,效果如圖5所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <line x1="20" y1="100"  x2="100" y2="20" stroke="black" stroke-width="2"/>
</svg>

圖 5

  其中stroke和stroke-width是筆畫屬性,可指定筆畫的顏色和寬度,相關屬性如表3所列,部分屬性的效果如圖6所示。

表 3

說明
stroke 筆畫顏色
stroke-dasharray 筆畫的外觀(實線、點線或虛線),由一系列逗號分隔的数字組成,表示長度和空隙長度
stroke-dashoffset 相對繪圖起點的偏移值
stroke-linecap 描邊的展現形狀
stroke-linejoin 路徑轉角處的形狀
stroke-miterlimit 斜接長度與線寬的最大比例
stroke-opacity 筆畫不透明度,取值範圍0~1,其中0表示透明
stroke-width 筆畫寬度

圖 6

2)<rect>

  除了直角矩形之外,還可以聲明圓角矩形,如下所示,效果如圖7所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect x="10" y="10" width="100" height="100" rx="15" ry="15" fill="#F60"/>
</svg>

圖 7

3)<circle>和<ellipse>

  利用圓形,可非常便捷的畫出圓環,效果如圖8所示。將<circle>元素的stroke-dasharray聲明為圓的周長(2πR),例如半徑為50,周長就是314。如果為stroke-dashoffset屬性定義一個值,就能得到圓環缺失一段的效果,從而就能模擬出圓環型的進度條了。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <circle cx="100" cy="100" r="50" stroke="black" stroke-width="2" 
    stroke-dasharray="314" stroke-dashoffset="40" fill="transparent" />
</svg>

圖 8

  橢圓和圓形類似,只是需要聲明兩個方向的半徑,如圖9所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <ellipse cx="100" cy="100" rx="100" ry="50" />
</svg>

圖 9

4)<polygon>

  <polygon>可畫出任意形狀的封閉圖形,例如平行四邊形、梯形等。在points屬性中,可聲明各個點的坐標,每組坐標用逗號隔開,下面繪製了一個五角星,如圖10所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <polygon points="100,0 160,180 10,60 190,60 40,180" fill="#F60"/>
</svg>

圖 10

5)<polyline>

  折線不需要閉合,與<polygon>元素類似,也是由points屬性繪製,如下所示,得到的折線如圖11所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <polyline points="20,100 40,60 70,80 100,20" fill="none" stroke="black" />
</svg>

圖 11

6)<path>

  上述基本形狀都可以由<path>元素來繪製,並且通過<path>元素還可繪製出不規則的圖形,例如心形,如下所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <path d="M 10,30
           A 20,20 0,0,1 50,30
           A 20,20 0,0,1 90,30
           Q 90,60 50,90
           Q 10,60 10,30 z" />
</svg>

  其中d屬性可聲明一系列路徑,包含多個指令,如表4所列。

表 4

指令 效果
M、m 移動到指定的坐標
L、l 繪製一條直線
H、h 繪製一條水平線
V、v 繪製一條垂直線
Z、z 關閉路徑
Q、q 繪製一條二次貝塞爾曲線
T、t 繪製一條平滑的二次貝塞爾曲線
C、c 繪製一條三次貝塞爾曲線
S、s 繪製一條平滑的三次貝塞爾曲線
A、a 繪製弧形曲線

三、文檔結構

1)內部樣式

  SVG允許在其內部嵌入<style>元素,如下所示,其中CDATA區段中的文本會被解析器忽略,但不影響渲染。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <style>
    <![CDATA[
    line {
      stroke: black;
      stroke-width: 2;
    }
    ]]>
  </style>
  <line x1="20" y1="100" x2="100" y2="20" />
</svg>

2)<g>

  <g>元素相當於一個容器,能將其所有的子元素組合在一起。應用於<g>元素中的屬性會被其子元素所繼承,如下所示,兩個圓的筆畫顏色都是綠色,而寬度都是10,如圖12所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <g id="ring" fill="white" stroke="green" stroke-width="10">
    <circle cx="80" cy="80" r="50" />
    <circle cx="120" cy="120" r="50" />
  </g>
</svg>

圖 12

3)<use>

  <use>元素可引用其它圖形,以及<g>元素,類似於複製黏貼的功能。在下面的示例中,通過<use>元素的xlink:href屬性引用了id為ring的<g>元素,並且將<use>元素上聲明的屬性傳給了<circle>元素。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <g id="ring">
    <circle cx="80" cy="80" r="50" />
    <circle cx="120" cy="120" r="50" />
  </g>
  <use x="100" y="0" fill="white" stroke="green" stroke-width="10" xlink:href="#ring" />
</svg>

  注意,當給<use>元素定義坐標后,<circle>元素會與其相加計算出最終的坐標,如圖13所示。

圖 13

4)<defs>

  可將需要復用的圖形抽象到<defs>元素中,在其內部定義的圖形不會直接呈現到頁面中。在上面那個示例的基礎上,將<g>元素整個放置到<defs>中,效果如圖14所示,沒有渲染<g>元素中的圓。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <defs>
    <g id="ring">
      <circle cx="80" cy="80" r="50" />
      <circle cx="120" cy="120" r="50" />
    </g>
  </defs>
  <use x="100" y="0" fill="white" stroke="green" stroke-width="10" xlink:href="#ring" />
</svg>

圖 14

5)<symbol>

  <symbol>提供了另一種組合圖形的方式,但與<g>元素不同,它的圖形不會呈現,並且它可以聲明viewBox和preserveAspectRatio兩個屬性,如下所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100">
  <symbol id="ring" viewBox="0 0 300 200">
    <circle cx="80" cy="80" r="50" />
    <circle cx="120" cy="120" r="50" />
  </symbol>
  <use fill="white" stroke="green" stroke-width="10" xlink:href="#ring" />
</svg>

6)<image>

  <use>元素可以引用SVG文件的某個部分,而<image>元素可以引用整個SVG文件或柵格圖像(如下所示),並且能控制引用文件的尺寸和preserveAspectRatio屬性,效果如圖15所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <image xlink:href="img/avatar.png" width="150" />
</svg>

圖 15

四、變形、圖案和漸變

1)變形

  transform屬性定義了一系列圖形元素變形的規則,包括位移(translate)、縮放(scale)、旋轉(rotate)和傾斜(skew)。注意,與CSS3中的transform屬性不同,SVG中的transform屬性作用的對象是坐標系統,而不是元素本身。

  translate()函數會接收兩個參數,沿x軸和y軸位移坐標系統,如圖16所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="translate(50, 30)" />
</svg>

圖 16

  scale()函數也會接收兩個參數(這點與CSS3中的scale()不同),沿x軸和y軸縮放坐標系統,如圖17所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="scale(2, 3)" />
</svg>

圖 17

  rotate()函數可接收三個參數,第一個是旋轉角度,另外兩個是原點坐標,也就是坐標系統按照該原點旋轉,如圖18所示,第三個矩形指定了原點。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="rotate(30)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="rotate(30, 50, 30)" />
</svg>

圖 18

  傾斜分為兩個函數:skewX()和skewY(),分別會沿着x軸和y軸傾斜,如圖19所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="skewX(30)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 300 200">
  <rect width="50" height="50" fill="#F60" transform="skewY(30)" />
</svg>

圖 19

2)圖案

  要創建一個圖案,就得使用<pattern>元素包裹圖形元素,再利用patternUnits屬性確定平鋪圖案的方式。它有兩個關鍵字可選,默認的objectBoundingBox會讓<pattern>元素的尺寸以百分數或0~1之間的小數表示,參照對象分別是引用<pattern>的圖形元素的寬和高。

  以下面的圖案為例,它的寬和高都是10%,參照的圓形的寬高都是200,計算出的實際值就都是20,效果如圖20所示。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200">
  <defs>
    <pattern id="star1" width="10%" height="10%" patternUnits="objectBoundingBox">
      <circle cx="10" cy="10" r="10" />
    </pattern>
  </defs>
  <circle cx="100" cy="100" r="100" fill="url(#star1)" />
</svg>

圖 20

  另一個userSpaceOnUse會讓<pattern>元素的尺寸以絕對值表示,如下所示,因為<pattern>元素的寬高都為25,所以圖案會有空白間隙,得到的效果如圖21所示。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200">
  <defs>
    <pattern id="star2" width="25" height="25" patternUnits="userSpaceOnUse">
      <circle cx="10" cy="10" r="10" />
    </pattern>
  </defs>
  <circle cx="100" cy="100" r="100" fill="url(#star2)" />
</svg>

圖 21

  <pattern>元素還包含另一個patternContentUnits屬性,用於處理圖案內部的排列方式,它的兩個關鍵字也是objectBoundingBox和userSpaceOnUse,後者是該屬性的默認值。

  objectBoundingBox會讓<pattern>中的圖形元素以小數定義,如下所示。三個屬性值都是0.1(不能用百分數),參照的仍然是引用<pattern>的圖形元素,計算得到的實際值都是20,效果如圖22所示,每個圖案只显示四分之一個圓。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200">
  <defs>
    <pattern id="star3" width="10%" height="10%" patternContentUnits="objectBoundingBox">
      <circle cx=".1" cy=".1" r=".1" />
    </pattern>
  </defs>
  <circle cx="100" cy="100" r="100" fill="url(#star3)" />
</svg>

圖 22

3)漸變

  <linearGradient>元素用於繪製線性漸變,其子元素<stop>可指定某處的色標(即漸變點),如下所示,在起點、中點和止點處聲明了三種顏色,其中stop-opacity用於聲明不透明度(取值範圍0~1),1表示完全不透明,得到的效果如圖23所示。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200">
  <defs>
    <linearGradient id="gradient">
      <stop offset="0" stop-color="#F60" />
      <stop offset="50%" stop-color="#CCC" stop-opacity=".5"/>
      <stop offset="100%" stop-color="#FC0" />
    </linearGradient>
  </defs>
  <rect width="200" height="100" fill="url(#gradient)" />
</svg>

圖 23

  如果要改變線性漸變的方向,可通過修改起點和終點的坐標實現,例如沿垂直線漸變,代碼如下,得到的效果如圖24所示。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200">
  <defs>
    <linearGradient id="gradientVertical" x1="0" y1="0" x2="0" y2="100%">
      <stop offset="0" stop-color="#F60" />
      <stop offset="50%" stop-color="#CCC" stop-opacity=".5" />
      <stop offset="100%" stop-color="#FC0" />
    </linearGradient>
  </defs>
  <rect width="200" height="100" fill="url(#gradientVertical)" />
</svg>

圖 24

  <linearGradient>元素還有一個spreadMethod屬性,可指定在漸變範圍之外的填充方式,它有三個值可選,如下所列。

  (1)pad:默認值,用起點和終點的顏色填充。

  (2)reflect:按終點到起點,起點到終點的方式重複填充。

  (3)repeat:按起點到終點的方式重複填充。

  下面用一個示例來演示spreadMethod屬性,如圖25所示,從左往右,spreadMethod屬性的值依次是pad、reflect和repeat。

<svg xmlns="http://www.w3.org/2000/svg" width="800" height="200">
  <defs>
    <linearGradient id="spreadMethod" x1="20%" y1="30%" x2="60%" y2="70%">
      <stop offset="0" stop-color="#F60" />
      <stop offset="40%" stop-color="#CCC" />
      <stop offset="80%" stop-color="#FC0" />
    </linearGradient>
    <linearGradient id="gradientPad" href="#spreadMethod" spreadMethod="pad" />
    <linearGradient id="gradientReflect" href="#spreadMethod" spreadMethod="reflect" />
    <linearGradient id="gradientRepeat" href="#spreadMethod" spreadMethod="repeat" />
  </defs>
  <rect width="200" height="100" fill="url(#gradientPad)" />
  <rect width="200" height="100" fill="url(#gradientReflect)" x="210" />
  <rect width="200" height="100" fill="url(#gradientRepeat)" x="420" />
</svg>

圖 25

  另外一種徑向漸變由<radialGradient>元素控制,具體可參考官方文檔。

五、文本

1)<text>

  <text>元素用於處理SVG文件中的文本,在該元素中可修改字體樣式,包括字體名稱、大小、顏色、外觀等。在下面的示例中,聲明了四個<text>元素,併為它們添加了各自的樣式,效果如圖26所示。

<svg xmlns="http://www.w3.org/2000/svg" width="250" height="100">
  <style>
    .small {
      font: italic 13px sans-serif;
    }
    .heavy {
      font: bold 30px sans-serif;
    }
    .Rrrrr {
      font: italic 40px serif;
      fill: red;
    }
  </style>
  <text x="20" y="35" class="small">My</text>
  <text x="40" y="35" class="heavy">name</text>
  <text x="55" y="55" class="small">is</text>
  <text x="65" y="55" class="Rrrrr">Strick!</text>
</svg>

圖 26

2)對齊

  在<text>元素中對齊文本得用text-anchor屬性,它的對齊方式為起點(start)、居中(middle)和終點(end)。在下面的示例中,為了便於觀察這三個關鍵字的行為,畫了一條參考線,如圖27所示。

<svg xmlns="http://www.w3.org/2000/svg" width="120" height="150">
  <path d="M60,15 L60,110 M30,40 L90,40 M30,75 L90,75 M30,110 L90,110" stroke="grey" />
  <text text-anchor="start" x="60" y="40">Start</text>
  <text text-anchor="middle" x="60" y="75">Middle</text>
  <text text-anchor="end" x="60" y="110">End</text>
</svg>

圖 27

  SVG中的文本對齊與CSS中的略有不同,當起點對齊時,第一個字符會貼着參考線;當居中對齊時,文本的中間位置會被參考線貫穿;當終點對齊時,文本的最後一個字符會貼着參考線。

3)<tspan>

  在<text>元素中,通過其子元素<tspan>可調整文本屬性,從而實現一段文本呈現不同的效果,如下所示,這段文本為斜體,而<tspan>元素中的文本被加粗並且賦予了紅色(如圖28所示)。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <style>
    text {
      font: italic 18px serif;
    }
    tspan {
      font: bold 20px sans-serif;
      fill: red;
    }
  </style>
  <text x="10" y="30" class="small">
    My name is
    <tspan>Strick</tspan>!
  </text>
</svg>

圖 28

4)長度
  textLength屬性用於定義文本的長度,lengthAdjust屬性用於設置字符間距和字形,如下所示,默認值spacing只會控制字符間距,而spacingAndGlyphs還能控制字形,如圖29所示。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="60">
  <text y="20" textLength="90%" lengthAdjust="spacing">Big text length</text>
  <text y="40" textLength="90%" lengthAdjust="spacingAndGlyphs">Big text length</text>
</svg>

圖 29

5)文本路徑

  將文本放置在<textPath>元素中,就可讓文本按任意的路徑排列,而不是以往的水平或垂直排列。在下面的示例中,文本按一條螺旋曲線排列,如圖30所示。

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="120">
  <defs>
    <path id="curve" d="M10,90 Q90,90 90,45 Q90,10 50,10 Q10,10 10,40 Q10,70 45,70 Q70,70 75,50" />
  </defs>
  <text>
    <textPath href="#curve">
      My name is Strick! What is your name?
    </textPath>
  </text>
</svg>

圖 30

六、動畫

1)<animate>

  <animate>是一個動畫元素,它可以包含在圖形元素中,多個<animate>元素可以實現多重動畫。例如將矩形先沿着水平方向,再沿着垂直方向位移,最後在位移結束后切換背景色的動畫,代碼如下所示,效果如圖31。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <rect id="move" width="50" height="50" fill="#F60">
    <animate attributeType="XML" dur="1s" repeatCount="1" attributeName="x"
        from="0" to="50" fill="freeze" begin="1s" id="line" />
    <animate attributeType="XML" dur="1s" repeatCount="1" attributeName="y"
        from="0" to="30" fill="freeze" begin="2s" />
    <animate attributeType="XML" dur="3s" repeatCount="indefinite" attributeName="fill"
        values="#F60;#FC0;#CCC" begin="line.end" />
  </rect>
</svg>

圖 31

  <animate>元素包含多個動畫屬性,此處只使用了其中的幾個,具體說明如下,其中fill=”freeze”是指動畫結束后保持最後的動作。

  (1)attributeName:執行動畫的屬性。

  (2)attributeType:屬性類型,可選值包括XML和CSS。

  (3)from:屬性的起始值。

  (4)to:屬性的結束值。

  (5)dur:動畫持續時間。

  (6)repeatCount:動畫執行次數,可以是有限次的整數,也可以是無限次的indefinite。

  (7)begin:動畫開始時機,可以是秒數,也可以是某個動作,例如上面第一個動畫結束后執行顏色的切換。

  <set>元素是對<animate>元素的補充,可為那些不能過渡的屬性提供動畫,例如在某個時刻显示文本,如下所示,點擊矩形可显示“change color”。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <!--省略矩形代碼-->
  <text x="100" y="20" text-anchor="middle" style="display:none">
    <set attributeName="display" attributeType="CSS" to="block" begin="move.click" dur="1s" fill="freeze" />
    change color
  </text>
</svg>

2)<animateTransform>

  對於transform屬性的動畫,得用<animateTransform>元素完成。下面的示例演示了旋轉矩形(如圖32所示),其中type屬性用於指定變形的動作,可選的值有translate、scale、rotate、skewX和skewY。

<svg xmlns="http://www.w3.org/2000/svg" width="180" height="160">
  <rect id="move" width="50" height="50" fill="#F60" x="80" y="80">
    <animateTransform attributeName="transform" attributeType="XML" type="rotate"
        from="0 80 80" to="360 80 80" dur="5s" repeatCount="indefinite" />
  </rect>
</svg>

圖 32

3)<animateMotion>

  <animateMotion>元素可讓圖形沿着任意路徑運動,無論是直線還是曲線,都能實現。在下面的示例中,橙色矩形會沿着S型曲線來回運動,如圖33所示。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <path fill="none" stroke="#000"
        d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  <rect width="20" height="10" fill="#F60">
    <animateMotion dur="10s" repeatCount="indefinite"
        path="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  </rect>
</svg>

圖 33

  如果要讓矩形始終沿着平行於曲線的方向運動,那麼可以將rotate屬性設為auto,如圖34所示。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <path fill="none" stroke="#000"
        d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  <rect width="20" height="10" fill="#F60">
    <animateMotion dur="10s" repeatCount="indefinite" rotate="auto"
        path="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  </rect>
</svg>

圖 34

 

【參考資料】
SVG元素參考

[技術分享] 理解 SVG 中的 Viewport 和 ViewBox-拖曳與縮放功能實做(上)

理解SVG viewport,viewBox,preserveAspectRatio縮放

SVG圖像的viewport和viewBox用於設置圖像可見區域的大小

SVG:理解stroke-dasharray和stroke-dashoffset屬性

SVG 研究之路 (16) – Stroke-miterlimit

如何使用SVG圖案

SVG 研究之路 (26) – 有趣的 Patterns

 

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

上周熱點回顧(6.15-6.21)

熱點隨筆:

· 因為知道了30+款在線工具,我的工作效率提升500%! (HollisChuang)
· 什麼?一個核同時執行兩個線程? (軒轅之風)
· .Net微服務實戰之DevOps篇 (陳珙)
· .Net 對於PDF生成以及各種轉換的操作 (沉_默)
· 龍芯團隊完成CoreCLR MIPS64移植,已在github開源 (張善友)
· foreach 集合又拋經典異常了,這次一定要刨根問底 (一線碼農)
· 對 JsonConvert 的認識太膚淺了,終於還是遇到了問題 (一線碼農)
· 深入理解 EF Core:EF Core 讀取數據時發生了什麼? (LiamWang)
· 養生吧,程序員! (沉默王二)
· cute-cnblogs 自定義博客園樣式美化二期來啦~ (麋鹿魯喲)
· .Net Core基礎的健康檢查 (她微笑的臉)
· 代碼之間為什麼要加空格? (沉默王二)

熱點新聞:

· 字節跳動程序員期權價值過億 28歲辭職享受人生引熱議 當事人回應
· 阿里P8員工1.6w招私人助理,網友群嘲:你咋不上天呢?
· 我,掉進20萬創業補貼陷阱:最後被告上法庭
· 獨家專訪28歲退休程序員郭宇:1600人加好友,問我“掙了多少錢”
· 北斗導航系統最後一顆衛星就緒:後天發射!
· 有碼變高清!AI一秒還原馬賽克,杜克大學出品
· “零收入”依然淡定,一家基礎軟件公司的冒險與底氣
· 重磅!突破美國封鎖,國產操作系統“天賜”即將誕生,火爆知乎
· 充電器1萬一隻53萬!波士頓動力網紅機器狗開售
· AMD將改寫10年來DIY市場歷史:份額逼近30% 大廠全齊了
· 兩千元的「反 5G 量子設備」,到底是怎樣的智商稅?
· 自主研發 華米發布全球最強大可穿戴人體傳感器

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

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

JSON類庫Jackson優雅序列化Java枚舉類

1. 前言

Java開發中我們為了避免過多的魔法值,使用枚舉類來封裝一些靜態的狀態代碼。但是在將這些枚舉的意思正確而全面的返回給前端卻並不是那麼順利,我們通常會使用Jackson類庫序列化對象為JSON,今天就來講一個關於使用Jackson序列化枚舉的通用性技巧。

2. 通用枚舉範式

為了便於統一處理和規範統一的風格,建議指定一個統一的抽象接口,例如:

/**
 * The interface Enumerator.
 */
public interface Enumerator {
    /**
     * Code integer.
     *
     * @return the integer
     */
    Integer code();

    /**
     * Description string.
     *
     * @return the string
     */
    String description();
}

我們來寫一個實現來標識性別:

public enum GenderEnum implements Enumerator {
   
    UNKNOWN(0, "未知"),

    MALE(1, "男"),

    FEMALE(2, "女");


    private final Integer code;
    private final String description;

    GenderEnum(Integer code, String description) {
        this.code = code;
        this.description = description;
    }


    @Override
    public Integer code() {
        return code;
    }

    @Override
    public String description() {
        return description;
    }
}

3. 序列化枚舉

如果我們直接使用Jackson對枚舉進行序列化,將只能簡單的輸出枚舉的String名稱:

    @Resource
    private ObjectMapper objectMapper;

    @Test
    void enumTest() {
        try {
            String s = objectMapper.writeValueAsString(GenderEnum.MALE);
            // 輸出字符串 MALE
            System.out.println(s);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

我們期望將GenderEnum.MALE 序列化為 {"code":1,"description":"男"} 。我們可以向ObjectMapper定製化一個Module來實現這種個性化需求:

         // 聲明一個簡單Module 對象
         SimpleModule module = new SimpleModule();
           // 給Module 添加一個序列化器
            module.addSerializer(Enumerator.class, new JsonSerializer<Enumerator>() {
                @Override
                public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                   // 開始寫入對象
                    gen.writeStartObject();
                    // 分別指定 k v   code   description 
                    gen.writeNumberField("code",value.code());
                    gen.writeStringField("description",value.description());
                    // 顯式結束操作
                    gen.writeEndObject();
                }
            });

        // 註冊 Module
        objectMapper.registerModule(module);

然後再次執行就會獲取我們期望的結果。然而這並不算合理。

4. Spring Boot 中自動全局配置

Spring Boot應用中我們希望能全局配置。Spring Boot的自動配置為我們提供了一個個性化定製ObjectMapper的可能性,你只需要聲明一個Jackson2ObjectMapperBuilderCustomizer並注入Spring IoC:

@Bean
public Jackson2ObjectMapperBuilderCustomizer enumCustomizer(){
    return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.serializerByType(Enumerator.class, new JsonSerializer<Enumerator>() {
        @Override
        public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                    gen.writeStartObject();
                    gen.writeNumberField("code",value.code());
                    gen.writeStringField("description",value.description());
                    gen.writeEndObject();


        }
    });
}

這樣就實現了全局配置。

5. 總結

這裏我們介紹了如何定製Jackson庫以達到對枚舉進行更加友好的序列化的目的。其實不單單枚舉,你也可以實現其它序列化,反序列化,時間輸出格式的定製。這些特性留給你自己挖掘。多多關注:碼農小胖哥 獲取更多開發技巧。

關注公眾號:Felordcn 獲取更多資訊

個人博客:https://felord.cn

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

英研究稱城市臭氧污染與死亡風險增加相關

摘錄自2020年2月17日北京新浪網報導

倫敦大學衛生和熱帶醫學院最近發佈一項研究說,對全球數百個城市的調查發現,人們日常暴露在城市地面臭氧污染中與死亡風險增加有關。

來自該學院以及多個科研機構的國際團隊在最新一期《英國醫學雜誌》上發表文章報告稱,他們採集了1985年至2015年間來自20個國家和地區406個城市的4500多萬例死亡案例相關數據,並分析了這些城市的污染狀況及死亡風險間的關係後發現,城市地面臭氧水平平均每上升10微克/立方米,總體死亡風險就會增加0.18%。也就是說,如果這些城市執行了更嚴格的空氣排放標準,每年共可減少6000多人死亡。

但團隊也表示,這項研究是基於觀察性分析,因此無法直接確立因果關係,研究結果的準確性也受到一些因素的限制。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

研究:野火危機影響75%澳洲人 當局支持率暴跌

摘錄自2020年2月18日中央社報導

澳洲野火延燒5個月,據今天(18日)公布的最新調查,澳洲75%民眾、將近1800萬人自認受到這波致命野火危機影響。調查也顯示,野火這一燒,同時燒掉了政府和煤炭計畫的支持率。

法新社報導,澳洲國立大學(Australian National University)社會研究主筆畢德爾(Nicholas Biddle)表示:「這場火災幾乎影響到每個澳洲民眾,這將會影響我們許多人好幾年。」

這項訪問3000人的調查指出,14%成人受到直接影響,他們的房屋沒了或受損,或是全家被迫撤離。

除了近300萬人直接受衝擊,更有1500萬名澳洲人受到間接影響,包括受野火煙霧影響或度假計畫泡湯。

上次大選支持政府的受訪者中,支持新建煤礦場的比例從野火危機前的72%跌到1月的57%。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

龍捲風侵襲美國阿肯色州 當局為加速救災實施宵禁

摘錄自2020年3月29日民視報導

美國中部阿肯色州瓊斯伯勒市,昨(28)日遭巨大龍捲風襲擊,多處建築物受損、飛機被吹翻,已知6人受傷。當局事後派出人員搜救又實施宵禁,確保民眾晚上7點之後不會外出,加速救災。

事情發生在美國中部時間28日下午5點左右,突如其來的巨大龍捲風,席捲阿肯色州的瓊斯伯勒市,多棟建築物屋頂瞬間被吹毀、路牌吹歪,甚至傳出當地機場有一架飛機被吹翻,損失慘重。所幸因為武漢肺炎疫情,多數店家早就拉下鐵門,居民也幾乎待在室內,因此只傳出數人受到輕傷。

當地政府第一時間發出警報,要求民眾待在室內避難,事後也派出國民兵進行三次搜救。最後決定實施宵禁,禁止民眾晚上7點後出門,方便有關單位加速清理。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準