Java通訊端實現應用程式對資料庫的存取

2022-09-19 18:02:23

最近在完成軟體體系結構上機實驗時,遇到一個有點點小難度的選做題,題目資訊如下:

利用通訊端技術實現應用程式中對資料庫的存取。應用程式只是利用通訊端連線向伺服器傳送一個查詢的條件,而伺服器負責對資料庫的查詢,然後伺服器再將查詢的結果利用建立的通訊端返回給使用者端,如下圖所示。

本來吧,選做題,不太想做的,但是考慮到以後工作的方向和後端相關,那還是做吧。

本次實驗需要做一個GUI介面和一個連線查詢功能,在論壇上借鑑了其他大佬獲取網站內容的部分程式碼,然後自己做了一個及其簡陋的swing介面,算是把這個實驗完成了。

本次實驗專案結構如下

--socketProject
    |--Client.java
    |--GUI.java
    |--SearchInfo.java
    |--Server.java
    |--ServerThread.java

Client.java

使用者端使用dis.readUTF()時,要注意再傳送個字元或者空字元,這裡傳送end,表示關閉連線。不然會出現EOFException

package socketProject;

import java.io.*;
import java.net.*;

public class Client {
    String studentNum = null;
    String result = null;

    public void setStudentNum(String num) {
        this.studentNum = num;
        System.out.println("stu: " + studentNum);
    }

    public void run() throws IOException {
        Socket ss = new Socket("127.0.0.1", 8888);
        System.out.println("Socket: " + ss);
        try {
            DataInputStream dis = new DataInputStream(ss.getInputStream());
            DataOutputStream dos = new DataOutputStream(ss.getOutputStream());
            // the interaction
            dos.writeUTF(studentNum); // 向伺服器傳送學號
            dos.flush();
            result = dis.readUTF().toString(); // 獲得使用者端的json字串
            System.out.println(result);
            dos.writeUTF("end"); // 不加這句會報錯
            dos.flush();
            if (dos != null)
                dos.close();
            if (dis != null)
                dis.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ss != null)
                ss.close();
        }
    }
	// gui介面用於獲取json結果
    public String getResult() {
        return result;
    }
}

Server.java

package socketProject;

import java.io.*;
import java.net.*;

public class Server extends Thread {
    public static final int PORT = 8888;

    // public static void main(String[] args) throws IOException {
    public void run() {
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("ServerSocket: " + serverSocket);
            try {
                while (true) {
                    Socket socket = serverSocket.accept();
                    System.out.println("Socket accept: " + socket);
                    Thread thread = new Thread(new ServerThread(socket));
                    thread.start(); // 開啟一個執行緒,使之支援接收多個使用者端的請求
                }
            } finally {
                serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ServerThread.java

package socketProject;

import java.io.*;
import java.net.*;

public class ServerThread extends Thread {
    Socket socket = null;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            while (true) {
                String str = dis.readUTF().toString();
                String data = new SearchInfo().run(str);
                if (str.equals("end"))
                    break;

                dos.writeUTF(data);
            }
            dos.close();
            dis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SearchInfo.java

package socketProject;

import java.io.*;
import java.net.*;

public class SearchInfo {
    public String run(String s) {
        String url = "your database interface";
        String param = s;
        String sendGET = GetUrl(url, param);
        return sendGET;
    }
    
    public static String GetUrl(String url, String param) {
        String result = ""; // define the result str
        BufferedReader read = null; // define the access result
        
        try {
            URL realUrl = new URL(url + param);
            URLConnection connection = realUrl.openConnection();
            
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 這裡補充通用的請求屬性
            connection.connect(); // 建立實際的連線
            
            read = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = read.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (read != null) {// 關閉流
                try {
                    read.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
    
    public String getJSON(String param) {
        return param;
    }
}

GUI.java

package socketProject;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;

public class GUI extends JFrame {
    private JButton connectDataBase;
    private JLabel entryStudentNum;
    private JTextField studentNum;
    private JButton sendRequest;
    private JLabel showResponseMsg;
    private JPanel northPanel;
    private JPanel southPanel;

    public GUI() {
        init();
    }

    public void init() {
        setTitle("沒啥技術含量的東西");
        // define the component for the window
        connectDataBase = new JButton("連線資料庫");
        entryStudentNum = new JLabel("輸入學號");
        studentNum = new JTextField();
        sendRequest = new JButton("傳送");
        showResponseMsg = new JLabel();

        // add the component to the panel
        this.setLayout(new GridLayout(2, 1));

        northPanel = new JPanel(new GridLayout(1, 4));

        northPanel.add(connectDataBase);
        northPanel.add(entryStudentNum);
        northPanel.add(studentNum);
        northPanel.add(sendRequest);

        southPanel = new JPanel(new GridLayout(1, 1));

        southPanel.add(showResponseMsg);

        setButtons();

        this.add(northPanel);
        this.add(southPanel);
        // initial the window
        setBounds(400, 200, 600, 120);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void setButtons() {
        connectDataBase.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 這裡初始化伺服器端
                Server server1 = new Server();
                Thread th1 = new Thread(server1);
                th1.start();
                // 這裡一定要開啟伺服器端執行緒,否則在點選此按鈕後,整個介面會卡住,無法進行下一步操作
            }
        });

        sendRequest.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Client client1 = new Client();
                client1.setStudentNum(studentNum.getText());
                // 獲取文字方塊的文字,並賦給使用者端的studentNum儲存
                try {
                    client1.run();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                showResponseMsg.setText(client1.getResult());
                // 將得到的資料顯示在介面上
            }
        });
    }

    public static void main(String[] args) {
        new GUI();
    }
}

最終效果如下:

使用時,先點選連線資料庫,然後根據學校提供的介面,輸入自己的學號,點選傳送,即可查詢個人資訊。

不過由於專案工作區非maven以及未來方向非Java的緣故,沒有去深究如何提取json的值 (偷個懶)

參考連結

Java請求一個URL,獲取返回的資料_杜嵐特的部落格-CSDN部落格

java.io.datainputstream.readunsignedshort_socket程式設計報異常java.io.EOFException_竇月汐的部落格-CSDN部落格