今天学习的主要内容是在IntelliJ IDEA开发环境中,通过部署Tomcat服务器并连接MySQL数据库,实现了一个完整的留言板系统。这个项目涵盖了前后端开发的全流程,具体包括以下关键环节:
- 开发环境搭建
- 使用IntelliJ IDEA Ultimate版(2023.3)作为开发工具
- 配置Tomcat 9.0服务器
- 建立MySQL 8.0数据库连接
- 前端开发
- 采用JSP+HTML+CSS技术栈
- 设计留言板界面包含:
- 留言展示区域(展示已有留言列表)
- 留言表单(包含用户名、留言内容输入框)
- 提交按钮
- 后端开发
- 使用Java Servlet处理HTTP请求
- 实现的主要功能点:
- GET请求处理:从数据库查询留言列表并返回给前端
- POST请求处理:接收前端提交的留言数据并存入数据库
- 采用JDBC连接池技术实现数据库操作
- 数据库设计
- 创建message表,包含字段:
- id(主键,自增)
- username(varchar,留言者姓名)
- content(text,留言内容)
- create_time(timestamp,留言时间)
- 功能实现细节
- 查看功能:
- 通过SELECT语句查询所有留言
- 按时间倒序排列显示
- 将查询结果封装为List<Message>对象返回前端
- 保存功能:
- 接收前端表单提交的username和content参数
- 执行INSERT语句将数据存入数据库
- 添加事务处理确保数据一致性
- 测试验证
- 通过浏览器访问留言板页面
- 测试留言提交和展示功能
- 验证数据库记录的增删改查操作
这个项目虽然基础,但完整实现了从用户界面到数据存储的整个流程,对于理解Web应用开发的基本原理和流程有很好的实践意义。
代码如下:
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbutils.QueryRunner;
import javax.sql.DataSource;
public class DButil {
public static HikariDataSource getDataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/javawebday1");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("admin123");
return dataSource;
}
}
import java.time.LocalDateTime;
public class message {
private Integer id;
private String nickname;
private String content;
private String ip;
private LocalDateTime mtime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public LocalDateTime getMtime() {
return mtime;
}
public void setMtime(LocalDateTime mtime) {
this.mtime = mtime;
}
}
import com.coder.message;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
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 java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.List;
@WebServlet("/view")
public class ViewMessageBoardServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//查询数据库
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/szb");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("admin123");
QueryRunner runner = new QueryRunner(dataSource);
String sql = "select id,nickname,content,ip,mtime from message order by mtime desc";
try {
List<message> list = runner.query(sql,new BeanListHandler<message>(message.class));
StringBuffer sbf = new StringBuffer();
sbf.append("<table width = '800' border = '1'> align = ‘center'")
.append("<tr><td>序号</td>")
.append("<td>昵称</td>")
.append("<td>留言</td>")
.append("<td>IP</td>")
.append("<td>时间</td></td>");
int index = 1;
for (message message : list) {
sbf.append("<tr>")
.append("<td>").append(index++).append("</td>")
.append("<td>").append(message.getNickname()).append("</td>")
.append("<td>").append(message.getContent()).append("</td>")
.append("<td>").append(message.getIp()).append("</td>")
.append("<td>").append(message.getMtime()).append("</td>")
.append("</tr>");
}
sbf.append("</table>");
out.println("<a href = 'buy.html'>继续留言</a>");
out.println(sbf);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbutils.QueryRunner;
import util.DButil;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.time.LocalDateTime;
/**
* @author MSI-NB
* @date 2025/8/6 22:41
*/
@WebServlet(name = "messageBoardServlet", urlPatterns = "/x")
public class messageBoardServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public messageBoardServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置请求编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
String nickname = request.getParameter("nickname");
String content = request.getParameter("content");
String ip = request.getRemoteAddr();
PrintWriter out = response.getWriter();
// out.println("您的名称是:" + nickname + "<br>");
// out.println("您的留言是:" + content + "<br>");
QueryRunner runner = new QueryRunner(DButil.getDataSource());
String sql = "insert into message(nickname,content,ip,mtime) values(default,?,?,?,?)";
try {
int update = runner.update(sql,nickname,content,ip, LocalDateTime.now());
System.out.println(update>0?"留言成功":"留言失败");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
message.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="x" method="post">
<div>
昵称:
<input type="text" name="nickName">
</div>
<div>
留言:
<textarea name="content"></textarea>
</div>
<div>
<button type="submit">提交留言</button>
</div>
</form>
</body>
</html>
通过实践,我总结出几个重要的经验教训:
获取客户端 IP 时,应该使用
String ip = req.getRemoteAddr()
,而不是getParameter
方法。当数据库表buy_recorders
的 ip 字段设为 NOT NULL 时,插入 null 值会直接引发 SQL 异常。即使 ip 字段允许为 null,在查询时使用
where ip = null
也会导致语法错误,正确的写法应该是where ip is null
,否则同样会触发 500 错误。在开发留言板功能时,我直接复制了之前的代码,但忘记修改新数据库的 SQL 语句,这又导致了 500 错误。这个疏忽让我意识到复制代码时需要格外谨慎。