tring user, String destination, Object payload, Map<String, Object> headers,
MessagePostProcessor postProcessor) throws MessagingException {
Assert.notNull(user, "User must not be null");
user = StringUtils.replace(user, "/", "%2F");
super.convertAndSend(this.destinationPrefix + user + destination, payload, headers, postProcessor);
}
说明最后的路径依然是/user/admin/queue/chat终点.
通讯层设计 – @SubscribeMapping
@SubscribeMapping注解可以完成订阅即返回的功能。
这个很像HTTP的request-response,但不同的是HTTP的请求和响应是同步的,每次请求必须得到响应。
而@SubscribeMapping则是异步的。意思是说:当订阅时,直到回应可响应时在进行处理。
通讯层设计 – 异常处理
@MessageMapping是支持jsr 303校验的,它支持@Validated注解,可抛出错误异常,如下:
@MessageMapping("broadcast")
public String broadcast(@Payload @Validated Message message, Principal principal) {
return "发送人: " + principal.getName() + " 内容: " + message.toString();
}
那异常如何处理呢
@MessageExceptionHandler,它可以进行消息层的异常处理
@MessageExceptionHandler
@SendToUser(value = "/queue/error",broadcast = false)
public String handleException(MethodArgumentNotValidException methodArgumentNotValidException) {
BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();
if (!bindingResult.hasErrors()) {
return "未知错误";
}
List<FieldError> allErrors = bindingResult.getFieldErrors();
return "jsr 303 错误: " + allErrors.iterator().next().getDefaultMessage();
}
其中@SendToUser,是指只将消息发送给当前用户,当然,当前用户需要订阅/user/queue/error地址。
注解中broadcast,则表明消息不进行多会话的传播(有可能一个用户登录3个浏览器,有三个会话),如果此broadcast=false,则只传给当前会话,不进行其他会话传播
总结
本文从websocket的原理和协议,以及内容相关协议等不同维度进行了详细介绍。
最终以一个应用场景为例,从项目的结构设计,以及代码策略设计,设计模式等不同方面展示了websocket的通讯功能在项目中的使用。
如何实现某一功能其实并不重要,重要的是得了解理论,深入理论之后,再进行开发。