WebSocketServer.java
package com.ws.wstest.websockeet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ws.wstest.model.TalkInfo;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//接收sid
private String sid="";
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session,@PathParam("sid") String sid) {
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
this.sid=sid;
try {
sendMessage("连接成功");
} catch (IOException e) {
System.out.println("websocket IO异常");
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到来自窗口"+sid+"的信息:"+message);
TalkInfo talkInfo= JSON.parseObject(message,new TypeReference<TalkInfo>(){});
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
if(item.sid.equals(talkInfo.getReceiverId())){
sendInfo(message,talkInfo.getReceiverId());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发自定义消息
* */
public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
System.out.println("推送消息到窗口"+sid+",推送内容:"+message);
for (WebSocketServer item : webSocketSet) {
try {
//这里可以设定只推送给这个sid的,为null则全部推送
if(sid==null) {
item.sendMessage(message);
}else if(item.sid.equals(sid)){
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
WebSocketConfig.java
package com.ws.wstest.websockeet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
* @author zhengkai
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WstestApplication.java
package com.ws.wstest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SpringBootApplication
public class WstestApplication {
public static void main(String[] args) {
SpringApplication.run(WstestApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")//可访问ip,ip最好从配置文件中获取,*代表所有ip都能访问
.allowedMethods("PUT", "DELETE", "GET", "POST")
.allowedHeaders("*")
.exposedHeaders("access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin",
"access-control-max-age",
"X-Frame-Options")
.allowCredentials(false).maxAge(3600);
}
};
}
}
TalkInfo.java
package com.ws.wstest.model;
import com.ws.wstest.Utils.Utils;
public class TalkInfo {
private String sendId;
private String receiverId;
private String time;
private long timestamp;
private String TalkContent;
public String getSendId() {
return sendId;
}
public void setSendId(String sendId) {
this.sendId = sendId;
}
public String getReceiverId() {
return receiverId;
}
public void setReceiverId(String receiverId) {
this.receiverId = receiverId;
}
public String getTime() {
return Utils.stampToDate(timestamp);
}
public void setTime(String time) {
this.time = time;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getTalkContent() {
return TalkContent;
}
public void setTalkContent(String talkContent) {
TalkContent = talkContent;
}
}
Utils.java
package com.ws.wstest.Utils;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Utils {
public static String stampToDate(String s){
long lt = new Long(s);
return stampToDate(lt);
}
public static String stampToDate(long timestamp){
Date date = new Date(timestamp);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(date);
}
}
Server.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.min.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
if (typeof (WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
$("#btnSend").click(function() {
var id= 6;
url="http://localhost:8080/checkcenter/socket/push/";
content=$("#et_content").val()
// content="黄金";
// turl=url+id+"?message="+content ;
turl=url+id+"?message="+content ;
fetch(turl);
// fetch(url);
etext="";
var txt1=document.getElementById("et_content");
txt1.value="";
// txt1.focus();
//
// $("#et_content").value=etext;
// $("#et_content").text(etext);
});
$("#btnClose").click(function() {
});
}
});
</script>
</head>
</body>
<textarea type="text" id="et_content" style="width:500px; height:300px;" >
</textarea >
<br>
<br>
<br>
<button id="btnSend">发送消息</button>
----------------------
<button id="btnClose">关闭连接</button>
</body>
</html>
whtml.html
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!--<script src="https://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.min.js"></script>-->
<!--<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>-->
<!--<script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>-->
<script src="http://cdn.jsdelivr.net/sockjs/1.0.1/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script>
<!--<script type="text/javascript" th:src="@{/js/sockjs.min.js}"></script>-->
<!--<script type="text/javascript" th:src="@{/js/stomp.js}"></script>-->
<!--<script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>-->
<script type="text/javascript" >
$(function() {
if (typeof (WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
// var id= (parseInt(Math.random()*16));
var id= 5;
var socket = new WebSocket("ws://408e1ad.nat123.cc/websocket/"+id);
//打开事件
socket.onopen = function() {
console.log("webSocket 已打开");
$('#tvH6').text("webSocket 已打开");
//socket.send("这是来自客户端的消息" + location.href + new Date());
};
//获得消息事件
var wmsg="";
socket.onmessage = function(msg) {
console.log(msg.data);
$("#tvH6").value=msg.data;
document.getElementById("btnClose").innerHtml=msg.data;
wmsg=msg.data+"\n";
$('#tvH6').text(wmsg);
//发现消息进入 调后台获取
//getCallingList();
};
//关闭事件
socket.onclose = function() {
console.log("webSocket已关闭");
$('#tvH6').text("会话被关闭");
};
//发生了错误事件
socket.onerror = function() {
console.log("webSocket发生了错误");
}
/* $(window).unload(function() {
socket.close();
}); */
$("#btnSend").click(function() {
// socket.send("这是来自客户端的消息" + new Date());
content=$("#et_content").val();
var sendMsg={
receiverId:"6",
sendId:id,
talkContent:content,
timestamp:Date.parse(new Date())/1000
};
var jsonString=JSON.stringify(sendMsg);
socket.send(jsonString);
console.log("这是来自客户端的消息" + new Date());
});
$("#btnOpen").click(function () {
// socket.
})
$("#btnClose").click(function() {
socket.close();
});
}
});
</script>
<style type="text/css">
body{font-size:12px;}
p,div{margin:0;padding:0}
.textarea{
width:500px;height:300px;position:absolute;background:none;z-index:9
}
.note{
position:absolute;line-height:20px;padding:3px 5px;
}
</style>
</head>
<body>
<div style="position:relative;">
<textarea id="et_content" class="textarea" onfocus="document.getElementById('note').style.display='none'" onblur="if(value=='')document.getElementById('note').style.display='block'"></textarea>
<div id="note" class="note">
<font color="#777">在这里写入你要发送的消息</font>
</div>
</div>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<Br>
<button id="btnSend">推送消息</button>
----------------------
<button id="btnOpen">打开连接</button>
----------------------
<button id="btnClose">关闭连接</button>
<H6 id="tvH6">
未初始化
</H6>
</body>
</html>
CheckCenterController.java
package com.ws.wstest.websockeet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
@Controller
@RequestMapping("/checkcenter")
public class CheckCenterController {
//页面请求
@GetMapping("/socket/{cid}")
public ModelAndView socket(@PathVariable String cid) {
ModelAndView mav=new ModelAndView("/socket");
mav.addObject("cid", cid);
return mav;
}
// 推送数据接口
@ResponseBody
@RequestMapping("/socket/push/{cid}")
public String pushToWeb(@PathVariable String cid,String message) {
try {
WebSocketServer.sendInfo(message,cid);
} catch (IOException e) {
e.printStackTrace();
return cid+"#"+e.getMessage();
}
return cid;
}
@RequestMapping("/whtml")
public String whtml(){
return "whtml";
}
}
安卓上主要
package com.example.wanghuanlong.websocketdemo;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.example.wanghuanlong.websocketdemo.adapter.TalkAdapter;
import com.example.wanghuanlong.websocketdemo.model.TalkInfo;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
TextView tv_main;
EditText et_main;
Button btn_main;
ListView lv_talk_content;
int id = 6;
List<TalkInfo> list;
TalkAdapter talkAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();//隐藏掉整个ActionBar,包括下面的Tabs
tv_main = findViewById(R.id.tv_main);
et_main = findViewById(R.id.et_main);
btn_main = findViewById(R.id.btn_main);
lv_talk_content = findViewById(R.id.lv_talk_content);
list=new ArrayList<>();
talkAdapter=new TalkAdapter(list,this);
lv_talk_content.setAdapter(talkAdapter);
connect();
findViewById(R.id.btn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mWebSocket != null) {
long timeStamp = Calendar.getInstance().getTimeInMillis();
TalkInfo info = new TalkInfo();
info.setSendId(id + "");
info.setReceiverId(5 + "");
info.setTimestamp(timeStamp);
info.setTalkContent(et_main.getText().toString());
list.add(info);
talkAdapter.setList(list);
talkAdapter.notifyDataSetChanged();
String msg= JSON.toJSONString(info);
mWebSocket.send(msg);
et_main.setText("");
}
}
});
}
private void connect() {
EchoWebSocketListener listener = new EchoWebSocketListener();
Request request = new Request.Builder()
.url("ws://408e1ad.nat123.cc/websocket/" + id)
.build();
OkHttpClient client = new OkHttpClient();
client.newWebSocket(request, listener);
client.dispatcher().executorService().shutdown();
}
private String tStr = "";
private WebSocket mWebSocket;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 200:
tv_main.setText(tStr);
try
{
TalkInfo info=JSON.parseObject(tStr,new TypeReference<TalkInfo>(){});
list.add(info);
talkAdapter.setList(list);
talkAdapter.notifyDataSetChanged();
}catch (Exception e){
}
break;
}
}
};
private class EchoWebSocketListener extends WebSocketListener {
@Override
public void onOpen(WebSocket webSocket, Response response) {
mWebSocket = webSocket;
// webSocket.send("hello world");
// webSocket.send("welcome");
// webSocket.send(ByteString.decodeHex("adef"));
// webSocket.close(1000, "关闭");
}
@Override
public void onMessage(WebSocket webSocket, String text) {
Log.e("onMessage", "onMessage: " + text);
tStr = text;
mHandler.sendEmptyMessage(200);
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
Log.e("onMessage", "onMessage byteString: " + bytes);
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
Log.e("onMessage", "onClosing: " + code + "/" + reason);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
Log.e("onMessage", "onClosed: " + code + "/" + reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
Log.e("onMessage", "onFailure: " + t.getMessage());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mWebSocket != null)
mWebSocket.close(9146, "onDestroy");
}
}