Web小案例-聊天室

一、简单介绍

1、 项目名:MyChat(Maven工程项目)
2、开发环境:Win10
3、开发工具:Eclipse + Tomcat + Chrome
4、使用技术:HTML + CSS + JS + JSP + JAVA + Servlet
5、第三方包:json-lib

<groupId>net.sf.json-lib</groupId>
   <artifactId>json-lib</artifactId>
   <version>2.4</version>
   <classifier>jdk15</classifier>
</dependency>

6、源码下载链接:https://pan.baidu.com/s/1F6sO_HScwcUJT9JRaaLfAQ

二、页面展示

1、 登录页面
登录页面
主要功能:输入昵称进入聊天室。昵称检测,要求不为空;不能与已登录的用户重复。如果为空或重复则在输入框中显示提示信息,不能用提示信息作为昵称,确定昵称后提示是否以此昵称进入。

2、 聊天室页面
聊天室页面1
聊天室页面2
主要功能:用户退出按钮、当前时间显示、用户列表显示、聊天信息显示、发送消息、文件上传(所有文件类型、图片支持预览)、文件列表显示、文件下载,其他功能可以到源码中查看。

3、点击文件列表中的下载按钮可以查看和下载文件
文件查看页面

三、AJAX简单封装

在处理页面请求时,多处用到了ajax请求,因此在这里做一下简单封装,大家也可以根据自己需求封装出合适的好用的ajax请求。

/** 获得ajax对象 */
function getXhr() {
    var xhr;
    if (window.XMLHttpRequest) {
        // 非IE浏览器
        xhr = new XMLHttpRequest();
    } else {
        // IE浏览器
        xhr = new ActiveXObject("Microsoft.XMLHttp");
    }
    return xhr;
}
/**
 * ajax请求,用来传输文本字符串
 * @param method 请求方式:get、post
 * @param url 请求路径
 * @param param 请求参数
 * @param resultType 返回结果类型:text、json
 * @param success 成功回调函数:function(result) {}
 * @param error 错误回调函数:function() {}
 */
function _ajax(method, url, param, resultType, success, error) {
    // 获取ajax对象
    var xhr = getXhr();
    // 打开连接,发送数据
    if (method == "get") {
        xhr.open("get", url+"?"+param, true);
        xhr.send(null);
    } else if (method == "post") {
        xhr.open("post", url, true);
        // 请求头,传输字符串
        xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
        xhr.send(param);
    } 
    // 回调函数
    success = success || function() {};
    error = error || function() {};
    // 绑定事件
    xhr.onreadystatechange = function () {
        // 返回数据
        var resultData;
        if (xhr.readyState == 4 && xhr.status == 200) {
            var text = xhr.responseText;
            if (resultType == "text") {
                resultData = text;
            } else if (resultType == "json") {
                resultData = JSON.parse(text);
            }
            //console.log(resultData);
            if (resultData) {
                success(resultData);
            } else {
                error();
            }
        }
    };
}
/**
 * ajax请求,用来上传文件
 * @param method 请求方式:post
 * @param url 请求路径
 * @param param 请求参数:表单数据formData
 * @param resultType 返回结果类型:text、json
 * @param success 成功回调函数:function(result) {}
 * @param error 错误回调函数:function() {}
 */
function _ajaxF(method, url, param, resultType, success, error) {
    // 获取ajax对象
    var xhr = getXhr();
    // 打开连接,发送数据
    xhr.open("post", url, true);
    xhr.send(param);
    // 回调函数
    success = success || function() {};
    error = error || function() {};
    // 绑定事件
    xhr.onreadystatechange = function () {
        // 返回数据
        var resultData;
        if (xhr.readyState == 4 && xhr.status == 200) {
            var text = xhr.responseText;
            if (resultType == "text") {
                resultData = text;
            } else if (resultType == "json") {
                resultData = JSON.parse(text);
            }
            //console.log(resultData);
            if (resultData) {
                success(resultData);
            } else {
                error();
            }
        }
    };
}

这里需要区别一下参数的写法:
传输字符串:"paramName"=paramValue&"paramName1"=paramValue1...
上传文件:参数为form表单对象,具体操作详见四、文件上传并保存到Tomcat服务器。
使用方法按要求传入参数即可。

四、文件上传并保存到Tomcat服务器

1、配置form表单,必须添加属性enctype="multipart/form-data",如果不添加默认为enctype="application/x-www-form-urlencoded"只能发送字符串,与上面封装的第一个ajax请求设置的请求头是一样的。action和method属性中的值可以不写,因为是用ajax发请求提交,如果是用表单直接提交则要写。需要提交的数据都要写name属性,为了能在服务器端进行区分除了文件数据外还有其他数据。我这里随文件提交的还有昵称,这个只是为了满足这里的需求,需要根据实际情况来定。

<!-- enctype="enctype="multipart/form-data"  -->
<form id="uploadFileForm" action="uploadFile.file" method="post" enctype="multipart/form-data">
    <!-- name="file",文件框必须写name属性 -->
    选择文件:<input id="file" name="file" type="file"/>
    <input id="user_name" name="${nickName }" type="text" value="${nickName }"/>
    <input id="send_file" type="button" value="发送文件"/>
</form>

2、获取form表单对象

var formData = new FormData(_id("uploadFileForm"));

3、发送请求

_ajaxF("post", "uploadFile.file", formData, "json",
    function(result) {
        //console.log(result);
        if(result.msg == "文件上传成功") {
            uploadFileEnd(id);
            confirm(result.msg);
        } else {
            uploadFileEnd(id);
            alert(result.msg);
        }
    },
    function() {
        alert("文件上传失败!");
    }
);

4、获取项目在服务器中的绝对路径

String realPath = getServletContext().getRealPath("/");

本人笔记本上获取的路径:D:\SoftwareInstallation\Tomcat8.0\wtpwebapps\MyChat\

5、处理上传的文件,这里贴出整个方法,看起来更完整,也有注释

    /**
     * 上传文件
     * @param req
     * @param res
     * @throws IOException 
     */
    private void uploadFile(HttpServletRequest req, HttpServletResponse res) throws IOException {
        FileOperationUtil.createSaveUploadFiles(realPath);
        // 获输出取流
        PrintWriter pw = res.getWriter();
        // 创建流
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        // 文件原名
        String fileName = "";
        // 文件保存之后的名字
        String fileSaveName = "";
        // 文件保存路径
        String savePath = "";
        // 昵称
        String nickName = "";
        // 返回消息
        String msg = "";
        try {
            if (ServletFileUpload.isMultipartContent(req)) {
                // 转换为文件上传请求
                ServletRequestContext src  = new ServletRequestContext(req);
                // 文件列表
                List<FileItem> fileItems = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(src);
                for (FileItem file : fileItems) {
                    //System.out.println("FileItems:" + file);
                    // 从打印的信息中可以看出如果是文件,isFormField值为false
                    if (!file.isFormField()) {
                        //System.out.println("file:" + file);
                        fileName = file.getName();
                        // 文件扩展名
                        String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
                        fileSaveName = System.currentTimeMillis() + fileType;
                        savePath = realPath + FileOperationUtil.SAVE_UPLOAD_FILE + fileSaveName;
                        // 获取文件输入流
                        InputStream is = file.getInputStream();
                        bis = new BufferedInputStream(is);
                        // 创建文件输出流保存文件
                        FileOutputStream fos = new FileOutputStream(savePath);
                        bos = new BufferedOutputStream(fos);
                        // 字节数组
                        byte[] buf = new byte[1024 * 10];
                        int n = bis.read(buf);
                        while(n != -1) {
                            bos.write(buf, 0, n);
                            n = bis.read(buf);
                        }
                    } else {
                        nickName = file.getFieldName();
                    }
                }
                // 保存上传信息
                UploadFile uFile = new UploadFile(nickName, fileName, fileSaveName, savePath, DateFormatUtil.timeFormat());
                uFiles.add(uFile);
                // 返回信息
                msg = "{msg:'文件上传成功'}";
                pw.println(JSONObject.fromObject(msg).toString());
                FileOperationUtil.saveUploadFile(realPath, uFiles);
            }
        } catch (FileUploadException e) {
            msg = "{msg:'文件上传失败'}";
            pw.println(JSONObject.fromObject(msg).toString());
        } finally {
            pw.close();
            if (bis != null) {
                bis.close();
            }
            if (bos != null) {
                bos.close();
            }
        }

    }

五、小结

以上代码是从案例中截取出来的,如果单看不好理解,可以下载源码结合源码一起看比较好。需要进一步了解的,想要玩一下的也可以下载源码。这个小案例中有些细节的地方没有处理好,欢迎大家一起交流。

版权声明:本文为zcooa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zcooa/article/details/80719753

智能推荐

Hadoop实战(4)_Hadoop的集群管理和资源分配

系列目录: Hadoop实战(1)_阿里云搭建Hadoop2.x的伪分布式环境 Hadoop实战(2)_虚拟机搭建Hadoop的全分布模式 Hadoop实战(3)_虚拟机搭建CDH的全分布模式 DataNode数据目录 如果有多个挂载点,可以有多个DataNode数据目录。 目前服务器硬件,标准小型机配置:32核、64G(128G)、64T(4T*16盘SAS盘)。通常为了提升磁盘吞吐量,每个盘单...

Tornado day02

一,项目模板: Tornado的项目也可以像Django和flask一样,将功能细分为几个模块 1.1 _ _ init _ _.py 1.2 setting .py 1.3 urls .py 1.4 views .py 1.5 manage .py 将这个模板拷贝下来,以后创建新项目的时候可以直接拷贝一份,在此模板上修改使用 文件链接 链接:https://pan.baidu.com/s/11E...

PAT乙级 | 1095 解码PAT准考证 (25分)(做题过程+注意事项+运行超时解决方法)

PAT 准考证号由 4 部分组成: 第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级; 第 2~4 位是考场编号,范围从 101 到 999; 第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位; 最后 11~13 位是考生编号,范围从 000 到 999。 现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。 输入格式: 输入首先在一行中给出两个正整数 ...

谈谈Java异常

0 概述 对于java工程师来说,是经常和异常打交道的,本文主要来谈一谈java中的异常。 1 异常类的继承关系 从下图(说明:图中只是列出部分异常类)可以看出: 异常的基类为Throwable,主要分为两个分支,即Error体系和Exception体系。 Exception下面分为RuntimeException和非RuntimeException(如IOException) 2 几种异常的区别...

通过设立FatFS隐藏分区,实现系统文件和用户文件的隔离

嘛。。这是一个关于个人使用FatFS文件系统的 一点小的经验。 我知道大家都会百度和谷歌,关于文件系统有什么用,文件系统怎么移植上自己的平台,看看资料也就懂了,在这里不再详述( 打字太慢一分钟50-60字懒得写)。本系列默认已经可以将设备模拟成u盘,并且已经通过修改diskio.c,可以实现ff.c中的各项功能( 不能实现的自行面壁)。FatFS项目官网 http://elm-chan.org/f...

猜你喜欢

Mysql之锁与事务知识要点小结

Mysql之锁与事务 平时的业务中,顶多也就是写写简单的sql,连事务都用的少,对锁这一块的了解就更加欠缺了,之前一个大神分享了下mysql的事务隔离级别,感觉挺有意思的,正好发现一个很棒的博文,然后也收集了一些相关知识,正好来学习下,mysql中锁与事务的神秘面纱,主要内容包括 共享锁和排它锁的区别以及适合范围 mysql的表锁和行锁的区别 怎么判断一个sql是否执行了锁,执行的是表锁还是行锁 ...

响应式图片二 通过srcset实现

具体方法如下: srcset=”图片地址+空格+尺寸描述符,图片地址+空格+尺寸描述符,图片地址+空格+尺寸描述符….” 浏览器会当前浏览的环境进行感知,这个感知包括网速、界面分辨率、DPR(屏幕像素比)等等,然后在图片中选择一个进行加载。 实际上,在相同DPR下,浏览器会根据屏幕的分辨率加载图片,但是加载了大的图片后再缩小还是会使用大的图片。综合考虑的算法非...

Training_model(2)

已经清洗处理了两个数据文件: application_{train|test}.csv :客户详细信息 bureau.csv : 客户历史信用报告 下面对这两个数据中的特征进行合并,然后Light Gradient Boosting Machine训练模型,之前只用客户数据的预测评分结果是0.734,这次加入了客户信用报告信息 load data 新增加了客户历史信用记录 Build Model ...

微信小程序 页面跳转(传参跟不传参)

跳转页面传参 1.首先我的目录结构是这样的,并在 cinema.wxml 定义了一个点击事件 bindtap=‘indetai’ 2.然后在 cinema.js 的data里面定义了一个 score,并实现了 indetai 方法 3.在 detai.js 的 data 里面也定义一个 score ,再在 onLoad 函数里面接收传递过来的值 4.在页面上显示得到的值 这...

JavaSE 10(二维数组)

前言:      在经历了血雨腥风的地狱模式后本以为迎来了学习的平静,但二维数组又打破了这难得的平静!!!二维数组在java编程中同样也是很重要的知识点,因此在这里我将整理二维数组的知识点与重点,以及习题,便于自己的复习与巩固。 二维数组的声明与创建: 下面是声明二维数组的语法: 数据类型[][]数组名 : 数据类型数组名[][]; (允许这种方式 ,但并不推荐使用它...