后台代码
package com.ctsh.iamnav.payPayment.webService;
import com.ctsh.iamnav.dao.BillAdjDao;
import com.ctsh.iamnav.utils.JsonHelperUtil;
import com.ctsh.iamnav.utils.SecurityXMLServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ContextLoader;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
@ServerEndpoint("/websocket/{id}/{connectFlag}")
public class WebSocket {
/**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0;
/**
* 创建一个线程安全的map
*/
private static Map<Long, List<WebSocket>> users = Collections.synchronizedMap(new HashMap());
// private static Map<Long,WebSocket> users = Collections.synchronizedMap(new HashMap());
/**
* 创建一个线程安全的List
*/
private static List<WebSocket> webSocketList = Collections.synchronizedList(new ArrayList<>());
private static CopyOnWriteArraySet<WebSocket> webSocketSet=new CopyOnWriteArraySet<>();
private static Log log = LogFactory.getLog(JsonHelperUtil.class);
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 线程类,监听843端口
*/
// private SecurityXMLServer securityXMLServer = new SecurityXMLServer();
// private Thread thread = new Thread(securityXMLServer);
/**
* 线程池
*/
// private static ExecutorService executorService = new ThreadPoolExecutor(5,5,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
// private ExecutorService threadPool = Executors.newCachedThreadPool();
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 放入map中的key,用来表示该连接对象
*/
private Long posId;
private String successMsg;
public static void setApplicationContext(ApplicationContext applicationContext) {
WebSocket.applicationContext = applicationContext;
}
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session,@PathParam("id") Long theFrontDesk,@PathParam("connectFlag") String connectFlag) {
System.out.println("into onOpen webSocket theFrontDesk:" + theFrontDesk + "connectFlag " + connectFlag);
log.info("into onOpen webSocket theFrontDesk:" + theFrontDesk + "connectFlag " + connectFlag);
/**
* 如果是0代表是销账传递的参数
* 如果是1代表是预存款传递的参数
* 如果是2代表POS机交易回退
*/
if(!("cf").equals(connectFlag) && !("ad").equals(connectFlag) && !("rd").equals(connectFlag)){
if("0".equals(connectFlag)){
successMsg = "cf连接成功";
}else if("1".equals(connectFlag)){
successMsg = "ad连接成功";
}else if("2".equals(connectFlag)){
successMsg = "rd连接成功";
}
}
//调用方法 这段代码不要删,删了就完蛋
SecurityXMLServer securityXMLServer = new SecurityXMLServer();
this.session=session;
if(null != theFrontDesk && 0!= theFrontDesk){
// SecurityXMLServer securityXMLServer = new SecurityXMLServer();
securityXMLServer.createServerSocket(843);
this.posId = theFrontDesk;
executorService.submit(securityXMLServer);
}else{
ApplicationContext ac = ContextLoader.getCurrentWebApplicationContext();
PayPaymentService payPaymentService = (PayPaymentService) ac.getBean("payPaymentService");
this.posId = payPaymentService.queryPayPosSeq();
}
if(null != users.get(posId)){
webSocketList.add(this);
users.put(posId,webSocketList);
}else{
webSocketList.clear();
webSocketList.add(this);
users.put(posId,webSocketList);
}
addOnlineCount(); //在线数
log.info("into onOpen , now onlineCount : " + getOnlineCount());
try {
this.session.getBasicRemote().sendText(successMsg+posId);
} catch (IOException e) {
log.error("websocket IO exception : "+e);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
SecurityXMLServer securityXMLServer = new SecurityXMLServer();
//从set中删除
users.remove(this.posId);
//关闭正在运行的线程
securityXMLServer.exit = false;
//关闭线程池
executorService.shutdown();
//在线数减1
subOnlineCount();
System.out.println("one connection close,now connection is" + getOnlineCount());
}
/**
* 收到客户端消息后触发的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message) {
log.info("onMessage : " + message);
//群发消息
try {
if (StringUtils.isEmpty(message)){
return ;
}
sendInfo(message);
} catch (IOException e) {
e.printStackTrace();
}
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误 session: "+session);
error.printStackTrace();
}
/**
* 群发自定义消息
*/
public void sendInfo(String message) throws IOException {
for (List<WebSocket> item : users.values()) {
for(WebSocket webSocket : item){
try {
webSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
}
兼容ie8的话,需要开线程监听843端口
package com.ctsh.iamnav.utils;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 用来解决Flash Socket通信的安全策略问题
* 监听843端口
*/
public class SecurityXMLServer implements Runnable {
private ServerSocket server;
private BufferedReader reader;
private BufferedWriter writer;
private String xml;
public volatile boolean exit = true;
public SecurityXMLServer(){
/*String path = "";
//此处的换成相应的读取xml文档的方式如dom或sax
//xml = readFile(path, "UTF-8");
xml = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
createServerSocket(843);*/
}
/*if("0".equals(flag)){
String path = "";
//此处的换成相应的读取xml文档的方式如dom或sax
//xml = readFile(path, "UTF-8");
xml = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
createServerSocket(843);
new Thread(this).start();
}else{
exit = true;
}*/
//启动服务
public void createServerSocket(int port){
try{
xml = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
//连接请求队列中的端口
server = new ServerSocket(port);
System.out.println("listener port:"+port);
}catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(exit){
// System.out.println("test:"+111);
Socket client = null;
try{
//从连接请求队列中取出843连接,开始监听843端口
client = server.accept();
InputStreamReader input = new InputStreamReader(client.getInputStream(), "UTF-8");
reader = new BufferedReader(input);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
writer = new BufferedWriter(outputStreamWriter);
//读取客户端发送的数据
StringBuilder data = new StringBuilder();
int c = 0;
while((c = reader.read())!=-1){
if(c!='\0'){
data.append((char)c);
}else{
break;
}
}
String info = data.toString();
System.out.println("输入请求"+info);
//接收到客户端的请求之后,将策略文件发送出去
if(info.indexOf("<policy-file-request/>") >=0){
writer.write(xml + "\0");
writer.flush();
System.out.println("将安全策略文件发送至: " + client.getInetAddress());
}else{
writer.write("请求无法识别\0");
writer.flush();
System.out.println("请求无法识别: "+client.getInetAddress());
}
client.close();
}catch(Exception e){
e.printStackTrace();
if(client != null){
try {
client.close();
} catch (IOException ex) {
ex.printStackTrace();
}
client = null;
}
}finally{
System.gc();
}
}
}
}
前台代码
function connectTheWebsocket(res){
//初始化socket连接
if (typeof WebSocket != 'undefined') {
alert("您的浏览器支持Websocket通信协议")
}else{
if (!!window.WebSocket && window.WebSocket.prototype.send){
alert("您的浏览器支持Websocket通信协议")
}else{
alert("您的浏览器不支持Websocket通信协议,请联系统一厂商适配人员!")
}
}
//本机测试地址,如果其他开发人员的IP和端口号与这个不相符,修改IP与端口号就可以,注意这里的ip地址不可以写localhost,涉及到网络安全问题。具体自行百度,必须写全你的ip地址
socket = new WebSocket("ws://你的id号:你的端口号/<%=request.getContextPath()%>/websocket/" + id + "/" + connectFlag);
// alert("end ");
socket.onopen = function() {
// alert(1);
socket.send("连接成功"+id+res);
// tag = 1;
};
//获得消息事件
socket.onmessage = function(msg) {
document.getElementById("history").value=msg.data;
socket.close();
};
//关闭事件
socket.onclose = function() {
// alert("Socket已关闭");
};
//错误事件
socket.onerror = function() {
alert("Socket发生了错误");
}
}
页面中需要引入三个js文件,如下,注意先后顺序,放错了会出问题
<script type="text/javascript">
window.WEB_SOCKET_SWF_LOCATION = "<%=request.getContextPath()%>/js/webSocket/WebSocketMain.swf";
</script>
<script type="text/javascript" src="<%= request.getContextPath()%>/js/webSocket/swfobject.js"></script>
<script type="text/javascript" src="<%= request.getContextPath()%>/js/webSocket/web_socket.js"></script>`
然而,我这个在自己和别人电脑上测试虽然兼容ie8了,但是客户电脑上死活无法通讯。。。天杀的客户电脑,我想给他砸了