内容简介:不同上文TestMQCtl:控制类提供模拟登录,登录成功后转到websocket页面login.jsp简单的form表单,将请求提到loginIn,并转到ws-sendtouser-rabbitmq.jsp页面
不同上文 Spring Boot系列十七 Spring Boot 集成 websocket,使用RabbitMQ做为消息代理 ,本文我们介绍通过Spring websocket实现向特定的用户发送消息。 本文的内容如下: 1. 首先实现简单的登录功能,这里向特定用户发送消息的必要条件 2. 用户登录系统后,才可以登录websocket,并重写MyPrincipal 3. 实现向特定用户发送消息的功能 4. 测试
首先实现简单的登录功能,这是向特定用户发送消息的必要条件
TestMQCtl:控制类提供模拟登录,登录成功后转到websocket页面
/**
* 模拟登录 */
@RequestMapping(value = "loginIn", method = RequestMethod.POST)
public String login(HttpServletRequest request, @RequestParam(required=true) String name, String pwd){
HttpSession httpSession = request.getSession();
// 如果登录成功,则保存到会话中
httpSession.setAttribute("loginName", name);
return "websocket/sendtouser/ws-sendtouser-rabbitmq";
}
/**
* 转到登录页面
*/
@RequestMapping(value = "login", method = RequestMethod.GET)
public String loginPage(){
// 转到登录页面
return "websocket/sendtouser/login";
}
/**
* websocket页面
* @return
*/
@RequestMapping(value="/broadcast-rabbitmq/index")
public String broadcastIndex(){
return "websocket/sendtouser/ws-sendtouser-rabbitmq";
}
复制代码
login.jsp简单的form表单,将请求提到loginIn,并转到ws-sendtouser-rabbitmq.jsp页面
<form action="loginIn" method="post">
用户名:<input type="text" name="name" />
<p>
密码:<input type="password" name="password" />
<p>
<input type="submit" value="submit" />
</form>
复制代码
ws-sendtouser-rabbitmq.jsp连接websocket并订阅消息,这个jsp之前的文章已经介绍过了这里不详细描述。页面通过向/ws/icc/websocket启动websocket,然后订阅/user/topic/demo消息
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
$('#response').html();
}
function connect() {
// websocket的连接地址,此值等于WebSocketMessageBrokerConfigurer中registry.addEndpoint("/ws/icc/websocket").withSockJS()配置的地址
var socket = new SockJS('/ws/icc/websocket'); //1
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
// 客户端订阅消息的目的地址:此值等于BroadcastCtl中@SendTo注解的里配置的值。
stompClient.subscribe(
'/user/topic/demo',
function(respnose){
showResponse(JSON.parse(respnose.body));
}
);
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function showResponse(message) {
var response = $("#response");
response.html(message.name + "<br\>" + response.html());
}
</script>
复制代码
用户登录系统后,才可以登录websocket,并重写MyPrincipal
AuthHandshakeInterceptorAuthHandshakeInterceptor是HandshakeInterceptor 的子类。在websocket握手前判断,判断当前用户是否已经登录。如果未登录,则不允许登录websocket
@Component
public class AuthHandshakeInterceptor implements HandshakeInterceptor {
private static final Logger log = LoggerFactory.getLogger(AuthHandshakeInterceptor.class);
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
HttpSession httpSession = getSession(request);
String user = (String)httpSession.getAttribute("loginName");
if(StringUtils.isEmpty(user)){
log.error("未登录系统,禁止登录websocket!");
return false;
}
log.info("login = " + user);
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
// 参考 HttpSessionHandshakeInterceptor
private HttpSession getSession(ServerHttpRequest request) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
return serverRequest.getServletRequest().getSession(false);
}
return null;
}
}
复制代码
MyPrincipalHandshakeHandlerMyPrincipalHandshakeHandler是DefaultHandshakeHandler 的子类,处理websocket请求,这里我们只重写determineUser方法,生成我们自己的Principal ,这里我们使用loginName标记登录用户,而不是默认值
@Component
public class MyPrincipalHandshakeHandler extends DefaultHandshakeHandler {
private static final Logger log = LoggerFactory.getLogger(MyPrincipalHandshakeHandler.class);
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
HttpSession httpSession = getSession(request);
String user = (String)httpSession.getAttribute("loginName");
if(StringUtils.isEmpty(user)){
log.error("未登录系统,禁止登录websocket!");
return null;
}
log.info(" MyDefaultHandshakeHandler login = " + user);
return new MyPrincipal(user);
}
private HttpSession getSession(ServerHttpRequest request) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
return serverRequest.getServletRequest().getSession(false);
}
return null;
}
}
复制代码
MyPrincipal定义自己的Principal
public class MyPrincipal implements Principal {
private String loginName;
public MyPrincipal(String loginName){
this.loginName = loginName;
}
@Override
public String getName() {
return loginName;
}
}
复制代码
配置websocket在registerStompEndpoints中将我们MyPrincipalHandshakeHandler 和AuthHandshakeInterceptor 配置到服务中 configureMessageBroker方法配置rabbitmq信息,这里略
@Configuration
// 此注解开使用STOMP协议来传输基于消息代理的消息,此时可以在@Controller类中使用@MessageMapping
@EnableWebSocketMessageBroker
public class WebSocketRabbitMQMessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer {
@Autowired
private MyPrincipalHandshakeHandler myDefaultHandshakeHandler;
@Autowired
private AuthHandshakeInterceptor sessionAuthHandshakeInterceptor;
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws/icc/websocket")
.addInterceptors(sessionAuthHandshakeInterceptor)
.setHandshakeHandler(myDefaultHandshakeHandler)
.withSockJS();
}
….
}
复制代码
实现向特定用户发送消息的功能
TestMQCtl: 登录到模拟发送页面:send.jsp 我们使用SimpMessagingTemplate 对象的convertAndSendToUser向指定用户的/topic/demo发送消息
@Autowired
private SimpMessagingTemplate template;
/**
* 发送页面
*/
@RequestMapping(value = "send")
public String sendMq2UserPage(String msg, String userName){
return "websocket/sendtouser/send";
}
/**
* 向执行用户发送请求
*/
@RequestMapping(value = "send2user")
@ResponseBody
public int sendMq2User(String msg, String name){
System.out.println("===========" + msg + "=======" + name);
RequestMessage demoMQ = new RequestMessage();
demoMQ.setName(msg);
template.convertAndSendToUser(name, "/topic/demo", JSON.toJSONString(demoMQ));
return 0;
}
复制代码
send.jsp模拟发送页面
<form action="login" method="post">
接收者用户:<input type="text" id="name" name="name" value="<%=session.getAttribute("loginName") %>" />
<p>
消息内容:<input type="text" id="msg" name="msg" />
<p>
<input type="button" id="send" value="发送" />
</form>
<script src="/websocket/jquery.js"></script>
<script type=text/javascript>
$("#send").click(function(){
$.post("send2user",
{
name: $('#name').val(),
msg: $('#msg').val()
},
function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
});
</script>
复制代码
在模拟界面,如果我们向其它用户发送信息,则此界面不会收到信息以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Spring Websocket实现向指定的用户发送消息
- 使用 THttpClient Post时发送指定编码的文本内容
- java通过smtp服务 给指定邮箱发送邮件含附件
- Spring Boot中使用WebSocket总结(二):向指定用户发送WebSocket消息并处理对方不在线的情况
- c# – “SMTP主机未指定” – 但是是否指定?
- 运维安全 | 如何限制指定账户不能SSH只能SFTP在指定目录
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JSP网站开发典型模块与实例精讲
李振捷 / 电子工业出版社 / 2006-8 / 50.0
本书是典型模块与实例精讲丛书中的一本。 本书讲解了使用JSP开发网站系统的经典模块和工程实例,基本囊括了JSP的重点技术,对这些模块稍加修改就可以直接使用到实际项目中。为了方便本书的读者交流在学习中遇到的问题,特地在本书的服务网站上公布了很多QQ群组,读者只要拥有QQ号码,就可以参与到本书的QQ学习群组中一起讨论学习心得。本书的作者还在一定的时间给读者提供在线答疑服务。一起来看看 《JSP网站开发典型模块与实例精讲》 这本书的介绍吧!