學習Java的Day27

今天學習的主要內容是在IntelliJ IDEA開發環境中,通過部署Tomcat服務器并連接MySQL數據庫,實現了一個完整的留言板系統。這個項目涵蓋了前后端開發的全流程,具體包括以下關鍵環節:

  1. 開發環境搭建
  • 使用IntelliJ IDEA Ultimate版(2023.3)作為開發工具
  • 配置Tomcat 9.0服務器
  • 建立MySQL 8.0數據庫連接
  1. 前端開發
  • 采用JSP+HTML+CSS技術棧
  • 設計留言板界面包含:
    • 留言展示區域(展示已有留言列表)
    • 留言表單(包含用戶名、留言內容輸入框)
    • 提交按鈕
  1. 后端開發
  • 使用Java Servlet處理HTTP請求
  • 實現的主要功能點:
    • GET請求處理:從數據庫查詢留言列表并返回給前端
    • POST請求處理:接收前端提交的留言數據并存入數據庫
  • 采用JDBC連接池技術實現數據庫操作
  1. 數據庫設計
  • 創建message表,包含字段:
    • id(主鍵,自增)
    • username(varchar,留言者姓名)
    • content(text,留言內容)
    • create_time(timestamp,留言時間)
  1. 功能實現細節
  • 查看功能:
    • 通過SELECT語句查詢所有留言
    • 按時間倒序排列顯示
    • 將查詢結果封裝為List<Message>對象返回前端
  • 保存功能:
    • 接收前端表單提交的username和content參數
    • 執行INSERT語句將數據存入數據庫
    • 添加事務處理確保數據一致性
  1. 測試驗證
  • 通過瀏覽器訪問留言板頁面
  • 測試留言提交和展示功能
  • 驗證數據庫記錄的增刪改查操作

這個項目雖然基礎,但完整實現了從用戶界面到數據存儲的整個流程,對于理解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;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}@Overrideprotected 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>

通過實踐,我總結出幾個重要的經驗教訓:

  1. 獲取客戶端 IP 時,應該使用 String ip = req.getRemoteAddr(),而不是 getParameter 方法。當數據庫表 buy_recorders 的 ip 字段設為 NOT NULL 時,插入 null 值會直接引發 SQL 異常。

  2. 即使 ip 字段允許為 null,在查詢時使用 where ip = null 也會導致語法錯誤,正確的寫法應該是 where ip is null,否則同樣會觸發 500 錯誤。

  3. 在開發留言板功能時,我直接復制了之前的代碼,但忘記修改新數據庫的 SQL 語句,這又導致了 500 錯誤。這個疏忽讓我意識到復制代碼時需要格外謹慎。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94957.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94957.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94957.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【計算機網絡 | 第3篇】物理媒介

文章目錄物理媒介介紹與物理媒體的分類&#x1f95d;成本考量引導型傳輸媒體&#x1f34b;引導型傳輸媒體&#xff1a;雙絞線&#x1f34b;?&#x1f7e9;雙絞線類別雙絞線的發展歷程雙絞線的物理限制引導型傳輸媒體&#xff1a;同軸電纜&#x1f34b;?&#x1f7e9;結構組成…

golang的切片

切片 為什么需要切片 用于元素的個數不確定&#xff0c;所以無法通過數組的形式來進行統計。此時就需要切片 切片&#xff0c;也因此可以粗略地理解為動態數組數組的長度不能用變量來確定&#xff0c;這時候切片slice也就派上用場了 切片地基本介紹 切片的英文是slice切片是數組…

在labview中實現視頻播放

這里分享一個迅雷的視頻播放控件APlayer&#xff0c;非常的好用。具體操作步驟如下&#xff1a; 1.下載控件: 首先下載http://aplayer.open.xunlei.com/codecs.zip&#xff0c;將codecs文件解壓后打開&#xff0c;按快捷鍵contrlA,隨后contrlc復制里面所有的文件&#xff1b;…

ubuntu 22.04 使用yaml文件 修改靜態ip

前提&#xff1a; 啟動服務 sudo systemctl start systemd-networkd 設置開機自啟 sudo systemctl enable systemd-networkd 檢查狀態&#xff08;確保顯示 active (running)&#xff09; sudo systemctl status systemd-networkd 若想停止&#xff1a; 停止當前運行的服務 sud…

閘機控制系統從設計到實現全解析:第 4 篇:Redis 緩存與分布式鎖實現

第 4 篇&#xff1a;Redis 緩存與分布式鎖實現 一、Redis 在系統中的核心作用票證信息緩存&#xff1a;將高頻訪問的票證數據&#xff08;如狀態、有效期&#xff09;緩存至 Redis&#xff0c;減少數據庫查詢&#xff0c;提升驗證響應速度。分布式鎖&#xff1a;在高并發場景下…

北京天津唐山廊坊滄州打撈日記

北京天津唐山廊坊滄州打撈日記 打撈搜蚯蚓疏通 北京&#xff1a;護城河畔的情誼打撈 清晨&#xff0c;北京的護城河在朝陽的映照下泛著微光。我接到一位年輕小伙的電話&#xff0c;聲音中滿是焦急。原來&#xff0c;他與女友在河邊約會時&#xff0c;不小心將女友送他的定情玉佩…

全志刷機工具:PhoenixSuit-全志芯片處理器-刷機工具安裝包及最詳細使用教程指南

全志刷機工具&#xff1a;PhoenixSuit-全志芯片處理器刷機工具安裝包及最詳細使用教程指南&#xff0c;此文章主要是分享機頂盒、電視盒子&#xff0c;全志芯片盒子&#xff08;其中包含全志處理器、全志芯片、全志CPU等等&#xff09;的刷機工具、刷機工具安裝教程以及如何使用…

淺談 VM 橋接模式:讓虛擬機像真實電腦一樣接入網絡

在虛擬化環境中&#xff0c;虛擬機&#xff08;Virtual Machine, VM&#xff09;與外部網絡之間的通信方式有多種&#xff0c;比如 NAT 模式、Host-Only 模式、橋接模式&#xff08;Bridged Networking&#xff09; 等。其中&#xff0c;橋接模式是最接近“真實物理機”網絡行為…

計算機視覺(1)-圖像采集設備選型全景表(工業 + 醫療 + 車載)

圖像采集設備選型全景表&#xff08;工業 醫療 車載&#xff09;一份面向工程師的“場景—設備—協議”速查表1 工業 & 醫療 & 通用場景應用場景主流設備形態接口 / 協議典型性能突出優勢致命短板動態范圍工業檢測AOI / 量測 / 缺陷工業相機 采集卡Camera Link HSCo…

計算機視覺(3)深度學習模型部署平臺技術選型與全棧實踐指南

一、部署平臺概述與分類 深度學習模型部署平臺的分類需兼顧技術特性與應用場景的適配性&#xff0c;基于“技術定位-場景適配”雙維度分類法&#xff0c;可將其劃分為通用開源框架、云廠商服務及專用邊緣工具三大類&#xff0c;各類別在設計目標、核心能力與場景覆蓋上呈現顯著…

Scratch編程:槍戰游戲(附源碼)

&#x1f3ae; 操作說明 W / A / S / D 或 方向鍵&#xff1a;移動 C&#xff1a;滑鏟 空格鍵&#xff1a;取消滑鏟 鼠標點擊&#xff1a;開火 數字鍵 1 / 2 / 3 / 4&#xff1a;切換武器 G&#xff1a;快速使用道具 F&#xff1a;近戰攻擊 Q&#xff1a;瞄準 / 使用技能…

應急響應復現

一、前言&#xff1a;當企業發生黑客入侵、系統崩潰或其它影響業務正常運行的安全事件時&#xff0c;急需第一時間進行處理&#xff0c;使企業的網絡信息系統在最短時間內恢復正常工作&#xff0c;進一步查找入侵來源&#xff0c;還原入侵事故過程&#xff0c;同時給出解決方案…

分布式事務Seata TCC模式篇

介紹 ? 官網: https://seata.apache.org/zh-cn/docs/user/mode/tcc ? 回顧Seata AT 模式基于 支持本地 ACID 事務 的 關系型數據庫&#xff0c;如下&#xff1a; 一階段 prepare 行為&#xff1a;在本地事務中&#xff0c;一并提交業務數據更新和相應回滾日志記錄。二階段 c…

Day37--動態規劃--52. 攜帶研究材料(卡碼網),518. 零錢兌換 II,377. 組合總和 Ⅳ,57. 爬樓梯(卡碼網)

Day37–動態規劃–52. 攜帶研究材料&#xff08;卡碼網&#xff09;&#xff0c;518. 零錢兌換 II&#xff0c;377. 組合總和 Ⅳ&#xff0c;57. 爬樓梯&#xff08;卡碼網&#xff09; 本文全部都是 ” 完全背包 “ 問題&#xff0c;從零到入坑&#xff0c;從入坑到爬出來。 本…

Linux文件操作

Linux文件Linux下的文件類型b 塊設備文件---->存儲類設備&#xff08;硬盤&#xff09;c 字符設備文件--->輸入輸出設備d 目錄文件--->文件夾- 普通文件--> xxx.c xxx.h xxx.txt xxx.jpg xxx.mp4 a.outl 軟鏈接文件-->快捷方式s 套接字文件-->網絡通信p 管道…

Linux epoll 觸發模式詳解:LT vs ET

兩種核心觸發模式 1. 水平觸發 (Level-Triggered, LT) 工作方式: 當文件描述符處于就緒狀態時,epoll 會持續通知 只要狀態未改變,每次調用 epoll_wait 都會返回該描述符 特點: c // 內核處理邏輯 (ep_send_events_proc) if (!(epi->event.events & EPOLLET)) { /…

STM32學習筆記6-TIM-2輸出比較功能

第二部分&#xff0c;定時器的輸出比較功能OC&#xff08;Output Compare&#xff09;輸出比較輸出比較可以通過比較CNT與CCR寄存器值的關系&#xff0c;來對輸出電平進行置1、置0或翻轉的操作&#xff0c;用于輸出一定頻率和占空比的PWM波形每個高級定時器和通用定時器都擁有4…

MATLAB核心技巧:從入門到精通

一 1.數值 顯示 格式 format style 設置 eg: pi format longE; or 2.清除指令 clc 清除命令行窗口 clear 清除工作區 cls 3.搜索路徑設置 path(path,E:\ads\) or addpath 4.M文件 用戶把要實現的命令寫在一個以.m為擴展的文件中&#xff0c;然后由matlab系統進行解讀…

AnyDesk遠程工具免費版,v9.5.110綠色便攜版,秒連遠程桌面,剪貼板同步超實用

[軟件名稱]: AnyDesk遠程工具免費版 [軟件大小]: 7.5 MB [軟件大小]: 夸克網盤 | 百度網盤 軟件介紹 AnyDesk 讓遠程工作變得輕而易舉。無論您身處辦公室的另一端還是世界的另一側&#xff0c;只需在設備上下載、安裝并啟動 AnyDesk.exe&#xff0c;即可輕松訪問遠程屏幕。…

AI: 給Gemini CLI配上“說明書”, 精通的GEMINI.md項目記憶

嘿&#xff0c;各位技術同好&#xff01;今天我們來聊一個能極大提升AI編程助手效率的酷炫功能——Google Gemini CLI 中的 GEMINI.md 文件。 在日常開發中&#xff0c;我們越來越依賴像 Gemini 這樣的 AI 助手來幫我們寫代碼、調試 Bug 甚至重構項目。但大家是否遇到過這種情況…