Servlet实现聊天室
目的
-
理解servlet的工作原理
-
掌握servlet编程基本技能
内容及要求
利用servlet技术实现一个简单的聊天室,实现多人同时交流。当发送聊天信息时,信息窗口刷新。信息窗口显示发言人的姓名以及发言的内容。在进入聊天室之前需要进行登录,即输入用户名。
提示
-
需要实现一个静态登录页面及一个servlet
-
对于聊天信息的保存可能用到servletcontext
-
对于用户名的保存可能用到HttpSession
思考
-
如何解决中文乱码的问题
-
如何实现页面的自动刷新
开发环境
在编写本项目时,使用的编程软件是Neatbeans 8.0.2 ,采用的JDK版本为1.8.0,使用的服务器为Neatbeans软件自带的GlassFish Servlet 4.1.1 ,读者可以借鉴编者的开发环境
代码实现
1.前端页面
1.1登录页面(index.html)
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!--
Author:H.J.Y
-->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聊天室</title>
</head>
<body>
<br>
<div>
<span style="padding-left: 5px;padding-right: 10px; background-color: rgba(10,10,10,0.1); height: 100px; font-size: 30px;border: 1px black solid; border-radius: 10px">聊天室</span>
</div>
<br>
<br>
<center>
<form action="Login" method="post">
<!--action的值为处理数据的Servlet代码的文件名称,method的值为请求的方式 -->
账户:<input type="text" name="username" ><br><br>
<!--name的作用就是作为Servlet中使用指定方法获取前端页面的数据的函数的参数-->
密码:<input type="password" name="password"><br>
<br>
<input type="reset" name="Reset" value="重置">
<input type="submit" name="Submit" value="登录">
</form>
</center>
</body>
</html>
1.2主窗口页面(Frame.html)
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
<!--<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!--
Author:H.J.Y
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>聊天室</title>
</head>
<frameset rows="20%,50%,30%" frameborder="no" border="0" framespacing="0">
<!--rows的值为三个不同面板所占的屏幕比例-->
<frame src="head.jsp" name="head" scrolling="No" noresize="noresize" title="head" />
<frame src="center.jsp" name="center" title="center" />
<frame src="bottom.jsp" name="bottom" scrolling="No" noresize="noresize" title="bottom" />
</frameset>
</html>
在这个页面里面我们采用了frame面板,将想要呈现的内容划分为三个不同的面板。在这三个面板中,中部面板用于刷新我们的聊天内容,底部用于发送聊天信息。
1.2.1头部页面(head.jsp)
<%--
Document : head
Created on : 2023-4-1, 21:58:04
Author : H.J.Y
--%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Frame的头部</title>
</head>
<body>
<div>
<center>
<span style="background-color: rgba(10,10,10,0.1);width: 200px; height: 100px; font-size: 50px;border: 1px black solid; border-radius: 10px;">聊天室</span>
</center>
</div>
</body>
</html>
1.2.2中部页面(center.jsp)
<%--
Document : Center
Created on : 2023-4-1, 21:29:27
Author : H.J.Y
--%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<p style="font-size: 30px ">
欢迎<font style="font-size: 35px; color: red;"><%=session.getAttribute("username")%></font>加入聊天室!
</p>
<p style="color: blue">开始您的快乐聊天旅途吧</p>
</body>
</html>
1.2.3底部页面(bottom.jsp)
<%--
Document : bootom
Created on : 2023-4-1, 21:30:47
Author : H.J.Y
--%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Frame的底部</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="Chatting" target="center">
<!--action的值为处理数据的Servlet代码的文件名称,method的值为请求的方式 -->
<%=session.getAttribute("username")%>
<!--获取登录者的用户名-->
对
<input type="text" name="toname" />
说:
<label>
<input type="text" name="word" />
</label>
<br>
<!--这个地方可以根据自己想要设置图片的个数进行修改-->
<input type="checkbox" name="img" value="./imgs/1.png" ><img src="./imgs/1.png">
<input type="checkbox" name="img" value="./imgs/2.png" ><img src="./imgs/2.png">
<input type="checkbox" name="img" value="./imgs/3.png" ><img src="./imgs/3.png">
<input type="checkbox" name="img" value="./imgs/4.png" ><img src="./imgs/4.png">
<input type="checkbox" name="img" value="./imgs/5.png" ><img src="./imgs/5.png">
<input type="checkbox" name="img" value="./imgs/6.png" ><img src="./imgs/6.png">
<input type="submit" name="Submit" value="提交" />
</form>
</body>
</html>
1.3登录失败页面(fail.html)
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!--
Author:H.J.Y
-->
<html>
<head>
<title>聊天室 </title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>登录失败,账号或密码存在错误!</h1>
<a href="index.html">点击这里跳转登录界面!!!</a>
</body>
</html>
在登录失败后会跳转到这个页面,这个页面里面我们放置了一个跳转的链接,点击后将会跳转到登录的页面,继续进行登录。
2.Servlet代码
2.1Login代码(Login.java)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.hjy;//此处根据自己的文件名称进行修改
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @name Login
* @author H.J.Y
*/
@WebServlet(name = "Login", urlPatterns = {"/Login"})
public class Login extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");//设置响应的编码格式
request.setCharacterEncoding("UTF-8");//响应请求的编码格式
String username = request.getParameter("username");//获取请求的username
String password = request.getParameter("password");//获取请求的password
if (username.length()!=0 && password.length()!=0 ) {//将获取到的账号和密码进行匹配操作,可以根据自己的需求修改校验条件
HttpSession session = request.getSession();//获取请求的会话
session.setAttribute("username", username);//在会话中存储username,对应username
RequestDispatcher rd = request.getRequestDispatcher("Frame.html");//获取Frame文件的请求路径
rd.forward(request, response);//跳转到获取到的路径
} else {
RequestDispatcher rd = request.getRequestDispatcher("fail.html");
rd.forward(request, response);
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
在这个页面里面中,我们将通过request.getParameter()获取前端页面中的数据。在代码中,我们拿到了前端的username和password的值,之后进行校验。如果校验成功,就获取会话对象,将username保存到会话中。如果校验失败,就跳转到失败页面。
2.2Chatting代码(Chatting.java)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.hjy;//此处根据自己的文件名称进行修改
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @name Chatting
* @author H.J.Y
*/
@WebServlet(name = "Chatting", urlPatterns = {"/Chatting"})
public class Chatting extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");//设置响应的编码格式为UTF-8
request.setCharacterEncoding("UTF-8");//设置请求的编码格式为UTF-8
PrintWriter out = response.getWriter();
String s="";//定义一个空字符串,用于对后续获取多个图片文件名称进行处理
out.println("<html>");
out.println("<head>");
out.println("<style>");
out.println("font{ font-size:20px;}");
out.println("img{ margin-top:10px; margin-left:50px}");
out.println("center{ color:rgba(10,10,10,0.3)} font-size:15px");
out.println("</style>");
out.println("</head>");
out.println("<body>");
String words = (String) getServletContext().getAttribute("words");//获取ServletContext对象中存储的消息
response.setHeader("refresh", "2");//设置消息头,这里作用是执行重刷新操作,刷新时间为两秒
HttpSession session = request.getSession();//获取session对象
String word = request.getParameter("word");//获取请求中word对应的值,指代发送的信息的内容
String toname = request.getParameter("toname");//获取请求中toname对应的值,指代消息的接收方
String img[] = request.getParameterValues("img");//获取请求中img对应的值,这里用与进行对图片的操作
String name = (String) session.getAttribute("username");//获取session中username对应的值
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//获取SimpleDateFormat对象并设置时间的格式
if (words == null) {
words = "";
}
if (words == null || word == null)
{
word = words;
}
else {
if (img==null){
word = "<center>"+sdf.format(System.currentTimeMillis())+"</center>"+"<br>"+ "<font>" + name+ "</font>" + "对" + "<font>"+ toname+"</font>"+ "说:" + word;//如果有图片就加+ "<img src = " + emotion + ">"
words = words + "<br>" + word;
}
else{
word = "<center>"+sdf.format(System.currentTimeMillis())+"</center>"+"<br>" + "<font>" + name + "</font>" + "对" + "<font>"+ toname+"</font>"+ "说:" + word+"<br>";
for (int i=0;i<img.length;i++){
s+="<img src = " + img[i] + ">"+"<br>";//将img[]中的值进行拼串处理
}
word+=s;
words = words + "<br>" + word;
}
}
getServletContext().setAttribute("words", words);//将交流的内容存储到ServletContext中
out.print(words);//输出交流的信息
out.println("</body>");
out.println("</html>");
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
至此,我们通过Servlet实现聊天室的功能就完成了。这个聊天室支持在局域网内实现多人对话,也可以在同一台电脑上使用不同的浏览器同时模拟多用户聊天。此外,如果读者在实际使用过程中出现什么问题并已经完成修改,请尽量在评论中回复编者,以便于编者完善该程序代码。