[Spring cloud 一步步實現廣告系統] 17. 根據流量類型查詢廣告

来源:https://www.cnblogs.com/zhangpan1244/archive/2019/08/12/11343026.html
-Advertisement-
Play Games

廣告檢索服務 功能介紹 媒體方(手機APP打開的展示廣告,走在路上看到的大屏幕廣告等等) 請求數據對象實現 從上圖我們可以看出,在媒體方向我們的廣告檢索系統發起請求的時候,請求中會有很多的請求參數信息,他們分為了三個部分,我們來編碼封裝這幾個參數對象信息以及我們請求本身的信息。Let's code. ...


廣告檢索服務

功能介紹

媒體方(手機APP打開的展示廣告,走在路上看到的大屏幕廣告等等)

請求數據對象實現

從上圖我們可以看出,在媒體方向我們的廣告檢索系統發起請求的時候,請求中會有很多的請求參數信息,他們分為了三個部分,我們來編碼封裝這幾個參數對象信息以及我們請求本身的信息。Let's code.

  • 創建廣告檢索請求介面

/**
 * ISearch for 請求介面,
 * 根據廣告請求對象,獲取廣告響應信息
 *
 * @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a>
 */
@FunctionalInterface
public interface ISearch {

    /**
     * 根據請求返回廣告結果
     */
    SearchResponse fetchAds(SearchRequest request);
}
  • 創建SearchRequest,包含三部分:mediaId,RequestInfo,FeatureInfo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchRequest {

    //媒體方請求標示
    private String mediaId;
    //請求基本信息
    private RequestInfo requestInfo;
    //匹配信息
    private FeatureInfo featureInfo;


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class RequestInfo {
        private String requestId;

        private List<AdSlot> adSlots;
        private App app;
        private Geo geo;
        private Device device;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class FeatureInfo {

        private KeywordFeature keywordFeature;
        private DistrictFeature districtFeature;
        private HobbyFeatrue hobbyFeatrue;

        private FeatureRelation relation = FeatureRelation.AND;
    }
}

其他的對象大家可以去github傳送門 & gitee傳送門 下載源碼。

UTOOLS1565403569539.png

檢索響應對象定義
/**
 * SearchResponse for 檢索API響應對象
 *
 * @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a>
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchResponse {

    //一個廣告位,可以展示多個廣告
    //Map key為廣告位 AdSlot#adSlotCode
    public Map<String, List<Creative>> adSlotRelationAds = new HashMap<>();

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Creative {

        private Long adId;
        private String adUrl;
        private Integer width;
        private Integer height;
        private Integer type;
        private Integer materialType;

        //展示監控url
        private List<String> showMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn");
        //點擊監控url
        private List<String> clickMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn");
    }

    /**
     * 我們的檢索服務針對的是記憶體中的索引檢索,那麼我們就需要一個轉換方法
     */
    public static Creative convert(CreativeIndexObject object) {
        
        return Creative.builder()
                       .adId(object.getAdId())
                       .adUrl(object.getAdUrl())
                       .width(object.getWidth())
                       .height(object.getHeight())
                       .type(object.getType())
                       .materialType(object.getMaterialType())
                       .build();
    }
}
根據流量類型廣告過濾

流量類型本身屬於推廣單元下的類目,有很多種類貼片廣告,開屏廣告等等,這些類型需要同步到媒體方,媒體方會根據不同的流量類型發起不同的廣告請求,我們需要先定義一個流量類型的信息類。

public class AdUnitConstants {
    public static class PositionType{
        //App啟動時展示的、展示時間短暫的全屏化廣告形式。
        private static final int KAIPING = 1;
        //電影開始之前的廣告
        private static final int TIEPIAN = 2;
        //電影播放中途廣告
        private static final int TIEPIAN_MIDDLE = 4;
        //暫停視頻時候播放的廣告
        private static final int TIEPIAN_PAUSE = 8;
        //視頻播放完
        private static final int TIEPIAN_POST = 16;
    }
}

從上述類型的數字,我們可以看出是2的倍數,這是為了使用位運算提升性能。

com.sxzhongf.ad.index.adunit.AdUnitIndexObject中,我們添加類型校驗方法:

public static boolean isAdSlotType(int adSlotType, int positionType) {
        switch (adSlotType) {
            case AdUnitConstants.PositionType.KAIPING:
                return isKaiPing(positionType);
            case AdUnitConstants.PositionType.TIEPIAN:
                return isTiePian(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_MIDDLE:
                return isTiePianMiddle(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_PAUSE:
                return isTiePianPause(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_POST:
                return isTiePianPost(positionType);
            default:
                return false;
        }
    }

    /**
     * 與運算,低位取等,高位補零。
     * 如果 > 0,則為開屏
     */
    private static boolean isKaiPing(int positionType) {
        return (positionType & AdUnitConstants.PositionType.KAIPING) > 0;
    }
    private static boolean isTiePianMiddle(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_MIDDLE) > 0;
    }

    private static boolean isTiePianPause(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_PAUSE) > 0;
    }

    private static boolean isTiePianPost(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_POST) > 0;
    }

    private static boolean isTiePian(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN) > 0;
    }

無所如何,我們都是需要根據positionType進行數據查詢過濾,我們在之前的com.sxzhongf.ad.index.adunit.AdUnitIndexAwareImpl中添加2個方法來實現過濾:

/**
     * 過濾當前是否存在滿足positionType的UnitIds
     */
    public Set<Long> match(Integer positionType) {
        Set<Long> adUnitIds = new HashSet<>();
        objectMap.forEach((k, v) -> {
            if (AdUnitIndexObject.isAdSlotType(positionType, v.getPositionType())) {
                adUnitIds.add(k);
            }
        });
        return adUnitIds;
    }

    /**
     * 根據UnitIds查詢AdUnit list
     */
    public List<AdUnitIndexObject> fetch(Collection<Long> adUnitIds) {
        if (CollectionUtils.isEmpty(adUnitIds)) {
            return Collections.EMPTY_LIST;
        }
        List<AdUnitIndexObject> result = new ArrayList<>();
        adUnitIds.forEach(id -> {
            AdUnitIndexObject object = get(id);
            if (null == object) {
                log.error("AdUnitIndexObject does not found:{}", id);
                return;
            }
            result.add(object);
        });

        return result;
    }
  • 實現Search服務介面

上述我們準備了一系列的查詢方法,都是為了根據流量類型查詢廣告單元信息,我們現在開始實現我們的查詢介面,查詢介面中,我們可以獲取到媒體方的請求對象信息,它帶有一系列查詢所需要的過濾參數:

/**
 * SearchImpl for 實現search 服務
 *
 * @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a>
 */
@Service
@Slf4j
public class SearchImpl implements ISearch {
    @Override
    public SearchResponse fetchAds(SearchRequest request) {

        //獲取請求廣告位信息
        List<AdSlot> adSlotList = request.getRequestInfo().getAdSlots();

        //獲取三個Feature信息
        KeywordFeature keywordFeature = request.getFeatureInfo().getKeywordFeature();
        HobbyFeatrue hobbyFeatrue = request.getFeatureInfo().getHobbyFeatrue();
        DistrictFeature districtFeature = request.getFeatureInfo().getDistrictFeature();
        //Feature關係
        FeatureRelation featureRelation = request.getFeatureInfo().getRelation();


        //構造響應對象
        SearchResponse response = new SearchResponse();
        Map<String, List<SearchResponse.Creative>> adSlotRelationAds = response.getAdSlotRelationAds();

        for (AdSlot adSlot : adSlotList) {
            Set<Long> targetUnitIdSet;
            //根據流量類型從緩存中獲取 初始 廣告信息
            Set<Long> adUnitIdSet = IndexDataTableUtils.of(
                    AdUnitIndexAwareImpl.class
            ).match(adSlot.getPositionType());
        }
        return null;
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 零基礎學python,python視頻教程 這是我收集到的互聯網上的視頻資源,所有內容均來自互聯網。僅供學習使用。 目前我在也在學習過程中,會把學習過程中遇到問題以及解決問題的方式,總結到我的公眾號【趣學程式】裡面。 偶爾會發表幾篇文章,供給大家學習使用。茫茫人海之中,只為交個朋友。還請多多多指教小 ...
  • 最近整理ssm,寫完demo案例,無論如何都訪問不了後臺,百度了好多,終於解決了問題所在 先看頁面信息: 因為一直報404錯誤,一直找路徑是不是弄錯了,或配置文件弄錯了,僅僅這個配置文件都看了無數遍,然而並沒有發現問題,後來百度這個描述才發現了問題The origin server did not ...
  • 這是一篇修改class文件的文章。註釋並不完全,要抓住這次練習的目的: boolean在虛擬機中是以何種方式解讀的 好的,開始我的表演 1.安裝asmtools.jar(本文尾部有步驟) 2.編寫一個java文件,並編譯,執行 2.1 Foo.java 1 public class Foo { 2 ...
  • 本文將通過for ... in ...的語法結構,遍歷字元串、列表、元組、字典等數據結構。 字元串遍歷 列表遍歷 元組遍歷 字典遍歷 1. 遍歷字典的key(鍵) 2. 遍歷字典的value(值) 3. 遍歷字典的項(元素) 重點:帶下標索引的遍歷 正常情況我們是這樣的 升級版使用 enumerat ...
  • 介紹 Eratosthenes篩法,又名埃氏篩法,對於求1~n區間內的素數,時間複雜度為n log n,對於10^6^ 以內的數比較合適,再超出此範圍的就不建議用該方法了。 篩法的思想特別簡單: 對於不超過n的每個非負整數p, 刪除2p, 3p, 4p,…, 當處理完所有數之後, 還沒有被刪除的就是 ...
  • 本文目錄 一、JPA介紹二、Spring Data JPA類結構圖1、類的結構關係圖三、代碼實現1、添加對應的Starter2、添加連接資料庫的配置3、主要代碼 一、JPA介紹 JPA是Java Persistence API的簡稱,中文名Java持久層API,是JDK 5.0註解或XML描述對象- ...
  • GitHub登錄 分析登錄頁面 開發者工具分析請求 從session請求分析得知: 1.請求的URL為:https://github.com/session 2.該請求為post請求,即需要上傳data表單,所以我們需要分析form-data 由form-data分析得知: 1.login:GitH ...
  • 伺服器數量過多,每次採用ip+埠 輸入密碼的方式登錄比較繁瑣,就採用了免密碼和埠登錄。 普通登錄方式: ssh p 27479 [email protected] 更換免密碼登錄: 本地操作: 本地的公鑰位置: ~/.ssh/id_rsa.pub ~/.ssh目錄下創建一個config文件, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...