1. 程式人生 > >JavaEE開發之SpringMVC中的靜態資源對映及伺服器推送技術

JavaEE開發之SpringMVC中的靜態資源對映及伺服器推送技術

在上篇部落格中,我們聊了《》。本篇部落格我們繼續的來聊SpringMVC的東西,下方我們將會聊到js、css這些靜態檔案的載入配置,以及伺服器推送的兩種實現方式。當然我們在伺服器推送時,會用到JQuery的東西,所以我們先聊一下如何載入靜態資原始檔,然後我們再聊如何實現伺服器推送。

下方給出了兩種實現伺服器推送的方式,一種是SSE(Server Send Event服務端推送事件))另一種是基於Servlet非同步處理的推送,下方會給出詳細的實現方式,並且給出了兩者的區別。

一、靜態資原始檔對映

靜態資原始檔對映在SpringMVC中的配置也是比較簡單的、在我們Spring的Config檔案裡邊配置一下即可。下方就是我們在配置靜態資原始檔時所做的內容。

1、對映資原始檔

首先我們在src/main/resources包下方建立了衣蛾assets檔案,該檔案下就存放著我們工程中所使用所有的靜態資原始檔。然後我們在Spring的配置檔案中重寫addResourceHandlers()方法,使用該方法來配置“assets”目錄。

  

2、資原始檔的引用

我們來建立一個jquery_test.jsp檔案,該檔案中引入了assets資料夾中js資料夾下的jquery.js檔案。在jquery_test.jsp中就使用了jQuery的東西。下方就是該檔案的所有內容。當然下方頁面的功能比較簡單,就是點選按鈕,往HTML中動態的新增新的節點。具體程式碼如下所示:

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"
> 7 <script type="text/javascript" src="assets/js/jquery.js"></script> 8 <script type="text/javascript"> 9 $(document).ready(function(){ 10 $("#click").click(function(){ 11 $("#test").append("<h2>Hello Spring MVC</h2>"); 12 }); 13 }); 14 15 </script> 16 <title>JQuery Demo</title> 17 </head> 18 <body> 19 <input type="button" id="click" value="JQuery-TEST-Click me"/> 20 <h2 id="test"></h2> 21 </body> 22 </html>

3、測試上述頁面

當然要想訪問上述頁面,還得在Spring的配置檔案中進行路由的配置。下方程式碼段就是Spring配置檔案中靜態檔案路由的快速配置。

  

下方就是我們對相應路由的訪問結果,如下所示。通過下方示例,我們可以看到jquery.js資原始檔可以被正常的訪問到。

  

二、Server Send Event (服務端推送事件)

Server Send Event簡稱SSE,使用該技術可以實現服務端像瀏覽器傳送事件,也就是所謂的服務端的PUSH。本篇部落格所聊的伺服器推送技術的實現原理是當客戶端向服務端傳送請求時,服務端會抓住這個請求不放,等有資料更新的時候才返回給客戶端。當客戶端接收到訊息後,再向服務端傳送請求,周而復始。

服務端推送以及客戶端傳送的網路請求都是單向通訊,後面的部落格我們會介紹一種雙向通訊技術:WebSocket。本篇我們就先聊聊服務端的推送事件。

1.建立SSEController

首先我們建立一個普通的SpringMVC的Controller,命名為SSEContrller。下方就是SSEController類的具體實現,內容與普通的Controller差不多。只不過相應的方法在路由配置時,將produces屬性的文字型別設定成“text/event-stream”即可。

在下方類的push()方法中,每500ms就會往客戶端傳送一個訊息。訊息的內容是當前時間,如下所示:

  

2、建立請求的JSP頁面

建立好上述類後,我們就該建立測試上述Controller的JSP頁面了,我們在相應的資源目錄中建立一個sse.jsp頁面。在sse.jsp頁面中,我們將會使用到JavaScript中的EventSource物件來監聽來著“/sse”路由的事件訊息,當收到上述Controller發起的事件後,會在事件回撥中做一些事情。當然,我們做的事情就是在HTML頁面中新增新的節點,將事件響應的訊息新增到HTML文字只能怪進行顯示。

下方就是sse.jsp頁面的具體程式碼。

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 7 <script type="text/javascript" src="assets/js/jquery.js"></script>
 8 <script type="text/javascript">
 9      if(window.EventSource){
10         var source = new EventSource('sse');
11         s = '';
12         source.addEventListener('message', function (e) {
13             s += e.data+"<br/>";
14             $("#msgFromSSE").html(s);
15         });
16 
17         source.addEventListener('open', function (e) {
18             console.log("連線開啟");
19         }, false);
20 
21         source.addEventListener('error', function (e) {
22             if (e.readyState == EventSource.CLOSED) {
23                 console.log("連線關閉");
24             } else {
25                 console.log(e.readyState);
26             }
27         }, false);
28     } else {
29         console.log("瀏覽器不支援SSE");
30     } 
31 </script>
32 <title>SSE Demo</title>
33 </head>
34 <body>
35 <h1>SSE-TEST</h1>
36 <div id="msgFromSSE"></div>
37 </body>
38 </html>

3、測試我們的SSE

上面的事件傳送端以及事件監聽端的程式碼已實現完畢。接下來我們就要進行測試了。在測試之前,我們還要做一件事情,就是為我們的sse.jsp頁面新增訪問路由。我們就選擇在Spring的配置檔案中進行快速配置sse.jsp頁面的路由。下方就是sse.jsp路由配置的相關程式碼:

registry.addViewController("/ssetest").setViewName("/sse");

配置完上述路由後我們就可以訪問上述路由所對應的JSP頁面了,下方就是具體的執行效果。從下方演示效果中,我們不難看出,每隔一段時間就會收到來自服務端的訊息事件,具體如下所示:

  

三、Servlet中的非同步推送

接下來我們來使用Servlet的非同步處理以及Spring的任務計劃(定時器)來實現事件的推送。當然本部分的最終實現效果與上述效果是一樣的,只不過是實現方式不同。SSE是需要新式瀏覽器的支援,而Servlet的非同步方法進行推送是跨瀏覽器的。接下來我們就來好好的來實現該技術點。

1、 實現Servlet中的非同步推送前的配置

首先我們需要在Spring的配置檔案中進行配置,是我們的Spring支援計劃任務(Scheduleing),其實就是支援定時器。因為我們要定時的向客戶端進行push,所以定時器的配置是必須的。

  

啟動完定時器後,我們需要在Web初始化的類中開啟Servlet的非同步支援,如下所示。 

  

2、建立Push Service

相關配置完成後,接下來我們要做的就是建立我們的Push Service。該Service就負責往客戶端進行Push事件,Push Service的類物件就是我們相應Controller的依賴物件 ,稍後,我們將會將該依賴注入到相應的Controller中進行事件的Push。

下方就是PushService類的具體程式碼實現,需要使用@Service進行修飾。然後例項化一個DeferredResult物件負責傳遞事件訊息。我們用到了@Scheduled註解來設定每次推送的間隔。

  

上面用到了@Service註解,我們可以點進去看一下Service註解中的內容。從其原始碼中我們不難看出其實@Service和@Component用法是一至的。@Service註解的實現如下所示:

  

3、建立呼叫PushService的Controller

建立完PushService後,接著就建立一個呼叫PushService的Controller類。下方這個ServletAsyncController就是負責呼叫PushService物件的Controller。其中使用了@Autowired註解來宣告依賴注入的注入點。然後通過路由,路由到呼叫PushService的方法中即可。DeferredResult<String>就是推送事件的載體、而訊息的型別是String型別。具體實現如下所示:

  

4、接收事件的JSP頁面的實現

建立完Push Service以及負責推送的Controller後,接下來我們就該建立接收推送的客戶端程式碼了。下方的程式碼比較簡單,主要是使用jQuery來接收的推送事件。然後將推送的內容append到html中進行顯示,如下所示:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="assets/js/jquery.js"></script>
<script type="text/javascript">

    deferred();

    function deferred() {
        $.get('servlet_push', function (data) {
            $("#content").append(data+'<br/>');
            deferred();
        });
    }
</script>
<title>Servlet_Async</title>
</head>
<body>
    <div id='content'></div>
</body>
</html>

給上述JSP頁面配置路由的程式碼在此就省略了,和之前一樣,給上述JSP頁面在SpringConfig檔案中配置一個路由,此處是“/async_push”, 然後我們對該路由進行訪問,下方就是訪問效果,如下所: