標籤: 銷售文案

  • 使用json-server與Mockjs搭建模擬服務

    使用json-server與Mockjs搭建模擬服務

    為什麼使用

    在項目開發中,常常需要邊寫前端頁面邊寫後端接口,但是後端接口服務往往是滯後於前端開發的,或者是不能及時提供的。出於前端開發的迅速和便捷去考慮,我們可以根據後端接口數據結構去模擬(mock)數據從而實現前端的獨立開發。
    JsonServer 主要的作用就是搭建本地的數據接口,創建json文件,便於調試調用
    Mockjs 主要的作用就是生成隨機數據,支持生成隨機的文本、数字、布爾值、日期、郵箱、鏈接、圖片、顏色等

    如何使用

    以下操作需要node.js環境

    1.創建文件夾

    選擇自己喜歡的位置創建一個文件夾,比如E:/mock

    2.安裝json-server

    進入E:/mock

    npm install json-server -g 

    安裝完執行 json-server -h,若安裝成功則會显示選項

    Options:
    –config, -c Path to config file [default: “json-server.json”]
    –port, -p Set port [default: 3000]
    –host, -H Set host [default: “localhost”]
    –watch, -w Watch file(s) [boolean]
    –routes, -r Path to routes file
    –middlewares, -m Paths to middleware files [array]
    –static, -s Set static files directory
    –read-only, –ro Allow only GET requests [boolean]
    –no-cors, –nc Disable Cross-Origin Resource Sharing [boolean]
    –no-gzip, –ng Disable GZIP Content-Encoding [boolean]
    –snapshots, -S Set snapshots directory [default: “.”]
    –delay, -d Add delay to responses (ms)
    –id, -i Set database id property (e.g. _id) [default: “id”]
    –foreignKeySuffix, –fks Set foreign key suffix (e.g. _id as in post_id)
    [default: “Id”]
    –quiet, -q Suppress log messages from output [boolean]
    –help, -h Show help [boolean]
    –version, -v Show version number [boolean]

    3.使用json-server
    • 創建json文件,如db.json,文件內容如下
    { "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } } 
    • 啟動json-server,cmd執行
    json-server --watch db.json 

    看到如下內容

     

    1574216715(1).jpg


    則運行成功,直接訪問圖中显示的三個地址可得結果,如


     

    1574216903(1).jpg


    至此,簡單的json-server服務已經搭建成功了,後續如果有更多需求,如跨域、參數查詢、路由這些,請參考json-server的github

     

    4.安裝Mockjs

    進入E:/mock

    npm install mockjs --save 
    5.使用Mockjs
    • 創建js文件,如news.js,文件內容如下
    let Mock=require('mockjs'); let Random=Mock.Random; module.exports=()=>{ let data={ news:[] }; let images=[1,2,3].map(x=>Random.image('120x60',Random.color(),Random.word(2,6))); for(let i=1;i<=100;i++){ let content=Random.cparagraph(0,10); data.news.push({ id:i, title:Random.cword(8,20), desc:content.substr(0,40), tag:Random.cword(2,6), views:Random.integer(100,5000), images:images.slice(0,Random.integer(1,3)) }) } return data } 
    • 啟動json-server,cmd執行
    json-server --watch news.js 

    訪問結果(部分)


     
     

    完成了以上的搭建與驗證過程后,你就可以開始使用json-server與Mockjs來繼續構建模擬服務器了,來滿足自己的各種需要

    Tips:

    1、也可以使用json-server db.json ,使用“json-server –watch db.json”命令可以實時監測db.json的變化;如果沒有 — watch 命令,即使db.json已經發生了改變,重新發請求,仍然會返回原先的mock data,返回狀態碼304,認為沒有變化。

    2、同時,我們可以發送 POST、PUT、PATCH和DELETE請求,相應的結果會通過lowdb自動保存到db.json。關於POST、PUT等相關請求的發送。

    3、我們的request body應該是一個json對象,比如{“name”:”Lynn”};

    4、POST、PUT、PATCH請求頭中要包含Content-Type: application/json;

    5、id的值是自動生成且不易變的。PUT請求和PATCH請求中自帶的id會被忽略。

     

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

    【其他文章推薦】

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

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

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

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

    ※超省錢租車方案

  • springboot_自動配置原理

    springboot_自動配置原理

    目錄

    • 1.1 @SpringBootApplication
    • 2.1 @EnableAutoConfiguration
      • 2.1.1 @AutoConfigurationPackage
      • 2.1.2 @Import({Registrar.class})
    • 3.1 以HttpEncodingAutoConfiguration為例

    springboot啥都不難,總所周知spring全家桶系列難就難在理解源碼。。。。。。。

    今天結合網上資料,自己總結了一下springboot的自動配置原理。

    我現在使用的springboot版本為2.3.1.不同版本的springboot在源碼上有差別!但大體一致。

    管他三七二十一先打個斷點再說:

    1.1 @SpringBootApplication

    這個註解點進去我們可以看到:

    這裏面主要關注兩個東西:

    • @SpringBootConfiguration
    • @EnableAutoConfiguration
      第一個註解點進去:

      可以看到這個@SpringBootConfiguration本質就是一個@Configuration,標註在某個類上,表示這是一個Spring Boot的配置類。
      第二個註解@EnableAutoConfiguration: 開啟自動配置類,SpringBoot的精華所在。(最重要的就是這個註解)

    2.1 @EnableAutoConfiguration

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        Class<?>[] exclude() default {};
    
        String[] excludeName() default {};
    }
    

    兩個比較重要的註解:

    • @AutoConfigurationPackage:自動配置包。
    • @Import({AutoConfigurationImportSelector.class}):導入自動配置的組件。

    2.1.1 @AutoConfigurationPackage

    點進去瞅瞅:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Import({Registrar.class})
    public @interface AutoConfigurationPackage {
        String[] basePackages() default {};
    
        Class<?>[] basePackageClasses() default {};
    }
    

    發現這裡有導入Regitstrar類:

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
            Registrar() {
            }
    
            public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
                AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
            }
    
            public Set<Object> determineImports(AnnotationMetadata metadata) {
                return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
            }
        }
    

    new PackageImport(metadata).getPackageName(),它其實返回了當前主程序類的 **同級以及子級 ** 的包組件。

    什麼意思呢?

    我們來看這樣一個目錄:

    bean1和我們的springboot啟動類位於同一個包下,二bean2不是位於我們啟動類的同級目錄或者子級目錄,那麼我們啟動的時候bean2是不會被加載到的!所以你項目的一切需要加入容器的類必須放在啟動類的同級包下或者它的子級目錄中。

    2.1.2 @Import({Registrar.class})

    AutoConfigurationImportSelector有一個方法為:selectImports。

    public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            } else {
                AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
                return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
            }
        }
    

    它首先回去檢查是否開啟了自動配置類,然後才回去加載註解數據 this.getAutoConfigurationEntry(annotationMetadata);
    那麼這個annotationMetadata在哪兒?
    來看下面一行代碼:

      protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
            List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
            Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
            return configurations;
        }
    

    SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    再點進去我們會發現這一行代碼:
    Enumeration urls = classLoader != null ? classLoader.getResources(“META-INF/spring.factories”) : ClassLoader.getSystemResources(“META-INF/spring.factories”);

    它其實是去加載 public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;外部文件。這個外部文件,有很多自動配置的類。如下:

    spring.factories文件由一組一組的key=value的形式,其中一個key是EnableAutoConfiguration類的全類名,而它的value是一個xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔。
    springboot項目啟動時,@SpringBootApplication用在啟動類在SpringApplication.run(…)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類加載到Spring容器中。

    3.1 以HttpEncodingAutoConfiguration為例

    @Configuration(
        proxyBeanMethods = false
    )    //表示是一個配置類,可以給容器中添加組件
    @EnableConfigurationProperties({ServerProperties.class})// 啟用ConfigurationProperties功能
    @ConditionalOnWebApplication(
        type = Type.SERVLET
    )
    @ConditionalOnClass({CharacterEncodingFilter.class})
    @ConditionalOnProperty(
        prefix = "server.servlet.encoding",
        value = {"enabled"},
        matchIfMissing = true
    )
    

    @EnableConfigurationProperties({ServerProperties.class})// 啟用ConfigurationProperties功能
    ServerProperties.class:

    @ConfigurationProperties(
        prefix = "server",
        ignoreUnknownFields = true
    )
    

    @ConditionalOnWebApplication :spring底層@Conditional註解,根據不同的條件進行判斷,如果滿足條件整個配置類才會生效。

    總結:
    1.springboot會自動加載大量的自動配置類。
    2.只要我們要用的組件有,我們就不需要再去配置
    3.給容器添加組件的時候。會從properties類中獲取某些屬性。我們就可以在配置文件中指定這些屬性。
    xxxxxAutoConfiguration:自動配置類

    給容器中添加屬性:
    xxxxProperties:封裝配置文件中的相關屬性。

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

    【其他文章推薦】

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

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

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

    ※超省錢租車方案

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

  • Java 多線程基礎(十一)線程優先級和守護線程

     Java 多線程基礎(十一)線程優先級和守護線程

    一、線程優先級

    Java 提供了一個線程調度器來監控程序啟動後進去就緒狀態的所有線程。線程調度器通過線程的優先級來決定調度哪些線程執行。一般來說,Java的線程調度器採用時間片輪轉算法使多個線程輪轉獲得CPU的時間片。然而根據實際情況,每個線程的重要程序也不相同,有時候我們想讓一些線程優先執行,那麼我們可以將他的優先級調高一下,這樣它們獲得的時間片會多一些。

    多個線程處於就緒狀態時,若這些線程的優先級相同,則線程調度器會按時間片輪轉方式或獨佔方式來分配線程的執行時間。

    java 中的線程優先級的範圍是1~10,默認的優先級是5。“高優先級線程”會優先於“低優先級線程”執行。

    Java中線程優先級分為三個級別:

    • 低優先級:1~4,其中類變量 Thread.MIN_PRORITY 最低,數值為1;
    • 默認優先級:如果一個線程沒有指定優先級,默認優先級為5,由類變量 Thread.NORM_PRORITY表示;
    • 高優先級:6~10,類變量 Thread.MAX_PRORITY 最高,數值為10。

    注意:具有相同優先級的多個線程,若它們都為高優先級Thread.MAX_PRORITY,則每個線程都是獨佔式的,也就是這些線程將被順序執行;若它們優先級不是高優先級,則這些線程將被同時執行,可以說是無序執行。

    java 中有兩種線程:用戶線程和守護線程。可以通過 isDaemon() 方法來區別它們:如果返回 false,則說明該線程是“用戶線程”;否則就是“守護線程”。
    用戶線程一般用戶執行用戶級任務,而守護線程也就是“後台線程”,一般用來執行後台任務。需要注意的是:Java虛擬機在“用戶線程”都結束後會後退出。

    JDK中對用戶線程與守護線程的解釋:

    每個線程都有一個優先級。“高優先級線程”會優先於“低優先級線程”執行。每個線程都可以被標記為一個守護進程或非守護進程。在一些運行的主線程中創建新的子線程時,
    子線程的優先級被設置為等於“創建它的主線程的優先級”,當且僅當“創建它的主線程是守護線程”時“子線程才會是守護線程”。
    當Java虛擬機啟動時,通常有一個單一的非守護線程(該線程通過是通過main()方法啟動)。JVM會一直運行直到下面的任意一個條件發生,JVM就會終止運行:
    ①、調用了exit()方法,並且exit()有權限被正常執行。 ②、所有的“非守護線程”都死了(即JVM中僅僅只有“守護線程”)。
    每一個線程都被標記為“守護線程”或“用戶線程”。當只有守護線程運行時,JVM會自動退出。
     

    二、線程優先級示例

    public class Demo01 {
        private static Object obj = new Object();
        public static void main(String[] args) {
            
            Thread t1 = new ThreadA("t1");
            Thread t2 = new ThreadA("t2");
            
            t1.setPriority(1); // 設置優先級為1
            t2.setPriority(10);// 設置優先級為10
            
            t1.start();
            t2.start();
        }
    }
    class ThreadA extends Thread{
        public ThreadA(String name) {
            super(name);
        }
        public void run() {
            for(int i = 0;i < 3;i++)
                System.out.println(Thread.currentThread().getName() + " [ " 
                        + Thread.currentThread().getPriority() + " ] loop " + i);  
        }
    }
    // 運行結果
    t1 [ 1 ] loop 0
    t2 [ 10 ] loop 0
    t2 [ 10 ] loop 1
    t2 [ 10 ] loop 2
    t1 [ 1 ] loop 1
    t1 [ 1 ] loop 2

    說明:

    ①、主線程main的優先級是5。
    ②、t1的優先級被設為1,而t2的優先級被設為10。cpu在執行t1和t2的時候,根據時間片輪循調度,所以能夠併發執行。

    三、守護線程示例

    public class Demo {
        public static void main(String[] args) {
    
            System.out.println(Thread.currentThread().getName()
                    +" [ isDaemon = "+Thread.currentThread().isDaemon()+ " ]");
            Thread t1=new ThreadA("t1");    
            Thread t2=new MyDaemon("t2");    
            t2.setDaemon(true);// 設置t2為守護線程
            t1.start();                        
            t2.start();                        
        }
    }
    class ThreadA extends Thread{
        public ThreadA(String name) {
            super(name);
        }
    
        public void run(){
            try {
                for (int i=0; i<5; i++) {
                    Thread.sleep(3);
                    System.out.println(this.getName() +"[ isDaemon = "+this.isDaemon()+ " ] " + "loop " + i);
                }
            } catch (InterruptedException e) {
            }
        }
    };
    
    class MyDaemon extends Thread{
        public MyDaemon(String name) {
            super(name);
        }
    
        public void run(){
            try {
                for (int i=0; i<10000; i++) {
                    Thread.sleep(1);
                    System.out.println(this.getName() +"[ isDaemon = " + this.isDaemon() +  " ] " +"loop "+i);
                }
            } catch (InterruptedException e) {
            }
        }
    }
    // 運行結果
    main [ isDaemon = false ]
    t2[ isDaemon = true ] loop 0
    t2[ isDaemon = true ] loop 1
    t2[ isDaemon = true ] loop 2
    t1[ isDaemon = false ] loop 0
    t2[ isDaemon = true ] loop 3
    t2[ isDaemon = true ] loop 4
    t1[ isDaemon = false ] loop 1
    t2[ isDaemon = true ] loop 5
    t2[ isDaemon = true ] loop 6
    t2[ isDaemon = true ] loop 7
    t1[ isDaemon = false ] loop 2
    t2[ isDaemon = true ] loop 8
    t2[ isDaemon = true ] loop 9
    t2[ isDaemon = true ] loop 10
    t1[ isDaemon = false ] loop 3
    t2[ isDaemon = true ] loop 11
    t2[ isDaemon = true ] loop 12
    t2[ isDaemon = true ] loop 13
    t2[ isDaemon = true ] loop 14
    t1[ isDaemon = false ] loop 4
    t2[ isDaemon = true ] loop 15

    說明:

    ①、主線程main是用戶線程,它創建的子線程t1也是用戶線程。
    ②、t2 是守護線程。在“主線程main”和“子線程t1”(它們都是用戶線程)執行完畢,只剩t2這個守護線程的時候,JVM自動退出。

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

    【其他文章推薦】

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

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

    ※回頭車貨運收費標準

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

    ※超省錢租車方案

  • Linux下9種優秀的代碼比對工具推薦

    Linux下9種優秀的代碼比對工具推薦

    大家好,我是良許。

    在我們編寫代碼的時候,我們經常需要知道兩個文件之間,或者同一個文件不同版本之間有什麼差異性。在 Windows 下有個很強大的工具叫作 BeyondCompare ,那在 Linux 下需要用到什麼工具呢?

    本文介紹 9 種 Linux 下常用的 9 種代碼比對工具,不僅有命令行工具,還有 GUI 界面工具,讓你輕鬆進行代碼比對。

    1. diff命令

    diff 命令是 Linux 下自帶的一個強大的文本比對工具,而且使用起來非常方便。對於它的使用,我之前也單獨寫過一篇文章介紹,點擊下方鏈接可以查看。

    教你一招Linux下文本比對方法

    diff 命令在大多數的 Linux 發行版里已經預裝了,它可以逐行比對兩個文本文件,並輸出它們的差異點。更多介紹可以直接查看它的 man 手冊。

    $ man diff
    

    但是,diff 命令雖然強大,但它的輸出結果實在是太感人了,不直觀也不清晰。於是,有大佬為了彌補這個缺點,基於 diff 開發了更強大的工具。這裏推薦兩個:colordiffwdiff

    colordiff命令

    colordiff 是一個 Perl 腳本工具,它的輸出結果和 diff 命令一樣,但是會給代碼着色,並且具有語法高亮功能。同時,你如果不喜歡它的默認顏色的話,還可以自定義主題。

    你可以自行安裝 colordiff 到你的電腦,根據不同的發行版選擇不同的安裝命令。

    $ yum install colordiff             [On CentOS/RHEL/Fedora]
    $ dnf install colordiff             [On Fedora 23+ version]
    $ sudo apt-get install colordiff    [On Debian/Ubuntu/Mint]
    

    同樣,你可以使用 man 命令查看它的幫助文檔:

    $ man colordiff
    
    wdiff命令

    diff 命令是逐行比較差異,而 wdiff 更變態,是逐字比較。所以如果你的文本只是修改了少數一些詞語的話,使用 wdiff 命令將更加高效。

    安裝命令如下:

    $ yum install wdiff             [On CentOS/RHEL/Fedora]
    $ dnf install wdiff             [On Fedora 23+ version]
    $ sudo apt-get install wdiff    [On Debian/Ubuntu/Mint]
    

    更詳細內容可以查看它的 man 手冊。

    $ man wdiff
    

    2. vimdiff命令

    vimdiff 等同於 vim -d 命令,即 Vim 編輯器的 diff 模式。

    該命令後面通常會接兩個或多個文件名作為參數,這些文件會同時在 Vim 編輯器的分割窗口中打開,並高亮显示文件中內容有差異的部分。

    它的中文主頁是:http://vimcdoc.sourceforge.net/doc/diff.html

    以上介紹的兩款是 Linux 命令行的對比工具,我們再來看一些 GUI 比對工具。

    3. Kompare

    Kompare 是基於 diff 的一個 GUI 工具,使用者可以很方便看到文件之間的差異,並且支持合併這些差異。

    Kompare 的特性有如下:

    • 支持多種 diff 格式;
    • 支持目錄之間的比對;
    • 支持讀取 diff 文件;
    • 自定義界面;
    • 創建及應用源文件的 patch 文件。

    該工具的主頁為:https://www.kde.org/applications/development/kompare/

    4. DiffMerge

    DiffMerge 是一個跨平台的 GUI 文本比對工具,具有 Linux ,Windows ,macOS 三大平台版本。我們知道,BeyondCompare 是一款收費軟件,所以如果你們公司的版權要求比較高的話,不妨考慮一下 DiffMerge工具。

    DiffMerge 具有兩大功能:1. 圖示化显示兩個文件之間的改變。包含內部行高亮和完整的編輯支持。2. 圖示化显示三個文件之間的改變。允許自動合併(當可以安全操作時)和對結果文件完全編輯控制。

    它具有以下特性:

    • 支持文件夾比對;
    • 集成文件瀏覽器;
    • 高度可配置。

    該工具的主頁為:https://sourcegear.com/diffmerge/

    5. Meld

    Meld 是一個輕量級 GUI 代碼比對工具,它支持用戶比對文件、目錄,並且高度集成版本控制軟件。但針對軟件開發人員,它的以下幾個特性尤為吸引人:

    • 執行雙向和三向差異併合並
    • 輕鬆地在差異和衝突之間導航
    • 逐個文件地比較兩個或三個目錄,显示新文件,缺失文件和更改文件
    • 支持許多版本控制系統,包括 Git,Mercurial,Bazaar 和 SVN 等。

    它的官網為:http://meldmerge.org/

    6. Diffuse

    Diffuse 是另外一款很受歡迎的,免費,小巧,也十分簡單的 GUI 文本差異比對合併工具,它是用 Python 寫成的,具有兩個主要功能:文件比對及版本控制,允許文件編輯、合併,並且輸出兩個文件的差異點。

    你可以使用它查看文本比對小結,使用鼠標選擇文件里的某行進行編輯。它的其它特性包括:

    • 語法高亮
    • 快捷鍵便於文本導航
    • 無限次撤銷
    • 支持 unicode 編碼文件
    • 支持許多版本控制系統,包括 Git,Mercurial,Bazaar 和 SVN 等。

    它的官網為:http://diffuse.sourceforge.net/

    7. XXdiff

    XXdiff 是一款免費、強大的文件及文件夾差異比對及合併工具,它可以運行在很多類 Unix 系統上。不過它有個限制就是它不支持 unicode 文件,也沒法辦法直接編輯文件。

    它具有以下特性:

    • 遞歸對比文件及文件夾
    • 高亮显示差異點
    • 合併差異點,導出結果
    • 支持外部 diff 工具,比如:GNU diff,SIG diff ,Cleareddiff ,以及其它更多工具
    • 支持腳本拓展

    8. KDiff3

    KDiff3 是另外一種很強大的跨平台差異比對及合併工具,它是由 KDevelop 開發而成,可以在所有類 Unix 平台上運行,包括 Linux ,Mac OS ,Windows 等。

    它可以比對或合併兩到三個文件或目錄,具有以下特性:

    • 可以逐句、逐字對比差異
    • 支持自動合併
    • 內置編輯器,可以手動解決衝突
    • 支持 unicode ,UTF-8 等各種編碼格式
    • 支持打印差異

    它的官網為: http://kdiff3.sourceforge.net/

    9. TkDiff

    TkDiff 是另外一種跨平台,易於使用的 GUI 文本比對工具,可以運行在 Linux ,Windows 及 MacOS 系統上。它同樣提供一個左右分開的界面,用於查看對比的兩個文件。

    但是,它也有一些其它文本對比工具沒有的功能,比如差異書籤,以及一個便於快速定位導航差異點的導航圖。

    它的官網為:https://sourceforge.net/projects/tkdiff/

    公眾號:良許Linux

    有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章

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

    【其他文章推薦】

    ※超省錢租車方案

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

    ※回頭車貨運收費標準

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

  • .NET Core請求控制器Action方法正確匹配,但為何404?

    .NET Core請求控制器Action方法正確匹配,但為何404?

    前言

    有些時候我們會發現方法名稱都正確匹配,但就是找不到對應請求接口,所以本文我們來深入了解下何時會出現接口請求404的情況。

    匹配控制器Action方法(404)

    首先我們創建一個web api應用程序,我們給出如下示例控制器代碼

    [ApiController]
    [Route("[controller]/[action]")]
    public class WeatherController : ControllerBase
    {
        [HttpGet]
        string Get()
        {
            return "Hello World";
        }
    }

     

    當我們進行如上請求時會發現接口請求不到,這是為何呢?細心的你應該可能發現了,對於請求方法是私有,而不是公共的,當我們加上public就可以請求到了接口

    [HttpGet("get")]
    public string Get()
    {
        return "Hello World";
    }

    匹配控制器Action方法本質

    經過如上示例,那麼對於Action方法的到底要滿足怎樣的定義才能夠不至於請求不到呢?接下來我們看看源碼怎麼講。我們找到DefaultApplicationModelProvider類,在此類中有一個OnProvidersExecuting方法用來構建控制器和Action方法模型,當我們構建完畢所有滿足條件的控制器模型后,緊接着勢必會遍歷控制器模型去獲取對應控制器模型下的Action方法,這裏只截取獲取Action方法片段,源碼如下:

    foreach (var controllerType in context.ControllerTypes)
    {    
        //獲取控制器模型下的Action方法
        foreach (var methodInfo in controllerType.AsType().GetMethods())
        {
            var actionModel = CreateActionModel(controllerType, methodInfo);
            if (actionModel == null)
            {
                continue;
            }
    
            actionModel.Controller = controllerModel;
            controllerModel.Actions.Add(actionModel);    
        }
    }

    上述紅色標記則是創建Action模型的重點,我們繼續往下看到底滿足哪些條件才創建Action模型呢?

    protected virtual ActionModel CreateActionModel(TypeInfo typeInfo, MethodInfo methodInfo)
    {
        if (typeInfo == null)
        {
            throw new ArgumentNullException(nameof(typeInfo));
        }
    
        if (methodInfo == null)
        {
            throw new ArgumentNullException(nameof(methodInfo));
        }
    
        if (!IsAction(typeInfo, methodInfo))
        {
            return null;
        }    
        ......    
    }

    到了這個方法裏面,我們找到了如何確定一個方法為Action方法的源頭,由於該方法有點長,這裏我採用文字敘述來作為判斷邏輯,如下:

    protected virtual bool IsAction(TypeInfo typeInfo, MethodInfo methodInfo)
    {
        //如果有屬性訪問器(無效)
    
        //如果有NonAction特性標識無效)
    
        //如果重寫Equals(Object), GetHashCode()方法(無效)
    
        //如果實現Dispose方法(無效)
    
        //如果是靜態方法(無效)
    
        //如果是抽象方法(無效)
    
        //如果是構造函數(無效)
    
        //如果是泛型方法(無效)
    
        //必須為公共方法
        return methodInfo.IsPublic;
    }

    如上是從方法定義的角度來過濾而獲取Action方法,除此之外,我們請求方法的名稱還可以自定義,比如通過路由、ActionName特性指定,那麼這二者是否存在優先級呢?比如如下示例:

    [ApiController]
    [Route("[controller]/[action]")]
    public class WeatherController : ControllerBase
    {
        [HttpGet]
        [ActionName("get1")]
        public string get()
        {
            var routeValue = HttpContext.Request.RouteValues.FirstOrDefault();
    
            return routeValue.Value.ToString();
        }
    }

    我們可以看到此時將以ActionName特性作為方法名稱。所以在上述過濾方法定義后開始構建方法模型,在此之後還會再做一步操作,那就是查找該方法是否通過ActionName特性標識,若存在則以ActionName特性標識給定的名稱作為請求方法名稱,否則以方法定義名稱為準,源碼如下:

    var actionModel = new ActionModel(methodInfo, attributes);
    
    AddRange(actionModel.Filters, attributes.OfType<IFilterMetadata>());
    
    var actionName = attributes.OfType<ActionNameAttribute>().FirstOrDefault();
    if (actionName?.Name != null)
    {
        actionModel.ActionName = actionName.Name;
    }
    else
    {
        actionModel.ActionName = methodInfo.Name;
    }

    還沒完,若是將路由特性放到Action方法上,如下,此時請求接口應該是weather/get還是weather/get1呢?

    [ApiController]
    public class WeatherController : ControllerBase
    {
        [HttpGet]
        [Route("weather/get")]
        [ActionName("get1")]
        public string get()
        {
            var routeValue = HttpContext.Request.RouteValues.FirstOrDefault();
    
            return routeValue.Value.ToString();
        }
    }

    此時若我們以weather/get1請求將出現404,還是以路由特性模板給定為準進行請求,但最終會將路由上Action方法名稱通過ActionName特性上的名稱賦值給Action模型中的ActionName進行覆蓋,源碼如下,所以上述我們得到的action名稱為get1,,當然這麼做沒有任何實際意義。

    public static void AddRouteValues(ControllerActionDescriptor actionDescriptor,ControllerModel controller,ActionModel action)
    {
        foreach (var kvp in action.RouteValues)
        {
            if (!actionDescriptor.RouteValues.ContainsKey(kvp.Key))
            {
                actionDescriptor.RouteValues.Add(kvp.Key, kvp.Value);
            }
        }
    
        if (!actionDescriptor.RouteValues.ContainsKey("action"))
        {
            actionDescriptor.RouteValues.Add("action", action.ActionName ?? string.Empty);
        }
    
        if (!actionDescriptor.RouteValues.ContainsKey("controller"))
        {
            actionDescriptor.RouteValues.Add("controller", controller.ControllerName);
        }
    }

    總結

    本文我們只是單獨針對查找Action方法名稱匹配問題做了進一步的探討,根據源碼分析,對Action方法名稱指定會做3步操作:第一,根據方法定義進行過濾篩選,第二,若方法通過AcionName特性標識則以其所給名稱為準,否則以方法名稱為準,最終賦值給ActionModel上的ActionName屬性,第三,將ActionModel上的ActionName值賦值給路由集合中的鍵Action。

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

    【其他文章推薦】

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

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

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

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

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

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

  • 高盛:再下60億美元資本 特斯拉就能顛覆汽車界

    上周,高盛分析師派翠克•阿爾尚博(Patrick Archambault)指出,特斯拉或許需要再投入60億美元現金(尤其在2017年至2025年之間),才能實現“到2020年電動汽車的年產量達到50萬輛”的目標,從而顛覆汽車市場。   而特斯拉希望在明年年底前交付10萬輛電動汽車,其中包括Model S和即將推出的Model X。阿爾尚博預測,特斯拉要實現既定目標,到2025年為止將需要生產180萬至320萬輛電動汽車。但是,屆時如果特斯拉未能實現這些生產目標,電池工廠所生產的多餘電池將可能最終由太陽能公司SolarCity所消化。   特斯拉已經為SolarCity生產了少量的蓄電元件,超級電池工廠竣工後將滿足SolarCity部分或全部的耗電需求。馬斯克表示,兩家公司能以獨特的方式相互相容。如果更多的美國人能接受太陽能用於住宅和商業供電,特斯拉及其電池製造合作夥伴松下就能把超級電池工廠過剩產能所餘下的蓄電元件提供給SolarCity。超級電池工廠每年將為特斯拉生產50萬件電池組,因此,特斯拉不打算成為SolarCity蓄電組件的主要供應商。但如果特斯拉達不到生產目標,超級電池工廠就可能為SolarCity多出出力。

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

  • 重歐美輕亞洲 特斯拉第200個充電站投入使用

    近日,特斯拉宣佈其第200個超級充電站已開放使用。這個超級充電站位於美國加州南部的奧克斯納德河流公園公務中心附近。特斯拉目前有57%的充電站位於美國。這些超級充電站可讓特斯拉電動汽車30分鐘充滿電。   特斯拉正不斷完善其充電網路,其向南有霍索恩(Hawthorne)和特甬牧場(Tejon Ranch)超級充電站,向北有索爾萬(Solvang)超級充電站,東部則有巴斯托(Barstow)超級充電站。他們表示明年其充電站網路將覆蓋美國98%的區域。   目前特斯拉已分別在北美、歐洲和亞洲建造了114座、66座、20座超級充電站。為了完善充電網路,特斯拉未來將在北美進一步縮小超級充電站間的間隙,並且將其將延伸至加拿大,而在歐洲,特斯拉將增大超級充電站密度和覆蓋國家。但是在亞洲,特斯拉的超級充電站建造計畫則顯得相對保守,如今在中國僅有7座。

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

    【其他文章推薦】

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

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

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

    南投搬家公司費用需注意的眉眉角角,別等搬了再說!

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

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

  • 中鋼參一腳 入股特斯拉馬達供應商富田

    中鋼集團於上周正式入股美國電動車大廠特斯拉(Tesla)馬達獨家供應商富田電機,成為其最大股東後,中鋼董事長鄒若齊 10 月 1 日首度透露,中鋼已向特斯拉釋出善意,將全力協助富田提升生產能力,希望能夠達到即時供料的能力,確保三方的穩定供應鏈關係。   中鋼轉投資、位於中部的富田公司,現在是特斯拉唯一的馬達材料供應商。中鋼日前投資富田,就是考量這一層供料關係,進而希望能夠強化與特斯拉的合作。   鄒若齊說,富田是中鋼重要的電磁鋼片客戶,但以它目前的產能,一年配合特斯拉的需求,是有能力供應幾千輛電動車所需的馬達給特斯拉。但若要富田供應上萬輛所需的馬達,恐就有困難。因此中鋼投資富田,最大目的就是要協助提升它的生產能力,希望未來能夠做到即時供料給特斯拉的目標,以穩定特斯拉的信心。

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

    【其他文章推薦】

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

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

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

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

    ※超省錢租車方案

  • 看好電動車!三星 LG 等韓企搶入功率半導體市場

    看好物聯網、電動車及智慧裝置未來的發展潛力,南韓大型企業正在全力衝刺功率半導體 (power semiconductor)。南韓媒體 ETNews 2 日報導,LG 電子 (LG Electronics) 正在積極研發功率半導體科技,該公司副董事長 Ku Bon-jun  2014 年稍早就曾親自訪問日本某家半導體公司,並取得技術顧問服務。分析顯示,Ku 這趟行程應該是為了開發 LG 集團瞄準的下一個成長動能──電動車。   功率半導體不但對耗電量有直接影響,也關係到電動車的品質好壞。LG 電子最近收購了 IC 設計商 Silicon Works,也是為了同樣的目的。   三星電子 (Samsung Electronics) 也在持續關注功率半導體的研發部門。三星除了自行開發行動裝置與面板的電源管理 IC 外,還打算發展應用於電動車、可再生能源的相關裝置。三星已經成功在自家的通訊晶片「Exynos Modem 303」導入電源管理解決方案「封包追蹤 (envelope tracking)」技術。這種技術可即時依據頻率、耗電量分配電力,並x連結至基頻 IC、電源管理 IC 以及無線功率放大器 (PA)。

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

    【其他文章推薦】

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

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

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

    ※超省錢租車方案

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

  • Tesla 神秘代號 D 新車 10/9 巴黎車展亮相

    Tesla 神秘代號 D 新車 10/9 巴黎車展亮相

        巴黎國際汽車大展將在 10 月 4 日登場,電動車大廠特斯拉(Tesla)也確定不會缺席。特斯拉預告 9 日將發表代號 D 的神秘新車。除此之外,特斯拉還有更多消息將宣佈,為車展提前炒熱話題。   特斯拉旗下有轎車 Model S、SUV 運動休旅車 Model X,以及正在開發之中的平價車款 Model 3。按此命名慣例,神秘新車預料將稱為 Model D。   特斯拉口風甚緊,此前外界對 Model D 毫無所悉,直至時機成熟,才由執行長 Elon Musk 透過推文對外宣布,且暗示還有其它產品消息。   Musk 曾嘲笑燃料電池,因此可以確定的是 Model D 絕非燃料電池動力車。至於 Musk 口中的其它消息指的可能是升級現有車種硬體設備,如更先進的車用資訊娛樂系統,也有傳言指出可能是全新的電動摩托車,以使特斯拉電動車產品線更多元化。     (Source:)

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

    【其他文章推薦】

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

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

    ※回頭車貨運收費標準

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

    ※超省錢租車方案