Java Servlet

      在〈Java Servlet〉中尚無留言

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>

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *