[Spring cloud realizes advertising system step by step] 13. Implementation of index service coding

Posted by kashmirekat on Wed, 07 Aug 2019 17:32:41 +0200

Last section We analyze two kinds of maintenance of advertising index, full index loading and incremental index maintenance. Because advertising retrieval is the most important link in the advertising system, we must seriously understand the idea of our index design, and then we will code to achieve index maintenance function.

We define an interface to receive all index additions, deletions and modifications. The interface defines a paradigm to receive two parameters. K represents the key value of our index, and V represents the return value.

/**
 * IIndexAware for Implementing Addition, Deletion, Amendment and Examination of Advertising Index
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | Ruochuan</a>
 */
public interface IIndexAware<K, V> {

    /**
     * Get the index by key
     */
    V get(K key);
    /**
     * Adding Index
     * @param key
     * @param value
     */
    void add(K key, V value);
    /**
     * Update index
     */
    void update(K key, V value);
    /**
     * Delete index
     */
    void delete(K key, V value);
}

We must know that not all database tables need to create indexes. For example, User tables are not needed when we retrieve data. Of course, there is no need to create indexes, and not all fields in tables need indexes. This is also based on specific business to determine field information. If we want to compile the index of promotion plan next, the name of promotion plan can be unnecessary. Next, we implement our first forward index.

  • First, create the entity object of the operation promotion plan
/**
 * AdPlanIndexObject for Popularization Plan Index Objects
 * We did not add the promotion plan name to this index object.
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | Ruochuan</a>
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdPlanIndexObject {

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

    /**
    * Update the index according to the actual field
    */
    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();
        }
    }
}
  • Then we create the implementation class of the promotion plan index and implement the IIndex Aware interface.
/**
 * AdPlanIndexAwareImpl for Extension Plan Index Implementation Class
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | Ruochuan</a>
 */
@Slf4j
@Component
public class AdPlanIndexAwareImpl implements IIndexAware<Long, AdPlanIndexObject> {

    private static Map<Long, AdPlanIndexObject> planIndexObjectMap;

    /**
     * Because it is possible to update the index in the process of operating the index, in order to prevent thread insecurity caused by multithreading, we can not use hashmap, we need to implement Concurrent HashMap.
     */
    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);
                //Query the current index information. If it does not exist, add the index information directly.
        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);
    }
}

So far, we have completed the coding of the index object and index operation of the promotion plan. You can refer to the examples above to complete the related index of the promotion unit, the promotion creativity, the region, the interest, the keywords and the promotion creativity and promotion unit in turn, or you can directly from the above example. Github portal / Gitee portal Download the source code.

According to the code above, we have implemented all the definitions of index operations, but in practice, when we need to use these services, we need to inject @Autowire into each Service. So many of our index operation classes do not include the index dimensions and workload that may be added in the future. It's too big and not easy to maintain. As a qualified programmer, it's very unfriendly. Maybe it will make subsequent developers scold their mother.

In order to prevent the subsequent scolding, we will write an index caching tool class com. sxzhongf. ad. index. IndexDataTable Utils, through which we can achieve an injection to solve the worries behind. To implement this tool class, we need to implement two interfaces: org.springframework.context.ApplicationContextAware and org.springframework.core.PriorityOrdered.

  • Spring framework. context. ApplicationContextAware, unified through the implementation of the interface class, to operate the Spring container and its Bean instances.
    In Spring, classes ending with Aware can be simply understood as applications wanting XXX, such as Application Context Aware for applications wanting Application Context, BeanFactory Aware for applications wanting BeanFactory, etc.
  • The loading order of the org.springframework.core.PriorityOrdered component can also be used with the org.springframework.core.Ordered component.
    The following code is our tool class:
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 JavaBeans that need to be cached for all index services
 *
 * How to use it:
 * Get the {@link com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl} index service class
 * As follows:
 * {@code
 *   IndexDataTableUtils.of(CreativeIndexAwareImpl.class)
 * }
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | Ruochuan</a>
 */
@Component
public class IndexDataTableUtils implements ApplicationContextAware, PriorityOrdered {

    //Inject Application Context
    private static ApplicationContext applicationContext;

    /**
     * Define Map for saving all Index es
     * Class Mark our index class
     */
    private static final Map<Class, Object> dataTableMap = new ConcurrentHashMap<>();

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

    /**
     * Get the index service cache
     */
    public static <T> T of(Class<T> klass) {
        T instance = (T) dataTableMap.get(klass);
        //If you get the index bean, return the current bean directly
        if (null != instance) {
            return instance;
        }
        //Get the index bean empty for the first time and write to Map
        dataTableMap.put(klass, bean(klass));
        return (T) dataTableMap.get(klass);
    }

    /**
     * Getting Bean Objects in Spring Containers
     */
    private static <T> T bean(String beanName) {
        return (T) applicationContext.getBean(beanName);
    }

    /**
     * Getting Bean Objects in Spring Containers
     */
    private static <T> T bean(Class klass) {
        return (T) applicationContext.getBean(klass);
    }

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

Topics: Java Spring Database github