需求:就是當后台操作完大量的數據之后,需要通知前端修改狀態,於是第一時間想到了使用WebSocket。
概念的話這里就不解釋了。
直接貼上我的代碼,在springBoot中的使用。
首先在pom.xml中加入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
將配置類加入容器管理
@Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
websocket服務端
@ServerEndpoint("/websocket/submitOnline")
@Component
public class WebSocketServer {
private Logger log = Logger.getLogger("webSocketServer");
private static Map<String, Session> clients = new ConcurrentHashMap<>();
@Autowired
private AdsMsgPlanService adsMsgPlanService;
public static WebSocketServer webSocketServer;
@PostConstruct
public void init(){
webSocketServer = this;
webSocketServer.adsMsgPlanService = this.adsMsgPlanService;
}
@OnOpen
public void onOpen(Session session) throws InterruptedException {
log.info("有新客戶端連接了"+session.getId());
clients.put(session.getId(),session);
}
@OnClose
public void onClose(Session session){
log.info("有用戶斷開了"+session.getId());
clients.remove(session.getId());
}
@OnError
public void onError(Throwable throwable){
throwable.printStackTrace();
}
@OnMessage
public void onMessage(String message){
log.info("服務端收到客戶端發來的消息"+message);
//這里是我自己的業務邏輯
Result result = null;
try {
SubmitOnlineVo submitOnlineVo = new SubmitOnlineVo();
submitOnlineVo.setId(Integer.parseInt(message));
submitOnlineVo.setStatus(PlanStatusConstant.ATONLINE);
Integer i = webSocketServer.adsMsgPlanService.updatePlan(submitOnlineVo);
if(i==-1){
result = new Result(BusinessConstant.SYSTEM_ERROR_CODE, "上線人數超過30萬!!!", i);
}else if(i==0){
result = new Result(BusinessConstant.SYSTEM_ERROR_CODE, "修改失敗", i);
}else{
Map<String,String> map = new HashMap<>();
map.put("id",message);
map.put("status","上線待投放");
result = new Result(BusinessConstant.SYSTEM_SUCESS_CODE, "修改成功", map);
}
this.sendAll(JSON.toJSONString(result));
}catch (Exception e){
e.printStackTrace();
result = new Result(BusinessConstant.SYSTEM_ERROR_CODE, e.getMessage(), null);
this.sendAll(JSON.toJSONString(result));
}
}
private void sendAll(String message){
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
sessionEntry.getValue().getAsyncRemote().sendText(message);
}
}
}
客戶端代碼(前端並不是我寫的,只是自己測試的時候寫的一個簡單頁面)
<html> <head></head> <body> <div id="messageId"></div> <script> var socket; if(typeof(WebSocket) == "undefined") { console.log("您的瀏覽器不支持WebSocket"); }else{ console.log("您的瀏覽器支持WebSocket"); //實現化WebSocket對象,指定要連接的服務器地址與端口 建立連接 socket = new WebSocket("ws://localhost:8080/websocket/submitOnline"); //打開事件 socket.onopen = function() { console.log("Socket 已打開"); socket.send("dfgh"); }; //獲得消息事件 socket.onmessage = function(msg) { console.log(msg.data); //發現消息進入 開始處理前端觸發邏輯 let msgDiv = document.getElementById("messageId"); msgDiv.innerHTML += msg.data; }; //關閉事件 socket.onclose = function() { console.log("Socket已關閉"); }; //發生了錯誤事件 socket.onerror = function() { alert("Socket發生了錯誤"); //此時可以嘗試刷新頁面 } } </script> </body> </html>
這個時候一個websocket已經搭建好了,但是這個時候的安全性存在問題.
因為是ws,就類似於http嘛,所以就想弄成wss的,也就是https
然后我這邊通過jdk生成一個密鑰來在本地實現一個https.
在cmd中輸入(要配置了jdk的環境變量)
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
參數就不一一解釋了.
然后會在c盤/用戶/當前用戶文件夾下生成一個keystore.p12的文件.

將它放到項目的resources目錄下,然后在application.properties文件中加入如下配置
server.port=8443 server.ssl.enabled=true server.ssl.key-store=classpath:keystore.p12 server.ssl.key-store-password=ouyang(你在cmd中輸入的密碼) server.ssl.key-store-type=PKCS12 server.ssl.key-alias=tomcat
然后一個配置類(允許http和https請求同時存在,將http轉發到https)
@Configuration public class ConnectorConfig { @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*");//設置所有路徑都配置https securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; tomcat.addAdditionalTomcatConnectors(getHttpConnector()); return tomcat; } private Connector getHttpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(8080); connector.setSecure(false); connector.setRedirectPort(8443); return connector; } }
如果要在postman中測試還需要關閉ssl certificate verification

這時候我們就可以將客戶端的websocket代碼改成wss來保證安全性了,當然這只是本地測試,在實際的生產環境應該都是https協議,所以直接使用wss就行。
