当前位置: 首页 > 知识库问答 >
问题:

在Spring websockets中发送错误消息

海宁
2023-03-14
@MessageExceptionHandler
@SendToUser(value = "/queue/error",broadcast = false)
public ApplicationError handleException(Exception message) throws ApplicationError {
        return  new ApplicationError("test");
}

我订阅了

stompClient.subscribe('/user/queue/error', stompErrorCallback, {token: accessToken});

在我的例子中,用户没有通过身份验证,但从这里

虽然用户目标通常意味着一个经过身份验证的用户,但它并不是严格要求的。不与经过身份验证的用户关联的WebSocket会话可以订阅用户目的地。在这种情况下,@sendtouser注释的行为与broadcast=false完全相同,即只针对发送正在处理的消息的会话。

public class ClientInboundChannelInterceptor extends ChannelInterceptorAdapter {
    @Autowired
    @Lazy(value = true)
    @Qualifier("brokerMessagingTemplate")
    private SimpMessagingTemplate simpMessagingTemplate;

    @Override
    public Message<?> preSend(Message message, MessageChannel channel) throws IllegalArgumentException{
         if(some thing goes wrong)
           throw new RuntimeException();
    }

    @MessageExceptionHandler
    @SendToUser(value = "/queue/error",broadcast = false)
    public ApplicationError handleException(RuntimeException message) throws    ApplicationError {
        return  new ApplicationError("test");
    }
}

@MessageExceptionHandler未捕获此异常。所以我尝试使用SimpMessagingTemplate直接将其发送给用户。

我基本上想做的是:

simpMessagingTemplate.convertAndSendToUser(SOMETHING,"/queue/error",e);

某些内容应该是正确的用户名,但在我的情况下,用户没有经过身份验证,因此我不能使用HeaderAccessor.getUser().getName()

我甚至试过

simpMessagingTemplate.convertAndSendToUser(headerAccessor.getHeader("","/queue/error",e, Collections.singletonMap(SimpMessageHeaderAccessor.SESSION_ID_HEADER, headerAccessor.getSessionId()));

但这不起作用。

我甚至尝试过headeraccessor.getSessionID()来代替username,但这似乎不起作用。

共有1个答案

麻烨
2023-03-14

我最初的直觉是正确的,在未经身份验证的用户情况下使用sessionId作为用户名,但问题出在头上。

通过@SendtouserSimpMessagingTemplate.ConvertandSendtouser()调试了几个小时后,我意识到如果我们使用@Sendtouser标头将自动设置,如果我们使用的是SimpMessagingTemplate.ConvertandSendtouser()则必须显式定义标头。

@sendtouser正在设置两个标头,

SimpMessageType:SimpMessageType.Message,SimpSessionID:SessionID

所以我尝试添加标题,

String sessionId = headerAccessor.getSessionId();
Map<String,Object> headerMap = new HashMap<>();
headerMap.put("simpMessageType", SimpMessageType.MESSAGE);
headerMap.put("simpSessionId",sessionId);   
simpMessagingTemplate.convertAndSendToUser(headerAccessor.getSessionId(),"/queue/error",e,headerMap);
String sessionId = headerAccessor.getSessionId();
Map<String,Object> headerMap = new HashMap<>();
headerMap.put("simpMessageType", SimpMessageType.MESSAGE);
headerMap.put("simpSessionId",sessionId); 
MessageHeaders headers = new MessageHeaders(headerMap);

simpMessagingTemplate.convertAndSendToUser(headerAccessor.getSessionId(),"/queue/error",e,headers);

经过更多的调试,我找到了设置头的正确方法,这可能是创建这些头的唯一方法(从SendtoMethodReturnValueHandler.java)。

private MessageHeaders createHeaders(String sessionId) {
    SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
    headerAccessor.setSessionId(sessionId);
    headerAccessor.setLeaveMutable(true);
    return headerAccessor.getMessageHeaders();
}

所以最后,

String sessionId = headerAccessor.getSessionId();
template.convertAndSendToUser(sessionId,"/queue/error","tesssssts",createHeaders(sessionId));

成功了。

 类似资料:
  • 我正在使用postman查看Twilio中发送消息api的响应格式。我使用的Api是https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Messages。我已经输入了基本的身份验证参数(帐户\u Sid和AuthToken作为用户名和密码),json请求格式为 但我得到的错误是21603,上面写着“需要一个‘发件人’电话号码”。你能告诉我

  • 问题内容: 我有两个servlet:第一个servlet与客户端相似,并创建了一个以调用第二个servlet。 我想发送一个特殊的错误,格式类似于JSON对象,因此我以这种方式调用sendError方法: 但是在第一个servlet中,当我读取方法错误时,我只是得到标准的HTTP消息,而不是作为字符串的json对象。 如何获取json字符串? 问题答案: 从javadoc: 服务器默认创建响应,使

  • 我在使用discord机器人添加此发送消息时遇到了一个奇怪的错误。我在学习Scratch教程 结果:- `(节点:8480)未经处理的PromisejectionWarning:DiscordAPIError:在C:\Users\Deepanshu\node\u modules\discord处缺少访问权限。js\src\client\rest\RequestHandlers\Sequential

  • 我正在使用spring-cloud-stream:1.3.0.发行版、spring-cloud-stream-binder-kafka:1.3.0.发行版开发spring引导应用程序。我使用spring integration dsl拆分文件中的行,使用beanio将行转换为json,要求将成功的json消息写入一个kafka主题,并将错误消息写入不同的kafka主题。下面是application

  • 我正在尝试使用HDFS kafka连接器将protobuf消息从kafka发送到HDFS。我的连接器配置如下所示 为了测试这一点,我尝试在一个小节点应用程序中发送protobuf序列化消息。这是我的文件: 和我的节点应用程序 但是,当我运行此程序时,我会出现以下错误: 我该如何解决这个问题?我的猜测是,我的protobuf模式没有在Kafka模式注册表中注册,但我不确定。如果是这种情况,是否有方法

  • 所以我想做一个机器人,通过命令为我快速计算。我的前缀是,命令是payment。例如,当我尝试命令时,每次都会出现相同的错误。我正在使用node btw。 我曾尝试将wait-before-send函数和async放在所有返回函数之前,但我得到了相同的错误。 以下是我不断发现的错误: 节点:18876)未处理的PromisejectionWarning:DiscordAPIError:无法在项处发送