功能需求:
通过quartz(也可以不用quartz,用redis的订阅发布)定时从redis中获得实时数据(可以是通过storm或其他工具分析的数据)推送到web页面展示出来。
实现思路:
1,可以通过轮询来实现,简单但是比较消耗资源。
2,使用webSocket实现,与服务端建立长连接,省去重复请求耗费的资源,注意只有H5支持。
使用webSocket实现图:
需要依赖的jar包:
<!-- quartz定时任务 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<!-- redis java客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- netty-socketio -->
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.8</version>
</dependency>
<!-- socket.io-client 将redis数据推送到webSocket服务 -->
<dependency>
<groupId>io.socket</groupId>
<artifactId>socket.io-client</artifactId>
<version>1.0.0</version>
</dependency>
实现代码:
1,webSocket 服务
package com.charhoo.anytest.websocket;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOServer;
public class AppServer {
public static void main(String[] args) throws InterruptedException
{
Configuration config = new Configuration();
config.setHostname("192.168.1.1");//设置ip
config.setPort(9093);//设置端口
SocketIOServer server = new SocketIOServer(config);//实例化SocketIOServer
CharteventListener listner = new CharteventListener();//设置服务监听
listner. setServer(server);
server.addEventListener("timeEvent", ChatObject.class, listner);// timeEvent为事件名称
server.start();//启动服务
Thread.sleep(Integer.MAX_VALUE) ;
server.stop();
}
}
2,quartz定时任务
package com.charhoo.socket.util;
import java.text.ParseException;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import com.charhoo.socket.job.RedisAlarmJob;
public class QuartzUtil {
public static Scheduler getScheduler() throws SchedulerException, ParseException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
JobDetail jobDetail = JobBuilder.newJob(RedisAlarmJob.class)
.withIdentity("redisAlarmJob", Scheduler.DEFAULT_GROUP)
.build();
String cronExpression = "0/5 * * * * ?"; // 每分钟的0s起,每5s触发任务
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("cronTrigger", Scheduler.DEFAULT_GROUP)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
return scheduler;
}
}
job
package com.charhoo.socket.job;
import java.util.Map;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.charhoo.socket.SocketClient;
import com.charhoo.socket.util.RedisUtil;
public class RedisAlarmJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
// 获取redis报警数据并发布到Socket
Map<String, String> data = RedisUtil.jedisCluster.hgetAll("youkey");
SocketClient.getInstance().emit("TimeEvent", data );
}
}
java-socketClient
package com.charhoo.socket;
import java.net.URISyntaxException;
import org.json.JSONException;
import org.json.JSONObject;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
public class SocketClient{
private static Socket instance;
public static synchronized Socket getInstance() {
if (instance == null) {
IO.Options options = new IO.Options();
options.forceNew = true;
options.reconnection = true;
try {
instance = IO.socket("http://192.168.1.1:9093", options);
instance.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
public void call(Object... args) {
System.out.println("connect");
}
}).on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
public void call(Object... args) {
System.out.println("connect timeout");
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
public void call(Object... args) {
System.out.println("connect error");
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
public void call(Object... args) {
System.out.println("disconnect");
}
}).on("TimeEvent", new Emitter.Listener() {
public void call(Object... args) {
System.out.println("服务端:"+args[0]);
}
});
instance.open();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return instance;
}
}
3,web页面
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Socketio chat</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="https://cdn.bootcss.com/socket.io/2.0.3/socket.io.js"></script>
<style>
body {
padding: 20px;
}
#console {
height: 400px;
overflow: auto;
}
</style>
</head>
<body>
<h1>Netty-socketio demo</h1>
<br />
<div id="console" class="well"></div>
</body>
<script type="text/javascript">
var socket = io.connect('http://192.168.1.1:9093');
socket.on('connect',function() {
output('<span class="connect-msg">Client has connected to the server!</span>');
});
socket.on('TimeEvent', function(data) {
output('<span class="username-msg">' + data.vid + ' : </span>'
+ data.speed);
});
function output(message) {
var currentTime = "<span class='time' >" + new Date() + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('#console').prepend(element);
}
</script>
</html>
启动:
先启动socketServer服务,再启动quartz定时任务,打开web页面就会收到redis的实时数据。
讲述的不明确的地方欢迎留言。