throws Exception {
http.csrf().disable()
.formLogin()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
相对较为简单,创建2个客户,4个普通用户。
当认证管理器认证后,会将认证后的合法认证安全对象user(即 认证后的token)放入STOMP的header中.
此例中,认证管理认证之后,认证的token为org.springframework.security.authentication.UsernamePasswordAuthenticationToken,
此token认证后,将放入websocket的header中。(即 后边会谈到的安全对象 java.security.Principal)
通讯层设计 – websocket配置
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic", "/queue");
}
}
此配置中,有几点需进行讲解:
其中端点”portfolio”,用于socktJs进行websocket连接时使用,只用于建立连接。
“/topic”, “/queue”,则为STOMP的语义约束,topic语义为1-n(广播机制),queue语义为1-1(单点机制)
“app”,此为应用级别的映射终点前缀,这样说有些晦涩,一会看一下示例将会清晰很多。
通讯层设计 – 创建连接
用于连接spring websocket的端点为portfolio,它可用于连接,看一下具体实现:
<script src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.min.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
var socket = new SockJS("/portfolio");
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
showGreeting("登录用户: " + frame.headers["user-name"]);
});
这样便建立了连接。 后续的其他操作就可以通过stompClient句柄进行使用了。
通讯层设计 – spring websocket消息模型
见模型图:
message-flow-simple-broker
此图来源spring-websocket官方文档
可以看出对于同一定于目标都为:/topic/broadcast,它的发送渠道为两种:/app/broadcast和/topic/broadcast
如果为/topic/broadcast,直接可将消息体发送给定于目标(/topic/broadcast)。
如果是/app/broadcast,它将消息对应在MessageHandler方法中进行处理,处理后的结果发放到broker channel中,最后再讲消息体发送给目标(/topic/broadcast)
当然,这里边所说的app前缀就是刚才我们在websocket配置中的前缀.
看一个例子:
前端订阅:
stompClient.subscribe('/topic/broadcast', function(greeting){
showGreeting(greeting.body);
});
后端服务:
@Controller
public class ChatWebSocket extends AbstractWebSocket{
@MessageMapping("broadcast")
public String broadcast(@Payload @Validated Message message, Principal principal) {
return "发送人: " + principal.getName() + " 内容: " + message.toString();
}
}
@Data
public class Message {
@NotNull(message = "标题不能为空")
private String title;
private String content;
}
前端发送:
function sendBroadcast() {
stompClient.send("/app/broadcast",{},JSON.stringify({'content':'message content'}));
}
这种发送将消息发送给后端带有@MessageMapping注解的方法,然后组合完数据以后,在推送给订阅/topic/broadcast的前端
function sendBroadcast() {
stompClient.send("/topic/broadcast",{},JSON.stringify({'content':'message content'}));
}
这种发送直接将消息发送给订阅/topic/broadcast的前端,并不通过注解方法进行流转。
我相信上述这个理解已经解释清楚了spring websocket的消息模型图
通讯层设计 – @MessageMapping
带有这个注解的@Controller下的方法,正是对应websocket中的中转数