第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程
首頁 慕課教程 Java 入門教程 Java 入門教程 業(yè)務(wù)實現(xiàn) 1

實戰(zhàn) - 業(yè)務(wù)實現(xiàn) 1

上一小節(jié)我們完成了數(shù)據(jù)庫的設(shè)計和創(chuàng)建,也向數(shù)據(jù)表中插入了一些初始數(shù)據(jù),本小節(jié)我們將開始具體業(yè)務(wù)代碼的實現(xiàn),如果大家還沒有完成上一小節(jié)的任務(wù),請務(wù)必先完成再來學(xué)習本節(jié)內(nèi)容。

1. 準備工作

在開始正式編碼之前,我們要做一些準備工作,主要是環(huán)境的搭建和工具類的引入。

1.1 創(chuàng)建 Maven 工程

打開 idea,點擊Create new Project按鈕:

在左側(cè)欄選擇Maven,Project SDK選擇14,勾選Create from archetype復(fù)選框,再選擇maven-archetype-quickstart,表示創(chuàng)建一個簡單 Java 應(yīng)用,點擊next按鈕:

輸入項目名稱goods,將項目路徑設(shè)置為本地桌面,GroupId可根據(jù)實際情況自定義,此處我設(shè)置為com.colorful,其余輸入框無需修改,采用默認即可,設(shè)置完成后,點擊next按鈕:

這一步來到Maven配置,idea自帶了Maven,我們使用默認的即可,直接點擊Finish按鈕完成項目創(chuàng)建:

此時,Maven會進行一些初始化配置,右下角對話框選擇Enable Auto-import按鈕,表示允許自動導(dǎo)入依賴:

稍等片刻,待看到左側(cè)項目的目錄結(jié)構(gòu)已經(jīng)生成好了,及表示已完成項目的初始化工作:

1.2 引入 MySQL 驅(qū)動

接下來引入mysql-connector-java驅(qū)動,由于我本地安裝的MySQL版本為8.0.21,因此mysql-connector-java的版本號也選擇8.0.21,大家根據(jù)自己實際情況選擇對應(yīng)版本。

打開pom.xml文件,在<dependencies></dependencies>節(jié)點內(nèi)插入如下xml

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
</dependency>

由于我們已經(jīng)配置了允許自動導(dǎo)入依賴,稍等片刻,mysql-connector-java 8.0.21就會被成功導(dǎo)入??稍?code>idea右側(cè)點擊Maven按鈕查看項目的依賴關(guān)系:

1.3 引入 JDBC 工具類

JDBC 相關(guān)操作是本項目的最常用的操作,我封裝了一個 JDBC 的工具類,主要通過 Java 的 JDBC API 去訪問數(shù)據(jù)庫,提供了加載配置、注冊驅(qū)動、獲得資源以及釋放資源等接口。

大家可以到我的 Github 倉庫下載這個 JDBCUtil類;也可以直接復(fù)制下面的代碼:

package com.colorful.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author colorful@TaleLin
 */
public class JDBCUtil {

    private static final String driverClass;
    private static final String url;
    private static final String username;
    private static final String password;

    static {
        // 加載屬性文件并解析
        Properties props = new Properties();
        // 使用類的加載器的方式進行獲取配置
        InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            assert inputStream != null;
            props.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        driverClass = props.getProperty("driverClass");
        url = props.getProperty("url");
        username = props.getProperty("username");
        password = props.getProperty("password");
    }

    /**
     * 注冊驅(qū)動
     */
    public static void loadDriver() throws ClassNotFoundException{
        Class.forName(driverClass);
    }

    /**
     * 獲得連接
     */
    public static Connection getConnection() throws Exception{
        loadDriver();
        return DriverManager.getConnection(url, username, password);
    }

    /**
     * 資源釋放
     */
    public static void release(PreparedStatement statement, Connection connection){
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            statement = null;
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            connection = null;
        }
    }

    /**
     * 釋放資源 重載方法
     */
    public static void release(ResultSet rs, PreparedStatement stmt, Connection conn){
        if(rs!= null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }

}

我本地將這個類放在了 com.colorful.util包下,大家可根據(jù)自身情況隨意放置。另外,由于該類在靜態(tài)代碼塊中加載了配置文件jdbc.properties,需要在resource下面新建一個 jdbc.properties文件,并寫入一下內(nèi)容:

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///imooc_goods_cms?serverTimezone=Asia/Shanghai&characterEncoding=UTF8
username=root
password=123456

我將數(shù)據(jù)放到了本地系統(tǒng)中,并且啟動端口是默認 3306,大家根據(jù)自己的MySQL實際配置自行修改。

1.4 測試代碼

為了測試我們的數(shù)據(jù)庫配置以及 JDBCUtil 類是否成功引入,現(xiàn)在到 test 目錄下,新建一個 JDBCTest 類:

package com.colorful;

import com.colorful.util.JDBCUtil;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;

public class JDBCTest {

    @Test
    public void testJDBC() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            // 獲得鏈接
            connection = JDBCUtil.getConnection();
            // 編寫 SQL 語句
            String sql = "SELECT * FROM `imooc_user` where `id` = ?";
            // 預(yù)編譯 SQL
            preparedStatement = connection.prepareStatement(sql);
            // 設(shè)置參數(shù)
            preparedStatement.setInt(1, 1);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                int id = resultSet.getInt("id");
                String nickname = resultSet.getString("nickname");
                Timestamp createTime = resultSet.getTimestamp("create_time");
                System.out.println("id=" + id);
                System.out.println("nickname=" + nickname);
                System.out.println("createTime=" + createTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 釋放資源
            JDBCUtil.release(resultSet, preparedStatement, connection);
        }
    }

}

如果配置成功,運行單元測試,將得到如下運行結(jié)果:

id=1
nickname=小慕
createTime=2020-07-20 16:53:19.0

下面為運行截圖:

2. 系統(tǒng)架構(gòu)

本商品管理系統(tǒng)的包結(jié)構(gòu)如下:

src
├── main       
│   ├── java    # 源碼目錄
│   │   └── com
│   │       └── colorful
│   │           ├── App.java    # 入口文件
│   │           ├── dao         # 數(shù)據(jù)訪問對象(Data Access Object,提供數(shù)據(jù)庫操作的一些方法)
│   │           ├── model       # 實體類(類字段和數(shù)據(jù)表字段一一對應(yīng))
│   │           ├── service     # 服務(wù)層(提供業(yè)務(wù)邏輯層服務(wù))
│   │           └── util        # 一些幫助類
│   └── resources
│       ├── imooc_goods_cms.sql # 建表的 SQL 文件
│       └── jdbc.properties     # jdbc 配置文件
└── test       # 單元測試目錄
    └── java
        └── com
            └── colorful
                ├── AppTest.java
                └── JDBCTest.java

大家可以提前熟悉一下本項目的項目結(jié)構(gòu),下面我們會一一講解。

3. 實體類

實體類的作用是存儲數(shù)據(jù)并提供對這些數(shù)據(jù)的訪問。在我們這個項目中,實體類統(tǒng)一被放到了model包下,通常情況下,實體類中的屬性與我們的數(shù)據(jù)表字段一一對應(yīng)。當我們編寫這些實體類的時候,建議對照著數(shù)據(jù)表的字段以防疏漏。

3.1 BaseModel

在我們數(shù)據(jù)表中,有幾個公共的字段,可以提取出一個實體類的父類 BaseModel ,并提供 gettersetter,源碼如下:

package com.colorful.model;

import java.sql.Timestamp;

public class BaseModel {

    private Integer id;

    private Timestamp createTime;

    private Timestamp updateTime;

    private Timestamp deleteTime;

    public Integer getId() {
        return id;
    }

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

    public Timestamp getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Timestamp createTime) {
        this.createTime = createTime;
    }

    public Timestamp getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Timestamp updateTime) {
        this.updateTime = updateTime;
    }

    public Timestamp getDeleteTime() {
        return deleteTime;
    }

    public void setDeleteTime(Timestamp deleteTime) {
        this.deleteTime = deleteTime;
    }

}

值得注意的是,Timestampjava.sql下的類。

3.2 實體類編寫

接下來,再在model包下新建 3 個類:User、GoodsCategory,并提供gettersetter 。如下是每個類的代碼:

package com.colorful.model;

public class User extends BaseModel {

    private String userName;

    private String nickName;

    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}
package com.colorful.model;

public class Goods extends BaseModel {

    private String name;

    private String description;

    private Integer categoryId;

    private Double price;

    private Integer stock;

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }

    public Double getPrice() {
        return price;
    }

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

    public Integer getStock() {
        return stock;
    }

    public void setStock(Integer stock) {
        this.stock = stock;
    }

}
package com.colorful.model;

public class Category extends BaseModel {

    private String name;

    private String description;

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

}

4. 實現(xiàn)用戶鑒權(quán)

4.1 登錄方式

想要使用系統(tǒng)進行商品管理,第一步要做的就是登錄。

我們的系統(tǒng)使用用戶名和密碼進行登錄校驗,上一小節(jié)我們已經(jīng)建立了imooc_user表,并向表中插入了一個用戶 admin,其密碼為 123456 。顯然,通過如下SQL就可以查詢到該用戶:

SELET * FROM `imooc_user` WHERE `username` = 'admin' AND password = '123456';

如果查詢到這個用戶,就表示用戶名密碼通過校驗,用戶可執(zhí)行后續(xù)操作,如果沒有查到,就要提示用戶重新輸入賬號和密碼。

4.2 數(shù)據(jù)訪問對象

我們先不管用戶是如何輸入賬號密碼的,接下來要編寫的業(yè)務(wù)代碼就是根據(jù)用戶名和密碼去查詢用戶。那么涉及到數(shù)據(jù)庫查詢的代碼應(yīng)該放到哪里呢?參考上面的系統(tǒng)架構(gòu)圖,DAO是數(shù)據(jù)訪問對象,我們可以在dao包下面新建一個UserDAO,并寫入如下代碼:

package com.colorful.dao;

import com.colorful.model.User;
import com.colorful.util.JDBCUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class UserDAO {

    public User selectByUserNameAndPassword(String username, String password) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        User user = new User();
        try {
            // 獲得鏈接
            connection = JDBCUtil.getConnection();
            // 編寫 SQL 語句
            String sql = "SELECT * FROM `imooc_user` where `username` = ? AND `password` = ? AND `delete_time` is null ";
            // 預(yù)編譯 SQL
            preparedStatement = connection.prepareStatement(sql);
            // 設(shè)置參數(shù)
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, password);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                user.setId(resultSet.getInt("id"));
                String nickname = resultSet.getString("nickname");
                if (nickname.equals("")) {
                    nickname = "匿名";
                }
                user.setNickName(nickname);
                user.setUserName(resultSet.getString("username"));
            } else {
                user = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 釋放資源
            JDBCUtil.release(resultSet, preparedStatement, connection);
        }
        return user;
    }

}

UserDAO 類下面有一個 selectByUserNameAndPassword()方法, 接收兩個參數(shù) usernamepassword,返回值類型是實體類 User,如果沒有查詢到,返回的是一個 null。

完成了 UserDAO 的編寫,我們需要到服務(wù)層 service包下,新建一個 UserService ,并寫入如下代碼:

package com.colorful.service;

import com.colorful.dao.UserDAO;
import com.colorful.model.User;

public class UserService {

    private final UserDAO userDAO = new UserDAO();

  	// 登陸
    public User login(String username, String password) {
        return userDAO.selectByUserNameAndPassword(username, password);
    }
    
}

到這里大家可能有些疑問,這個類下面的login()方法,直接調(diào)用了我們剛剛編寫的 DAO 下面的 selectByUserNameAndPassword() 方法,為什么還要嵌套這么一層么?這不是多此一舉么?

要討論 service 層的封裝是不是過度設(shè)計,就要充分理解設(shè)計服務(wù)層的概念和意義,服務(wù)層主要是對業(yè)務(wù)邏輯的封裝,對于更為復(fù)雜的項目,用戶登錄會有更多的方式,因此在服務(wù)層,會封裝更多的業(yè)務(wù)邏輯。如果沒有服務(wù)層,這些復(fù)雜的邏輯不得不都寫在數(shù)據(jù)訪問層,顯然這是不合理的。我們現(xiàn)在這個項目沒有使用任何框架,等到后面大家學(xué)習了Spring這種框架,一定會對這樣的分層的好處有所體會。

4.3 使用 Scanner 類與用戶交互

完成了上面一系列的封裝,就剩下我們和用戶的交互了,本項目中,我們使用 Scanner 類來接收用戶的輸入,并使用print()方法向屏幕輸出。

打開 App.java 入口文件,創(chuàng)建UserService實例,編寫一個主流程方法 run(),并在入口方法 main()中調(diào)用該方法:

package com.colorful;

import com.colorful.model.User;
import com.colorful.service.UserService;

import java.util.Scanner;

/**
 * @author colorful@TaleLin
 * Imooc Goods
 */
public class App {

    private static final UserService userService = new UserService();
    
    /**
     * 主流程方法
     */
    public static void run() {
        User user = null;
        System.out.println("歡迎使用商品管理系統(tǒng),請輸入用戶名和密碼:");
        do {
            Scanner scanner = new Scanner(System.in);
            // 登錄
            System.out.println("用戶名:");
            String username = scanner.nextLine();
            System.out.println("密碼:");
            String password = scanner.nextLine();
            user = userService.login(username, password);
            if (user == null) {
                System.out.println("用戶名密碼校驗失敗,請重新輸入!");
            }
        } while (user == null);
        System.out.println("歡迎您!" + user.getNickName());
        // TODO 登錄成功,編寫后續(xù)邏輯
    }

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

run()方法中有一個 do ... while循環(huán),循環(huán)的條件是 user 對象為 null。

我們知道,do... while循環(huán)會首先執(zhí)行 do 中的循環(huán)體,循環(huán)體中創(chuàng)建了一個 Scanner 類的實例,獲取到用戶的輸入后,我們會調(diào)用用戶服務(wù)層的login()方法,該方法返回實體類對象User,如果其為 null表示用戶名密碼校驗失敗,需要用戶重新輸入, user == null,滿足循環(huán)的條件,會一直執(zhí)行循環(huán)體中的代碼。直到循環(huán)體中的 user不為 null (也就是用戶登錄校驗成功后)才終止循環(huán)。

下面運行App.javamain()方法,如下為登錄失敗的截圖:

如果用戶名密碼檢驗錯誤,就要反復(fù)輸入用戶名密碼重新登錄。

如下為登錄成功的截圖:

5. 小結(jié)

在本小節(jié),我們成功搭建了項目工程,通過實現(xiàn)一個用戶鑒權(quán)模塊,介紹了整體的系統(tǒng)架構(gòu)。我們在編寫實體類的同時,復(fù)習了面向?qū)ο蟮睦^承性;在數(shù)據(jù)訪問層,也復(fù)習了 JDBC API 的使用;在編寫程序入口文件的同時,也復(fù)習了 Scanner 類的使用和循環(huán)的使用。

關(guān)于系統(tǒng)鑒權(quán),這里還有一個待優(yōu)化的地方,大家下去之后可以思考一下,在下一小節(jié)的開頭,我將帶領(lǐng)大家一起來優(yōu)化。下一小節(jié)也將主要講解最后剩余的商品模塊和分類模塊的實現(xiàn),也會復(fù)習到很多其他方面的基礎(chǔ)知識。