[Spring cloud 一步步实现广告系统] 13. 索引服务编码实现

  • 时间:
  • 浏览:0

上一节让我们我们我们儿儿分析了广告索引的维护有2种,全量索引加载增量索引维护。以后广告检索是广告系统中最为重要的环节,让我们我们我们儿儿一定要认真理解让我们我们我们儿儿索引设计的思路,接下来让我们我们我们儿儿来编码实现索引维护功能。

让我们我们我们儿儿来定义另另一一两个多接口,来接收所有index的增完正查操作,接口定义另另一一两个多范型,来接收另另一一两个多参数,K代表让我们我们我们儿儿索引的健值,V代表返回值。

/**
 * IIndexAware for 实现广告索引的增完正查
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 */
public interface IIndexAware<K, V> {

    /**
     * 通过key 获取索引
     */
    V get(K key);
    /**
     * 再加索引
     * @param key
     * @param value
     */
    void add(K key, V value);
    /**
     * 更新索引
     */
    void update(K key, V value);
    /**
     * 删除索引
     */
    void delete(K key, V value);
}

让我们我们我们儿儿一定要知道,并都不 所有的数据库表都还可以创建索引,比如User表让我们我们我们儿儿在数据检索的时候真是是还可以了的,当然也就没必要创建索引,以后,也都不 表中的所有字段都还可以索引,你这些也是根据具体的业务来选择字段信息,比如让我们我们我们儿儿接下来要编写的推广计划索引中,推广计划名称就还可以不还可以了。下面,让我们我们我们儿儿来实现让我们我们我们儿儿的第另另一一两个多正向索引

  • 首先创建操作推广计划的实体对象
/**
 * AdPlanIndexObject for 推广计划索引对象
 * 你这些索引对象让我们我们我们儿儿这麼再加 推广计划名称
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdPlanIndexObject {

    private Long planId;
    private Long userId;
    private Integer planStatus;
    private Date startDate;
    private Date endDate;

    /**
    * 根据实际字段来更新索引
    */
    public void update(AdPlanIndexObject newObject) {

        if (null != newObject.getPlanId()) {
            this.planId = newObject.getPlanId();
        }
        if (null != newObject.getUserId()) {
            this.userId = newObject.getUserId();
        }
        if (null != newObject.getPlanStatus()) {
            this.planStatus = newObject.getPlanStatus();
        }
        if (null != newObject.getStartDate()) {
            this.startDate = newObject.getStartDate();
        }
        if (null != newObject.getEndDate()) {
            this.endDate = newObject.getEndDate();
        }
    }
}
  • 以后创建推广计划索引实现类,并实现IIndexAware接口。
/**
 * AdPlanIndexAwareImpl for 推广计划索引实现类
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 */
@Slf4j
@Component
public class AdPlanIndexAwareImpl implements IIndexAware<Long, AdPlanIndexObject> {

    private static Map<Long, AdPlanIndexObject> planIndexObjectMap;

    /**
     * 以后操作索引的过程蕴藏以后对索引进行更新,为了出理

多多多线程


造成的多多线程


不安全难题,让我们我们我们儿儿还可以了使用hashmap,还可以实现ConcurrentHashMap
     */
    static {
        planIndexObjectMap = new ConcurrentHashMap<>();
    }

    @Override
    public AdPlanIndexObject get(Long key) {
        return planIndexObjectMap.get(key);
    }

    @Override
    public void add(Long key, AdPlanIndexObject value) {

        log.info("AdPlanIndexAwareImpl before add::{}", planIndexObjectMap);
        planIndexObjectMap.put(key, value);
        log.info("AdPlanIndexAwareImpl after add::{}", planIndexObjectMap);
    }

    @Override
    public void update(Long key, AdPlanIndexObject value) {

        log.info("AdPlanIndexAwareImpl before update::{}", planIndexObjectMap);
                //查询当前的索引信息,以后不所处,直接新增索引信息
        AdPlanIndexObject oldObj = planIndexObjectMap.get(key);
        if (null == oldObj) {
            planIndexObjectMap.put(key, value);
        } else {
            oldObj.update(value);
        }

        log.info("AdPlanIndexAwareImpl after update::{}", planIndexObjectMap);
    }

    @Override
    public void delete(Long key, AdPlanIndexObject value) {

        log.info("AdPlanIndexAwareImpl before delete::{}", planIndexObjectMap);
        planIndexObjectMap.remove(key);
        log.info("AdPlanIndexAwareImpl after delete::{}", planIndexObjectMap);
    }
}

至此,让我们我们我们儿儿以后完成了推广计划的索引对象和索引操作的代码编写,让我们我们我们儿儿还可以参考中间的示例,依次完成推广单元推广创意地域兴趣关键词以及推广创意和推广单元的关联索引,以后可直接从 Github传送门 / Gitee传送门 下载源码。

按照上述代码展示,让我们我们我们儿儿以后实现了所有的索引操作的定义,以后实际情况汇报中,让我们我们我们儿儿还可以使用有有哪些服务的时候,还可以在每另另一一两个多Service中@Autowired注入,让我们我们我们儿儿这麼多的索引操作类,还不蕴藏后续还有以后还可以新增的索引维度,工作量真是是很多,以后不方便维护,作为另另一一两个多合格的多多线程 员来说,这是非常不友好的,你爱不爱我会让后续的开发人员骂娘。

为了出理 后续被骂,让我们我们我们儿儿来编写另另一一两个多索引缓存工具类com.sxzhongf.ad.index.IndexDataTableUtils,通过你这些索引缓存工具类来实现一次注入,出理 后顾之忧。要实现你这些工具类,让我们我们我们儿儿还可以实现另另一一两个多接口:org.springframework.context.ApplicationContextAwareorg.springframework.core.PriorityOrdered

  • org.springframework.context.ApplicationContextAware, 统一通过实现该接口的类,来操作Spring容器以及其中的Bean实例。

    在Spring中,以Aware为后缀刚始于的类,让我们我们我们儿儿还可以简单的理解为多多线程 我想要XXX,比如ApplicationContextAware代表多多线程 我想要ApplicationContext,BeanFactoryAware 表示多多线程 我想要BeanFactory...等等
  • org.springframework.core.PriorityOrdered组件加载顺序,也还可以使用org.springframework.core.Ordered

    以下代码为让我们我们我们儿儿的工具类:
package com.sxzhongf.ad.index;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * IndexDataTableUtils for 所有索引服务还可以缓存的Java Bean
 *
 * 使用法子

:
 * 获取{@link com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl}索引服务类
 * 如下:
 * {@code
 *   IndexDataTableUtils.of(CreativeIndexAwareImpl.class)
 * }
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 */
@Component
public class IndexDataTableUtils implements ApplicationContextAware, PriorityOrdered {

    //注入ApplicationContext
    private static ApplicationContext applicationContext;

    /**
     * 定义用于保存所有Index的Map
     * Class标示让我们我们我们儿儿的索引类
     */
    private static final Map<Class, Object> dataTableMap = new ConcurrentHashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        IndexDataTableUtils.applicationContext = applicationContext;
    }

    /**
     * 获取索引服务缓存
     */
    public static <T> T of(Class<T> klass) {
        T instance = (T) dataTableMap.get(klass);
        //以后获取到索引bean,直接返回当前bean
        if (null != instance) {
            return instance;
        }
        //首次获取索引bean为空,写入Map
        dataTableMap.put(klass, bean(klass));
        return (T) dataTableMap.get(klass);
    }

    /**
     * 获取Spring 容器中的Bean对象
     */
    private static <T> T bean(String beanName) {
        return (T) applicationContext.getBean(beanName);
    }

    /**
     * 获取Spring 容器中的Bean对象
     */
    private static <T> T bean(Class klass) {
        return (T) applicationContext.getBean(klass);
    }

    @Override
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE;
    }
}