├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── cn
│ │ └── blingfeng
│ │ └── websocket
│ │ ├── WebsocketApplication.java
│ │ ├── config
│ │ └── WebSocketConfig.java
│ │ ├── controller
│ │ ├── ChatController.java
│ │ └── WebSocketServer.java
│ │ ├── pojo
│ │ ├── ChatResult.java
│ │ ├── Client2ServerMessage.java
│ │ ├── Server2ClientMessage.java
│ │ └── WxLoginResult.java
│ │ └── utils
│ │ ├── FastJsonUtils.java
│ │ └── HttpRequestUtil.java
└── resources
│ ├── application.yml
│ └── templates
│ └── webSocket.html
└── test
└── java
└── cn
└── blingfeng
└── websocket
└── WebsocketApplicationTests.java
/README.md:
--------------------------------------------------------------------------------
1 | 微信小程序匿名聊天后端demo
2 | 小程序连接:https://github.com/itblingfeng/wx-chat
3 |
4 | springboot+websocket的简单整合
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | cn.blingfeng
7 | chat
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | chat
12 | Demo project for Spring Boot
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.0.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-web
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-test
36 | test
37 |
38 |
39 | org.java-websocket
40 | Java-WebSocket
41 | 1.3.0
42 |
43 |
44 |
45 | org.springframework.boot
46 | spring-boot-starter-websocket
47 |
48 |
49 |
50 |
51 | com.alibaba
52 | fastjson
53 | 1.2.15
54 |
55 |
56 |
57 | org.apache.httpcomponents
58 | httpclient
59 | 4.5.3
60 |
61 |
62 |
63 |
64 | org.apache.httpcomponents
65 | httpcore
66 | 4.4.8
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.boot
74 | spring-boot-maven-plugin
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/WebsocketApplication.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class WebsocketApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(WebsocketApplication.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/config/WebSocketConfig.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.socket.server.standard.ServerEndpointExporter;
6 |
7 | @Configuration
8 | public class WebSocketConfig {
9 | @Bean
10 | public ServerEndpointExporter serverEndpointExporter(){
11 | return new ServerEndpointExporter();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/controller/ChatController.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.controller;
2 |
3 | import cn.blingfeng.websocket.pojo.ChatResult;
4 | import cn.blingfeng.websocket.pojo.WxLoginResult;
5 | import cn.blingfeng.websocket.utils.FastJsonUtils;
6 | import cn.blingfeng.websocket.utils.HttpRequestUtil;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.util.StringUtils;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import java.io.IOException;
13 | import java.util.Queue;
14 | import java.util.Random;
15 |
16 | @RestController
17 | @RequestMapping("chat")
18 | public class ChatController {
19 |
20 | private Integer count;
21 | private String SECRET = "";
22 | private String APPID = "";
23 | private String JS_CODE;
24 | @RequestMapping(value = "/random",method = RequestMethod.POST)
25 | public ChatResult randomChat(){
26 |
27 | //用户随机分配聊天室
28 | Random random = new Random();
29 | int i = random.nextInt(3);
30 | return new ChatResult(100,"分配成功",i);
31 |
32 | }
33 | @PostMapping("/login/{code}")
34 | public ChatResult auth(@PathVariable("code")String code){
35 | WxLoginResult wxLoginResult = null;
36 | JS_CODE = code;
37 | String msg;
38 | String loginValidURL = "https://api.weixin.qq.com/sns/jscode2session?appid="+APPID+"&secret="+SECRET+"&js_code="+JS_CODE+"&grant_type=authorization_code";
39 | try {
40 | wxLoginResult = FastJsonUtils.toBean(HttpRequestUtil.get(loginValidURL), WxLoginResult.class);
41 | } catch (IOException e) {
42 | e.printStackTrace();
43 | }
44 | System.out.println(wxLoginResult.getOpenid());
45 | return new ChatResult(200,"success",null);
46 | }
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/controller/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.controller;
2 |
3 | import cn.blingfeng.websocket.pojo.Server2ClientMessage;
4 | import cn.blingfeng.websocket.utils.FastJsonUtils;
5 | import org.springframework.stereotype.Component;
6 |
7 | import javax.websocket.*;
8 | import javax.websocket.server.PathParam;
9 | import javax.websocket.server.ServerEndpoint;
10 | import java.io.IOException;
11 | import java.util.Date;
12 | import java.util.Map;
13 | import java.util.concurrent.CopyOnWriteArraySet;
14 |
15 | @ServerEndpoint("/websocket/{id}/{to}")
16 | @Component
17 | public class WebSocketServer {
18 | private static int onlineCount = 0;
19 | private static CopyOnWriteArraySet webSocketSet =
20 | new CopyOnWriteArraySet();
21 | private Session session;
22 | public String id;
23 | public String to;
24 | @OnOpen
25 | public void onOpen(Session session,
26 | @PathParam("id") String id,
27 | @PathParam("to")String to) throws IOException {
28 | this.session = session;
29 | this.id = id;
30 | this.to = to;
31 | webSocketSet.add(this);
32 | onlineAdd();
33 |
34 | }
35 | @OnMessage
36 | public void onMessage(String message,Session session) throws IOException {
37 | webSocketSet.stream()
38 | .filter(e->e.to.equals(this.to)&&e!=this)
39 | .forEach(e-> {
40 | try {
41 | e.session.getBasicRemote()
42 | .sendText(FastJsonUtils
43 | .toJSONString(new Server2ClientMessage(message,new Date(),1)));
44 | } catch (IOException e1) {
45 | e1.printStackTrace();
46 | }
47 | });
48 |
49 | }
50 | @OnClose
51 | public void close(){
52 | webSocketSet.remove(this);
53 | onlineSub();
54 | }
55 |
56 | public synchronized void onlineAdd(){
57 | onlineCount++;
58 | }
59 | public synchronized void onlineSub(){
60 | onlineCount--;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/pojo/ChatResult.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.pojo;
2 |
3 | public class ChatResult {
4 | private Integer code;
5 |
6 | private String message;
7 |
8 | private Object data;
9 |
10 | public ChatResult(Integer code,String message,Object data){
11 | this.code = code;
12 | this.message = message;
13 | this.data = data;
14 | }
15 | public Integer getCode() {
16 | return code;
17 | }
18 |
19 | public void setCode(Integer code) {
20 | this.code = code;
21 | }
22 |
23 | public String getMessage() {
24 | return message;
25 | }
26 |
27 | public void setMessage(String message) {
28 | this.message = message;
29 | }
30 |
31 | public Object getData() {
32 | return data;
33 | }
34 |
35 | public void setData(Object data) {
36 | this.data = data;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/pojo/Client2ServerMessage.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.pojo;
2 |
3 | import java.util.Date;
4 |
5 | public class Client2ServerMessage {
6 | private String message;
7 |
8 | private Date sendDate;
9 |
10 | private Integer type;
11 |
12 | public String getMessage() {
13 | return message;
14 | }
15 |
16 | public void setMessage(String message) {
17 | this.message = message;
18 | }
19 |
20 | public Date getSendDate() {
21 | return sendDate;
22 | }
23 |
24 | public void setSendDate(Date sendDate) {
25 | this.sendDate = sendDate;
26 | }
27 |
28 | public Integer getType() {
29 | return type;
30 | }
31 |
32 | public void setType(Integer type) {
33 | this.type = type;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/pojo/Server2ClientMessage.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.pojo;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | public class Server2ClientMessage {
7 | private static SimpleDateFormat time=new SimpleDateFormat("HH:mm:ss");
8 | public Server2ClientMessage(String message,Date date,Integer type){
9 | this.message = message;
10 | this.date = date;
11 | this.type = type;
12 | }
13 | private String message;
14 |
15 | private Date date;
16 |
17 | private Integer type;
18 |
19 | public String getMessage() {
20 | return message;
21 | }
22 |
23 | public void setMessage(String message) {
24 | this.message = message;
25 | }
26 |
27 | public String getDate() {
28 | return time.format(date);
29 | }
30 |
31 | public void setDate(Date date) {
32 | this.date = date;
33 | }
34 |
35 | public Integer getType() {
36 | return type;
37 | }
38 |
39 | public void setType(Integer type) {
40 | this.type = type;
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/pojo/WxLoginResult.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.pojo;
2 |
3 | public class WxLoginResult {
4 |
5 |
6 | private String openid;
7 | private String session_key;
8 | private String unionid;
9 | private int errcode;
10 | private String errmsg;
11 |
12 | public String getOpenid() {
13 | return openid;
14 | }
15 |
16 | public void setOpenid(String openid) {
17 | this.openid = openid;
18 | }
19 |
20 | public String getSession_key() {
21 | return session_key;
22 | }
23 |
24 | public void setSession_key(String session_key) {
25 | this.session_key = session_key;
26 | }
27 |
28 | public String getUnionid() {
29 | return unionid;
30 | }
31 |
32 | public void setUnionid(String unionid) {
33 | this.unionid = unionid;
34 | }
35 |
36 | public int getErrcode() {
37 | return errcode;
38 | }
39 |
40 | public void setErrcode(int errcode) {
41 | this.errcode = errcode;
42 | }
43 |
44 | public String getErrmsg() {
45 | return errmsg;
46 | }
47 |
48 | public void setErrmsg(String errmsg) {
49 | this.errmsg = errmsg;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/utils/FastJsonUtils.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.utils;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer;
6 | import com.alibaba.fastjson.serializer.SerializeConfig;
7 | import com.alibaba.fastjson.serializer.SerializerFeature;
8 |
9 | import javax.xml.crypto.dsig.keyinfo.KeyValue;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class FastJsonUtils {
14 |
15 | private static final SerializeConfig config;
16 |
17 | static {
18 | config = new SerializeConfig();
19 | config.put(java.util.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式
20 | config.put(java.sql.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式
21 | }
22 |
23 | private static final SerializerFeature[] features = {SerializerFeature.WriteMapNullValue, // 输出空置字段
24 | SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null
25 | SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null
26 | SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null
27 | SerializerFeature.WriteNullStringAsEmpty // 字符类型字段如果为null,输出为"",而不是null
28 | };
29 |
30 |
31 | public static String toJSONString(Object object) {
32 | return JSON.toJSONString(object, config, features);
33 | }
34 |
35 | public static String toJSONNoFeatures(Object object) {
36 | return JSON.toJSONString(object, config);
37 | }
38 |
39 |
40 |
41 | public static Object toBean(String text) {
42 | return JSON.parse(text);
43 | }
44 |
45 | public static T toBean(String text, Class clazz) {
46 | return JSON.parseObject(text, clazz);
47 | }
48 |
49 | // 转换为数组
50 | public static Object[] toArray(String text) {
51 | return toArray(text, null);
52 | }
53 |
54 | // 转换为数组
55 | public static Object[] toArray(String text, Class clazz) {
56 | return JSON.parseArray(text, clazz).toArray();
57 | }
58 |
59 | // 转换为List
60 | public static List toList(String text, Class clazz) {
61 | return JSON.parseArray(text, clazz);
62 | }
63 |
64 | /**
65 | * 将javabean转化为序列化的json字符串
66 | * @param keyvalue
67 | * @return
68 | */
69 | public static Object beanToJson(KeyValue keyvalue) {
70 | String textJson = JSON.toJSONString(keyvalue);
71 | Object objectJson = JSON.parse(textJson);
72 | return objectJson;
73 | }
74 |
75 | /**
76 | * 将string转化为序列化的json字符串
77 | * @param keyvalue
78 | * @return
79 | */
80 | public static Object textToJson(String text) {
81 | Object objectJson = JSON.parse(text);
82 | return objectJson;
83 | }
84 |
85 | /**
86 | * json字符串转化为map
87 | * @param s
88 | * @return
89 | */
90 | public static Map stringToCollect(String s) {
91 | Map m = JSONObject.parseObject(s);
92 | return m;
93 | }
94 |
95 | /**
96 | * 将map转化为string
97 | * @param m
98 | * @return
99 | */
100 | public static String collectToString(Map m) {
101 | String s = JSONObject.toJSONString(m);
102 | return s;
103 | }
104 |
105 | }
--------------------------------------------------------------------------------
/src/main/java/cn/blingfeng/websocket/utils/HttpRequestUtil.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket.utils;
2 |
3 | import org.apache.http.client.config.RequestConfig;
4 | import org.apache.http.client.methods.CloseableHttpResponse;
5 | import org.apache.http.client.methods.HttpGet;
6 | import org.apache.http.client.methods.HttpPost;
7 | import org.apache.http.entity.StringEntity;
8 | import org.apache.http.impl.client.CloseableHttpClient;
9 | import org.apache.http.impl.client.HttpClients;
10 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
11 |
12 | import java.io.BufferedReader;
13 | import java.io.IOException;
14 | import java.io.InputStreamReader;
15 | import java.nio.charset.Charset;
16 |
17 | public class HttpRequestUtil {
18 | private static CloseableHttpClient httpClient;
19 |
20 | static {
21 | PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
22 | cm.setMaxTotal(100);
23 | cm.setDefaultMaxPerRoute(20);
24 | cm.setDefaultMaxPerRoute(50);
25 | httpClient = HttpClients.custom().setConnectionManager(cm).build();
26 | }
27 |
28 | public static String get(String url) throws IOException {
29 | CloseableHttpResponse response = null;
30 | BufferedReader in = null;
31 | String result = "";
32 | try {
33 | HttpGet httpGet = new HttpGet(url);
34 | RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
35 | httpGet.setConfig(requestConfig);
36 | httpGet.setConfig(requestConfig);
37 | httpGet.addHeader("Content-type", "application/json; charset=utf-8");
38 | httpGet.setHeader("Accept", "application/json");
39 | response = httpClient.execute(httpGet);
40 | in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
41 | StringBuffer sb = new StringBuffer("");
42 | String line = "";
43 | String NL = System.getProperty("line.separator");
44 | while ((line = in.readLine()) != null) {
45 | sb.append(line + NL);
46 | }
47 | in.close();
48 | result = sb.toString();
49 | } catch (IOException e) {
50 | e.printStackTrace();
51 | } finally {
52 | try {
53 | if (null != response) {
54 | response.close();
55 | }
56 | } catch (IOException e) {
57 | e.printStackTrace();
58 | }
59 | }
60 | return result;
61 | }
62 |
63 | public static String post(String url, String jsonString) {
64 | CloseableHttpResponse response = null;
65 | BufferedReader in = null;
66 | String result = "";
67 | try {
68 | HttpPost httpPost = new HttpPost(url);
69 | RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
70 | httpPost.setConfig(requestConfig);
71 | httpPost.setConfig(requestConfig);
72 | httpPost.addHeader("Content-type", "application/json; charset=utf-8");
73 | httpPost.setHeader("Accept", "application/json");
74 | httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
75 | response = httpClient.execute(httpPost);
76 | in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
77 | StringBuffer sb = new StringBuffer("");
78 | String line = "";
79 | String NL = System.getProperty("line.separator");
80 | while ((line = in.readLine()) != null) {
81 | sb.append(line + NL);
82 | }
83 | in.close();
84 | result = sb.toString();
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | } finally {
88 | try {
89 | if (null != response) {
90 | response.close();
91 | }
92 | } catch (IOException e) {
93 | e.printStackTrace();
94 | }
95 | }
96 | return result;
97 | }
98 |
99 | }
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9000
3 | spring:
4 | application:
5 | name: chat
6 |
--------------------------------------------------------------------------------
/src/main/resources/templates/webSocket.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SpringBoot实现广播式WebSocket
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
37 |
--------------------------------------------------------------------------------
/src/test/java/cn/blingfeng/websocket/WebsocketApplicationTests.java:
--------------------------------------------------------------------------------
1 | package cn.blingfeng.websocket;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class WebsocketApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------