Путь к росту программиста
Интернет/Программист/Технологии/Обмен данными
Чтение этой статьи займет около 6 минут.
Откуда: juejin.cn/post/7301910992320479284
Стоит отметить:
традиционное письмо
public Boolean doRegisterVip(){
//1. Зарегистрируйтесь как участник.
registerVip();
//2. Присоединяйтесь к группе участников.
joinMembershipGroup();
//3. Отправка купонов
issueCoupons();
//4. Push-сообщение
sendWelcomeMsg();
}
Такой способ записи связывает все действия в методе doRegisterVip. Во-первых, эффективность выполнения низкая, во-вторых, степень связи слишком высока, и, наконец, его нелегко расширить. Так как же оптимизировать эту логику?
Введение в принцип событийно-ориентированной модели
Модель Spring, управляемая событиями, состоит из трех частей:
событие:Настраиваемый пользователемсобытиепредставлены классами и связанными атрибутами и поведениямисобытиеособенность,После Spring 4.2 нет необходимости явно наследовать класс ApplicationEvent при определении события.,Просто определите компонент напрямую,Spring автоматически перенесет событие через PayloadApplicationEvent.
Опубликовано событием:существоватьSpringСносноApplicationEventPublisherПучоксобытиепубликовать,Таким образом, контент может потребляться и обрабатываться слушателем.
событиеслушатель:ApplicationListener,Мониторинг релизов событий,Обработка последующих операций после возникновения события.
Схема следующая:
package com.example.event.config;
/**
* событиедвигатель */
public interface EventEngine {
/**
* отправлятьсобытие *
* @param event событие
*/
void publishEvent(BizEvent event);
}
package com.example.event.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import org.springframework.util.CollectionUtils;
/**
* класс реализации обработчика событий
*/
public class EventEngineImpl implements EventEngine {
/**
* Асинхронный исполнитель. Системе также необходимо определить собственный пул потоков.
*/
private Executor bizListenerExecutor;
/**
* Будет ли асинхронным, значение по умолчанию — false
*/
private boolean async;
/**
* подписчик KEY — ТЕМА, VALUES — коллекция слушателей.
*/
private Map<String, List<BizEventListener>> bizSubscribers = new HashMap<>(16);
@Override
public void publishEvent(BizEvent event) {
List<BizEventListener> listeners = bizSubscribers.get(event.getTopic());
if (CollectionUtils.isEmpty(listeners)) {
return;
}
for (BizEventListener bizEventListener : listeners) {
if (bizEventListener.decide(event)) {
//Если выполняется асинхронно, поместите его в пул потоков
if (async) {
bizListenerExecutor.execute(new EventSubscriber(bizEventListener, event));
} else {
bizEventListener.onEvent(event);
}
}
}
}
/**
* Setter method for property <tt>bizListenerExecutor</tt>.
*
* @param bizListenerExecutor value to be assigned to property bizListenerExecutor
*/
public void setBizListenerExecutor(Executor bizListenerExecutor) {
this.bizListenerExecutor = bizListenerExecutor;
}
/**
* Setter method for property <tt>bizSubscribers</tt>.
*
* @param bizSubscribers value to be assigned to property bizSubscribers
*/
public void setBizSubscribers(Map<String, List<BizEventListener>> bizSubscribers) {
this.bizSubscribers = bizSubscribers;
}
/**
* Setter method for property <tt>async</tt>.
*
* @param async value to be assigned to property async
*/
public void setAsync(boolean async) {
this.async = async;
}
}
package com.example.event.config;
import java.util.EventObject;
/**
* бизнессобытие */
public class BizEvent extends EventObject {
/**
* Topic
*/
private final String topic;
/**
* идентификатор компании
*/
private final String bizId;
/**
* данные
*/
private final Object data;
/**
* @param topic eventtopic, используется для различения типов событий
* @param bizId Идентификатор компании, идентифицирующий этот звонок
* @param data объект EventTransfer
*/
public BizEvent(String topic, String bizId, Object data) {
super(data);
this.topic = topic;
this.bizId = bizId;
this.data = data;
}
/**
* Getter method for property <tt>topic</tt>.
*
* @return property value of topic
*/
public String getTopic() {
return topic;
}
/**
* Getter method for property <tt>id</tt>.
*
* @return property value of id
*/
public String getBizId() {
return bizId;
}
/**
* Getter method for property <tt>data</tt>.
*
* @return property value of data
*/
public Object getData() {
return data;
}
}
package com.example.event.config;
/**
* Слушатель событий. Примечание. В настоящее время контекст потока отсутствует. При необходимости измените конструктор, чтобы отобразить копированную информацию о контексте.
*/
public class EventSubscriber implements Runnable {
/**
* Бизнес-слушатель
**/
private BizEventListener bizEventListener;
/**
* бизнессобытие */
private BizEvent bizEvent;
/**
* @param bizEventListener событиеслушатель * @param bizEvent событие
*/
public EventSubscriber(BizEventListener bizEventListener, BizEvent bizEvent) {
super();
this.bizEventListener = bizEventListener;
this.bizEvent = bizEvent;
}
@Override
public void run() {
bizEventListener.onEvent(bizEvent);
}
}
package com.example.event.config;
import java.util.EventListener;
/**
* Слушатель деловых мероприятий
*
*/
public interface BizEventListener extends EventListener {
/**
* Выполнять ли событие
*
* @param event событие
* @return
*/
public boolean decide(BizEvent event);
/**
* осуществлятьсобытие *
* @param event событие
*/
public void onEvent(BizEvent event);
}
package com.example.event.config;
/**
* тема механизма событий, используемая для различения типов событий
*/
public class EventEngineTopic {
/**
* Присоединяйтесь к группе участников
*/
public static final String JOIN_MEMBERSHIP_GROUP = "joinMembershipGroup";
/**
* Отправить купоны
*/
public static final String ISSUE_COUPONS = "issueCoupons";
/**
* push-сообщение
*/
public static final String SEND_WELCOME_MSG = "sendWelcomeMsg";
}
package com.example.event.listener;
import com.example.event.config.BizEvent;
import com.example.event.config.BizEventListener;
import org.springframework.stereotype.Component;
/**
* Купонный процессор
*/
@Component
public class CouponsHandlerListener implements BizEventListener {
@Override
public boolean decide(BizEvent event) {
return true;
}
@Override
public void onEvent(BizEvent event) {
System.out.println("Купонный процессор:выдан купон на скидку 10%");
}
}
package com.example.event.listener;
import com.example.event.config.BizEvent;
import com.example.event.config.BizEventListener;
import org.springframework.stereotype.Component;
/**
* Процессор группы участников
*/
@Component
public class MembershipHandlerListener implements BizEventListener {
@Override
public boolean decide(BizEvent event) {
return true;
}
@Override
public void onEvent(BizEvent event) {
System.out.println("Процессор группы участников:Вы успешно добавили Присоединяйтесь к группе участников");
}
}
package com.example.event.listener;
import com.example.event.config.BizEvent;
import com.example.event.config.BizEventListener;
import org.springframework.stereotype.Component;
/**
* Процессор push-сообщений
*/
@Component
public class MsgHandlerListener implements BizEventListener {
@Override
public boolean decide(BizEvent event) {
return true;
}
@Override
public void onEvent(BizEvent event) {
System.out.println("Процессор push-сообщений:Добро пожаловать, чтобы стать участником! ! ! ");
}
}
package com.example.event.listener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.example.event.config.BizEventListener;
import com.example.event.config.EventEngine;
import com.example.event.config.EventEngineImpl;
import com.example.event.config.EventEngineTopic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
/**
* Конфигурация движка eventDrive
*/
@Configuration
public class EventEngineConfig {
/**
* Асинхронная обработка пула потоковсобытие
*/
private static final Executor EXECUTOR = new ThreadPoolExecutor(20, 50, 10, TimeUnit.MINUTES,
new LinkedBlockingQueue(500), new CustomizableThreadFactory("EVENT_ENGINE_POOL"));
@Bean("eventEngineJob")
public EventEngine initJobEngine(CouponsHandlerListener couponsHandlerListener,
MembershipHandlerListener membershipHandlerListener,
MsgHandlerListener msgHandlerListener) {
Map<String, List<BizEventListener>> bizEvenListenerMap = new HashMap<>();
//Регистрация купона
bizEvenListenerMap.put(EventEngineTopic.ISSUE_COUPONS, Arrays.asList(couponsHandlerListener));
//Регистрируем событие группы участников
bizEvenListenerMap.put(EventEngineTopic.JOIN_MEMBERSHIP_GROUP, Arrays.asList(membershipHandlerListener));
//Регистрируемся для события push-сообщения
bizEvenListenerMap.put(EventEngineTopic.SEND_WELCOME_MSG, Arrays.asList(msgHandlerListener));
EventEngineImpl eventEngine = new EventEngineImpl();
eventEngine.setBizSubscribers(bizEvenListenerMap);
eventEngine.setAsync(true);
eventEngine.setBizListenerExecutor(EXECUTOR);
return eventEngine;
}
}
package com.example.event.controller;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import com.example.event.config.BizEvent;
import com.example.event.config.EventEngine;
import com.example.event.config.EventEngineTopic;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* тест
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Resource(name = "eventEngineJob")
private EventEngine eventEngine;
@GetMapping("/doRegisterVip")
public String doRegisterVip(@RequestParam(required = true) String userName,
@RequestParam(required = true) Integer age) {
Map<String, Object> paramMap = new HashMap<>(16);
paramMap.put("userName", userName);
paramMap.put("age", age);
//1. Зарегистрируйтесь как участник.,Здесь не реализовано
System.out.println("Успешно зарегистрирован участник");
//2. Присоединяйтесь к группе участников.
eventEngine.publishEvent(
new BizEvent(EventEngineTopic.JOIN_MEMBERSHIP_GROUP, UUID.randomUUID().toString(), paramMap));
//3. Отправка купонов
eventEngine.publishEvent(
new BizEvent(EventEngineTopic.ISSUE_COUPONS, UUID.randomUUID().toString(), paramMap));
//4. Push-сообщение
eventEngine.publishEvent(
new BizEvent(EventEngineTopic.SEND_WELCOME_MSG, UUID.randomUUID().toString(), paramMap));
return «Зарегистрирован успешно»;
}
}
http://localhost:8080/test/doRegisterVip?userName=zhangsan&age=28
<END>
Содержимое включает основы Java.、JavaWeb、Оптимизация производительности MySQL、JVM、Замок、Миллионы одновременных、очередь сообщений、Высокопроизводительное кэширование、отражение、Принцип пружинного семейного ведра、микросервисы、Zookeeper... и другие технологические стеки!