zoukankan      html  css  js  c++  java
  • SpringBoot 搭建简单聊天室

    SpringBoot 搭建简单聊天室(queue 点对点)

    1、引用 SpringBoot 搭建 WebSocket 链接

      https://www.cnblogs.com/yi1036943655/p/10089100.html

    2、整合Spring Security

    package com.example.demo.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        /**
         *   简单解释一下
         *      页面(login、ws)不设置拦截
         *      登录页面login
         *      登陆成功页面chat
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                    .antMatchers("/","/login","/ws").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/chat")
                    .permitAll()
                    .and()
                    .logout()
                    .permitAll();
    
        }
    
        /**
         * 添加两个用户
         *      账号:wfy 密码:wfy
         *      账号:wisely 密码:wisely
         *      角色:USER
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth
                    .inMemoryAuthentication()
                    .passwordEncoder(new MyPasswordEncoder())
                    .withUser("wfy").password("wfy").roles("USER")
                    .and()
                    .withUser("wisely").password("wisely").roles("USER");
        }
    
        /**
         * 静态资源路径不设置拦截
         * @param web
         * @throws Exception
         */
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/resources/static/**");
        }
    }

    3、配置WebSocket

    package com.example.demo.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
    import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
    import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
    
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    
        /**
         * 配置链接端点
         * @param registry
         */
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry){
            registry.addEndpoint("/endpointWisely").withSockJS();
            registry.addEndpoint("/endpointChat").withSockJS();
        }
    
        /**
         * 配置消息代理
         * @param registry
         */
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry){
            registry.enableSimpleBroker("/topic","/queue");
        }
    }

    4、书写控制器

    package com.example.demo.controller;
    
    import com.example.demo.PoJo.WiselyMessage;
    import com.example.demo.PoJo.WiselyResponse;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.messaging.handler.annotation.MessageMapping;
    import org.springframework.messaging.handler.annotation.SendTo;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.stereotype.Controller;
    
    import java.security.Principal;
    
    @Controller
    public class WsController {
    
        /**
         * 服务器 推送数据
         */
        @Autowired
        private SimpMessagingTemplate messagingTemplate;
    
        /**
         * MessageMapping 类似于 RequestMapping
         * SendTo 订阅地址 类似于 订阅一个URL (我的理解就是 调用了这个方法 在返回的时候会给订阅该url的地址发送数据)
         * @param message
         * @return
         * @throws Exception
         */
        @MessageMapping("/welcome")
        @SendTo("/topic/getResponse")
        public WiselyResponse say(WiselyMessage message) throws Exception {
            Thread.sleep(3000);
            return new WiselyResponse("Welcome," + message.getName() + "!");
        }
    
        /**
         * 通过convertAndSendToUser 向指定用户发送消息
         * @param principal
         * @param msg
         */
        @MessageMapping("/chat")
        public void handleChat(Principal principal,String msg){
            if("wfy".equals(principal.getName())){
                messagingTemplate.convertAndSendToUser("wisely","queue/notifications",principal.getName() + "-send : "+ msg );
            }else{
                messagingTemplate.convertAndSendToUser("wfy","queue/notifications",principal.getName() + "-send : "+ msg );
            }
        }
    
    
    }

    5、书写页面(chat)

    <!DOCTYPE html>
    
    <html xmlns:th="http://www.thymeleaf.org">
    <meta charset="UTF-8" />
    <head>
        <title>Home</title>
        <script th:src="@{sockjs.min.js}"></script>
        <script th:src="@{stomp.min.js}"></script>
        <script th:src="@{jquery.js}"></script>
    </head>
    <body>
    <p>
        聊天室
    </p>
    
    <form id="wiselyForm">
        <textarea rows="4" cols="60" name="text"></textarea>
        <input type="submit"/>
    </form>
    
    <script th:inline="javascript">
        $('#wiselyForm').submit(function(e){
            e.preventDefault();
            var text = $('#wiselyForm').find('textarea[name="text"]').val();
            sendSpittle(text);
        });
    
        var sock = new SockJS("/endpointChat"); //1
        var stomp = Stomp.over(sock);
        stomp.connect('guest', 'guest', function(frame) {
            stomp.subscribe("/user/queue/notifications", handleNotification);//2
        });
    
    
        function handleNotification(message) {
            $('#output').append("<b>Received: " + message.body + "</b><br/>")
        }
    
        function sendSpittle(text) {
            stomp.send("/chat", {}, text);//3
        }
        $('#stop').click(function() {sock.close()});
    </script>
    
    <div id="output"></div>
    </body>
    </html>

    页面(login)

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <meta charset="UTF-8" />
    <head>
        <title>登陆页面</title>
    </head>
    <body>
    <div th:if="${param.error}">
        无效的账号和密码
    </div>
    <div th:if="${param.logout}">
        你已注销
    </div>
    <form th:action="@{/login}" method="post">
        <div><label> 账号 : <input type="text" name="username"/> </label></div>
        <div><label> 密码: <input type="password" name="password"/> </label></div>
        <div><input type="submit" value="登陆"/></div>
    </form>
    </body>
    </html>

    6、编写视图解析器

    package com.example.demo.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry){
            registry.addViewController("/ws").setViewName("/ws");
            registry.addViewController("/login").setViewName("/login");
            registry.addViewController("/chat").setViewName("/chat");
        }
    }

    7、记录一个坑

      1)、如果使用的是 Security5.0 以上会报错 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

    解决办法:

    package com.example.demo.config;
    
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    public class MyPasswordEncoder implements PasswordEncoder {
    
        @Override
        public String encode(CharSequence charSequence) {
            return charSequence.toString();
        }
    
        @Override
        public boolean matches(CharSequence charSequence, String s) {
            return s.equals(charSequence.toString());
        }
    
    }
  • 相关阅读:
    ci框架与smarty的整合
    jQuery 1.3.2 简单实现select二级联动
    Nginx配置https
    tp5.1最新的类库使用规则
    Linux指令大全
    Redis锁机制处理高并发
    Nginx配置https站点
    vue的入门
    HTTP 请求头中的 X-Forwarded-For,X-Real-IP
    Composer包制作以及发布!
  • 原文地址:https://www.cnblogs.com/yi1036943655/p/10089243.html
Copyright © 2011-2022 走看看