分類
發燒車訊

使用四叉樹優化碰撞檢測

四叉樹是干什麼的?

百度百科
四元樹又稱四叉樹是一種樹狀數據結構,在每一個節點上會有四個子區塊。四元樹常應用於二維空間數據的分析與分類。 它將數據區分成為四個象限。數據範圍可以是方形或矩形或其他任意形狀。
從定義我們可以看出重點信息:

  1. 樹狀結構
  2. 四個區塊
  3. 分類
  4. 矩形

圖示講解

講解之前需要先說明一下四叉樹是用來做什麼的,明白了原理才好理解它的行為。
使用四叉樹就是使用分類的方法,減少碰撞節點的個數,只取出與給定碰撞體相同區域或者壓在碰撞體所在區域邊上的對象。

  1. 將遊戲屏幕分為四個區域。
  2. 插入對象
  3. 插入的對象超過了我們設置的閾值時,劃分
  4. 插入的對象再次超過了我們設置的閾值時,繼續分。

分析

插入

從上面的圖示我們可以很好理解四叉樹的原理。涉及的都是插入操作。
那麼插入操作具體都做了什麼呢?

從代碼中我們可以看出:

  1. 當插入第一個對象的時候只走了2;這個時候沒有子樹,所以不會走1,因為objects(管理的對象)的長度還沒有超過我們設置的閾值MAX_OBJECTS,所以也不會走3。
  2. 一直插入,當objects中的數量,超過了我們設置的閾值MAX_OBJECT,就會開始劃分,產生子樹,有了nodes,劃分之後將自己管理的節點插入到子樹中。再此之前,都不會走1,因為還沒有產生子樹。
  3. 劃分之後再次插入新對象,如果對象可以獲得對應的象限,就會走1 不會走2和3,如果沒有獲得對應的象限才會走2,3(沒有獲得的情況可能是你創建的對象在屏幕外,遊戲中很多情況是敵人從屏幕外走進屏幕的,具體可參考我做的《星際迷航》或者《星際戰》遊戲)。

更新對象

我是把四插入作為了對象管理器使用,要不然對象也需要更新,所以有了這一步操作。如果不這樣你需要自己創建對象管理器,一個一個放進去,刪除。通過四叉樹直接管理省了不少事情。

更新象限信息。

這是一個遞歸操作,更新象限做的事情比較多了。

  1. 檢查對象是否存活,如果死亡就回收,我這裏使用了對象池,所以對象實現了poolAble接口。

  2. 判斷對象的所佔區域是否在四叉樹的區域內
    這裏需要說明的是一個四叉樹本身的區域是它管理的四個象限這麼大。也就是一個四叉樹管理四個象限

    不在管理區域的話需要判斷當前this是否為根節點,如果是說明對象已經出屏了。(這個時候可以通過對象實現的isVisible接口來控制是否回收,因為不是所有在屏幕外的都要回收,比如要進入屏幕的敵人,是不可能回收的,所以需要自己用isVisible接口來控制)。如果不是就將對象放入根節點,重新劃分。

  3. 在管理區域內,就看看在四叉樹管理的哪個象限里。更新象限信息。

    如果沒有變化什麼都不過,如果有變化,先判斷象限是否為-1,為什麼會出現-1,也就是不在四個象限的任何一個象限?因為壓線了。此番操作后的結果如下圖。

根據給定矩形獲取對象列表

  1. 第一個是步長,用於獲取深度,當然深度越長,處理的時間越長,獲取的對象也精細。這個可以根據自己遊戲的同屏四叉樹層級而定了。
  2. 如果通過obj的rect獲得對象所在象限如果獲得了對應的象限,用獲得的象限的四叉樹再獲取。如果壓線的話就需要將碰撞的兩個象限的內容都取出來。
  3. 返回四叉樹中沒有分割象限的對象。

怎麼用呢?

自然就是把要碰撞的對象傳給retrieve函數獲得需要碰撞的對象列表進行碰撞檢測了。
也就是文章靠頭說的:
使用四叉樹就目的是為了減少碰撞節點的個數。使用的是分類的方法。
至於用什麼樣的碰撞檢測函數,不是四叉樹關心的事情,

至於用幾個四叉樹管理對象,也不是四叉樹關心的事情。

結語

想要demo的同學可以去我的微店或者官方creator商城購買《跨引擎遊戲框架》源碼,跟demo是一個項目。買過的同學請加我好友,群已經建好,有更新我會群里直接發包。

源碼購買入口:

demo展示:

項目截圖:

框架的相關模塊教程可以到《我的專輯》遊戲開發進階教程中獲取。
後續還會推出更多與框架有關的教程:如:戰鬥框架,教學框架等等。並附帶完整的遊戲實現(飛行射擊遊戲為例,學會做飛行射擊遊戲不是目的,目的是通過這一款遊戲,你可以獲得做其他所有類型的遊戲的思路)。希望可以在不餓死自己的前提下幫助更過的朋友們快速找到開發思路。

長按下方二維碼,關注《微笑遊戲》公眾號,獲取更多精彩內容。

歡迎掃碼關注公眾號《微笑遊戲》,瀏覽更多內容。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

福斯推出概念電動車,續航力上看600公里

福斯汽車(Volkswagen)因排氣造假醜聞而加速電動車研發腳步,不僅研發電動車平台MEB,更預計在今年9月底的巴黎車展上推出首輛由MEB平台打造的電動概念車。這款電動概念車的續航力據報導可達400~600公里。

媒體報導,福斯這款即將面世MEB平台電動概念車,外觀較接近既有車款,大小類似Golf,空間則接近Passat。為維持價格合理,並未採用太多昂貴的輕量複合材質。

值得注意的是,在NEDC標準測試下,這款概念車的續航力可達400~600公里之遠。優異的續航性能與合理定價,將有助提高消費者對產品的接受度。此外,這款概念車據稱已十分接近量產階段,預期會在2019年正式投產。

MEB平台也會陸續研發出多款電動汽車,如Phaeton、Budd-e等。福斯計畫在2025年之前推出至少30款電動車款,並在2030年時將電動車銷售量提高到旗下總銷量的三分之一。

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

【其他文章推薦】

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

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

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

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

利基應用突破,崧騰五年車用佔比衝兩成

車用接單突破,電源開關模組廠商崧騰(3484)車用高壓連接器,8月起開始放量,另開關模組也切入大陸合資車廠,預計11、12月開始交貨。董事長張俊雲(附圖)表示,今(2016)年算是打入車用客戶很好的開始,2017-2018年會看到比較明顯的效果,五年內期許車用佔比能超過兩成。

崧騰成立於1992年,初期是以單純的開關鍵為主,其後在為日系工具機客戶開發機構與控制器,建立成功模式下,開始整合機構模具、電子控制器與軟硬體的能力,並逐步擴大利基領域的轉型;以今年前8月來看,資訊與消費電子的營收占比已掉到35~36%,取而代之的是工具機占比超過四成,家電占比則拉高至15~17%。

而今年崧騰在車用上也有重大突破。張俊雲透露,該公司在車用的產品包括車用電源插座、電池連接器、高壓連接器及開關模組等,以高壓連接器來說,因需承受至少170伏特以上的電壓測試,且車廠供應鏈封閉,過去幾乎都是如美商安費諾等的天下,但公司歷經一年以上的開發與認證,去年起已陸續打入電動機車及中美電動車大廠客戶,且8月起單月出貨已有萬顆水準,同時未來配合電源廠客戶台達電(2308)的開發進度,產品還有機會擴及電動車或充電座上其他機構零件。

除了高壓連接器,張俊雲說,在傳統車廠方面,崧騰也已接獲大陸合資車廠開關模組訂單,預計11、12月交貨。他說,今年是車用很好的開始,2017-2018年會看到比較明顯的成果,期許五年內車用佔比能突破兩成水準。

除利基應用的開花結果外,配合全球客戶的東南亞布局,崧騰也在2013年8月設立柬埔寨廠,工廠坐落於金邊奇倉工業區,2014年2月正式量產,生產端子座注射、線材加工、成品組裝等自動化相對較低的製程,現有月產能共計1,500萬個,對集團單月營業額貢獻80-100萬美元,占比近一成。

張俊雲說,包括台達電、日本客戶與美系工具機大廠,都逐步建置東南亞的供貨基地,主要考量不外乎人工成本較低與人力穩定度較高,而該公司當時赴柬國設廠,考慮的也是約當大陸及泰國三分之一的人工成本、政治相對穩定、沒有外匯管制、占比六成的勞動人口等;其對東南亞兩個據點泰國及柬埔寨的長期期許是,前者能擔綱集團在東協的銷售據點,後者則是製造中心,並能與中國大陸的華南及華東生產基地,並駕齊驅。

法人也估計,崧騰今年第三季營收可望創下新高,第四季小幅衰退,但下半年在營收規模與毛利率提升下,獲利將較上半年近倍成長,全年仍力拼本業獲利持續加溫,整體盈餘優於去年水準。

本文由嘉實資訊 MoneyDJ 授權使用 記者 蕭燕翔 報導

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

人臉識別和手勢識別應用(face++)開發

基礎認識

本項目使用的是face++平台,人臉識別+手勢識別雙確認显示。

python編程,代碼簡介,方便擴展。

 

該項目適用於Windows系統和Linux系統,但必須安裝相應的模塊,其中包括

 

l  Python3  python 庫,邏輯編寫

l  Pillow   窗口開發實現

l  opencv-python python的opencv接口

l  Opencv庫   用於人臉檢測

 

本次測試是在win 10電腦上

 

視頻演示:

https://www.bilibili.com/video/BV1Wk4y1z7H7

 

安裝python3

這個網上到處都是資料,找一找就知道啦

官網:

https://www.python.org/

 安裝pillow

該庫用於python做界面開發,詳細參考:https://www.cnblogs.com/dongxiaodong/p/9971974.html

這個庫一般電腦都自帶有了,可以先不安裝,直接運行代碼。

如果出現以下錯誤,則必須手動安裝

ModuleNotFoundError: No module named ‘PIL’

安裝命令:

pip install pillow

安裝opencv-python

Opencv可以實現人臉檢測、人臉對比識別等功能,但在次只是用它來實現了人臉檢測並做人臉框圖,並沒有更多功能的實現,想要獲取更多功能的學習參考,請訪問:https://www.cnblogs.com/dongxiaodong/p/10134904.html

pip install opencv-python

如果出現紅色字體,表示安裝出錯了,必須從新運行安裝命令

 

 Face++

Face++在項目中用於人臉識別和手勢識別

系統流程主要為如下:

 

測試

(一)  獲取人臉標識

工程目錄:

 

l  運行項目,攝像頭將開啟,實時展示所拍攝的畫面

l  按下空格鍵即可獲取人臉標識,輸出人臉標識和存儲到data文件目錄下

l  此時按下ESC鍵則退出程序

l  同一個人的人臉標識很有可能是不一樣的,因為它更多的是基於本次照片計算

 

(二)  創建人臉庫&人臉標識添加到人臉庫

 

 

 

l  創建人臉標識庫,標識名自定義,但同一用戶內不可有相同的人臉標識庫

l  在函數填寫自己賬戶下唯一的人臉庫標識名

 

 

l  將人臉標識添加到人臉庫中

l  在函數中填寫人臉庫標識和我們第一步獲取的人臉標識,將人臉標識添加到人臉庫中

l  人臉庫可以添加多個不同的人臉標識

 

(三)  人臉庫搜索結果比對

 

l  修改為我們剛剛所創建的人臉庫,進行接下來的人臉識別查找

l  運行工程后將開啟攝像頭進行照片實時捕獲識別,並在屏幕中显示識別結果

l  識別包括人臉識別和手勢識別

l  只有在人臉識別正確的情況下才會開啟手勢識別

 

人臉識別失敗

人臉識別成功,無手勢

人臉識別成功,手勢為合攏

人臉識別成功,手勢為打開

 

 

視頻演示:

https://www.bilibili.com/video/BV1Wk4y1z7H7

 

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

【其他文章推薦】

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

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

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

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

基於NACOS和JAVA反射機制動態更新JAVA靜態常量非@Value註解

1.前言

項目中都會使用常量類文件, 這些值如果需要變動需要重新提交代碼,或者基於@Value註解實現動態刷新, 如果常量太多也是很麻煩; 那麼 能不能有更加簡便的實現方式呢?

本文講述的方式是, 一個JAVA類對應NACOS中的一個配置文件,優先使用nacos中的配置,不配置則使用程序中的默認值;

2.正文

nacos的配置如下圖所示,為了滿足大多數情況,配置了 namespace命名空間和group;

 

 

 新建個測試工程 cloud-sm.

bootstrap.yml 中添加nacos相關配置;

為了支持多配置文件需要注意ext-config節點,group對應nacos的添加的配置文件的group; data-id 對應nacos上配置的data-id

配置如下:

server:
  port: 9010
  servlet:
    context-path: /sm
spring:
  application:
    name: cloud-sm
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.100.101:8848 #Nacos服務註冊中心地址
        namespace: 1
      config:
        server-addr: 192.168.100.101:8848 #Nacos作為配置中心地址
        namespace: 1
        ext-config:
          - group: TEST_GROUP
            data-id: cloud-sm.yaml
            refresh: true
          - group: TEST_GROUP
            data-id: cloud-sm-constant.properties
            refresh: true

接下來是本文重點:

1)新建註解ConfigModule,用於在配置類上;一個value屬性;

2)新建個監聽類,用於獲取最新配置,並更新常量值

實現流程:

1)項目初始化時獲取所有nacos的配置

2)遍歷這些配置文件,從nacos上獲取配置

3)遍歷nacos配置文件,獲取MODULE_NAME的值

4)尋找配置文件對應的常量類,從spring容器中尋找 常量類 有註解ConfigModule 且值是 MODULE_NAME對應的

5)使用JAVA反射更改常量類的值

6)增加監聽,用於動態刷新

 

import org.springframework.stereotype.Component;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Component
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ConfigModule {
    /**
     *  對應配置文件裏面key為( MODULE_NAME ) 的值
     * @return
     */
    String value();
}
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.utils.LogUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * nacos 自定義監聽
 *
 * @author zch
 */
@Component
public class NacosConfigListener {
    private Logger LOGGER = LogUtils.logger(NacosConfigListener.class);
    @Autowired
    private NacosConfigProperties configs;
    @Value("${spring.cloud.nacos.config.server-addr:}")
    private String serverAddr;
    @Value("${spring.cloud.nacos.config.namespace:}")
    private String namespace;
    @Autowired
    private ApplicationContext applicationContext;
    /**
     * 目前只考慮properties 文件
     */
    private String fileType = "properties";
    /**
     * 需要在配置文件中增加一條 MODULE_NAME 的配置,用於找到對應的 常量類
     */
    private String MODULE_NAME = "MODULE_NAME";

    /**
     * NACOS監聽方法
     *
     * @throws NacosException
     */
    public void listener() throws NacosException {
        if (StringUtils.isBlank(serverAddr)) {
            LOGGER.info("未找到 spring.cloud.nacos.config.server-addr");
            return;
        }
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr.split(":")[0]);
        if (StringUtils.isNotBlank(namespace)) {
            properties.put(PropertyKeyConst.NAMESPACE, namespace);
        }

        ConfigService configService = NacosFactory.createConfigService(properties);
        // 處理每個配置文件
        for (NacosConfigProperties.Config config : configs.getExtConfig()) {
            String dataId = config.getDataId();
            String group = config.getGroup();
            //目前只考慮properties 文件
            if (!dataId.endsWith(fileType)) continue;

            changeValue(configService.getConfig(dataId, group, 5000));

            configService.addListener(dataId, group, new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    changeValue(configInfo);
                }

                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        }
    }

    /**
     * 改變 常量類的 值
     *
     * @param configInfo
     */
    private void changeValue(String configInfo) {
        if(StringUtils.isBlank(configInfo)) return;
        Properties proper = new Properties();
        try {
            proper.load(new StringReader(configInfo)); //把字符串轉為reader
        } catch (IOException e) {
            e.printStackTrace();
        }
        String moduleName = "";
        Enumeration enumeration = proper.propertyNames();
        //尋找MODULE_NAME的值
        while (enumeration.hasMoreElements()) {
            String strKey = (String) enumeration.nextElement();
            if (MODULE_NAME.equals(strKey)) {
                moduleName = proper.getProperty(strKey);
                break;
            }
        }
        if (StringUtils.isBlank(moduleName)) return;
        Class curClazz = null;
        // 尋找配置文件對應的常量類
        // 從spring容器中 尋找類的註解有ConfigModule 且值是 MODULE_NAME對應的
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            Class clazz = applicationContext.getBean(beanName).getClass();
            ConfigModule configModule = (ConfigModule) clazz.getAnnotation(ConfigModule.class);
            if (configModule != null && moduleName.equals(configModule.value())) {
                curClazz = clazz;
                break;
            }
        }
        if (curClazz == null) return;
        // 使用JAVA反射機制 更改常量
        enumeration = proper.propertyNames();
        while (enumeration.hasMoreElements()) {
            String key = (String) enumeration.nextElement();
            String value = proper.getProperty(key);
            if (MODULE_NAME.equals(key)) continue;
            try {
                Field field = curClazz.getDeclaredField(key);
                //忽略屬性的訪問權限
                field.setAccessible(true);
                Class<?> curFieldType = field.getType();
                //其他類型自行拓展
                if (curFieldType.equals(String.class)) {
                    field.set(null, value);
                } else if (curFieldType.equals(List.class)) { // 集合List元素
                    field.set(null, JSONUtils.parse(value));
                } else if (curFieldType.equals(Map.class)) { //Map
                    field.set(null, JSONUtils.parse(value));
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                LOGGER.info("設置屬性失敗:{} {} = {} ", curClazz.toString(), key, value);
            }
        }
    }

    @PostConstruct
    public void init() throws NacosException {
        listener();
    }
}

 3.測試

1)新建常量類Constant,增加註解@ConfigModule(“sm”),盡量測試全面, 添加常量類型有 String, List,Map

@ConfigModule("sm")
public class Constant {

    public static volatile String TEST = new String("test");

    public static volatile List<String> TEST_LIST = new ArrayList<>();
    static {
        TEST_LIST.add("默認值");
    }
    public static volatile Map<String,Object> TEST_MAP = new HashMap<>();
    static {
        TEST_MAP.put("KEY","初始化默認值");
    }
    public static volatile List<Integer> TEST_LIST_INT = new ArrayList<>();
    static {
        TEST_LIST_INT.add(1);
    }
}

2)新建個Controller用於測試這些值

@RestController
public class TestController {

    @GetMapping("/t1")
    public Map<String, Object> test1() {
        Map<String, Object> result = new HashMap<>();

        result.put("string" , Constant.TEST);
        result.put("list" , Constant.TEST_LIST);
        result.put("map" , Constant.TEST_MAP);
        result.put("list_int" , Constant.TEST_LIST_INT);
        result.put("code" , 1);
        return result;
    }
}

3)當前nacos的配置文件cloud-sm-constant.properties為空

 4)訪問測試路徑localhost:9010/sm/t1,返回為默認值

{
    "code": 1,
    "string": "test",
    "list_int": [
        1
    ],
    "list": [
        "默認值"
    ],
    "map": {
        "KEY": "初始化默認值"
    }
}

5)然後更改nacos的配置文件cloud-sm-constant.properties;

 6)再次訪問測試路徑localhost:9010/sm/t1,返回為nacos中的值

{
    "code": 1,
    "string": "12351",
    "list_int": [
        1,
        23,
        4
    ],
    "list": [
        "123",
        "sss"
    ],
    "map": {
        "A": 12,
        "B": 432
    }
}

4.結語

這種實現方式優點如下:

1)動態刷新配置,不需要重啟即可改變程序中的靜態常量值

2)使用簡單,只需在常量類上添加一個註解

3)避免在程序中大量使用@Value,@RefreshScope註解

 不足:

此代碼是個人業餘時間的想法,未經過生產驗證,實現的數據類型暫時只寫幾個,其餘的需要自行拓展

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

如何只用5分鐘完成數據 列表、創建頁面

前言

我們當然希望能夠更快的完成我們的工作,這樣我們才能有更多的時間做其他的事情,比如說測試、學習、放鬆。

背景

軟件一般也就這麼幾個方面的工作要做,增、刪、改、查。如果歸結到頁面上來說,那麼無非也就這麼幾個頁面Form頁面(增)、列表頁面(查、刪)、編輯頁面(改)。很大程度上,你的項目就是由不同的實體的這麼幾個頁面組裝起來的。既然他們都是這麼幾個頁面,那麼,我們是不是可以考慮針對這幾個頁面進行抽象呢?然後使用數據描述這幾個頁面的行為。

效果

經典倒敘,先上效果圖

列表頁面

創建頁面

目前就簡單實現了列表頁面和創建頁面。編輯頁面,跟創建頁面太像了。暫時還沒有實現相關內容,不過,這個不是很重要了。

實現過程

需求分析

其實,每個頁面都是存在固定的路數的。

比如說:

列表頁面裡邊主要存在這麼幾個參數:列表名、列表頭上的按鈕、列表的表頭、列表內容、列表每一行中的操作、分頁控件。

表單頁面列表主要存在這麼幾個參數:表單名、表單內容項。

主要的參數出現的位置都是固定的。但是什麼地方出現什麼內容則是可以變化的,一般情況下,我們都是通過代碼,一遍一遍的重寫這些頁面,然後來達到不同的應用之間的變化的目的。其實我們是可以通過數據來描述他們的。比如說向下面這樣。

列表頁面的定義

Form表單頁面的定義

原始數據的定義

然後將這些定義好的屬性通過後端渲染到頁面上。

就可以達到,前邊展示的這種效果了。

數據存儲

因為數據類型是自定義的,所以數據存儲的字段也是可以自己隨便預設的。然後系統就可以直接支持這一數據類型。在這個Demo裡邊,我是簡單粗暴的使用了文件存儲Json文件的方式來進行保存的數據。

其實應該鏈接數據庫的。不過我在Demo項目裡邊留下了相關的接口,只要再實現一個數據庫版本的實例就可以無縫對接了。

其實

當然了這隻是他的最初級的形態,因為現在寫的配置文件都是通過手寫來實現,將來可以做一個編輯器。並且可以實時看到調整過的效果。

其實這個做法,是來源於PaaS項目中的一個很小很小的功能塊。真正的PaaS項目這一整套東西都是在線上直接編輯看效果的。

最後

系列

這個項目將來會融入到我寫的PaaS Demo中作為前端展示部分。 系列的目錄在 https://juejin.im/post/5eca2a186fb9a047e96b2884 這個部分會一點點完善。

開源

雖然東西不大,但是還是希望能給你一點點啟發。 項目地址 https://gitee.com/anxin1225/Dov.GenericWeb

簡單的體驗

部署到雲端了,可以簡單體驗一下。

http://gw.ash50p.com/Generic/Meeting.Record/List

轉載莫忘原文地址:https://juejin.im/post/5eeb85b8e51d45740850f755

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

【其他文章推薦】

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

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

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

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

Netty中的這些知識點,你需要知道!

一、Channel

Channel是一個接口,而且是一個很大的接口,我們稱之為“大而全”,囊括了server端及client端接口所需要的接口。

Channel是一個門面,封裝了包括網絡I/O及相關的所有操作。

Channel聚合了包括網絡讀寫、鏈路管理、網絡連接信息、獲取EventLoop、Pipeline等相關功能類;統一分配,調度實現相應場景的功能。

一個Channel 對應一個物理連接,是基於物理連接上的操作包裝。

二、EventLoop

EventLoop,Event意為事件、Loop意為環,EventLoo即為事件環

EventLoop是一種程序設計結構等待以及分發事件。

NioEventLoop,是一個Netty工作線程,又不僅僅是一個Netty工作線程。

標準的netty線程模型 中我們講過Netty的標準線程池模型,池子里的每個線程對象就是一個NioEventLoop對象。或負責接受連接,或負責網絡I/O

說它不僅僅是一個Netty線程,因為它實現了很多功能,我們可以看下它的繼承圖:

它的上方有兩個枝丫,一個線程屬性,一個EventLoop,它是Netty的Reactor線程

既然是Reactor線程,那麼首先我們需要一個多路復用器。在Netty NioEventLoop中,包就含一個 Selector,它的操作對象是Channel。

NioEventLoop的主要邏輯在它的run()方法,方法體內是一個無限循環 for (;;),循環體內實現Loop功能。這也是通用的NIO線程實現方式。

 

Loop 從任務隊列里獲取任務,然後檢查多路復用器中就緒的Channel進行處理。

三、Unsafe

Netty中的Unsafe,一個Channel內部聚合接口,用以處理實際的網絡I/O讀寫。當然,取Unsafe命名,源碼中釋義:提供的網絡相關的操作方法,永遠不應該被開發人員操作使用。

它是Channel的一個輔助接口,主要方法:

1、register:註冊Channel

2、deregister:取消註冊

3、bind:綁定地址,服務端綁定監聽特定端口;客戶端指定本地綁定Socket地址。

4、connect:建立連接

5、disconnect:斷開連接

6、close:關閉連接

7、write:調度寫,將數據寫入buffer,並未真正進入Channel

8、flush:將緩衝區中的數據寫入Channel

四、AdaptiveRecvByteBufAllocator

動態緩衝區分配器,源碼說明:根據實時的反饋動態的增加或者減少預需的緩衝區大小。

如果一次分配的緩衝區被填滿了,則調高下一次分配的緩衝區大小。

如果連續兩次實際使用的容量低於分配的緩衝區大小特定比例,則減小下一次分配的緩衝區大小。

其它情景,保持分配大小不變。

Netty的這種“智能化”處理,可以說是相當有用的:

1、首先,實際的應用場景千差萬別,同一場景下不同時刻的緩衝區需求也是實時變化(一句話可以是一個字,也可能是1000個字),這就需要Netty動態調整緩衝分配大小以適應不同的業務場景,時刻場景

2、其次,過大的不必要的內存分配,會導致Buffer處理性能下降;過小的內存分配,則會導致頻繁的分配釋放。這都是一個優良的網絡框架不應該有的。 

3、最後,動態的調整最直接的好處就是內存的的高效使用,一定程度上做到了按需分配。 

五、ChannelPipeline

Pipeline 管道,Channel的數據流通管道,在這個管道中,可以做很多事情。

ChannelPipeline 是一種職責鏈,可以對其中流動的數據進行過濾、攔截處理,是一種插拔式的鏈路裝配器

1、ChannelPipline是一個容器

支持查詢、添加、刪除、替換等容器操作。

2、ChannelPipline支持動態的添加和刪除 Handler

ChannelPipline的這種特性給了我們相當的想象空間,例如動態的添加系統擁塞保護Handler,敏感數據過濾Handler、日誌記錄Handler、性能統計Handler等。

3、ChannelPipline 是線程安全的

ChannelPipline使用 synchronized 實現線程安全,業務線程可以併發的操作ChannelPipline。但需要注意的是,Handler是非線程安全的

六、HandlerAdapter

Adapter是一種適配器,對於用戶自定義的Handler,可以通過繼承HandlerAdapter,來規避不必要的接口實現

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

非洲豬瘟來源 陸專家疑世界盃肉品帶回病毒

摘錄自2018年9月19日中央社報導

針對非洲豬瘟傳進中國途徑,中國科學家現推斷懷疑,有可能是陸客前往俄羅斯觀看世界盃,所購買並帶回中國的肉製品帶有病毒,因未食用丟棄成為餿水,後被拿去餵養生豬引發疫情。

中國農業科學院哈爾濱獸醫研究所副研究員孫元指出,即便未通過俄羅斯世界盃這個可能管道擴散到中國,以後也會由其他路徑而來。他表示,2014年相關研究顯示中國當時確實沒有非洲豬瘟病毒,如今一個月內就在中國多地出現,蔓延之快令人警惕。

孫元也認為,蔓延原因或許跟病毒的生命力強有關。非洲豬瘟病毒耐高溫,耐pH值範圍廣,在血液、糞便和組織裡可長期存活,凍肉裡可存活數年乃至數十年,未熟肉、醃肉、泔水(餿水)、下腳料中可長時間存活。

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

【其他文章推薦】

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

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

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

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

微塑膠汙染新途徑 透過孑孓進入食物鏈

摘錄自2018年09月19日中央社報導

英國瑞丁大學(University of Reading)研究人員19日表示,蚊子幼蟲孑孓會吞食塑膠製品破裂後形成的微塑膠,被吞食的微粒中,許多會隨著孑孓的成長,轉移到成蚊體內,微塑膠可能透過蚊子和其他飛行昆蟲,從空中進入人類生態系。

同時,這也代表若有任何生物吃下這些會飛的蚊子,也會跟著吃進微小塑膠粒,而眾所周知,會捕食這類昆蟲的動物包括數種鳥類、蝙蝠和蜘蛛,這些動物又成為其他動物獵食的目標,進而在食物鏈內傳遞。

研究報告主要作者、瑞丁大學生物科學家賈拉漢(Amanda Callaghan)接受媒體訪問時談到:「這項發現的重要性是此現象可能相當普遍。我們只挑選蚊子作為樣本進行觀察,不過還有許多昆蟲活在水裡,生命週期也和孑孓一樣,會吞食水裡的東西,然後變成成蟲。」

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

分類
發燒車訊

特斯拉技術長史陶柏:未來電動車終將成汽車主流

電動車大廠特斯拉(Tesla)共同創辦人暨技術長史陶柏(JB Straubel)今(14)日在台發表演說,他指出,當年外界都不看好特斯拉,但憑著推動永續能源發展的熱情,與打造能源系統的理念,特斯拉在堅困環境裡推出了能讓所有消費者接受的電動車,並預期未來電動車最終會成為所有汽車主流。

 ( Photo Credit: Tesla )

史陶柏並指出,長期而言,希望能將太陽能的應用擴散到家庭用電;過去幾年太陽能發電的成本是現在的數百倍,不過,現在成本已經大幅下降,太陽光電的市場價格降低,而永續能源若能跟電動車等交通工具結合,未來太陽光電將會是再生能源的主力。

另外,前行政院長張善政今日在論壇研討會上詢問史陶柏,新創公司於全球推廣新產品時,各國政府應扮演什麼樣的角色?史陶柏回應,新科技在進入新市場和國家時,有時無法完全符合當地法規,政府最重要的角色,是提供公平競爭的環境。他也建議,對於能源,政府可以去檢視化石燃料的成本與替代能源的成本,並試著改變對能源的認知。

史陶柏也指出,對於電動車發展史來說,電池向來是應用時最大的問題,而特斯拉正在建造電池廠Gigafactory,該廠是全球面積最大建築之一,預計會將所有電池生產鏈整合,以降低成本,打造消費者最能接受的電動汽車。

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

【其他文章推薦】

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

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

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

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新