Java學習-第一部分-第三階段-項目實戰:滿漢樓項目

来源:https://www.cnblogs.com/wenjie2000/archive/2022/09/25/16727122.html
-Advertisement-
Play Games

滿漢樓項目 筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 註意:筆記內容僅為實現該項目的基本後端功能,並不會實現可視化界面,效果都在控制台展示。 要完成的滿漢樓項目說明 滿漢樓項目功能多,界面複雜,涉及到複雜的awt和swing技 ...


滿漢樓項目

筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

註意:筆記內容僅為實現該項目的基本後端功能,並不會實現可視化界面,效果都在控制台展示。

要完成的滿漢樓項目說明

滿漢樓項目功能多,界面複雜,涉及到複雜的awt和swing技術和事件編程,做如下調整:

  1. 去掉界面和事件處理(工作中使用很少),使用控制台界面
  2. 完成滿漢樓項目的登錄、訂座、點餐和結賬、查看賬單等功能
  3. 提示:在實際工作中,獨立完成項目新功能非常重要,這是鍛煉編程能力和思想的重要途徑

界面設計

用戶登錄

image

顯示餐桌狀態

image

預定

image

顯示菜品

image

點餐

image

查看賬單

image

結賬

image

項目設計

image

準備工作

準備工具類Utility,提高開發效率,並搭建項目的整體結構

在實際開發中,公司都會提供相應的工具類和開發庫,可以提高開發效率

  1. 瞭解Utility類的使用

  2. 測試Utility類

基本結構

image

在MySQL中創建表

#用戶表
create table employee (
	id int primary key auto_increment, #自增
	empId varchar(50) not null default '',#員工號
	pwd char(32) not null default '',#密碼md5
	name varchar(50) not null default '',#姓名
	job varchar(50) not null default '' #崗位
)charset=utf8; 

insert into employee values(null, '6668612', md5('123456'), '張三豐', '經理');
insert into employee values(null, '6668622', md5('123456'),'小龍女', '服務員');
insert into employee values(null, '6668633', md5('123456'), '張無忌', '收銀員');
insert into employee values(null, '666', md5('123456'), '老韓', '經理');

#餐桌表
create table diningTable (
	id int primary key auto_increment, #自增, 表示餐桌編號
	state varchar(20) not null default '',#餐桌的狀態
	orderName varchar(50) not null default '',#預訂人的名字
	orderTel varchar(20) not null default ''
)charset=utf8; 

insert into diningTable values(null, '空','','');

#菜譜
create table menu (
	id int primary key auto_increment, #自增主鍵,作為菜譜編號(唯一)
	name varchar(50) not null default '',#菜品名稱
	type varchar(50) not null default '', #菜品種類
	price double not null default 0#價格
)charset=utf8; 

insert into menu values(null, '八寶飯', '主食類', 10);
insert into menu values(null, '叉燒包', '主食類', 20);
insert into menu values(null, '宮保雞丁', '熱菜類', 30);
insert into menu values(null, '山藥撥魚', '冷盤類', 14);
insert into menu values(null, '銀絲捲', '甜食類', 9);
insert into menu values(null, '水煮魚', '熱菜類', 26);
insert into menu values(null, '甲魚湯', '湯類', 100);
insert into menu values(null, '雞蛋湯', '湯類', 16);

#賬單流水, 考慮可以分開結賬, 並考慮將來分別統計各個不同菜品的銷售情況
create table bill (
	id int primary key auto_increment, #自增主鍵
	billId varchar(50) not null default '',#賬單號可以按照自己規則生成 UUID
	menuId int not null default 0,#菜品的編號, 也可以使用外鍵
	nums SMALLINT not null default 0,#份數
	money double not null default 0, #金額
	diningTableId int not null default 0, #餐桌
	billDate datetime not null ,#訂單日期
	state varchar(50) not null default '' # 狀態 '未結賬' , '已經結賬', '掛單'
)charset=utf8;

druid配置文件(需要根據自己情況進行配置)

#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true
username=root
password=123456
#initial connection Size
initialSize=10
#min idle connecton size
minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000

BasicDAO(如果看過我上一節的筆記,就可以不需要再寫一遍,直接拿來用)

package com.zwj.mhl.dao;

import com.zwj.mhl.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;


/**
 * 開發BasicDAO , 是其他DAO的父類
 */
public class BasicDAO<T> { //泛型指定具體類型

    private QueryRunner qr =  new QueryRunner();

    //開發通用的dml方法, 針對任意的表
    public int update(String sql, Object... parameters) {

        Connection connection = null;

        try {
            connection = JDBCUtilsByDruid.getConnection();
            int update = qr.update(connection, sql, parameters);
            return  update;
        } catch (SQLException e) {
           throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    //返回多個對象(即查詢的結果是多行), 針對任意表

    /**
     *
     * @param sql sql 語句,可以有 ?
     * @param clazz 傳入一個類的Class對象 比如 Actor.class
     * @param parameters 傳入 ? 的具體的值,可以是多個
     * @return 根據Actor.class 返回對應的 ArrayList 集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    //查詢單行結果 的通用方法
    public T querySingle(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    //查詢單行單列的方法,即返回單值的方法

    public Object queryScalar(String sql, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new ScalarHandler(), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }
}

JDBCUtilsByDruid(基於druid資料庫連接池的工具類)

package com.zwj.mhl.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 基於druid資料庫連接池的工具類
 */
public class JDBCUtilsByDruid {

    private static DataSource ds;

    //在靜態代碼塊完成 ds初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //編寫getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //關閉連接, 老師再次強調: 在資料庫連接池技術中,close 不是真的斷掉連接
    //而是把使用的Connection對象放回連接池
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {

        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

Utility(輔助輸入數據的工具類)

package com.zwj.mhl.utils;


/**
   工具類的作用:
   處理各種情況的用戶輸入,並且能夠按照程式員的需求,得到用戶的控制台輸入。
*/

import java.util.*;

public class Utility {
   //靜態屬性。。。
    private static Scanner scanner = new Scanner(System.in);

    
    /**
     * 功能:讀取鍵盤輸入的一個菜單選項,值:1——5的範圍
     * @return 1——5
     */
   public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1, false);//包含一個字元的字元串
            c = str.charAt(0);//將字元串轉換成字元char類型
            if (c != '1' && c != '2' && 
                c != '3' && c != '4' && c != '5') {
                System.out.print("選擇錯誤,請重新輸入:");
            } else break;
        }
        return c;
    }

   /**
    * 功能:讀取鍵盤輸入的一個字元
    * @return 一個字元
    */
    public static char readChar() {
        String str = readKeyBoard(1, false);//就是一個字元
        return str.charAt(0);
    }
    /**
     * 功能:讀取鍵盤輸入的一個字元,如果直接按回車,則返回指定的預設值;否則返回輸入的那個字元
     * @param defaultValue 指定的預設值
     * @return 預設值或輸入的字元
     */
    
    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);//要麼是空字元串,要麼是一個字元
        return (str.length() == 0) ? defaultValue : str.charAt(0);
    }
   
    /**
     * 功能:讀取鍵盤輸入的整型,長度小於2位
     * @return 整數
     */
    public static int readInt() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(2, false);//一個整數,長度<=2位
            try {
                n = Integer.parseInt(str);//將字元串轉換成整數
                break;
            } catch (NumberFormatException e) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
        return n;
    }
    /**
     * 功能:讀取鍵盤輸入的 整數或預設值,如果直接回車,則返回預設值,否則返回輸入的整數
     * @param defaultValue 指定的預設值
     * @return 整數或預設值
     */
    public static int readInt(int defaultValue) {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, true);
            if (str.equals("")) {
                return defaultValue;
            }
         
         //異常處理...
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
        return n;
    }

    /**
     * 功能:讀取鍵盤輸入的指定長度的字元串
     * @param limit 限制的長度
     * @return 指定長度的字元串
     */

    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }

    /**
     * 功能:讀取鍵盤輸入的指定長度的字元串或預設值,如果直接回車,返回預設值,否則返回字元串
     * @param limit 限制的長度
     * @param defaultValue 指定的預設值
     * @return 指定長度的字元串
     */
   
    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("")? defaultValue : str;
    }


   /**
    * 功能:讀取鍵盤輸入的確認選項,Y或N
    * 將小的功能,封裝到一個方法中.
    * @return Y或N
    */
    public static char readConfirmSelection() {
        System.out.println("請輸入你的選擇(Y/N)");
        char c;
        for (; ; ) {//無限迴圈
           //在這裡,將接受到字元,轉成了大寫字母
           //y => Y n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("選擇錯誤,請重新輸入:");
            }
        }
        return c;
    }

    /**
     * 功能: 讀取一個字元串
     * @param limit 讀取的長度
     * @param blankReturn 如果為true ,表示 可以讀空字元串。 
     *                   如果為false表示 不能讀空字元串。
     *           
    * 如果輸入為空,或者輸入大於limit的長度,就會提示重新輸入。
     * @return
     */
    private static String readKeyBoard(int limit, boolean blankReturn) {
        
      //定義了字元串
      String line = "";

      //scanner.hasNextLine() 判斷有沒有下一行
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();//讀取這一行
           
         //如果line.length=0, 即用戶沒有輸入任何內容,直接回車
         if (line.length() == 0) {
                if (blankReturn) return line;//如果blankReturn=true,可以返回空串
                else continue; //如果blankReturn=false,不接受空串,必須輸入內容
            }

         //如果用戶輸入的內容大於了 limit,就提示重寫輸入  
         //如果用戶如的內容 >0 <= limit ,我就接受
            if (line.length() < 1 || line.length() > limit) {
                System.out.print("輸入長度(不能大於" + limit + ")錯誤,請重新輸入:");
                continue;
            }
            break;
        }
        return line;
    }
}

代碼實現

註意:建議看代碼之前先根據上面的信息自己寫

image

com.zwj.mhl

dao

BasicDAO

package com.zwj.mhl.dao;

import com.zwj.mhl.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;


/**
 * 開發BasicDAO , 是其他DAO的父類
 */
public class BasicDAO<T> { //泛型指定具體類型

    private QueryRunner qr =  new QueryRunner();

    //開發通用的dml方法, 針對任意的表
    public int update(String sql, Object... parameters) {

        Connection connection = null;

        try {
            connection = JDBCUtilsByDruid.getConnection();
            int update = qr.update(connection, sql, parameters);
            return  update;
        } catch (SQLException e) {
           throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }

    }

    //返回多個對象(即查詢的結果是多行), 針對任意表

    /**
     *
     * @param sql sql 語句,可以有 ?
     * @param clazz 傳入一個類的Class對象 比如 Actor.class
     * @param parameters 傳入 ? 的具體的值,可以是多個
     * @return 根據Actor.class 返回對應的 ArrayList 集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }

    }

    //查詢單行結果 的通用方法
    public T querySingle(String sql, Class<T> clazz, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    //查詢單行單列的方法,即返回單值的方法

    public Object queryScalar(String sql, Object... parameters) {

        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection, sql, new ScalarHandler(), parameters);

        } catch (SQLException e) {
            throw  new RuntimeException(e); //將編譯異常->運行異常 ,拋出
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }
}

BillDAO

package com.zwj.mhl.dao;

import com.zwj.mhl.domain.Bill;

public class BillDAO extends BasicDAO<Bill> {
}

DiningTableDAO

package com.zwj.mhl.dao;

import com.zwj.mhl.domain.DiningTable;

public class DiningTableDAO extends BasicDAO<DiningTable> {
    //如果有特別的操作,可以寫在 DiningTableDAO
}

EmployeeDAO

package com.zwj.mhl.dao;

import com.zwj.mhl.domain.Employee;

public class EmployeeDAO extends BasicDAO<Employee> {
    //這裡還可以寫特有的操作.
}

MenuDAO

package com.zwj.mhl.dao;

import com.zwj.mhl.domain.Menu;

public class MenuDAO extends BasicDAO<Menu> {
}

MultiTableDAO

package com.zwj.mhl.dao;


import com.zwj.mhl.domain.MultiTableBean;

public class MultiTableDAO extends BasicDAO<MultiTableBean> {
}

domain

Bill

package com.zwj.mhl.domain;

import java.util.Date;

/**
 * Bill 是javabean 和 bill對應
 * id int primary key auto_increment, #自增主鍵
 *     billId varchar(50) not null default '',#賬單號可以按照自己規則生成 UUID
 *     menuId int not null default 0,#菜品的編號, 也可以使用外鍵
 *     nums int not null default 0,#份數
 *     money double not null default 0, #金額
 *     diningTableId int not null default 0, #餐桌
 *     billDate datetime not null ,#訂單日期
 *     state varchar(50) not null default '' # 狀態 '未結賬' , '已經結賬', '掛單'
 */
public class Bill {
    private Integer id;
    private String billId;
    private Integer menuId;
    private Integer nums;
    private Double money;
    private Integer diningTableId;
    private Date billDate;
    private String state;

    public Bill() {
    }

    public Bill(Integer id, String billId, Integer menuId, Integer nums, Double money, Integer diningTableId, Date billDate, String state) {
        this.id = id;
        this.billId = billId;
        this.menuId = menuId;
        this.nums = nums;
        this.money = money;
        this.diningTableId = diningTableId;
        this.billDate = billDate;
        this.state = state;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBillId() {
        return billId;
    }

    public void setBillId(String billId) {
        this.billId = billId;
    }

    public Integer getMenuId() {
        return menuId;
    }

    public void setMenuId(Integer menuId) {
        this.menuId = menuId;
    }

    public Integer getNums() {
        return nums;
    }

    public void setNums(Integer nums) {
        this.nums = nums;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public Integer getDiningTableId() {
        return diningTableId;
    }

    public void setDiningTableId(Integer diningTableId) {
        this.diningTableId = diningTableId;
    }

    public Date getBillDate() {
        return billDate;
    }

    public void setBillDate(Date billDate) {
        this.billDate = billDate;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Override
    public String toString() {
        return  id +
                "\t\t" + menuId +
                "\t\t\t" + nums +
                "\t\t\t" + money +
                "\t" + diningTableId +
                "\t\t" + billDate +
                "\t\t" + state ;
    }
}

DiningTable

package com.zwj.mhl.domain;

/**
 * 這是一個javabean 和 diningTable 表對應
 *     id int primary key auto_increment, #自增, 表示餐桌編號
 *     state varchar(20) not null default '',#餐桌的狀態
 *     orderName varchar(50) not null default '',#預訂人的名字
 *     orderTel varchar(20) not null default ''
 */
public class DiningTable {
    private Integer id;
    private String state;
    private String orderName;
    private String orderTel;

    public DiningTable() {
    }

    public DiningTable(Integer id, String state, String orderName, String orderTel) {
        this.id = id;
        this.state = state;
        this.orderName = orderName;
        this.orderTel = orderTel;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    public String getOrderTel() {
        return orderTel;
    }

    public void setOrderTel(String orderTel) {
        this.orderTel = orderTel;
    }

    @Override
    public String toString() {
        return id + "\t\t\t" + state;
    }
}

Employee

package com.zwj.mhl.domain;

/**
 * 這是一個javabean 和 employee對應
 * id int primary key auto_increment, #自增
 *     empId varchar(50) not null default '',#員工號
 *     pwd char(32) not null default '',#密碼md5
 *     name varchar(50) not null default '',#姓名
 *     job varchar(50) not null default '' #崗位
 */
public class Employee {
    private Integer id;
    private String empId;
    private String pwd;
    private String name;
    private String job;

    public Employee() { //無參構造器,底層apache-dbutils反射需要
    }

    public Employee(Integer id, String empId, String pwd, String name, String job) {
        this.id = id;
        this.empId = empId;
        this.pwd = pwd;
        this.name = name;
        this.job = job;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }
}

Menu

package com.zwj.mhl.domain;

/**
 * 該類(javabean)和 menu 表對應
 * id int primary key auto_increment, #自增主鍵,作為菜譜編號(唯一)
 * name varchar(50) not null default '',#菜品名稱
 * type varchar(50) not null default '', #菜品種類
 * price double not null default 0#價格
 */
public class Menu {
    private Integer id;
    private String name;
    private String type;
    private Double price;

    public Menu() {//無參構造器
    }

    public Menu(Integer id, String name, String type, Double price) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.price = price;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return id + "\t\t\t" + name + "\t\t" + type + "\t\t" + price;
    }
}

MultiTableBean

package com.zwj.mhl.domain;

import java.util.Date;

/**
 * 這是一個javabean 可以和多張表進行對應
 */
public class MultiTableBean {
    private Integer id;
    private String billId;
    private Integer menuId;
    private Integer nums;
    private Double money;
    private Integer diningTableId;
    private Date billDate;
    private String state;
    //增加一個來自menu表的列 name
    //思考 這裡的屬性名是否一定要和表的列名保持一致.
    //答: 可以不一致,但是需要sql做相應的修改, 規範需要保持一致.
    private String name;
    //增加來自menu表的列 price
    private Double price;//預設值 null

    public MultiTableBean() {
        System.out.println("反射調用....");
    }

//    public MultiTableBean(Integer id, String billId, Integer menuId, Integer nums, Double money, Integer diningTableId, Date billDate, String state, String name, Double price) {
//        this.id = id;
//        this.billId = billId;
//        this.menuId = menuId;
//        this.nums = nums;
//        this.money = money;
//        this.diningTableId = diningTableId;
//        this.billDate = billDate;
//        this.state = state;
//        this.name = name;
//        this.price = price;
//    }

    //給price生成setter 和 getter

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }


    //給name生成setter 和 getter


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBillId() {
        return billId;
    }

    public void setBillId(String billId) {
        this.billId = billId;
    }

    public Integer getMenuId() {
        return menuId;
    }

    public void setMenuId(Integer menuId) {
        this.menuId = menuId;
    }

    public Integer getNums() {
        return nums;
    }

    public void setNums(Integer nums) {
        this.nums = nums;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public Integer getDiningTableId() {
        return diningTableId;
    }

    public void setDiningTableId(Integer diningTableId) {
        this.diningTableId = diningTableId;
    }

    public Date getBillDate() {
        return billDate;
    }

    public void setBillDate(Date billDate) {
        this.billDate = billDate;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Override
    public String toString() {
        return  id +
                "\t\t" + menuId +
                "\t\t\t" + nums +
                "\t\t\t" + money +
                "\t" + diningTableId +
                "\t\t" + billDate +
                "\t\t" + state +
                "\t\t" + name +
                "\t\t" + price;
    }
}

service

BillService

package com.zwj.mhl.service;

import com.zwj.mhl.dao.BillDAO;
import com.zwj.mhl.dao.MultiTableDAO;
import com.zwj.mhl.domain.Bill;
import com.zwj.mhl.domain.MultiTableBean;

import java.util.List;
import java.util.UUID;

/**
 * 處理和賬單相關的業務邏輯
 */
public class BillService {
    //定義BillDAO屬性
    private BillDAO billDAO = new BillDAO();
    //定義MenuService 屬性
    private MenuService menuService = new MenuService();
    //定義DiningTableService屬性
    private DiningTableService diningTableService = new DiningTableService();

    private MultiTableDAO multiTableDAO = new MultiTableDAO();

    //思考
    //編寫點餐的方法
    //1. 生成賬單
    //2. 需要更新對應餐桌的狀態
    //3. 如果成功返回true, 否則返回false
    public boolean orderMenu(int menuId, int nums, int diningTableId) {
        //生成一個賬單號,UUID
        String billID = UUID.randomUUID().toString();

        //將賬單生成到bill表, 要求直接計算賬單金額
        int update = billDAO.update("insert into bill values(null,?,?,?,?,?,now(),'未結賬')",
                billID, menuId, nums, menuService.getMenuById(menuId).getPrice() * nums, diningTableId);

        if (update <= 0) {
            return false;
        }

        //需要更新對應餐桌的狀態
        return diningTableService.updateDiningTableState(diningTableId, "就餐中");

    }

    //返回所有的賬單, 提供給View調用
    public List<Bill> list() {
        return billDAO.queryMulti("select * from bill", Bill.class);
    }

    //返回所有的賬單並帶有菜品名,價格, 提供給View調用
    public List<MultiTableBean> list2() {
        return multiTableDAO.queryMulti("SELECT bill.*, name,price " +
                "FROM bill, menu " +
                "WHERE bill.menuId = menu.id", MultiTableBean.class);
    }


    //查看某個餐桌是否有未結賬的賬單
    public boolean hasPayBillByDiningTableId(int diningTableId) {

        Bill bill =
                billDAO.querySingle("SELECT * FROM bill WHERE diningTableId=? AND state = '未結賬' LIMIT 0, 1", Bill.class, diningTableId);
        return bill != null;
    }

    //完成結賬[如果餐桌存在,並且該餐桌有未結賬的賬單]
    //如果成功,返回true, 失敗返回 false
    public boolean payBill(int diningTableId, String payMode) {

        //如果這裡使用事務的話,需要用ThreadLocal來解決 , 框架中比如mybatis 提供了事務支持
        //1. 修改bill表
        int update = billDAO.update("update bill set state=? where diningTableId=? and state='未結賬'", payMode, diningTableId);

        if(update <= 0) { //如果更新沒有成功,則表示失敗...
            return false;
        }
        //2. 修改diningTable表
        //註意:不要直接在這裡操作,而應該調用DiningTableService 方法,完成更新,體現各司其職

        if(!diningTableService.updateDiningTableToFree(diningTableId, "空")) {
            return false;
        }
        return true;

    }

}

DiningTableService

package com.zwj.mhl.service;

import com.zwj.mhl.dao.DiningTableDAO;
import com.zwj.mhl.domain.DiningTable;

import java.util.List;

public class DiningTableService { //業務層
    //定義一個DiningTableDAO對象
    private DiningTableDAO diningTableDAO = new DiningTableDAO();

    //返回所有餐桌的信息
    public List<DiningTable> list() {

        return diningTableDAO.queryMulti("select id, state from diningTable", DiningTable.class);
    }

    //根據id , 查詢對應的餐桌DiningTable 對象
    //,如果返回null , 表示id編號對應的餐桌不存在
    public DiningTable getDiningTableById(int id) {

        //老韓小技巧:把sql語句放在查詢分析器去測試一下.
        return diningTableDAO.querySingle("select * from diningTable where id = ?", DiningTable.class, id);
    }

    //如果餐桌可以預定,調用方法,對其狀態進行更新(包括預定人的名字和電話)
    public boolean orderDiningTable(int id, String orderName, String orderTel) {

        int update =
                diningTableDAO.update("update diningTable set state='已經預定', orderName=?, orderTel=? where id=?", orderName, orderTel, id);

        return  update > 0;
    }

    //需要提供一個更新 餐桌狀態的方法
    public boolean updateDiningTableState(int id, String state) {

        int update = diningTableDAO.update("update diningTable set state=? where id=?", state, id);
        return update > 0;
    }

    //提供方法,將指定的餐桌設置為空閑狀態
    public boolean updateDiningTableToFree(int id, String state) {

        int update = diningTableDAO.update("update diningTable set state=?,orderName='',orderTel='' where id=?", state, id);
        return update > 0;
    }

}

EmployeeService

package com.zwj.mhl.service;

import com.zwj.mhl.dao.EmployeeDAO;
import com.zwj.mhl.domain.Employee;

/**
 * 該類完成對employee表的各種操作(通過調用EmployeeDAO對象完成)
 */
public class EmployeeService {

    //定義一個 EmployeeDAO 屬性
    private EmployeeDAO employeeDAO = new EmployeeDAO();

    //方法,根據empId 和 pwd 返回一個Employee對象
    //如果查詢不到,就返回null
    public Employee getEmployeeByIdAndPwd(String empId, String pwd) {

        return employeeDAO.querySingle("select * from employee where empId=? and pwd=md5(?)", Employee.class, empId, pwd);

    }
}

MenuService

package com.zwj.mhl.service;

import com.zwj.mhl.dao.MenuDAO;
import com.zwj.mhl.domain.Menu;

import java.util.List;

/**
 * 完成對menu表的各種操作(通過調用MenuDAO)
 */
public class MenuService {

    //定義MenuDAO 屬性
    private MenuDAO menuDAO = new MenuDAO();

    //返回所有的菜品, 返回給界面使用
    public List<Menu> list() {
        return menuDAO.queryMulti("select * from menu", Menu.class);
    }

    //需要方法,根據id, 返回Menu對象
    public Menu getMenuById(int id) {
        return menuDAO.querySingle("select * from menu where id = ?", Menu.class, id);
    }
}

utils

JDBCUtilsByDruid

package com.zwj.mhl.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 基於druid資料庫連接池的工具類
 */
public class JDBCUtilsByDruid {

    private static DataSource ds;

    //在靜態代碼塊完成 ds初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //編寫getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //關閉連接, 老師再次強調: 在資料庫連接池技術中,close 不是真的斷掉連接
    //而是把使用的Connection對象放回連接池
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {

        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

Utility

package com.zwj.mhl.utils;


/**
   工具類的作用:
   處理各種情況的用戶輸入,並且能夠按照程式員的需求,得到用戶的控制台輸入。
*/

import java.util.*;
/**

   
*/
public class Utility {
   //靜態屬性。。。
    private static Scanner scanner = new Scanner(System.in);

    
    /**
     * 功能:讀取鍵盤輸入的一個菜單選項,值:1——5的範圍
     * @return 1——5
     */
   public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1, false);//包含一個字元的字元串
            c = str.charAt(0);//將字元串轉換成字元char類型
            if (c != '1' && c != '2' && 
                c != '3' && c != '4' && c != '5') {
                System.out.print("選擇錯誤,請重新輸入:");
            } else break;
        }
        return c;
    }

   /**
    * 功能:讀取鍵盤輸入的一個字元
    * @return 一個字元
    */
    public static char readChar() {
        String str = readKeyBoard(1, false);//就是一個字元
        return str.charAt(0);
    }
    /**
     * 功能:讀取鍵盤輸入的一個字元,如果直接按回車,則返回指定的預設值;否則返回輸入的那個字元
     * @param defaultValue 指定的預設值
     * @return 預設值或輸入的字元
     */
    
    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);//要麼是空字元串,要麼是一個字元
        return (str.length() == 0) ? defaultValue : str.charAt(0);
    }
   
    /**
     * 功能:讀取鍵盤輸入的整型,長度小於2位
     * @return 整數
     */
    public static int readInt() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(2, false);//一個整數,長度<=2位
            try {
                n = Integer.parseInt(str);//將字元串轉換成整數
                break;
            } catch (NumberFormatException e) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
        return n;
    }
    /**
     * 功能:讀取鍵盤輸入的 整數或預設值,如果直接回車,則返回預設值,否則返回輸入的整數
     * @param defaultValue 指定的預設值
     * @return 整數或預設值
     */
    public static int readInt(int defaultValue) {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, true);
            if (str.equals("")) {
                return defaultValue;
            }
         
         //異常處理...
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
        return n;
    }

    /**
     * 功能:讀取鍵盤輸入的指定長度的字元串
     * @param limit 限制的長度
     * @return 指定長度的字元串
     */

    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }

    /**
     * 功能:讀取鍵盤輸入的指定長度的字元串或預設值,如果直接回車,返回預設值,否則返回字元串
     * @param limit 限制的長度
     * @param defaultValue 指定的預設值
     * @return 指定長度的字元串
     */
   
    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("")? defaultValue : str;
    }


   /**
    * 功能:讀取鍵盤輸入的確認選項,Y或N
    * 將小的功能,封裝到一個方法中.
    * @return Y或N
    */
    public static char readConfirmSelection() {
        System.out.println("請輸入你的選擇(Y/N)");
        char c;
        for (; ; ) {//無限迴圈
           //在這裡,將接受到字元,轉成了大寫字母
           //y => Y n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("選擇錯誤,請重新輸入:");
            }
        }
        return c;
    }

    /**
     * 功能: 讀取一個字元串
     * @param limit 讀取的長度
     * @param blankReturn 如果為true ,表示 可以讀空字元串。 
     *                   如果為false表示 不能讀空字元串。
     *           
    * 如果輸入為空,或者輸入大於limit的長度,就會提示重新輸入。
     * @return
     */
    private static String readKeyBoard(int limit, boolean blankReturn) {
        
      //定義了字元串
      String line = "";

      //scanner.hasNextLine() 判斷有沒有下一行
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();//讀取這一行
           
         //如果line.length=0, 即用戶沒有輸入任何內容,直接回車
         if (line.length() == 0) {
                if (blankReturn) return line;//如果blankReturn=true,可以返回空串
                else continue; //如果blankReturn=false,不接受空串,必須輸入內容
            }

         //如果用戶輸入的內容大於了 limit,就提示重寫輸入  
         //如果用戶如的內容 >0 <= limit ,我就接受
            if (line.length() < 1 || line.length() > limit) {
                System.out.print("輸入長度(不能大於" + limit + ")錯誤,請重新輸入:");
                continue;
            }
            break;
        }

        return line;
    }
}

view

MHLView

package com.zwj.mhl.view;

import com.zwj.mhl.domain.*;
import com.zwj.mhl.service.BillService;
import com.zwj.mhl.service.DiningTableService;
import com.zwj.mhl.service.EmployeeService;
import com.zwj.mhl.service.MenuService;
import com.zwj.mhl.utils.Utility;

import java.util.List;
import java.util.UUID;

/**
 * 這是主界面
 */
public class MHLView {

    //控制是否退出菜單
    private boolean loop = true;
    private String key = ""; //接收用戶的選擇
    //定義EmployeeService 屬性
    private EmployeeService employeeService = new EmployeeService();
    //定義DiningTableService的屬性
    private DiningTableService diningTableService = new DiningTableService();
    //定義MenuService屬性
    private MenuService menuService = new MenuService();
    //定義BillService屬性
    private BillService billService = new BillService();

    public static void main(String[] args) {
        new MHLView().mainMenu();
    }

    //完成結賬
    public void payBill() {
        System.out.println("==============結賬服務============");
        System.out.print("請選擇要結賬的餐桌編號(-1退出): ");
        int diningTableId = Utility.readInt();
        if (diningTableId == -1) {
            System.out.println("=============取消結賬============");
            return;
        }
        //驗證餐桌是否存在
        DiningTable diningTable = diningTableService.getDiningTableById(diningTableId);
        if (diningTable == null) {
            System.out.println("=============結賬的餐桌不存在============");
            return;
        }
        //驗證餐桌是否有需要結賬的賬單
        if (!billService.hasPayBillByDiningTableId(diningTableId)) {
            System.out.println("=============該餐位沒有未結賬賬單============");
            return;
        }
        System.out.print("結賬方式(現金/支付寶/微信)回車表示退出: ");
        String payMode = Utility.readString(20, "");//說明如果回車,就是返回 ""
        if ("".equals(payMode)) {
            System.out.println("=============取消結賬============");
            return;
        }
        char key = Utility.readConfirmSelection();
        if (key == 'Y') { //結賬

            //調用我們寫的方法
            if (billService.payBill(diningTableId, payMode)) {
                System.out.println("=============完成結賬============");
            } else {
                System.out.println("=============結賬失敗============");
            }

        } else {
            System.out.println("=============取消結賬============");
        }
    }

    //顯示賬單信息
    public void listBill() {
//        List<Bill> bills = billService.list();
//        System.out.println("\n編號\t\t菜品號\t\t菜品量\t\t金額\t\t桌號\t\t日期\t\t\t\t\t\t\t狀態");
//        for (Bill bill : bills) {
//            System.out.println(bill);
//        }
//        System.out.println("==============顯示完畢============");

        List<MultiTableBean> multiTableBeans = billService.list2();
        System.out.println("\n編號\t\t菜品號\t\t菜品量\t\t金額\t\t桌號\t\t日期\t\t\t\t\t\t\t狀態\t\t菜品名\t\t價格");
        for (MultiTableBean bill : multiTableBeans) {
            System.out.println(bill);
        }
        System.out.println("==============顯示完畢============");
    }

    //完成點餐
    public void orderMenu() {
        System.out.println("==============點餐服務============");
        System.out.print("請輸入點餐的桌號(-1退出): ");
        int orderDiningTableId = Utility.readInt();
        if (orderDiningTableId == -1) {
            System.out.println("==============取消點餐============");
            return;
        }
        System.out.print("請輸入點餐的菜品號(-1退出): ");
        int orderMenuId = Utility.readInt();
        if (orderMenuId == -1) {
            System.out.println("==============取消點餐============");
            return;
        }
        System.out.print("請輸入點餐的菜品量(-1退出): ");
        int orderNums = Utility.readInt();
        if (orderNums == -1) {
            System.out.println("==============取消點餐============");
            return;
        }

        //驗證餐桌號是否存在.
        DiningTable diningTable = diningTableService.getDiningTableById(orderDiningTableId);
        if (diningTable == null) {
            System.out.println("==============餐桌號不存在============");
            return;
        }
        //驗證菜品編號
        Menu menu = menuService.getMenuById(orderMenuId);
        if (menu == null) {
            System.out.println("==============菜品號不存在============");
            return;
        }

        //點餐
        if (billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)) {
            System.out.println("==============點餐成功============");
        } else {
            System.out.println("==============點餐失敗============");
        }
    }

    //顯示所有菜品
    public void listMenu() {
        List<Menu> list = menuService.list();
        System.out.println("\n菜品編號\t\t菜品名\t\t類別\t\t價格");
        for (Menu menu : list) {
            System.out.println(menu);
        }
        System.out.println("==============顯示完畢============");
    }

    //完成訂座
    public void orderDiningTable() {
        System.out.println("==============預定餐桌============");
        System.out.print("請選擇要預定的餐桌編號(-1退出): ");
        int orderId = Utility.readInt();
        if (orderId == -1) {
            System.out.println("==============取消預訂餐桌============");
            return;
        }
        //該方法得到的是 Y 或者 N
        char key = Utility.readConfirmSelection();
        if (key == 'Y') {//要預定

            //根據orderId 返回 對應DiningTable對象, 如果為null, 說明該對象不存在
            DiningTable diningTable = diningTableService.getDiningTableById(orderId);
            if (diningTable == null) {//
                System.out.println("==============預訂餐桌不存在============");
                return;
            }
            //判斷該餐桌的狀態是否 "空"
            if (!("空".equals(diningTable.getState()))) {//說明當前這個餐桌不是 "空" 狀態
                System.out.println("==============該餐桌已經預定或者就餐中============");
                return;
            }

            //接收預定信息
            System.out.print("預定人的名字: ");
            String orderName = Utility.readString(50);
            System.out.print("預定人的電話: ");
            String orderTel = Utility.readString(50);

            //更新餐桌狀態
            if (diningTableService.orderDiningTable(orderId, orderName, orderTel)) {
                System.out.println("==============預訂餐桌成功============");
            } else {
                System.out.println("==============預訂餐桌失敗============");
            }

        } else {
            System.out.println("==============取消預訂餐桌============");
        }

    }

    //顯示所有餐桌狀態
    public void listDiningTable() {
        List<DiningTable> list = diningTableService.list();
        System.out.println("\n餐桌編號\t\t餐桌狀態");
        for (DiningTable diningTable : list) {
            System.out.println(diningTable);
        }
        System.out.println("==============顯示完畢============");
    }

    //顯示主菜單
    public void mainMenu() {

        while (loop) {

            System.out.println("\n===============滿漢樓================");
            System.out.println("\t\t 1 登錄滿漢樓");
            System.out.println("\t\t 2 退出滿漢樓");
            System.out.print("請輸入你的選擇: ");
            key = Utility.readString(1);
            switch (key) {
                case "1":
                    System.out.print("輸入員工號: ");
                    String empId = Utility.readString(50);
                    System.out.print("輸入密  碼: ");
                    String pwd = Utility.readString(50);
                    Employee employee = employeeService.getEmployeeByIdAndPwd(empId, pwd);
                    if (employee != null) { //說明存在該用戶
                        System.out.println("===============登錄成功[" + employee.getName() + "]================\n");
                        //顯示二級菜單, 這裡二級菜單是迴圈操作,所以做成while
                        while (loop) {
                            System.out.println("\n===============滿漢樓(二級菜單)================");
                            System.out.println("\t\t 1 顯示餐桌狀態");
                            System.out.println("\t\t 2 預定餐桌");
                            System.out.println("\t\t 3 顯示所有菜品");
                            System.out.println("\t\t 4 點餐服務");
                            System.out.println("\t\t 5 查看賬單");
                            System.out.println("\t\t 6 結賬");
                            System.out.println("\t\t 9 退出滿漢樓");
                            System.out.print("請輸入你的選擇: ");
                            key = Utility.readString(1);
                            switch (key) {
                                case "1":
                                    listDiningTable();//顯示餐桌狀態
                                    break;
                                case "2":
                                    orderDiningTable();
                                    break;
                                case "3":
                                    listMenu();
                                    break;
                                case "4":
                                    orderMenu();
                                    break;
                                case "5":
                                    listBill();//顯示所有賬單
                                    break;
                                case "6":
                                    payBill();
                                    break;
                                case "9":
                                    loop = false;
                                    break;
                                default:
                                    System.out.println("你的輸入有誤,請重新輸入");
                                    break;
                            }
                        }
                    } else {
                        System.out.println("===============登錄失敗================");
                    }
                    break;
                case "2":
                    loop = false;//
                    break;
                default:
                    System.out.println("你輸入有誤,請重新輸入.");
            }
        }
        System.out.println("你退出了滿漢樓系統~");
    }

}

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

-Advertisement-
Play Games
更多相關文章
  • 出現的原因一般是伺服器的root用戶沒有開啟訪問許可權,一般來說值允許本地的訪問。 解決方法: 一:第一種方法 1、首先打開xshell連接伺服器的終端 2、以root許可權登錄 mysql -u root -p 如果不知道伺服器的root密碼的話就去寶塔面板那裡修改 3、選擇mysql mysql> ...
  • 1.1 資料庫系統概述: 1.1.1資料庫的4個基本概念 資料庫的四個基本概念 - 數據 - 資料庫 - 資料庫管理系統 - 資料庫系統 數據:數據是資料庫中存儲的基本對象 數據是描述事物的一個符號,可以描述數字、圖形、聲音、語言等待,但都要經過數字化後存入計算器 資料庫(簡稱DB):資料庫是長期存 ...
  • 前文回顧:實現一個簡單的Database1(譯文) 譯註:cstsck在github維護了一個簡單的、類似sqlite的資料庫實現,通過這個簡單的項目,可以很好的理解資料庫是如何運行的。本文是第二篇,主要是實現資料庫的前端組件,編譯器與虛擬機部分功能 Part 2 世界上最簡單的SQL編譯器與虛擬機 ...
  • 在最新一屆國際資料庫頂級會議 ACM SIGMOD 2022 上,來自清華大學的李國良和張超兩位老師發表了一篇論文:《HTAP Database: What is New and What is Next》,並做了 《HTAP Database:A Tutorial》 的專項報告。這幾期學術分享會的 ...
  • 問題:【Chrome插件 Chrome extension 】報錯 Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. 在看一個別人插件的時候發現一個如上所述的報錯,雖然 ...
  • 以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接 微信公眾號「englyf」https://www.cnblogs.com/englyf/ 對於閉包的理解,其實可以歸納為,在創建函數時,同時創建了一個集合,這個集合是用來保存函數內的各個變數(無論是內部定義的,還是外部定義的),當調用函數時,變數 ...
  • 前言 請講下 JavaScript 中的數據類型? 前端面試中,估計大家都被這麼問過。 答:Javascript 中的數據類型包括原始類型和引用類型。其中原始類型包括 null、undefined、boolean、string、symbol、bigInt、number。引用類型指的是 Object。 ...
  • 1、Date => String 代碼 /** * 函數描述:時間格式化工具 * @param format {String} 格式(y-年,M-月,d-日,H-時[24],h-時[12],m-分,s-秒,S-毫秒(3位數),q-季度,ap,午前am/午後pm) * @returns {String ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...