在没有WebSocket时,大多时候我们在处理服务端主动给浏览器推送消息都是非常麻烦,且有很多弊端,如:

1.Ajax轮循

优点:客户端很容易实现良好的错误处理系统和超时管理,实现成本与Ajax轮询的方式类似。

缺点:需要服务器端有特殊的功能来临时挂起连接。当客户端发起的连接较多时,服务器端会长期保持多个连接,具有一定的风险。

2. 基于 Iframe 及 htmlfile 的流(streaming)方式 俗称长连接。

优点: 实时性好(消息延时小);性能好(能支持大量用户)

缺点: 长期占用连接,丧失了无状态高并发的特点。

今天我们就来说说WebSocket。它是HTML5开始提供的。

websocket方式

优点:

  1.    1、较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有210字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的4字节的掩码。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。
  2. 2、更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。
  3. 3、保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
  4. 4、更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
  5. 5、可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
  6. 6、更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

缺点:不支持低版本的IE浏览器

今天就和大家一起学习SpringBoot整合webSocket 一对一发送消息,一对多发送消息,服务器主动推送消息。

什么是webSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
 

对于上面的业务,我给大家画一个牛成图。hiahia~~ 可以参考看看哈。

不知道大家能不能看懂。再给大家写一个word版本的流程图:

好了,废话少说现在SpringBoot和WebSocket集成 上代码:

①、工程目录:

 

②、pom文件:

  1. pom.xml文件:
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <parent>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-parent</artifactId>
  9. <version>2.1.6.RELEASE</version>
  10. <relativePath/> <!-- lookup parent from repository -->
  11. </parent>
  12. <groupId>cn.cnbuilder</groupId>
  13. <artifactId>websocket</artifactId>
  14. <version>0.0.1-SNAPSHOT</version>
  15. <name>websocket</name>
  16. <description>Demo project for Spring Boot</description>
  17.  
  18. <properties>
  19. <java.version>1.8</java.version>
  20. </properties>
  21.  
  22. <dependencies>
  23. <!--SpringBootWeb包-->
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-web</artifactId>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter</artifactId>
  32. </dependency>
  33.  
  34. <!--webSocketjar-->
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-websocket</artifactId>
  38. </dependency>
  39.  
  40. <!--访问接口跳转templates目录下的html 必须加-->
  41. <dependency>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  44. </dependency>
  45. </dependencies>
  46. <!--打包-->
  47. <build>
  48. <plugins>
  49. <plugin>
  50. <groupId>org.springframework.boot</groupId>
  51. <artifactId>spring-boot-maven-plugin</artifactId>
  52. </plugin>
  53. </plugins>
  54. </build>
  55. </project>

③、webSocket配置文件:

  1. WebSocketConfig
  2. package cn.cnbuilder.websocket.config;
  3.  
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
  7.  
  8. @Configuration
  9. public class WebSocketConfig {
  10.  
  11. @Bean
  12. public ServerEndpointExporter serverEndpointExporter() {
  13. return new ServerEndpointExporter();
  14. }
  15. }

④、websocket连接信息配置:

  1. ProductWebSocket
  2.  
  3. package cn.cnbuilder.websocket;
  4.  
  5. import org.springframework.stereotype.Component;
  6.  
  7. import javax.websocket.*;
  8. import javax.websocket.server.PathParam;
  9. import javax.websocket.server.ServerEndpoint;
  10. import java.io.IOException;
  11. import java.text.DateFormat;
  12. import java.text.SimpleDateFormat;
  13. import java.util.Date;
  14. import java.util.concurrent.ConcurrentHashMap;
  15.  
  16. /**
  17. * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
  18. * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
  19. * @ServerEndpoint 可以把当前类变成websocket服务类
  20. */
  21. @ServerEndpoint("/websocket/{userId}")
  22. @Component
  23. public class ProductWebSocket {
  24.  
  25. //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
  26. private static int onlineCount = 0;
  27.  
  28. //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户id
  29. private static ConcurrentHashMap<String, ProductWebSocket> webSocketSet = new ConcurrentHashMap<String, ProductWebSocket>();
  30.  
  31. //与某个客户端的连接会话,需要通过它来给客户端发送数据
  32. private Session session;
  33.  
  34. //当前发消息的人员编号
  35. private String userId = "";
  36.  
  37. /**
  38. * 线程安全的统计在线人数
  39. *
  40. * @return
  41. */
  42. public static synchronized int getOnlineCount() {
  43. return onlineCount;
  44. }
  45.  
  46. public static synchronized void addOnlineCount() {
  47. ProductWebSocket.onlineCount++;
  48. }
  49.  
  50. public static synchronized void subOnlineCount() {
  51. ProductWebSocket.onlineCount--;
  52. }
  53.  
  54. /**
  55. * 连接建立成功调用的方法
  56. *
  57. * @param param 用户唯一标示
  58. * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
  59. */
  60. @OnOpen
  61. public void onOpen(@PathParam(value = "userId") String param, Session session) {
  62. userId = param;//接收到发送消息的人员编号
  63. this.session = session;
  64. webSocketSet.put(param, this);//加入线程安全map中
  65. addOnlineCount(); //在线数加1
  66. System.out.println("用户id:" + param + "加入连接!当前在线人数为" + getOnlineCount());
  67. }
  68.  
  69. /**
  70. * 连接关闭调用的方法
  71. */
  72. @OnClose
  73. public void onClose() {
  74. if (!userId.equals("")) {
  75. webSocketSet.remove(userId); //根据用户id从ma中删除
  76. subOnlineCount(); //在线数减1
  77. System.out.println("用户id:" + userId + "关闭连接!当前在线人数为" + getOnlineCount());
  78. }
  79. }
  80.  
  81. /**
  82. * 收到客户端消息后调用的方法
  83. *
  84. * @param message 客户端发送过来的消息
  85. * @param session 可选的参数
  86. */
  87. @OnMessage
  88. public void onMessage(String message, Session session) {
  89. System.out.println("来自客户端的消息:" + message);
  90. //要发送人的用户uuid
  91. String sendUserId = message.split(",")[1];
  92. //发送的信息
  93. String sendMessage = message.split(",")[0];
  94. //给指定的人发消息
  95. sendToUser(sendUserId, sendMessage);
  96.  
  97. }
  98.  
  99. /**
  100. * 给指定的人发送消息
  101. *
  102. * @param message
  103. */
  104. public void sendToUser(String sendUserId, String message) {
  105.  
  106. try {
  107. if (webSocketSet.get(sendUserId) != null) {
  108. webSocketSet.get(sendUserId).sendMessage(userId + "给我发来消息,消息内容为--->>" + message);
  109. } else {
  110.  
  111. if (webSocketSet.get(userId) != null) {
  112. webSocketSet.get(userId).sendMessage("用户id:" + sendUserId + "以离线,未收到您的信息!");
  113. }
  114. System.out.println("消息接受人:" + sendUserId + "已经离线!");
  115. }
  116. } catch (IOException e) {
  117. e.printStackTrace();
  118. }
  119. }
  120.  
  121. /**
  122. * 管理员发送消息
  123. *
  124. * @param message
  125. */
  126. public void systemSendToUser(String sendUserId, String message) {
  127.  
  128. try {
  129. if (webSocketSet.get(sendUserId) != null) {
  130. webSocketSet.get(sendUserId).sendMessage("系统给我发来消息,消息内容为--->>" + message);
  131. } else {
  132. System.out.println("消息接受人:" + sendUserId + "已经离线!");
  133. }
  134. } catch (IOException e) {
  135. e.printStackTrace();
  136. }
  137. }
  138.  
  139. /**
  140. * 给所有人发消息
  141. *
  142. * @param message
  143. */
  144. private void sendAll(String message) {
  145. String sendMessage = message.split(",")[0];
  146. //遍历HashMap
  147. for (String key : webSocketSet.keySet()) {
  148. try {
  149. //判断接收用户是否是当前发消息的用户
  150. if (!userId.equals(key)) {
  151. webSocketSet.get(key).sendMessage("用户:" + userId + "发来消息:" + " <br/> " + sendMessage);
  152. System.out.println("key = " + key);
  153. }
  154. } catch (IOException e) {
  155. e.printStackTrace();
  156. }
  157. }
  158. }
  159.  
  160. /**
  161. * 发生错误时调用
  162. *
  163. * @param session
  164. * @param error
  165. */
  166. @OnError
  167. public void onError(Session session, Throwable error) {
  168. System.out.println("发生错误");
  169. error.printStackTrace();
  170. }
  171.  
  172. /**
  173. * 发送消息
  174. *
  175. * @param message
  176. * @throws IOException
  177. */
  178. public void sendMessage(String message) throws IOException {
  179. //同步发送
  180. this.session.getBasicRemote().sendText(message);
  181. //异步发送
  182. //this.session.getAsyncRemote().sendText(message);
  183. }
  184. }

⑤、服务器推送接口:

  1. IndexController
  2. package cn.cnbuilder.websocket.controller;
  3.  
  4. import cn.cnbuilder.websocket.ProductWebSocket;
  5.  
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.GetMapping;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.ResponseBody;
  10.  
  11. import java.util.Map;
  12. import java.util.concurrent.TimeUnit;
  13.  
  14. @Controller
  15. public class IndexController {
  16.  
  17. @GetMapping(value = "/")
  18. @ResponseBody
  19. public Object index() {
  20.  
  21. return "Hello,ALl。This is yuanmayouchuang webSocket demo!";
  22. }
  23.  
  24. @ResponseBody
  25. @GetMapping("test")
  26. public String test(String userId, String message) throws Exception {
  27. if (userId == "" || userId == null) {
  28. return "发送用户id不能为空";
  29. }
  30. if (message == "" || message == null) {
  31. return "发送信息不能为空";
  32. }
  33. new ProductWebSocket().systemSendToUser(userId, message);
  34. return "发送成功!";
  35. }
  36.  
  37. @RequestMapping(value = "/ws")
  38. public String ws() {
  39. return "ws";
  40. }
  41.  
  42. @RequestMapping(value = "/ws1")
  43. public String ws1() {
  44. return "ws1";
  45. }
  46. }

⑥:SpringBoot配置文件

  1. application.yml:
  2. #端口号
  3. server:
  4. port: 12006

⑦:动态banner:

  1. banner.txt:
  2. __ ____ ____ _______
  3. \ \ / / \/ \ \ / / ____|
  4. \ \_/ /| \ / |\ \_/ / |
  5. \ / | |\/| | \ /| |
  6. | | | | | | | | | |____
  7. |_| |_| |_| |_| \_____|::猿码优创:websocket SpringBoot Demo 博客地址:www.cnbuilder.cn

⑧:前段代码:

  1. ws.html:
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <title>WebSocket SpringBootDemo</title>
  6. </head>
  7. <body>
  8. <!--userId:发送消息人的编号-->
  9. <div>默认用户idxiaoyou001(后期可以根据业务逻辑替换)</div>
  10.  
  11. <br/><input id="text" type="text"/>
  12. <input placeholder="请输入接收人的用户id" id="sendUserId"></input>
  13. <button onclick="send()">发送消息</button>
  14. <br/>
  15.  
  16. <button onclick="closeWebSocket()">关闭WebSocket连接</button>
  17. <br/>
  18. <div>公众号:猿码优创</div>
  19. <br/>
  20. <div id="message"></div>
  21. </body>
  22.  
  23. <script type="text/javascript">
  24. var websocket = null;
  25.  
  26. var userId = "xiaoyou001"
  27.  
  28. //判断当前浏览器是否支持WebSocket
  29. if ('WebSocket' in window) {
  30. websocket = new WebSocket("ws://127.0.0.1:12006/websocket/" + userId);
  31. }
  32. else {
  33. alert('当前浏览器不支持websocket哦!')
  34. }
  35.  
  36. //连接发生错误的回调方法
  37. websocket.onerror = function () {
  38. setMessageInnerHTML("WebSocket连接发生错误");
  39. };
  40.  
  41. //连接成功建立的回调方法
  42. websocket.onopen = function () {
  43. setMessageInnerHTML("WebSocket连接成功");
  44. }
  45.  
  46. //接收到消息的回调方法
  47. websocket.onmessage = function (event) {
  48. setMessageInnerHTML(event.data);
  49. }
  50.  
  51. //连接关闭的回调方法
  52. websocket.onclose = function () {
  53. setMessageInnerHTML("WebSocket连接关闭");
  54. }
  55.  
  56. //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  57. window.onbeforeunload = function () {
  58. closeWebSocket();
  59. }
  60.  
  61. //将消息显示在网页上
  62. function setMessageInnerHTML(sendMessage) {
  63. document.getElementById('message').innerHTML += sendMessage + '<br/>';
  64. }
  65.  
  66. //关闭WebSocket连接
  67. function closeWebSocket() {
  68. websocket.close();
  69. }
  70.  
  71. //发送消息
  72. function send() {
  73. var message = document.getElementById('text').value;//要发送的消息内容
  74.  
  75. if (message == "") {
  76. alert("发送信息不能为空!")
  77. return;
  78. } //获取发送人用户id
  79. var sendUserId = document.getElementById('sendUserId').value;
  80. if (sendUserId == "") {
  81. alert("发送人用户id不能为空!")
  82. return;
  83. }
  84.  
  85. document.getElementById('message').innerHTML += (userId + "给" + sendUserId + "发送消息,消息内容为---->>" + message + '<br/>');
  86. message = message + "," + sendUserId//将要发送的信息和内容拼起来,以便于服务端知道消息要发给谁
  87. websocket.send(message);
  88. }
  89. </script>
  90. </html>
  91.  
  92. ws1.html
  93. <!DOCTYPE html>
  94. <html xmlns="http://www.w3.org/1999/html">
  95. <head>
  96. <title>WebSocket SpringBootDemo</title>
  97. </head>
  98. <body>
  99. <!--userId:发送消息人的编号-->
  100. <div>默认用户idxiaoyou002(后期可以根据业务逻辑替换)</div>
  101.  
  102. <br/><input id="text" placeholder="请输入要发送的信息" type="text"/>
  103. <input placeholder="请输入接收人的用户id" id="sendUserId"></input>
  104. <button onclick="send()">发送消息</button>
  105. <br/>
  106.  
  107. <button onclick="closeWebSocket()">关闭WebSocket连接</button>
  108. <br/>
  109. <div>公众号:猿码优创</div>
  110. </br>
  111. <div id="message"></div>
  112. </body>
  113.  
  114. <script type="text/javascript">
  115. var websocket = null;
  116.  
  117. var userId = "xiaoyou002"
  118.  
  119. //判断当前浏览器是否支持WebSocket
  120. if ('WebSocket' in window) {
  121. websocket = new WebSocket("ws://127.0.0.1:12006/websocket/" + userId);
  122. }
  123. else {
  124. alert('当前浏览器不支持websocket哦!')
  125. }
  126.  
  127. //连接发生错误的回调方法
  128. websocket.onerror = function () {
  129. setMessageInnerHTML("WebSocket连接发生错误");
  130. };
  131.  
  132. //连接成功建立的回调方法
  133. websocket.onopen = function () {
  134. setMessageInnerHTML("WebSocket连接成功");
  135. }
  136.  
  137. //接收到消息的回调方法
  138. websocket.onmessage = function (event) {
  139. setMessageInnerHTML(event.data);
  140. }
  141.  
  142. //连接关闭的回调方法
  143. websocket.onclose = function () {
  144. setMessageInnerHTML("WebSocket连接关闭");
  145. }
  146.  
  147. //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  148. window.onbeforeunload = function () {
  149. closeWebSocket();
  150. }
  151.  
  152. //将消息显示在网页上
  153. function setMessageInnerHTML(sendMessage) {
  154. document.getElementById('message').innerHTML += sendMessage + '<br/>';
  155. }
  156.  
  157. //关闭WebSocket连接
  158. function closeWebSocket() {
  159. websocket.close();
  160. }
  161.  
  162. //发送消息
  163. function send() {
  164. var message = document.getElementById('text').value;//要发送的消息内容
  165.  
  166. if (message == "") {
  167. alert("发送信息不能为空!")
  168. return;
  169. } //获取发送人用户id
  170. var sendUserId = document.getElementById('sendUserId').value;
  171. if (sendUserId == "") {
  172. alert("发送人用户id不能为空!")
  173. return;
  174. }
  175.  
  176. document.getElementById('message').innerHTML += ("我给" + sendUserId + "发送消息,消息内容为---->>" + message + '<br/>');
  177. message = message + "," + sendUserId//将要发送的信息和内容拼起来,以便于服务端知道消息要发给谁
  178. websocket.send(message);
  179. }
  180. </script>
  181. </html>

测试:启动项目

首页访问地址:http://127.0.0.1:12006/

访问WebSocket测试页面1:http://127.0.0.1:12006/ws

访问流程图:

测试一对一发送消息:给另一个用户发送信息

换一个浏览器,测试两个 不要用同一浏览器,要不会出问题。

访问WebSocket测试页面2:http://127.0.0.1:12006/ws1

一对一发送消息牛成图:

测试服务器主动向浏览器推送消息:http://127.0.0.1:12006/test?userId=xiaoyou002&message=我是小优,听到请回答。

接口地址:http://127.0.0.1:12006/test

参数:userId:推送人用户id ws.html :xiaoyou001 ws1.html:xiaoyou002 写死的,可根据业务动态写活。

一对多推送的话:流程和一对一相似。大家自行研究哈。

  1. /**
  2. * 给所有人发消息
  3. *
  4. * @param message
  5. */
  6. private void sendAll(String message) {
  7. String sendMessage = message.split(",")[0];
  8. //遍历HashMap
  9. for (String key : webSocketSet.keySet()) {
  10. try {
  11. //判断接收用户是否是当前发消息的用户
  12. if (!userId.equals(key)) {
  13. webSocketSet.get(key).sendMessage("用户:" + userId + "发来消息:" + " <br/> " + sendMessage);
  14. System.out.println("key = " + key);
  15. }
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }

以上就是websocket一对一发送消息,一对多发送消息,服务器主动推送消息 感觉是不是超简单!

文章摘自:https://cloud.tencent.com/developer/article/1474265

https://blog.lqdev.cn/2018/08/14/springboot/chapter-nineteen/

另备注另一种实现方法:https://blog.csdn.net/Ouyzc/article/details/79994401

https://docs.spring.io/spring/docs/5.0.8.RELEASE/spring-framework-reference/web.html#websocket

springboot websocket 简单入门的更多相关文章

  1. Java Springboot webSocket简单实现,调接口推送消息到客户端socket

    Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...

  2. websocket简单入门

    今天说起及时通信的时候,突然被问到时用推的方式,还是定时接受的方式,由于之前页面都是用传统的ajax处理,可能对ajax的定时获取根深蒂固了,所以一时之间没有相同怎么会出现推的方式呢?当被提及webs ...

  3. SpringBoot之简单入门

    一,spring boot 是什么? spring boot的官网是这样说的: Spring Boot makes it easy to create stand-alone, production- ...

  4. poi整合springboot超简单入门例子

    1.导入依赖 2.application.properties只需要数据库连接信息就可以 3.目录结构 有个没用的service,请忽略 4.Controller,因为入门列子,所以简单的导出 导入读 ...

  5. 统一日志监控系统 springboot websocket 简单版 王代军-作品

    http://git.oschina.net/redArmy/springboot-websocket-logs 目的: 统一监控 开发测试环境日志 如果需要可以拓展线上环境的日志(自己视情况而定) ...

  6. springboot 学习之路 1(简单入门)

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  7. SpringBoot+SpringData 整合入门

    SpringData概述 SpringData :Spring的一个子项目.用于简化数据库访问,支持NoSQL和关系数据存储.其主要目标是使用数据库的访问变得方便快捷. SpringData 项目所支 ...

  8. SpringBoot 搭建简单聊天室

    SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...

  9. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

随机推荐

  1. vue页面跳转

    一.在template中的常见写法: <router-link to="/recommend"> <button class="button" ...

  2. 学而不思则罔 - SAP云平台ABAP编程环境的由来和适用场景

    最近Jerry写了一系列关于SAP云平台ABAP编程环境的技术文章,这些文章都是围绕着在云上的ABAP编程环境的具体知识点来分享,比如要完成一个具体的开发需求,所需要的编程步骤.这些文章陆续收到一些读 ...

  3. scrapy 用pycharm调试

    1. 用pycharm打开scrapy项目,随便右击一个.py文件,选择Debug "***" 2. pycharm 右上角点击刚才debug的文件,选择Edit Configur ...

  4. springboot使用过滤器Filter

    先创建过滤器配置类: ## 引入的包部分省略... @Configuration public class FilterConfig { @SuppressWarnings({"rawtyp ...

  5. 不错的DSP和FPGA作者

    https://blog.csdn.net/wordwarwordwar/article/details/90233903

  6. 初识面向对象(钻石继承,super,多态,封装,method,property,classmethod,staticmethod)

    组合 什么有什么的关系 一个类的对象作为另一个类的对象继承 子类可以使用父类中的名字(静态属性 方法)抽象类和接口类 只能不继承,不能被实例化 子类必须实现父类中的同名方法———规范代码 metacl ...

  7. OSS阿里云相关文档

    OSS阿里云相关文档 oss文档链接

  8. C 语言究竟是一门怎样的语言?

    C语言是计算机及其相关专业的必修课,很多编程爱好者也是从C语言开始的编程之旅. C语言之父镇楼! 相较于GO,python等语言而言C语言真可以算是老古董了(发明于上世纪70年代),但是也正因为其历史 ...

  9. VBS 自动发消息给对方

    http://www.vbsedit.com/ Dim Name,Msg Name= "我家丫头" Msg = "333" set ws=wscript.cre ...

  10. 【转】spring 自定义注解(annotation)与 aop获取注解

    首先我们先介绍Java自定义注解. 在开发过程中,我们实现接口的时候,会出现@Override,有时还会提示写@SuppressWarnings.其实这个就是Java特有的特性,注解. 注解就是某种注 ...