5 changed files with 256 additions and 0 deletions
-
12src/main/java/com/iflytop/colortitration/app/common/annotation/CommandDebugMapping.java
-
67src/main/java/com/iflytop/colortitration/app/controller/CmdController.java
-
67src/main/java/com/iflytop/colortitration/app/controller/CmdDebugController.java
-
55src/main/java/com/iflytop/colortitration/app/core/command/CommandDebugHandlerRegistry.java
-
55src/main/java/com/iflytop/colortitration/app/core/command/CommandHandlerRegistry.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(); |
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue