当前位置: 首页 > news >正文

wordpress新闻站主题南京模板网站开发

wordpress新闻站主题,南京模板网站开发,怎么做 社区网站,微信分销app#x1f389;#x1f389;欢迎光临#xff0c;终于等到你啦#x1f389;#x1f389; #x1f3c5;我是苏泽#xff0c;一位对技术充满热情的探索者和分享者。#x1f680;#x1f680; #x1f31f;持续更新的专栏《Spring 狂野之旅#xff1a;从入门到入魔》 欢迎光临终于等到你啦 我是苏泽一位对技术充满热情的探索者和分享者。 持续更新的专栏《Spring 狂野之旅从入门到入魔》 本专栏带你从Spring入门到入魔  这是苏泽的个人主页可以看到我其他的内容哦 努力的苏泽http://suzee.blog.csdn.net/ 本文给大家带来的是SpringBoot整合WebSocket 实现一个简单的聊天功能 然后再进阶到语音的聊天 视频聊天 目录 在视频聊天的基础上 还要再实现 美颜、心跳检查掉线、掉帧优化。掉线重连等企业级业务需求  一、WebSocket概述​编辑 实现步骤 首先引入依赖 设置拦截器 自定义报错 这是我做的自定义类型 可以根据自己的修改 拦截器配置 拦截器实现 websocket服务实现 在视频聊天的基础上 还要再实现 美颜、心跳检查掉线、掉帧优化。掉线重连等企业级业务需求  一、WebSocket概述 WebSocket是基于TCP协议的一种网络协议它实现了浏览器与服务器全双工通信支持客户端和服务端之间相互发送信息。在有WebSocket之前如果服务端数据发生了改变客户端想知道的话只能采用定时轮询的方式去服务端获取这种方式很大程度上增大了服务器端的压力有了WebSocket之后如果服务端数据发生改变可以立即通知客户端客户端就不用轮询去换取降低了服务器的压力。目前主流的浏览器都已经支持WebSocket协议了。 WebSocket使用ws和wss作资源标志符它们两个类似于http和httpswss是使用TSL的ws。主要有4个事件 onopen 创建连接时触发onclose 连接断开时触发onmessage   接收到信息时触发onerror   通讯异常时触发 实现步骤 首先引入依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependencydependency!-- websocket --groupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId/dependencydependency!-- fastjson --groupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.47/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency 设置拦截器 自定义报错 Slf4j RestControllerAdvice public class WebExceptionAdvice {ExceptionHandler(RuntimeException.class)public ResponseEntityResult handleRuntimeException(HttpServletRequest request, RuntimeException e) {log.error(e.toString(), e);Result result Result.fail(e.getMessage());HttpStatus status HttpStatus.INTERNAL_SERVER_ERROR;//500if (e instanceof UnAuthorException) {//这个是拦截器报错才设置的状态码status HttpStatus.UNAUTHORIZED;//401}ResponseEntityResult resultResponseEntity new ResponseEntity(result, status);log.error(resultResponseEntity.toString());return resultResponseEntity;} } 这是我做的自定义类型 可以根据自己的修改 public class UnAuthorException extends RuntimeException {public UnAuthorException(String message) {super(message);} } 拦截器配置 Configuration public class MvcConfig implements WebMvcConfigurer {Resourceprivate StringRedisTemplate stringRedisTemplate;Override//添加拦截器 InterceptorRegistry registry 拦截器的注册器 excludePathPatterns排除不需要的拦截的路径// 只要跟登录无关就不需要拦截 拦截器的作用只是校验登录状态public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/index/**,/user/wechat/login,/user/zfb/login,//...这里自己去设置 不想被拦截的页面 剩下的就是被拦截的).order(1); // order是设置先后 // 刷新token的拦截器registry.addInterceptor(new RefreshTokeninterceptor(stringRedisTemplate)).addPathPatterns(/**).order(0);} } 拦截器实现 public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.判断是否需要拦截ThreadLocal中是否有用户if (UserHolder.getUser() nullListenerHolder.getListener()null) {System.out.println(拦截器报错啦);//response.getHeader(erro);throw new UnAuthorException(用户未登录);}return true;} } /*/***author suze*date 2023-10-25*time 15:23**/ public class RefreshTokeninterceptor implements HandlerInterceptor {//而MvcConfig中使用了 LoginInterceptor 所以我们要去到MvcConfig进行注入private StringRedisTemplate stringRedisTemplate;//因为这个类不是spring boot构建的而是手动创建的类所以依赖注入不能用注解来注入要我们手动使用构造函数来注入这个依赖public RefreshTokeninterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token2request.getHeader(token2);String ListenerKey LOGIN_LISTENER_KEY token2;//这里的倾听者信息是在倾听者登录的函数里面把倾听者信息录入进去String LisStr stringRedisTemplate.opsForValue().get(ListenerKey);if(LisStr null || LisStr.isEmpty()){System.err.println(倾听者token为空);}else {Listener listener JSON.parseObject(LisStr, Listener.class);ListenerHolder.saveListener(listener);stringRedisTemplate.expire(ListenerKey,15, TimeUnit.MINUTES);return true;}//获取请求头中的token 在前端代码中详见authorizationString token request.getHeader(token);if(StrUtil.isBlank(token)){//判断是否为空System.err.println(token为空);return true;}// 基于token获取Redis用户String key LOGIN_USER_KEYtoken;String userstr stringRedisTemplate.opsForValue().get(key);//System.err.println(基于token获取Redis用户:userstr);//判断用户是否存在 不存在的话就查询是否是倾听者的情况if(userstr null || userstr.isEmpty()){System.err.println(用户为空);return true;}// 将查询到的user的json字符串转化为user对象User user JSON.parseObject(userstr, User.class);//存在 保存用户信息到TheadLocalUserHolder.saveUser(user);System.out.println(保存用户user.getOpenId()信息到TheadLocal了);//刷新token有效期stringRedisTemplate.expire(key,15, TimeUnit.MINUTES);//放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//移除用户UserHolder.removeUser();ListenerHolder.removeListener();} }根据自己需求 删掉一些我这边业务的部分 不删也行 也能用 就是有点慢 websocket服务实现 ServerEndpoint(value /imserver/{userId}) Component public class WebSocketServer {private static final Logger log LoggerFactory.getLogger(WebSocketServer.class);/*** 记录当前在线连接数*/public static final MapString, Session sessionMap new ConcurrentHashMap();//public static final MapString, Session UserMap new ConcurrentHashMap();这里没有需要知道对方名字的需求 所以不需要加 需要再加/*** HEAD* 设置为静态的 公用一个消息map ConcurrentMap为线程安全的map HashMap不安全*///这里的messageMap存的是某用户已经离线 他离线后收到的消息的集合 所以这里的key是接收者的keyprivate static ConcurrentMapString, ListString messageMap new ConcurrentHashMap();/**** 连接建立成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(userId) String userId) {sessionMap.put(userId, session);// stringRedisTemplate.opsForList().log.info(有新用户加入userId{}, 当前在线人数为{}, userId, sessionMap.size());JSONObject result new JSONObject();JSONArray array new JSONArray();result.set(users, array);for (Object key : sessionMap.keySet()) {JSONObject jsonObject new JSONObject();jsonObject.set(userId, key);// {userId: aysgduiehfiuew, userId: admin}array.add(jsonObject);}//这里得到的是该用户的历史记录map userMessageListString userMessage messageMap.get(userId);//载入历史记录 这个过程相当于重新把消息发给自己if (userMessage!null) {for (int i userMessage.size() - 1; i 0; i--) {String message userMessage.get(i);//这里的session的作用是告诉sendMessage发给谁 这里是要加载自己错过的历史消息// 所以是把历史记录发给自己 所以toSession填的是自己的sessionthis.sendMessage(message, session); // Thread.sleep(10000);}messageMap.remove(userId);} // {users: [{userId: zhang},{ userId: admin}]}sendAllMessage(JSONUtil.toJsonStr(result)); // 后台发送消息给所有的客户端}/*** 服务端发送消息给客户端*/private void sendMessage(String message, Session toSession) {try {log.info(服务端给客户端[{}]发送消息{}, toSession.getId(), message);toSession.getBasicRemote().sendText(message);//String from JSONUtil.parseObj(message).getStr(from);if (!messageMap.get(toSession.getId()).isEmpty()) {ListString list messageMap.get(toSession.getId());log.info(有待发送的消息继续存储);list.add(message);//toSession是被发送者的idmessageMap.put(toSession.getId(), list);return;} else {ListString list new ArrayList();//该用户发的离线消息的集合list.add(message);messageMap.put(toSession.getId(), list);log.info(用户不在线保存信息);return;}} catch (Exception e) {log.error(服务端发送消息给客户端失败, e);}// {users: [{userId: zhang},{ userId: admin}]}}/*** 连接关闭调用的方法*/OnClosepublic void onClose(Session session, PathParam(userId) String userId) {sessionMap.remove(userId);log.info(有一连接关闭移除username{}的用户session, 当前在线人数为{}, userId, sessionMap.size());}/*** 收到客户端消息后调用的方法* 后台收到客户端发送过来的消息* onMessage 是一个消息的中转站* 接受 浏览器端 socket.send 发送过来的 json数据* param message 客户端发送过来的消息*/OnMessagepublic void onMessage(String message, Session session, PathParam(userId) String userId) {log.info(服务端收到用户username{}的消息:{}, userId, message);JSONObject obj JSONUtil.parseObj(message);String toUserId obj.getStr(to); // to表示发送给哪个用户比如 adminString text obj.getStr(text); // 发送的消息文本 hello//建立一个数组 把每一次的都装进去 然后下面//TODO 这里要写 一个缓存历史记录的方法来处理 除了test123 是用于心跳的 就不用缓存if(!toUserId.equals(test123)){Session toSession sessionMap.get(toUserId); // 根据 to userId来获取 session再通过session发送消息文本if (toSession ! null) {// 服务器端 再把消息组装一下组装后的消息包含发送人和发送的文本内容// {from: zhang, text: hello}JSONObject jsonObject new JSONObject();jsonObject.set(from, userId); // from 是 zhangjsonObject.set(text, text); // text 同上面的textthis.sendMessage(jsonObject.toString(), toSession);log.info(发送给用户username{}消息{}, toUserId, jsonObject.toString());} else {log.info(发送失败未找到用户username{}的session, toUserId);}}}OnErrorpublic void onError(Session session, Throwable error) {log.error(发生错误);error.printStackTrace();}/*** 服务端发送消息给所有客户端*/private void sendAllMessage(String message) {try {for (Session session : sessionMap.values()) {log.info(服务端给客户端[{}]发送消息{}, session.getId(), message);session.getBasicRemote().sendText(message);}} catch (Exception e) {log.error(服务端发送消息给客户端失败, e);}} } 这里再写视频聊天就太多了 打算放到下一篇专门来写 如果感兴趣的朋友可以私信找我拿项目  或者关注我下一篇专门讲解 给个三连吧兄弟们 制作不易 WebRTC实现多人聊天室文字语音视频进阶美颜 掉帧优化掉线重连
http://www.pierceye.com/news/352341/

相关文章:

  • wap手机网站建设刀模 东莞网站建设
  • 怎样做网站的外链做推广优化的网站有哪些内容
  • 永嘉规划建设局网站备案个人网站做淘宝客
  • 枣庄网站建设电话网站怎么做 凡科
  • 视频网站点击链接怎么做的宁波网站建设接单
  • 网站报价表怎么做wordpress 横向扩展
  • 溧阳网站建设哪家好网站建设的教程
  • 360怎么做网站做pop网站
  • 网站建设方案书2000字中国正国级名单
  • 企业网站的布局类型网站移动页面怎么做的
  • 人是用什么做的视频网站吗wordpress如何设水印图片
  • 蛋糕店的网站建设咋写深圳市宝安区邮政编码
  • 东莞横沥网站建设杭州网站制作排名
  • 百合怎么做网站网站开发语
  • 网站搭建哪里找最好天津市建设工程信息网站
  • 有免费注册网站吗做教育网站还挣钱吗
  • 网站做百度推广需要哪些条件店铺推广软文范例
  • 台州企业网站搭建特点迅美网站建设
  • 做营销网站推广官方网站建设方法
  • 网页设计精选网站网站查询功能怎么做
  • 重庆专业网站推广流程建立平台的步骤
  • 舟山市普陀区建设局网站net网站开发 兼职
  • 网站备案流程阿里云南宁网站建设官网
  • h5网站制作介绍简单的静态 新闻 asp 网站源码
  • 济南seo网站推广公司帮别人做彩票网站吗
  • 郑州市网站建设怎么样wordpress wp editor
  • 台州网站建设 推广公司网络营销课程总结范文
  • 网站 外包 版权杭州做官网的有哪些公司
  • 微信网站html5中山平面设计公司
  • 建站网站教程视频世界网站排名