JAVA可視化鬧鐘源碼

来源:https://www.cnblogs.com/mxdon/archive/2019/08/08/11324600.html
-Advertisement-
Play Games

概述 一些同學的Java課設有這樣一個問題,比較感興趣就做了一下 功能介紹: 1、可增加鬧鐘 2、可刪除鬧鐘 3、時間到了響鈴 4、關閉鬧鐘不會丟失鬧鐘(因為鬧鐘存儲在txt文件中,不會因程式關閉就終止) 缺點 1、沒有使用多線程,鬧鐘響起時只能等待1分鐘或者關閉程式 2、界面設計不夠美觀,後期有時 ...


概述

一些同學的Java課設有這樣一個問題,比較感興趣就做了一下

功能介紹:

1、可增加鬧鐘

2、可刪除鬧鐘

3、時間到了響鈴

4、關閉鬧鐘不會丟失鬧鐘(因為鬧鐘存儲在txt文件中,不會因程式關閉就終止)

缺點

1、沒有使用多線程,鬧鐘響起時只能等待1分鐘或者關閉程式

2、界面設計不夠美觀,後期有時間會進行修改,重新設計

3、沒有鬧鐘修改的功能,雖然可以通過增刪來達到修改的目的,但功能仍然屬於空缺範圍

  1 package Clock;
  2 
  3 import sun.audio.AudioPlayer;
  4 import sun.audio.AudioStream;
  5 
  6 import javax.swing.*;               //awt和swing是做界面用的類
  7 import java.awt.*;
  8 import java.awt.event.ActionEvent;
  9 import java.awt.event.ActionListener;
 10 import java.awt.event.WindowAdapter;
 11 import java.awt.event.WindowEvent;
 12 import java.io.*;                   //io流用於讀寫文件,包括增刪鬧鐘、打開鈴聲等等
 13 import java.util.Calendar;          //用於獲取當前時間的類
 14 import java.util.GregorianCalendar;//標準陽曆
 15 import java.util.StringTokenizer;  //讀取文件轉換成電腦語言用的類
 16 /*
 17 1 計時器
 18 要求1:一個帶有可視化界面的鐘錶。
 19 要求2:可以添加若幹個鬧鐘。
 20 要求3:具備持久化功能,關閉程式不能丟失鬧鐘。
 21 要求4:鬧鐘是可編輯,可刪除的。
 22 
 23 實現:先創建一個面板顯示鬧鐘,面板內創建按鈕增加鬧鐘,按鈕查看鬧鐘,按鈕刪除鬧鐘
 24      線程間隔1s讀取時間和鬧鐘比較
 25 
 26  */
 27 public class ClockTry extends JFrame implements Runnable {
 28     /* 成員變數 */
 29     private JPanel xx;      //總的面板
 30     private JComboBox ho;   //hour選擇時間的下拉框
 31     private JComboBox mi;  //min選擇分鐘的下拉框
 32     private JButton tjnz;   //添加鬧鐘的按鈕
 33     private JButton schour;    //刪除鬧鐘的按鈕
 34     private String filename = "D://homework//java//Gui//src//Clock//0.wav";     //所有的路徑改這兩個地方就可以了
 35     private String pathname = "D://homework//java//Gui//src//Clock//nz.txt"; // 絕對路徑或相對路徑都可以,寫入文件時演示相對路徑,讀取以上路徑的input.txt文件
 36 
 37     private int HOUR;       //定義HOUR用於接收按鈕按下從下拉框中獲取的數據
 38     private int MIN;        //同上
 39 
 40     int x = 100, y = 100, r = 100; // (x,y)為(0,0)點,表示原點
 41     int h, m, s; // 時,分,秒
 42     double rad = Math.PI / 180; //
 43 
 44     private String[][] str= new String[100][2];     //定義二維數組,用於存儲以及對小時和分針的操作,暫定為100個鬧鐘於是定義為【100】【2】
 45     /**
 46     *讀取文件,每次的增刪都需要對數據進行讀取,將數據寫在面板上也需要讀取數據
 47      */
 48     public void readFile() {
 49         try (FileReader reader = new FileReader(pathname);      //創建一個FilReader對象,將文件讀出來,相當於請教一個當地人,當地人瞭解本地文化,但是語言不通聽不懂
 50              BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言,相當於請一個翻譯,把當地人讀取的東西轉換成電腦能懂的東西
 51         ) {
 52             String line;
 53 
 54             int i =0;
 55             while ((line = br.readLine()) != null) {        //翻譯理解的東西存到line裡面
 56                 int j =0;
 57                 StringTokenizer st = new StringTokenizer(line, ":");        //重點:由於存儲數據時都是時間,道理來說都是數字,無法區分小時部分和分鐘部分
 58                 while (st.hasMoreTokens()){               //每讀取一次讀到的內容     //所以這裡用分割符“:”來分割,相應的,後面的寫入文件也應該已“:”分割進行寫入
 59                     str[i][j]=st.nextToken();               //把讀到的內容存儲在數組裡面便於後面的操做——增刪
 60                     j++;                                    //包括上面的j=0,是將for迴圈拆分放進while迴圈中,要不然迴圈寫起來也很麻煩
 61                 }
 62                 //System.out.print(str[i][0]+":"+str[i][1]);       寫的時候用來在控制台列印查看效果
 63                 //System.out.println();
 64                 i++;
 65                 j = 0;
 66             }
 67         } catch (IOException e) {
 68             e.printStackTrace();                    //try……catch拋出異常
 69         }
 70     }
 71 
 72 
 73     /**
 74      * 寫入TXT文件
 75      */
 76     public void writeFile() {
 77         HOUR = Integer.valueOf(ho.getSelectedIndex());                          //獲取下拉框中的值,存儲到HOUR中
 78         MIN = Integer.valueOf(mi.getSelectedIndex());
 79         String x = HOUR + ":" + MIN;
 80         try (FileWriter writer = new FileWriter(pathname,true);         //同上面的讀取,本地人寫入,註意:後面的append:true是表示不是重新寫,而是在後面追加
 81              BufferedWriter out = new BufferedWriter(writer)                    //翻譯一下再寫入
 82         ) {
 83 
 84             out.write(HOUR + ":" + MIN + "\r\n");                           //這裡寫入的時候把:寫進去了!
 85             out.flush();                                                        // 把緩存區內容壓入文件,電腦的存儲過程,存在緩存區再寫入文件
 86             JOptionPane.showMessageDialog(null,"鬧鐘添加成功!","添加鬧鐘提醒",JOptionPane.INFORMATION_MESSAGE); //提示框:添加鬧鐘成功
 87         } catch (IOException e) {
 88             e.printStackTrace();
 89 
 90         }
 91 
 92     }
 93 
 94 
 95     /**
 96      * 刪除鬧鐘,實際上是先將要刪除的數據找到移除數組,再將數組重新寫入,所以要先讀取文件,再重新寫入
 97      */
 98     public void shanchuFile() {
 99         HOUR = Integer.valueOf(ho.getSelectedIndex());
100         MIN = Integer.valueOf(mi.getSelectedIndex());
101         try (FileWriter writer = new FileWriter(pathname);              //沒有append:true,表示重新寫!
102              BufferedWriter out = new BufferedWriter(writer)
103         ) {
104             readFile();
105             for (int i = 0; i < 100; i++) {
106                 if (Integer.valueOf(str[i][0])==HOUR && Integer.valueOf(str[i][1])==MIN){
107                     continue;
108                 }
109                 else{
110                     out.write(str[i][0]+":"+str[i][1]+"\r\n"); // \r\n即為換行
111                 }
112             }
113 
114             //out.write("1"+"1"+"\r\n"); // \r\n即為換行
115             out.flush(); // 把緩存區內容壓入文件
116         } catch (IOException e) {
117             e.printStackTrace();
118         }catch (NumberFormatException e){
119             System.out.println("this isn't exist!");
120             JOptionPane.showMessageDialog(null,"該鬧鐘已刪除!","刪除鬧鐘提醒",JOptionPane.INFORMATION_MESSAGE); //彈窗提示
121         }
122     }
123 
124     /* 初始化函數 */
125     public void init() {
126 
127         Calendar now = new GregorianCalendar();     //獲取當前時間
128         /*
129          * GregorianCalendar(標準陽曆)
130          * 是Calendar(日曆)【國際環境下都能運行的程式】
131          * 的子類
132          */
133         s = now.get(Calendar.SECOND) * 6; // 秒針轉換成角度:1秒,秒針動一次,轉動6°
134         m = now.get(Calendar.MINUTE) * 6; // 分針轉換為角度:1分,分針動一次,轉動6°
135         h = now.get(Calendar.HOUR) * 30 + now.get(Calendar.MINUTE) / 12 * 6; // 先把分化為小時,再乘以6°,因為分針轉12°,時針才會轉1°,一小時中間有5格,數學問題
136         /*
137          * Calendar.HOUR 顯示範圍:1-12(無論AM還是PM) Calendar.HOUR_OF_DAY 顯示範圍:1-24(包括PM
138          */
139 
140         Thread t = new Thread(this);        //添加線程,線程目標是整個程式,this
141         t.start();                                  //線程就緒
142     }
143 
144     public void paint(Graphics g) {                 //awt中的方法,因為要時時顯示鬧鐘,所以不得不使用繪畫的方式,不斷重繪
145         super.paint(g);
146         /*
147          * paint(g)函數會重繪圖像,要加上super.paint(g),表示在原來圖像的基礎上,再畫圖。
148          * 如果不加super.paint(g),重繪時,會將原有的繪製清空,再根據paing(g)函數繪製。
149          */
150 
151         g.setColor(Color.BLACK);                    //設置畫筆顏色——黑色
152         g.drawOval(x, y, r * 2, r * 2);// 畫表
153         /* drawOval(x,y,width,height)以矩形恰好框住橢圓,矩形左上角的頂點坐標為(x,y) */
154 
155         // 秒針
156         int x1 = (int) (90 * Math.sin(rad * s));
157         int y1 = (int) (90 * Math.cos(rad * s));
158         g.drawLine(r+x, r+y, r+x + x1, r +y- y1);
159         /* drawLine(a,b,c,d) (a,b)為起始坐標 (c,d)為終點坐標 */
160 
161         // 分針
162         x1 = (int) (80 * Math.sin(rad * m));
163         y1 = (int) (80 * Math.cos(rad * m));
164         g.drawLine(r+x, r+y, r +x+ x1, r+y - y1);
165 
166         // 時針
167         x1 = (int) (60 * Math.sin(rad * h));
168         y1 = (int) (60 * Math.cos(rad * h));
169         g.drawLine(r+x, r+y, r+x + x1, r +y- y1);
170 
171         // 畫數字
172         int d = 30;
173         for (int i = 1; i <= 12; i++) {
174             x1 = (int) ((r - 10) * Math.sin(rad * d));
175             y1 = (int) ((r - 10) * Math.cos(rad * d));
176             g.drawString(String.valueOf(i), r+x + x1, r+y - y1);    //字元型的數據才能畫
177             d += 30;
178         }
179 
180         // 畫刻度
181         d = 0;
182         for (int i = 1; i <= 60; i++) {
183             x1 = (int) ((r - 2) * Math.sin(rad * d));
184             y1 = (int) ((r - 2) * Math.cos(rad * d));
185             g.drawString(".", r+x + x1, r +y- y1);      //畫的是點,表示刻度
186             d += 6;
187         }
188         // 顯示時間
189         Calendar now1 = new GregorianCalendar();
190         int a, b, c;
191         a = now1.get(Calendar.HOUR_OF_DAY);     //獲取當前的小時
192         b = now1.get(Calendar.MINUTE);          //獲取當前的分鐘
193         c = now1.get(Calendar.SECOND);           //獲取當前的秒鐘
194         g.drawString(a + ":" + b + ":" + c, 175, 330);      //將時間也畫到面板上
195         g.drawString("全部鬧鐘:",100,350);                  //全部鬧鐘
196 
197         try (FileReader reader = new FileReader(pathname);
198              BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言
199         ) {
200             String line;
201 
202             int i =0;
203             while ((line = br.readLine()) != null) {
204                 int j =0;
205                 StringTokenizer st = new StringTokenizer(line, ":");
206 while (st.hasMoreTokens()){
207 str[i][j]=st.nextToken();
208                     j++;
209                 }
210                 g.drawString(str[i][0]+":"+str[i][1]+"\n",180+(i/10)*70,350+15*(i-(i/10)*10));  //貌似重新寫了一下readfile的方法,其實是有區別的,這裡是讀取以後畫出來
211 //qbnz.setText(str[i][0]+":"+str[i][1]+"\n");
212 //System.out.print(str[i][0]+":"+str[i][1]);
213 //System.out.println();
214                 i++;
215                 j = 0;
216             }
217         } catch (IOException z) {
218             z.printStackTrace();
219         }
220     }
221 
222 
223 // 實現Runnable,實現implement Runnable就務必實現run方法,使線程運行
224 public void run() {
225 while (true) {
226 try {
227                 Thread.sleep(1000);// 間隔一秒
228             } catch (Exception ex) {
229             }
230             s += 6;                // 秒針每次走6°
231 if (s >= 360) {
232                 s = 0;            // 秒針歸零
233                 m += 6;
234 if (m == 72 || m == 144 || m == 288) {
235                 h += 6;                // 分針走72°,時針走6° 分針的12倍,時針走一次
236                 }
237 
238 if (m >= 360) {
239                 m = 0;                // 分針歸零
240                 h += 6;
241                 }
242 if (h >= 360) {
243                 h = 0;                // 時針歸零
244                 }
245             }
246 
247 
248 this.repaint();     // 重新繪製
249 //this.readFile();
250 this.alert();       //將鬧鐘加入到線程當中
251         }}
252 
253 public void alert(){
254         Calendar now1 = new GregorianCalendar();
255 int a, b;
256         a = now1.get(Calendar.HOUR_OF_DAY);
257         b = now1.get(Calendar.MINUTE);      //這裡沒有獲取秒針是因為鬧鐘不看秒針。。。。。
258 try (FileReader reader = new FileReader(pathname);
259 BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成電腦能讀懂的語言
260         ) {
261 String line;
262 String[][] str= new String[100][2];
263 int i =0;
264 while ((line = br.readLine()) != null) {
265 int j =0;
266                 StringTokenizer st = new StringTokenizer(line, ":");
267 while (st.hasMoreTokens()){
268 str[i][j]=st.nextToken();
269                     j++;
270                 }
271 if (a==Integer.valueOf(str[i][0]) && b==Integer.valueOf(str[i][1])){        //讀取後與獲得的時間比較,如果鬧鐘存在,就響
272 try{
273                         InputStream in = new FileInputStream("D://homework//java//Gui//src//Clock//0.wav");//FIlename 是你載入的聲音文件如(“game.wav”)
274                         AudioStream as = new AudioStream(in);           //和讀取文件類似的原理,經翻譯之後才播放出來
275                         AudioPlayer.player.start(as);       //用靜態成員player.start播放音樂
276                         } catch(FileNotFoundException e){
277                         System.out.print("FileNotFoundException ");
278                     } catch(IOException e){
279                         System.out.print("有錯誤!");
280                     }
281                 }
282                 i++;
283                 j = 0;
284             }
285         } catch (IOException z) {
286             z.printStackTrace();
287         }
288     }
289 
290 //初始化界面
291 public  void  launchFrame(){
292         xx = new JPanel();      //插入一個面板
293 String[] hours = new String[24];        //長度為24的數組用於存儲小時
294 for (int i = 0; i < hours.length; i++) {
295             hours[i]=i+"";              //迴圈對hour進行賦值
296         }
297         ho = new JComboBox(hours);      //將hour加入到下拉框中
298         ho.setSize(50,40);  //設置大小好像沒用
299 String[] mins = new String[60];     //同理,這是分鐘的地方
300 for (int i = 0; i < mins.length; i++) {
301             mins[i]=i+"";                   //分鐘賦值
302         }
303         mi = new JComboBox(mins);           //分鐘下拉框
304         mi.setSize(50,40);
305         tjnz = new JButton();               //添加鬧鐘的按鈕,拼音首字母
306         tjnz.setText("添加到鬧鐘");             //按鈕上顯示的文字
307         tjnz.setSize(100,40);
308         schour = new JButton();                 //刪除鬧鐘的按鈕
309         schour.setText("從鬧鐘中刪除");           //按鈕上顯示的文字
310         schour.setSize(100,40);
311 
312 /**
313          * 將按鈕下拉框啥的加入到面板中
314          */
315         xx.add(ho);
316         xx.add(mi);
317         xx.add(tjnz);
318         xx.add(schour);
319 this.add(xx);       //將面板加入到this對象中,要不然面板就不顯示
320         tjnz.addActionListener(new ActionListener() {       //添加按鈕的功能
321                 @Override                                   //重寫的標識,務必要會
322 public void actionPerformed(ActionEvent e) {
323 // TODO Auto-generated method stub
324                     HOUR = Integer.valueOf(ho.getSelectedIndex());
325                     MIN = Integer.valueOf(mi.getSelectedIndex());      //獲取到時分後
326                     writeFile();                                       //寫入txt文件保存為鬧鐘
327                     readFile();                                        //再讀取,這樣才能時時更新面板上的全部鬧鐘
328         }});
329 
330         schour.addActionListener(new ActionListener() {
331                 @Override
332 public void actionPerformed(ActionEvent e) {
333 // TODO Auto-generated method stub
334                     HOUR = Integer.valueOf(ho.getSelectedIndex());
335                     MIN = Integer.valueOf(mi.getSelectedIndex());
336                     shanchuFile();                                      //這裡是刪除鬧鐘的按鈕功能
337                     readFile();
338                 }});
339 
340 this.setTitle("小鬧鐘");                                     //設置視窗標題
341 this.setVisible(true);                                      //設置視窗不隱身
342 this.setSize(700,500);                        //設置視窗大小
343 this.setLocation(500, 250);                           //設置視窗位置,相對於桌面左上角
344 this.init();                                                //調用初始化函數進行初始化
345 this.alert();
346 //this.run();       //重覆調用run()方法結果是秒針一次走12°
347 this.addWindowListener(new WindowAdapter() {
348             @Override
349 public void windowClosing(WindowEvent e) {
350                 System.exit(0);
351             }
352         });     //設置視窗叉號的功能,點擊就關閉程式
353     }
354 
355 
356 
357 public static void main(String[] args) {
358         ClockTry c = new ClockTry();        //main方法,必有的成分,創建主類對象,
359         c.launchFrame();                    //調用初始化面板的方法,簡化了本該在main方法中寫的代碼
360 
361 }}

運行效果

2

3

此版本為第一次嘗試,後續有時間會繼續更新版本


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫在前面:今天主要介紹兩個東西:JS標識符和數據類型 一 變數和常量 在介紹標識符之前有必要先瞭解一下JS中的變數和常量。 變數:程式執行期間可操作的臨時存儲數據的記憶體空間。 聲明方式: var:函數作用域,變數聲明提前,可重覆聲明,後聲明的覆蓋前面的。 let:塊級作用域,聲明不會提前,不可重覆聲 ...
  • 設計原則的目的是構建出更加穩定和健壯的軟體。而像這樣的軟體要求 - 松耦合 - 可擴展性強 ...
  • 為了面向介面編程,而不是面向實現編程,所以此時我麽就不能再直接使用new了,因 為當看到“new”時,我們就會想到“具體”。 下麵來看一個例子,假如你有一個披薩店,你的代碼可能這麼寫: 但是此時你需要更多披薩類型,所以你就要修改代碼,如下所示: 但是此時由於產業競爭問題,你想加入一些其他口味的piz ...
  • 另一篇文章,也對TempData 做了很詳細的介紹,鏈接地址:https://www.jianshu.com/p/eb7a301bc536 。 MVC中的 TempData 可以在Controller之間進行傳遞,如果使用過了之後,不管是在View里使用,還是在controller里使用,再次獲取就 ...
  • 前言: 本文一切觀點和測試代碼是在python3的基礎上。 Content: 1.什麼是魔法函數,魔法函數__getitem__在python中應用。 2.python的數據模型和數據模型這種設計對python的影響 3.python常用的魔法函數 4.從len()方法看魔法函數的特點 5.魔法函數 ...
  • 剛到大三時前面兩年荒廢了 什麼都沒學到所以打算自學個編程 自己對Java非常感興趣 就打算自學Java 但是一開始看書 有很多看不懂 非常苦惱 也打算過去培訓 但是培訓太貴了 最後打算還是先自學一段時間 不行再去培訓 最後買了一套教程 覺得這套教程非常不錯 老師講解非常細緻 通俗易懂 自學了幾個月 ...
  • 一、集成開發環境(Integrated Develop Environment,簡稱IDE) 1.什麼是集成開發環境 (1)集成開發環境可以使軟體開發變得更簡單 (2)沒有IDE工具: i.需要安裝JDK,需要配置環境變數;需要手動的將java源文件編譯生成class位元組碼文件; ii.java源程 ...
  • 結合 "Spring 後置處理器源碼" 和 "Spring Aware源碼" ,再來看下 Spring AOP 的源碼。 啟動 AOP 使用 @EnableAspectJAutoProxy 這個註解來啟用 AOP 的能力了。它使用 @Import 導入類 AspectJAutoProxyRegist ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...