编写自己的聊天网站(一)
编写自己的聊天网站(一)
欢迎大家加我微信交流技术—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 ,然后就可以刘一手和王德发实时通信了。
最后:当然这只是最简单的例子:后面还有实现类似微信网页版的功能 ,登录注册-好友列表-群聊-添加好友一系列的功能