學習源碼的第八個月,我成了Spring的開源貢獻者_網頁設計

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

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

我的經歷

關注我的朋友都知道,關注兩個字划重點,要考!

我最近一直在寫Spring的文章,而且僅僅是Spring FrameWork的文章 ,從最開始的官網入門到現在源碼的深度分析。主要就是三個系列

官網入門系列,Spring官網讀書筆記,這一系列的文章是入門Spring的不二之選,也是後續源碼閱讀的基礎

雜談系列,Spring雜談,這主要是一些補充內容,可以幫助大家更全面學習到Spring中的各個知識點,同時也會分享一些源碼閱讀技巧,個人學習心得之類的,雜談嘛,就是不知道放哪裡的文章都打算放這裏,比如這篇文章。

源碼分析系列,Spring源碼解析,該專欄目前正在創作中,相對而言學習難度比較大,而且因為筆者寫的比較細,估計大部分同學看起來會很費勁,不過如果你能認真看完,收穫絕對巨大!當然有不懂得地方也可以給筆者留言,或者關注文章末尾的公眾號。

本文的主要目的是教(zhuang)學(bi)

就是從筆者的實際經驗出發,談一談怎麼成為一個開源項目的貢獻者

我先說說我自己的經歷吧,在創作上篇文章的時候,筆者發現Spring在實例化對象的時候有這麼一段代碼,在org.springframework.beans.factory.support.ConstructorResolver#resolveConstructorArguments方法中

// 本文不探討技術細節,只是為了簡單說明這個問題,所以省略無關代碼	
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

      // ....
		for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
			int index = entry.getKey();
			if (index < 0) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid constructor argument index: " + index);
			}
            // 問題就出在這裏
			if (index > minNrOfArgs) {
				minNrOfArgs = index + 1;
			}
       // ..... 

上述代碼中,minNrOfArgs這個變量就是保存方法需要的最小參數個數,但是index是下標索引,索引是從0開始的,如果有下標為n的元素,那麼最小的參數個數應該是n+1嘛,所以if中的邏輯是沒有問題的,但是if這個判斷是有問題的,正確的做法應該是

if (index+1 > minNrOfArgs) {
    minNrOfArgs = index + 1;
}

當發現這個問題的時候,第一反應就是肯定是我的姿勢不對,錯的怎麼可能是代碼,肯定是我!

接下來,我就對這段代碼進行了慘無人道的調試,在無數次debug后,我發現,這個地方確實有問題!

在確認了這個問題之後,我要思考的就是怎麼把自己的想法反饋給Spring,換而言之,怎麼為偉大的開源來做貢獻呢?正常來要達到這個目的有兩個方式

  • 提交issue
  • 直接在GitHub上提交PR(pull request)

對應的就是在GitHub上點擊下圖紅框選中的兩個位置

如果是使用提交issue的方式,相當於給官方團隊提交了一個議題,這個議題可能是你發現代碼中的某個bug,也可能是你覺得官方的做法不夠好,你有更好的想法等等。感興趣的話,大家可以去看看Spring中現在有哪些還未關閉的issue,說不定其中一個你就能解決呢~!

如果要採用提交PR的方式的話,首先你得將代碼fork到自己的GitHub中,然後在從自己的GitHub檢出到本地,在本地做完修改后,提交到GitHub倉庫中,最後從自己的GitHub向Spring官方倉庫發起一個PR。

像我的話很早就已經將代碼fork到了自己GitHub

上圖中的第一個紅框,說明我這個倉庫是從Spring官方fork過來的,第二個紅框就是可以從這裏向Spring官方提交一個PR。關於詳細的如何提交PR,大家可以自行百度,這裏不做詳細的介紹了。

另外,說了這麼多,先給大家看下我提交的issue吧。

issue鏈接:https://github.com/spring-projects/spring-framework/issues/25130

因為內容也不長,所以我這裏把原文就直接放到下面了

In ConstructorResolver:

private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
		TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
		// ...

		for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
			int index = entry.getKey();
			if (index < 0) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid constructor argument index: " + index);
			}
			if (index > minNrOfArgs) {
				minNrOfArgs = index + 1;
			}
			// ....
		}
// ....
 return minNrOfArgs;
}

I assume that method resolveConstructorArguments is to resolve contructor arguments in the XML file and return the minimum number of parameters required by contructor 。but if the first parameter is autowired , the second parameter is config by XML file,the method will not work well。

example:

public class FactoryObject {
	
 public DmzService getDmz(String name, int age, Date birthDay, OrderService orderService) {

	public DmzService getDmz(OrderService orderService,String name) {
		
		return new DmzService(orderService,name);
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
	   default-autowire="constructor">
	<bean id="factoryObject" class="com.dmz.spring.first.instantiation.service.FactoryObject"/>

	<bean class="com.dmz.spring.first.instantiation.service.OrderService" id="orderService"/>

	<bean id="dmzService" factory-bean="factoryObject" factory-method="getDmz">
		<constructor-arg index="1"  value="dmz"/>
	</bean>

</beans>

the resolveConstructorArguments method will return 1,but correct answer is 2。

I think the problem arises because of this judgment:

if (index > minNrOfArgs) {
 minNrOfArgs = index + 1;
}

It might be better to change it to look like this

if (index + 1 > minNrOfArgs) {
 minNrOfArgs = index + 1;
}s

我在提交issue時主要是按照這種思路

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

  1. 首先擺出有問題的代碼
  2. 描述具體的問題,我是直接通過一個例子來描述的
  3. 說出自己的建議

這幾天我又多看了看別人提交的issue,對比起來,我覺得至少應該還要添加一點

  • 應該要明確的指出具體哪個版本上出現的問題

碰到的問題

1、擔心鬧烏龍

雖然在之前我已經調試過了無數次代碼,但是心裏還是沒譜啊。畢竟我這麼謹(cai)慎(ji)的一個人,萬一被人噴了怎麼辦?不知道你會不會這麼想,反正我當時就是這麼想的,如果你是這麼想的,建議你去看看別人提交的issue。搜索條件如下

is:closed label:”status: invalid”

我覺得你看幾個,自然就有信心了!

2、不知道要怎麼提交

每個開源的項目,只要作者希望這個項目越來越好的話,都會詳細的說明如何給這個項目做開源貢獻,Spring肯定也不例外,這裏還是以提交issue為例,當你點擊New issue的時候會出現下面這張圖

在上圖左邊的框里很明確的告訴了你提交issue應該要注意什麼

  • 首先,你應該要去Stack Overflow提問
  • 如果是bug,你應該要指明版本以及你想要做什麼
  • 如果是一個增強的話,要提供上下文並且描述清楚問題
  • 同一個問題,issue跟PR最好只提交一個,因為GitHub認為它們是一樣的,如果你還不能確定的話,先提交一個issue

而右上角還有更加詳細的文檔可供參考。

3、英文

大家應該看到了,整個issue都是用英文寫的,那麼英文不好怎麼辦呢?這個時候就要掏出我們的神器了

嗯,就是詞典,筆者習慣是使用有道詞典。我建議英文不好的同學可以這樣,先將整個issue用中文寫好,如果你真的英文一竅不通的話,可以直接通過翻譯軟件逐句翻譯,然後粘貼到GitHub上。但是千萬千萬不要使用中文,就像下面這個哥們

issue鏈接:https://github.com/spring-projects/spring-framework/pull/25127

像這種issue是會被直接打上invalid(不合格)標籤的,你就想想吧,你學不會英文,你指望我們的外國朋友能看懂中文嘛?是我中華上線五千年的文化不夠博大精深嗎?

4、擔心問題描述的不清楚

其實這個問題就是因為英文不好衍生出來的。因為英文不好,自然就會擔心我寫的東西他能不能看懂呢?我的建議就是,結合你測試的代碼去描述問題。你不用去擔心別人看不懂你寫的代碼,就以我那個issue的處理流程為例吧。

在你剛剛提交issue時,有專門的issuemaster(issue管理員)會給你提交的issue打上一個wait-for-triage的標籤,標誌這個issue是待處理的。

隨後我提交的這個issue,就被指派給了jhoeller。你要擔心他看不懂代碼嗎?給你看兩個東西吧

你知道那個紅框是啥意思嗎?就是說我發現的那個有問題代碼的類的作者就是他。

再看一張

就是說,jhoeller從2003年開始就已經是Spring這個項目的管理者以及發布經理了。2003年,我還是一個小學生……..

所以啊,只要你稍微正常點,基本上人家都能get到你的點。

給你的建議

其實筆者從發現這個問題到最終提交issue大概經過了一周時間,期間一直在猶豫要不要提交issue,就是因為上面提到的幾個問題,一直躊躇不前。但是等我下定決心要去做這件事的時候總共就花了幾個小時的時間。包括研究issue提交的規則以及寫一篇英文版的issue。並且我提交issue的第二天就馬上被處理了,並且jhoeller在 f9aae8d 這個commit中已經接受我的建議。

所以我要說的就是,

真正動手的話,不管什麼問題總能找到解決方案

而只是停留在空想,在躊躇,你永遠有一堆問題

臨淵羡魚,不如退而結網

以此文與君共勉!

如果本文對你由幫助的話,記得點個贊吧!也歡迎關注我的公眾號,微信搜索:程序員DMZ,或者掃描下方二維碼,跟着我一起認認真真學Java,踏踏實實做一個coder。

我叫DMZ,一個在學習路上匍匐前行的小菜鳥!

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

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

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

初窺Ansible playbook_貨運

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

Ansible是一個系列文章,我會盡量以通俗易懂、詼諧幽默的總結方式給大家呈現這些枯燥的知識點,讓學習變的有趣一些。
Ansible系列博文直達鏈接:Ansible入門系列

前言

在上一篇文章中說到Ansible有兩種玩法,一種是Ansible Ad-Hoc,另一種是就是這裏要說的playbook。playbook是Ansible進行配置管理的組件,雖然Ansible的日常Ad-Hoc命令功能很強大,能完成一些基本的配置管理工作,但是Ad-Hoc命令無法支撐複雜環境的配置管理工作。在我們實際使用Ansible的工作中,大部分時間都是在編寫playbook,接下來就重點說說如何玩轉這個playbook。

執行playbook命令

我們都是按照yaml語法規則來編寫playbook,至於yaml怎麼玩,後面的文章我會總結一下的。在我們按照要求編寫好了yaml文件后,如何來執行這個yaml文件呢?

Ansible提供了一個單獨的命令:ansible-playbook命令,我們可以通過這個命令來執行yaml腳本。常見的ansible-playbook的使用方法如下:

最簡單的使用方法:

ansible-playbook copyDemo.yaml

我們還可以使用以下命令查看輸出的細節:

ansible-playbook copyDemo.yaml --verbose

我們也可以使用以下命令查看該yaml腳本將影響的主機列表:

ansible-playbook copyDemo.yaml --list-hosts

還可以使用以下命令檢查yaml腳本語法是否正確:

ansible-playbook copyDemo.yaml --syntax-check

上面的幾種使用方法基本就涵蓋了我們日常工作中80%的場景了,剩餘的20%場景,比如并行、異步等,很少用到,等真正用到的時候再去查閱相關資料也來的及。而工作中,更多的時候,我們不是在編寫playbook,就是在編寫playbook的路上。所以,接下來我重點說說如何寫這個playbook,也就是playbook的基本語法。

playbook基本語法

最基本的playbook腳本分為三個部分:

  1. 在哪些機器上以什麼身份執行
  2. 執行的任務有哪些
  3. 善後任務有哪些

我們在編寫playbook腳本的時候,總是離不開上面的三個部分的。下面先來一個稍微有點複雜的playbook腳本,讓大家先有一個整體的認識。

---
- hosts: server1
  user: root
  vars:
    http_port: 80
    max_clients: 200

  tasks:
    - name: Write apache config file
      template: src=/home/test1/httpd.j2 dest=/home/test2/httpd.conf
      notify:
        - restart apache
    - name: Ensure apache is running
      service: name=httpd state=started

  handlers:
    - name: restart apache
      service: name=httpd state=restarted

現在就對上述三部分稍作詳細總結。

主機和用戶

上面的yaml腳本,我們一開始就會看到hostsuservars,其中vars在後面的文章進行專門總結。而這裏的hostsuser就是表示我們這個yaml將要在哪些主機上用哪個用戶身份去操作。而這裏的深一層次的關係如下錶所示:

key 含義
hosts 為主機的IP,或者主機組名,或者關鍵字all
user 在遠程以哪個身份執行
become 切換成其他用戶身份執行,值為yes或者no
become_method 與become一起使用,值可以為sudo/su
become_user 與become一起使用,可以是root或者其它用戶名

在實際工作中,如果我們不指定user時,則默認使用連接遠程主機的用戶進行操作,如果指定了執行用戶而與ansible_ssh_user指定用戶不一致時,則需要開啟become操作,這裏的become配置與ansible.cfg中配置將相互配合完成工作,yaml中的become優先級高於ansible.cfg中配置中的優先級。

任務列表

任務列表是整個playbook的核心,對於任務列表,我們首先需要知道以下三點內容:

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

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

  • 任務是從上到下順序執行的,如果中間發生錯誤,那麼整個playbook會中止;
  • 每一個任務都是對模塊的一次調用,只是使用不同的參數和變量而已;
  • 每一個任務最好有一個name屬性,這樣在執行yaml腳本時,可以看到執行進度信息。

對於任務的參數有兩種不同的寫法,我們在編寫yaml腳本時,可以按照自己的喜好進行選擇。

寫法一:

- name: Write apache config file
  template: src=/home/test1/httpd.j2 dest=/home/test2/httpd.conf

寫法二:

- name: Write apache config file
  template: 
    src: /home/test1/httpd.j2
    dest: /home/test2/httpd.conf

這兩種寫法都是OK的,我一般喜歡第二種寫法。

最後,對於任務我們還需要特別一個點,那就是任務的執行狀態。我們在執行Ansible Ad-Hoc或者ansible-playbook的時候,在輸出中都會有一個changed字段,比如:

192.168.1.3                : ok=2    changed=0    unreachable=0    failed=0  

或者

192.168.1.3                : ok=2    changed=1    unreachable=0    failed=0

這裏的這個changed就是人物的執行狀態,但是它為什麼一會是0,一會有是1呢?這就要說到Ansible中一個叫做“冪等性”的概念。

冪等性

冪等性是數學和計算機科學上一個常見的概念,多次執行產生的結果不會發生改變,這樣的特性就被成為冪等性。

大多數的Ansible模塊在設計時保證了冪等性,冪等性保證了Ansible腳本多次執行情況下的相同結果,盡可能的避免使用那些不能滿足冪等性的模塊。比如我們經常使用的shell模塊就是非冪等性的。

我們要明白Ansible是以“結果為導向的”,我們指定了一個“目標狀態”,Ansible會自動判斷“當前狀態”是否與“目標狀態”一致,如果一致,則不進行任何操作;如果不一致,那麼就將“當前狀態”變成“目標狀態”,這就是“冪等性”,“冪等性”可以保證我們重複的執行同一項操作時,得到的結果是一樣的。

那這個冪等性與上面的changed又有什麼關係呢?且聽我下面慢慢道來!

  • changed為false或者0時,表示Ansible沒有進行任何操作,沒有“改變什麼”;
  • changed為true或者大於0時,表示Ansible執行了操作,“當前狀態”已經被Ansible改變成了“目標狀態”。

copy這個模塊來舉例子說明,當我們準備將一個文件通過Ansible拷貝到遠程主機時,copy模塊首先檢查遠程是否已經存在了該文件,如果不存在,則把文件拷貝過去,返回changed為大於0;如果存在時,則開始比對兩個文件的md5值,如果md5值一致,則說明兩個文件是一樣的,則不需要拷貝,此時copy模塊則什麼都不幹,返回changed為0。

總結

通過三篇文章總結了Ansible中的常用模塊、Ansible Ad-Hoc和ansible-playbook的一些慣用用法,從我的實際學習經驗來說,學到這裏,你可以將這三塊內容結合起來使用了,至少可以在你們生產環境鼓搗一下了。生來就是折騰,更何況我們這麼拚命、努力的學習呢!

果凍想,認真玩技術的地方。

2019年5月18日,於內蒙古呼和浩特。

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

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

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

面試官問我會不會Elasticsearch,我語塞了…_網頁設計公司

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

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

少點代碼,多點頭髮

本文已經收錄至我的GitHub,歡迎大家踴躍star 和 issues。

https://github.com/midou-tech/articles

從今天開始準備給大家帶來全新的一系列文章,Elasticsearch系列

新系列肯定會有很多疑惑,先為大家答疑解惑,下面是今天要講的問題

為什麼寫Elasticsearch系列文章?

之前在文章中也陸陸續續的提到過,龍叔是做搜索引擎的。搜索引擎技術屬於商業技術,大家耳熟能詳的百度搜索,Google搜索,這可都是因為把握核心搜索技術,從而誕生了商業帝國。

每個互聯網大廠都想去分一杯搜索的羹,360搜索、神馬、頭條、搜狗搜索等等,由此可見搜索技術的商業作用和機密性了。

搜索把握用戶的入口

蘑菇街的搜索引擎是一款使用C++開發、完全自研、沒有開源的搜索引擎,沒有開源就是不能隨便寫出來的。

但是現在不一樣了

第一、我離職了,離開了意味着不在持有那些商業機密了,就算不講出來我也沒啥心理負擔(但還是不能講的,離職協議寫的很清楚,不能泄露公司商業機密)。

第二、去新的公司還是在搜索領域,他們用Es Elasticsearch是一個開源搜索,開源的東西可以隨便說,但還是不能說公司的商業數據

自己一直在搜索領域做,輸出搜索相關的文章,第一個可以讓自己更好的學習和總結,第二個可以讓粉絲們了解到搜索這個神秘的技術,增加大家自身的核心競爭力。

後面會說到,Elasticsearch是搜索引擎,但不簡單隻能使用在搜索領域,他可以作用的場景非常多。

Elasticsearch是什麼?

Elasticsearch 是一個分佈式的開源搜索分析引擎,適用於所有類型的數據,包括文本、数字、地理空間、結構化和非結構化數據。

Elasticsearch 在 Apache Lucene 的基礎上開發而成,Elasticsearch 以其簡單的 REST 風格 API、分佈式特性、速度和可擴展性而聞名,是 Elastic Stack 的核心組件。

Elastic Stack 是適用於數據採集、充實、存儲、分析和可視化的一組開源工具。人們通常將 Elastic Stack 稱為 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列豐富的輕量型數據採集代理,這些代理統稱為 Beats,可用來向 Elasticsearch 發送數據。

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

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

Elasticsearch 的實現原理主要分為以下幾個步驟,首先用戶將數據提交到Elasticsearch 數據中心,再通過分詞控制器去將對應的數據分詞,將其權重和分詞結果一併存入數據,當用戶搜索數據時候,再根據權重將結果排名,打分,再將返回結果呈現給用戶。

是什麼差不多搞清楚了,再說說ES都哪些成熟的應用以及在哪些領域使用。

Elasticsearch在哪些領域使用?

  • 應用程序搜索
  • 網站搜索
  • 企業搜索
  • 日誌處理和分析
  • 基礎設施指標和容器監測
  • 應用程序性能監測
  • 地理空間數據分析和可視化
  • 安全分析
  • 業務分析

Elasticsearch有哪些特點?

Elasticsearch 很快。 由於 Elasticsearch 是在 Lucene 基礎上構建而成的,所以在全文本搜索方面表現十分出色。Elasticsearch 同時還是一個近實時的搜索平台,這意味着從文檔索引操作到文檔變為可搜索狀態之間的延時很短,一般只有一秒。因此,Elasticsearch 非常適用於對時間有嚴苛要求的用例,例如安全分析和基礎設施監測。

Elasticsearch 具有分佈式的本質特徵。 Elasticsearch 中存儲的文檔分佈在不同的容器中,這些容器稱為分片,可以進行複製以提供數據冗餘副本,以防發生硬件故障。Elasticsearch 的分佈式特性使得它可以擴展至數百台(甚至數千台)服務器,並處理 PB 量級的數據。

Elasticsearch 包含一系列廣泛的功能。 除了速度、可擴展性和彈性等優勢以外,Elasticsearch 還有大量強大的內置功能(例如數據匯總和索引生命周期管理),可以方便用戶更加高效地存儲和搜索數據。

Elastic Stack 簡化了數據採集、可視化和報告過程。 通過與 Beats 和 Logstash 進行集成,用戶能夠在向 Elasticsearch 中索引數據之前輕鬆地處理數據。同時,Kibana 不僅可針對 Elasticsearch 數據提供實時可視化,同時還提供 UI 以便用戶快速訪問應用程序性能監測 (APM)、日誌和基礎設施指標等數據。

學習Elasticsearch能提高哪些競爭力?

看到Elasticsearch在這麼多的領域在使用,特點也這麼明顯。看到這裏估計都不用在說什麼核心競爭力,你已經意識到了。

Elastic 於 2018 年 6 月 29 日正式推出 Elastic Certified Engineer 認證考試,認證通過可以獲得官方頒發的證書和徽章,title就是 Elastic認證工程師

具體認證的細節和含金量,沒有具體研究過,但是可以很明顯的感受到官方出了這樣一個認證,表明社會需要大量這樣的人才,而這方面人才的培養和考核指標還欠缺。

有沒有必要一定要考這個認證?

個人覺得,和英語四六級一樣,通過了再說沒用。

如果你是學生,可以考慮去考一個認證,因為你很難有業務場景驅使你去做這方面的成長,認證一定是有難度的,一個一個的困難會驅使你成長,最終這個認證也會成為招聘時一個非常大的亮點。

這個認證會有哪些幫助?

  • 對於快速的構建知識體系幫助。

  • 對於全面的熟悉官方文檔幫助。

  • 對於實戰解決線上問題幫助。(遇到了相關技術問題基本上不需要再求助於社區,80%以上的問題自己基本就能解決。)

  • 對於增強信心、克服英文恐懼幫助。

Elasticsearch 支持哪些編程語言?

  • Java
  • JavaScript (Node.js)
  • Go
  • .NET (C#)
  • PHP
  • Perl
  • Python
  • Ruby

哪裡可以找到有關 Elasticsearch 的更多信息?

  • Elasticsearch GitHub 存儲庫:https://github.com/elastic
  • Elasticsearch 官方文檔:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
  • Elasticsearch中文社區:https://elasticsearch.cn

我是龍叔,一個分享互聯網技術和心路歷程的star。

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

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

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

居然還有人這樣解說mybatis運行原理_台中搬家

台中搬家公司費用怎麼算?

擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司

目錄

  • Mybatis基本認識
    • 動態代理
      • JDK實現
      • CGLIB動態代理
      • 總結
    • 反射
  • Configuration對象作用
  • 映射器結構
  • sqlsession執行流程(源碼跟蹤)
    • Executor
    • StatementHandler
    • 結果處理器(ResultSetHandler)
    • 總結
  • 主題

mybatis運行分為兩部分,第一部分讀取配置文件緩存到Configuration對象中。用以創建SqlSessionFactory,第二部分是SqlSession的執行過程。

Mybatis基本認識

動態代理

  • 之前我們知道Mapper僅僅是一個接口,而不是一個邏輯實現類。但是在Java中接口是無法執行邏輯的。這裏Mybatis就是通過動態代理實現的。關於動態代理我們常用的有Jdk動態代理和cglib動態代理。兩種卻別這裏不做贅述。關於CGLIB代理在框架中使用的比較多。

  • 關於動態代理就是所有的請求有一個入口,由這個入口進行分發。在開發領域的一個用途就是【負載均衡】

  • 關於Mybatis的動態代理是使用了兩種的結合。

  • 下面看看JDK和cglib兩種實現

JDK實現

  • 首先我們需要提供一個接口 , 這個接口是對我們程序員的一個抽象。 擁有編碼和改BUG的本領

public interface Developer {

    /**
     * 編碼
     */
    void code();

    /**
     * 解決問題
     */
    void debug();
}

  • 關於這兩種本領每個人處理方式不同。這裏我們需要一個具體的實例對象

public class JavaDeveloper implements Developer {
    @Override
    public void code() {
        System.out.println("java code");
    }

    @Override
    public void debug() {
        System.out.println("java debug");
    }
}

  • 我們傳統的調用方式是通過java提供的new 機制創造一個JavaDeveloper對象出來。而通過動態代理是通過java.lang.reflect.Proxy對象創建對象調用實際方法的。

  • 通過newProxyInstance方法獲取接口對象的。而這個方法需要三個參數
    ClassLoader loader : 通過實際接口實例對象獲取ClassLoader
    Class<?>[] interfaces : 我們抽象的接口
    InvocationHandler h : 對我們接口對象方法的調用。在調用節點我們可以進行我們的業務攔截


JavaDeveloper jDeveloper = new JavaDeveloper();
Developer developer = (Developer) Proxy.newProxyInstance(jDeveloper.getClass().getClassLoader(), jDeveloper.getClass().getInterfaces(), (proxy, method, params) -> {
    if (method.getName().equals("code")) {
        System.out.println("我是一個特殊的人,code之前先分析問題");
        return method.invoke(jDeveloper, params);
    }
    if (method.getName().equals("debug")) {
        System.out.println("我沒有bug");

    }
    return null;
});
developer.code();
developer.debug();

CGLIB動態代理

  • cglib動態代理優點在於他不需要我們提前準備接口。他代理的實際的對象。這對於我們開發來說就很方便了。

public class HelloService {
    public HelloService() {
        System.out.println("HelloService構造");
    }

    final public String sayHello(String name) {
        System.out.println("HelloService:sayOthers>>"+name);
        return null;
    }

    public void sayHello() {
        System.out.println("HelloService:sayHello");
    }
}

  • 下面我們只需要實現cglib提供的MethodInterceptor接口,在初始化設置cglib的時候加載這個實例化對象就可以了

public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("======插入前置通知======");
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("======插入後者通知======");
        return object;
    }
}

  • 下面我們就來初始化設置cglib

public static void main(String[] args) {
    //代理類class文件存入本地磁盤方便我們反編譯查看源代碼
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/root/code");
    //通過CGLIB動態代理獲取代理對象過程
    Enhancer enhancer = new Enhancer();
    //設置enhancer對象的父類
    enhancer.setSuperclass(HelloService.class);
    // 設置enhancer的回調對象
    enhancer.setCallback(new MyMethodInterceptor());
    //創建代理對象
    HelloService helloService = (HelloService) enhancer.create();
    //通過代理對象調用目標方法
    helloService.sayHello();
}

  • 仔細看看cglib和spring的aop特別像。針對切點進行切面攔截控制。

總結

  • 通過對比兩種動態代理我們很容易發現,mybatis就是通過JDK代理實現Mapper調用的。我們Mapper接口實現通過代理到xml中對應的sql執行邏輯

反射

  • 相信有一定經驗的Java工程師都對反射或多或少有一定了解。其實從思想上看不慣哪種語言都是有反射的機制的。
  • 通過反射我們就擺脫了對象的限制我們調用方法不再需要通過對象調用了。可以通過Class對象獲取方法對象。從而通過invoke方法進行方法的調用了。

Configuration對象作用

  • Configuration對象存儲了所有Mybatis的配置。主要初始化一下參數
    • properties
    • settings
    • typeAliases
    • typeHandler
    • ObjectFactory
    • plugins
    • environment
    • DatabaseIdProvider
    • Mapper映射器

映射器結構

  • BoundSql提供三個主要的屬性 parameterMappings 、parameterObject、sql

  • parameterObject參數本身。我們可以傳遞java基本類型、POJO、Map或者@Param標註的參數。

  • 當我們傳遞的是java基本類型mybatis會轉換成對應的包裝對象 int -> Integer

  • 如果我們傳遞POJO、Map。就是對象本身

  • 我們傳遞多個參數且沒有@Param指定變量名則parameterObject 類似
    {“1″:p1,”2″:p2,”param1″:p1,”param2”:p2}

    台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

    台中搬家公司推薦超過30年經驗,首選台中大展搬家

  • 我們傳遞多個參數且@Param指定變量名 則parameterObject類似
    {“key1″:p1,”key2″:p2,”param1″:p1,”param2”:p2}

  • parameterMapping 是記錄屬性、名稱、表達式、javaType,jdbcType、typeHandler這些信息

  • sql 屬性就是我們映射器中的一條sql. 正常我們在常見中對sql進行校驗。正常不需要修改sql。

sqlsession執行流程(源碼跟蹤)

  • 首先我們看看我們平時開發的Mapper接口是如何動態代理的。這就需要提到MapperProxyFactory這個類了。該類中的newInstance方法

protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  • 通過上滿代碼及上述對jdk動態代理的表述。我們可以知道mapperProxy是我們代理的重點。
  • MapperProxy是InvocationHandler的實現類。他重寫的invoke方法就是代理對象執行的方法入口。

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
    if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, args);
    } else if (isDefaultMethod(method)) {
    return invokeDefaultMethod(proxy, method, args);
    }
} catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}


private boolean isDefaultMethod(Method method) {
return (method.getModifiers()
    & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC
    && method.getDeclaringClass().isInterface();
}

  • 通過源碼發現。invoke內部首先判斷對象是否是類 。 通過打斷點發現最終會走到cacheMapperMethod這個方法去創建MapperMethod對象。
  • 繼續查看MapperMethod中execute方法我們可以了解到內部實現其實是一個命令行模式開發。通過判斷命令從而執行不同的語句。判斷到具體執行語句然後將參數傳遞給sqlsession進行sql調用並獲取結果。到了sqlsession就和正常jdbc開發sql進行關聯了。sqlsession中ExecutorStatementHandlerParameterHandlerResulthandler四大天王

Executor

  • 顧名思義他就是一個執行器。將java提供的sql提交到數據庫。Mybatis提供了三種執行器。

  • Configuration.classnewExecutor源碼

  • 根據uml我們不難看出mybatis中提供了三類執行器分別SimpleExecutor、ReuseExecutor、BatchExecutor

public SqlSession openSession() {
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      // 得到configuration 中的environment
      final Environment environment = configuration.getEnvironment();
      // 得到configuration 中的事務工廠
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 獲取執行器
      final Executor executor = configuration.newExecutor(tx, execType);
      // 返回默認的SqlSession
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

  • 通過上述源碼我們知道在sqlsession獲取一個數據庫session對象時我們或根據我們的settings配置加載一個Executor對象。在settings中配置也很簡單

<settings>
<!--取值範圍 SIMPLE, REUSE, BATCH -->
	<setting name="defaultExecutorType" value="SIMPLE"/>
</settings>

  • 我們也可以通過java代碼設置

factory.openSession(ExecutorType.BATCH);

StatementHandler

  • 顧名思義,StatementHandler就是專門處理數據庫回話的。這個對象的創建還是在Configuration中管理的。

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

  • 很明顯Mybatis中StatementHandler使用的是RoutingStatementHandler這個class
  • 關於StatementHandler和RoutingStatementHandler之間的關係我們通過源碼可以看出這裏和Executor一樣都是適配器模式。採用這種模式的好處是方便我們對這些對象進行代理。這裏讀者可以猜測一下是使用了哪種動態代理。給點提示 這裏使用了接口哦

  • 在查看BaseStatementHandler結構我們會發現和Executor一模一樣。同樣的Mybatis在構造RoutingStatementHandler的時候會根據setting中配置來加載不同的具體子類。這些子類都是繼承了BaseStatementHandler.

  • 前一節我們跟蹤了Executor。 我們知道Mybatis默認的是SimpleExecutor。 StatementHandler我們跟蹤了Mybaits默認的是PrePareStatementHandler。在SimpleExecutor執行查詢的源碼如下

  • 我們發現在executor查詢錢會先讓statementHandler構建一個Statement對象。最終就是StatementHandler中prepare方法。這個方法在抽象類BaseStatmentHandler中已經封裝好了。
  • 這個方法的邏輯是初始化statement和設置連接超時等一些輔助作用
  • 然後就是設置一些參數等設置。最後就走到了執行器executor的doquery
  • PrepareStatement在我們jdbc開發時是常見的一個類 。 這個方法執行execute前我們需要設置sql語句,設置參數進行編譯。這一系列步驟就是剛才我們說的流程也是PrepareStatementHandler.prepareStatement幫我們做的事情。那麼剩下的我們也很容易想到就是我們對數據結果的封裝。正如代碼所示下馬就是resultSetHandler幫我們做事情了。

結果處理器(ResultSetHandler)


@Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          handleResultSet(rsw, resultMap, null, parentMapping);
        }
        rsw = getNextResultSet(stmt);
        cleanUpAfterHandlingResultSet();
        resultSetCount++;
      }
    }

    return collapseSingleResultList(multipleResults);
  }

  • 這個方法我們可以導出來是結果xml中標籤配置對結果的一個封裝。

總結

  • SqlSession在一個查詢開啟的時候會先通過CacheExecutor查詢緩存。擊穿緩存後會通過BaseExector子類的SimpleExecutor創建StatementHandler。PrepareStatementHandler會基於PrepareStament執行數據庫操作。並針對返回結果通過ResultSetHandler返回結果數據

主題

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

台中搬家公司費用怎麼算?

擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司

國外零售商洩漏 Intel 第 11 代 Rocket Lake-S 處理器的售價,i9-11900K 價格比上一代便宜一些_網頁設計公司

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

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

先前 CES 2021 發表會上,Intel 正式透露第 11 代 Rocket Lake-S 處理器(i9-11900K)官方效能跑分之後,相信不少玩家都非常期待,不僅比上一代還強,也勝過對手的 AMD 12 核心 Ryzen 5900X,不過當時並沒有公布售價,也因此想買的人究竟該準備多少,只能參考第 10 代的價格。最近國外就有一間零售商,疑似搶先放上第 11 代 Rocket Lake-S 處理器的價格列表,從 i9、i7、一直到 i5 都有,有些比較貴,有些便宜。

國外零售商洩漏 Intel 第 11 代 Rocket Lake-S 處理器的售價

近日比利時一間 2Compute 電腦硬體零售商在它的官網上,洩漏第 11 代 Rocket Lake-S 處理器的價格列表,而且現在還沒刪除,感覺就像是故意放上去一樣。

根據列表顯示,新一代遊戲旗艦處理器 8 核心 16 執行緒的 i9-11900K 單顆未稅價為 499.70 歐元,含稅之後變成 605 歐元,代表說比上一代 i9-10900K 還便宜 9.8% 左右。

下圖是 i9-11900K 的價格:

i9-10900K 的價格,單顆未稅價 549 歐元,含稅之後 665 歐元:

下方為第 11 代 Rocket Lake-S 處理器與第 10 代 Comet Lake-S 處理器的比較圖,i9-11900KF 也比上一代便宜,但 i9-11900 與 i9-11900F 就沒有,其餘 i7、i5 大多數也比上一代貴:

2Compute 網站洩漏的 Rocket Lake-S 處理器價格清單(含稅價):

  • i5-11400:205 歐元
  • i5-11400F:175 歐元
  • i5-11500:227 歐元
  • i5-11600:250 歐元
  • i5-11600K:294 歐元
  • i5-11600KF:265 歐元
  • i7-11700:371 歐元
  • i7-11700F:342 歐元
  • i7-11700K:456 歐元
  • i7-11700KF:427 歐元
  • i9-11900:494 歐元
  • i9-11900F:465 歐元
  • i9-11900K:605 歐元
  • i9-11900KF:576 歐元

如果比較整體價格,第 11 代 Rocket Lake-S 處理器平均大約比第 10 代 Comet Lake-S 處理器貴 14% 左右。當然,這是零售商搶先洩漏的清單,也因此一切還是要以 Intel 官方為主。

Intel 第 11 代 Rocket Lake-S 處理器預計會在 3 月正式推出,下個月應該會有更確切的消息出現。

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

有趣的是,除了 2Compute,國外其實還有其他零售商也洩漏這價格清單,不過大家都不太一樣,讓人看起來有點亂:

Intel 11th Gen Price

10th Gen sheet is for comparison pic.twitter.com/kAvMbIQjKm

— 포시포시 (@harukaze5719) January 17, 2021

資料來源:Video Cardz

Intel 第 11 代「Rocket Lake」與第 12 代「Alder Lake」搶先看

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

次世代 ROG Phone 騰訊搶先預告登場!傳升級 65W 快充應援你的電競行動生活_網頁設計公司

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

2021 年新世代電競手機戰爭最早將在 3 月開打?根據華碩 ROG 在微博最近釋出的預告,可以看到採用新設計「即將升級」的 ROG Phone(可能是 ROG Phone 4 但也有消息指出會跳版號到 ROG Phone 5)即將來襲。繼續閱讀次世代 ROG Phone 騰訊搶先預告登場!傳將升級65W 快充應援你的電競行動生活報導內文。

次世代 ROG Phone 騰訊搶先預告登場!傳升級 65W 快充應援你的電競行動生活

身為電競手機概念的先驅者,ROG 絕對可以被算上一角。現在,他們的旗艦電競手機 ROG Phone 的戰力升級版,也確認將在與騰訊繼續合作之下推出 — 儘管,由內部型號 I003D 跳至 I005DA 的新款 ROG 電競手機,是否會跳號成為 ROG Phone 5 仍是個謎(還是會一次推兩款?)。
根據官方在社群平台的預告圖片,有著明顯可見的銀河星座背景,被許多人推測可能最快將會在 3 月推出。而從手機螢幕刻意在底端「留黑」的圖片也可以斷言,新世代 ROG 電競手機可能將不再延續上下螢幕邊框比例對稱的設計語言,在頂端與左右三邊都將迎接盡可能薄到視覺難以察覺的超薄邊框。

這樣一張簡單的預告圖片,似乎可預期 ROG Phone 將迎接手機內外的全面硬體大改 — 所以老配件可能… 至於前置鏡頭何去何從,這好像對華碩來講也不是問題?(ZenFone 7 Pro 表示:)但就目前流傳的實機照看來,背面很可能與 ROG Phone 3 相比沒有太多的變動,但疑似多了個疑似為遊戲專用的按鈕;側面的充電孔應該依然有保留 。至於「05」的編號,看來也就是會直接跳號了?

▲圖片來源:WHYLAB(微博)

是說,先前已有強大跑分數字流出,以電競遊戲高效能而生做為最主要特色的 ROG Phone,一直以來都提供了許多超前業界的規格。但顯然對使用者而言,仍有著更完美規格方面的期待 — 像是快充規格方面,根據最近的傳言則是指出將從先前的 30W 一舉提升至 65W;電量部分更可能直衝 6,000mAh,應該會是更符合使用者需求的提升。

看來在更多配件曝光之前,已經可以預期 ROG Phone 4 / ROG Phone 5 將「升級」成更完美電競手機了?

▲圖片來源:PhoneArena

本篇圖片 / 引用來源

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

延伸閱讀:

中國電動車全面跟上 1,000 公里續航?專家:不可能「全都好」

不只潮更厲害!AirPods Max 開箱使用體驗(同場加映:全色系動眼看!)

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

Safari 導入延伸功能系統,目前開發者反應冷淡_網頁設計

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

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

在 WWDC 2020 時,Apple 宣布將在 Mac 版的Safari 14 中導入在 Chrome、Firefox 等瀏覽器上行之有年且受到用戶大大歡迎的的擴展應用 Web Extensions API,不過至今 6 個月過去了,由於 Apple 本身的遊戲規則獨立於其他平台之外,開發者的反應顯得冷淡,上架的新應用自然也不如預期。

Safari 導入擴展延伸系統,目前開發者反應冷淡

可在 MacOS Big Sur、Catalina 與 Mojave 上運行的 Safari 14,理論上可以為基於 JavaScript 的 Chrome、Firefox、Edge 等瀏覽器開發者提供大致上差不多的程式碼,並且轉換成 Mac 版 Safari 的擴展外掛。不過依照目前的進展來看,在 Mac APP Store 上所提供的 Safari 擴展中基本上都是 Safari 14 發表會之前的項目,僅有極少數新擴展出現。

Andrew Abrahamowicz 在 Library Extension 擴展外掛的開發上投注了 10 年的時間,是一款可以把當地圖書館書況在 Amazon 等網站的圖書賣場中顯示出來的外掛,Abrahamowicz 表示開發這款應用並不是他的本業,因此能夠付出的精力與時間也很有限,為此他入手了新的 M1 Mac 來進行後續的研究開發。支援一個新平台對開發者來說必須負擔很多額外的工作,除了必須利用 Xcode 設定之外,還必須處理 Apple 對延伸功能一些特定的安全限制,所以必須額外撰寫適用的程式碼,以便讓 Safari 版本能夠擁有和其他平台上一樣的功能。

從上面的例子可以看到許多癥結,像是大多數開發者都是業餘進行時間有限、因限定 Apple 硬體設備才能開發而卡住,以及對 Apple 開發工具的不熟悉等,都會成為開發者反應不如預期的原因。其中一個典型的例子就是 Beyond20 這款擴展,該擴展能夠將 D&D Beyond 角色表與 Roll20 等虛擬桌面服務連接起來,如果想要在 Mac 上使用,編輯只能切換到 Chrome 或 Firefox 瀏覽器。該應用項目負責人表示因為不是屬於 Chromium 系統而需要額外工作,加上自己平常並不使用 Safari ,所以不願意在 Safari 上架自家外掛。

目前看來,推動 Web Extensions API 是一項沒有盡頭的任務,在 APP Store 中已經出現極少數的外掛上架, 梭說可能會帶動其他擴展跟著行動,但大多數開發者似乎仍不為所動。國外媒體的意見是,如果最終 Apple 能夠將 Safari 擴展也推動到 iOS 或 iPadOS 上
,或許對於外掛的增長會更有效果。

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

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

◎資料來源:Six colors

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

國外網友結合二手健身車與任天堂健身環等設備,組出了一台可以邊運動邊玩「瑪利歐賽車」的鍛鍊神器_貨運

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

瑪利歐賽車是任天堂旗下的人氣遊戲,很多玩家喜歡它豐富的賽道設計,每場比賽中隨機刷出的道具更是給賽事增添不少勝負變數。小到香蕉皮,大到無敵星星,各種道具不但促進了瑪利歐賽車系列的大賣,也不知道撕破了多少人之間的友誼。今天不是要告訴大家瑪利歐賽車的必勝方法。而是介紹一個玩膩《健身環大冒險》,於是用一點小工具跟改裝技巧,土砲出了健身環版瑪利歐賽車專用套件的神人。用這個套件玩《瑪車》未必能讓你百戰百勝,但能讓你邊玩邊消耗熱量,甚至達到健身減重的效果:

▲(圖片翻攝自 Youtube 影片)

瑪利歐賽車系列遊戲打從超任時代就開始風靡許多大小朋友,這系列遊戲有多好玩自然不需要筆者多做介紹。歷經數年演變,畫面也從 2D、3D 到現在高畫質畫面,稱得上是任天堂的一大台柱。很多人購買 Switch 主機以後,往往也會順便來一片《瑪利歐賽車 8 Deluxe》來跟家人朋友同樂,是一款相當適合多人競技的遊戲。

有了健身環,瑪利歐賽車也可以拿來運動

在任天堂推出 Wii 主機以後,體感控制就成為許多新遊戲開創新玩法的靈感來源。從 Wii 推出的時代就有許多運動或競技相關的遊戲採用了體感操控。像是 2006 年推出的 Wii Sport、2007 年的 Wii Fit、2019 對應新主機 Switch 推出的健身環與健身環大冒險遊戲,這些遊戲都顯示運動類遊戲成為任天堂開創新玩法的重要領域。不過,這些遊戲通常都有個缺點,就是綁定的某些套件,例如健身環大冒險之於任天堂健身環。這些套件通常也無法對應到其他遊戲的玩法上。於是一位玩家就跳出來替任天堂健身環進行了一點小小的改造,搭配一台二手健身車,組合成讓人一邊運動一邊玩瑪利歐賽車的新套件「Labo Fit Adventure Kart」:

▲健身環、手把跟改裝過的二手健身車,組成了這個奇妙的健身套件(圖片翻攝自 Youtube 影片)

這套或可取名為「Labo 健身賽車冒險」的套件組合了一個健身環,一個 Switch 手把和一台二手健身車。主要的邏輯是讓健身環、健身車的操控能夠對應到 Switch 手把按鍵上,才能利用這組套件來進行有系。這位名為「Mike Choi(@mechachoi)」的國外網友就利用了自製的裝置「TAPBO」來成為溝通這些裝備的橋樑,最後讓這些裝置能成為玩家的手與腳。一邊進行著遊戲的同時,一邊還可以鍛鍊身體。既能避免沉迷遊戲,還能夠減少身上贅肉,一舉兩得:

▲TAPBO套件主要用處就是接收訊號以控制手把(圖片翻攝自 Youtube 影片)

Mike Choi 網友透過瑪利歐賽車這個遊戲做為示範,來展示自己組裝起來的「Labo Fit Adventure Kart」。簡單的說,使用者必須腳踏健身車來讓遊戲中的卡丁車加速。利用健身環做為虛擬的方向盤轉動卡丁車的前輪。至於瑪利歐賽車中重要的道具發射功能,則是透過擠壓健身環來達成。這些動作說明起來很簡單。但要一邊運動一邊在遊戲中進行排位的攻防,並不是一件簡單的事。若真能靠這個方式成為瑪利歐賽車大師,想必體脂率也大幅降低了不少:

▲作者在自己的推特上宣傳自作套件,吸引不少網友轉推(圖片翻攝自 Twitter 網頁)

▲一邊騎車讓卡丁車加速,一邊控制方向盤(健身環),一邊還得透過擠壓健身環放道具(圖片翻攝自 Youtube 影片)

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

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

Mike Choi 網友也在自己的套件介紹影片中說明了製造流程。就概念來說相信有點電機底子的人都不會覺得太難,只是難在要用這個方式真的在遊戲中跟親友競爭,取勝的機率相對低落的多。Mike Choi 網友甚至還試著玩了一下另一款任天堂的旗下大作「任天堂明星大亂鬥特別版」,從影片中看起來的確不是普通的累。對於有心想健身或減肥的人,藉著遊戲持之以恆的話,說不定真的能有所成效也說不定:

▲連大亂鬥也支援,不過這樣玩直的很累(圖片翻攝自 Youtube 影片)

▲可惜的是他這套純手工健身器材尚未販售,不過這個點子應該會吸引健身器材大廠或是任天堂尋求合作才是(圖片翻攝自 Youtube 影片)

消息來源

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

[C#.NET 拾遺補漏]01:字符串操作_網頁設計公司

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

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

字符串操作在任意編程語言的日常編程中都隨處可見,今天來匯總一下 C# 中關於字符串的一些你可能遺忘或遺漏的知識點。

逐字字符串

在普通字符串中,反斜杠字符是轉義字符。而在逐字字符串(Verbatim Strings)中,字符將被編程器按照原義進行解釋。使用逐字字符串只需在字符串前面加上 @ 符號。

// 逐字字符串:轉義符
var filename = @"c:\temp\newfile.txt";
Console.WriteLine(filenaame);

// 逐字字符串:多行文本
var multiLine = @"This is a
multiline paragraph."
;
Console.WriteLine(multiLine);

// 非逐字字符串
var escapedFilename = "c:\temp\newfile.txt";
Console.WriteLine(escapedFilename);

輸出:

c:\temp\newfile.txt
This is a
multiline paragraph.
c: emp
ewfile.txt

逐字字符串中唯一不被原樣解釋的字符是雙引號。由於雙引號是定義字符串的關鍵字符,所以在逐字字符串中要表達雙引號需要用雙引號進行轉義。

varstr = @"""I don't think so"", he said.";
Console.WriteLine(str);
// 輸出:"I don't think so", he said.

在逐字字符串中也可以 $ 符號實現字符串內插值。

Console.WriteLine($@"Testing \n 1 2 {5 - 2}");
// 輸出:Testing \n 1 2 3

数字格式化轉換

典型的的格式化方法為:

string.Format("{index[:format]}", number)

可使用“0”和“#”佔位符進行補位。“0” 表示位數不夠位數就補充“0”,小數部分如果位數多了則會四舍五入;“#”表示佔位,用於輔助“0”進行補位。

標準格式化用法:

// “0”描述:佔位符,如果可能,填充位
string.Format("{0:000000}",1234); // 結果:001234

// “#”描述:佔位符,如果可能,填充位
string.Format("{0:######}",1234); // 結果:1234
string.Format("{0:#0####}",1234); // 結果:01234
string.Format("{0:0#0####}",1234); // 結果:0001234

// "."描述:小數點
string.Format("{0:000.000}", 1234); // 結果:1234.000
string.Format("{0:000.000}", 4321.12543); // 結果:4321.125

// ","描述:千分表示
string.Format("{0:0,0}", 1234567); //結果:1,234,567

// "%"描述:格式化為百分數
string.Format("{0:0%}",1234); // 結果:123400%
string.Format("{0:#%}", 1234.125); // 結果:123413%
string.Format("{0:0.00%}",1234); // 結果:123400.00%
string.Format("{0:#.00%}",1234.125); // 結果:123412.50%

內置快捷字母格式化用法:

// E-科學計數法表示
(25000).ToString("E"); // 結果:2.500000E+004

// C-貨幣表示,帶有逗號分隔符,默認小數點后保留兩位,四舍五入
(2.5).ToString("C"); // 結果:¥2.50

// D[length]-十進制數
(25).ToString("D5"); // 結果:00025

// F[precision]-浮點數,保留小數位數(四舍五入)
(25).ToString("F2"); // 結果:25.00

// G[digits]-常規,保留指定位數的有效数字,四舍五入
(2.52).ToString("G2"); // 結果:2.5

// N-帶有逗號分隔符,默認小數點后保留兩位,四舍五入
(2500000).ToString("N"); // 結果:2,500,000.00

// X-十六進制,非整型將產生格式異常
(255).ToString("X"); // 結果:FF

ToString 也可以自定義補零格式化:

(15).ToString("000");              // 結果:015
(15).ToString("value is 0"); // 結果:value is 15
(10.456).ToString("0.00"); // 結果:10.46
(10.456).ToString("00"); // 結果:10
(10.456).ToString("value is 0.0"); // 結果:value is 10.5

轉換為二進制、八進制、十六進制輸出:

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

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

int number = 15;
Convert.ToString(number, 2); // 結果:1111
Convert.ToString(number, 8); // 結果:17
Convert.ToString(number, 16); // 結果:f

自定義格式化器:

public class CustomFormat : IFormatProvider, ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))
{
return null;
}
if (format == "Reverse")
{
return string.Join("", arg.ToString().Reverse());
}
return arg.ToString();
}

public object GetFormat(Type formatType)
{
return formatType == typeof(ICustomFormatter) ? this : null;
}
}

使用自定義格式化器:

String.Format(newCustomFormat(), "-> {0:Reverse} <-", "Hello World");
// 輸出:-> dlroW olleH <-

字符串拼接

將數組中的字符串拼接成一個字符串:

var parts = new[] { "Foo", "Bar", "Fizz", "Buzz"};
var joined = string.Join(", ", parts);
// joined = "Foo, Bar, Fizz, Buzz"

以下四種方式都可以達到相同的字符串拼接的目的:

string first = "Hello";
string second = "World";
string foo = first + " " + second;
string foo = string.Concat(first, " ", second);
string foo = string.Format("{0} {1}", firstname, lastname);
string foo = $"{firstname} {lastname}";

字符串內插法

簡單用法:

var name = "World";
var str =$"Hello, {name}!";
// str = "Hello, World!"

帶日期格式化:

var date = DateTime.Now;
var str = $"Today is {date:yyyy-MM-dd}!";

補齊格式化(Padding):

var number = 42;

// 向左補齊
var str = $"The answer to life, the universe and everything is {number, 5}.";
// str = "The answer to life, the universe and everything is ___42." ('_'表示空格)

// 向右補齊
var str = $"The answer to life, the universe and everything is ${number, -5}.";
// str = "The answer to life, the universe and everything is 42___."

結合內置快捷字母格式化:

var amount = 2.5;
var str = $"It costs {amount:C}";
// str = "¥2.50"

var number = 42;
var str = $"The answer to life, the universe and everything is {number, 5:f1}.";
// str = "The answer to life, the universe and everything is ___42.1"

參考:

1.《C# 7.0 in a Nutshell》

2. https://bit.ly/2U1eIK9

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

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

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

Nvidia 悄悄放寬 G-Sync Ultimate 認證的標準,高亮度不再是必要條件_如何寫文案

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

在 2013 年時,Nvidia 推出了新的同步技術 G-Sync,確保顯示器畫面更新與顯示卡處理保持同步,從而避免影像撕裂、卡頓等現象,進而提升用戶接受到的影像品質,顯示器上必須搭載專用的 G-Sync 硬體模組來達成這個目標。在此 2 年之後,AMD 推出了自家的 FreeSync 同步,採開放式設計且不需要專用的硬體,顯示效果也不錯,很快就蔚為風潮,並且被納入了 VESA 適應性同步標準之中。

Nvidia 悄悄放寬 G-Sync Ultimate 認證的標準,高亮度不再是必要條件

隨著 AMD 的進展,Nvidia 也逐步開放了三種不同等級的 G-Sync,分別為不需要加裝專用硬體模組的 G-Sync Compatible,需加裝硬體模組的 G-Sync,以及除需安裝硬體模組還額外支援最高解析度與更新率、超低延遲、多區背光、廣色域且亮度不低於 1000nits(HDR 1000 認證)的 G-Sync Ultimate。近日,Nvidia 將 Asus PG32UQX、LG 34GP950G 與微星 MEG381CQR 納入 G-Sync Ultimate 列表中,但除了第一款螢幕可達到 1400nits 外,後兩款在亮度方面卻僅通過 HDR 600 的認證,實際上並不能滿足 G-Sync Ultimate 的條件。

從 Nvidia 官網上所看到的最新資訊,可以發現關於 G-Sync Ultimate 有關於亮度高於 1000nits 的要求已經悄悄被刪除,也不再提到高亮度的好處,也就是說未來對製造商來說,要想拿到最高等級的 G-Sync Ultimate 認證,相對更為容易與簡單。

不過從消費者角度來看,雖然市面上標榜通過 G-Sync Ultimate 認證的選項會變多,但也表示其他規格方面的落差也會變大,容易引起混亂,在選購時更得睜大眼睛,避免被認證標章的話術所迷惑。

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

◎資料來源:PC Gamer、Tom’s Hardware

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※別再煩惱如何寫文案,掌握八大原則!

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。