環(huán)信聊天記錄保存到數據庫實體

發(fā)現環(huán)信的根據時間條件拉取歷史消息接口已經停用,就做了個通過導出聊天記錄接口保存到數據庫實體的功能,分享一下.

大致的思路:

   1.通過環(huán)信的接口,把前一天24小時的數據壓縮包下載到本地

    2.把下載后的文件解壓讀取處理,寫入到實體

    3.設置一個定時器,定時執(zhí)行.

1.通過環(huán)信接口拉取數據,并解壓讀取

環(huán)信接口地址

@Service
public class EaseMobService implements IEaseMobService{

    @Autowired
    private IChatMessageService chatMessageService;
    @Override
    public void saveChatMessages() {
        //下載文件保存路徑
        String filePath = "/opt/apache/chatFiles/";
        //未加時間戳的請求地址
        //OrgInfo.ORG_NAME  環(huán)信org_name  OrgInfo.APP_NAME 環(huán)信app_name
        String requestUrl = "http://a1.easemob.com/"+ OrgInfo.ORG_NAME + "/" + OrgInfo.APP_NAME + "/chatmessages/";
        //獲取前一天內的時間list
        List<String> hourList = DateUtils.getOneDayHourList(DateUtils.getBeforeDayDate(new Date(), 1));
        //環(huán)信token 自己寫一個工具類獲取token
        String token = TokenUtil.getAccessToken();
        //獲取下載地址
        for(String hour: hourList){
            try {
                String downloadUrl = HttpUtil.getEasemobChatMessageDownloadUrl(requestUrl + hour, token);
                if(!"fail".equals(downloadUrl)){
                    //下載壓縮文件到指定文件夾
                    String fileName = hour + ".gz";
                    String downLoadResult = HttpUtil.downloadFileByUrls(downloadUrl, fileName,filePath);
                    //下載成功進行解壓文件和讀取文件
                    if("ok".equals(downLoadResult)){
                        //解壓文件
                        String outPutFilePath = unZipFile(filePath + fileName);
                        //讀取文件
                        if(outPutFilePath.length() >0) {
                            String content = readFile2String(outPutFilePath);
                            //處理文本內容,寫入實體
                            if(content.length() > 0) {
                                chatMessageService.handleContent(content);
                            }
                        }
                    }
                }
                //延時執(zhí)行,環(huán)信下載接口有限流
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 讀取文件內容
    **/
    private String readFile2String(String outPutFilePath) {
        String content = "";
        String encoding = "UTF-8";
        File file = new File(outPutFilePath);
        Long fileLength = file.length();
        byte[] fileContent = new byte[fileLength.intValue()];
        try {
            FileInputStream in = new FileInputStream(file);
            in.read(fileContent);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            content = new String(fileContent, encoding).trim();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 解壓文件并返回解壓后的文件
    **/
    private String unZipFile(String filePath) {
        //解壓gz壓縮包
        String ouPutFile = "";
        try {
            //建立gzip壓縮文件輸入流
            FileInputStream fIn = new FileInputStream(filePath);
            //建立gzip解壓工作流
            GZIPInputStream gzIn = new GZIPInputStream(fIn);
            //建立解壓文件輸出流
            ouPutFile = filePath.substring(0,filePath.lastIndexOf('.'));
            FileOutputStream fOut = new FileOutputStream(ouPutFile);
            int num;
            byte[] buf=new byte[1024];

            while ((num = gzIn.read(buf,0,buf.length)) != -1)
            {
                fOut.write(buf,0,num);
            }
            gzIn.close();
            fOut.close();
            fIn.close();
        } catch (Exception e){
            e.printStackTrace();
        }
        return ouPutFile;
    }
}

DateUtils工具類方法

  /**
     * 獲取指定日期的一天小時集合yyyyMMddHH
    **/
    public static List<String> getOneDayHourList(Date date){
        List<String> hourList = new ArrayList<String>();
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
        String dateString = fmt.format(date);
        for(int i = 0; i < 24; i++) {
            String hour = String.valueOf(i);
            if(i < 10){
                hour = "0" + hour;
            }
            hourList.add(dateString + hour);
        }
        return hourList;
    }
/**
     * 獲取指定日期的前N天日期
    **/
public static Date getBeforeDayDate(Date date, int beforeDay)
    {
        Calendar a = Calendar.getInstance();
        a.setTime(date);
        a.add(Calendar.DATE, -beforeDay);
        return a.getTime();
    }

HttpUtil工具類

public class HttpUtil {

   private static Logger log = LoggerFactory.getLogger(HttpUtil.class);

    public static String getEasemobChatMessageDownloadUrl(String getUrl, String token) {
        String downloadUrl = "";
        try {
            URL url = new URL(getUrl);    //把字符串轉換為URL請求地址
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打開連接
            //設置Head參數
            connection.setRequestProperty("Content-Type", " application/json");//設定 請求格式 json,也可以設定xml格式的
            connection.setRequestProperty("Accept-Charset", "utf-8");  //設置編碼語言
            connection.setRequestProperty("Connection", "keep-alive");  //設置連接的狀態(tài)
            connection.setRequestProperty("Authorization", token);
            connection.connect();// 連接會話
            // 獲取輸入流
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {// 循環(huán)讀取流
                sb.append(line);
            }
            br.close();// 關閉流
            connection.disconnect();// 斷開連接
            //返回結果處理
            JSONArray jsonArray = JSON.parseArray("[" + sb.toString() + "]");
            JSONObject jsonObject = (JSONObject) jsonArray.get(0);
            JSONArray urlJSON = JSON.parseArray(jsonObject.get("data").toString());
            downloadUrl = ((JSONObject) urlJSON.get(0)).get("url").toString();
        } catch (Exception e) {
            return "fail";
        }
        return downloadUrl;
    }

    /**
     * 通過url下載文件到本地
    **/
    public static String  downloadFileByUrls(String urlStr,String fileName,String savePath){
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //設置超時間為3秒
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403錯誤
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到輸入流
            InputStream inputStream = conn.getInputStream();
            //獲取自己數組
            byte[] getData = readInputStream(inputStream);
            //文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {
                saveDir.mkdir();
            }
            File file = new File(saveDir + File.separator + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(getData);
            if (fos != null) {
                fos.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            return "ok";
        }catch (Exception e){
            e.printStackTrace();
            return "fail";
        }
    }


    /**
     * 從輸入流中獲取字節(jié)數組
     */
    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }
}

2.數據庫實體,及文本讀取內容處理

chat_message表

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for chat_message
-- ----------------------------
DROP TABLE IF EXISTS `chat_message`;
CREATE TABLE `chat_message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `msg_id` varchar(25) DEFAULT NULL,
  `timestamp` datetime DEFAULT NULL,
  `direction` varchar(50) DEFAULT NULL,
  `to_user` varchar(50) DEFAULT NULL,
  `from_user` varchar(50) DEFAULT NULL,
  `msg` varchar(255) DEFAULT NULL,
  `type` varchar(20) DEFAULT NULL,
  `url` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

文本處理

 /**
     * 處理環(huán)信返回的內容,寫入實體
     *
     * @param content
     */
    @Override
    public void handleContent(String content) {
        JSONArray jsonArray = JSON.parseArray("[" + content + "]");
        List<ChatMessage> chatMessageList = new ArrayList<ChatMessage>();
        for(int i = 0; i < jsonArray.size(); i++){
            ChatMessage chatMessage = new ChatMessage();
            JSONObject jsonObject = (JSONObject) jsonArray.get(i);
            JSONArray bodyJsons = (JSONArray)((JSONObject) jsonObject.get("payload")).get("bodies");
            for(int j = 0; j < bodyJsons.size(); j ++) {
                JSONObject bodyJson = (JSONObject) bodyJsons.get(j);
                chatMessage.setMsgId(jsonObject.getString("msg_id"));
                chatMessage.setTimestamp(new Date(Long.parseLong(jsonObject.getString("timestamp"))));
                chatMessage.setDirection(jsonObject.getString("direction"));
                chatMessage.setToUser(jsonObject.getString("to"));
                chatMessage.setFromUser(jsonObject.getString("from"));
                chatMessage.setMsg(bodyJson.getString("msg"));
                chatMessage.setType(bodyJson.getString("type"));
                chatMessage.setUrl(bodyJson.getString("url"));
                chatMessageList.add(chatMessage);
            }
        }
        //批量插入到數據庫
        getMapper().insertBatch(chatMessageList);
    }

用到了mybatis批量插入數據庫,貼一下chatMessageMapper的這一段

<insert id="insertBatch" parameterType="java.util.List"
          useGeneratedKeys="true">
    insert into chat_message (msg_id, timestamp, direction, to_user, from_user, msg, type, url)
    values
    <foreach collection="list" item="item" index="index" separator=",">
      (#{item.msgId,jdbcType=VARCHAR}, #{item.timestamp,jdbcType=TIMESTAMP},
      #{item.direction,jdbcType=VARCHAR},#{item.toUser,jdbcType=VARCHAR},#{item.fromUser,jdbcType=VARCHAR},
      #{item.msg,jdbcType=VARCHAR},#{item.type,jdbcType=VARCHAR},#{item.url,jdbcType=VARCHAR})
    </foreach>
  </insert>

3.再設置一個定時器定時執(zhí)行service就可以了,還可以根據實際項目需求設置定時清理從環(huán)信下載的壓縮包文件.

定時器

/**
 * 定時器實現
 *
 * @author Ray
 * @date 2018/1/27 10:35
 */
@Component
public class Timer implements ITimer{

    private static Logger log = LoggerFactory.getLogger(Timer.class);

    @Autowired
    IOrderService orderService;
    @Autowired
    ICouponService couponService;
    @Autowired
    IEaseMobService easeMobService;

    /*
1 Seconds (0-59)
2 Minutes (0-59)
3 Hours (0-23)
4 Day of month (1-31)
5 Month (1-12 or JAN-DEC)
6 Day of week (1-7 or SUN-SAT)
7 Year (1970-2099)
    取值:可以是單個值,如6氏淑;
    也可以是個范圍,如9-12簿训;
    也可以是個列表,如9,11,13
    也可以是任意取值米间,使用*
*/
    @Scheduled(cron = "0 0 12 * * ?")
    public void everyDay() {
        log.info("每日定時器執(zhí)行");
        //1.檢查訂單自動收貨
        orderService.checkReceiveConfirm();
        log.info("檢查訂單自動收貨");
        //2.失效用戶優(yōu)惠券
        couponService.updateCouponUseStatusOnTime();
        log.info("失效用戶優(yōu)惠券");
        //3.保存前一天聊天記錄
        easeMobService.saveChatMessages();
        log.info("保存前一天聊天記錄");
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末强品,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子屈糊,更是在濱河造成了極大的恐慌的榛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逻锐,死亡現場離奇詭異夫晌,居然都是意外死亡,警方通過查閱死者的電腦和手機昧诱,發(fā)現死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門晓淀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盏档,你說我怎么就攤上這事凶掰。” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵锄俄,是天一觀的道長。 經常有香客問我勺拣,道長奶赠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任药有,我火速辦了婚禮毅戈,結果婚禮上,老公的妹妹穿的比我還像新娘愤惰。我一直安慰自己苇经,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布宦言。 她就那樣靜靜地躺著扇单,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奠旺。 梳的紋絲不亂的頭發(fā)上蜘澜,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音响疚,去河邊找鬼鄙信。 笑死,一個胖子當著我的面吹牛忿晕,可吹牛的內容都是我干的装诡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼践盼,長吁一口氣:“原來是場噩夢啊……” “哼鸦采!你這毒婦竟也來了?” 一聲冷哼從身側響起咕幻,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤赖淤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谅河,有當地人在樹林里發(fā)現了一具尸體咱旱,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年绷耍,在試婚紗的時候發(fā)現自己被綠了吐限。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡褂始,死狀恐怖诸典,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情崎苗,我是刑警寧澤狐粱,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布舀寓,位于F島的核電站,受9級特大地震影響肌蜻,放射性物質發(fā)生泄漏互墓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一蒋搜、第九天 我趴在偏房一處隱蔽的房頂上張望篡撵。 院中可真熱鬧,春花似錦豆挽、人聲如沸育谬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膛檀。三九已至,卻和暖如春娘侍,著一層夾襖步出監(jiān)牢的瞬間宿刮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工私蕾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僵缺,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓踩叭,卻偏偏與公主長得像磕潮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子容贝,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理自脯,服務發(fā)現,斷路器斤富,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 國家電網公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數據交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,869評論 6 13
  • 好久沒有寫代碼了膏潮,今天自己開發(fā)了一個快遞查詢的微信小程序,把自己心得記錄下來方便以后鞏固满力。ps焕参,小程序學的太晚了,...
    徐薇薇閱讀 1,745評論 0 5
  • 深秋之后的時節(jié)油额, 多半成熟幽暗叠纷, 寧靜成一片低調著的希望, 這亦是生命孕育生長的傳奇潦嘶。 淹沒在時光里的不息生命涩嚣, ...
    心羽自心閱讀 152評論 0 3
  • 當炮火擊碎大門的那一刻,當嘶吼回蕩天空的那一刻,當尸體橫躺街頭的那一刻航厚,城市變作了地獄顷歌,人間化作了煉獄,也許這就是...
    苦中甘閱讀 476評論 0 1