標籤: USB CONNECTOR

  • 每天3分鐘操作系統修鍊秘籍(17):進程間通信(3):套接字

    每天3分鐘操作系統修鍊秘籍(17):進程間通信(3):套接字

    套接字

    套接字(Socket)用於協調不同計算機上的進程間通信,也就是基於網絡的通信。當然,也可以在本機上使用套接字進行進程間的通信。

    套接字通信的方式非常多,有Unix域套接字、TCP套接字、UDP套接字、鏈路層套接字等等。但最常用的肯定是TCP套接字。所以,這裏介紹下TCP Socket通信方式,稍後再單獨介紹Unix域套接字。

    TCP Socket用於客戶端、服務端的基於TCP協議的通信,所以在客戶端和服務端均需要創建一個套接字。創建TCP套接字時會返回這個套接字的文件描述符,可通過這個文件描述符對套接字進行讀和寫操作。

    對比一下,當一個程序需要對一個磁盤文件同時進行讀寫操作(在命令行下似乎沒有找到這種命令,但通過編程方式是很容易實現的)時,由於只通過單個文件描述符同時負責讀和寫,很可能需要通過不斷移動文件指針的方式來改變讀寫的位置,否則數據很容易錯亂。

    而TCP套接字也是通過單個文件描述符進行讀寫套接字的,為了保證讀和寫的位置不錯亂,操作系統在內核空間為每個TCP套接字維護了兩個buffer空間,一個buffer用於寫、一個buffer用於讀。提供讀的buffer空間稱為recv buffer,提供寫的buffer空間稱為send buffer,它們統稱為socket buffer

    所以,服務端和客戶端通過兩個套接字通信就簡單了,一端向send buffer寫數據,該buffer的數據會通過已經建立好的TCP連接發送到另一端的recv buffer,於是另一端只需從recv buffer中讀數據即可實現不同計算機上的進程間通信。過程如圖。

    Unix域套接字

    Unix域套接字是套接字的一種,用於本機進程間通信,一般用來實現雙向通信的管道。Unix域套接字是比網絡套接字輕量級且高效的多,因為它不涉及網絡通信,不需要監聽連接,不需要綁定地址,不需要關心協議類型,等等。

    創建Unix域套接字后返回兩個文件描述符,這兩個文件描述符均對套接字可讀、可寫,從而實現全雙工的雙向通信。

    同樣的,為了避免使用單個文件描述符同時讀、寫造成的數據錯亂,Unix域套接字也有兩個buffer空間。

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

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 甲烷排放嚴重低估 研究:石油天然氣危害氣候 比預期還糟

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

    【其他文章推薦】

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

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

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

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

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

    ※試算大陸海運運費!

  • 日本密室會議干預審查 火山灰影響核電廠 安全堪虞

    文:宋瑞文(媽媽監督核電廠聯盟特約撰述)

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 堆肥葬更環保 美各州搶立法通過

    摘錄自2020年2月17日台灣醒報報導

    堆肥葬即將成為新的喪葬趨勢!Recompose公司16日發表聲明,藉由6位志願者遺體的實驗測試,證實利用遺體堆肥不會生成有害物質。當前美國多州正考慮將堆肥葬合法化。

    根據華盛頓州立大學教授卡彭特・伯格斯表示,在人體分解的最後階段加入混合木屑等營養材料,能讓微生物發揮更大效用。最後再加溫至攝氏55度消毒殺菌,分解後的土壤即可作為堆肥使用。

    據《科學新聞》週刊報導,Recompose公司創始人卡特李娜・斯派德在報告中特別表明,堆肥葬的有機降解相對於火葬,可以減少1.4噸的碳排放量,只使用火化所需能源的8分之 1。而相對於土葬,能夠大幅縮小土地使用空間,考慮土葬的棺材用料和成本,也降低碳足跡與喪葬費用。雖然堆肥葬不如火葬費用便宜,但廣泛運用後價格會有變低趨勢。

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

    【其他文章推薦】

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

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

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

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

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

    ※試算大陸海運運費!

  • 全球批評升溫 日本將收緊燃煤發電設備出口條件

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

    日本環境大臣小泉進次郎(Shinjiro Koizumi)今(25日)表示,日本收緊出口燃煤發電設備條件的審查報告將在6月底前發布。

    路透社報導,在日本政府支持印尼、越南興建燃煤發電廠及日本蓋新的燃煤發電廠,引起全球批評後,小泉進次郎做上述宣布。小泉進次郎在記者會上表示,這項討論將為日本於12月籌劃的新基礎設施出口政策勾勒輪廓。

    在現行政策下,當有國家或如果有國家需要選擇以燃煤作為發電來源,並向日本請求提供高效能的燃煤發電技術時,日本將會支持。

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 武漢肺炎延燒 泰非政府組織籲關野生動物市場

    摘錄自2020年02月26日中央社報導

    武漢肺炎蔓延全球,野生動物被懷疑是可能的傳染源。泰國非政府組織(NGO)今(26日)發布報告,呼籲大眾停止購買野生動物,亞洲各國政府應關閉所有野生動物交易市場。

    泰國非政府組織自由地(Freeland)與卓越分析中心販運部門(Analytical Center of Excellence on Trafficking)發布「東南亞的野生動物販運:演化、軌跡和如何組織販運」報告,提出上述呼籲。

    自由地創辦人蓋爾斯特(Steven Galster)在記者會中指出,野生動物交易衍生的疾病風險問題,不只在中國,也不會只在武漢肺炎。緬甸、越南和泰國都賣野生動物,例如穿山甲、烏龜、猴子等。

    自由地執行經理馬占達(Onkuri Majumdar)指出,大家關注2019年冠狀病毒疾病(COVID-19,武漢肺炎)可能是蝙蝠或穿山甲傳染給人類。但不要忘記,嚴重急性呼吸道症候群(SARS)、禽流感、伊波拉病毒(Ebola Virus)甚至愛滋病毒都是由動物傳給人類,撲殺這些動物並不是解決的辦法。她呼籲各國政府關閉野生動物交易市場,大眾停止購買野生動物。

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

    【其他文章推薦】

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

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

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

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

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

    ※試算大陸海運運費!

  • 氣候風險應納入企業稽核 全球會計師公會聯盟發起倡議

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • Spring註解@Configuration是如何被處理的?

    Spring註解@Configuration是如何被處理的?

    從SpringApplication開始

    一般情況下啟動SpringBoot都是新建一個類包含main方法,然後使用SpringApplication.run來啟動程序:

    @SpringBootApplication
    public class AutoConfigApplication {
    
        public static void main(String[] args){
            ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(AutoConfigApplication.class,args);
        }
    }
    

    SpringApplication.run接收兩個參數分別為:primarySource、運行參數(args),上面的代碼使用AutoConfigApplication.class作為primarySource。SpringApplication還有一個實例方法也叫run,SpringBoot的大部分啟動都由實例run方法來完成的,其中構造ApplicationContext由createApplicationContext方法完成:

    protected ConfigurableApplicationContext createApplicationContext() {
            Class<?> contextClass = this.applicationContextClass;
            if (contextClass == null) {
                try {
                    switch (this.webApplicationType) {
                    case SERVLET:
                        contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                        break;
                    case REACTIVE:
                        contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                        break;
                    default:
                        contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                    }
                }
                catch (ClassNotFoundException ex) {
                    throw new IllegalStateException(
                            "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
                }
            }
            return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
        }

    createApplicationContext根據this.webApplicationType來構造ApplicationContext,不同的環境都會使用不同的實例,但本文非web環境所有構造的時候會使用AnnotationConfigApplicationContext類。創建AnnotationConfigApplicationContext的時候會調用默認構造方法

    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

    AnnotationConfigApplicationContext默認構造函數創建兩個對象:

    • reader(AnnotatedBeanDefinitionReader):用於手動註冊bean
    • scanner(ClassPathBeanDefinitionScanner): 用於掃描Component、Repository、Service等註解

    AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner會註冊一些註解處理器,註冊的方式都是使用AnnotationConfigUtils的registerAnnotationConfigProcessors方法

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, @Nullable Object source) {
    
            ...
            
            if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
            ...
            return beanDefs;
        }

    最終AnnotationConfigApplicationContext構造方法執行完成后ApplicationContext會有以下BeanDefinition:

    構造完ApplicationContext后SpringApplicaiton緊接着會加載primarySource,上面提到 過primarySource是在運行的時候傳遞進來的(AutoConfigApplication.class),加載過程中不貼代碼了,只要知道最終ApplicaitonContext中會多一個AutoConfigApplication的BeanDefinition:

    小結

    總的來說SpringApplicaiton主要幹了這些事:

    • 創建AnnotationConfigApplicationContext
    • 加載一些處理註解的后處理器如:ConfigurationClassPostProcessor
    • primarySource加載進ApplicationContext

    最重要的一點是,現在是有一個AnnotationConfigApplicationContext裡面包含了primarySource(AutoConfigApplication)以及ConfigurationClassPostProcessor。打個斷點在ApplicaitonContext刷新之前打印下context中的bean的名稱,可以確定這樣說沒毛病!

    @Configuration啥時候被解析?

    雖說有了primarySource和ConfigurationClassPostProcessor后處理器,還是需要有個執行的入口。ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcessor的實現類,BeanDefinitionRegistryPostProcessor會在ApplicationContext的refresh操作時被處理:

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                ...
                invokeBeanFactoryPostProcessors(beanFactory);
                ...
            }
    }
        
    public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
            
            ...
            //找出所有類型為BeanDefinitionRegistryPostProcessor的bean的名稱
            String[] postProcessorNames =
                        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            //執行BeanDefinitionRegistryPostProcessor
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            ...
    }
    
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            //調用postProcessBeanDefinitionRegistry方法
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }   
    

    invokeBeanDefinitionRegistryPostProcessors會調用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,通過斷點調試工具確認下ConfigurationClassPostProcessor有沒有在這一步被處理:

    調試輸出postProcessors集合裏面有一個了ConfigurationClassPostProcessor元素,說明了ConfigurationClassPostProcessor的執行入口沒有問題。

    ConfigurationClassPostProcessor處理器

    ConfigurationClassPostProcessor首先會判斷在ApplicationContext中的bean是否被@Configuration註解標記,然後使用ConfigurationClassParser來解析@Configuration,ConfigurationClassPostProcessor的解析@Configuration的大致流程:

    1. 使用ConfigurationClassUtils.checkConfigurationClassCandidate檢查BeanDefinition是否@Configuration註解標記
    2. 對@Configuration進行排序
    3. 使用ConfigurationClassParser解析@Configuration註解的信息
    4. 使用ConfigurationClassBeanDefinitionReader解析BeanDefinition
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
            
            //獲取所有BeanDefinitio名稱
            String[] candidateNames = registry.getBeanDefinitionNames();
            
            for (String beanName : candidateNames) {
                BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                //如果是full、lite則說明已經處理過的類
                if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                        ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                    }
                }
                //檢查BeanDefinition是否有@Configuration註解
                else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
            }
    
            //如果沒有找到@Configuration標記的類,則返回不作處理也
            if (configCandidates.isEmpty()) {
                return;
            }
    
            //對@Configuration進行排序
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
            
            ...
      
            ConfigurationClassParser parser = new ConfigurationClassParser(
                    this.metadataReaderFactory, this.problemReporter, this.environment,
                    this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
            Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
            do {
                //解析@Configuration class
                parser.parse(candidates);
                parser.validate();
    
                Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
    
                //讀取BeanDefinition
                if (this.reader == null) {
                    this.reader = new ConfigurationClassBeanDefinitionReader(
                            registry, this.sourceExtractor, this.resourceLoader, this.environment,
                            this.importBeanNameGenerator, parser.getImportRegistry());
                }
                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
    
                candidates.clear();
                ...
            }
            while (!candidates.isEmpty());
            ...
        }

    最後還是通過調試工具看一下示例中的的啟動類AutoConfigApplication沒有被處理:

    圖上显示configCandidates中有一個名稱為autoConfigApplication的BeanDefinition的元素,說明AutoConfigApplication會被當作配置類解析,但是AutoConfigApplication並沒有使用@Configuration註解,為什麼還會被當做配置類呢?其實@Configuration在@SpringBootApplication註解中:

    紅色背景列出來的就是@Configuration註解,它是@SpringBootConfiguration的元註解。

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

    【其他文章推薦】

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

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

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

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

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

    ※試算大陸海運運費!

  • HNU_團隊項目_數據庫框架Mybatis_環境配置和樣例,IDEA項目搭建四——使用Mybatis實現Dao層

    HNU_團隊項目_數據庫框架Mybatis_環境配置和樣例,IDEA項目搭建四——使用Mybatis實現Dao層

    前言

    數據庫從最傳統的JDBC連接方式和數據庫池化技術Hibernate的使用,再到Mybatis的快捷輕量級操作,技術迭代的速度飛快。

    在了解了基礎的理論和方法后,學習前沿編程框架、工具,我認為是一種必然的趨勢。

    再不看看外面,可能真的要落伍了~

    之後,我借團隊項目開發的機會,學習了Mybatis框架,和大家分享一下經驗,願意和大家共同進步!

     

    正文

    從零開始

    參考: 

    1. 下載Mybatis的,並且導入

      點擊連接,選擇下載Mybatis的jar包。這裡有三個文件,基礎使用的話,下載第一個mybatis-3.5.3.zip即可,如果需要查看源碼的話,建議將Source code也下載下來,Windows使用zip,Ubuntu使用tar.gz;

      Eclipse導入只要build puth即可,IDEA的話,在File->Project Structure里導入jar;(建議在項目內建一個lib文件夾,便於遷移)

      只是數據庫部分的話,以下兩個包便足夠了。

     

     

    2. 新建Java Web Application,編寫數據庫配置文件

    文件名可以自定義,我設置的是Mybatis.xml。但是要放到src的根目錄下,這一點要注意。

    注意

    url的配置信息中 ” & ” 符號無法解析,需要變為 “ &amp; “;

    映射文件路徑以 “ / ”作為文件夾,從src作為根目錄進行訪問;

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE configuration
     3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5 <!--上面一段是非常重要的,有了這一段,xml的配置就擁有了自動補全,這也是考量Mybatis包是否導入成功的一個方面;-->
     6 <configuration>
     7 <!--    可以兼容多種數據庫,配置多個environment,default為當前配置-->
     8     <environments default="mysql">
     9         <environment id="mysql">
    10             <transactionManager type="JDBC"/>
    11 <!--            使用數據庫池化技術,詳細可以看官方文檔-->
    12             <dataSource type="POOLED">
    13                 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    14                 <property name="url" value="jdbc:mysql://localhost:3306/databaseName?useUnicode=true&amp;serverTimezone=GMT%2B8&amp;characterEncoding=utf-8"/>
    15                 <property name="username" value=username"/>
    16                 <property name="password" value="password"/>
    17             </dataSource>
    18         </environment>
    19     </environments>
    20 <!--    映射文件路徑,需要告訴數據庫,要執行哪些操作,以及數據庫實體類和字段的對應關係,接下來進行解釋-->
    21     <mappers>
    22         <mapper resource="main/mapper/UserMapper.xml"/>
    23     </mappers>
    24 </configuration>

     

    3. 編寫執行SQL語句的SqlSessionFactory

      可以編寫工具類或者工廠類,避免代碼重複。我這裏設置的是DBTools.java

     1 package main.dao;
     2 
     3 import org.apache.ibatis.io.Resources;
     4 import org.apache.ibatis.session.SqlSession;
     5 import org.apache.ibatis.session.SqlSessionFactory;
     6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     7 
     8 import javax.annotation.Resource;
     9 import java.io.IOException;
    10 import java.io.InputStream;
    11 
    12 /*
    13 Comet_Fei
    14 2019/11/17
    15 */
    16 public class DBTools
    17 {
    18     private static SqlSessionFactory sqlSessionFactory;
    19 
    20     static
    21     {
    22         try
    23         {
    24             //輸入流讀取文件 Resources Mybatis的自帶加載類
    25             InputStream config = Resources.getResourceAsStream("mybatis.xml");
    26             //工廠設計模式
    27             sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    28         }
    29         catch (IOException e)
    30         {
    31             e.printStackTrace();
    32         }
    33     }
    34 
    35     //創建可以執行映射文件sql的sqlsession
    36     public static SqlSession getSqlSession()
    37     {
    38         return sqlSessionFactory.openSession();
    39     }
    40 }

     

    4. 編寫表對應的實體類User.java

     此處可用IDEA的pojo快捷操作,生成對應實體;

    package main.pojo;
    
    
    public class User {
    
        private String userPhoneNumber;private String userName;private String userPassword;public User(String userPhoneNumber, String userName, String userPassword) {
            this.userPhoneNumber = userPhoneNumber;
            this.userName = userName;
            this.userPassword = userPassword;
        }
    
        public String getUserPhoneNumber() {
            return userPhoneNumber;
        }
    
        public void setUserPhoneNumber(String userPhoneNumber) {
            this.userPhoneNumber = userPhoneNumber;
        }public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }public String getUserPassword() {
            return userPassword;
        }
    
        public void setUserPassword(String userPassword) {
            this.userPassword = userPassword;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "userPhoneNumber='" + userPhoneNumber + '\'' +
                    ", userName='" + userName + '\'' +
                    ", userPassword='" + userPassword + '\'' +
                    '}';
        }
    }

     

     

    5. 編寫實體管理類映射接口UserMapper.java

      UserMapper接口和Mybatis的映射xml文件相對應,便於操作和使用

     

     1 package main.mapper;
     2 
     3 import main.pojo.User;
     4 
     5 import java.util.List;
     6 
     7 /*
     8 Comet_Fei
     9 2019/11/17
    10 */
    11 public interface UserMapper
    12 {
    13     int addUser(User user);
    14     User getUser(String userPhoneNumber);
    15     int deleteUser(String userPhoneNumber);
    16     int setPassword(User user);
    17     List<User> listUser();
    18 
    19 }

     

    5. 編寫映射文件UserMapper.xml

      這類文件非常重要,會將數據庫表和Java代碼的pojo(bean)進行映射,極大的簡化了操作步驟,減小代碼量。

    參數說明:

    • resultMap是數據庫表和實體的Map映射設置,在使用時,只要加入 resultMap=”userResultMap” 參數即可,如select語句;
    • parameterType是傳入的參數類型,如果傳入參數較多的話,可以使用實體類傳參,但是要寫明實體類全路徑;(還沒有學習複雜語句,所以這裏只是簡單介紹)
    • resultType是返回值類型,但是不能和resultMap同時存在;
    • 傳參方式如代碼所示,用  ${ } 標識參數,和接口一致;
    • namespace是全路徑,訪問到當前對應Map的接口文件;
    • 注意傳參的數據類型,如果是字符型或者String,需要用單引號包含,如: ‘${userName}’ 
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="main.mapper.UserMapper">
        <resultMap id="userResultMap" type="main.pojo.User">
            <result property="userPhoneNumber" column="user_phone_number"/>
            <result property="headPictureId" column="head_pictureId"/>
            <result property="rolePowerId" column="role_power_id"/>
            <result property="userName" column="user_name"/>
            <result property="userPersonalAutograph" column="user_personal_autograph"/>
            <result property="userPassword" column="user_password"/>
            <result property="userSex" column="user_sex"/>
            <result property="userEmail" column="user_email"/>
            <result property="userAddress" column="user_address"/>
            <result property="userUploadNumbers" column="user_upload_numbers"/>
        </resultMap>
    
        <!--    添加用戶-->
        <insert id="addUser" parameterType="main.pojo.User">
            INSERT INTO user(user_phone_number, user_name, user_password)
            VALUES ('${userPhoneNumber}', '${userName}', '${userPassword}');
        </insert>
        <!--    刪除用戶-->
        <delete id="deleteUser" parameterType="String">
            DELETE FROM user WHERE user_phone_number = '${userPhoneNumber}';
        </delete>
    
        <!--    獲得賬號為user_phone_number的用戶-->
        <select id="getUser" resultMap="userResultMap">
            SELECT * FROM user WHERE user_phone_number = '${userPhoneNumber}';
        </select>
    
        <!--    獲得用戶列表-->
        <select id="listUser" resultType="main.pojo.User">
            SELECT * FROM user;
        </select>
    
        <!--    找回密碼-->
        <update id="setPassword" parameterType="main.pojo.User">
            UPDATE user SET user_password = ${userPassword} WHERE user_phone_number = '${userPhoneNumber}';
        </update>
    
    </mapper>

     

     

    6. 最後是操作層(DAO)UserDao.java

      因為操作層有特定的業務,這裏只是一個示意而已。java裏面的main函數可以進行局部測試,便於和前端、控制器(servlet)等對接。

     1 package main.dao;
     2 
     3 import main.mapper.UserMapper;
     4 import main.pojo.User;
     5 import org.apache.ibatis.session.SqlSession;
     6 
     7 import java.io.IOException;
     8 
     9 /*
    10 Comet_Fei
    11 2019/11/17
    12 */
    13 public class UserDao {
    14 //    定義dao內的sqlSession和映射接口mapper
    15     private SqlSession sqlSession;
    16     private UserMapper mapper;
    17 
    18     public UserDao()
    19     {
    20 //        通過工廠,初始化session;通過特有getMapper設置映射接口
    21         sqlSession = DBTools.getSqlSession();
    22         mapper = sqlSession.getMapper(UserMapper.class);
    23     }
    24 
    25     //添加用戶 成功1 失敗0
    26     public int addUser(String userPhoneNumber, String userPassword) throws IOException
    27     {
    28         //用戶的 手機號,姓名(默認手機號),密碼
    29         User user = new User(userPhoneNumber,userPhoneNumber, userPassword);
    30         int result = mapper.addUser(user);
    31         sqlSession.commit();
    32         System.out.println(result);
    33         return result;
    34     }
    35 
    36     //用戶登錄 短信 成功2;失敗0
    37     public int right(String userPhoneNumber)
    38     {
    39         int result;
    40         User user = mapper.getUser(userPhoneNumber);
    41         if(user != null)
    42         {
    43             result = 2;//登錄成功
    44         }
    45         else
    46         {
    47             result = 0;//登錄失敗
    48         }
    49         sqlSession.commit();
    50         return result;
    51     }
    52 
    53     //用戶登錄 手機 密碼 成功2;密碼錯誤1;手機號錯誤0
    54     public int right(String userPhoneNumber, String userPassword)
    55     {
    56         int result;
    57         User user = mapper.getUser(userPhoneNumber);
    58         if((user != null)&&(userPassword.equals(user.getUserPassword())))
    59         {
    60             result = 2;//登錄成功
    61         }
    62         else if(user != null)
    63         {
    64             result = 1;//密碼錯誤
    65         }
    66         else
    67         {
    68             result = 0;//此手機號未註冊
    69         }
    70         sqlSession.commit();
    71         return result;
    72     }
    73 
    74     //刪除用戶 成功是1,不成功是0
    75     public int deleteUser(String userPhoneNumber)
    76     {
    77         int result = mapper.deleteUser(userPhoneNumber);
    78         sqlSession.commit();
    79         return result;
    80     }
    81 
    82     //重設密碼
    83     public int setPassword(String userPhoneNumber, String userPassword)
    84     {
    85         User user = new User(userPhoneNumber, userPhoneNumber, userPassword);
    86         return mapper.setPassword(user);
    87     }
    88     public static void main(String[] args) throws IOException {
    89         UserDao dao = new UserDao();
    90 //        System.out.println(dao.deleteUser("111")); //刪除用戶
    91 //        dao.addUser("111","111");// 添加用戶
    92 //        System.out.println(dao.right("11"));//短信登錄;
    93 //        System.out.println(dao.right("111","111"));//短信登錄;
    94         System.out.println(dao.setPassword("111","111"));
    95     }
    96 }

     

    以上為全部內容,之後還會寫一些關於IDEA操作上的快捷鍵,如,IDEA如何連接數據庫、快速生成pojo實體類等的博客。

    如果運行異常,歡迎留言交流,共同進步!

    這裏特別感謝博客: 

     

     

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

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 【原創】使用批處理腳本自動生成並上傳NuGet包

    【原創】使用批處理腳本自動生成並上傳NuGet包

      Hello 大家好,我是TANZAME,我們又見面了。

      NuGet 是什麼這裏就不再重複啰嗦,園子里一搜一大把。今天要跟大家分享的是,在日常開發過程中如何統一管理我們的包,如何通過批處理腳本生成包並自動上傳到 NuGet。在實際項目開發過程中我們要上傳自己的包,一般的步驟都是:nuget spec => nuget pack => nuget push,一個包都要至少重複三個動作,如果有 N 個包那就要重複 N*3 次,想想都不能忍,所以便有了今天的分享主題。

    • 生成目錄

      既然是統一管理,生成的包自然是放在同一個文件夾,而不是分散在各個 .proj 目錄里。這裏我們在解決方案所在目錄新建一個目錄,這樣做的目的是方便 bat 腳本找到解決方案下面的子項目。比如我這裏新建的是 .nuget 這個目錄,需要注意的是如果目錄名稱有特殊字符的話不能直接右鍵新建,需要用命令提示符,直接在解決方案所在目錄使用快捷鍵 SHIFT + 右鍵 就能直接打開命令提示符,這樣可以省去一大堆 cd 的操作。

     

    • 下載 NuGet

      到 NuGet 官網下載命令行接口(CLI)。nuget.exe提供了完整的 nuget 功能, 可用於安裝、創建、發布和管理包, 而無需對項目文件進行任何更改。

    1. 請訪問 ,並選擇 NuGet 3.3 或更高版本(2.8.6 與 Mono 不兼容)。 始終建議使用最新版。若要將包發布到 nuget.org,版本至少必須是 4.1.0。
    2. 每次下載都直接下載 nuget.exe 文件。 讓瀏覽器將文件保存到選定文件夾。 此文件不 是安裝程序;如果直接在瀏覽器中運行,就不會看到任何內容。
    3. 將文件夾添加到 nuget.exe 中放置 PATH 環境變量的位置,這樣就可以從任意位置使用 CLI 工具。這裏我們把它放在上一步新建的 .nuget 文件夾下面,並設置 PATH 環境變量。

     

    • 生成清單

      是包含包元數據的 XML 清單, 此清單同時用於生成包以及為使用者提供信息。這個清單文件我們只需要生成一次,以後都不需要再重新生成。 .net Core 和使用sdk 特性.NET Standard 項目不需要 .nuspec 文件,如果是.net Core 和使用sdk 特性.NET Standard 項目則忽略此步驟。轉到項目所在目錄,SHIFT + 右鍵 調出命令提示符,輸入 nuget spec 命令即可生成我們所需要的包元數據清單。

     

      將這個清單文件剪切到第一步新建的 .nuget 文件夾,剪切過去後項目下面就不會憑空多出一個文件,看着清爽多了。然後做一下調整填入我們自己項目的相關信息, 比如像下面這樣:

    <?xml version="1.0" encoding="utf-8"?>
    <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
      <metadata>
        <id>TZM.XFramework</id>
        <version>$version$</version>
        <title>$title$</title>
        <authors>$author$</authors>
        <owners>$author$</owners>
        <license type="expression">Apache-2.0</license>
        <projectUrl>https://github.com/TANZAME/TZM.XFramework</projectUrl>
        <iconUrl>http://go.microsoft.com/fwlink/?LinkID=386613</iconUrl>
        <description>TZM.XFramework is a lightweight and high performance object-relational mapper for .NET use the original Entity Framework api.</description>
        <copyright>Copyright 2019</copyright>
        <tags>.NET SqlServer MSSQL Database Data O/RM ADO.NET</tags>
        <repository type="git" url="https://github.com/TANZAME/TZM.XFramework" />
        <dependencies />
        <frameworkAssemblies>
          <frameworkAssembly assemblyName="System.Data"/>
          <frameworkAssembly assemblyName="System.ComponentModel.DataAnnotations"/>
          <frameworkAssembly assemblyName="System.Net.Http"/>
        </frameworkAssemblies>
      </metadata>
    </package>

     

    • 編寫腳本

      在第一步新建的文件夾里新建一個 bat 文件,重命名為 package.bat,接下來編寫我們的自動腳本。完整 bat 腳本,直接上代碼片段。

    1. 這裏我設置 nuget pack 包屬性為Release,並且不自動生成,所以需要先在 Release 模式下編譯完成再運行腳本。加上 -Build 參數的話輸出的信息太多看得賊難受,這裏把它去掉,我們自己手動編譯。
    2. 填充api_key。去 nuget 官網 登錄自己的帳號並創建一個 key,複製粘貼到 api_key 變量。
    3. 注意 .net framework 項目(fx)和 .net core 項目使用的命令不一樣
    4. 至此我們所有的準備步驟都已完成,雙擊 package.bat 運行腳本,解放雙手。
    @echo off
    set api_key=xxxxxxlef2j57rw4q26qcrvycvznyvcurgfxbzxxxxxxxx
    set source_api_uri=https://api.nuget.org/v3/index.json
    set startup_dir=%~dp0
    cd ..\
    set startup_dir=%cd%
    cd .nuget
    
    :: 打包 TZM.XFramework -Build
    echo pack TZM.XFramework
    copy TZM.XFramework.nuspec %startup_dir%\net45\TZM.XFramework
    nuget pack %startup_dir%\net45\TZM.XFramework\TZM.XFramework.csproj -Properties Configuration=Release
    del %startup_dir%\net45\TZM.XFramework\TZM.XFramework.nuspec
    echo=
    
    :: 打包 TZM.XFrameworkCore
    echo pack TZM.XFrameworkCore
    dotnet pack --no-build --configuration Release --output %startup_dir%\.nuget\ %startup_dir%\netcore\TZM.XFrameworkCore\TZM.XFrameworkCore.csproj
    
    :: 批量推送包
    for /R %cd% %%f in (*.nupkg) do ( 
    echo=
    dotnet nuget push %%f -k %api_key% -s %source_api_uri%
    )
    
    echo=
    pause

      最後貼一張最終運行的效果圖:

    • 總結

       通過這個腳本,我們可以在一個文件夾里統一管理我們的包,做到一鍵生成、上傳同時保持項目文件的清爽,嗯簡直不要太方便 ~..~

       參考資料:

       技術交流群:816425449

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

    【其他文章推薦】

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

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

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

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

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

    ※試算大陸海運運費!