java代碼網(wǎng)頁聊天 java實(shí)現(xiàn)網(wǎng)頁聊天

怎樣用java web和websocket實(shí)現(xiàn)網(wǎng)頁即時(shí)通訊

原理

成都創(chuàng)新互聯(lián)公司,為您提供網(wǎng)站建設(shè)公司、成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設(shè)計(jì),對(duì)服務(wù)PE包裝袋等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!

WebSocket protocol 。

現(xiàn)很多網(wǎng)站為了實(shí)現(xiàn)即時(shí)通訊,所用的技術(shù)都是輪詢(polling)。輪詢是在特定的的時(shí)間間隔(如每1秒),由瀏覽器對(duì)服務(wù)器發(fā)出HTTP request,然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端的瀏覽器。這種傳統(tǒng)的HTTP request 的模式帶來很明顯的缺點(diǎn) – 瀏覽器需要不斷的向服務(wù)器發(fā)出請(qǐng)求,然而HTTP request 的header是非常長(zhǎng)的,里面包含的有用數(shù)據(jù)可能只是一個(gè)很小的值,這樣會(huì)占用很多的帶寬。

而比較新的技術(shù)去做輪詢的效果是Comet – 用了AJAX。但這種技術(shù)雖然可達(dá)到全雙工通信,但依然需要發(fā)出請(qǐng)求。

在 WebSocket API,瀏覽器和服務(wù)器只需要做一個(gè)握手的動(dòng)作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。在此WebSocket 協(xié)議中,為我們實(shí)現(xiàn)即時(shí)服務(wù)帶來了兩大好處:

1. Header

互相溝通的Header是很小的-大概只有 2 Bytes

2. Server Push

服務(wù)器的推送,服務(wù)器不再被動(dòng)的接收到瀏覽器的request之后才返回?cái)?shù)據(jù),而是在有新數(shù)據(jù)時(shí)就主動(dòng)推送給瀏覽器。

一、項(xiàng)目簡(jiǎn)介

WebSocket是HTML5一種新的協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,這里就將使用WebSocket來開發(fā)網(wǎng)頁聊天室,前端框架會(huì)使用AmazeUI,后臺(tái)使用Java,編輯器使用UMEditor。

二、涉及知識(shí)點(diǎn)

網(wǎng)頁前端(HTML+CSS+JS)和Java

三、軟件環(huán)境 Tomcat 7 JDK 7 Eclipse JavaEE 現(xiàn)代瀏覽器

四、效果截圖

效果1

效果2

五、項(xiàng)目實(shí)戰(zhàn)

1. 新建項(xiàng)目

打開Eclipse JavaEE,新建一個(gè)名為Chat的Dynamic Web Project,然后導(dǎo)入處理JSON格式字符串所需要的包,把commons-beanutils-1.8.0.jar、commons-collections-3.2.1.jar、commons-lang-2.5.jar、commons-logging-1.1.1.jar、ezmorph-1.0.6.jar和json-lib-2.4-jdk15.jar這幾個(gè)包放在WebContent/WEB-INF/lib目錄下,最后把項(xiàng)目發(fā)布到Tomcat服務(wù)器上,到此空項(xiàng)目就搭建完成了。

2. 編寫前端頁面

在WebContent目錄下新建一個(gè)名為index.jsp的頁面,這里使用了AmazeUI框架,它是一個(gè)跨屏自適應(yīng)的前端框架,消息輸入框使用了UMEditor,它是一個(gè)富文本在線編輯器,能讓我們的消息內(nèi)容多姿多彩。

首先從 AmazeUI官網(wǎng) 下載壓縮包,然后解壓把a(bǔ)ssets文件夾拷貝到WebContent目錄下,這樣我們就能使用AmazeUI了。

再從 UEditer官網(wǎng) 下載Mini版的JSP版本壓縮包,解壓后把整個(gè)目錄拷貝到WebContent目錄下,接下來就可以編寫前端代碼了,代碼如下(你可以按照自己的喜好編寫):

?

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 ? ?%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%!DOCTYPE htmlhtml lang="zh"headmeta charset="utf-8"meta http-equiv="X-UA-Compatible" content="IE=edge"meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"titleShiYanLou Chat/title!-- Set render engine for 360 browser --meta name="renderer" content="webkit"!-- No Baidu Siteapp--meta http-equiv="Cache-Control" content="no-siteapp" /link rel="alternate icon" href="assets/i/favicon.ico"link rel="stylesheet" href="assets/css/amazeui.min.css"link rel="stylesheet" href="assets/css/app.css"!-- umeditor css --link href="umeditor/themes/default/css/umeditor.css" rel="stylesheet"style.title {?text-align: center;}.chat-content-container {?height: 29rem;?overflow-y: scroll;?border: 1px solid silver;}/style/headbody?!-- title start --?div class="title"??div class="am-g am-g-fixed"???div class="am-u-sm-12"????h1 class="am-text-primary"ShiYanLou Chat/h1???/div??/div?/div?!-- title end --?!-- chat content start --?div class="chat-content"??div class="am-g am-g-fixed chat-content-container"???div class="am-u-sm-12"????ul id="message-list" class="am-comments-list am-comments-list-flip"/ul???/div??/div?/div?!-- chat content start --?!-- message input start --?div class="message-input am-margin-top"??div class="am-g am-g-fixed"???div class="am-u-sm-12"????form class="am-form"?????div class="am-form-group"??????script type="text/plain" id="myEditor" style="width: 100%;height: 8rem;"/script?????/div????/form???/div??/div??div class="am-g am-g-fixed am-margin-top"???div class="am-u-sm-6"????div id="message-input-nickname" class="am-input-group am-input-group-primary"?????span class="am-input-group-label"i class="am-icon-user"/i/span?????input id="nickname" type="text" class="am-form-field" placeholder="Please enter nickname"/????/div???/div???div class="am-u-sm-6"????button id="send" type="button" class="am-btn am-btn-primary"?????i class="am-icon-send"/i Send????/button???/div??/div?/div?!-- message input end --?!--[if (gte IE 9)|!(IE)]!--?script src="assets/js/jquery.min.js"/script?!--![endif]--?!--[if lte IE 8 ]?script src=""/script?![endif]--?!-- umeditor js --?script charset="utf-8" src="umeditor/umeditor.config.js"/script?script charset="utf-8" src="umeditor/umeditor.min.js"/script?script src="umeditor/lang/zh-cn/zh-cn.js"/script?script??$(function() {???// 初始化消息輸入框???var um = UM.getEditor('myEditor');???// 使昵稱框獲取焦點(diǎn)???$('#nickname')[0].focus();??});?/script/body/html ?

編寫完成之后啟動(dòng)Tomcat服務(wù)器,然后訪問 ? ,會(huì)看到如下界面。

3. 編寫后臺(tái)代碼

新建一個(gè)com.shiyanlou.chat的包,在包中創(chuàng)建一個(gè)名為ChatServer的類,從JavaEE 7開始就統(tǒng)一了WebSocket的API,因此無論是什么服務(wù)器,用Java寫的代碼都是一樣的,代碼如下:

?

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 ? ?package com.shiyanlou.chat;import java.text.SimpleDateFormat;import java.util.Date;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import net.sf.json.JSONObject;/**?* 聊天服務(wù)器類?* @author shiyanlou?*?*/@ServerEndpoint("/websocket")public class ChatServer {?private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");? // 日期格式化?@OnOpen?public void open(Session session) {??// 添加初始化操作?}?/**??* 接受客戶端的消息,并把消息發(fā)送給所有連接的會(huì)話??* @param message 客戶端發(fā)來的消息??* @param session 客戶端的會(huì)話??*/?@OnMessage?public void getMessage(String message, Session session) {??// 把客戶端的消息解析為JSON對(duì)象??JSONObject jsonObject = JSONObject.fromObject(message);??// 在消息中添加發(fā)送日期??jsonObject.put("date", DATE_FORMAT.format(new Date()));??// 把消息發(fā)送給所有連接的會(huì)話??for (Session openSession : session.getOpenSessions()) {???// 添加本條消息是否為當(dāng)前會(huì)話本身發(fā)的標(biāo)志???jsonObject.put("isSelf", openSession.equals(session));???// 發(fā)送JSON格式的消息???openSession.getAsyncRemote().sendText(jsonObject.toString());??}?}?@OnClose?public void close() {??// 添加關(guān)閉會(huì)話時(shí)的操作?}?@OnError?public void error(Throwable t) {??// 添加處理錯(cuò)誤的操作?}} ?

4. 前后臺(tái)交互

后臺(tái)寫完了,前臺(tái)要用WebSocket連接后臺(tái),需要新建一個(gè)WebSocket對(duì)象,然后就可以和服務(wù)器端進(jìn)行交互,從瀏覽器發(fā)送消息給服務(wù)器端,同時(shí)要驗(yàn)證輸入框的內(nèi)容是否為空,然后接受服務(wù)端發(fā)送的消息,把它們動(dòng)態(tài)地添加到聊天內(nèi)容框中,在

?

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 ? ?var um = UM.getEditor('myEditor');$('#nickname')[0].focus();// 新建WebSocket對(duì)象,最后的/websocket對(duì)應(yīng)服務(wù)器端的@ServerEndpoint("/websocket")var socket = new WebSocket('ws://${pageContext.request.getServerName()}:${pageContext.request.getServerPort()}${pageContext.request.contextPath}/websocket');???// 處理服務(wù)器端發(fā)送的數(shù)據(jù)???socket.onmessage = function(event) {????addMessage(event.data);???};???// 點(diǎn)擊Send按鈕時(shí)的操作???$('#send').on('click', function() {????var nickname = $('#nickname').val();????if (!um.hasContents()) {??? // 判斷消息輸入框是否為空?????// 消息輸入框獲取焦點(diǎn)?????um.focus();?????// 添加抖動(dòng)效果?????$('.edui-container').addClass('am-animation-shake');?????setTimeout("$('.edui-container').removeClass('am-animation-shake')", 1000);????} else if (nickname == '') {??? // 判斷昵稱框是否為空?????//昵稱框獲取焦點(diǎn)?????$('#nickname')[0].focus();?????// 添加抖動(dòng)效果?????$('#message-input-nickname').addClass('am-animation-shake');?????setTimeout("$('#message-input-nickname').removeClass('am-animation-shake')", 1000);????} else {?????// 發(fā)送消息?????socket.send(JSON.stringify({??????content : um.getContent(),??????nickname : nickname?????}));?????// 清空消息輸入框?????um.setContent('');?????// 消息輸入框獲取焦點(diǎn)?????um.focus();????}???});???// 把消息添加到聊天內(nèi)容中???function addMessage(message) {????message = JSON.parse(message);????var messageItem = 'li class="am-comment '??????+ (message.isSelf ? 'am-comment-flip' : 'am-comment')??????+ '"'??????+ 'a href="javascript:void(0)" img src="assets/images/'??????+ (message.isSelf ? 'self.png' : 'others.jpg')??????+ '" alt="" width="48" height="48"http://a'??????+ 'divheaderdiv'??????+ 'a href="javascript:void(0)"'??????+ message.nickname + '/a time' + message.date??????+ '/time/div/header'??????+ 'div' + message.content??????+ '/div/div/li';????$(messageItem).appendTo('#message-list');????// 把滾動(dòng)條滾動(dòng)到底部????$(".chat-content-container").scrollTop($(".chat-content-container")[0].scrollHeight);???} ?

到這步,簡(jiǎn)單的網(wǎng)頁聊天室就完成了,你可以多開幾個(gè)窗口或在局域網(wǎng)中邀請(qǐng)小伙伴們來一起測(cè)試。

六、小結(jié)

本次項(xiàng)目課使用WebSocket實(shí)現(xiàn)了簡(jiǎn)單的網(wǎng)頁聊天室,其實(shí)WebSocket不僅可以應(yīng)用于瀏覽器,也可以應(yīng)用于桌面客戶端。

用JAVA 編寫簡(jiǎn)單網(wǎng)絡(luò)聊天程序

/**

* 基于UDP協(xié)議的聊天程序

*

* 2007.9.18

* */

//導(dǎo)入包

import java.awt.*;

import java.awt.event.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.*;

import java.net.*;

public class Chat extends JFrame implements ActionListener

{

//廣播地址或者對(duì)方的地址

public static final String sendIP = "172.18.8.255";

//發(fā)送端口9527

public static final int sendPort = 9527;

JPanel p = new JPanel();

List lst = new List(); //消息顯示

JTextField txtIP = new JTextField(18); //填寫IP地址

JTextField txtMSG = new JTextField(20); //填寫發(fā)送消息

JLabel lblIP = new JLabel("IP地址:");

JLabel lblMSG = new JLabel("消息:");

JButton btnSend = new JButton("發(fā)送");

byte [] buf;

//定義DatagramSocket的對(duì)象必須進(jìn)行異常處理

//發(fā)送和接收數(shù)據(jù)報(bào)包的套接字

DatagramSocket ds = null;

//=============構(gòu)造函數(shù)=====================

public Chat()

{

CreateInterFace();

//注冊(cè)消息框監(jiān)聽器

txtMSG.addActionListener(this);

btnSend.addActionListener(this);

try

{

//端口:9527

ds =new DatagramSocket(sendPort);

}

catch(Exception ex)

{

ex.printStackTrace();

}

//============接受消息============

//匿名類

new Thread(new Runnable()

{

public void run()

{

byte buf[] = new byte[1024];

//表示接受數(shù)據(jù)報(bào)包

while(true)

{

try

{

DatagramPacket dp = new DatagramPacket(buf,1024,InetAddress.getByName(txtIP.getText()),sendPort);

ds.receive(dp);

lst.add("【消息來自】◆" + dp.getAddress().getHostAddress() + "◆"+"【說】:" + new String (buf,0,dp.getLength()) /*+ dp.getPort()*/,0);

}

catch(Exception e)

{

if(ds.isClosed())

{

e.printStackTrace();

}

}

}

}

}).start();

//關(guān)閉窗體事件

this.addWindowListener(new WindowAdapter()

{

public void windowClosing(WindowEvent w)

{

System.out.println("test");

int n=JOptionPane.showConfirmDialog(null,"是否要退出?","退出",JOptionPane.YES_NO_OPTION);

if(n==JOptionPane.YES_OPTION)

{

dispose();

System.exit(0);

ds.close();//關(guān)閉ds對(duì)象//關(guān)閉數(shù)據(jù)報(bào)套接字

}

}

});

}

//界面設(shè)計(jì)布局

public void CreateInterFace()

{

this.add(lst,BorderLayout.CENTER);

this.add(p,BorderLayout.SOUTH);

p.add(lblIP);

p.add(txtIP);

p.add(lblMSG);

p.add(txtMSG);

p.add(btnSend);

txtIP.setText(sendIP);

//背景顏色

lst.setBackground(Color.yellow);

//JAVA默認(rèn)風(fēng)格

this.setUndecorated(true);

this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);

this.setSize(600,500);

this.setTitle("〓聊天室〓");

this.setResizable(false);//不能改變窗體大小

this.setLocationRelativeTo(null);//窗體居中

this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

this.setVisible(true);

txtMSG.requestFocus();//消息框得到焦點(diǎn)

}

//===============================Main函數(shù)===============================

public static void main(String[]args)

{

new Chat();

}

//================================發(fā)送消息===============================

//消息框回車發(fā)送消息事件

public void actionPerformed(ActionEvent e)

{

//得到文本內(nèi)容

buf = txtMSG.getText().getBytes();

//判斷消息框是否為空

if (txtMSG.getText().length()==0)

{

JOptionPane.showMessageDialog(null,"發(fā)送消息不能為空","提示",JOptionPane.WARNING_MESSAGE);

}

else{

try

{

InetAddress address = InetAddress.getByName(sendIP);

DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(txtIP.getText()),sendPort);

ds.send(dp);

}

catch(Exception ex)

{

ex.printStackTrace();

}

}

txtMSG.setText("");//清空消息框

//點(diǎn)發(fā)送按鈕發(fā)送消息事件

if(e.getSource()==btnSend)

{

buf = txtMSG.getText().getBytes();

try

{

DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(txtIP.getText()),sendPort);

}

catch(Exception ex)

{

ex.printStackTrace();

}

txtMSG.setText("");//清空消息框

txtMSG.requestFocus();

}

}

}

如何實(shí)現(xiàn)java網(wǎng)頁聊天

主要有這么幾個(gè)頁面:1.注冊(cè) 2.登陸 3.房間選擇和聊天頁面 。用戶先到1頁面注冊(cè)賬號(hào),然后到2登陸聊天室,再到3頁面加入一個(gè)已經(jīng)創(chuàng)建的房間,開始聊天。具體做就麻煩了,我以前做這個(gè)玩意花了2天。有個(gè)技術(shù)難點(diǎn)要克服,A在他的聊天頁面上說了一句話,B的聊天頁面必須立刻把這句話顯示出來??梢赃@么做,A說話了,他點(diǎn)了提交按鈕,那么一個(gè)請(qǐng)求被提交到后臺(tái)的servlet或者action,后臺(tái)知道A說了一句話,于是,把全局變量(例如application里)messageArrived的值設(shè)置為true,聊天頁面有段JavaScript代碼,每隔一小段時(shí)間(如0.2秒)檢查messageArrived的值,發(fā)現(xiàn)messageArrived==true,就刷新頁面(頁面刷新時(shí),A說的話就顯示出來了),然后再把messageArrived設(shè)回false。這樣聊天記錄能實(shí)時(shí)地顯示。因?yàn)槊總€(gè)人說話,都會(huì)導(dǎo)致整個(gè)頁面刷新,所以這個(gè)聊天室給人的感覺是,頁面一卡一卡的,不正常。ajax用上以后,不會(huì)有整個(gè)頁面老刷新的現(xiàn)象了,給用戶的感覺很好。

網(wǎng)頁標(biāo)題:java代碼網(wǎng)頁聊天 java實(shí)現(xiàn)網(wǎng)頁聊天
本文路徑:http://muchs.cn/article36/dossipg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)定制開發(fā)、微信公眾號(hào)、服務(wù)器托管ChatGPT、網(wǎng)頁設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)