哈尔滨建设银行网站,网站建设运营服务商,商务风页面设计,wordpress md5工具什么是WebSocket
WebSocket 是一种网络通信协议#xff0c;很多高级功能都需要它。 我们已经有了 HTTP 协议#xff0c;为什么还需要另一个协议#xff1f;它能带来什么好处#xff1f; 因为 HTTP 协议有一个缺陷#xff1a;通信只能由客户端发起。 如果我们想要服务器给…什么是WebSocket
WebSocket 是一种网络通信协议很多高级功能都需要它。 我们已经有了 HTTP 协议为什么还需要另一个协议它能带来什么好处 因为 HTTP 协议有一个缺陷通信只能由客户端发起。 如果我们想要服务器给客户端发信息只能由客户端建立长连接这种消耗性能的操作。 WebSocket 协议在2008年诞生2011年成为国际标准。所有浏览器都已经支持了。 它的最大特点就是服务器可以主动向客户端推送信息客户端也可以主动向服务器发送信息是真正的双向平等对话属于服务器推送技术的一种。
详细的WebSocket可以参考阮一峰的博客 http://www.ruanyifeng.com/blog/2017/05/websocket.html
Maven 依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId
/dependencySpringBoot配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** Created with IntelliJ IDEA.** Auther: zlf* Date: 2021/04/30/16:58* Description:*/
Configuration
//EnableWebSocketMessageBroker
public class WebSocketConfig {Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}}WebSokect 通信
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** Created with IntelliJ IDEA.** Auther: zlf* Date: 2021/04/30/17:48* Description:*/
Slf4j
ServerEndpoint(/webSocket/{code})
Component
public class WebSocketServer {/*** concurrent包的线程安全Set用来存放每个客户端对应的WebSocket对象。*/private static CopyOnWriteArraySetWebSocketServer webSocketSet new CopyOnWriteArraySet();/*** 与客户端的连接会话需要通过它来给客户端发送数据*/private Session session;/*** 接收识别码*/private String code ;/*** 连接建立成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(code) String code) {this.session session;//如果存在就先删除一个防止重复推送消息实际这里实现了set不删除问题也不大webSocketSet.removeIf(webSocket - webSocket.code.equals(code));webSocketSet.add(this);this.code code;log.info(建立WebSocket连接code code当前连接数webSocketSet.size());}/*** 连接关闭调用的方法*/OnClosepublic void onClose() {webSocketSet.remove(this);log.info(关闭WebSocket连接code this.code当前连接数webSocketSet.size());}/*** 收到客户端消息后调用的方法** param message 客户端发送过来的消息*/OnMessagepublic void onMessage(String message, Session session) {log.info(收到来[ code ]的信息: message);}OnErrorpublic void onError(Session session, Throwable error) {log.error(websocket发生错误);error.printStackTrace();}/*** 实现服务器主动推送*/private void sendMessage(String message) throws IOException {this.session.getBasicRemote().sendText(message);}/*** 群发自定义消息*/public void sendAll(String message) {log.info(推送消息到 code 推送内容: message);for (WebSocketServer item : webSocketSet) {try {item.sendMessage(message);} catch (IOException e) {e.printStackTrace();}}}/*** 定点推送*/public void sendTo(String message, PathParam(code) String code) {for (WebSocketServer item : webSocketSet) {try {if (item.code.equals(code)) {log.info(推送消息到[ code ]推送内容: message);item.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}Overridepublic boolean equals(Object o) {if (this o) {return true;}if (o null || getClass() ! o.getClass()) {return false;}WebSocketServer that (WebSocketServer) o;return Objects.equals(session, that.session) Objects.equals(code, that.code);}Overridepublic int hashCode() {return Objects.hash(session, code);}
}这样前端发起相应的请求就可以建立双向的通信。
#前端Vue代码
templatedivwebsocket/div
/templatescript
export default {data(){return{user : JSON.parse(localStorage.getItem(user))?JSON.parse(localStorage.getItem(user)):null}},created(){this.initWebSocket();},methods: {initWebSocket(){ //初始化weosocket// 建立连接 在请求中带上token 由SpringSecurity进行权限认证const wsuri ws://localhost:8001/webSocket/this.user.id?AuthorizationlocalStorage.getItem(token);this.websock new WebSocket(wsuri);this.websock.onmessage this.websocketonmessage;this.websock.onopen this.websocketonopen;this.websock.onerror this.websocketonerror;this.websock.onclose this.websocketclose;},websocketonopen(){ //连接建立之后执行send方法发送数据let actions {test:12345};this.websocketsend(JSON.stringify(actions));},websocketonerror(){//连接建立失败重连console.log(----连接失败重连)this.initWebSocket();},websocketonmessage(e){ //数据接收//const redata JSON.parse(e.data);console.log(e.data);},websocketsend(Data){//数据发送this.websock.send(Data);},websocketclose(e){ //关闭console.log(断开连接,e);},},
}
/scriptstyle/style关于权限认证
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.youshe.mcp.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** Description: JWT登录授权过滤器* Author: zlf* Date: 2021/3/30*/
Component
Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {Autowiredprivate JwtTokenUtil jwtTokenUtil;Value(${jwt.tokenHeader})private String tokenHeader;Value(${jwt.tokenHead})private String tokenHead;Autowiredprivate MyUserDetailsService userDetailsService;Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws ServletException, IOException {String authHeader request.getHeader(this.tokenHeader);if(StringUtils.isBlank(authHeader)){// 由于webSocket 没有设置token在请求头里而在url中// websocket连接时令牌放在url参数上authHeader request.getParameter(this.tokenHeader);}if (authHeader ! null authHeader.startsWith(this.tokenHead)) {String authToken authHeader.substring(this.tokenHead.length());// The part after Bearer String username jwtTokenUtil.getUserNameFromToken(authToken);//log.info(checking username:{}, username);if (username ! null SecurityContextHolder.getContext().getAuthentication() null) {UserDetails userDetails userDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(authToken, userDetails)) {UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, new BCryptPasswordEncoder().encode(userDetails.getPassword()), userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));//log.info(authenticated user:{}, username);SecurityContextHolder.getContext().setAuthentication(authentication);}}}chain.doFilter(request, response);}}测试
import com.youshe.commonutils.vo.ResultVo;
import com.youshe.mcp.entity.User;
import com.youshe.mcp.service.UserService;
import com.youshe.mcp.service.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import sun.plugin.liveconnect.SecurityContextHelper;import javax.xml.transform.Result;
import java.security.Security;/*** Created with IntelliJ IDEA.** Auther: zlf* Date: 2021/04/30/18:03* Description:*/
RestController
RequestMapping(/test)
public class testController {AutowiredUserService userService;AutowiredWebSocketServer webSocketServer;// 向请求的用户 推送消息GetMapping(test)public ResultVo test(){UserDetails userDetails (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();String username userDetails.getUsername();User user userService.getUserByName(username);webSocketServer.sendTo(向客户端推送实时消息,user.getId());return ResultVo.ok();}
}效果