日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

某电商平台开发记要——客服系统

發布時間:2025/4/5 windows 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 某电商平台开发记要——客服系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

假如網站需要提供客服功能,如果只是簡單的聊天咨詢可以考慮營銷QQ、百度商橋等(目前大部分網站采用此方式,包括一些知名行業電商);如果需要更精細化的管理,比如客服人員安排、各項數據統計匯總,那么需要對接專業的第三方客服平臺,比如網易七魚,當然價格不菲;然而若是如京東本身就是一個平臺,需要為每個商家提供各自的客服管理,首先目前第三方提供商并無此類產品(網易七魚據說已經開發出來了,但是官網上沒找到),其次即使有,價格也肯定不便宜,而且數據在別人那里總歸不好。所以電商平臺的客服系統,一般都是自己開發。當然了,借助優秀的開源項目,自主開發[一套簡單能用的]也變得輕松很多。

我采用了openfire+spark+layim,前兩者基于java平臺,layim是國人開發的一個webim前端組件。

先來看大致效果(左邊是瀏覽器layim-客戶提咨詢,右邊是spark聊天窗口-客服解答)

圖示:

本文涉及到的知識點(雜亂,后續會不定期添加內容):

Java基礎

Intellij Idea:Java IDE

Mybatis:半ORM

XMPP協議

smack:XMPP協議的Java封裝

openfire

fastpath:openfire插件,我們需要依賴它實現客服功能

wechat

spark


一秒鐘入門Java

Java SE(J2SE):Standard Edition,可認為是基礎庫,用于開發和部署桌面、服務器以及嵌入設備(J2ME)和實時環境中的Java應用程序。

Java EE(J2EE):基于SE的高級庫,提供 Web 服務、組件模型、管理和通信 API,可以用來實現企業級的面向服務體系結構。

可以知道J2EE比J2SE多了Web相關的組件和API,但是本人在使用SpringMVC框架開發Web應用程序時,去官網Java SE頁面下載的JDK,也能正常開發。后來查看官網的Java EE的下載頁面,發現提供的SDK中主要包含一個叫GlassFish的開源組件和一些示例及文檔,而Java EE剛開始是以一種規范提出,GlassFish可以看作是實現了這些規范的JEE容器,而我們開發Web站點時部署到服務器(比如Tomcat),實現了JEE規范其中的Servlet容器部分,所以以JDK開發Web并不會出現問題。

JNDI 是什么

目前流行的IDE有Eclipse和IntelliJ IDEA,前者免費且由于歷史關系占有率一直很高,后者也有社區版,據說使用性上目前完勝前者。

final關鍵詞:類似于.NET的readonly

匿名內部類

定義一個類A(可以為abstract),為方便說明,在A中定義一個[抽象]方法dosth。在調用方法里可以直接new A,并且同時給dosth賦方法體。

public abstract A{ public void dosth() {} }public abstract B{ public void call() {final A a = new A() {public void dosth() {//這里寫方法體 }};} }

看著是實例化了A的一個對象,其實是實例化了A類的匿名子類。

Access restriction:eclipse對某些java包(or 類?)有access rules,比如 sun.awt.shell.ShellFolder。因為這些JAR默認包含了一系列的代碼訪問規則(Access Rules),如果代碼中引用了這些訪問規則所禁止引用類,那么就會提示這個錯誤信息。解決方法:既然存在訪問規則,那么修改訪問規則即可。打開項目的Build Path Configuration頁面,打開引用的[報錯]JAR包,選中Access rules條目,選擇右側的編輯按鈕,添加一個訪問規則即可。

Java NIO

Apache Mina

CopyOnWrite:CopyOnWrite容器即寫時復制的容器。通俗的理解是當我們往一個容器添加元素的時候,不直接往當前容器添加,而是先將當前容器進行Copy,復制出一個新的容器,然后新的容器里添加元素,添加完元素之后,再將原容器的引用指向新的容器。這樣做的好處是我們可以對CopyOnWrite容器進行并發的讀,而不需要加鎖。從JDK1.5開始Java并發包里提供了兩個使用CopyOnWrite機制實現的并發容器,它們是CopyOnWriteArrayList和CopyOnWriteArraySet。

Maven:項目管理工具。不像VS,eclipse是更純粹的編碼工具,在維護jar包和項目之間的依賴關系、項目的構建目標等方面的功能比較弱(比如拷貝了一個項目,我們需要手動去Configure Build Path),而Maven就是補足于此。Maven獨立于IDE,eclipse有一個插件叫M2E,里面內置了Maven。Maven項目的配置信息保存在pom.xml文件中。

我們在導入Maven項目時,有時會發現不止一個pom.xml,那是因為項目中有子項目(module,module有自己的pom.xml),只要選擇最頂層的pom.xml文件即可,會自動加載引用到的子項目。

JavaBean:一般可看作是POJO,可參看?Java Bean 是個什么概念??(不過這個問題里有個答主說Java沒有事件的概念,讓我大吃一驚,不過轉念一想,Java主要用于開發服務端應用,確實不怎么涉及到[自定義]事件。其實Java中是有事件機制的,只是不知變通,就一個半成品的觀察者模式,想想C#的委托,其實就一個函數指針的事)

MVC:當.Neter們在被Asp.Net的重量壓得踹不過氣來的時候,Java已經有MVC的概念了。很多模式,.Net界都是直接copy,.Neter們并沒有對其歷史的認知,所以接收不能,MVC就是如此。其實在Asp.Net時代已經有MVC的影子,就是一般處理程序.ashx。很早以前,用戶提交都是提交到具體的一個頁面,于是會經常導致一個頁面并不是用于顯示,而是用于業務邏輯的處理,于是后來把業務邏輯單獨拎出來,這便是Controller,用戶請求的是Controller,不再是具體頁面,并且Controller里不再使用類似HttpRequest或者HttpResponse獲取數據和返回響應,而是使用對象的形式(M),這便是MVC模式。可參看?Java Web開發模式

Java中的注解相當于.NET中的Attribute。

Spring是一個IOC和AOP框架。我們可以通過在xml文件中配置bean,然后在代碼中使用@Autowired或@Resource注入bean實例,不過配置的環節稍顯繁瑣,能不能省略呢?答案是肯定的,Sping2.5開始支持注解注入,具體可看 spring注解注入:<context:component-scan>詳解。需要注意的是,@Component及相關的幾個注解類,在應用到interface上的時候,可能并不如預期工作,因為interface并不能實例化,而這幾個注解類貌似又沒有@Inherited修飾,所以就算有實現類或運行時的動態實現類,也不會注冊到上下文中;且修飾的類要有公共構造函數。另外注入[被注入方]一般只能在注入方本身是已注冊的bean里,若在普通類里想通過@Autowired或@Resource的方式注入bean,則稍微有點繞,可參看?Java普通類獲取Spring XML中Bean的方法總結

關于Servlet、Struts、Spring、SpringMVC的關系與區別可參看?Java開發web的幾種開發模式 和?SpringMVC與Struts2的對比

SpringMVC竟然URL和參數大小寫敏感,雖然有辦法配置,但這種預設沒有道理吧。。。

Servlet url-pattern /與/*區別:兩者的長度不同,根據最長路徑匹配的優先級,/*比/更容易被選中,而/的真正含義是,缺省匹配。既所有的URL都無法被選中的時候,就一定會選中/,可見它的優先級是最低的,這就兩者的區別。

xml文件也可以打包進jar包,但是訪問jar包里的xml文件就不能按文件目錄的方式來了,可參看?http://blog.csdn.net/jianxin1009/article/details/18814799?

application.getInitParameter:jsp中9個內置對象之一application,它的數據對整個web應用都有效,application有一個重要的用途就是通過getInitParameter()獲取web.xm中的配置參數,這樣可以提高代碼的移植性。

dwr:簡化ajax調用,使得調用遠程服務器方法看上去像調用本地方法一樣。

在java項目中必不可少的是我們要指定一個jdk。在指定jdk的同時,還可以指定jdk的Language level,這個有點像我們工程最低支持版本。比如Language level 設置了5.0 只是就不能出現使用6.0/7.0特性的代碼,因為這些特性在5.0的環境下是無法編譯的。或者可以理解ide會安裝Language level指定的jdk版本來對我們的代碼進行編譯,以及錯誤檢查。即同樣的jdk對應不同的Language Level會采用[可能]不同的編譯和優化方式。

Java中也有類似.Net的字符串池的概念,請看?String中intern的方法

Java插件技術: OSGi

貌似在同一package下,protected可見。(和.NET不同)

Java的泛型類型只能是引用類型,而不能是基礎類型,但是Java針對每個基礎類型有對應的封裝類型,比如boolean對應Boolean,后者是引用類型,可以為null,當封裝類型不為null時,可以隱式轉換,但寫代碼時null的情況要自己處理,如

private boolean existUser(String username) {Boolean result = null; return result != null && result.booleanValue(); }

Ant:類似于.NET的MSBuild,其構建文件默認為build.xml(可以在其中指定構建基于的Java平臺版本),每個構建文件都對應于一個項目,但是大型項目經常包含大量的子項目,每一個子項目都可以有自己的構建文件。

一個.java文件中可以定義多個類,但是public修飾的只能至多有一個,且要與文件名相同,編譯后,有幾個類就會產生幾個對應的.class文件。jar包類似.Net的dll,它將多個.class文件打包一塊。大多數?JAR?文件包含一個?META-INF?目錄,它用于存儲包和擴展的配置數據,如安全性和版本信息。Java 2?平臺識別并解釋?META-INF?目錄中的下述文件和目錄,以便配置應用程序、擴展和類裝載器。具體可看?MANIFEST.MF 文件內容完全詳解。

System.getProperty()獲取系統/項目全局變量,比如Java運行時版本,當然我們也可以通過System.setProperty()設置自定義變量。

Java桌面客戶端編程:Java Swing 。桌面程序畢竟不是Java的主流領域,因此各IDE貌似也并未作太多努力,相較VS的所見即所得的控件拖拽開發模式,Java GUI編程就吃力很多了。

Java國際化:i18n,注意中文的資源文件,貌似需要先UTF-8轉碼,大約就是像這樣。(可以使用JDK自帶的native2ascii.exe)


Intellij Idea

使用Intellij Idea創建spring mvc時(沒用maven),run都報?Error during artifact deployment. See server log for details 錯誤,后來把lib文件夾拷到WEB-INFO文件夾下就沒問題了,不知何故。

原因:tomcat默認是去web-info/lib/下找依賴的jar包。手動拷jar包畢竟不是一個好辦法,其實我們可以在下圖處進行Artifacts設置

運行項目,項目目錄下會多出一個out文件夾,生成所有的站點文件,依賴包會自動拷貝到下面的WEB-INF/lib/下,如下圖:

IDEA配置artifacts中Web Application:Exploded和Web Application:Archive的區別:前者以文件夾形式(War Exploded)發布項目,后者以war包形式(每次都會重新打包全部的)。Tomcat會自動解壓war包并啟動站點,缺點是會造成一段時間的站點不可用,而以文件夾形式發布的話,則支持熱部署(需進行額外的一些配置)。

當然我們也可以使用Maven進行依賴包的管理。在當前項目右鍵->Add Framework Support->Maven即可。注意需要在Project Structure-> Project Settings中移除之前非Maven引用的包依賴。此時運行項目,項目目錄下會多出一個target文件夾,其下有生成的站點文件。但是運行時發現WEB-INF下的文件除了web.xml外,其它的文件都不會覆蓋,貌似用maven管理的web工程,需要將applicationContext.xml等資源文件放在resource目錄下,然后以classpath的方式去訪問。后來發現jsp頁面也無法自動更新到target目錄,再后來聽說maven有一套約定的目錄結構,貌似又可以通過pom.xml進行自定義配置,神煩!目前靠手動覆蓋。參考?Maven使用點滴?配置即可(webappDirectory我沒設置,就設置了warSourceDirectory,能正常更新了

Intellij Idea中有個Ant Build Window,默認顯示的是主項目下build.xml中的targets,and?by default, IDEA only shows the default target and targets that have descriptions。對這個有疑問可參看?How to get Ant Build to list all targets in a hierarchy of build files.

可以在Run/Debug Configurations Window中設置自定義系統變量,如下圖(-D不能省):


MyBatis

一個半ORM框架,SQL語句并不是像EF一樣由框架解析,而是要預先寫在xml中或者寫在Java注解(同.Net的Attribute)中,且不支持匿名類型(即select出來的數據要么是基礎類型,要么要有對應的Java Bean)。一般情況下,我們使用resultType映射查詢結果和對象即可(MyBatis 會在幕后自動創建一個 ResultMap),當只想映射部分字段或者包含復雜類型屬性的時候,我們需要自定義ResultMap。

MyBatis不支持方法重載,因為它是通過方法名稱(不加參數)去查找執行方法,因此我們設置不同的方法名,或者使用動態sql。


XMPP協議

JID表示一個地址,由三部分組成——node、domain和resource。例如:xiaoming@xiaoming.home/sleeping,xiaoming就是node ,xiaoming.home就是domain,sleeping就是resource。node domain 和resource任何一部分都不能超過1023 字節 ,加上@和 /,一個JID 總共不能超過3071字節。BareJid就是去掉resource,只包含node@domain。

XMPP包含IQ, message and presence 三種packet。


smack

ConnectionConfiguration.Builder的setXmppDomain和setHost的區別?一個是域(服務器集群),一個是其中的一臺服務器,應該只要設置其中一個就可以了。

使用XMPPTCPConnectionConfiguration建立連接時報空指針錯誤,調試發現有個base64encoder未賦值,需要引用smack-java7包,該包會初始化base64encoder,如果是安卓開發,那么就引用smack-android。


openfire?

使用idea導入openfire代碼,過程可參考將openfire源碼部署到IDEA中 或者?IntelliJ IDEA搭建openfire4.1.3開發環境 。使用openfire配置界面只能配置一個數據庫,且我也不打算完全依賴它生成的數據庫。我需要openfire部分功能使用現有的數據庫(比如用戶表),而openfire的業務數據仍然使用生成的數據庫,因此涉及到多庫連接。這只能去修改源碼了。

上面說到的配置界面設置的項最終存儲在ofproperty表中。在配置界面完成配置后,我們也可以在conf/openfire.xml中重新設置值,重啟openfire,配置文件中的值會更新到數據庫中。

以AuthFactory為例,其initProvider方法里有?JiveGlobals.migrateProperty("provider.auth.className"); ,XMLProperties根據"provider.auth.className"讀取xml文件中的值(getProperty方法)

//按逗號拆分為數組 String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML hierarchy. Element element = document.getRootElement(); for (String aPropName : propName) {element = element.element(aPropName);if (element == null) {return null;} } value = element.getTextTrim();

對應的配置節寫法如下(可以看到,propName對應各層級element,而非attribute形式)

<provider><auth><className>org.jivesoftware.openfire.auth.JDBCAuthProvider</className></auth> </provider>

而后覆蓋數據庫值

public void migrateProperty(String name) {if (getProperty(name) != null) {if (JiveGlobals.getProperty(name) == null) {JiveGlobals.setProperty(name, getProperty(name));deleteProperty(name);}else if (JiveGlobals.getProperty(name).equals(getProperty(name))) {deleteProperty(name);}else if (!JiveGlobals.getProperty(name).equals(getProperty(name))) {Log.warn("XML Property '"+name+"' differs from what is stored in the database. Please make property changes in the database instead of the configuration file.");}} }

當然,若是我們有數據庫權限,直接進入數據庫修改也一樣。

openfire源碼采用JDBC方式操作數據庫,而且沒有做很好的封裝,重復代碼較多,如下圖所示

相似代碼在與數據庫交互的地方隨處可見。部分邏輯的抽取,莫過于lambda(回調函數)的方式。考慮到Java8已經支持lambda表達式,重構如下:

public <T> T excuteQuery(String queryText, Function<ResultSet, T> func) {T result = null;Connection con = null;PreparedStatement pstmt = null;ResultSet rs = null;try {con = getConnection();pstmt = con.prepareStatement(queryText);rs = pstmt.executeQuery();if (rs.next()) {result = func.apply(rs);}} catch (SQLException e) {Log.error(e.getMessage(), e);} finally {DbConnectionManager.closeConnection(rs, pstmt, con);}return result; }

但是在寫調用代碼的時候提示:

雖然我們在excuteQuery方法中已經catch了這個異常,但是編譯器并不買賬。而且就算我們在方法定義時已經throws了相關異常,也沒用,如下圖:

解決方法有兩種:可以在lambda體內catch異常后不再throw;或者自定義一個Functional Interface,其中聲明一個定義了異常的方法,

@FunctionalInterface public interface CheckedSQLExceptionFunction<T, R> {R apply(T t) throws SQLException; }

然后將Function<Result,T>的地方替換為CheckedSQLExceptionFunction<ResultSet, T>。這兩種都顯得別扭與不合理,導致這一問題的是,Java Lambda規定如果Lambda中拋出了異常,那么這個異常一定要在Functional Interface中的abstract方法上定義。這是一個讓人無法理解的規定。

遇到lambda的另一個坑:

由于username有重新賦值,所以編譯報錯,是不是很喜感?我不得不用一個臨時變量解決。。

官方提供了一種集成外部用戶體系的方法(Custom Database Integration Guide),然后并不支持加鹽密碼,于是我只能自己擼碼解決。關鍵是實現兩個接口:AuthProvider 和 UserProvider,只要實現部分方法即可,很簡單不贅述。

部署

部署到centos7。首先?rpm -qa | grep openjdk 查看所有已安裝的jdk,如果版本不滿足則先 rpm -e --nodeps [java-1.7.0-openjdk[-headless]] 卸載掉。然后去官網上下載合適版本的server jre/jre/sdk包(下面會進一步說明),然后解壓,設置環境變量,就算安裝完畢了(不過這種安裝方式通過rpm -qa可是找不到的哦)。具體可看?Centos7 JDK8安裝配置。

講道理,jdk是開發時候用的,部署的話我們只要安裝jre就可以了。我剛開始下載的是server jre包,在ant的時候報 package javafx.util does not exist 的錯(因為我在代碼里用到了Pair<>二元組,屬于javafx.util包),然而網上查了下,貌似javaFX是用于客戶端GUI方面的組件(不知道是否我這里報錯的javafx同個概念)。我懶得探究,馬上去官網下了jre包(官網說Covers most end-users needs. Contains everything required to run Java applications on your system.),載下來之后發現果然有jfxrt.jar(包含javafx.util),歡欣鼓舞,但是ant之后報無法找到/lib/tools.jar——因為build.xml里有用到這個jar——之前server jre是有的,也是日了狗了。馬上去下jdk,瘋狂操作之后終于編譯通過。

也可以在windows平臺編譯打包,然后拷貝到linux系統。

官網上是說./openfire start啟動openfire,然而我只找到openfire.bat和openfirectl,先試了./openfirectl start 報錯:Could not find Openfire installation under /opt,/usr/share,or /usr/local,查看openfirectl的shell代碼,發現當OPENFIRE_HOME未設置時,會去這三個目錄下找openfire,于是為其設置真實根目錄,然而雖沒報錯,但還是沒有運行起來。試了下openfire.bat,報Permission denied,尼瑪,我可是用root登錄的。先不管原因,我再去官網下了4.1.6(目前最新版)的tar包,發現bin目錄下果然有個openfire文件,拷到服務器上后報同樣的Permission denied的錯誤——網上說root并不默認就有所有文件的最高權限,但是他可以隨意給自己增加權限——好吧,設置了權限之后,執行./openfire start 沒報錯,但是依舊沒有運行起來。。。后來發現沒有輸出錯誤信息,是因為shell里寫了/dev/null 2>&1,去掉之后終于提示——Could not find or load main class com.install4j.runtime.launcher.UnixLauncher——shell代碼里該類指向的目錄本地編譯不存在,最后在官網tar包里發現有一個名為.install4j的隱藏文件夾,拷貝后總算運行起來了。?

記得打開相應端口。


webchat

用戶一般都是通過瀏覽器進行咨詢,有個webchat示例可以參考(openfire4.2 配置fastpath、webchat、spark實現客服系統),但那是基于很久以前的smack版本,轉過來也費了不少勁,特別是QueueUpdate包擴展已經不再內置支持,調試了半天在smack中找到幾個關鍵文件,這些都是內置資源文件,項目運行時會讀取這些文件,調用ProviderManager.addExtensionProvider將配置項緩存起來,如果不修改xml的話,那么在外部調用該方法也是可以的。參照著寫了一個QueueUpdateProvider,順便了解了下XmlPullParser的用法。

關于自定義包和擴展,后來才發現官網上有介紹: Provider Architecture: Stanza Extensions and Custom IQ's,也是心累。

再后來,發現部分非內置的擴展的Provider已經在擴展類里[作為內部類]定義好了,比如QueueUpdate.Provider。。。吐血。關于內部類可參看?java中的內部類總結

部署

在CentOS安裝tomcat9.0.1。去官網下載tar.gz包,解壓,然后去到bin目錄,在catalina.sh文件添加內容export CLASSPATH=$JAVA_HOME/lib,然后./startup.sh即可,另外記得開放8080端口。當然我們可以更改端口以及綁定域名,參考?tomcat發布應用并配置域名。關于項目打包成war包,參考?Intellij IDEA社區版打包Maven項目成war包,并部署到tomcat上。


fastpath

增加幾個http接口,如新增客服組,添加客服等,示例代碼如下:

public class MasonServlet extends HttpServlet {@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);AuthCheckFilter.addExclude("fastpath/mason/*"); // 公共接口不需身份校驗 }@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String action = request.getRequestURI();action = action.substring(action.indexOf("mason/") + 6);OPResult result = null;if (action.toLowerCase().equals("createworkgroup")) {String wgName = request.getParameter("wgName");String description = request.getParameter("description");String agents = request.getParameter("agents");result = createWorkgroup(wgName, description, agents);}if (result == null) {result = new OPResult();result.setSuccess(false);result.setMessage("未找到對應方法");}response.setContentType("application/json; charset=utf-8");response.setCharacterEncoding("UTF-8");Genson genson = new Genson();String json = genson.serialize(result);response.getOutputStream().write(json.getBytes("UTF-8"));}// 新增工作組(會同時建立一個默認客服組,每個工作組可以包含多個客服組)private OPResult createWorkgroup(String wgName, String description, String agents) {OPResult result = new OPResult();Map errors = WorkgroupUtils.createWorkgroup(wgName, description, agents);if (errors.size() == 0) {Workgroup workgroup = WorkgroupManager.getInstance().getWorkgroup(wgName);result.setData(workgroup.getJID());result.setSuccess(true);} elseresult.setSuccess(false);return result;} }

完了我們就可以重新構建該插件了,在intellij中可以在窗口中設置(看了下build.xml,發現plugin任務可以構建單個插件,它接收plugin的參數表明構建的是哪個插件):

?

由于代碼中用到了genson這個第三方jar包,雖然直接編譯沒問題(項目的其它地方有引用),但用ant構建的時候會報錯,提示找不到這個組件,原因官網說了:Any JAR files your plugin needs during compilation should be put into the lib directory,因此我們需要將該jar包復制一份到fastpath/lib目錄下。


spark

此spark非彼spark,而是一個開源IM桌面客戶端。下載下來2.8.3代碼,導入到IntelliJ,運行輸出了空指針異常,調試發現找不到資源文件?"META-INF/plugins.xml",查看編譯后的jar文件,里面已經包含了resources/META-INF/plugins.xml。再查看Project Structure,發現沒有為主模塊Spark設置Resource Folders,添加了resources文件夾后編譯運行正常,此時再看jar文件,里面并沒有resources目錄,META-INF直接在根目錄體現。

也就是說,將某個目錄設置為資源文件夾(Resource Folders),意即將該目錄下的子目錄一起打包進jar包(不包含該目錄本身),而getResource()方法獲取特定路徑的資源時,是直接去jar包根目錄下查找對應文件。

似乎還要設置VM arguments:-Djava.library.path=build/lib/dist/windows64,具體值按照操作系統來。參看?openfire-spark 二次開發-(二)運行環境配置

?

相關資料:TCP長連接與短連接、心跳機制

?

轉載請注明本文出處:http://www.cnblogs.com/newton/p/7269373.html

總結

以上是生活随笔為你收集整理的某电商平台开发记要——客服系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。