1 문제 설명
Java EE 관련 기술을 사용하여 간단한 웹 채팅방 시스템을 구현하려면 다음과 같은 요구 사항이 있습니다.
(1) 로그인 정보에는 사용자 이름과 비밀번호가 포함됩니다. 두 개의 버튼을 사용하여 각각 로그인 정보를 제출하고 재설정합니다.
(2) 사용자 이름이 이 그룹의 구성원 이름이고 비밀번호가 해당 학번인 경우, 사용자가 제출한 로그인 정보를 처리하는 서블릿 프로그램 Main.java를 작성합니다. , LoginSuccess 표시 채팅 인터페이스로 이동합니다(QQ 그룹 채팅 인터페이스와 유사하며 HTML의 프레임셋 태그를 사용하여 두 개의 창을 생성할 수 있습니다. 하나는 사용자 정보 입력용이고 다른 하나는 모든 사용자 채팅 기록 표시용). LoginFail 페이지로 이동하여 사용자에게 다시 로그인하라는 메시지를 표시합니다(참고: 이 페이지에는 이전 로그인 인터페이스가 포함되어야 합니다).
(3) "정보 입력" 창과 "채팅 기록 표시" 창의 내용을 각각 표시하는 두 개의 서블릿 프로그램을 작성합니다. 사용자가 "정보 입력" 창에 채팅 내용을 입력하고 "를 클릭합니다. 보내기' 버튼을 클릭하면 메시지를 보낸 사용자의 이름과 채팅 내용이 '채팅 기록 표시' 창에 표시됩니다. 팁: 이를 달성하려면 HTML의 textarea 태그를 사용하세요.
(4) 사용자가 이 기능을 선택하고 로그인에 성공하면 다음 번에 사용자 이름과 비밀번호를 입력하지 않고도 로그인할 수 있도록 로그인 인터페이스에 사용자 이름과 비밀번호를 기억하는 기능을 구현합니다. . 팁: 이 기능은 두 개의 쿠키를 통해 제공됩니다.
다음 기능을 선택하세요.
(5) 세션의 생성 및 소멸 이벤트를 모니터링하여 현재 온라인(로그인)된 사람의 수를 세고 이를 세션에 표시하는 리스너 프로그램을 작성합니다. 채팅 인터페이스가 우수합니다.
(6) 이 시스템의 모든 서블릿 프로그램을 필터링하는 필터를 추가합니다. 이 필터는 요청 및 응답 객체의 인코딩 형식 설정을 구현합니다. (이 기능을 구현한 후 서블릿은 다음에서 매개변수 정보를 직접 얻을 수 있습니다. 요청에 대한 형식 인코딩을 구현하지 않고 요청 객체). Filter와 다른 리소스 간의 프로그램 실행 순서를 [GlassFish Server] 뷰에 출력합니다.
2가지 솔루션
2.1 기대효과
그림 1: 온라인 채팅 시스템 동작 다이어그램
2.2 시스템 구조 다이어그램
그림 2: 시스템 구조 다이어그램
welcome.jsp 세부 정보 페이지 :
그림 3: Welcome.jsp의 실제 동작 다이어그램
2.3 구체적인 코딩
(1) Main.java(서블릿 클래스)는 요청 할당을 통해 login.jsp 페이지에 사용자가 제출한 로그인 정보를 처리합니다(그리고 쿠키를 사용하여 사용자의 로그인 사용자 이름과 비밀번호를 기억하는 기능을 구현합니다). 성공하면 환영으로 이동합니다. .jsp, 실패하면 login.jsp로 이동합니다. 구체적인 구현은 다음과 같습니다.
온라인 채팅 시스템 로그인 홈 페이지 login.jsp 페이지 코드:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String username = ""; String password = ""; //String[] checkBox = request.getParameterValues("save_password"); //获取当前站点的所有Cookie Cookie[] cookies = request.getCookies(); for (int i = 0; i < cookies.length; i++) { //对cookies中的数据进行遍历,找到用户名、密码的数据 if ("username".equals(cookies[i].getName())) { //读取时URLDecoder.decode进行解码(PS:Cookie存取时用URLEncoder.encode进行编码) username = java.net.URLDecoder.decode(cookies[i].getValue(),"UTF-8"); } else if ("password".equals(cookies[i].getName())) { password = java.net.URLDecoder.decode(cookies[i].getValue(),"UTF-8"); } } %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>网上聊天室登陆页面</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <style type="text/css"> * { margin: 0; padding: 0; } body { font-size: 0px; padding: 200px; } </style> </head> <body> <form action="Main" method="post"> <div style="background:#49AFFF;font-size: 80px;text-align:center;">网上聊天室</div> <div style="background:#75FFE7;font-size: 35px;text-align:center;"> <span>用户名:</span><input type="text" name="username" value="<%=username%>" style="border:1px solid #ccc; width:400px; height:40px;" ></div> <div style="background:#75FFE7;font-size: 35px;text-align:center;"> <span>密 码 :</span><input type="password" name="password" value="<%=password%>" style="border:1px solid #ccc; width:400px; height:40px;" ></div> <div style="background:#75FFE7;font-size: 25px;text-align:center;"> <input type="checkbox" value="save" name="save_password">记住密码 <input type="submit" value="登陆" name="login" style="width: 100px; height: 40px;font-size: 30px;"> <input type="reset" value="重置" name="reset" style="width: 100px; height: 40px;font-size: 30px;"></div> </form> </body> </html>
Main.java 클래스 코드:
package com.liuzhen.chart; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class Main extends HttpServlet { /** * Constructor of the object. */ public Main() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.setContentType("text/html;charset=utf-8"); //此出注解是因为使用CodeFilter类过滤所有Servlet,转换编码 //request.setCharacterEncoding("utf-8"); String userName = request.getParameter("username"); String passWord = request.getParameter("password"); String checkBox = request.getParameter("save_password"); System.out.println("userName:"+userName+"\n"+"passWord:"+passWord); request.getSession().setAttribute("nameSession", userName); //将用户名存入session中 String[] name_one = {"柳真","刘仁杰","吴超","张浩东","陈初相"}; String[] pwd_one = {"201421092073","201421092068","201421092077","201421092082","201421092119"}; String name_two = ""; String pwd_two = ""; boolean login_test = false; for(int i=0;i<5;i++){ name_two = name_one[i]; pwd_two = pwd_one[i]; if(userName.equals(name_two) && passWord.equals(pwd_two)) login_test = true; } if(login_test) { if ("save".equals(checkBox)) { //Cookie存取时用URLEncoder.encode进行编码(PS:读取时URLDecoder.decode进行解码) String name = URLEncoder.encode(userName,"UTF-8"); //创建两个Cookie对象 Cookie nameCookie = new Cookie("username", name); //设置Cookie的有效期为3天 nameCookie.setMaxAge(60 * 60 * 24 * 3); String pwd = URLEncoder.encode(passWord,"UTF-8"); Cookie pwdCookie = new Cookie("password", pwd); pwdCookie.setMaxAge(60 * 60 * 24 * 3); response.addCookie(nameCookie); response.addCookie(pwdCookie); } request.getRequestDispatcher("welcome.jsp").forward(request, response); } else{ response.sendRedirect("loginFail.jsp"); // request.getRequestDispatcher("loginFail.jsp").forward(request, response); } } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }
로그인 실패 페이지 loginFail.jsp 페이지 코드:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'loginFail.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="content-type" content="text/html; charset=gb2312"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <br> <br> <h1>用户名和密码不匹配,请重新登陆!</h1> <a href="login.jsp">重新登陆</a> </body> </html>
로그인 성공 페이지 Welcome.jsp 페이지 코드(여기서 프레임셋 태그가 사용되며 헤더, 왼쪽 부분 및 중간 홈 페이지, 개체 헤더의 세 부분으로 나뉩니다.) .jsp, 각각 left.jsp 및 main.jsp 페이지):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>网上聊天室</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="content-type" content="text/html; charset=gb2312"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <frameset rows="100,*" cols="*" frameborder="no" border="0" framespacing="0"> <frame src="header.jsp" name="topFrame" scrolling="auto" noresize="noresize" id="topFrame"/> <frameset cols="213,*" frameborder="no" border="0" framespacing="0"> <frame src="left.jsp" name="leftFrame" scrolling="No" noresize="noresize" id="leftFrame"/> <frame src="main.jsp" name="mainFrame" scrolling="auto" id="mainFrame"/> </frameset> </frameset> <body> </body> </html>
채팅 헤더 header.jsp 페이지 코드:
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gb2312" pageEncoding="gb2312"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title></title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <meta http-equiv="Content-Type" content="text/html;charset=gb2312"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body topmargin="0" leftmargin="0" rightmargin="0"> <form action=""> <table width="100%" height="79" border="0" cellpadding="0" cellspacing="0" align=center> <tr> <td bgcolor="F9A859" valign="top"> <table width="100%" height="50" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="FBEAD0"> <tr> <td align="center" style="font-size:40px;"> 网上聊天室 </td> </tr> </table> </td> </tr> <tr> <td bgcolor="F9A859" valign="top"> <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td align="center" style="font-size:20px" valign="middle"> 欢迎<%=(String)request.getSession().getAttribute("nameSession") %>访问! 当前在线人数为<%=application.getAttribute("peopleOnline")%>人 </td> </tr> </table> </td> </tr> </table> </form> </body> </html>
채팅 왼쪽 left.jsp 페이지 코드(for 여기에는 아름다운 표시가 있습니다. jquery-1.4.2 패키지를 사용하세요.):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'test.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="content-type" content="text/html; charset=gb2312"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <style type="text/css"> * { margin: 0; padding: 0; } body { font-size: 15px; padding: 00px; } .menu { width: 500px; border-bottom: solid 1px gray; } .menu h3 { border: solid 1px gray; height: 30px; line-height: 30px; padding-left: 10px; padding:0 5px; border-bottom: none; cursor: pointer; } .menu p { border-left: solid 1px gray; border-right: solid 1px gray; padding: 20px 0; padding-left: 5px; } .changecolor{background-color:red;} </style> <script src="js/jquery-1.4.2.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { $(".menu p:not(:first)").hide(); $(".menu h3").css("background", "#ccc"); $(".menu h3").hover(function () { $(this).css("background-color", "gray").siblings("h3").css ("background-color", "#ccc");}); $(".menu h3").mouseleave(function () { $(".menu h3").css("background", "#ccc");}); //离开时将其变为原来颜色 var index = $(".menu h3").index(this); $(".menu h3").click(function () { $(this).next("p").slideToggle().siblings("p").slideUp(); }); }); </script> </head> <body> <div class="menu"> <h3> 我的好友</h3> <p> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/><br/> <a href="index.jsp">周杰伦</a><br/> </p> <h3> 我的朋友</h3> <p> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/><br/> <a href="index.jsp">李连杰</a><br/> </p> <h3> 陌生人</h3> <p> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/><br/> <a href="index.jsp">比尔盖茨</a><br/> </p> </div> </body> </html>
채팅 홈페이지 main.jsp 페이지 코드:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'main.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="InputInformation" method=post> <textarea cols="105" rows="25" name="show_textarea"><%=request.getAttribute("input_textarea")%></textarea> <br> <textarea cols="105" rows="5" name="input_textarea"></textarea><br> <input type="submit" value="发送" name="button_one" style="width: 100px; height: 40px;font-size: 25px;"><br> </form> </body> </html>
(2) InputInformation.java(Servlet 클래스)가 가져옵니다. 요청 할당을 통한 메인 .jsp 채팅 입력 상자에 정보를 입력하고 main.jsp 페이지로 이동하여 채팅 기록 표시 상자에 채팅 정보를 표시합니다. 구체적인 구현은 다음과 같습니다.
InputInformation.java 클래스 코드는 다음과 같습니다.
package com.liuzhen.chart; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class InputInformation extends HttpServlet { public String chat_record = ""; //定义聊天记录变量,此处为全局变量 /** * Constructor of the object. */ public InputInformation() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.setContentType("text/html;charset=utf-8"); //此出注解是因为使用CodeFilter类过滤所有Servlet,转换编码 //request.setCharacterEncoding("utf-8"); String input_textarea = request.getParameter("input_textarea"); Date now = new Date(); //创建日期对象,及系统当前时间 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 String time = dateFormat.format( now ); //按照给定的日期格式获取系统当前时间 String t = (String)request.getSession().getAttribute("nameSession"); //获取登陆页面用户名 chat_record += t+" "+input_textarea+" "+time+"\n"; //聊天记录存储 request.setAttribute("input_textarea",chat_record); //将当前聊天输入内容存储 request.getRequestDispatcher("main.jsp").forward(request,response); //跳转到当前聊天输入界面,即界面布局不变 } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }
(3)CodeFilter.java(过滤器类)截取系统所有Servlet类,实现对请求和响应对象的编码格式的设置,均设置为UTF-8。具体实现如下:
CodeFilter.java类代码如下:
package com.liuzhen.chart; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //采用注解方式配置URL,此处就不必再在web.xml文件中配置。如果两者均配置的话,系统将以web.xml文件中配置信息为准 @WebFilter(filterName="CodeFilter",urlPatterns={"/*"}) public class CodeFilter implements Filter{ @Override public void destroy() { System.out.println("destroy---CodeFilter"); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("start----doFilter--CodeFilter"); HttpServletRequest request =(HttpServletRequest) arg0; HttpServletResponse response =(HttpServletResponse) arg1; //以上是强制内型转换,使用request对象和response对象 request.setCharacterEncoding("utf-8"); //设置过滤页面提取数据的编码 response.setContentType("text/html;charset=utf-8"); //设置过滤页面显示数据的编码 arg2.doFilter(arg0, arg1);//在页面跳转之前执行此语句前面的代码,执行完页面的代码之后,在执行后面的语句 System.out.println("第一个字符过滤器"); System.out.println("end------doFilter--CodeFilter"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init----CodeFilter"); } }
(4)OnlineListener.java(监听器类)主动监听系统Web容器,返回当前聊天系统在线人数,具体实现如下:
OnlineListener.java类代码如下:
package com.liuzhen.chart; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class OnlineListener implements HttpSessionListener{ public void sessionCreated(HttpSessionEvent arg0) { ServletContext context = arg0.getSession().getServletContext(); Integer count = (Integer) context.getAttribute("peopleOnline"); if (count == null) { count = 1; } else { count++; } context.setAttribute("peopleOnline", count); } public void sessionDestroyed(HttpSessionEvent arg0) { ServletContext context = arg0.getSession().getServletContext(); Integer count = (Integer) context.getAttribute("peopleOnline"); count--; context.setAttribute("peopleOnline", count); } }
此处还要给OnlineListener监听器类在web.xml文件中配置路径,web.xml配置代码具体如下(红色标记代码):
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <listener> <listener-class>com.liuzhen.chart.OnlineListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>Main</servlet-name> <servlet-class>com.liuzhen.chart.Main</servlet-class> </servlet> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>InputInformation</servlet-name> <servlet-class>com.liuzhen.chart.InputInformation</servlet-class> </servlet> <servlet-mapping> <servlet-name>Main</servlet-name> <url-pattern>/Main</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>InputInformation</servlet-name> <url-pattern>/InputInformation</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>
在调用监听器类实现监听系统当前在线人数时,本机上同一个浏览器同时登陆多个用户,只能算作一次,本机上不同浏览器登陆则分别算作一次。以下分别是在IE、谷歌和360浏览器登陆在线人数显示:
图四:IE浏览器登陆,显示在线人数1人
图五:谷歌浏览器登陆,显示在线人数2人
图六:360浏览器登陆,显示在线人数3人
附:本文系统代码Coding链接:https://coding.net/u/LiuZhen1995/p/MyDemo/git/tree/origin_seven