##转载请标明出处 http://coderknock.com ######源码:http://git.oschina.net/sanchan/SparkJsonRedis Spark Framework beetl fastjson 结合 #####项目结构如下 ######pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.coderknock</groupId>
<artifactId>TestSpark</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<log4j_version>1.2.17</log4j_version>
<slf4j_version>1.7.21</slf4j_version>
</properties>
<dependencies>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<version>3.7.1</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>test</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>sources</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
WebSocket推送,普通Get请求以及返回Json的请求、使用Beetl进行视图解析的方法:
/**
* 拿客 www.coderknock.com
* 微信公众号 coderknock
* 作者:三产
*/
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import static spark.Spark.*;
public class Test {
private static Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
//设置端口
port(9090);
//EchoWebSocket不能是内部类
webSocket("/echo", EchoWebSocket.class);
//这个必须有,不然注册不成功
init();
// matches "GET /hello/foo" and "GET /hello/bar"
// request.params(":name") is 'foo' or 'bar'
get("/hello/:name", (request, response) -> {
//使用Beetl进行视图的解析
return Tmpl.render("hello.html", request.params());
});
// matches "GET /say/hello/to/world"
// request.splat()[0] is 'hello' and request.splat()[1] 'world'
get("/say/*/to/*", (request, response) -> {
response.type("application/json");
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("1", request.splat()[0]);
map.put("2", request.splat()[1]);
//打印结果
logger.debug("$$$$$$$$$$$$$$$$$" + JSON.toJSON(map).toString());
return JSON.toJSON(map);
});
get("/home", (request, response) -> {
return Tmpl.render("index.html");
});
int i = 0;
//WebSocket主动推送的实现,启动轮询,定时发送消息
while (true) {
try {
Thread.currentThread().sleep(1000);
i++;
logger.debug("--->" + i);
if (i % 5 == 1) {
EchoWebSocket.send(i);
logger.debug("--->第" + i + "次发送");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
WebSocket实现类
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* 拿客 www.coderknock.com
* 微信公众号 coderknock
* 作者:三产
*/
@WebSocket
public class EchoWebSocket {
private static Logger logger = LoggerFactory.getLogger(EchoWebSocket.class);
// Store sessions if you want to, for example, broadcast a message to all users
private static final Queue<Session> sessions = new ConcurrentLinkedQueue<>();
@OnWebSocketConnect
public void connected(Session session) {
sessions.add(session);
//建立连接的时候
logger.debug("新增了Session" + session.toString());
}
@OnWebSocketClose
public void closed(Session session, int statusCode, String reason) {
sessions.remove(session);
//关闭连接或者浏览器关闭时
logger.debug("删除了Session" + session.toString());
}
@OnWebSocketMessage
public void message(Session session, String message) throws IOException {
//获取到客户端发送的消息时,对消息进行输出,病简单处理返回另一个消息
System.out.println("Got: " + message); // Print message
session.getRemote().sendString(message + "1231"); // and send it back
}
public static void send(int i) {
//这里只是简单的给所有用户推送,其实可以改造一下(将Session与用户id之类的通过发送消息的方式一一对应,这样可以为特定用户进行消息的发送)
sessions.forEach(session -> {
try {
session.getRemote().sendString("第" + i + "次主动推送");
} catch (Exception e) {
logger.error("主动推送失败", e);
}
}
);
}
}
Beetl的一个简单封装:
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.WebAppResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* 拿客 www.coderknock.com
* 微信公众号 coderknock
* 作者:三产
*/
public class Tmpl {
private static GroupTemplate gt;
private static Logger logger = LoggerFactory.getLogger(Tmpl.class);
static {
try {
Configuration cfg = Configuration.defaultConfiguration();
WebAppResourceLoader resourceLoader = new WebAppResourceLoader();
gt = new GroupTemplate(resourceLoader, cfg);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String render(String tmplPath) {
Template t = gt.getTemplate(tmplPath);
return t.render();
}
public static String render(String tmplPath, Map<String, String> param) {
Template t = gt.getTemplate(tmplPath);
Map<String, String> convertMap = new HashMap<>();
try {
param.forEach((x, y) -> {
if (x.startsWith(":")) {
convertMap.put(x.substring(1), y);
}
});
} catch (Exception e) {
logger.error("转换失败", e);
}
t.binding(convertMap);
return t.render();
}
}
Get请求高并发测试:
/**
* 拿客 www.coderknock.com
* 微信公众号 coderknock
* 作者:三产
*/
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class TestGet {
//大家可以适当加大,但是如果太大可能会导致get请求发送失败,大家有优化建议可以告诉我(客户端问题,并不是Spark处理不了高并发)
private static int thread_num = 500;
private static int client_num = 500;
public static void main(String[] args) {
long time = System.currentTimeMillis();
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semp = new Semaphore(thread_num);
for (int index = 0; index < client_num; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
semp.acquire();
System.out.println("------------------|" + NO + "|------------------");
HttpResponse response = HttpRequest
.get("http://localhost:9090/say/Hello-" + NO + "/to/World" + NO
)
.acceptEncoding("gzip")
.send();
System.out.println(response.unzip());
System.out.println("------------------&" + NO + "&------------------");
//业务逻辑
semp.release();
} catch (Exception e) {
e.printStackTrace();
}
}
};
exec.execute(run);
}
exec.shutdown();
}
}
WebSocket可以通过websocket.html测试(建议使用火狐浏览器): 先点击“建立连接”,然后可以填写一些内容,点击“发送数据”,连接建立后就开始了主动推送,我设置的是5秒钟一次。