网上留言簿(Java,MySQL,Tomcat,SSM框架)

一、设计要求
1.进行网上留言簿的需求分析和功能设计;
2.在数据库中构建数据库、表或视图,熟悉数据库开发流程;
3.根据网上留言簿的功能,设计各页面和脚本,掌握动态网页的制作技术;
二、开发环境与工具
Java,MySQL,Tomcat,SSM框架
IDEA
三、设计原理
HTTP协议:
HTTP(Hypertext Transfer Protocol)是一种应用层协议,它是用于在网络上传输超文本的通信协议。HTTP是构建在客户端-服务器模型上的,客户端发送HTTP请求,服务器响应请求并返回数据。HTTP是无状态的,每个请求都是独立的,服务器不会保留关于客户端的信息

  1. HTTP的特点
    1.1 无连接
    HTTP是无连接的协议,即每个请求和响应之间都是相互独立的,服务器不会保留与客户端的连接状态。每个请求都需要建立一次连接,完成后即断开连接,这有助于减少服务器资源的占用。
    1.2 无状态
    HTTP是无状态的协议,每个请求都是独立的,服务器不会记住之前的请求信息。为了实现状态保持,引入了Cookie和Session机制,通过在请求和响应中携带标识信息来实现用户状态的保持。
    1.3 简单快速
    HTTP的设计目标之一是简单快速,它采用了简单的请求-响应模型,头部信息采用纯文本格式,易于阅读和调试。这使得HTTP在传输超文本等简单数据时非常高效。
    1.4 灵活
    HTTP是一种灵活的协议,它支持多种数据格式和多种请求方法。通过不同的Content-Type头部,可以传输文本、图像、音频等不同类型的数据。
  2. HTTP的工作原理
    2.1 请求-响应模型
    HTTP通信遵循请求-响应模型。客户端发送HTTP请求到服务器,服务器处理请求并返回HTTP响应。请求和响应都包含了头部信息和可选的消息体。
    2.2 请求方法
    HTTP定义了一些常用的请求方法,如GET、POST、PUT、DELETE等。不同的请求方法对应不同的操作,比如GET用于获取资源,POST用于提交数据等。
    2.3 URL和URI
    Uniform Resource Locator(URL)是用于定位资源的字符串,它包含了协议、主机、端口、路径等信息。Uniform Resource Identifier(URI)是资源的唯一标识符,URL是URI的一种。
    2.4 头部信息
    HTTP请求和响应中包含了头部信息,头部信息包括了请求/响应的元数据,如Content-Type、Content-Length、User-Agent等。头部信息的正确设置对于正确处理请求和响应非常重要。
    2.5 状态码
    HTTP响应中包含了状态码,用于表示服务器对请求的处理结果。常见的状态码有200 OK表示成功,404 Not Found表示资源不存在,500 Internal Server Error表示服务器内部错误等。
  3. HTTP在Web开发中的应用
    3.1 静态资源请求
    浏览器通过HTTP请求获取Web页面的各种静态资源,如HTML、CSS、JavaScript、图像等。这些资源通过HTTP协议在客户端和服务器之间传输。
    3.2 表单提交
    通过HTTP的POST请求,浏览器可以将用户在表单中输入的数据提交给服务器。服务器通过解析POST请求的消息体获取用户提交的数据。
    3.3 Cookie和Session
    为了实现状态保持,服务器通过HTTP响应头部的Set-Cookie字段将Cookie信息发送给客户端,客户端保存Cookie信息并在后续的请求中发送给服务器。服务器通过Cookie中的信息来维护用户的状态。
    3.4 RESTful API
    RESTful API是一种基于HTTP协议设计的Web API,它使用HTTP方法和状态码来实现资源的增删改查。RESTful API广泛应用于Web服务的开发。
    3.5 安全性
    HTTP协议本身是明文传输的,为了保障数据的安全性,引入了HTTPS协议,通过SSL/TLS协议对HTTP通信进行加密,提供了安全的数据传输通道。
    客户端-服务器通信模型:
    客户端-服务器通信模型是一种分布式计算模型,它是通过网络连接将任务分配和数据交换的一种架构。该模型中,客户端和服务器分别承担不同的角色,协同工作以实现信息交互和服务提供。
  4. 基本概念
    1.1 客户端
    客户端是指请求服务的一方,通常是用户使用的终端设备,比如浏览器、移动应用或桌面软件。客户端发起请求,向服务器请求服务或获取数据。
    1.2 服务器
    服务器是提供服务的一方,它接收来自客户端的请求,处理请求并返回相应的结果。服务器通常是一台计算机或计算机集群,运行着服务端应用程序。
    1.3 请求和响应
    客户端通过发送请求向服务器请求服务,服务器接收请求并返回响应。请求和响应包含了通信双方之间传输的信息,如数据、操作指令等。
  5. 特点
    2.1 分布式
    客户端和服务器分别运行在不同的设备或计算节点上,通过网络进行通信。这种分布式的架构使得系统更加灵活,可以横向扩展以应对不同规模的需求。
    2.2 请求-响应模型
    客户端向服务器发起请求,服务器处理请求后返回响应。这种模型简单而有效,使得客户端和服务器之间的交互变得清晰,每个请求都有相应的响应。
    2.3 可扩展性
    由于分布式的特性,客户端-服务器模型具有良好的可扩展性。可以通过增加服务器节点或客户端来实现系统的扩展,以适应不断增长的用户和数据量。
  6. 工作流程
    3.1 请求过程
    客户端发起请求:客户端向服务器发起请求,请求可以包含特定的操作、数据或其他参数。
    传输请求:请求通过网络传输到服务器,通常使用HTTP、TCP/IP等协议进行通信。
    服务器接收请求:服务器接收并解析客户端的请求,执行相应的操作或查询数据库等。
    处理请求:服务器处理请求,可能涉及到计算、数据库查询、业务逻辑等操作。
    生成响应:服务器生成响应数据,将处理结果封装成响应报文。
    传输响应:响应通过网络传输到客户端。
    3.2 响应过程
    客户端接收响应:客户端接收服务器返回的响应数据。
    解析响应:客户端解析响应,提取所需的数据或状态信息。
    更新界面:如果是Web应用,客户端可能更新用户界面,展示最新的数据或信息。
    客户端可能发起新的请求,继续与服务器进行交互。
    数据库连接池:
    数据库连接池是一种用于管理和复用数据库连接的技术,它在数据库访问中发挥着重要作用,提高了应用程序的性能和资源利用率。
  7. 基本概念
    1.1 数据库连接
    数据库连接是应用程序与数据库之间的通信通道,它允许应用程序执行SQL语句并与数据库交互。连接的创建和释放是相对耗时的操作。
    1.2 数据库连接池
    数据库连接池是一组数据库连接的缓存,它们被提前创建并保存在池中,以供应用程序在需要时复用。连接池管理连接的分配和释放,有效减少了数据库连接的创建和销毁次数。
  8. 工作原理
    2.1 连接池初始化
    连接池在应用程序启动时进行初始化。在这个阶段,连接池会创建一定数量的数据库连接,并将它们放入连接池中。这些连接被称为初始连接。
    2.2 连接请求
    应用程序需要与数据库通信时,它从连接池中请求一个数据库连接。连接池会检查是否有空闲的连接,如果有,则分配给应用程序;如果没有,则创建新的连接。
    2.3 连接使用
    应用程序使用分配到的连接执行SQL查询或更新操作。连接使用完成后,并不立即关闭,而是返回到连接池中等待下一次请求。
    2.4 连接释放
    当应用程序不再需要连接时,它将连接释放回连接池。连接池并不会真正关闭连接,而是将连接标记为空闲状态,以备后续请求使用。
    2.5 连接池维护
    连接池需要定期检查连接的健康状况,包括连接是否超时、是否有效等。对于长时间未使用的连接,连接池可能会选择关闭以释放资源。
  9. 优势和作用
    3.1 资源复用
    连接池通过复用数据库连接,减少了连接的创建和销毁开销,提高了资源利用率。
    3.2 性能优化
    由于连接已经被初始化并保持在池中,应用程序在需要时可以直接获取连接,而不必等待连接的创建过程,从而提高了数据库访问性能。
    3.3 连接管理
    连接池可以管理连接的数量,防止由于连接泄漏或过多连接导致数据库性能下降。它还能通过一些配置参数控制连接的最大数量、最小数量等。
    3.4 防止数据库压力过大
    数据库连接是有限资源,过多的连接可能导致数据库性能下降。连接池通过限制连接数量,防止了对数据库的过度压力。
    Tomcat:
    Tomcat(Apache Tomcat)是一个开源的、轻量级的应用服务器,它是Apache软件基金会的一个项目,用于实现Java Servlet、JavaServer Pages(JSP)等Java技术的Web应用程序的部署和运行。
  10. Servlet 和 JSP
    Tomcat的基础是Java Servlet 和 JSP 技术,它们分别是服务器端的Java程序和Java服务器页面。Servlet 是一种用Java编写的服务器端程序,能够处理HTTP请求和生成HTTP响应。JSP 是一种在HTML中嵌入Java代码的技术,用于创建动态的Web页面。
  11. 架构模型
    Tomcat的架构模型主要分为两个部分:Catalina 和 Coyote。
    Catalina: 负责处理Servlet和JSP。它包含一个Servlet容器,用于加载和运行Servlet,还有一个JSP引擎,用于编译和执行JSP页面。
    Coyote: 负责处理底层的HTTP协议。它是Tomcat的连接器,用于处理客户端的HTTP请求并将其传递给Catalina进行处理。Coyote还负责将Servlet或JSP生成的HTTP响应返回给客户端。
  12. 生命周期
    Tomcat的生命周期包括初始化、启动、运行和停止等阶段。
    初始化: 在这个阶段,Tomcat会加载配置文件、初始化Catalina和Coyote等组件。
    启动: Tomcat启动时会初始化并启动Servlet容器和连接器,监听指定的端口等待客户端请求。
    运行: 在运行阶段,Tomcat接收到HTTP请求后,Coyote将请求传递给Catalina,Catalina加载并执行相应的Servlet或JSP,生成HTTP响应返回给客户端。
    停止: 当接收到停止命令时,Tomcat会优雅地关闭连接器和Servlet容器,释放占用的资源。
  13. 目录结构
    Tomcat的目录结构通常包括以下几个重要的目录:
    bin: 包含启动和停止Tomcat的脚本文件。
    conf: 包含Tomcat的配置文件,其中server.xml是主要的配置文件,包括端口配置、连接器配置等。
    lib: 包含Tomcat运行所需的JAR文件,包括Servlet API等。
    webapps: 用于存放Web应用程序的目录,每个应用程序通常以一个文件夹的形式存在。
  14. Connector
    Connector是Coyote的组成部分,用于处理底层的网络通信。Tomcat支持多种Connector,包括HTTP、HTTPS、AJP(Apache JServ Protocol)等。
    HTTP Connector: 用于处理HTTP协议,是Tomcat的默认连接器,通常监听在端口80。
    HTTPS Connector: 用于处理通过SSL加密的HTTPS协议,通常监听在端口443。
    AJP Connector: 用于处理与Apache HTTP Server之间的通信,提高性能和可扩展性。
  15. 部署和Web应用管理
    Tomcat允许通过将Web应用程序的文件部署到webapps目录来实现应用程序的部署。每个Web应用程序都以一个文件夹的形式存在,包含WEB-INF目录,其中包含了应用程序的配置信息、类文件和部署描述符等。
    Tomcat还提供了管理应用程序的Web界面,允许用户通过浏览器进行部署、启动、停止和卸载应用程序。
    四、系统功能描述及软件模块划分
    基于需求分析,我认为网上留言簿应当有以下功能和模块:
    (1)用户模块
    1)用户注册:用户通过填写用户名、昵称、密码、邮箱、电话等信息完成注册。
    2)用户登录:用户在登录时需输入正确的用户名和密码。为防止机器人恶意登录,还需输入正确的验证码。
    (2)管理员模块
    1)用户管理:管理员可以查看、删除用户信息。为防止恶意操作,管理员操作时需登录后才能执行相应权限。
    2)留言管理:管理员可以查看、删除留言。
    (3)共有功能
    1)发布留言:用户可以发表自己的观点和看法。在发布留言时,系统应自动检测恶意言论、广告等信息,并进行拦截和处理。
    2)查看留言:用户可以查看其他用户发布的留言,并根据自己的兴趣进行筛选和排序。
    3)发布回复:用户可以在留言下方发表自己的回复,与其他用户进行互动。为保证回复内容的质量,可设置审核机制。
    在这里插入图片描述
    图1 系统主要功能
    在这里插入图片描述
    图2 大致流程和功能展示
    用户登陆的时候,需要输入正确的用户名,密码和验证码
    在这里插入图片描述
    图3 用户登录
    在用户注册的时候,需要验证邮箱、电话格式是否正确以及进行确认二次密码:
    在这里插入图片描述

图4 用户注册
在管理员模式下,可以删除用户和用户信息,具体删除步骤如下图所示:
在这里插入图片描述

图5 删除用户
在系统模块划分方面,主要分为两部分用户模块、管理员模块和留言模块,其中用户模块主要属性有ID,用户名、昵称、email、电话、密码;管理员模块主要有id、用户名、密码、role,其中role作为管理员的唯一标识符,只能在数据库中进行修改;留言模块主要有ID、发布人、标题、发布时间、回复。
图6 用户模块
图6 用户模块
在这里插入图片描述

图7 管理员模块
在这里插入图片描述

图8 留言模块
我认为我的系统主要创新点为以下六个部分:
1.参考了网上的ssm模块,利用spring接口厘清前后端,并采用mybatis数据库连接池来连接数据库和代码
2.用户登录时需要输入随机四位数数字验证码,防止机器人恶意登录
3.用户注册时需要二次输入密码验证(网页会自动识别name是password的文本框进行隐藏),并且需要验证邮箱格式和电话号码的格式。
4.用户或者管理员可以查看自己的个人资料,并且修改其中的数据
5.用户注册时可以选择自己的头像(必须是jpg格式)
6.管理员可以删除留言、删除用户
五、设计步骤
用户模块:
首先我定义了用户的属性:

public class User implements Serializable{
    private Integer id;
    private String username;
    private String password;
    private String nickname;
    private String email;
    private String tel;
    private String logo;
    private Integer role;
    private Integer isdel;

后面还有许多对用户属性进行操作的函数。
在用户登录的时候,我还需要进行对验证码的生成,验证码生成代码如下所示:

<%!
Color getRandColor(int fc,int bc){
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
%>
<%//在内存中创建图象
try{
int width = 60, height = 20;
BufferedImage image = new BufferedImage(width, height,
       BufferedImage.TYPE_INT_RGB);
//获取图形上下文
Graphics g = image.getGraphics();
Random random = new Random();
//设定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
//画边
g.setColor(getRandColor(160,200));
g.drawRect(0, 0, width - 1, height - 1);
String sRand="";

g.setFont(new Font("Times New Roman",Font.PLAIN,18));
g.setColor(getRandColor(160,200));
for (int j=0;j<4;j++){
    String rand=String.valueOf(random.nextInt(10));
    sRand+=rand;
    g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
    g.drawString(rand,13*j+6,16);
}
//将认证码存入SESSION  
session.setAttribute("code", sRand);
//随机产生88个干扰点,使图象中的认证码不易被其它程序探测到
g.setColor(Color.black);
for (int i = 0; i < 20; i++) {
    int x = random.nextInt(width);
    int y = random.nextInt(height);
    g.drawOval(x, y, 0, 0);
}
//图象生效
g.dispose();
OutputStream os=response.getOutputStream();
//输出图象到页面
ImageIO.write(image, "JPEG", os);
os.flush();
os.close();
os=null;
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
}
catch(IllegalStateException e)
{
    System.out.println(e.getMessage());
    e.printStackTrace();
}
%>

在后端,通过用户属性和spring提供的接口处理前端用户的注册、登录与删除,然后在xml文件将更改过的数据通过sql语句写入数据库,从而实现用户的注册、登录、(被)删除。
在前端,用户登录的主要代码如下:

<div class="col-md-3 text-center">
    <div class="animated fadeInRight">
       <c:if test="${currentUser==null}">
          <form action="<%=Const.ROOT %>user/login" method="post" id="loginForm" onsubmit="return dosubmit()">
          <h3 style="border-bottom:1px dashed #999;padding-bottom:10px;">用户登录</h3>
          <br>
             <p class="text-left">用户名:<input type="text" name="username" id="username"/></p>
             <p class="text-left">密    码:<input type="password" name="password" id="password"/></p>
             <p class="text-left">验证码:<img src="<%=Const.ROOT %>code.jsp" onclick="changeCode()" id="codeimg"/><input type="text" name="code" id="code"/></p>
             <p class="text-left"></p>
             <button type="submit" class="button-grey animated fadeInUp">登录</button>
             没有账号?<a class="link-contact" href="#contact">注册一个</a>
          </form>
       </c:if>
       <c:if test="${currentUser!=null}">
          <h3 style="border-bottom:1px dashed #999;padding-bottom:10px;">欢迎你</h3>
          <br>
             <p class="text-center"><img src="<%=Const.ROOT %>${currentUser.logo}" style="max-width:100px;"/></p>
             <p class="text-center">${currentUser.nickname}</p>
             <p class="text-center"><a class="link-contact" href="<%=Const.ROOT %>user_detail.jsp">个人资料</a></p>
             <button type="button" class="button-grey animated fadeInUp" onclick="location.href='<%=Const.ROOT %>user/loginOut'">退出</button>
       </c:if>
    </div>
</div>
用户注册的主要代码如下:
<div class="fluid-container" id="contact">
    <div class="row">
       <div class="col-md-12 text-left">
          <div class="section-header contact-header">
             <h3>用户注册</h3>              
          </div>
       </div>
    </div>
    <div class="section-contact">
       <div class="row">
          <div class="col-md-8 col-sm-12 col-xs-12">
             <form action="<%=Const.ROOT %>user/add" method="post" onsubmit="return checkUserAdd()" id="contact-form" >
                <fieldset>
                   <label for="uname">用户名:</label>
                   <input type="text" name="username" id="uname">
                </fieldset>
                <fieldset>
                   <label for="tel">头像:</label>
                   <input type="file" id="fujian" name="fujian" onchange="updateFile()"/>
                           <input type="hidden" id="logo" name="logo" value="images/default.jpg"/>
                </fieldset>
                <fieldset>
                   <label for="name">昵称:</label>
                   <input type="text" name="nickname" id="name">
                </fieldset>
                <fieldset>
                   <label for="pass1">密码:</label>
                   <input type="password" name="password" id="pass1">
                </fieldset>
                <fieldset>
                   <label for="pass2">确认密码:</label>
                   <input type="password" id="pass2">
                </fieldset>
                <fieldset>
                   <label for="age">email:</label>
                   <input type="text" name="email" id="email">
                </fieldset>
                <fieldset>
                   <label for="tel">电话:</label>
                   <input type="text" name="tel" id="tel">
                </fieldset>
                
                <fieldset>
                   <input type="submit" class="button-dark" value="注册">
                </fieldset>
             </form>
          </div>
          <div class="col-md-7 col-sm-12 col-xs-12">
             
          </div>
       </div>
    </div>
</div>

同时,用户后还可以查看自己的个人资料,个人资料页面的主要代码如下:

<fieldset>
    <label for="tel">头像:</label>
    <input type="file" id="fujian" name="fujian" onchange="updateFile()"/>
                      <input type="hidden" id="logo" name="logo" value="${currentUser.logo }"/>
</fieldset>
<fieldset>
    <label for="name">昵称:</label>
    <input type="text" name="nickname" id="nickname" value="${currentUser.nickname }">
</fieldset>
<fieldset>
    <label for="pass1">密码:</label>
    <input type="password" name="password" id="pass1"  value="${currentUser.password }">
</fieldset>
<fieldset>
    <label for="pass2">确认密码:</label>
    <input type="password" id="pass2">
</fieldset>
<fieldset>
    <label for="age">email:</label>
    <input type="text" name="email" id="email"  value="${currentUser.email }">
</fieldset>

<fieldset>
    <label for="tel">电话:</label>
    <input type="text" name="tel" id="tel"  value="${currentUser.tel }">
</fieldset>
<fieldset>
    <input type="submit" class="button-dark" value="修改">
</fieldset>
管理员模块只是用户模块的变体,在页面部分判断role是否为0,则多增加查看用户列表、删除用户、删除留言功能:
删除留言功能:
<c:if test="${sessionScope.currentUser.id==m.uid || sessionScope.currentUser.role==0}">
        [<a href="javascript:dodel(${m.id})">删除</a>]
</c:if>
用户列表和删除用户功能:
<div class="animated fadeInDown">
    <h3 style="border-bottom:1px dashed #999;padding-bottom:10px;">用户列表</h3>
    <form action="<%=Const.ROOT %>user/list" method="post" id="sform">
                <input type="hidden" name="pageBean.pageNo" value="1" id="pageNo"/>
    <table class="table">
        <thead>
        <tr>
            <th>ID</th>
            <th>用户名</th>
            <th>昵称</th>
            <th>email</th>
            <th>电话</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <c:forEach items="${list}" var="m" varStatus="st">
        <tr>
            <td>${st.count}</td>
          <td>${m.username}</td>
          <td>${m.nickname }</td>
          <td>${m.email}</td>
          <td>${m.tel}</td>
          <td><a class="button-grey" href="javascript:dodel(${m.id})">删除</a></td>
        </tr>
       </c:forEach>
       <tr align="center">
          <td colspan="5">
          <input type="button" class="button-dark" value="上一页" onclick="doPage('${pageBean.prePage }')"> 
          <input type="button" class="button-dark" value="下一页" onclick="doPage('${pageBean.nextPage }')">
          </td>
        </tr>
        </tbody>
    </table>   
    </form>
</div>

值得注意的是,用户列表显示的只能是普通用户,sql语句为:select * from user where isdel=0 and role=1,只有未删除的普通用户才会被显示、被删除。
信息模块和回复模块:
在后端,分别对其定义了属性和接口,而在前端,我则是主要实现了发表留言,回复留言功能,在这些留言的内容输入设置上,我是直接导入了ckeditor的富文本编辑器。
显示留言:

<table class="table">
    <thead>
    <tr>
        <th>ID</th>
        <th>发布人</th>
        <th>标题</th>
        <th>发布时间</th>
        <th>查看</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach items="${messageList}" var="m" varStatus="st">
    <tr>
        <td>${st.count}</td>
       <td>${m.nickname }</td>
       <td>${m.title }</td>
       <td>${m.msgtime}</td>
       <td>
       <a class="button-grey" href="<%=Const.ROOT %>message/detail?id=${m.id}">查看</a>
       <c:if test="${sessionScope.currentUser.role==0}">
       <a class="button-grey" href="javascript:dodel(${m.id})">删除</a>
       </c:if>
       </td>
    </tr>
    </c:forEach>
    <tr align="center">
       <td colspan="5">
       <input type="button" class="button-dark" value="上一页" onclick="doPage('${pageBean.prePage }')"> 
       <input type="button" class="button-dark" value="下一页" onclick="doPage('${pageBean.nextPage }')">
       </td>
    </tr>
    </tbody>
</table>
发表留言:
<fieldset>
    <label for="title">标题:</label>
    <input type="text" name="title" id="title" style="color:#333;">
</fieldset>
<fieldset>
    <label for="content">内容:</label>
    <textarea name="content" id="content" rows="8" style="color:#333;"></textarea>
    <script>
       CKEDITOR.replace('content');
    </script>
</fieldset>
<fieldset>
    <input type="submit" class="button-dark" value="发表">
</fieldset>
回复列表:
<h3 style="border-bottom:1px dashed #999;padding-bottom:10px;">回复列表</h3>
<form action="<%=Const.ROOT %>message/detail" method="post" id="sform">
                <input type="hidden" name="pageBean.pageNo" value="1" id="pageNo"/>
                <input type="hidden" name="id" value="${message.id}"/>
<table class="table">
 <c:forEach items="${replys}" var="m" varStatus="st">
   <tr>
       <td rowspan="3" style="width:20%">
       <img src="<%=Const.ROOT %>${m.logo}" style="max-width:80px"/><br/>${message.nickname}<br/>
       <c:if test="${sessionScope.currentUser.id==m.uid || sessionScope.currentUser.role==0}">
                [<a href="javascript:dodel(${m.id})">删除</a>]
       </c:if>
       </td>
   </tr>
    <tr align="left">
        <td>${m.content }</td>
    </tr>
    <tr align="left">
        <td>回复时间:${m.replytime }</td>
    </tr>
    </c:forEach>
    <tr align="center">
       <td colspan="5">
       <input type="button" class="button-dark" value="上一页" onclick="doPage('${pageBean.prePage }')"> 
       <input type="button" class="button-dark" value="下一页" onclick="doPage('${pageBean.nextPage }')">
       </td>
    </tr>
</table>    
</form>

发表回复的代码与发表留言的代码几乎一样,都是使用了ckeditor富文本编辑器作为内容编辑。
绘制验证码的流程图如下所示:
在这里插入图片描述

图9 绘制验证码
六、关键问题及其解决方法

1.用户注册时的头像上传问题:
上传头像成功后,为什么用户的头像没有及时更新,需要刷新页面才能看到新上传的头像?
解决方法:在上传头像成功后,使用JavaScript或其他前端技术动态更新用户头像的显示,而不是依赖于刷新整个页面。
2.密码确认输入框问题:
为什么添加了name="password"属性后,密码确认输入框才能显示密码按钮?
解决方法:确认密码输入框不需要显示密码按钮,因为用户通常不需要查看确认密码。可以通过在确认密码输入框上方增加一条提示信息的方式来引导用户正确输入密码。
3.SSM框架下数据与数据库连接问题:
如何确保SSM框架下的数据与数据库正确连接?
解决方法:确保数据库配置正确,包括数据库连接URL、用户名和密码。检查MyBatis配置文件是否正确配置了数据源和映射文件。
4.富文本编辑器显示问题:
为什么在代码中引入了CKEditor,但富文本编辑器在页面中没有显示?
解决方法:确保CKEditor的资源文件路径正确引入,检查浏览器控制台是否有相关的错误信息。可能需要查看CKEditor的初始化和调用是否正确。
5.管理员删除用户和留言的权限问题:
如何在系统中正确实现管理员对用户和留言的删除权限控制?
解决方法:在后端代码中实现权限验证,确保只有经过身份验证的管理员才能执行删除操作。可以使用Spring Security等框架来简化权限管理。
6.字符编码问题:
页面出现中文乱码或字符编码不正确。
解决方法: 在HTML文档的头部添加,确保所有涉及字符编码的地方都使用UTF-8。在Tomcat中检查URIEncoding配置。
7.会话管理问题:
用户登录状态无法正确保存或会话失效。
解决方法: 检查Tomcat中会话管理的配置,确保会话超时时间等参数设置正确。查看前端代码,确保会话ID的正确传递和保存。
七、设计结果
留言板首页第一部分:如图所示,留言板首页第一部分有留言列表和用户登录部分,用户可以查看已发送的消息的ID、收信人、消息内容、发送时间等信息,这些信息以表格的形式展示在网页的左侧,如果用户已经注册,可以在网页的右测输入用户名、密码以及验证码来进行登录。具体如图10所示。
当用户输入了正确的用户名、密码以及验证码,用户即可成功登录,显示用户头像和昵称,并且可以选择退出。具体如图11所示:
在这里插入图片描述

图10 留言板首页第一部分
在这里插入图片描述

图11 用户成功登录
留言板首页第二部分:如图所示,是发表留言部分,用户需要在提供的文本框中输入标题和正文,在输入正文的时候还可以在文本框上方的图标中选择不同的文字格式选项,如加粗、斜体、下划线、文字颜色等,来美化或突出自己的内容。最后用户需要在页面底部点击提交按钮,来发表留言,从而让自己的留言在留言板上显示。具体如图12所示
在这里插入图片描述

图12 发表留言界面
留言板首页第三部分:第三部分是用户注册部分,用户需要输入用户名、昵称、密码以及再次确认密码、email、电话。同时用户可以选择自己的头像,若是未选择,头像则是默认为default.jpg。用户此时输入的邮箱和电话必须符合格式。
在这里插入图片描述
图13 用户注册界面
留言板首页管理员部分:管理员登录时,网页上会增加两个按钮,一个是用户列表按钮,一个是删除留言按钮:
在这里插入图片描述

图14 管理员部分首页
查看留言部分:用户可以点击查看按钮来查看留言和回复,并且也可以在下面回复,具体回复界面和发表留言界面几乎一致,这里展现查看留言和回复的界面:
在这里插入图片描述

图15 查看留言和回复界面
用户列表界面:管理员可以查看用户列表并且选择将某些用户删除,在这里,管理员也可以看到用户的部分信息:
在这里插入图片描述

图17 用户列表
个人资料界面:在个人资料界面,用户可以看到自己已经设置的信息,如用户昵称、email、电话等,并且可以修改其中内容,如头像、密码等
在这里插入图片描述

图18 个人资料
数据库部分:用户注册、留言发表、发表回复等操作都会更新数据库,我在数据库中创建了三个表,分别存储留言信息、回复信息和用户信息。
在这里插入图片描述

图19 留言信息
在这里插入图片描述

图20 回复信息
在这里插入图片描述

图21 用户信息
八、软件使用说明
我主要使用的环境是java 1.8。
在配置完环境和tomcat之后首先点击调试或者运行按钮打开留言板首页。

  1. 用户注册和登录:
    注册:
    (1)在用户登录框下方找到注册按钮点击跳转到最下方用户注册界面,或者直接鼠标滚轮滚到最下方用户注册界面
    (2)填写用户名、昵称、密码、邮箱、电话等信息,并且需要二次确认密码。
    (3)上传头像(选择jpg文件)不上传也会有默认头像。
    (4)点击注册按钮完成注册。
    登录:
    (1)在留言板首页找到用户登录框。
    (2)输入正确的用户名和密码。
    (3)输入验证码。
    (4)点击登录按钮。
  2. 用户个人资料管理:
    (1)登录后,用户可以查看个人资料和头像。
    (2)点击头像下方个人资料,可以进入个人资料页面。
    (3)在个人资料页面,可以修改昵称、密码、邮箱、电话、密码等信息。
    (4)可以上传新的头像。
  3. 发表留言和回复:
    (1)在首页或留言列表页面,找到发表留言的按钮。
    (2)输入留言标题和内容,点击发表按钮。
    (3)查看其他用户的留言,可以点击留言下方的回复按钮进行回复。
  4. 查看和管理留言:
    (1)用户可以在首页的留言列表页面查看所有留言。
    (2)用户可以点击留言标题查看详细内容。
  5. 管理员功能:
    (1)管理员可以查看和删除所有普通用户信息。
    (2)管理员可以删除留言。
    (3)管理员权限只能在数据库中修改
    九、参考资料
    [1] 赵强 编著.精通JSP编程.北京:电子工业出版社,2006:34-56.
    [2] 史胜辉,王春明,沈学华 JavaEE基础教程 清华大学出版社 2010.
    [3] 霍尔等著 Mysql与JSP核心编程 北京 清华大学出版社 2010.
    [4] 郭克华编 JavaEE程序设计与应用开发 北京 清华大学出版社 2011.
    十、验收时间及验收情况
    2024年1月22日星期一
    十一、设计体会
    在安全性设计方面,为了增加系统的安全性,我引入了验证码机制和密码确认策略。验证码机制有效防范了恶意登录,而密码确认策略则是在用户注册时引入了二次输入密码验证,以及验证邮箱和电话格式的步骤。这样的设计保障了用户信息的安全,也降低了系统遭受攻击的可能性。
    文件上传和富文本编辑器应用则丰富了系统的功能和用户体验。用户可以自主选择头像,而富文本编辑器的使用则让用户在留言时可以更加自由地表达观点。这些功能的引入不仅使得系统更加具有互动性和趣味性,也提升了用户的满意度。
    在迭代优化方面,我深刻理解到系统设计不是一成不变的,而是需要不断迭代和优化的过程。通过反复测试、用户反馈和不断修复问题,我提高了自己的调试能力和解决问题的能力。这也使我更加明白了系统设计的持续性和演进性。
    全面考虑各方面因素是系统设计的必要条件。不仅要注重技术层面,还需要全面考虑用户需求、安全性、性能等方方面面的因素。这种全面性的思考让我更好地把握项目的方向,确保设计出一个稳健、高效且用户友好的系统。
    个人成长和收获方面,技术广度得到了显著提升。项目中的前后端开发、数据库设计、系统架构等多个方向的涉猎,让我更全面地理解和解决实际问题。在问题解决和调试能力方面,我在项目中遇到了各种各样的问题,通过不断的调试和问题解决,我提高了自己的调试能力和解决问题的能力。而在项目管理与协同能力方面,独立完成项目需要全面负责项目的方方面面,这锻炼了我的项目管理和协同能力。
    总体而言,这个留言板系统的设计和开发过程不仅让我实现了技术上的突破,更在思考和体会中收获颇丰。这一过程不仅对我的技术水平提出了更高的要求,更使我对系统设计的复杂性和综合性有了更加深入的认识。这将对我的未来工作和学习产生积极的影响。在项目中遇到问题、解决问题的过程中,我逐渐培养了对问题深入思考的习惯,在设计与开发的过程中,我发现问题不仅仅存在于代码层面,更涉及到用户需求、系统架构、安全性等多个方面。这使我逐渐建立了系统性思维的观念,将问题看作一个复杂系统中相互关联的一部分,这种思维方式让我更好地理解了设计和开发的全过程。
    注:因为隐私原因,很多内容进行了修改,代码显示会与图片不同,还有!配置环境不会配的话很麻烦,请自行晚上搜索。
    资源链接:https://download.csdn.net/download/m0_63554401/88815828
  • 63
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白鹿依海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值