springboot校園交友網站1.0(Springboot+Mybatis+thymeleaf+人臉識別+語音助手+百度地圖)

涉及技術

  • 前端:以HTML+CSS+JS爲基礎,以LayUI爲前端框架
  • 後端:JAVA爲語言基礎,Springboot爲後端框架,整合Mybatis替代了傳統的JDBC模式,數據庫是用的Mysql,模板引擎使用了Springboot推薦的Thymeleaf

數據庫設計

項目的數據庫設計改動過幾次,以下是最終版本
在這裏插入圖片描述
表與表的關聯性還是很強的,這裏提一點,就是當一開始的測試數據不完整或者添加了太多不必要的數據時,可能涉及數據庫的數據全部刪除的再重添加,你可以選擇使用觸發器,或者使用以下的方式:
如果你是使用的SQLyog,那麼你可以打開SQLyog點擊上方的數據庫,然後點擊備份與導出,然後點擊“以SQL轉儲文件備份數據庫”,然後你可以在彈出框中選擇“僅結構”,即可導出數據庫的SQL腳本,再刪除數據庫,再運行腳本創建數據庫(個人學習記錄,哈哈)
在這裏插入圖片描述

前端搭建

前端的搭建我主要採用的是LayUI框架(好用!),這裏就不多說,大家可以去官網學習學習,裏面的各類組件都是直接可以使用的,官網鏈接如下:
LayUI框架
除此之外,注意些常見問題
在這裏插入圖片描述
注意在你的js最外面加上如下代碼
在這裏插入圖片描述
其他相關問題 --> LayUI社區

後端實現

項目使用的是MVC設計模式(這裏盜圖了,具體在哪裏看到的,忘記了,對不住了,兄弟),用戶通過點擊,發送請求,再通過控制層實現對持久層的調用,再交還數據給控制層,通過Thymeleaf模板嵌套至前端中,進行實時渲染,同時用戶得到響應
在這裏插入圖片描述
通過maven創建JavaWeb項目,解決導入依賴的jar造成的不必要的衝突,在框架上,我們使用了SpringBoot,簡化了繁瑣的配置,我們整合了MyBatis,通過xml配置對數據庫的數據進行映射,從而實現對數據庫的操控,使用Druid數據源,可以有效監控併合理分配對數據庫的連接

項目重點實現

搜索欄(模糊查詢)

模糊查詢

首頁發佈請求遍歷

首頁遍歷

分類跳轉

分類跳轉
雖然都是概要圖,但是我在最後配了項目百度雲,你可以對比代碼閱讀,理解更加深刻

項目難點

圖片是使用base64的格式存入數據庫中(每個任務可以配多張圖片)
like this:
任務配圖
每個任務除了可以配圖以外,還有其他很多屬性,比如任務時間,任務地點等(都可以在上面的數據庫設計中看到,對應task表),當我們想將任務配圖像其他屬性一樣(比如任務時間,任務地點等)在前端通過thymeleaf中的th:each遍歷出來時,才發現,任務配圖和任務不是一張表(也就是 "pictures"表和 "task"表是分開的,只是通過task_id這個外鍵關聯),所以在控制層中寫了一個模型工具類(ModelUtil)

package com.kuang.utils;

import lombok.Data;

import java.util.List;

/**
 * @author HP
 */
@Data
public class ModelUtil<T> {
    /**模型對象*/
    private T obj;
    /**模型對象中圖片base64數據集合 指上傳多張圖片*/
    private List<String> base64;
}

然後在控制層中的代碼如下:

   /**
     * @return 首頁
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public String toMainPage(Model model){
        //導航欄  大小分類
        int parent_sort_id = 0;
        Collection<Sorts> sorts = indexService.getAll(parent_sort_id);
        model.addAttribute("sorts",sorts);
        Collection<Sorts> smallsorts = indexService.getAllSmallSorts(parent_sort_id);
        model.addAttribute("smallsorts",smallsorts);

        //發佈的任務
        List<ModelUtil> m = new ArrayList<>();
        List<Task> tasks = indexService.getTaskAll();
        tasks.forEach(t -> {
            ModelUtil<Task> modelUtil = new ModelUtil<>();

            List<TaskPictures> taskPictures = indexService.getAllTaskPictures(t.getTaskId());
            List<String> bases = new ArrayList<>();
            taskPictures.forEach(p -> bases.add(new String(p.getTaskPicture(), StandardCharsets.UTF_8)));
            modelUtil.setObj(t);
            modelUtil.setBase64(bases);
            m.add(modelUtil);
        });
        model.addAttribute("tasks", m);

        return "fore/index";
    }

其次是在前端中的thymeleaf:
遍歷首頁任務
遍歷效果如圖:
首頁遍歷

接口調用(人臉識別+語音識別+百度地圖API)

人臉識別

這一方面我在博客裏多次提到過了,具體實現大家可以去看看我的java學生管理系統(百度人臉識別 + Swing + mysql + 郵件發送 )
裏面涉及到了百度AI從註冊到對單個參數的提取,可以幫助你實現人臉識別,在這次項目中唯一不同的是,我是通過H5打開的攝像頭,而鏈接中因爲用的是Swing,所以我當時採用的是opencv打開攝像頭來實時監測人臉(它自帶算法可以監測到人臉),下面附上H5打開攝像頭的代碼和一張比較重要的關係圖

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>人臉識別</title>
</head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<style>

    #video {
        position: absolute;
        right: 0;
        top: 0;
        margin: -100px -240px auto;
    }

    #img {
        position: absolute;
        left: 0;
        top: 0;
    }

    .auto {
        position: absolute;
        left: 50%;
        top: 50%;
        height: 320px;
        margin-top: -160px;
    }

    button {
        cursor: pointer;
        margin: 0 auto;
        border: 1px solid #f0f0f0;
        background: #5CACEE;
        color: #FFF;
        width: 100px;
        height: 36px;
        line-height: 36px;
        border-radius: 8px;
        text-align: center;
        /*禁止選擇*/
        -webkit-touch-callout: none;
        /* iOS Safari */
        -webkit-user-select: none;
        /* Chrome/Safari/Opera */
        -khtml-user-select: none;
        /* Konqueror */
        -moz-user-select: none;
        /* Firefox */
        -ms-user-select: none;
        /* Internet Explorer/Edge */
        user-select: none;
        /* Non-prefixed version, currently not supported by any browser */
    }
</style>

<body background="/static/img/face_bg.png">
    <div class="auto">
        <video id="video" width="480" height="320" autoplay></video>
        <canvas id="canvas" width="480" height="320" style="display: none;"></canvas>
        <div>
            <button id="capture" onclick="alert('請將正臉置於攝像頭前');" style="display: none;"></button>
        </div>

    </div>


    <script>
        var file, stream;
        //訪問用戶媒體設備的兼容方法
        function getUserMedia(constraints, success, error) {
            if (navigator.mediaDevices.getUserMedia) {
                //最新的標準API
                navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
            } else if (navigator.webkitGetUserMedia) {
                //webkit核心瀏覽器
                navigator.webkitGetUserMedia(constraints, success, error)
            } else if (navigator.mozGetUserMedia) {
                //firfox瀏覽器
                navigator.mozGetUserMedia(constraints, success, error);
            } else if (navigator.getUserMedia) {
                //舊版API
                navigator.getUserMedia(constraints, success, error);
            }
        }

        let video = document.getElementById('video');
        let canvas = document.getElementById('canvas');
        let context = canvas.getContext('2d');

        function success(stream) {
            //兼容webkit核心瀏覽器
            let CompatibleURL = window.URL || window.webkitURL;
            //將視頻流設置爲video元素的源
            console.log(stream);
            stream = stream;
            //video.src = CompatibleURL.createObjectURL(stream);
            video.srcObject = stream;
            video.play();
        }

        function error(error) {
            console.log(`訪問用戶媒體設備失敗${error.name}, ${error.message}`);
        }

        if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
            //調用用戶媒體設備, 訪問攝像頭
            getUserMedia({ video: { width: 480, height: 320 } }, success, error);
        } else {
            alert('不支持訪問用戶媒體');
        }

        // 獲取base64圖片鏈接
        document.getElementById('capture').addEventListener('click', function () {
            context.drawImage(video, 0, 0, 480, 320);
            // 獲取圖片base64鏈接
            var image_js = canvas.toDataURL('image/png');
            console.log(image_js);

            //ajax傳輸圖片至後端
            $.ajax({
                async: false,
                type: "post",
                url: "/login/receiveData",
                data: { 'base64': JSON.stringify(image_js) },
                dataType: "json",
                mimeType: "multipart/form-data",
                success: function (data) {
                    alert(data.msg);
                    location.reload();

                    if (data.success) {
                        location.href = "/index";
                        $(".msg").stop(true, true).animate({
                            opacity: 1
                        }, 550, function () {
                            $(".msg").animate({
                                opacity: 0
                            }, 1500, function () {
                                location.href = "/index";
                            });
                        });
                    } else {
                        location.href = "/user/toLogin";
                    }
                },

                error: function (data) {
                }
            })


        });

        // 兩秒後模擬點擊
        setTimeout(function () {
            // IE
            if (document.all) {
                document.getElementById("capture").click();
            }
            // 其它瀏覽器
            else {
                var e = document.createEvent("MouseEvents");
                e.initEvent("click", true, true);
                document.getElementById("capture").dispatchEvent(e);
            }
        }, 2000);



    </script>
</body>

</html>

人臉識別關係圖
展示效果:這是人臉註冊的,和人臉登錄頁面基本一樣(註冊成功後跳轉登錄頁,人臉登錄後跳首頁)
人臉識別展示圖

語音識別

其實語音播報這塊,我之前也發過博客,主要是利用語音播報(文字轉語音)和實時錄音並上傳百度AI(語音轉文字),就這兩項即可實現簡單的人機對話,大家可以移步至:
java+百度語音識別(語音助手)
而這次項目只是在首頁加了一個小按鈕,供用戶點擊,再將點擊事件通過ajax傳到後端的控制層,控制層再和持久層交互,這樣實現語音操作數據庫,當然你也可以加個工具類,通過語音播報的形式,實現人機對話(此時就有小夥伴要問了,你這不智能啊!還要手點,辣雞!這個嘛,後面還在學習語音喚醒,敬請期待)
語音助手
以下是上圖頁面中關於語音助手的js(“Tiko”是上圖黃色機器人按鈕button的id,回調函數中主要是寫的跳轉到的對應分類頁面,也就是我上面說的調用持久層的給予用戶的響應)
語音助手js
總覽關係圖:(上傳百度AI平臺這塊和人臉識別步驟基本一致,你可以多看看人臉識別是如何實現的)
語音識別
控制層的代碼涉及語音的比較廣,我後面直接給項目代碼,就不單獨寫出來了

百度地圖API

這塊調用我也只是小有涉及,不多但確實對我的項目有幫助,提升了用戶體驗
百度地圖API
這塊確實不難,我就不細說了,具體參看它的官網 --> 百度地圖開放平臺官網示例
這些示例都很好用,基本拿來即用,只是有一點很不好就是在定位方面,百度地圖沒法讓我們準確定位到自己的位置,只能定位到城市級別的水平,我參看了其他幾個地圖開發平臺好像都是這樣

項目後續跟進(盡全力跟進,但不一定成,哈哈)

  1. 會加入語音喚醒,這樣就不用點擊按鈕
  2. 加入消息通知(應該是通過消息隊列)
  3. 設置會員等級,加入支付功能(支付即可成爲會員,你懂的)
  4. 美化UI

項目百度雲鏈接

分享給小夥伴們,希望能幫到你,共同努力!一起進步!(安裝方式和相關配置都在鏈接中)
鏈接:https://pan.baidu.com/s/1sCaZIzTnGDJwgCrZeVog3Q
提取碼:wbpe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章