Java Servlet 並不屬於 Java SE(Standard Edition),它是一種擴充套件,稱為 Jakarta EE,專門用於處理 Web 應用相關的需求。要使用 Servlet 功能,必須透過支援 Java EE 的 Web 容器,例如 Tomcat、Jetty 或 GlassFish,這些容器會內建提供所需的 Servlet API。
若不使用這些容器,也可以手動引入相應的 JAR 檔(如 jakarta.servlet-api.jar),即可在專案中使用 Servlet 技術。
PHP、Python Web、Java Web
php
在 PHP 的網頁開發中,除了可撰寫純 .html 的靜態頁面外,也常使用 .php 副檔名來建立動態網頁。.php 檔案會由 PHP 伺服器解析並執行內部的程式碼,最後輸出成 HTML 格式,傳送至用戶端瀏覽器顯示。 .php 檔案本質上是 HTML 文件中嵌入 PHP 程式碼的結合體。PHP 程式區塊通常以 <?php …. ?> 作為標記,用來分隔 HTML 與 PHP 程式碼。PHP 的語法與 C 語言相似,這種將程式邏輯與畫面結合的寫法,在大型專案中可能會導致程式碼結構混亂,維護上較為困難。
Python Web
在 Python 的 Web 框架中,Django 是目前較為普及的套件。它不僅可以作為 Web Server,還讓開發者能以純 Python 撰寫後端邏輯、模板以及靜態 HTML 頁面。 Django 的模板系統類似於 PHP 的作法,允許在 HTML 中嵌入特定的模板語法,以便與後端 Python 程式碼進行資料傳遞與渲染,扮演 Python 與 HTML 之間的溝通橋樑。 不過 Django 的模板語法較為受限與不便,盡量少用。
Java Web
在 Java Web 開發中,常見的做法是使用 Tomcat 作為 Web Server,再透過 Servlet 技術撰寫純 Java 的後端程式碼。JSP(JavaServer Pages)則是一種嵌入於 HTML 中的語法,用來與後端進行資料交換與畫面呈現,其概念類似於 Python 的模板引擎。 早期 JSP 曾被視為有潛力取代 PHP 的技術,因為它同時具備動態內容與 Java 的穩定性。然而,隨著專案規模增長,JSP 的頁面往往容易變得雜亂,將商業邏輯與畫面混在一起,導致程式碼難以維護。因此在後來的開發實務中,越來越多開發者轉向使用 Servlet 或其他更具架構化的 MVC 框架,如 Spring MVC,以達到更好的模組分離與可維護性。
MySQL 連線
JDBC 驅動
請先到 MySQL 官網 https://dev.mysql.com/downloads/connector/j/ 下載最新版本的驅動程式,Operating System 請選取 Platform Independent,然後再選取 zip 檔。
下載完成後請將 zip 檔解開,在 NetBeans 的 Libraries 按右鍵 Add JAR/Folder,然後選定 mysql-connector-j-8.4.0.jar,當執行編譯時,此 .jar 會自動複製到專案下的 build\web\WEB-INF\lib 之下。
WEB-INF\lib 日後會手動複製到 Tomcat docBase 目錄下,所以不需要再複製到系統級的 C:\Program Files\Apache Software Foundation\Tomcat 11.0\lib。但如果是在 JSP 網頁使用資料庫連線,還是需要手動複製一份到 Tomcat 11.0\lib。
Servlet 網頁
撰寫 Servlet 網頁時,有幾個坑要避開。
手動輸入 java.sql
NetBeans 有 Bug,需手動在程式碼中輸入如下
import java.sql.*
載入驅動程式
Java 6 開始不用手動載入驅動程式,但在 Servlet 還是需要手動載入驅動程式,如下所示。
try{
Class.forName("com.mysql.cj.jdbc.Driver");
}
catch (ClassNotFoundException ex){
out.println(ex.toString());
}
完整代碼
請新增一個 Servlet 網頁,輸入如下完整的代碼
package net.ddns.mahaljsp; import java.sql.*; import java.io.IOException; import java.io.PrintWriter; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet(name = "index", urlPatterns = {"/index"}) public class index extends HttpServlet { protected void processRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String url="jdbc:mysql://ip/cloud"; String user="帳號"; String password="密碼"; PreparedStatement stmt; ResultSet rs; try (PrintWriter out = response.getWriter()) { try{ Class.forName("com.mysql.cj.jdbc.Driver"); try(Connection conn=DriverManager.getConnection(url,user,password)){ stmt=conn.prepareStatement("select * from 台灣股市"); rs=stmt.executeQuery(); out.println("<html>"); out.println("<head>"); out.println("<title>MySQL連線</title>"); out.println("</head>"); out.println("<body>"); out.println( "<table border='1' cellspacing='0' cellpadding='0' width='300'" ); while(rs.next()){ out.println("<tr>"); out.printf("<td>%s</td><td>%s</td><td>%s</td>", rs.getString(2), rs.getString(3), rs.getString(6) ); out.println("</tr>"); } out.println("</table>"); out.println("</body>"); out.println("</html>"); } catch (SQLException ex) { out.print(ex.toString()); } } catch(ClassNotFoundException ex){ out.println(ex.toString()); } } } }
JSP網頁
底下是使用 jsp 網頁的寫法。
<body>
<%!
String user = "student";
String pass = "1234";
String db = "travel";
String url = String.format(
"jdbc:mysql://localhost:3306/%s?useUnicode=true&characterEncoding=UTF-8",
db);
Connection conn;
Statement stmt;
%>
<%
try{
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url,user,pass);
}
catch(SQLException e){
out.println("SQL Exception : " + e);
}
%>
<table border="1" cellpadding="0" cellspacing="0">
<%
//顯示資料庫內容
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from member");
while (rs.next()) {
out.println("<tr>");
out.println(String.format("<td>%s</td><td>%s</td><td>%s</td>",
rs.getString(2),
rs.getString(3),
rs.getString(4)));
out.println("</tr>");
}
%>
</table>
</body>
會員登入系統
Servlet 的運作方式如果用文字描述,一大篇文章也寫不完,直接實作會員登入系統看程式碼是最為快速的方法。
會員登入系統分為登入表單 (login.jsp),登入處理程式 (login.java),即登入成功畫面 (welcome.jsp)。
login.jsp
首先在專案按右鍵/New/JSP,File Name 輸入 login,完整代碼如下。
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>登入系統</title></head>
<style>
table{
margin:0px auto;
width:250px;
border:1px solid;
border-collapse:collapse;
font-size:16px;
}
tr{
border:1px solid;
}
td{
border:1px solid;
}
</style>
<body>
<form method="post" action="login">
<table>
<tr>
<td colspan=2" style="text-align:center;">會員登入系統</td>
</tr>
<tr>
<td>帳號</td>
<td>
<input type="text" name="userAccount"/>
</td>
</tr>
<tr>
<td>密碼</td>
<td>
<input type="password" name="userPassword"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;">
<input type="submit" value="登入">
</td>
</tr>
</table>
</form>
<p style="color:red;">${error}</p>
</body>
</html>
上述表單 action 屬性會跳到 /login 網頁,此為 Servlet 網頁。
Login.java
在專案下按「右鍵/New/Servlet」,Class Name 輸入 login,完整代碼如下。
package net.ddns.mahaljsp; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import java.io.PrintWriter; import java.sql.*; @WebServlet(name = "login", urlPatterns = {"/login"}) public class login extends HttpServlet { @Override protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); boolean isValid=false; String userAccount=request.getParameter("userAccount"); String userPassword=request.getParameter("userPassword"); try { Class.forName("com.mysql.cj.jdbc.Driver"); try(Connection conn=DriverManager.getConnection( G.dbUrl,G.dbUser, G.dbPassword)) { String cmd="select * from 會員資料 where userAccount=? and userPassword=?"; PreparedStatement ps=conn.prepareStatement(cmd); ps.setString(1, userAccount); ps.setString(2, userPassword); ResultSet rs=ps.executeQuery(); if (rs.next())isValid=true; } catch(SQLException ex){} if(isValid){ HttpSession session=request.getSession(); session.setAttribute("user", userAccount); response.sendRedirect("welcome.jsp"); } else{ response.getWriter().println("帳密錯誤"); } } catch (ClassNotFoundException ex) {} } @Override public String getServletInfo() { return "Short description"; } }
session 是記錄登入者的帳號,而 response.sendRedirect 則是跳轉其它網頁。
welcome.jsp
因為上述 login.java 如果登入成功會自動轉跳 welcome.jsp,所以就隨意寫個測試程式,代碼如下
<%@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> <h1>歡迎光臨</h1> </body> </html>