websocket是什么?
至于websocket
是什么、有什么用这样的问题一Google一大把,这里我就简要的说些websocket
再本次实例中的作用吧。
由于在本次实例中需要实现的是一个聊天室,一个实时的聊天室。如下图:
采用websocket
之后可以让前端和和后端像C/S模式一样实时通信,不再需要每次单独发送请求。由于是基于H5的所以对于老的浏览器如IE7、IE8之类的就没办法了,不过H5是大势所趋这点不用担心。
后端
既然推出了websocket
,作为现在主流的Java肯定也有相应的支持,所以在JavaEE7
之后也对websocket
做出了规范,所以本次的代码理论上是要运行在Java1.7
+和Tomcat7.0+
之上的。
看过我前面几篇文章的朋友应该都知道本次实例也是运行在之前的SSM之上的,所以这里就不再赘述了。
首先第一步需要加入websocket
的依赖:
< dependency> < groupid>javax.websocket< /groupid> < artifactid>javax.websocket-api< /artifactid> < version>1.1< /version> < /dependency> < dependency> < groupid>org.springframework< /groupid> < artifactid>spring-websocket < version>${spring.version}< /version> < /dependency>
以上就是使用websocket
所需要用到的包。spring-websocket
这个主要是在之后需要在websocket
的后端注入service
所需要的。
之后再看一下后端的核心代码MyWebSocket.java
package com.crossoverJie.controller; /** * Created by Administrator on 2016/8/7. */ import com.crossoverJie.pojo.Content; import com.crossoverJie.service.ContentService; import org.apache.camel.BeanInject; import org.apache.camel.EndpointInject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.web.context.support.SpringBeanAutowiringSupport; import org.springframework.web.socket.server.standard.SpringConfigurator; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CopyOnWriteArraySet; import javax.annotation.PostConstruct; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; //该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。 /** 类似Servlet的注解mapping。无需在web.xml中配置。 * configurator = SpringConfigurator.class是为了使该类可以通过Spring注入。 */ @ServerEndpoint(value = "/websocket",configurator = SpringConfigurator.class) public class MyWebSocket { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; public MyWebSocket() { } @Autowired private ContentService contentService ; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 // 若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet(); //与客户端的连接会话,需要通过它来给客户端发送数据 private Session session; /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ @OnOpen public void onOpen(Session session){ this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose(){ webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("来自客户端的消息:" + message); //群发消息 for(MyWebSocket item: webSocketSet){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("发生错误"); error.printStackTrace(); } /** * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ //保存数据到数据库 Content content = new Content() ; content.setContent(message); SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd HH:mm:dd") ; content.setCreateDate(sm.format(new Date())); contentService.insertSelective(content) ; this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { MyWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { MyWebSocket.onlineCount--; } }
这就是整个websocket
的后端代码。看起来也比较简单主要就是使用那几个注解。每当有一个客户端连入、关闭、发送消息都会调用各自注解的方法。这里我讲一下sendMessage()
这个方法。