编写自己的聊天网站(一)

编写自己的聊天网站(一)

编写自己的聊天网站(一)

欢迎大家加我微信交流技术—xy1399666

后端实现技术(springboot+websocket+security)

前言:第一次写,有不到之处请提出意见,希望我们一起进步。
1.首先当然是创建一个springboot项目,相信这个大家应该都没什么问题哈,然后是引入websocket和security的jar包啦。当然后面还要连接数据库的mybtis-jar包,这些基础的就不贴出来了

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

		 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>

2.写个WebSocket配置类WebSocketConfig

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    //注册STOMP协议的节点
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //映射指定的 URL,指定使用SockJS协议
        registry.addEndpoint("/endpointWisely").withSockJS();  //注册STOMP协议的节点endpoint,并指定SockJS协议
       // 1  注册一个新的endpoint
        registry.addEndpoint("/endpointChat").withSockJS();
    }

    //配置消息代理
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //广播式应该配置一个topic代理
        registry.enableSimpleBroker("/queue","/topic");

    }
}

3.接下来在配置一下Security(WebSecurityConfig)

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    Daouser dao;
    @Autowired
    DataSource dataSource;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.
                authorizeRequests()
                //1    对/  和  /login  路径不拦截
                .antMatchers("/","/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                //2    设置登录页面的路径
                .loginPage("/login")
                //3     成功后跳转至fchat路径
                .defaultSuccessUrl("/fchat")
                .permitAll()
                .and()
                .logout()
                .permitAll();

    }

    //4  在内存中配置两个用户名、密码、角色,定义认证用于信息获取来源以及密码校验规则
    //认证信息获取来源是内存获取——inMemoryAuthentication
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{

        //代码报错  There is no PasswordEncoder mapped for the id “null”
        //https://blog.csdn.net/canon_in_d_major/article/details/79675033
        //Spring security 5.0中新增了多种加密方式,也改变了密码的格式
        //要将前端传过来的密码进行某种方式加密,spring security 官方推荐的是使用bcrypt加密方式
           //基于内存存储用户信息
           auth.userDetailsService(new WebSecuritylet());
        auth
                .inMemoryAuthentication()
                .withUser("liuyishou").password("123456").roles("USER")
                .and()
                .withUser("wangdefa").password("123456").roles("USER");
        }

    }

    //5  指定路径下的静态资源不拦截
    @Override
    public void configure(WebSecurity webSecurity) throws Exception{
        webSecurity.ignoring().antMatchers("/resources/static/**");
    }

}

(4) 控制器示例

@Controller
public class WsController {

    //1 通过SimpMessagingTemplate 向浏览器发送消息
    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @MessageMapping("/chat")
    public void handleChat(Principal principal, String msg){  //2   springMVC 中可以直接在参数中获取principal,它包含了当前用户的信息
        //3  如果发送人是mmz,则发送给wisely,暂时硬编码测试,生产中看情况
        if(principal.getName().equals("gdg")){
            //4 向用户发送消息,convertAndSendToUser(接收消息的用户,浏览器的订阅地址,消息体)
            messagingTemplate.convertAndSendToUser("yq","/queue/notifications",principal.getName() + "-send:" + msg);
        }else {
            messagingTemplate.convertAndSendToUser("gdg","/queue/notifications",principal.getName() + "-send:" + msg);
        }
    }

(5) 登录页面 在src/main/resources/templates下新建 login.html,

<!DOCTYPE html>
<html lang="zh-CN"
      xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<meta http-equiv="Content-Type" content="text/html;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)聊天页面 在src/main/resources/templates下新建 chat.html,

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<head>
    <title>Home</title>
    <!--<script th:src="@{/https://code.jquery.com/jquery-3.4.1.min.js}" type="text/javascript"></script>-->
    <script th:src="@{/static/jquery-3.3.1.js}" type="text/javascript"></script>
    <script th:src="@{/static/sockjs.min.js}" type="text/javascript"></script>
    <script th:src="@{/static/stomp.min.js}" type="text/javascript"></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  连接endpoint
    var stomp = Stomp.over(sock);
    stomp.connect('guest', 'guest', function(frame) {
        //2    订阅 /user/queue/notifications 发送的消息,要求与messagingTemplate 中定义的地址一样,多了个user,且是必须的,这样才能把消息发送到指定的用户
        stomp.subscribe("/user/queue/notifications", handleNotification);
    });



    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>

(7)增加页面的viewController

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        //访问localhost:8787/ws  跳转ws.html页面
        registry.addViewController("/ws").setViewName("/ws");

        registry.addViewController("/login").setViewName("/login");
        registry.addViewController("/chat").setViewName("/chat");

    }

    /**
     * 自动配置静态资源
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/");
        super.addResourceHandlers(registry);
    }

}

ps:打开两个浏览器窗口,谷歌浏览器可设置两个独立用户,然后访问http://localhost:8085/login
登录 liuyishou/123456,wangdefa/123456 ,然后就可以刘一手和王德发实时通信了。

最后:当然这只是最简单的例子:后面还有实现类似微信网页版的功能 ,登录注册-好友列表-群聊-添加好友一系列的功能

    原文作者:qq_45876098
    原文地址: https://blog.csdn.net/qq_45876098/article/details/105860773
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞