SpringBoot 仿抖音短视频小程序开发(三)

栏目: jQuery · 发布时间: 6年前

内容简介:SpringBoot 仿抖音短视频小程序开发(一):项目的简介(SpringBoot 仿抖音短视频小程序开发(二):项目功能分析与具体实现(源代码: SpringBoot 仿抖音短视频小程序开发 全栈式实战项目(

SpringBoot 仿抖音短视频小程序开发(一):项目的简介( https://segmentfault.com/a/11...

SpringBoot 仿抖音短视频小程序开发(二):项目功能分析与具体实现( https://segmentfault.com/a/11...

源代码: SpringBoot 仿抖音短视频小程序开发 全栈式实战项目( https://gitee.com/scau_zns/sh...

短视频后台管理系统:( https://gitee.com/scau_zns/sh...

小程序的后台管理系统

SpringBoot 仿抖音短视频小程序开发(三)

涉及的技术栈:Bootstrap + jQuery + jGrid + SSM框架 + zookeeper

一、用户列表的获取与分页

前端代码:

<div class="usersList_wrapper">
                <!-- 用户列表展示的表格 -->  
                <table id="usersList"></table>
                <!-- 底部的分页条 -->  
                <div id="usersListPager"></div>  
            </div>

jGrid发送请求获取数据封装好展示到页面

// 用户列表
        var handleList = function() {
            
            // 上下文对象路径
            var hdnContextPath = $("#hdnContextPath").val();
            var apiServer = $("#apiServer").val();
            
            var jqGrid = $("#usersList");  
            jqGrid.jqGrid({  
                caption: "短视频用户列表",  
                url: hdnContextPath + "/users/list.action",  
                mtype: "post",  
                styleUI: 'Bootstrap',//设置jqgrid的全局样式为bootstrap样式  
                datatype: "json",  
                colNames: ['ID', '头像', '用户名', '昵称', '粉丝数', '关注数', '获赞数'],  
                colModel: [  
                    { name: 'id', index: 'id', width: 30, sortable: false, hidden: false },  
                    { name: 'faceImage', index: 'username', width: 50, sortable: false,
                        formatter:function(cellvalue, options, rowObject) {
                            <!-- 配置的虚拟目录apiServer = http://192.168.199.150:8080 -->
                            var src = apiServer + cellvalue;
                            var img = "<img src='" + src + "' width='120'></img>"
                            return img;
                        }  
                    },
                    { name: 'username', index: 'password', width: 30, sortable: false },
                    { name: 'nickname', index: 'nickname', width: 30, sortable: false },
                    { name: 'fansCounts', index: 'age', width: 20, sortable: false },
                    { name: 'followCounts', index: 'sexValue', width: 20, sortable: false },
                    { name: 'receiveLikeCounts', index: 'province', width: 20, sortable: false, hidden: false }
                ],  
                viewrecords: true,          // 定义是否要显示总记录数
                rowNum: 10,                    // 在grid上显示记录条数,这个参数是要被传递到后台
                rownumbers: true,              // 如果为ture则会在表格左边新增一列,显示行顺序号,从1开始递增。此列名为'rn'
                autowidth: true,              // 如果为ture时,则当表格在首次被创建时会根据父元素比例重新调整表格宽度。如果父元素宽度改变,为了使表格宽度能够自动调整则需要实现函数:setGridWidth
                height: 500,                // 表格高度,可以是数字,像素值或者百分比
                rownumWidth: 36,             // 如果rownumbers为true,则可以设置行号 的宽度
                pager: "#usersListPager",        // 分页控件的id  
                subGrid: false                // 是否启用子表格
            }).navGrid('#usersListPager', {
                edit: false,
                add: false,
                del: false,
                search: false
            });
            
      
            // 随着窗口的变化,设置jqgrid的宽度  
            $(window).bind('resize', function () {  
                var width = $('.usersList_wrapper').width()*0.99;  
                jqGrid.setGridWidth(width);  
            });  
            
            // 不显示水平滚动条
            jqGrid.closest(".ui-jqgrid-bdiv").css({ "overflow-x" : "hidden" });
            
            // 条件查询所有用户列表
            $("#searchUserListButton").click(function(){
                var searchUsersListForm = $("#searchUserListForm");
                jqGrid.jqGrid().setGridParam({ 
                    page: 1,
                    url: hdnContextPath + "/users/list.action?" + searchUsersListForm.serialize(),
                }).trigger("reloadGrid");
            });
        }

后端获取用户列表分页数据的接口:

@PostMapping("/list")
    @ResponseBody
    public PagedResult list(Users user , Integer page) {
        
        PagedResult result = usersService.queryUsers(user, page == null ? 1 : page, 10);
        return result;
    }

SpringBoot 仿抖音短视频小程序开发(三)

搜索功能的实现:

<!-- 搜索内容 -->
        <div class="col-md-12">
            <br/>
                <form id="searchUserListForm" class="form-inline" method="post" role="form">
                    <div class="form-group">
                        <label class="sr-only" for="username">用户名:</label>
                        <input id="username" name="username" type="text" class="form-control" placeholder="用户名" />
                    </div>
                    <div class="form-group">
                        <label class="sr-only" for="nickname">昵称:</label>
                        <input id="nickname" name="nickname" type="text" class="form-control" placeholder="昵称" />
                    </div>
                    <button id="searchUserListButton" class="btn yellow-casablanca" type="button">搜    索</button>
                </form>
            </div>

使用jGrid发送请求给后台

// 条件查询所有用户列表
        $("#searchUserListButton").click(function(){
            var searchUsersListForm = $("#searchUserListForm");
            jqGrid.jqGrid().setGridParam({ 
                page: 1,
                url: hdnContextPath + "/users/list.action?" + searchUsersListForm.serialize(),
            }).trigger("reloadGrid");
        });

二、背景音乐BGM的上传、查询和删除

SpringBoot 仿抖音短视频小程序开发(三)

上传

$("#file").fileupload({
        pasteZone: "#bgmContent",
        dataType: "json",
        done: function(e, data) {
            console.log(data);
            
            if (data.result.status != '200') {
                alert("长传失败...");
            } else {
                var bgmServer = $("#bgmServer").val();
                var url = bgmServer + data.result.data;
                $("#bgmContent").html("<a href='" + url + "' target='_blank'>点我播放</a>");
                $("#path").attr("value", data.result.data);
            }
            
        }
    });

后台接口保存BGM的方法参考上传头像的方法

SpringBoot 仿抖音短视频小程序开发(三)

分页查询

参考用户列表信息的分页查询多少

删除BGM

var deleteBgm = function(bgmId) {
    var flag = window.confirm("是否确认删除???");
    if (!flag) {
        return;
    }
    $.ajax({
        url: $("#hdnContextPath").val() + '/video/delBgm.action?bgmId=' + bgmId,
        type: "POST",
        success: function(data) {
            if (data.status == 200 && data.msg == 'OK') {
                alert('删除成功~~');
                var jqGrid = $("#bgmList");  
                jqGrid.jqGrid().trigger("reloadGrid");
            }
        }
    })
}

三、举报管理

禁止播放

SpringBoot 仿抖音短视频小程序开发(三)

var forbidVideo = function(videoId) {
    var flag = window.confirm("是否禁播");
    if (!flag) {
        return;
    }
    $.ajax({
        url: $("#hdnContextPath").val() + "/video/forbidVideo.action?videoId=" + videoId,
        type: "POST",
        async: false,
        success: function(data) {
            if(data.status == 200 && data.msg == "OK") {
                alert("操作成功");
                var jqGrid = $("#usersReportsList");  
                //reloadGrid是重新加载表格
                jqGrid.jqGrid().trigger("reloadGrid");
            } else {
                console.log(JSON.stringify(data));
            }
        }
    })
}

四、后台管理系统增加或删除BGM,向zookeeper-server创建子节点,让小程序后端监听【重点】

1、首先安装Zookeeper到 Linux 上,启动服务器

SpringBoot 仿抖音短视频小程序开发(三)

2、编写zk客户端代码:

import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ZKCurator {
    //zk客户端
    private CuratorFramework client = null;
    
    final static Logger log = LoggerFactory.getLogger(ZKCurator.class);
 
    public ZKCurator(CuratorFramework client) {
        this.client = client;
    }
    
    public void init() {
        client = client.usingNamespace("admin");
        try {
            //判断在admin命名空间下是否有bgm节点 /admin/bgm
            if( client.checkExists().forPath("/bgm") == null ) {
                //对于zk来讲,有两种类型的节点,一种是持久节点(永久存在,除非手动删除),另一种是临时节点(会话断开,自动删除)
                client.create().creatingParentContainersIfNeeded()
                .withMode(CreateMode.PERSISTENT) //持久节点
                .withACL(Ids.OPEN_ACL_UNSAFE)  //匿名权限
                .forPath("/bgm"); 
                log.info("zookeeper客户端连接初始化成功");
                log.info("zookeeper服务端状态:{}",client.isStarted());
            }
        } catch (Exception e) {
            log.error("zookeeper客户端连接初始化失败");
            e.printStackTrace();
        }
    }
    
    /**
     * 增加或者删除Bgm,向zk-server创建子节点,供小程序后端监听
     * @param bgmId
     * @param operType
     */
    public void sendBgmOperator(String bgmId, String operObject) {
        try {
            client.create().creatingParentContainersIfNeeded()
            .withMode(CreateMode.PERSISTENT) //持久节点
            .withACL(Ids.OPEN_ACL_UNSAFE)  //匿名权限
            .forPath("/bgm/" + bgmId, operObject.getBytes());

        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}

3、在applicationContext-zookeeper.xml配置zookeeper:

<!-- 创建重连策列 -->
    <bean id="retryPolicy" class="org.apache.curator.retry.ExponentialBackoffRetry">
        <!-- 每次重试连接的等待时间 -->
        <constructor-arg index="0" value="1000"></constructor-arg>
        <!-- 设置最大的重连次数 -->
        <constructor-arg index="1" value="5"></constructor-arg>
    </bean>
    
    <!-- 创建zookeeper客户端  -->
    <bean id="client" class="org.apache.curator.framework.CuratorFrameworkFactory"
        factory-method="newClient" init-method="start">
        <constructor-arg index="0" value="120.79.18.35:2181"></constructor-arg>
        <constructor-arg index="1" value="10000"></constructor-arg>
        <constructor-arg index="2" value="10000"></constructor-arg>
        <constructor-arg index="3" ref="retryPolicy"></constructor-arg>
    </bean>
     
     <!-- 调用init方法启动 -->
    <bean id="ZKCurator" class="com.imooc.web.util.ZKCurator" init-method="init">
        <constructor-arg index="0" ref="client"></constructor-arg>
    </bean>

4、上传或者删除BGM时调用VideoServiceImpl.java的方法

@Autowired
    private ZKCurator zKCurator;
    @Override
    public void addBgm(Bgm bgm) {
        String id = sid.nextShort();
        bgm.setId(id);
        bgmMapper.insert(bgm);
        Map<String, String> map = new HashMap<>();
        map.put("operType", BGMOperatorTypeEnum.ADD.type);
        map.put("path", bgm.getPath());
        zKCurator.sendBgmOperator(id, JSONUtils.toJSONString(map));
    }

    @Override
    public void deleteBgm(String id) {
        Bgm bgm = bgmMapper.selectByPrimaryKey(id);
        
        bgmMapper.deleteByPrimaryKey(id);
        Map<String, String> map = new HashMap<>();
        map.put("operType", BGMOperatorTypeEnum.DELETE.type);
        map.put("path", bgm.getPath());
        zKCurator.sendBgmOperator(id, JSONUtils.toJSONString(map));
    }

5、小程序编写代码监听zookeeper的节点,并对其做出相应的删除和上传操作【重点】

初始化zookeeper客户端

private CuratorFramework client = null;

    final static Logger log = LoggerFactory.getLogger(ZKCuratorClient.class);

//    public static final String ZOOKEEPER_SERVER = "120.79.18.36:2181";

    public void init() {
        if(client != null) {
            return;
        }
        //重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
        //创建zk客户端  120.79.18.36:2181
        client = CuratorFrameworkFactory.builder().connectString(resourceConfig.getZookeeperServer()).sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy).namespace("admin").build();
        //启动客户端
        client.start();
        try {
            addChildWatch("/bgm");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

监听zk-server的节点,当短视频后台管理系统上传或者删除某个BGM的时候,小程序后台服务器通过Zookeeper监听自动下载背景音乐

public void addChildWatch(String nodePath) throws Exception {
        final PathChildrenCache cache = new PathChildrenCache(client, nodePath, true);
        cache.start();
        cache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
                    log.info("监听到事件CHILD_ADDED");
                    //1. 从数据库查询bgm对象,获取路径Path
                    String path = event.getData().getPath();
                    String operatorObjStr = new String(event.getData().getData());
                    Map<String, String> map = JsonUtils.jsonToPojo(operatorObjStr, Map.class);
                    String operatorType = map.get("operType");
                    String songPath = map.get("path");

//                    String[] arr = path.split("/");
//                    String bgmId = arr[arr.length-1];
//                    Bgm bgm =  bgmService.queryBgmById(bgmId);
//                    if(bgm == null){
//                        return;
//                    }
                    //1.1 bgm所在的相对路径
//                String songPath = bgm.getPath();

                    //2. 定义保存到本地的bgm路径
//                String filePath = "E:\\imooc_videos_dev" + songPath;
                    String filePath = resourceConfig.getFileSpace() + songPath;

                    //3. 定义下载的路径(播放url)
                    String[] arrPath = songPath.split("\\\\"); //windows
//                    String[] arrPath = songPath.split("/"); //linux
                    String finalPath = "";
                    //3.1 处理url的斜杠以及编码
                    for(int i=0; i<arrPath.length;i++){
                        if(StringUtils.isNotBlank(arrPath[i])) {
                            finalPath += "/";
                            finalPath += URLEncoder.encode(arrPath[i], "UTF-8");
                        }
                    }
//                    String bgmUrl = "http://192.168.199.150:8080/mvc" + finalPath;
                    String bgmUrl = resourceConfig.getBgmServer() + finalPath;

                    if(operatorType.equals("1")){
                        //下载bgm到springboot服务器
                        URL url = new URL(bgmUrl);
                        File file = new File(filePath);
                        FileUtils.copyURLToFile(url, file);
                        client.delete().forPath(path);
                    }else if(operatorType.equals("2")){
                        File file = new File(filePath);
                        FileUtils.forceDelete(file);
                        client.delete().forPath(path);
                    }

                }
            }
        });
    }

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

More Eric Meyer on CSS (Voices That Matter)

More Eric Meyer on CSS (Voices That Matter)

Eric A. Meyer / New Riders Press / 2004-04-08 / USD 45.00

Ready to commit to using more CSS on your sites? If you are a hands-on learner who has been toying with CSS and want to experiment with real-world projects that will enable you to see how CSS......一起来看看 《More Eric Meyer on CSS (Voices That Matter)》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具