在现在很多业务场景(比如聊天室),又或者是手机端的一些online游戏,都需要做到实时通信,那怎么来进行双向通信呢,总不见得用曾经很破旧的ajax每隔10秒或者每隔20秒来请求吧,我的天呐(),这尼玛太坑了

跟webservice来相比,Web Socket可以做到保持长连接,或者说强连接,一直握手存在两端可以互相发送消息互相收到消息,而webservice是一次性的,你要我响应就必须要请求我一次(黄盖:“请鞭挞我吧!”)

注:浏览器需要使用高版本的chrome或者Firefox,Tomcat使用8

先来了解一下基本概念

一、WebSocket是HTML5出的,是一种协议,也就是说原版的HTTP协议没有变化的,又或者说这两者压根就是不一样的东西,HTTP本身就不支持强连接
二、Websocket是什么样的协议,具体有什么优点
首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。
举个栗子吧,简单来说
1) HTTP的生命周期通过Request来界定,也就是一个Request 对应一个Response,或者多个Request 对应多个Response,
也就是说request对应的response数量是恒定不变的。而且这个response也是被动的,不能主动发起,必须有request才会有response
 
那么Websocket究竟是啥玩意呢
首先Websocket是基于HTTP协议的,或者说引用了HTTP的协议来完成一小部分的握手
简单来说,客服的发起请求到服务端,服务端找到对应的小弟(服务助理),找到好,这个小弟就会一直和老大保持联系,为老大服务
三、Websocket的作用
曾经接触WebSocket之前,我接触过ajax轮询以及long poll ,先来说说这2个概念,因为至今还有一些小项目是这么做的
ajax轮询:
原理非常简单,JS控制让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息,有的话就响应给客户端
以此循环获取后端的数据,同时浏览器又不需要刷新
简单的例子:OA首页显示流程,每个几秒刷新看看有没有需要处理的新流程出现

long poll:
long poll 其实原理跟 ajax轮询 差不多,都是采用循环的方式,不过采取的手段不太友好,是阻塞模型,客户端发起请求后,如果没响应,就一直不返回Response,直到有响应才返回,返回完之后,客户端再次建立连接,如此循环往复不亦乐乎。。。

从上面这两种方式看出他们都是在不断地建立HTTP连接,然后等待服务器处理,这样显得十分被动
 
那么缺点也随之而来:
这两种形式非常消耗资源,性能也不不好

好!接下来说说Websocket
Websocket的出现,使得资源不需要像之前那种方式那么浪费

它非常主动,服务端就可以主动推送信息给客户端
所以,只需建立一次HTTP请求,就可以做到源源不断的信息传送了。(就像你在手机上玩ol游戏,一开始建立连接后,你就一直保持在线,除非你断线再连)

下面贴出我的代码片段以及github地址
功能点:

spring websocket chating room
使用spring websocket实现聊天室基本功能
1.群发消息给所有人
2.悄悄话给某个人

效果:
主要代码:
pom.xml引入必要的库
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.lee</groupId>
  6. <artifactId>websocket</artifactId>
  7. <name>maven-spring-websocket-01</name>
  8. <packaging>war</packaging>
  9. <version>1.0.0-BUILD-SNAPSHOT</version>
  10.  
  11. <properties>
  12.  
  13. <java.version>1.7</java.version>
  14. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  15. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  16.  
  17. <spring.version>4.0.0.RELEASE</spring.version>
  18.  
  19. <junit.version>4.11</junit.version>
  20.  
  21. <!-- Logging -->
  22. <logback.version>1.0.13</logback.version>
  23. <slf4j.version>1.7.7</slf4j.version>
  24. </properties>
  25.  
  26. <dependencies>
  27. <!--spring MVC -->
  28. <dependency>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-core</artifactId>
  31. <version>${spring.version}</version>
  32. </dependency>
  33.  
  34. <dependency>
  35. <groupId>org.springframework</groupId>
  36. <artifactId>spring-web</artifactId>
  37. <version>${spring.version}</version>
  38. </dependency>
  39.  
  40. <dependency>
  41. <groupId>org.springframework</groupId>
  42. <artifactId>spring-webmvc</artifactId>
  43. <version>${spring.version}</version>
  44. </dependency>
  45.  
  46. <!-- jstl -->
  47. <dependency>
  48. <groupId>jstl</groupId>
  49. <artifactId>jstl</artifactId>
  50. <version>1.2</version>
  51. </dependency>
  52.  
  53. <!--spring测试框架 -->
  54. <dependency>
  55. <groupId>org.springframework</groupId>
  56. <artifactId>spring-test</artifactId>
  57. <version>${spring.version}</version>
  58. <scope>test</scope>
  59. </dependency>
  60.  
  61. <!--spring数据库操作库 -->
  62. <dependency>
  63. <groupId>org.springframework</groupId>
  64. <artifactId>spring-jdbc</artifactId>
  65. <version>${spring.version}</version>
  66. </dependency>
  67.  
  68. <dependency>
  69. <groupId>junit</groupId>
  70. <artifactId>junit</artifactId>
  71. <version>4.8.2</version>
  72. <scope>test</scope>
  73. </dependency>
  74.  
  75. <!--spring websocket库 -->
  76. <dependency>
  77. <groupId>org.springframework</groupId>
  78. <artifactId>spring-websocket</artifactId>
  79. <version>${spring.version}</version>
  80. </dependency>
  81. <dependency>
  82. <groupId>org.springframework</groupId>
  83. <artifactId>spring-messaging</artifactId>
  84. <version>${spring.version}</version>
  85. </dependency>
  86.  
  87. <!--jackson用于json操作 -->
  88. <dependency>
  89. <groupId>com.fasterxml.jackson.core</groupId>
  90. <artifactId>jackson-databind</artifactId>
  91. <version>2.3.0</version>
  92. </dependency>
  93.  
  94. <dependency>
  95. <groupId>commons-fileupload</groupId>
  96. <artifactId>commons-fileupload</artifactId>
  97. <version>1.2.2</version>
  98. </dependency>
  99. <dependency>
  100. <groupId>commons-io</groupId>
  101. <artifactId>commons-io</artifactId>
  102. <version>2.2</version>
  103. </dependency>
  104.  
  105. <!-- Logging with SLF4J & LogBack -->
  106. <dependency>
  107. <groupId>org.slf4j</groupId>
  108. <artifactId>slf4j-api</artifactId>
  109. <version>${slf4j.version}</version>
  110. <scope>compile</scope>
  111. </dependency>
  112. <dependency>
  113. <groupId>ch.qos.logback</groupId>
  114. <artifactId>logback-classic</artifactId>
  115. <version>${logback.version}</version>
  116. <scope>runtime</scope>
  117. </dependency>
  118.  
  119. <!--使用阿里的连接池 -->
  120. <dependency>
  121. <groupId>com.alibaba</groupId>
  122. <artifactId>druid</artifactId>
  123. <version>1.0.4</version>
  124. </dependency>
  125.  
  126. <!--mysql connector -->
  127. <dependency>
  128. <groupId>mysql</groupId>
  129. <artifactId>mysql-connector-java</artifactId>
  130. <version>5.1.29</version>
  131. </dependency>
  132.  
  133. </dependencies>
  134.  
  135. <build>
  136. <plugins>
  137. <plugin>
  138. <groupId>org.apache.maven.plugins</groupId>
  139. <artifactId>maven-compiler-plugin</artifactId>
  140. <configuration>
  141. <source>1.7</source>
  142. <target>1.7</target>
  143. </configuration>
  144. </plugin>
  145. </plugins>
  146. </build>
  147.  
  148. </project>

主要结构

HandshakeInterceptor.java

  1. package com.lee.websocket;
  2.  
  3. import java.util.Map;
  4.  
  5. import javax.servlet.http.HttpSession;
  6.  
  7. import org.springframework.http.server.ServerHttpRequest;
  8. import org.springframework.http.server.ServerHttpResponse;
  9. import org.springframework.http.server.ServletServerHttpRequest;
  10. import org.springframework.web.socket.WebSocketHandler;
  11.  
  12. public class HandshakeInterceptor implements org.springframework.web.socket.server.HandshakeInterceptor {
  13.  
  14. //进入hander之前的拦截
  15. @Override
  16. public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
  17. if (request instanceof ServletServerHttpRequest) {
  18. ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
  19.  
  20. String clientName = (String)servletRequest.getServletRequest().getParameter("name");
  21. System.out.println(clientName);
  22.  
  23. HttpSession session = servletRequest.getServletRequest().getSession(true);
  24. // String userName = "lee";
  25. if (session != null) {
  26. //使用userName区分WebSocketHandler,以便定向发送消息
  27. // String clientName = (String) session.getAttribute("WEBSOCKET_USERNAME");
  28. map.put("WEBSOCKET_USERNAME", clientName);
  29. }
  30. }
  31. return true;
  32. }
  33.  
  34. @Override
  35. public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
  36.  
  37. }
  38.  
  39. }

HomeController.java

  1. package com.lee.websocket;
  2.  
  3. import java.text.DateFormat;
  4. import java.util.Date;
  5. import java.util.Locale;
  6.  
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.ui.Model;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RequestMethod;
  13.  
  14. /**
  15. * Handles requests for the application home page.
  16. */
  17. @Controller
  18. public class HomeController {
  19.  
  20. private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
  21.  
  22. /**
  23. * Simply selects the home view to render by returning its name.
  24. */
  25. @RequestMapping(value = "/", method = RequestMethod.GET)
  26. public String home(Locale locale, Model model) {
  27. logger.info("Welcome home! The client locale is {}.", locale);
  28.  
  29. Date date = new Date();
  30. DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
  31.  
  32. String formattedDate = dateFormat.format(date);
  33.  
  34. model.addAttribute("serverTime", formattedDate );
  35.  
  36. return "home";
  37. }
  38.  
  39. @RequestMapping(value = "/chat", method = RequestMethod.GET)
  40. public String chat(Locale locale, Model model) {
  41. return "chat";
  42. }
  43.  
  44. }

WebSocketConfig.java

  1. package com.lee.websocket;
  2.  
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.socket.config.annotation.EnableWebSocket;
  5. import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
  6. import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
  7.  
  8. @Configuration
  9. @EnableWebSocket//开启websocket
  10. public class WebSocketConfig implements WebSocketConfigurer {
  11. @Override
  12. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
  13. registry.addHandler(new WebSocketHander(),"/echo").addInterceptors(new HandshakeInterceptor()); //支持websocket 的访问链接
  14. registry.addHandler(new WebSocketHander(),"/sockjs/echo").addInterceptors(new HandshakeInterceptor()).withSockJS(); //不支持websocket的访问链接
  15. }
  16. }

WebSocketHander.java

  1. package com.lee.websocket;
  2.  
  3. import java.io.IOException;
  4. import java.util.ArrayList;
  5.  
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.web.socket.CloseStatus;
  9. import org.springframework.web.socket.TextMessage;
  10. import org.springframework.web.socket.WebSocketHandler;
  11. import org.springframework.web.socket.WebSocketMessage;
  12. import org.springframework.web.socket.WebSocketSession;
  13.  
  14. public class WebSocketHander implements WebSocketHandler {
  15. private static final Logger logger = LoggerFactory.getLogger(WebSocketHander.class);
  16.  
  17. private static final ArrayList<WebSocketSession> users = new ArrayList<>();
  18.  
  19. //初次链接成功执行
  20. @Override
  21. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  22. logger.debug("链接成功......");
  23. users.add(session);
  24. String userName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");
  25. if(userName!= null){
  26. session.sendMessage(new TextMessage("欢迎来到Nathan的聊天室,我们开始聊天吧!~"));
  27. }
  28. }
  29.  
  30. //接受消息处理消息
  31. @Override
  32. public void handleMessage(WebSocketSession session, WebSocketMessage<?> webSocketMessage) throws Exception {
  33. String clientName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");
  34.  
  35. clientName = "<a onclick='changeChater(this)'>" + clientName + "</a>";
  36.  
  37. String msg = webSocketMessage.getPayload().toString();
  38. String charter = "";
  39.  
  40. String msgs[] = msg.split("\\|");
  41. if (msgs.length > 1) {
  42. msg = msgs[1];
  43. charter = msgs[0];
  44. sendMessageToUser(charter, new TextMessage(clientName + " 悄悄地对你说 :" + msg));
  45. } else {
  46. sendMessageToUsers(new TextMessage(clientName + " 说:" + msg));
  47. }
  48.  
  49. }
  50.  
  51. @Override
  52. public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
  53. if(webSocketSession.isOpen()){
  54. webSocketSession.close();
  55. }
  56. logger.debug("链接出错,关闭链接......");
  57. users.remove(webSocketSession);
  58. }
  59.  
  60. @Override
  61. public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
  62. logger.debug("链接关闭......" + closeStatus.toString());
  63. users.remove(webSocketSession);
  64. }
  65.  
  66. @Override
  67. public boolean supportsPartialMessages() {
  68. return false;
  69. }
  70.  
  71. /**
  72. * 给所有在线用户发送消息
  73. *
  74. * @param message
  75. */
  76. public void sendMessageToUsers(TextMessage message) {
  77. for (WebSocketSession user : users) {
  78. try {
  79. if (user.isOpen()) {
  80. user.sendMessage(message);
  81. }
  82. } catch (IOException e) {
  83. e.printStackTrace();
  84. }
  85. }
  86. }
  87.  
  88. /**
  89. * 给某个用户发送消息
  90. *
  91. * @param userName
  92. * @param message
  93. */
  94. public void sendMessageToUser(String userName, TextMessage message) {
  95. for (WebSocketSession user : users) {
  96. if (user.getHandshakeAttributes().get("WEBSOCKET_USERNAME").equals(userName)) {
  97. try {
  98. if (user.isOpen()) {
  99. user.sendMessage(message);
  100. }
  101. } catch (IOException e) {
  102. e.printStackTrace();
  103. }
  104. break;
  105. }
  106. }
  107. }
  108. }
Person.java
  1. package com.lee.websocket.entity;
  2.  
  3. public class Person {
  4.  
  5. private int age;
  6. private String name;
  7. private String sex;
  8.  
  9. public int getAge() {
  10. return age;
  11. }
  12. public void setAge(int age) {
  13. this.age = age;
  14. }
  15. public String getName() {
  16. return name;
  17. }
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. public String getSex() {
  22. return sex;
  23. }
  24. public void setSex(String sex) {
  25. this.sex = sex;
  26. }
  27.  
  28. }

chat.jsp

  1. <%@ page contentType="text/html; charset=utf-8" language="java" %>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
  6. <!-- 新 Bootstrap 核心 CSS 文件 -->
  7. <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
  8. <!-- 可选的Bootstrap主题文件(一般不用引入) -->
  9. <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
  10. <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
  11. <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
  12. <!--<script type="text/javascript" src="js/jquery-1.7.2.js"></script>-->
  13. <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  14. <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  15. <title>webSocket测试</title>
  16. <script type="text/javascript">
  17. var chater;
  18.  
  19. $(function(){
  20.  
  21. var websocket;
  22. function connectServer() {
  23. var clientName = $("#client_name").val();
  24. if ("WebSocket" in window) {
  25. websocket = new WebSocket("ws://127.0.0.1:8080/websocket/echo?name=" + clientName);
  26. } else if ("MozWebSocket" in window) {
  27. alert("MozWebSocket");
  28. websocket = new MozWebSocket("ws://echo");
  29. } else {
  30. alert("SockJS");
  31. websocket = new SockJS("http://127.0.0.1:8080/websocket/sockjs/echo");
  32. }
  33. }
  34.  
  35. // websocket.onopen = function (evnt) {
  36. // $("#tou").html("链接服务器成功!")
  37. // };
  38. // websocket.onmessage = function (evnt) {
  39. // $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
  40. // };
  41. // websocket.onerror = function (evnt) {
  42. // };
  43. // websocket.onclose = function (evnt) {
  44. // $("#tou").html("与服务器断开了链接!")
  45. // }
  46.  
  47. $("#conncet_server").bind("click", function() {
  48. connectServer();
  49.  
  50. websocket.onopen = function (evnt) {
  51. $("#tou").html("链接服务器成功!")
  52. };
  53. websocket.onmessage = function (evnt) {
  54. $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
  55. };
  56. websocket.onerror = function (evnt) {
  57. };
  58. websocket.onclose = function (evnt) {
  59. $("#tou").html("与服务器断开了链接!")
  60. }
  61. });
  62.  
  63. $("#send").bind("click", function() {
  64. send();
  65. });
  66.  
  67. function send(){
  68. if (websocket != null) {
  69. var message = document.getElementById("message").value;
  70.  
  71. if ($.trim(chater) != "") {
  72. message = chater + "|" + message;
  73. }
  74.  
  75. websocket.send(message);
  76. } else {
  77. alert("未与服务器链接.");
  78. }
  79. }
  80. });
  81.  
  82. function changeChater(e) {
  83. chater = $(e).html();
  84. alert("您将和" + chater + "进行聊天...");
  85. }
  86. </script>
  87.  
  88. </head>
  89. <body>
  90.  
  91. <div class="page-header" id="tou">webSocket及时聊天Demo程序</div>
  92. <div class="well" id="msg"></div>
  93. <div class="col-lg">
  94. <div class="input-group">
  95. <input type="text" class="form-control" placeholder="请输入用户名..." id="client_name">
  96. <span class="input-group-btn">
  97. <button class="btn btn-default" type="button" id="conncet_server">连接服务器</button>
  98. </span>
  99. </div>
  100. </div>
  101.  
  102. <br/>
  103.  
  104. <div class="col-lg">
  105. <div class="input-group">
  106. <input type="text" class="form-control" placeholder="发送信息..." id="message">
  107. <span class="input-group-btn">
  108. <button class="btn btn-default" type="button" id="send">发送</button>
  109. </span>
  110. </div>
  111. </div>
  112. </body>
  113.  
  114. </html>
 
有兴趣的朋友可以关注github地址:https://github.com/leechenxiang/maven-spring-websocket-01

基于Spring 4.0 的 Web Socket 聊天室/游戏服务端简单架构的更多相关文章

  1. socket聊天室(服务端)(多线程)(TCP)

    #include<string.h> #include<signal.h> #include<stdio.h> #include<sys/socket.h&g ...

  2. 重构 JAVA 聊天室 —— CS 模式的简单架构实现

    前言 自从开始弄起数据挖掘之后,已经很久没写过技术类的博客了,最近学校 JAVA 课设要求实现一个聊天室,想想去年自己已经写了一个了,但是有些要求到的功能我也没实现,但看着原有的代码想了想加功能好像有 ...

  3. JAVA-Socket通信 打造属于自己的聊天室(服务端)

    我们每天都在使用着微信.QQ等聊天软件,但不知你是否有想过这些聊天软件是如何实现的?是否想过要制作一个属于自己的聊天室? 本篇博客将带你打造一个简单的属于自己的聊天室,将cmd作为聊天窗口,可通过内网 ...

  4. 基于spring boot2.0+spring security +oauth2.0+ jwt微服务架构

    github地址:https://github.com/hankuikuide/microservice-spring-security-oauth2 项目介绍 该项目是一个演示项目,主要演示了,基于 ...

  5. DispatcherServlet和ContextLoaderListener,还有spring+servlet3.0 无web.xml启动问题

    上篇提到: 关于spring +springmvc中两个spring应用上下文(DispatcherServlet和ContextLoaderListener)的问题,挺让人迷糊的. 他们都是加载Be ...

  6. 转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端

    from: http://ybak.iteye.com/blog/1853335 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端 游戏服 ...

  7. Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

    这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...

  8. 基于tcp和多线程的多人聊天室-C语言

    之前在学习关于网络tcp和多线程的编程,学了知识以后不用一下总绝对心虚,于是就编写了一个基于tcp和多线程的多人聊天室. 具体的实现过程: 服务器端:绑定socket对象->设置监听数-> ...

  9. python socket 聊天室

    socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...

随机推荐

  1. utc时间转换成标准时间

    把这个时间 /Date(1484884647943+0800)/ 转成标准时间 String str = String.format("%tF %<tT", 14848846 ...

  2. 【oracle】dblink创建

    目的:oracle中跨数据库查询 两台数据库服务器db_A(本地)和db_B(远程192.168.1.100),db_A下用户user_a 需要访问到db_B下user_b的数据 解决:查询得知使用d ...

  3. HTTP和Socket的区别

    1: HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用. HTTP ...

  4. HTTP Content-type整理

    文件扩展名 Content-Type(Mime-Type) 文件扩展名 Content-Type(Mime-Type) .*( 二进制流.不知道下载文件类型) application/octet-st ...

  5. 改进版高速排序(平均复杂度O(NlogN))

    #include<iostream> using namespace std; #define MAXSIZE 21 typedef int SqList[MAXSIZE]; #defin ...

  6. GIS+=地理信息+容器技术(4)——Docker执行

    -------------------------------------------------------------------------------------- Blog:    http ...

  7. 算法笔记_127:蓝桥杯2017模拟赛-本科组习题解答(Java)

     目录 1 算年龄 2 猜算式 3 排列序数 4 字符串比较 5 还款计算 6 滑动解锁 7 风险度量   PS:以下代码部分仅供参考,若有不当之处,还请路过同学指出哦~ 1 算年龄 标题:算年龄 英 ...

  8. 使用 Spring 2.5 TestContext 测试框架

    Spring 2.5 TestContext 测试框架用于测试基于 Spring 的程序,TestContext 测试框架和低版本 Spring 测试框架没有任何关系,是一个全新的基于注解的测试框架, ...

  9. 深入理解索引系列1:B+树

  10. html5之canvas画图 1.写字板功能

     写字板事例:       写字板分析:1.点击鼠标開始写字(onmosedown)2.按下鼠标写字(onmousemove)3.松开鼠标,停下写字(撤销onmousemove事件):       代 ...