Web統合mpush開発
32752 ワード
サービスの導入方法の参照:https://github.com/mywiki/mpush-doc/blob/master/SUMMARY.md mpushの公式詳細開発ドキュメントを完了します.http://mpush.mydoc.io/?t=134820
redisはデフォルトではネイティブのみアクセスできます.プロファイルを変更する必要があります.参照してください.https://blog.csdn.net/weiyangdong/article/details/79916445変更
完全なWebプロジェクトdemol接続:https://download.csdn.net/download/qq_16758997/10943141
Mpush-Allocサービスをインストールするときは、mpush.configプロファイルのws-server-portのポート番号(アナログクライアントのポート番号)を変更してください.
一、普通のmaven webプロジェクトを新規作成するか、新しいwebプロジェクトを新規作成してmavenプロジェクトに変換する(文章は後者の方式を採用し、jdk 1.8、tomcat 9.0)
二、pom.xmlファイルを以下のように変更する.
新しいラベルセクション、mpush関連jarパッケージをインポート
com.github.mpusher mpush-client 0.8.0
srcディレクトリの下にアプリケーション.confファイルを新規作成します.ファイルの内容は次のとおりです.
三、普通のクラスを新設し、二つのインタフェースPushSender(mpush起動は使用する必要がある)、サーブレットContextListener(webプロジェクトのリスナーが継承する必要があるクラス)を実現する必要がある
tomcat起動時にmpushメッセージ送信サービスを起動し、単例モードを採用し、静的共通getメソッドを増やして詳細なプッシュサービスインスタンスを取得し、他のクラス呼び出しを共有する
//tomcatで起動するのはメッセージ送信サービスを起動することです //タイマーを起動 @Override public void contextInitialized(ServletContextEvent arg0) { //PushClient PushClient=new PushClient(); if (pushSender == null) pushSender = PushSender.create(); pushSender.start().join(); }
public static PushSender getPushSender() { if (pushSender == null) pushSender = PushSender.create(); return pushSender; }
四、webプロジェクトリスナーの構成を増やし、web.xmlファイルを修正する
カスタムWebプロジェクトのリスナーを追加します(ここでのクラスパスは、手順3で新規作成したリスナークラスパスです).
com.webpush.service.ServiceManager
ここまでmpush継承環境の開発構築は完了しており,以下の内容はテストのservletを追加することである.
五、2つのservletクラスを新規作成し、web.xmlファイル構成を追加する:
最初のservletクラス:
2番目のservletクラス:
2番目のservletクラスを新規作成する前に、redisのプロファイルを作成します.ファイル名:redis.properties、srcディレクトリの下に置きます.
servletクラス
Web.xmlファイルの変更
Web Socketクライアントは、メッセージテストを受けます(appは公式サイトでダウンロードしてください.Android 7.0以上のバージョンがバインドをクリックして終了したら、Android 6.0以下のバージョンに変更してテストをインストールしてください).
クライアントのすべてのユーザー・リスト
Webプロジェクトを実行し、効果を表示します.
もしあなたに役に立つならいいねを覚えていますよ.
ようこそグループ:517413713討論
redisはデフォルトではネイティブのみアクセスできます.プロファイルを変更する必要があります.参照してください.https://blog.csdn.net/weiyangdong/article/details/79916445変更
完全なWebプロジェクトdemol接続:https://download.csdn.net/download/qq_16758997/10943141
Mpush-Allocサービスをインストールするときは、mpush.configプロファイルのws-server-portのポート番号(アナログクライアントのポート番号)を変更してください.
一、普通のmaven webプロジェクトを新規作成するか、新しいwebプロジェクトを新規作成してmavenプロジェクトに変換する(文章は後者の方式を採用し、jdk 1.8、tomcat 9.0)
二、pom.xmlファイルを以下のように変更する.
4.0.0
webmpush
webmpush
0.0.1-SNAPSHOT
war
com.github.mpusher
mpush-client
0.8.0
src
src
**/*.java
maven-compiler-plugin
3.7.0
1.8
1.8
maven-war-plugin
3.2.1
WebContent
新しいラベルセクション、mpush関連jarパッケージをインポート
com.github.mpusher mpush-client 0.8.0
srcディレクトリの下にアプリケーション.confファイルを新規作成します.ファイルの内容は次のとおりです.
##################################################################################################################
#
# NOTICE:
#
# ,
# mpush.conf 。
#
# HOCON 。 https://github.com/typesafehub/config 。
# , 。
#
##################################################################################################################
mp {
#
home=${user.dir} //
#
log-level=warn
log-dir=${mp.home}/logs
log-conf-path=${mp.home}/conf/logback.xml
#
core {
max-packet-size=10k //
compress-threshold=10k // ,
min-heartbeat=3m //
max-heartbeat=3m //
max-hb-timeout-times=2 //
session-expired-time=1d // session 1
epoll-provider=netty //nio:jdk ,netty: netty
}
#
security {
#rsa 、 key 1024; bin/rsa.sh , @see com.mpush.tools.crypto.RSAUtils#main
private-key="MIIBNgIBADANBgkqhkiG9w0BAQEFAASCASAwggEcAgEAAoGBAKCE8JYKhsbydMPbiO7BJVq1pbuJWJHFxOR7L8Hv3ZVkSG4eNC8DdwAmDHYu/wadfw0ihKFm2gKDcLHp5yz5UQ8PZ8FyDYvgkrvGV0ak4nc40QDJWws621dm01e/INlGKOIStAAsxOityCLv0zm5Vf3+My/YaBvZcB5mGUsPbx8fAgEAAoGAAy0+WanRqwRHXUzt89OsupPXuNNqBlCEqgTqGAt4Nimq6Ur9u2R1KXKXUotxjp71Ubw6JbuUWvJg+5Rmd9RjT0HOUEQF3rvzEepKtaraPhV5ejEIrB+nJWNfGye4yzLdfEXJBGUQzrG+wNe13izfRNXI4dN/6Q5npzqaqv0E1CkCAQACAQACAQACAQACAQA="
public-key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCghPCWCobG8nTD24juwSVataW7iViRxcTkey/B792VZEhuHjQvA3cAJgx2Lv8GnX8NIoShZtoCg3Cx6ecs+VEPD2fBcg2L4JK7xldGpOJ3ONEAyVsLOttXZtNXvyDZRijiErQALMTorcgi79M5uVX9/jMv2Ggb2XAeZhlLD28fHwIDAQAB"
aes-key-length=16 //AES key
}
#
net {
local-ip="127.0.0.1" // ip, IP
public-ip="127.0.0.1" // ip, IP
connect-server-bind-ip="" //connSrv ip ( anyLocalAddress 0.0.0.0 or ::0)
connect-server-register-ip=${mp.net.public-ip} // ip, zk ip, public-ip
connect-server-port=3000 // ,
connect-server-register-attr { // zk , , alloc
weight:1
}
gateway-server-bind-ip="" //gatewaySrv ip ( anyLocalAddress 0.0.0.0 or ::0)
gateway-server-register-ip=${mp.net.local-ip} // ip, zk ip, local-ip
gateway-server-port=3001 // ,
gateway-server-net=tcp // tcp/udp/sctp/udt
gateway-client-port=4000 //UDP
gateway-server-multicast="239.239.239.88" //239.0.0.0~239.255.255.255 ,
gateway-client-multicast="239.239.239.99" //239.0.0.0~239.255.255.255 ,
gateway-client-num=1 //
admin-server-port=3002 // ,
ws-server-port=0 //websocket , , 0 websocket
ws-path="/" //websocket path
public-host-mapping { // IP IP ,
//"10.0.10.156":"111.1.32.137"
//"10.0.10.166":"111.1.33.138"
}
snd_buf { //tcp/udp
connect-server=32k
gateway-server=0
gateway-client=0 //0
}
rcv_buf { //tcp/udp
connect-server=32k
gateway-server=0
gateway-client=0 //0
}
write-buffer-water-mark { //netty
connect-server-low=32k
connect-server-high=64k
gateway-server-low=10m
gateway-server-high=20m
}
traffic-shaping { //
gateway-client {
enabled:false
check-interval:100ms
write-global-limit:30k
read-global-limit:0
write-channel-limit:3k
read-channel-limit:0
}
gateway-server {
enabled:false
check-interval:100ms
write-global-limit:0
read-global-limit:30k
write-channel-limit:0
read-channel-limit:3k
}
connect-server {
enabled:false
check-interval:100ms
write-global-limit:0
read-global-limit:100k
write-channel-limit:3k
read-channel-limit:3k
}
}
}
#Zookeeper
zk {
server-address="127.0.0.1:2181" // "," :"10.0.10.44:2181,10.0.10.49:2181" @see org.apache.zookeeper.ZooKeeper#ZooKeeper()
namespace=mpush
digest=mpush //zkCli.sh acl addauth digest mpush
watch-path=/
retry {
#initial amount of time to wait between retries
baseSleepTimeMs=3s
#max number of times to retry
maxRetries=3
#max time in ms to sleep on each retry
maxSleepMs=5s
}
connectionTimeoutMs=5s
sessionTimeoutMs=5s
}
#Redis
redis {
cluster-model=single //single,cluster,sentinel
sentinel-master:"",
nodes:["127.0.0.1:6379"] //["127.0.0.1:6379"] ip:port
password="" //your password
config {
maxTotal:8,
maxIdle:4,
minIdle:1,
lifo:true,
fairness:false,
maxWaitMillis:5000,
minEvictableIdleTimeMillis:300000,
softMinEvictableIdleTimeMillis:1800000,
numTestsPerEvictionRun:3,
testOnCreate:false,
testOnBorrow:false,
testOnReturn:false,
testWhileIdle:false,
timeBetweenEvictionRunsMillis:60000,
blockWhenExhausted:true,
jmxEnabled:false,
jmxNamePrefix:pool,
jmxNameBase:pool
}
}
#HTTP
http {
proxy-enabled=true// Http
max-conn-per-host=5 // , web nginx ,
default-read-timeout=10s //
max-content-length=5m //response body
dns-mapping { // IP,
//"mpush.com":["127.0.0.1:8080", "127.0.0.1:8081"]
}
}
#
thread {
pool {
conn-work:0 // ,0 cpu (2*cpu)
gateway-server-work:0 // ,0 cpu (2*cpu)
http-work:0 //http proxy netty client work pool size,0 cpu (2*cpu)
ack-timer:1 // ACK
push-task:0 // , , 0 Gateway Server work ,tcp 0
gateway-client-work:0 // ,0 cpu (2*cpu),
push-client:2 // ,
event-bus { //
min:1
max:16
queue-size:10000 // online,offline
}
mq { // ,
min:1
max:4
queue-size:10000
}
}
}
#
push {
flow-control { //qps = limit/(duration)
global:{ // ,
limit:5000 //qps = 5000
max:0 //UN limit
duration:1s //1s
}
broadcast:{ // ,
limit:3000 //qps = 3000
max:100000 //10w
duration:1s //1s
}
}
}
#
monitor {
dump-dir=${mp.home}/tmp
dump-stack=false // dump
dump-period=1m //
print-log=true //
profile-enabled=false //
profile-slowly-duration=10ms // 10ms
}
#SPI
spi {
thread-pool-factory:"com.mpush.tools.thread.pool.DefaultThreadPoolFactory"
dns-mapping-manager:"com.mpush.common.net.HttpProxyDnsMappingManager"
}
}
三、普通のクラスを新設し、二つのインタフェースPushSender(mpush起動は使用する必要がある)、サーブレットContextListener(webプロジェクトのリスナーが継承する必要があるクラス)を実現する必要がある
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.FutureTask;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.mpush.api.push.PushContext;
import com.mpush.api.push.PushResult;
import com.mpush.api.push.PushSender;
import com.mpush.api.service.Listener;
public class ServiceManager implements PushSender, ServletContextListener {
public static PushSender pushSender = null;
// tomcat
//
@Override
public void contextInitialized(ServletContextEvent arg0) {
// PushClient PushClient=new PushClient();
if (pushSender == null)
pushSender = PushSender.create();
pushSender.start().join();
}
public static PushSender getPushSender() {
if (pushSender == null)
pushSender = PushSender.create();
return pushSender;
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
pushSender.stop();
}
@Override
public void start(Listener listener) {
// TODO Auto-generated method stub
}
@Override
public void stop(Listener listener) {
// TODO Auto-generated method stub
}
@Override
public CompletableFuture start() {
// TODO Auto-generated method stub
return null;
}
@Override
public CompletableFuture stop() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean syncStart() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean syncStop() {
// TODO Auto-generated method stub
return false;
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public boolean isRunning() {
// TODO Auto-generated method stub
return false;
}
@Override
public FutureTask send(PushContext context) {
// TODO Auto-generated method stub
return null;
}
}
tomcat起動時にmpushメッセージ送信サービスを起動し、単例モードを採用し、静的共通getメソッドを増やして詳細なプッシュサービスインスタンスを取得し、他のクラス呼び出しを共有する
//tomcatで起動するのはメッセージ送信サービスを起動することです //タイマーを起動 @Override public void contextInitialized(ServletContextEvent arg0) { //PushClient PushClient=new PushClient(); if (pushSender == null) pushSender = PushSender.create(); pushSender.start().join(); }
public static PushSender getPushSender() { if (pushSender == null) pushSender = PushSender.create(); return pushSender; }
四、webプロジェクトリスナーの構成を増やし、web.xmlファイルを修正する
webpush
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
com.webpush.service.ServiceManager
カスタムWebプロジェクトのリスナーを追加します(ここでのクラスパスは、手順3で新規作成したリスナークラスパスです).
com.webpush.service.ServiceManager
ここまでmpush継承環境の開発構築は完了しており,以下の内容はテストのservletを追加することである.
五、2つのservletクラスを新規作成し、web.xmlファイル構成を追加する:
最初のservletクラス:
package com.webpush.pushmessage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mpush.api.push.AckModel;
import com.mpush.api.push.MsgType;
import com.mpush.api.push.PushCallback;
import com.mpush.api.push.PushContext;
import com.mpush.api.push.PushMsg;
import com.mpush.api.push.PushResult;
import com.mpush.api.push.PushSender;
import com.webpush.service.ServiceManager;// servlet ( )
/**
* Servlet implementation class Htmlpushmesg
*/
@WebServlet("/htmlpushmesg")
public class Htmlpushmesg extends HttpServlet {
private static final long serialVersionUID = 1L;
PushResult pushResult=null;//
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
int msgType=Integer.valueOf(request.getParameter("msgtype"));
String pushMsg=request.getParameter("pushMsg");
String broadcast=request.getParameter("broadcast");
String[] userIds=request.getParameterValues("userId");
List users=new ArrayList();
if(userIds!=null)
for(int i=0,len=userIds.length;i future = */sender.send(context);
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(10));
request.setAttribute("pushResult", pushResult);
request.getRequestDispatcher("/push.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2番目のservletクラス:
2番目のservletクラスを新規作成する前に、redisのプロファイルを作成します.ファイル名:redis.properties、srcディレクトリの下に置きます.
jedis.pool.maxActive=1024
jedis.pool.maxIdle=200
jedis.pool.maxWait=10000
jedis.pool.testOnBorrow=true
jedis.pool.testOnReturn=true
jedis.pool.timeout=10000
# ip application.conf redis IP
redisReadURL=127.0.0.1
redisReadPort=6379
# ip application.conf redis IP
redisWriteURL=127.0.0.1
redisWritePort=6379
# redis , application.conf redis
password=
servletクラス
package com.webpush.pushmessage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mpush.tools.config.CC;
import com.mpush.tools.config.data.RedisNode;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
*
*/
@WebServlet("/userStutas")
public class UserStutas extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("users", getRedisdata());
request.getRequestDispatcher("/userlist.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* redis
*/
//
private static int MAX_ACTIVE = 1024;
// pool idle( ) jedis , 8。
private static int MAX_IDLE = 200;
// , , -1, 。 , JedisConnectionException
private static int MAX_WAIT = 10000;
//
private static int TIMEOUT = 10000;
// borrow jedis , validate ; true, jedis ;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
//
static void load() {
Config config = ConfigFactory.load();//
String custom_conf = "mp.conf";// , jvm -Dmp.conf
if (config.hasPath(custom_conf)) {
File file = new File(config.getString(custom_conf));
if (file.exists()) {
Config custom = ConfigFactory.parseFile(file);
config = custom.withFallback(config);
}
}
Config cfg = CC.cfg.getObject("mp").toConfig().getObject("redis").toConfig();
try {
JedisPoolConfig redisconf = new JedisPoolConfig();
redisconf.setMaxTotal(MAX_ACTIVE);
redisconf.setMaxIdle(MAX_IDLE);
redisconf.setMaxWaitMillis(MAX_WAIT);
redisconf.setTestOnBorrow(TEST_ON_BORROW);
RedisNode redisnode=cfg.getList("nodes")
.stream()//
.map(v -> RedisNode.from(v.unwrapped().toString()))
.collect(Collectors.toCollection(ArrayList::new)).get(0);
jedisPool = new JedisPool(redisconf, redisnode.getHost(), redisnode.getPort(), TIMEOUT, cfg.getString("password"));
} catch (Exception e) {
e.printStackTrace();
}
}
public Map>> getRedisdata() {
Jedis jedis = getJedis();
Map>> map = new HashMap>>();
for(String key : jedis.keys("mp:ur:*")) {
//System.err.println(key+"\t");
Map> maplist=new HashMap>();
for(String ke : jedis.hkeys(key)) {
maplist.put(ke, jedis.hmget(key,ke));
//System.out.print(ke+"\t");
//System.out.println(jedis.hmget(key,ke));
}
map.put(key, maplist);
}
returnResource(jedis);
return map;
}
/**
* Redis
*/
static {
load();
}
/**
* Jedis
*/
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
return resource;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/***
*
*
*/
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
Web.xmlファイルの変更
webpush
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
com.webpush.service.ServiceManager
htmlpushmesg
com.webpush.pushmessage.Htmlpushmesg
htmlpushmesg
/htmlpushmesg.do
userStutas
com.webpush.pushmessage.UserStutas
userStutas
/userStutas.do
Web Socketクライアントは、メッセージテストを受けます(appは公式サイトでダウンロードしてください.Android 7.0以上のバージョンがバインドをクリックして終了したら、Android 6.0以下のバージョンに変更してテストをインストールしてください).
MPush WebSocket Client
(function (window) {
let socket, session = {}, ID_SEQ = 1;
let config = {listener: null, log: console};
let listener = {
onOpened: function (event) {
if (config.listener != null) {
config.listener.onOpened(event);
}
handshake();
},
onClosed: function (event) {
if (config.listener != null) {
config.listener.onClosed(event);
}
session = {};
ID_SEQ = 1;
socket = null;
},
onHandshake: function () {
session.handshakeOk = true;
if (config.listener != null) {
config.listener.onHandshake();
}
if (config.userId) {
bindUser(config.userId, config.tags);
}
},
onBindUser: function (success) {
if (config.listener != null) {
config.listener.onBindUser(success);
}
},
onReceivePush: function (message, messageId) {
if (config.listener != null) {
config.listener.onReceivePush(message, messageId);
}
},
onKickUser: function (userId, deviceId) {
if (config.listener != null) {
config.listener.onKickUser(userId, deviceId);
}
doClose(-1, "kick user");
}
};
const Command = {
HANDSHAKE: 2,
BIND: 5,
UNBIND: 6,
ERROR: 10,
OK: 11,
KICK: 13,
PUSH: 15,
ACK: 23,
UNKNOWN: -1
};
function Packet(cmd, body, sessionId) {
return {
cmd: cmd,
flags: 16,
sessionId: sessionId || ID_SEQ++,
body: body
}
}
function handshake() {
send(Packet(Command.HANDSHAKE, {
deviceId: config.deviceId,
osName: config.osName,
osVersion: config.osVersion,
clientVersion: config.clientVersion
})
);
}
function bindUser(userId, tags) {
if (userId && userId != session.userId) {
session.userId = userId;
session.tags = tags;
send(Packet(Command.BIND, {userId: userId, tags: tags}));
}
}
function ack(sessionId) {
send(Packet(Command.ACK, null, sessionId));
}
function send(message) {
if (!socket) {
return;
}
if (socket.readyState == WebSocket.OPEN) {
socket.send(JSON.stringify(message));
} else {
config.log.error("The socket is not open.");
}
}
function dispatch(packet) {
switch (packet.cmd) {
case Command.HANDSHAKE: {
config.log.debug(">>> handshake ok.");
listener.onHandshake();
break;
}
case Command.OK: {
if (packet.body.cmd == Command.BIND) {
config.log.debug(">>> bind user ok.");
listener.onBindUser(true);
}
break;
}
case Command.ERROR: {
if (packet.body.cmd == Command.BIND) {
config.log.debug(">>> bind user failure.");
listener.onBindUser(false);
}
break;
}
case Command.KICK: {
if (session.userId == packet.body.userId && config.deviceId == packet.body.deviceId) {
config.log.debug(">>> receive kick user.");
listener.onKickUser(packet.body.userId, packet.body.deviceId);
}
break;
}
case Command.PUSH: {
config.log.debug(">>> receive push, content=" + packet.body.content);
let sessionId;
if ((packet.flags & 8) != 0) {
ack(packet.sessionId);
} else {
sessionId = packet.sessionId
}
listener.onReceivePush(packet.body.content, sessionId);
break;
}
}
}
function onReceive(event) {
config.log.debug(">>> receive packet=" + event.data);
dispatch(JSON.parse(event.data))
}
function onOpen(event) {
config.log.info("Web Socket opened!");
listener.onOpened(event);
}
function onClose(event) {
config.log.info("Web Socket closed!");
listener.onClosed(event);
}
function onError(event) {
config.log.info("Web Socket receive, error");
doClose();
}
function doClose(code, reason) {
if (socket) socket.close();
config.log.info("try close web socket client, reason=" + reason);
}
function doConnect(cfg) {
config = copy(cfg);
socket = new WebSocket(config.url);
socket.onmessage = onReceive;
socket.onopen = onOpen;
socket.onclose = onClose;
socket.onerror = onError;
config.log.debug("try connect to web socket server, url=" + config.url);
}
function copy(cfg) {
for (let p in cfg) {
if (cfg.hasOwnProperty(p)) {
config[p] = cfg[p];
}
}
return config;
}
window.mpush = {
connect: doConnect,
close: doClose,
bindUser: bindUser
}
})(window);
function $(id) {
return document.getElementById(id);
}
let log = {
log: function () {
$("responseText").value += (Array.prototype.join.call(arguments, "") + "\r
");
}
};
log.debug = log.info = log.warn = log.error = log.log;
function connect() {
mpush.connect({
url: $("url").value,
userId: $("userId").value,
deviceId: "test-1001",
osName: "web " + navigator.userAgent,
osVersion: "55.2",
clientVersion: "1.0",
log: log
});
}
function bind() {
mpush.bindUser($("userId").value)
}
クライアントのすべてのユーザー・リスト
Insert title here
>> map = (Map>>) request.getAttribute("users");
Set set = map.keySet();
for (String user : set) {
Set se = map.get(user).keySet();
Iterator it = se.iterator();
%>
m = JSON.parseObject(list, Map.class);
%>
" : " "%>
" : " "%>
Webプロジェクトを実行し、効果を表示します.
もしあなたに役に立つならいいねを覚えていますよ.
ようこそグループ:517413713討論