Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.sdn.api.event.MessageEvent Maven / Gradle / Ivy
package org.sdn.api.event;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.sdn.api.DefaultOpenClient;
import org.sdn.api.OpenApiException;
import org.sdn.api.domain.OpenClientDO;
import org.sdn.api.request.SubscribeEventRequest;
import org.sdn.api.response.SubscribeEventResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.*;
/**
* User: humucai
* Date: 2018/11/27
* Time: 18:28
*/
public class MessageEvent implements BeanPostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(MessageEvent.class);
private Object instance;
private Method method;
private static Map executors = new HashMap<>();
private static Map> groups = new HashMap<>();
private static boolean isInit = false;
private static MessageEvent defaultExecutor;
private static Listener listener;
private MessageEvent(Object instance, Method method) {
this.instance = instance;
this.method = method;
}
public MessageEvent() {
}
public synchronized static void start(DefaultOpenClient client, String accessToken) throws OpenApiException {
if (isInit) {
return;
}
isInit = true;
subscribeEvent(client, accessToken);
startEventListener();
}
// 订阅事件
private static void subscribeEvent(DefaultOpenClient client, String accessToken) throws OpenApiException {
OpenClientDO openClientDO = client.getOpenClientDO();
String authEvent = openClientDO.getAuthEvent();
if (isNullOrEmpty(authEvent) || isNullOrEmpty(accessToken)) {
return;
}
try {
JSONObject o = JSON.parseObject(authEvent);
List> ps = new ArrayList<>();
String groupId = openClientDO.getAppSecret();
for (String key : o.keySet()) {
JSONObject ob = o.getJSONObject(key);
JSONObject condition = ob.getJSONObject("condition");
String server = condition.getString("server");
String username = condition.getString("username");
String password = condition.getString("password");
Conn conn = new Conn(server, groupId, username, password);
if (!groups.containsKey(conn)) {
List topics = new ArrayList<>();
topics.add(key);
groups.put(conn, topics);
} else {
groups.get(conn).add(key);
}
String event = ob.getString("event");
if (event != null) {
JSONArray sub = condition.getJSONArray("sub");
sub.forEach((x) -> {
Map param = new HashMap<>();
try {
param.put("servicename", key);
JSONObject simpleObj = (JSONObject) x;
simpleObj.forEach((k, v) -> {
if (v instanceof JSONArray) {
ArrayList> eventList = new ArrayList();
((JSONArray) v).forEach((obj) -> {
HashMap m = new HashMap();
((JSONObject) obj).forEach((sk, sv) -> {
String s;
if (sv instanceof JSONObject){
s = ((JSONObject) sv).toJSONString();
}else {
s = sv.toString();
}
m.put(sk, s);
});
eventList.add(m);
});
param.put(k, eventList);
} else {
param.put(k, v.toString());
}
});
} catch (Exception e) {
LOG.warn("parse error : {}", authEvent);
}
ps.add(param);
});
}
}
for (Map p : ps) {
SubscribeEventRequest request = new SubscribeEventRequest(p);
SubscribeEventResponse response = client.defaultExecute(request, accessToken);
if (response.isSuccess()) {
if (!response.isOk()) {
throw new OpenApiException("subscribe event error");
}
}
}
} catch (Exception e) {
throw new OpenApiException("subscribe event error", e);
}
}
private static void startEventListener() {
groups.forEach((conn, topics) -> new Thread(new EventConsumerRunner(conn, topics)).start());
}
public static void setListener(Listener l) {
listener = l;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
for (Method m : methods) {
EventListener eventListener = AnnotationUtils.findAnnotation(m, EventListener.class);
if (eventListener == null) {
continue;
}
String v = eventListener.value();
String stringType = "java.lang.String";
Class>[] parameterTypes = m.getParameterTypes();
if (isNullOrEmpty(v)) {
if (parameterTypes.length > 1 &&
Objects.equals(parameterTypes[0].getName(), stringType) &&
Objects.equals(parameterTypes[1].getName(), stringType)) {
defaultExecutor = new MessageEvent(bean, m);
}
} else {
if (parameterTypes.length < 1 ||
!Objects.equals(parameterTypes[0].getName(), stringType)) {
continue;
}
if (!isNullOrEmpty(v)) {
executors.put(v, new MessageEvent(bean, m));
}
}
}
return bean;
}
private static boolean isNullOrEmpty(String s) {
return s == null || s.trim().equals("");
}
private static class Conn {
String servers;
String groupId;
String username;
String password;
Conn(String servers, String groupId, String username, String password) {
this.servers = org.sdn.api.utils.StringUtils.parseServers(servers);
this.groupId = groupId;
this.username = username;
this.password = password;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Conn conn = (Conn) o;
return Objects.equals(servers, conn.servers) &&
Objects.equals(groupId, conn.groupId) &&
Objects.equals(username, conn.username) &&
Objects.equals(password, conn.password);
}
@Override
public int hashCode() {
return Objects.hash(servers, groupId, username, password);
}
}
private static class EventConsumerRunner implements Runnable {
private Conn conn;
private List topics;
EventConsumerRunner(Conn conn, List topics) {
this.conn = conn;
this.topics = topics;
}
@Override
public void run() {
String jaasTemplate = "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"%s\" password=\"%s\";";
String jaasCfg = String.format(jaasTemplate, conn.username, conn.password);
Properties props = new Properties();
props.put("bootstrap.servers", conn.servers);
props.put("group.id", conn.groupId);
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.mechanism", "PLAIN");
props.put("sasl.jaas.config", jaasCfg);
try(KafkaConsumer consumer = new KafkaConsumer<>(props)) {
consumer.subscribe(new ArrayList<>(topics));
// fix sleeptime to avoid to busy cpu usage;
long sleepTime = 1L;
while (true) {
ConsumerRecords records = consumer.poll(Duration.ofMillis(sleepTime));
if(records.isEmpty()){
sleepTime = 1000L;
}else{
sleepTime = 1L;
}
for (ConsumerRecord record : records) {
String topic = record.topic();
if (listener != null) {
listener.handle(record.value(), topic);
}
MessageEvent event = executors.get(topic);
if (event == null) {
if (defaultExecutor != null) {
invoke(defaultExecutor.instance, defaultExecutor.method, record.value(), topic);
} else if (listener == null) {
LOG.warn("no `{}` event handler defined", topic);
}
continue;
}
invoke(event.instance, event.method, record.value());
}
}
}
}
private void invoke(Object instance, Method method, Object... param) {
try {
method.invoke(instance, param);
} catch (IllegalAccessException | InvocationTargetException e) {
// ignore error
LOG.warn("Event process error, ", e);
}
}
}
}