##轉載請標明出處 http://coderknock.com ######源碼:http://git.oschina.net/sanchan/SparkJsonRedis Spark Framework beetl fastjson 結合 #####項目結構以下 ######pom.xml以下:html
<?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進行視圖解析的方法:java
/** * 拿客 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實現類git
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的一個簡單封裝:web
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請求高併發測試:redis
/** * 拿客 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秒鐘一次。apache