IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE,sockjs-1.1.1,stomp-1.2搭建基于Tomcat-7.0.68的WebSocket应用

接着上文IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE搭建基于Tomcat-7.0.68的WebSocket应用

上文的最后我们说到,WebSocket是需要定时心跳的,否则会在一段时间后自动断开连接,而更重要的是,不是所有的浏览器都支持WebSocket,早期的IE 10之前的版本就是不支持的,而这一部分的设备其实是不算少的,而sockjs的出现,恰恰好来解决了这个问题。对于不支持WebSocket的浏览器,sockjs使用了多种方式来兼容这种情况,包括使用长轮询等方式,Spring更是内建支持这种方式。

下面我们看如何在上篇文章的基础上,增加对于sockjs的支持。

首先是STOMP的文档官网地址 http://stomp.github.io/
代码的地址为https://github.com/jmesnil/stomp-websocket,项目下面的lib/stomp.js就是我们想要的文件。也可以本站下载stomp.js.zip

接下来sockjs的代码地址https://github.com/sockjs/sockjs-client,项目下面的dist/sockjs-1.1.1.js就是我们想要的文件。也可以本站下载sockjs-1.1.1.js.zip

接下来我们把下载到的文件放到我们工程目录下面的web->resources->javascript目录下面,如下图:

stomp-websockjs-resources

接下来,添加我们需要的com.fasterxml.jackson.core:jackson-annotations:2.8.1,com.fasterxml.jackson.core:jackson-core:2.8.1,com.fasterxml.jackson.core:jackson-databind:2.8.1这三个jar包,增加的方式参照上一篇中对于javax.servlet:javax.servlet-api:3.1.0的操作方法。与上一篇的操作不同的是,这次添加的三个jar包,都要放到编译完成后的War包中。最后的结果如下图:
ToolsJacksonMaven

ToolsJacksonMavenWar

下面,我们开始进行代码的操作,我们在上篇文章中的src->Tools->WebSocket中新增两个源代码文件SockJsController.java,WebJsSocketConfig.java.如下图:

NewJavaSourcesForSockjs

其中的代码如下:
SockJsController.java

WebJsSocketConfig.java

然后修改WebSocket.jsp

最后,我们修改web->WEB-INF->web.xml,在其中增加

修改后的最终结果如下:

参考链接


 

Android Studio 2.1.3配置Robolectric-3.0,Powermock-1.6.5单元测试环境

Android Studio提供了比较方便的单元测试,但是由于Android系统的限制(ClassloaderGoogle自己实现的,Powermock无法修改底层的bytecode),目前Powermock还没办法直接在设备上执行测试,但是我们代码中难免存在一些静态对象,需要测试的时候,只能求助于PowermockRobolectric的组合。
具体的配置如下:
1.首先在需要测试的项目的build.gradle中声明需要使用PowermockRobolectric

2.定义测试基类,在基类中声明一些必备的设置
AbsRobolectricPowerMockTest.java

3.定义真正的测试子类
DeckardActivityTest.java

注意,参考链接中的内容不可完全相信,按照参考链接中的配置(Robolectric-3.1.2+PowerMock-1.6.5),一般会遇到如下问题(看上去很怪异,其实是由于不同的classloader同时加载了相同的类,导致尽管类名是相同的,但是依旧无法进行类型转换):

参考链接


Gradle本站镜像

使用Android Studio开发,最痛苦的其中一项是Maven下载数据缓慢,目前已经可以根据在Ubuntu 14.04 系统中的Apache Tomcat上部署Apache Archiva 2.2.1来使用本站的代理服务器的方式进行提速了。另一个痛苦的事情就是下载Gradle工具包的速度异常缓慢了,不仅慢,而且还容易失败。
目前本网站已经提供了Gradle工具包的下载代理,具体的操作就是把services.gradle.org进行域名污染,指向本站的IP地址121.199.27.227
Windows下的解决方法为修改C:\Windows\System32\drivers\etc下的hosts文件,里面增加如下内容:

接着修改Android Studio项目下的gradle\wrapper\gradle-wrapper.properties文件,把其中的

修改为:

注意,上面的修改其实主要是把HTTPS修改成了HTTP,原因在于HTTPS无法进行域名污染。

当然,另外一个比较简单的修改方式为,只要修改distributionUrl为本站地址,更加省事:

目前本站提供的Gradle工具包版本如下:

当前更建议大家使用 腾讯的国内镜像 https://mirrors.cloud.tencent.com/gradle/

参考链接


gradle不同版本下载太慢---腾讯做了国内镜像可以直接下载

使用junit测试IntelliJ IDEA 2016.2建立的maven项目

maven project项目中引入junit插件并不困难,只需要在pom.xml中配置好依赖包即可(IDE环境下,依赖项会自动生成)。另外,test类文件需要按照/src/main/java/的文件结构(main改为test)。
pom.xml

如下图:

mavenjunitpath

Ubuntu 16.04下Tomcat 7.0.68启动服务时候报告“java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;”

在使用Ubuntu16.04 安装openjdk-7-jdk介绍的方式切换Java1.7版本后,在进行代码调试的时候,Tomcat 7.0.68报告如下错误:

这说明Ubuntu 16.04下的Tomcat是在Java 8环境下面编译的,尽管我们已经切换到Java 7下面了,但是Tomcat并不能很好的执行我们的Java 7代码。这个时候的解决方法就是,编译代码的时候指定Java 7,但是在Tomcat执行的时候,指定使用Java 8来运行。

参考链接


Java error java.util.concurrent.ConcurrentHashMap.keySet

IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE搭建基于Tomcat-7.0.68的WebSocket应用

先参照 IntelliJ IDEA 2016.1建立Strut2工程并使用Tomcat调试建立新的工程,一步一步操作,包括最后引用Spring框架部分。

经过上面的操作,Spring-WebSocket的包应该已经被默认引入了,如下图所示:

spring-websocket-release-lib

这就意味着我们已经不需要再进行过多的额外配置了。

接下来,我们在src->Tools下面新建一个WebSocket的目录,里面创建三个Java文件。如下图:
WebSocketJavaSourceList

每个文件中的代码如下:
SystemWebSocketHandler.java

WebSocketConfig.java

WebSocketHandshakeInterceptor.java

由于我们使用了Struts2导致我们的网络请求优先被Struts2的拦截器拦截,而Struts2又处理不了websocket请求,结果直接返回了404错误。因此我们需要替换掉默认的在web.xml中定义的Struts2的拦截器,要求Struts2不处理websocket请求。
我们在src->Tools下面新建一个Filter的目录,下面创建一个名为StrutsPrepareAndExecuteFilterEx.java的源代码文件,如下图:

StrutsPrepareAndExecuteFilterEx
具体的代码如下:
StrutsPrepareAndExecuteFilterEx.java

这时候的代码是无法编译通过的,原因是依赖的javaxJar包不存在。此时,我们需要手工引入javax.servlet:javax.servlet-api:3.1.0这个Jar包。如下图:

ToolWebSocketProjectStructure

ToolWebSocketProjectStructureAddJars

ToolWebSocketProjectStructureAddJarsFromMaven

ToolWebSocketProjectStructureAddJarsFromMavenJavaxServerletApi3.1.0

ToolWebSocketProjectStructureAddJarsFromMavenJavaxServerletApi3.1.0Add

ToolWebSocketProjectStructureAddJarsFromMavenJavaxServerletApi3.1.0AddApply

还要注意,刚刚添加进入的javax.servlet:javax.servlet-api:3.1.0这个Jar包,我们只在编译期间使用,在运行时候,使用Tomcat自己实现的那个同名Jar包。也就是这个包是个Provided,而不是Compile关系,具体如下图:

ToolWebSocketProjectStructureKeepOutsideWar

接下来,修改web.xml指定Struts2的拦截器为我们定义的拦截器

修改为

经过上面的修改后,依旧是没办法进行网络访问的,原因是web.xml中的Spring拦截器并没有拦截WebSocket的数据请求。

修改为

注意增加的

下一步,配置Spring的配置文件web->WEB-INF->dispatcher-servlet.xml增加配置信息类的扫描目录包含我们刚刚创建的src->Tools->WebSocket的目录(缺少这一步会导致我们通过注解实现的配置信息类没有被自动加载,导致无法访问),修改后的内容如下:

最后,调用的页面的代码
WebSocket.jsp

最后的客户端显示效果如下图所示:
WebSocketJsp

注意:如此创建的WebSocket是会在两三分钟后主动断开连接的,原因在于WebSocket需要周期性的发送心跳报文来维持连接。后续我们会尝试使用sockjs来实现自动发送心跳的逻辑。

具体的sockjs的接入方法,参考IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE,sockjs-1.1.1,stomp-1.2搭建基于Tomcat-7.0.68的WebSocket应用

Ubuntu16.04 安装openjdk-7-jdk

Ubuntu16.04的安装源已经默认没有openjdk7了,所以要自己手动添加仓库,如下:

# 1. oracle openjdk ppa source

# 2. oracle java jdk ppa source

JDK6 :

JDK 7:

JDK 8:

如果安装成功之后还是不能用可能不有多个版本,选的不对

选出正确的版本

参考链接


Ubuntu16.04 安装openjdk-7-jdk

Windows 7下WireShark抓取127.0.0.1(Loopback)报文

1.如果已经安装了WireShark,并且使用的是WinPacp,那么需要先卸载WireShark

2.WireShark的版本号必须是高于1.12.81.99.9,建议使用2.0.5以上的版本。下载地址为:https://www.wireshark.org/download/注意:一定要使用这个链接,从首页点击进入的页面下载的时候,会错误的定位到一个不正常的CDN服务器上,导致下载速度极慢。也可以在本站下载:Wireshark-win64-2.0.5

3.下载并且安装最新的Npcap,下载链接地址https://github.com/nmap/npcap/releases,为了防止出现被墙的问题,也可以在本服务器下载:npcap-0.08-r4

安装的时候,需要勾选"Install Npcap in WinPcap API-compatible Mode",否则WireShark是没办法识别到Npcap是否已经安装。

4.WireShark启动之后选择"Npcap Loopback Adapter"进行抓包。如下图:

WireSharkAdapterSel

5.目前遇到的问题就是Npcap还不够稳定,有线情况下,基本都是正常的,但是在WiFi情况下的公司网络中,有时候会导致无法访问网络。此时的解决方法是在出口网卡属性中禁用(不需要在全部网卡中禁用,只需要在出口网卡中禁用即可)。

DisableNpcapWFPDriver

参考链接


在VC中用CMarkup类操纵XML

首先到http://www.firstobject.com/dn_markup.htm上面下载CMarkup类,将CMarkup.cppCMarkup.h导入到我们的工程中就可以了。编译可能会出现问题,解决的方法是在CMarkup.cpp的开头加上#include,或者关闭预编译也可以。

1.创建一个XML文档

对于创建一个XML文档,需要实例化一个CMarkup对象,并调用AddElem创建根元素。在这个位置,如果你调用AddElem("School"),文档会简单的装一个空元素. 然后调用AddChildElem在根元素的下面创建元素。

效果如下:

2.浏览特定元素

//***********************这样也可以*****************************/

//*********************或者这样也可以*************************/

//***********结果**************

3.修改元素
//把Department为"English"改为"Chinese"

效果如下:

4.添加
4.1 添加在最后面(用AddElem

效果如下:

4.2 添加在最前面(用InsertElem

效果如下:

5.删除

效果如下:

上面的例子都是不带属性的,下面举一个带有属性的例子。
1.生成XML文档

效果如下:

2.查找特定属性

3.修改特定属性

效果如下:

参考链接


在VC中用CMarkup类操纵XML