特斯拉、Airbnb 合作,至少百間民宿將加裝電動車充電座

  對於特斯拉(Tesla)的充電式電動車而言,最大普及障礙就是充電座設施的密度,如果只能在自己家充電,那電動車的作用就相當有限了,為此,特斯拉找上了分享經濟旅遊住宿網站 Airbnb,與其旗下的民宿合作,在民宿安裝 Model S 電動車充電座,這樣一來旅遊住宿時也能充電,擴增 Model S 電動車車主的活動範圍。   特斯拉將根據資格標準審查,包括要四星級以上、並至少有 5 個房間,符合水準的 Airbnb 旗下高檔民宿,可獲得免費充電座,充電座本身價值 750 美元,不過民宿本身要負擔安裝費用,安裝費用隨地區不同,可能超過 900 美元,安裝完成後,Airbnb 將在網站上標示該民宿為特斯拉電動車可充電民宿。特斯拉初期將先從加州開始,選擇 30 家加州 Airbnb 旗下高檔民宿免費安裝充電座,之後再逐步擴大到全球,目前只有 12 戶民宿擁有特斯拉充電座,最終將至少有 100 家 Airbnb 旗下民宿可得到免費充電座。   這只是特斯拉積極建立充電站努力的其中一環,特斯拉正積極布建其 Supercharger 快速充電站,目前全球已有 487 座,也與餐廳、旅館、度假村合作,在其中建立壁式充電座,方便車主造訪時順便充電,至 2015 年 6 月,特斯拉在全球已經與 1,200 家業主合作設立充電座。   Airbnb 旗下民宿與特斯拉合作可說是雙贏選擇,雖然仍需負擔安裝費用,但安裝後,可吸引大多為高階消費者的特斯拉車主入住,不僅對生意與品牌形象有幫助,車主充電付出充電費用,一個晚上大約可增加 10 美元營收,對民宿不無小補。而對特斯拉來說,充電座越普及,車子也更好賣。   特斯拉目前大體上只在美國主要城市與幹道路線上布置充電座,經常遭到質疑與攻擊,聲稱電動車可能會在荒郊野外沒電,儘管特斯拉嚴詞反擊目前布站範圍已經涵蓋 96% 美國地區,要故意開到離充電站遠到來不及去充電的地區沒那麼容易,但特斯拉對這樣的抨擊也不敢怠慢,2015 年 3 月時推出軟體更新,整合充電站位置到導航系統之中,一旦車主離充電站距離可能超出殘餘電力可行駛里程,就發出警告,確保不會發生半途沒電的情況。   但要讓潛在消費者更安心買車,最根本之道仍是布建更多充電站,與 Airbnb 的合作代表特斯拉又向前跨出一步,未來可預期特斯拉將更積極推動類似的合作案。     本文全文授權轉載自《科技新報》─〈〉

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

007.Kubernetes二進制部署Flannel

一 部署flannel

1.1 安裝flannel


kubernetes 要求集群內各節點(包括 master 節點)能通過 Pod 網段互聯互通。flannel 使用 vxlan 技術為各節點創建一個可以互通的 Pod 網絡,使用的端口為 UDP 8472。




flanneld 第一次啟動時,從 etcd 獲取配置的 Pod 網段信息,為本節點分配一個未使用的地址段,然後創建 flannedl.1 網絡接口(也可能是其它名稱,如 flannel1 等)。




flannel 將分配給自己的 Pod 網段信息寫入 /run/flannel/docker 文件,docker 後續使用這個文件中的環境變量設置 docker0 網橋,從而從這個地址段為本節點的所有 Pod 容器分配 IP。

更多flannel參考:《008.Docker Flannel+Etcd分佈式網絡部署》。

  1 [root@k8smaster01 ~]# cd /opt/k8s/work/
  2 [root@k8smaster01 work]# mkdir flannel
  3 [root@k8smaster01 work]# wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
  4 [root@k8smaster01 work]# tar -xzvf flannel-v0.11.0-linux-amd64.tar.gz -C flannel


1.2 分發flannel

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp flannel/{flanneld,mk-docker-opts.sh} root@${master_ip}:/opt/k8s/bin/
  7     ssh root@${master_ip} "chmod +x /opt/k8s/bin/*"
  8   done


1.3 創建flannel證書和密鑰

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > flanneld-csr.json <<EOF
  3 {
  4     "CN": "flanneld",
  5     "hosts": [],
  6     "key": {
  7         "algo": "rsa",
  8         "size": 2048
  9     },
 10     "names": [
 11         {
 12             "C": "CN",
 13             "ST": "Shanghai",
 14             "L": "Shanghai",
 15             "O": "k8s",
 16             "OU": "System"
 17         }
 18     ]
 19 }
 20 EOF
 21 #創建flanneld的CA證書請求文件



解釋:

該證書只會被 kubectl 當做 client 證書使用,所以 hosts 字段為空。

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cfssl gencert -ca=/opt/k8s/work/ca.pem \
  3 -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json \
  4 -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld	#生成CA密鑰(ca-key.pem)和證書(ca.pem)


1.4 分發證書和私鑰

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ssh root@${master_ip} "mkdir -p /etc/flanneld/cert"
  7     scp flanneld*.pem root@${master_ip}:/etc/flanneld/cert
  8   done


1.5 寫入集群 Pod 網段信息

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# etcdctl \
  4   --endpoints=${ETCD_ENDPOINTS} \
  5   --ca-file=/opt/k8s/work/ca.pem \
  6   --cert-file=/opt/k8s/work/flanneld.pem \
  7   --key-file=/opt/k8s/work/flanneld-key.pem \
  8   mk ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 21, "Backend": {"Type": "vxlan"}}'



注意:注意:本步驟只需執行一次。

提示:flanneld 當前版本 (v0.11.0) 不支持 etcd v3,故使用 etcd v2 API 寫入配置 key 和網段數據;

寫入的 Pod 網段 ${CLUSTER_CIDR} 地址段(如 /16)必須小於 SubnetLen,必須與 kube-controller-manager 的 –cluster-cidr 參數值一致。

1.6 創建flanneld的systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > flanneld.service << EOF
  4 [Unit]
  5 Description=Flanneld overlay address etcd agent
  6 After=network.target
  7 After=network-online.target
  8 Wants=network-online.target
  9 After=etcd.service
 10 Before=docker.service
 11 
 12 [Service]
 13 Type=notify
 14 ExecStart=/opt/k8s/bin/flanneld \\
 15   -etcd-cafile=/etc/kubernetes/cert/ca.pem \\
 16   -etcd-certfile=/etc/flanneld/cert/flanneld.pem \\
 17   -etcd-keyfile=/etc/flanneld/cert/flanneld-key.pem \\
 18   -etcd-endpoints=${ETCD_ENDPOINTS} \\
 19   -etcd-prefix=${FLANNEL_ETCD_PREFIX} \\
 20   -iface=${IFACE} \\
 21   -ip-masq
 22 ExecStartPost=/opt/k8s/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
 23 Restart=always
 24 RestartSec=5
 25 StartLimitInterval=0
 26 
 27 [Install]
 28 WantedBy=multi-user.target
 29 RequiredBy=docker.service
 30 EOF



解釋:

mk-docker-opts.sh:該腳本將分配給 flanneld 的 Pod 子網段信息寫入 /run/flannel/docker 文件,後續 docker 啟動時使用這個文件中的環境變量配置 docker0 網橋;

flanneld:使用系統缺省路由所在的接口與其它節點通信,對於有多個網絡接口(如內網和公網)的節點,可以用 -iface 參數指定通信接口;

flanneld:運行時需要 root 權限;

-ip-masq: flanneld 為訪問 Pod 網絡外的流量設置 SNAT 規則,同時將傳遞給 Docker 的變量 –ip-masq(/run/flannel/docker 文件中)設置為 false,這樣 Docker 將不再創建 SNAT 規則; Docker 的 –ip-masq 為 true 時,創建的 SNAT 規則比較“暴力”:將所有本節點 Pod 發起的、訪問非 docker0 接口的請求做 SNAT,這樣訪問其他節點 Pod 的請求來源 IP 會被設置為 flannel.1 接口的 IP,導致目的 Pod 看不到真實的來源 Pod IP。 flanneld 創建的 SNAT 規則比較溫和,只對訪問非 Pod 網段的請求做 SNAT。

1.7 分發flannel systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp flanneld.service root@${master_ip}:/etc/systemd/system/
  7   done


二 啟動並驗證

2.1 啟動flannel

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh root@${master_ip} "systemctl daemon-reload && systemctl enable flanneld && systemctl restart flanneld"
  6   done


2.2 檢查flannel啟動

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh root@${master_ip} "systemctl status flanneld|grep Active"
  6   done



2.3 檢查pod網段信息

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# etcdctl \
  3   --endpoints=${ETCD_ENDPOINTS} \
  4   --ca-file=/etc/kubernetes/cert/ca.pem \
  5   --cert-file=/etc/flanneld/cert/flanneld.pem \
  6   --key-file=/etc/flanneld/cert/flanneld-key.pem \
  7   get ${FLANNEL_ETCD_PREFIX}/config			#查看集群 Pod 網段(/16)



  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# etcdctl \
  3   --endpoints=${ETCD_ENDPOINTS} \
  4   --ca-file=/etc/kubernetes/cert/ca.pem \
  5   --cert-file=/etc/flanneld/cert/flanneld.pem \
  6   --key-file=/etc/flanneld/cert/flanneld-key.pem \
  7   ls ${FLANNEL_ETCD_PREFIX}/subnets			#查看已分配的 Pod 子網段列表(/24)
  8 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  9 [root@k8smaster01 ~]# etcdctl \
 10   --endpoints=${ETCD_ENDPOINTS} \
 11   --ca-file=/etc/kubernetes/cert/ca.pem \
 12   --cert-file=/etc/flanneld/cert/flanneld.pem \
 13   --key-file=/etc/flanneld/cert/flanneld-key.pem \
 14   get ${FLANNEL_ETCD_PREFIX}/subnets/172.30.32.0-21	#查看某一 Pod 網段對應的節點 IP 和 flannel 接口地址




解釋:

172.30.32.0/21 被分配給節點 k8smaster01 (172.24.8.71);

VtepMAC 為 k8smaster01 節點的 flannel.1 網卡 MAC 地址。

2.4 檢查flannel網絡信息

  1 [root@k8smaster01 ~]# ip addr show



解釋:flannel.1 網卡的地址為分配的 Pod 子網段的第一個 IP(.0),且是 /32 的地址。

  1 [root@k8smaster01 ~]# ip route show |grep flannel.1
  2 172.30.128.0/21 via 172.30.128.0 dev flannel.1 onlink
  3 172.30.208.0/21 via 172.30.208.0 dev flannel.1 onlink



解釋:

到其它節點 Pod 網段請求都被轉發到 flannel.1 網卡;

flanneld 根據 etcd 中子網段的信息,如 ${FLANNEL_ETCD_PREFIX}/subnets/172.30.32.0-21 ,來決定進請求發送給哪個節點的互聯 IP。

2.5 驗證各節點flannel


在各節點上部署 flannel 后,檢查是否創建了 flannel 接口(名稱可能為 flannel0、flannel.0、flannel.1 等):

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh ${master_ip} "/usr/sbin/ip addr show flannel.1|grep -w inet"
  6   done



輸出:

  1 >>> 172.24.8.71
  2     inet 172.30.32.0/32 scope global flannel.1
  3 >>> 172.24.8.72
  4     inet 172.30.128.0/32 scope global flannel.1
  5 >>> 172.24.8.73
  6     inet 172.30.208.0/32 scope global flannel.1



在各節點上 ping 所有 flannel 接口 IP,確保能通:

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for master_ip in ${MASTER_IPS[@]}
  3   do
  4     echo ">>> ${master_ip}"
  5     ssh ${master_ip} "ping -c 1 172.30.32.0"
  6     ssh ${master_ip} "ping -c 1 172.30.128.0"
  7     ssh ${master_ip} "ping -c 1 172.30.208.0"
  8   done


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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

中國發佈《電動汽車充電基礎設施發展指南(2015-2020年)》

  各省、自治區、直轄市、新疆生產建設兵團發展改革委(能源局)、工業和資訊化主管部門、住房城鄉建設廳(委、局),國家電網公司、南方電網公司:   為落實《國務院辦公廳關於加快新能源汽車推廣應用的指導意見》(國辦發〔2014〕35號),科學引導電動汽車充電基礎設施建設,促進電動汽車產業健康快速發展,我們組織編制了《電動汽車充電基礎設施發展指南(2015-2020年)》,現予印發,請認真貫徹執行。  

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

簡單看看@RequestBody註解原理

       又到了很無聊的時候了,於是隨便看看源碼假裝自己很努力的樣子,哈哈哈;

  記得上一篇博客隨便說了一下RequestBody的用法以及注意的問題,這個註解作為非常常用的註解,也是時候了解一波其中的原理了。

    溫馨提示:閱讀本篇博客,默認你之前大概看過springmvc源碼,懂得其中的基本流程

1.HttpMessageConverter接口

  這個接口就是@RequestBody和@ResponseBody這兩個註解的精髓,我們就先看看這個頂層接口定義了哪些方法:

public interface HttpMessageConverter<T> {

    //判斷當前轉換器是否可以解析前端傳過來的數據
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

    //判斷當前轉換器是否可以將後端數據解析為前端需要的格式
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

    //當前轉換器能夠解析所有的數據類型
    List<MediaType> getSupportedMediaTypes();

    //這個方法就是讀取前端傳過來的數據
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;

    //將後台數據轉換然後返回給前端
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;

}

   

  我們從這個頂層接口中這幾個方法就大概能看到一些東西,可以肯定的就是在@RequestBody和@ResponseBody這兩個註解原理的內部轉換器應該都是實現了這個HttpMessageConverter,因為這個接口裡又是read,又是write;然後就是在上面我只是簡單說了前端傳過來的數據,返回給前端需要的格式這種模糊的說法,為什麼不直接說返回json格式的數據呢?

  哈哈,可能有的小夥伴會說,瑪德,你絕逼是怕說錯,才說這些模糊的說法;咳,當然有部分是這個意思,但是最大的原因就是上面方法參數中有個類MediaType,你打開看看就知道了,這裏定義了很多的可以解析的數據類型,比如”application/json”,”application/xml”,”image/gif”,”text/html”….等等,還有好多聽都沒聽過的;

  其實了解http請求的小夥伴應該已經看出來了,這裏這些數據類型就是下圖所示的這些;當然,我們暫時只關注json的,至於其他類型的怎麼解析有興趣的小夥伴可以研究研究;

 

 2.HandlerMethodArgumentResolver接口

  我們看看這個接口,看名字就知道應該是方法參數解析器,很明顯就是用於解析方法Controller中方法的參數的,還是簡單看看這個接口中的方法:

public interface HandlerMethodArgumentResolver {

    //該解析器是否支持解析Controller中方法中的參數,因為這裏參數類型可以是簡單類型,也可以是集合等類型
    boolean supportsParameter(MethodParameter parameter);

    //開始解析Http請求中的數據,解析出來的數據要和方法參數對應
    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

   這個接口定義的方法作用其實就是將http請求中的參數對應到Controller中的參數

 

3.HandlerMethodReturnValueHandler接口 

public interface HandlerMethodReturnValueHandler {

    //這個方法判斷該處理器是否支持返回值類型,這裏的返回值就是controller方法執行后的返回值
    boolean supportsReturnType(MethodParameter returnType);

    //將controller方法的返回值進行解析成前端需要的格式,後續就會丟給前端
    void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

   這個接口的作用:比如一個Controller方法中的返回值是一個集合,那麼springmvc內部在將數據返回給前端之前,就會先拿到所有的返回值解析器,然後遍歷每一個,分別執行supportsReturnType方法,看看哪個解析器可以解析集合類型,找到解析器之後,然後再執行handleReturnValue方法解析就行了,其實2中的方法參數解析器也是這樣的一個步驟

 

4.ServletInvocableHandlerMethod類

  這個類是干什麼的呢?看過springmvc源碼的人應該知道一點,還是簡單說說吧,在springmvc中會將controller中的每個被RequestMapping註解修飾的方法(也可以叫做處理器)給封裝成ServletInvocableHandlerMethod類,封裝后想要執行該處理器方法只需要執行該類的invokeAndHandle方法;

  請注意:就是在invokeAndHandle這個方法中會調用:調用方法參數解析器——>執行處理器方法——–>調用返回值解析器、

  可以簡單看看源碼,請一定要了解springmvc的流程,因為我不會從頭到尾講一遍,我們直接從DispatcherServlet中的doDispatch方法的ha.handle(xxx)這裏說起,這裏主要是執行處理器適配器的handle方法,這裏具體的處理器適配器實現是:AbstractHandlerMethodAdapter

  

  我們進入AbstractHandlerMethodAdapter這個適配器的handle方法看看(^o^)/:

//可以看到這裏就是調用了handleInternal方法,而handleInternal方法未實現
public final ModelAndView handle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception {
        return handleInternal(request, response, (HandlerMethod) handler);
    }


//這個方法在子類RequestMappingHandlerAdapter中實現
protected abstract ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response,HandlerMethod handlerMethod) throws Exception;

 

  接下來我們看看RequestMappingHandlerAdapter中實現的handleInternal方法(」゜ロ゜)」:

protected final ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response,HandlerMethod handlerMethod) throws Exception {

        //省略跟邏輯無關的代碼
                .......
               .........
        
        return invokeHandlerMethod(request, response, handlerMethod);
    }

 

  進入invokeHandlerMethod方法看看(´・_・`):

private ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response,HandlerMethod handlerMethod) throws Exception {
        
        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);

        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        //省略一些代碼

        //就是再這裏去執行Controller中的處理器方法
        requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

        //此處省略好多代碼
    }

 

  繼續進入到invokeAndHandle方法內部看看╮(╯_╰)╭:

public final void invokeAndHandle(NativeWebRequest request, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {
         //請注意,這裏面就是執行handler方法的位置
        Object returnValue = invokeForRequest(request, mavContainer, providedArgs);

        //省略一些代碼              

        try {
            //這裏就是執行我們前面說的返回值解析器
            returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
        } 
       //省略一些代碼
    }

 

  看看invokeForRequest方法你就能看到有趣的東西ヽ(”`▽´)ノ

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
                //這裏就是從request中拿到參數,利用方法參數解析器進行解析,映射到方法參數中,這個方法就在下面
                Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
        
               //省略一些代碼
        
                //這裏就是根據上一步將請求參數映射到處理器方法參數中,然後執行對應的處理器方法
               Object returnValue = doInvoke(args);
        
               //省略一些代碼
        
                return returnValue;
    }


private Object[] getMethodArgumentValues(NativeWebRequest request,@Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {
          //這裏獲取匹配到的handler方法的參數數組,每個參數在之前都被封裝成了一個MethodParameter對象,然後再遍歷這個數組,將其中每個MethodParameter和http請求提供的參數進行比較,
至於怎麼比較,就會用到之前說的參數解析器的那個support方法
MethodParameter[] parameters = getMethodParameters(); Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = resolveProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (this.argumentResolvers.supportsParameter(parameter)) { try { args[i] = this.argumentResolvers.resolveArgument( parameter, mavContainer, request, this.dataBinderFactory); continue; } //省略一些代碼 return args; }

 

     其實到這裏,有木有感覺清晰一點了,那麼肯定有小夥伴要問了,說了半天,你還是沒有說json是怎麼解析的啊?

  不要急,我們先把大概的流程過一遍之後,後面的都是小問題,那麼,我們的轉換器是在哪裡轉換的呢?

  欲知後事如何,請往後面看

 

5.無題

  在4中我們重點看兩個地方,第一個地方:this.argumentResolvers.supportsParameter(parameter);第二個地方:this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);

  5.1.RequestResponseBodyMethodProcessor

    第一個地方,我們點進去supportsParameter方法,

   

    

  然後我們進入getArgumentResolver方法內部(´□`川):

@Nullable
    private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
        HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
        if (result == null) {
             //for循環遍歷所有的方法參數解析器,
            for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
                
//省略一些代碼
//判斷哪一個解析器支持解析request中的參數,這裏很關鍵,因為眾多解析器中其中有一個參數解析器是RequestResponseBodyMethodProcessor,
          //下面我們看看這個解析器的supportParameter方法
if (methodArgumentResolver.supportsParameter(parameter)) { result = methodArgumentResolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

  

  RequestResponseBodyMethodProcessor的supportsParameter方法,這裏想必能看得懂吧,就是看Controller中的處理器方法中的參數前面有沒有RequestBody註解,有註解,那麼這個RequestResponseBodyMethodProcessor解析器就會生效

  對了,補充一點,這個解析器RequestResponseBodyMethodProcessor可是同時實現了方法參數解析器接口、返回參數解析器接口的哦,這說明了處理返回值解析器用的也是這個解析器

 

  5.2.執行argumentResolvers.resolveArgument()方法

//這個方法就到了最關鍵的地方了,注意了注意了
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) 

  throws Exception { //獲取一個轉換器,用於讀取前端傳過來的json數據 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType());

//獲取handler方法形參中的所有註解,例如@Valid。@PathVariable等 Annotation[] annotations = parameter.getParameterAnnotations();

     for (Annotation annot : annotations) {       //判斷如果是以valid開頭的註解,其實就是@Valid註解或者是@Validated註解,那麼就會去校驗是否符合規則嘛,這個不用多說         if(annot.annotationType().getSimpleName().startsWith("Valid")) { String name = Conventions.getVariableNameForParameter(parameter); WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); Object hints = AnnotationUtils.getValue(annot); binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints}); BindingResult bindingResult = binder.getBindingResult(); if (bindingResult.hasErrors()) { throw new MethodArgumentNotValidException(parameter, bindingResult); } } } return arg; }

  最後我們只需要輕輕點開readWithMessageConverters方法,就能看到更有意思的東西~^o^~

 

6.xxxConverter

  我們進入readWithMessageConverters這個方法,

@SuppressWarnings("unchecked")
    protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter methodParam, Class<T> paramType) throws IOException,
            HttpMediaTypeNotSupportedException {
            //這裏回答了本篇最開始說的MediaType 到底是什麼東西,從哪裡獲取的,很明顯是從請求頭中的ContentType獲取的
             MediaType contentType = inputMessage.getHeaders().getContentType();
            if (contentType == null) {
                 contentType = MediaType.APPLICATION_OCTET_STREAM;
            }
            //獲取所有的HttpMessageConverter,遍歷,看看哪一個轉換器支持前端傳過來的數據類型
            for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
                 if (messageConverter.canRead(paramType, contentType)) {
//調用對應的轉換器的read方法去把前端傳過來的json字符串轉為java對象
return ((HttpMessageConverter<T>) messageConverter).read(paramType, inputMessage); } } //省略一些代碼 }

  

   到了這裏肯定有人會說,那到底用的是哪一個轉換器呢?難道是要我們自己導入?還是默認已經導入轉換器了呢?

  當然是默認就為你初始化了一些轉換器了啊,如果你想自定義也行,而且仔細看看下圖中跟json有關的只有MappingJackson2HttpMessageConverter這個轉換器了,可想而知這個轉換器(實際上是這個轉換器的父類方法中才有具體的操作)中使用的就是開源的Jackson來將json字符串轉為java對象的,有興趣了解的可以使用一下Jackson自己嘗試一下;

  偷偷告訴你(҂ ˘ _ ˘ ),springboot默認已經導入了Jackson包,如果你後期想用其他的轉換器,只需要導入相關依賴就ok了;

  

 

 

7.結束

  這篇博客到這裏就差不多了,寫了好久,邊寫邊查資料,可以說每次看源碼都能學到新的東西,當然,我也沒有死磕精神,不是不想,主要是沒有那個水平,哈哈;

  其實還要寫還能寫,不是還有個@ResponseBody原理還沒說嗎?其實跟@RequestBody大同小異的,有興趣的可以在第4點最後的代碼中返回值參數處理器方法,這裏就是入口

  話說還有個問題沒有解決,本來我想找一下最後的那幾個轉換器初始化時機的,然後實在是找不出來啊,查了一下資料,都說是在處理器適配器的構造器中初始化這些轉換器的,哎,jdk1.8,我在適配器中找了好久,愣是沒找到,打斷點也調試不出來,把自己坑了好久;

  有沒有大哥知道初始化時機的,評論一下,謝謝了(ㄒoㄒ)

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

第二次汽車下鄉政策或啟動 新能源汽車將成為受益者?

據報導,中國將啟動新一輪汽車下鄉政策,1.6升以下乘用車、微型客貨、皮卡等輕型貨車將納入產品範圍。與此同時,中國還計畫加大停車場和新能源汽車充電基礎設施建設力度。

分析人士認為,二三線城市及四五線的農村的汽車保有量較低,剛性需求較大,預計將成為未來汽車市場增長的主力。

中國品牌汽車與新能源汽車有望雙提升

據中汽協發佈的10月份汽車產銷資料來看,1-10月,中國乘用車累計銷售1648.47萬輛,中國品牌乘用車共銷售675.71萬輛,同比增長12.58%,乘用車銷售總量的40.99%,佔有率比上年同期提升3.16個百分點。

根據乘聯會廠家資料,2015年4季度的新能源乘用車出現爆發增長態勢。11月的新能源乘用車銷量24664台,暴增2.4倍,其中插電混合動力達到7599台,純電動車達到17065台。

一旦新一輪汽車下鄉政策實施,加之新能源汽車充電基礎設施建設力度不斷提升,這不僅將為二三線甚至四五線的消費者帶來更多新車選擇,更將帶動中國汽車品牌以及新能源汽車產銷實現新突破。

可以預見,即將到來的“第二次汽車下鄉”,有望對“十三五”開局之年的汽車產業和發展注入新的動力這一方面會進一步刺激中國品牌車企加速對四五線市場的深耕;另一方面,新能源汽車廠家的佈局與規劃能否滿足未來的市場需求,一切都尚待觀察。

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

為何特斯拉 Model S 有高滿意度,「擁有好的客服不怕產品出包」

俗話說早起的鳥兒有蟲吃,不過早買的消費者買到的第一批產品常常問題最多,因為日後的產品,隨著製造技術與經驗進步,以及收到第一批產品的問題回報,品質會逐漸改進。電動車也不例外,美國電動車及油電混合車推動組織 Plug In America 分析報告顯示,特斯拉(Tesla)Model S 電動車,其 2012 ~ 2013 年款的早期車主,可能有高達三分之二行駛 6 萬英里(9.66 萬公里)就需要更換傳動系統。

Plug In America 的分析報告資料來自 370 名車主,其中 43 名擁有 2014 ~ 2015 年份 Model S,由於是新買的車,行駛里程尚未超過 2 萬英里,而根據 327 名早期購買的車主資料進行數學運算分析,預測有 66% 車主行駛 6 萬英里就需要更換傳動系統。不過需要更換傳動系統不代表傳動系統已經故障損壞,因為特斯拉的政策是,一旦傳動系統開始發出不正常雜音就提早換新,而不是等到傳動系統真的故障損壞才換修,另外由於特斯拉保固 8 年,換新對車主也不會造成額外負擔。   這份資料也說明了為何 Model S 遭到一些負面評價,如美國消費性商品評鑑雜誌《消費者報告》(Consumer Reports)把 Model S 從推薦名單中除名,其原因就是認定其「問題發生率高於平均」。日後特斯拉多次表示其技術與經驗進步讓產品品質大幅提升,2015 年 11 月時更表示將故障率降至原有的一半,執行長伊隆‧馬斯克(Elon Musk)也對近幾個月出貨的傳動系統表示信心滿滿。   不過,到底特斯拉的製造品質是否提升,恐怕要等 2014 ~ 2015 年的車輛行駛更久才能見真章。   無論如何,可以確定的一點是,Model S  仍銷售破 10 萬輛,而《消費者報告》指出,儘管問題發生率高於平均,特斯拉車主的滿意度卻居高不下,有高達 97% 車主說會再買特斯拉,原因在於高效率的客服,以最快速度幫助消費者解決問題,不論是馬達、差速器、剎車、資訊系統出問題,都以最不讓消費者困擾的方式盡速更換,「誠意」讓人滿意。   新創產品總是難免有許多意料之外的問題,特斯拉的例子或許可以成為很好的範例,不論是硬體產品還是服務,爛的客服能把好產品弄臭,好的客服讓產品出包也無妨,這天差地別,業者可得戒慎恐懼。

(首圖來源: CC BY 2.0)    (本文授權轉載自《》─〈〉)

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

2016中國‧重慶國際電動汽車產業展

時間: 2016年5月19日-21日  
地點: 中國•重慶國際博覽中心
主辦單位:中國國際貿易促進委員會重慶市委員會、重慶市電動汽車行業協會(籌)
承辦單位:重慶鼎臻會展服務有限公司
同期展會:第十九屆中國(重慶)國際投資暨採購會(渝洽會)

一、展會前沿

2015年5月24日,國家主席習近平考察上汽集團時指出:“汽車行業市場很大,發展新能源汽車是我國從汽車大國邁向汽車強國的必由之路,要加大新能源汽車的研發力度,開發適應各種需求的產品,使之成為一個強勁的增長點”。國務院總理李克強2015年9月到10月多次主持召開國務院常務會議部署加快電動汽車充電基礎設施和城市停車場建設,補公共服務短板促進擴內需惠民生。國家在2014、2015年2年期間出臺30余項電動汽車產業專題扶持政策,大力發展電動汽車產業,電動汽車產業成為國家戰略。同時一系列有利於消費者購買電動汽車的補貼政策陸續出臺和規模宏大的電動汽車充電樁建設計畫快速部署推動了我國電動車產業的快速發展。尤其是2015年,電動汽車產銷量的增加直接刺激了社會研發力量的加強、業內企業的高度關注和投資熱情的高漲,資料顯示,1- 9月份,我國市場電動汽車銷售量同比增加135%,成為全球最大的電動汽車銷售市場。

重慶作為國內最大汽車生產基地,是我國發展電動汽車最早的城市之一,具有汽車產業聚集度高、科技研發實力雄厚、電動汽車領域人才豐富、政府高度重視等優勢。為了積極回應國家大力發展新能源電動汽車的戰略規劃,進一步利用和發揮重慶汽車產業優勢,特由重慶貿促會牽頭舉辦2016中國•重慶國際電動汽車產業展,本屆展會以“創新、共用、綠色”為主題,將為全國電動汽車整車企業、電動汽車配套服務企業、汽車經銷商、電動汽車材料研發製造企業及相關科研機構等搭建展覽展示、學術研討、銷售推廣及合作交流平臺。

二、展會內容

(一)時間安排
1.報到布展:2016年5月17日-18日
2.展出時間:2016年5月19日-21日
3.撤展時間:2016年5月21日下午15:00

(二)展覽展示
展示面積:25000㎡      展商數量:預計260家      整車品牌:30家
展區規劃:1.電動汽車整車品牌展示交易區
2.電動汽車充電設施與技術展示區
3.電動汽車新材料與輕量化技術展示區
4.智慧汽車與車聯網應用展示區
5.電動汽車電池、電機與控制系統展示區
6.電動汽車製造技術裝備與零部件展示區

(三)配套活動
1.中國•重慶電動汽車萬人試乘試駕活動
2.中國電動汽車新材料與輕量化發展論壇
3.2016中國•重慶石墨烯產業創新發展論壇
4.首屆中國電動汽車經銷商大會
5.中國電動與智慧汽車發展論壇

(四)專題展設置
1.中國•重慶國際電池工業展
2.中國•重慶國際充電站(樁)技術設備展
3.中國電動物流車推廣應用展
4.中國•重慶國際電動客車與城市公交應用展
5.中國•重慶國際智慧汽車及車聯網技術展
6.中國•重慶國際電動汽車驅動及控制系統展

(五)展會優勢
1.擁有“國內最大汽車生產基地”作為展會的產業支撐。
2.是國內唯一一個隻專注於“電動汽車”展示推廣平臺,突顯專業性。
3.B2C和B2B兩種展會理念的有效結合,實現了產銷和供需同台。
4.將為終端應用商、電動汽車製造廠商與配套服務商等舉辦參與性強、體驗度高、關注度高的專業活動。
5.展會自身的新聞媒體宣傳與“渝洽會”的本地影響力,將有效保障專業觀眾數量和展會影響力。

(六)宣傳推廣
1.在大眾媒體和專業網媒、紙媒投放展會廣告並定期推送展會資訊。
2.利用新媒體對展會進行全天候推廣和宣傳。
3.向重慶市各機關單位、大型國企、商協會等發放參觀券和門票。
4.展前一個月將組織人員在重慶各商圈、金融中心、商務樓宇、高檔社區等地方造勢宣傳並發放參觀門票。
5.與部分行業媒體和協會達成戰略合作關係,不定期、不間斷向行業企業、行業人士發送邀請函和展會簡報,利用網路媒體的宣傳覆蓋優勢宣傳本次展會,盡可能的吸引主辦方未能邀請到的潛在觀眾。
6.展會期間除合作的專業媒體外還邀請大眾媒體全面報導開幕式及展會現場盛況,並對行業內有影響力的參展企業作專題採訪、報導。

(七)收費與合作  
1.展位收費:
標準展位(3m×3m):8900元/個,角標9800元/個。  
室內空地(最少36㎡):980元/㎡。
2.其他廣告:展會還設置了會議資料、會刊、證卡和現場廣告宣傳,具體宣傳方式和收費情況請致電詳詢洽談。
3.展會合作:本次展會及舉辦的會議活動都將面向全行業企業征邀協辦、贊助和合作單位,具體合作方式和權益彙報內容可致電詳詢洽談。

(八)參展參會
1.參展:欲參展單位提前確定參展面積和展位位置,同時索取《參展合同》認真填寫並蓋章以傳真或郵件的方式傳至大會組委會,並於7日內將參展費用匯至組委會指定帳號,組委會將依據“先報名、先付款、先安排”的原則確定展位。
2.參會:參觀參會企業和代表根據展會安排、會議設置填寫《專業觀眾回執表》、《參會回執表》並蓋章以傳真或郵件的方式傳至大會組委會。
3.服務:組委會將為參展參會企業和代表提供展位搭建、廣告製作、交通住宿、物品租賃、商務考察、會議策劃、合作對接等綜合性、專業性服務,具體內容可見《展商服務手冊》,其他可致電組委會諮詢。

三、聯繫方式  
連絡人:祝航 +86 18580108949     
電  話:+86 23-67951625       
傳  真:+86 23-67072100      
郵  箱:
網  址:       

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

工信部: 2015年中國累計生產新能源汽車37.90萬輛 同比增長4倍

據中國工業和資訊化部裝備工業司11日發佈消息,2015年中國累計生產新能源汽車37.90萬輛,同比增長4倍。

其中,純電動乘用車生產14.28萬輛,同比增長3倍;插電式混合動力乘用車生產6.36萬輛,同比增長3倍。純電動商用車生產14.79萬輛,同比增長8倍;插電式混合動力商用車生產2.46萬輛,同比增長79%。

此外, 2015年12月,中國新能源汽車生產9.98萬輛,同比增長3倍。其中,純電動乘用車生產2.57萬輛,同比增長114%,插電式混合動力乘用車生產1.05萬輛,同比增長2倍;純電動商用車生產5.78萬輛,同比增長6倍,插電式混合動力商用車生產5725輛,同比增長51%。
 

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

研究:行星行撞地球之前 恐龍已面臨大氣汞污染

編譯:嚴融怡(胡適國小創思組科任教師)

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

2016中國(中原)國際充電站(樁)技術設備展覽會

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

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!