使用类:
@Component
public class TaskReceiver {
@Autowired
TaskHandlerMapping mapper;
@RabbitHandler
@RabbitListener(queues = {MqTaskConstant.QUEUE_WS_CAMUNDA_EVENT_TASK} )
public void sendNotice(Message message, Channel channel) throws IOException {
if (message.getBody() == null) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
return;
}
String str = new String(message.getBody());
try {
JsonNode taskMessage = CNPCJacksonUtil.decode(str, JsonNode.class);
String eventName = taskMessage.get("eventName").asText();
//获取真正处理消息的处理者
TaskEventTypeHandler handler = mapper.getHandler(eventName);
//不同情况进行入库
if(handler != null){
handler.handleMessage(str);
}
}catch(Exception e){
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
注意:
//需要注入策略类,否则策略没办法初始化
@Autowired
TaskHandlerMapping mapper;
TaskEventTypeHandler handler = mapper.getHandler(eventName);
映射类
//映射类主要是获取到具体的策略
@Component
public class TaskHandlerMapping
{
Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
//这里注入也可以使用@AutoWired
private final TaskCreateHandler taskCreateHandler;
private final TaskAssignmentHandler taskAssignmentHandler;
public TaskHandlerMapping(TaskCreateHandler taskCreateHandler, TaskAssignmentHandler taskAssignmentHandler )
{
this.taskCreateHandler = taskCreateHandler;
this.taskAssignmentHandler = taskAssignmentHandler;
}
@PostConstruct
public void config()
{
handlerList.put(TaskConstant.CREATE, taskCreateHandler);
handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
}
public TaskEventTypeHandler getHandler(String eventName)
{
return handlerList.get(eventName);
}
}
策略接口:
@Component
public interface TaskEventTypeHandler {
void handleMessage(String message) throws Exception ;
}
具体的策略A
@Component
public class TaskCreateHandler implements TaskEventTypeHandler {
@Override
public void handleMessage(String taskMessage) throws Exception {
}
}
具体的策略B
@Component
public class TaskAssignmentHandler implements TaskEventTypeHandler {
@Override
public void handleMessage(String message) {
}
}
整体的逻辑: receiver接受到mq消息进行消费,因为消息分不同的情况:任务的指派和生成等6种情况都需要入库,并且入库的数据不同,因为给每一种写了对应的策略。
坑:
1 static代码块初始化会导致注入的策略为空。 因为static随着类的加载而加载,此时策略还没有初始化到springContext 中 . 因此下面这种写法不可取
static Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
@Autowired
private static TaskCreateHandler taskCreateHandler;
@Autowired //为空,spring没有初始化
private static TaskAssignmentHandler taskAssignmentHandler;
static {
handlerList.put(TaskConstant.CREATE, taskCreateHandler);
handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
}
2 初始化顺序 Constructor >> @Autowired >> @PostConstruct
因为上面的初始化时机的问题,使用@PostConstruct进行初始化:
@Component
public class TaskHandlerMapping
{
Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
@Autowired
private TaskCreateHandler taskCreateHandler;
@Autowired
private TaskAssignmentHandler taskAssignmentHandler;
//这样可以初始化
@PostConstruct
public void config()
{
handlerList.put(TaskConstant.CREATE, taskCreateHandler);
handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
}
//用static初始化就不行,taskCreateHandler和taskAssignmentHandler都为null,因为static初始化太早了
// static {
// handlerList.put(TaskConstant.CREATE, taskCreateHandler);
// handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
// }
public TaskEventTypeHandler getHandler(String eventName)
{
return handlerList.get(eventName);
}
}