Browse Source

feat:增加指令接口

master
白凤吉 2 weeks ago
parent
commit
4d88c03610
  1. 12
      src/main/java/com/iflytop/colortitration/app/common/annotation/CommandDebugMapping.java
  2. 67
      src/main/java/com/iflytop/colortitration/app/controller/CmdController.java
  3. 67
      src/main/java/com/iflytop/colortitration/app/controller/CmdDebugController.java
  4. 55
      src/main/java/com/iflytop/colortitration/app/core/command/CommandDebugHandlerRegistry.java
  5. 55
      src/main/java/com/iflytop/colortitration/app/core/command/CommandHandlerRegistry.java

12
src/main/java/com/iflytop/colortitration/app/common/annotation/CommandDebugMapping.java

@ -0,0 +1,12 @@
package com.iflytop.colortitration.app.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CommandDebugMapping {
String value();
}

67
src/main/java/com/iflytop/colortitration/app/controller/CmdController.java

@ -0,0 +1,67 @@
package com.iflytop.colortitration.app.controller;
import cn.hutool.json.JSONUtil;
import com.iflytop.colortitration.app.common.constant.CommandStatus;
import com.iflytop.colortitration.app.core.command.CommandHandler;
import com.iflytop.colortitration.app.core.command.CommandHandlerRegistry;
import com.iflytop.colortitration.app.model.dto.CommandDTO;
import com.iflytop.colortitration.app.websocket.server.DebugGenerator;
import com.iflytop.colortitration.app.websocket.server.WebSocketSender;
import com.iflytop.colortitration.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@Tag(name = "前端业务指令")
@RestController
@RequestMapping("/api/cmd")
@RequiredArgsConstructor
@Slf4j
public class CmdController {
private final CommandHandlerRegistry registry;
private final WebSocketSender webSocketService;
@Operation(summary = "前端统一调用一个接口")
@PostMapping
public Result<?> controlMethod(@Valid @RequestBody CommandDTO commandDTO){
String commandId = commandDTO.getCommandId();
String command = commandDTO.getCommand();
try {
webSocketService.pushDebug(DebugGenerator.generateJson(commandId, command, CommandStatus.RECEIVE, "已收到业务指令请求,开始处理"));
CommandHandler commandHandler = registry.getCommandHandler(command);
if (commandHandler == null) {
webSocketService.pushDebug(DebugGenerator.generateJson(commandId, command, CommandStatus.DEVICE_ERROR, "未找到对应的业务指令"));
log.error("未找到对应的业务指令");
return Result.failed();
}
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.START, "业务指令开始执行"));
log.info("业务指令开始执行");
CompletableFuture<Void> future = commandHandler.handle(commandDTO);
future.whenComplete((v, ex) -> {
if (ex != null) {
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.FAIL, "执行业务指令发生异常", ex.getMessage()));
log.error("执行业务指令发生异常: {}", JSONUtil.toJsonStr(commandDTO), ex);
} else {
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.SUCCESS, "业务指令执行成功"));
log.info("业务指令执行成功");
}
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.FINISH, "业务指令执行结束"));
log.info("业务指令执行结束");
});
} catch (Exception e) {
log.error("执行业务指令发生异常: {}", JSONUtil.toJsonStr(commandDTO), e);
return Result.failed(e.getMessage());
}
return Result.success();
}
}

67
src/main/java/com/iflytop/colortitration/app/controller/CmdDebugController.java

@ -0,0 +1,67 @@
package com.iflytop.colortitration.app.controller;
import cn.hutool.json.JSONUtil;
import com.iflytop.colortitration.app.common.constant.CommandStatus;
import com.iflytop.colortitration.app.core.command.CommandDebugHandlerRegistry;
import com.iflytop.colortitration.app.core.command.CommandHandler;
import com.iflytop.colortitration.app.model.dto.CommandDTO;
import com.iflytop.colortitration.app.websocket.server.DebugGenerator;
import com.iflytop.colortitration.app.websocket.server.WebSocketSender;
import com.iflytop.colortitration.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@Tag(name = "前端调试指令")
@RestController
@RequestMapping("/api/debug/cmd")
@RequiredArgsConstructor
@Slf4j
public class CmdDebugController {
private final CommandDebugHandlerRegistry registry;
private final WebSocketSender webSocketService;
@Operation(summary = "前端调试指令")
@PostMapping
public Result<?> controlMethod(@Valid @RequestBody CommandDTO commandDTO) {
String commandId = commandDTO.getCommandId();
String command = commandDTO.getCommand();
try {
webSocketService.pushDebug(DebugGenerator.generateJson(commandId, command, CommandStatus.RECEIVE, "已收到调试指令请求,开始处理"));
CommandHandler commandHandler = registry.getCommandHandler(command);
if (commandHandler == null) {
webSocketService.pushDebug(DebugGenerator.generateJson(commandId, command, CommandStatus.DEVICE_ERROR, "未找到对应的调试指令"));
log.error("未找到对应的调试指令");
return Result.failed();
}
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.START, "调试指令开始执行"));
log.info("调试指令开始执行");
CompletableFuture<Void> future = commandHandler.handle(commandDTO);
future.whenComplete((v, ex) -> {
if (ex != null) {
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.FAIL, "执行调试指令发生异常", ex.getMessage()));
log.error("执行调试指令发生异常: {}", JSONUtil.toJsonStr(commandDTO), ex);
} else {
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.SUCCESS, "调试指令执行成功"));
log.info("调试指令执行成功");
}
webSocketService.pushCMDResponse(DebugGenerator.generateJson(commandId, command, CommandStatus.FINISH, "调试指令执行结束"));
log.info("调试指令执行结束");
});
} catch (Exception e) {
log.error("执行调试指令发生异常: {}", JSONUtil.toJsonStr(commandDTO), e);
return Result.failed(e.getMessage());
}
return Result.success();
}
}

55
src/main/java/com/iflytop/colortitration/app/core/command/CommandDebugHandlerRegistry.java

@ -0,0 +1,55 @@
package com.iflytop.colortitration.app.core.command;
import com.iflytop.colortitration.app.common.annotation.CommandDebugMapping;
import com.iflytop.colortitration.common.exception.AppException;
import com.iflytop.colortitration.common.result.ResultCode;
import io.micrometer.common.lang.NonNull;
import jakarta.annotation.PostConstruct;
import jakarta.validation.constraints.NotNull;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class CommandDebugHandlerRegistry implements ApplicationContextAware {
private final Map<String, CommandHandler> handlerMap = new HashMap<>();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@PostConstruct
public void init() {
Map<String, Object> beans = applicationContext.getBeansWithAnnotation(CommandDebugMapping.class);
for (Object bean : beans.values()) {
// 获取实际目标类而不是代理类
Class<?> targetClass = AopUtils.getTargetClass(bean);
CommandDebugMapping mapping = targetClass.getAnnotation(CommandDebugMapping.class);
if (mapping != null && bean instanceof CommandHandler) {
String mappingKey = mapping.value();
handlerMap.put(mappingKey, (CommandHandler) bean);
}
}
}
/**
* 通过模块名称和命令名称获取命令处理器
*
* @param commandName 命令名称
* @return 命令处理器
*/
public CommandHandler getCommandHandler(@NotNull String commandName) {
if (!handlerMap.containsKey(commandName)) {
throw new AppException(ResultCode.COMMAND_NOT_FOUND);
}
return handlerMap.get(commandName);
}
}

55
src/main/java/com/iflytop/colortitration/app/core/command/CommandHandlerRegistry.java

@ -0,0 +1,55 @@
package com.iflytop.colortitration.app.core.command;
import com.iflytop.colortitration.app.common.annotation.CommandMapping;
import com.iflytop.colortitration.common.exception.AppException;
import com.iflytop.colortitration.common.result.ResultCode;
import io.micrometer.common.lang.NonNull;
import jakarta.annotation.PostConstruct;
import jakarta.validation.constraints.NotNull;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class CommandHandlerRegistry implements ApplicationContextAware {
private final Map<String, CommandHandler> handlerMap = new HashMap<>();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@PostConstruct
public void init() {
Map<String, Object> beans = applicationContext.getBeansWithAnnotation(CommandMapping.class);
for (Object bean : beans.values()) {
// 获取实际目标类而不是代理类
Class<?> targetClass = AopUtils.getTargetClass(bean);
CommandMapping mapping = targetClass.getAnnotation(CommandMapping.class);
if (mapping != null && bean instanceof CommandHandler) {
String mappingKey = mapping.value();
handlerMap.put(mappingKey, (CommandHandler) bean);
}
}
}
/**
* 通过模块名称和命令名称获取命令处理器
*
* @param commandName 命令名称
* @return 命令处理器
*/
public CommandHandler getCommandHandler(@NotNull String commandName){
if (!handlerMap.containsKey(commandName)) {
throw new AppException(ResultCode.COMMAND_NOT_FOUND);
}
return handlerMap.get(commandName);
}
}
Loading…
Cancel
Save