《5K入门级项目实战:好来屋在线影院》之第 7 战 —— 电影动态管理、EasyUI combobox 远程调用 API 接口

OK,经常前面的学习,我们基本掌握了 EasyUI 的使用。接下来的这个功能算是挺简单的。电影动态,就是新出了什么电影的动态信息,像我们的QQ空间动态、朋友圈动态一样:让别人了解发生了什么新鲜事。

OK,我们开始用程序的思维思考问题。先来创建这一节需要的数据库表:movie_dynamic

CREATE TABLE `movie_dynamic` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,自动增长',
  `movie_id` int(11) DEFAULT NULL COMMENT '参考 movie_info 表的主键',
  `dynamic` varchar(100) DEFAULT NULL COMMENT '动态信息',
  `movie_url` varchar(255) DEFAULT NULL COMMENT '电影参考链接',
  `create_time` date DEFAULT NULL COMMENT '发布日期',
  PRIMARY KEY (`id`),
  KEY `movie_id` (`movie_id`),
  CONSTRAINT `movie_dynamic_ibfk_1` FOREIGN KEY (`movie_id`) REFERENCES `movie_info` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='电影动态信息表';

这是设置了一个外键,参考 movie_info 表的主键。

使用 Mybatis 逆向工程,生成电影动态信息的实体和 mapper 文件,并剪切到对应的目录下。这里不再赘述。

package com.movie.entity;

import java.io.Serializable;
import java.util.Date;

public class MovieDynamicEntity implements Serializable {

    private static final long serialVersionUID = -1816292474079277549L;

    private Integer id;

    private Integer movieId;//电影主键 id

    private String dynamic;//电影动态信息

    private String movieUrl;//电影参考链接

    private Date createTime;//发布日期

    为缩短篇幅,这里省略 get、set 方法,请自行增加。
}

MovieDynamicEntityMapper.xml 完整代码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.movie.database.dao.MovieDynamicDao">
  <resultMap id="BaseResultMap" type="com.movie.entity.MovieDynamicEntity">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="movie_id" jdbcType="INTEGER" property="movieId" />
    <result column="dynamic" jdbcType="VARCHAR" property="dynamic" />
    <result column="movie_url" jdbcType="VARCHAR" property="movieUrl" />
    <result column="create_time" jdbcType="DATE" property="createTime" />
  </resultMap>

    <!-- 根据主键 id 删除 -->
  <delete id="delete" parameterType="java.lang.Integer">
    delete from movie_dynamic
    where id = #{id,jdbcType=INTEGER}
  </delete>

    <!-- 新增,发布时间直接使用 mysql 的 now() 函数 -->
  <insert id="insert" parameterType="com.movie.entity.MovieDynamicEntity">
    insert into movie_dynamic
    (movie_id, dynamic,movie_url,create_time)
    values
    (#{movieId,jdbcType=INTEGER},
      #{dynamic,jdbcType=VARCHAR},
      #{movieUrl,jdbcType=VARCHAR},
      now())
  </insert>

</mapper>

main.html 文件中,我们用到“电影动态管理”需要对应的文件名是:movieDynamic.html

我们在 html 文件夹上创建 movieDynamic.html

movieDynamic.html 的完整代码如下(需要好好斟酌一下,或者自学 EasyUI 的基本用法):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>电影动态信息管理页面</title>
<link rel="stylesheet" type="text/css" href="/static/jquery-easyui-1.7.0/themes/default/easyui.css"></link>
<link rel="stylesheet" type="text/css" href="/static/jquery-easyui-1.7.0/themes/icon.css"></link>
<script type="text/javascript" src="/static/jquery-easyui-1.7.0/jquery.min.js"></script>
<script type="text/javascript" src="/static/jquery-easyui-1.7.0/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/static/jquery-easyui-1.7.0/locale/easyui-lang-zh_CN.js"></script>

<script type="text/javascript">

    //进入页面时,自动调用 API 接口加载数据
    $(document).ready(function(){
        // 把电影名称调用 API 接口,加载到 movieComboList 下拉框中
        $('#movieComboList').combobox({
            mode:'remote' ,//remote 是远程模式,当用户输入字符到 input 文本框中,控件将发送 'q' 参数到远程服务器。
            url:'/admin/movie/comboList',//调动的接口地址是电影管理的模块
            valueField:'id',//数据字段:对应电影实体的id
            textField:'movieName',//显示的字段:对应电影实体的名称
            delay:200 //页面加载完毕后,延迟 200 毫秒加载
        });
    });

    //模糊搜索电影动态信息
    function searchInfo(){
        //调用 datagrid 的 load 方法做查询
        $("#movieDataGrid").datagrid('load',{
            queryParams: {
                dynamic: $("#searchId").val()  //后台取值时,根据 dynamic 作为 key 来取值
            }
        });
    }

    //删除信息
    function deleteInfo(){
        //获取数据网格的选中框
        var selectedRows = $("#movieDataGrid").datagrid("getSelections");
        if(selectedRows.length == 0){
            $.messager.alert("系统提示","请选择要删除的数据!");
            return;
        }
        //将勾选的电影动态信息存入数组
        var movieIds = [];
        for(var i=0;i < selectedRows.length;i++){
            movieIds.push(selectedRows[i].id);
        }
        var deleteIds = movieIds.join(",");
        $.messager.confirm("系统提示","您确定要删除这<font color=red>"+selectedRows.length+"</font>条数据吗?",function(r){
            if(r){
                //使用 post 方法,调用 API 接口,删除 id 集合
                $.post("/admin/movieDynamic/delete",{ids:deleteIds},function(result){
                    //获取接口返回的数据,API 接口需要返回 flag 作为 key 的键值对数据,即 Map
                    if(result.flag){
                        $.messager.alert("系统提示","数据已成功删除!");
                        $("#movieDataGrid").datagrid("reload");//重新加载网格数据
                    }else{
                        $.messager.alert("系统提示","数据删除失败!");
                    }
                },"json");//指定 post 方法传递的是 json 格式的参数
            }
        });
    }

    var url;
    //打开“添加电影动态信息”的窗口,把 url 赋值
    function openInfoAddDialog(){
        $("#dlg").dialog("open").dialog("setTitle","添加电影动态信息");
        url="/admin/movieDynamic/save";
    }
    //点击“保存”按钮时调用的方法,注意这个 url 是打开窗口时赋值的 url
    function saveInfo(){
        $("#fm").form("submit",{
            url:url,
            onSubmit:function(){
                return $(this).form("validate");//form 表单的基本校验
            },
            success:function(result){
                var result = eval('('+result+')');
                //API 后台返回的数据,flag 作为key
                if(result.flag){
                    $.messager.alert("系统提示","保存成功!");
                    resetValue();//清空数据
                    $("#dlg").dialog("close");//关掉窗口
                    $("#movieDataGrid").datagrid("reload");//重新加载网格数据
                }else{
                    $.messager.alert("系统提示","保存失败!");
                    return;
                }
            }
        });
    }

    //关掉“添加电影动态信息”窗口,调用窗口“重置值”的方法
    function closeInfoDialog(){
        $("#dlg").dialog("close");
        resetValue();
    }

    //窗口重置值的方法,将各个输入框的数据清空
    function resetValue(){
        $("#movieComboList").combobox("setValue","");//清空电影名称下拉框数据
        $("#dynamicId").val("");//动态信息输入框
        $("#movieUrlId").val("");//电影网站 URL 输入框
    }

    //格式化发布日期
    function formatCreateTime(val,row) {
        if (val != null) {
            var date = new Date(val);
            return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
        }
    }

</script>
</head>
<body style="margin: 1px">
    <table id="movieDataGrid" title="电影动态信息管理" class="easyui-datagrid"
       fitColumns="true" pagination="true" rownumbers="true"
       url="/admin/movieDynamic/list" fit="true" toolbar="#tb">
    <thead>
    <tr>
        <th field="cb" checkbox="true" align="center"></th>
        <th field="movieName" width="100" align="center">电影名称</th>
        <th field="dynamic" width="300" align="center">动态信息</th>
        <th field="movieUrl" width="150" align="center">详细网址</th>
        <th field="createTime" width="80" align="center" formatter="formatCreateTime">发布日期</th>
    </tr>
    </thead>
    </table>
    <div id="tb">
        <div>
            <a href="javascript:openInfoAddDialog()" class="easyui-linkbutton" iconCls="icon-add" plain="true">添加</a>
            <a href="javascript:deleteInfo()" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
        </div>
    <div>
        <!-- event.keyCode==13 是监听回车键 -->
        &nbsp;电影动态信息:&nbsp;<input type="text" id="searchId" size="20" onkeydown="if(event.keyCode == 13) searchInfo()"/>
        <a href="javascript:searchInfo()" class="easyui-linkbutton" iconCls="icon-search" plain="true">搜索</a>
    </div>
    </div>
    <!-- 添加信息的窗口,默认关闭。 -->
    <div id="dlg" class="easyui-dialog" style="width:500px;height:230px;padding: 10px 20px" closed="true" buttons="#dlg-buttons">
        <form id="fm" method="post">
            <table cellspacing="8px">
                <tr>
                    <td>电影名称:</td>
                    <!-- 注意:form 表单的 name 对应电影动态信息实体的属性 -->
                    <td><input type="text" id="movieComboList" name="movieId" size="24" maxlength="80" class="easyui-combobox"  data-options="required:true,panelHeight:'auto'"/></td>
                </tr>
                <tr>
                    <td>动态信息:</td>
                    <td><input type="text" id="dynamicId" name="dynamic" class="easyui-validatebox" required="true" style="width: 250px"/></td>
                </tr>
                <tr>
                    <td>详细网址:</td>
                    <td><input type="text" id="movieUrlId" name="movieUrl" class="easyui-validatebox" validType="url" required="true" style="width: 300px"/></td>
                </tr>
            </table>
        </form>
    </div>

    <div id="dlg-buttons">
        <a href="javascript:saveInfo()" class="easyui-linkbutton" iconCls="icon-ok">保存</a>
        <a href="javascript:closeInfoDialog()" class="easyui-linkbutton" iconCls="icon-cancel">关闭</a>
    </div>
</body>
</html>

先把服务起来,看下我们的页面是个什么效果。

点击“添加”按钮:

 

OK,有增加、删除的功能按钮,有搜索框,有数据网格,还有分页信息等等,这些都需要我们开发对应 API 接口。

我们先创建一个接口,即进入管理页面后,电影名称从数据库中读取到下拉列表中。

 

OK,刚从菜单进入页面时,就去调用 API 接口,拉取电影名称存入到下拉框中,这时候输入框内容是空的,所以获取到的数据应该是没有。同时,这是使用 remote 是远程模式,当用户输入字符到 input 文本框中,控件将发送 'q' 参数到远程服务器,也会调用 API 接口。这个路径请求的是 admin/movie/comboList ,在我们项目中分在 movieInfo 模块。因此我们需要在 MovieInfoController 类里增加这个 API 接口。

注意:

返回的对象必须是 result,因为前端已经根据 result.id 来获取返回的电影名称了。

 

MovieInfoController 完整代码如下:

package com.movie.controller.admin;

import com.movie.entity.MovieInfoEntity;
import com.movie.manage.MovieInfoManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-17 上午 11:27
 */
@RestController
@RequestMapping(value = "/admin/movie")
public class MovieInfoController {

    @Autowired
    private MovieInfoManage movieInfoManage;

    @ResponseBody
    @RequestMapping("/save")
    public Map<String,Object> save(MovieInfoEntity entity, @RequestParam("imageFile") MultipartFile file){
        Map<String,Object> map = new HashMap<>();
        boolean flag = movieInfoManage.save(entity,file);
        map.put("flag",flag);
        return map;
    }

    //富文本编辑器上传文件
    @ResponseBody
    @RequestMapping("/ckeditorUpload")
    public String ckeditorUpload(@RequestParam("upload")MultipartFile file,String CKEditorFuncNum){
        String result = movieInfoManage.ckeditorUpload(file,CKEditorFuncNum);
        return  result;
    }

    //模糊查询用户输入的电影名称,返回到下拉框中
    @ResponseBody
    @RequestMapping("/comboList")
    public List<MovieInfoEntity> comboList(String q){
        List<MovieInfoEntity> result = movieInfoManage.comboList(q);
        return result;
    }
}

接下来,需要在 MovieInfoManage 接口里增加 comboList 方法,完整代码如下:

package com.movie.manage;

import com.movie.entity.MovieInfoEntity;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-17 上午 11:32
 */
public interface MovieInfoManage {

    //保存电影信息
    boolean save(MovieInfoEntity entity, MultipartFile file);

    //富文本编辑器上传文件
    String ckeditorUpload(MultipartFile file,String CKEditorFuncNum);

    //模糊查询用户输入的电影名称,返回到下拉框中
    List<MovieInfoEntity> comboList(String q);
}

MovieInfoManageImpl 实现类完整代码;

package com.movie.manage.impl;

import com.movie.database.service.MovieInfoService;
import com.movie.entity.MovieInfoEntity;
import com.movie.manage.MovieInfoManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-17 上午 11:36
 */
@Service
public class MovieInfoManageImpl implements MovieInfoManage {

    @Value("${image.path}")
    private String imageFilePath;

    @Autowired
    private MovieInfoService movieInfoService;

    //新增电影信息
    @Override
    public boolean save(MovieInfoEntity entity, MultipartFile file) {
        boolean flag = false;
        try {
            if (!StringUtils.isEmpty(file)) {
                String originalFilename = file.getOriginalFilename();//获取文件名
                entity.setImageName(originalFilename);//设置到实体中
                String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));//获取文件后缀
                String newFileName = System.currentTimeMillis() + suffixName;//新的文件名,避免文件名重复
                FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(imageFilePath + newFileName));
            }

            //将富文本的 html 代码转换特殊字符,防止对网站进行xss跨站攻击
            //方案 1:转成十进制
            String movieContent = HtmlUtils.htmlEscapeDecimal(entity.getMovieContent());
            //方案 2:转成十六进制
            //String movieContent = HtmlUtils.htmlEscapeHex(entity.getMovieContent());

            entity.setMovieContent(movieContent);
            //解码只需一个方法即可,解码后返回给前端,跟传递进来的时候是一样的。
            //String movieContent = HtmlUtils.htmlUnescape(entity.getMovieContent());

            int count = movieInfoService.insert(entity);
            if (count > 0) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    //富文本编辑器上传文件
    @Override
    public String ckeditorUpload(MultipartFile file,String CKEditorFuncNum){
        String result = "";
        try{
            String originalFilename = file.getOriginalFilename();//获取文件名
            String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));//获取文件后缀
            String newFileName = System.currentTimeMillis() + suffixName;//新的文件名,避免文件名重复
            FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(imageFilePath + newFileName));

            StringBuilder sb = new StringBuilder();
            sb.append("<script type=\"text/javascript\">");
            //注意:/movieImages/ 返回虚拟路径给前端,对应配置类 WebConfig 的路径。
            sb.append("window.parent.CKEDITOR.tools.callFunction("+ CKEditorFuncNum + ",'" + "/movieImages/" + newFileName + "','')");
            sb.append("</script>");
            result = sb.toString();
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    //模糊查询用户输入的电影名称,返回到下拉框中
    @Override
    public List<MovieInfoEntity> comboList(String q){
        List<MovieInfoEntity> list = new ArrayList<>();
        try{
            if(!StringUtils.isEmpty(q)){
                list = movieInfoService.findByParam(q);//调用接口作电影名称的模糊查询
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return list;
    }
}

MovieInfoService 类需要增加 findByParam 方法,完整代码:

package com.movie.database.service;

import com.movie.database.dao.MovieInfoDao;
import com.movie.entity.MovieInfoEntity;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-17 下午 12:27
 */
@Service
public class MovieInfoService {

    @Autowired(required = false)
    private MovieInfoDao movieInfoDao;

    //新增电影信息。
    //@Transactional(readOnly = false) //readOnly 的事务默认为 false,有读写的操作,可以不设置
    public int insert(MovieInfoEntity entity){
        return movieInfoDao.insert(entity);
    }

    //调用接口作电影名称的模糊查询
    @Transactional(readOnly = true)//事务只读
    public List<MovieInfoEntity> findByParam(@Param("q") String q){
        return movieInfoDao.findByParam(q);
    }

}

MovieInfoDao 接口需要增加 findByParam 方法,完整代码:

package com.movie.database.dao;

import com.movie.entity.MovieInfoEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-17 下午 12:33
 */
@Mapper
public interface MovieInfoDao {

    //新增电影信息
    int insert(MovieInfoEntity entity);

    //调用接口作电影名称的模糊查询
    List<MovieInfoEntity> findByParam(@Param("q") String q);
}

最后,MovieInfoEntityMapper.xml 文件需要增加查询的方法,我们限定只查询前 10 条记录(多少由你定)返回给接口。

    <!-- 根据电影名称模糊查询,限制前 10 个即可 -->
    <select id="findByParam" parameterType="java.lang.String" resultMap="BaseResultMap">
        select id, movie_name
        from movie_info
        where movie_name like CONCAT('%',#{q,jdbcType=VARCHAR}, '%')
        limit 0,10
    </select>

这里注意 like (模糊查询)语句的用法,以及 concat 字符串拼接函数的用法。

 

OK,我们启动服务,测试功能。

点击左边的“电影动态管理”菜单,延迟 200 毫秒已经调用我们的 API 接口了。这是后输入框是空的,接口直接返回空数据。

如果这时候打开浏览器的调试模式(F12),会看到一行报错信息:

这是 EasyUI 的 DataGrid 调用的接口,因为我们还没写对应的 API 接口,所以报 404 错误,可以先忽略。

我们点击“添加”按钮,在电影名称的下拉框输入电影的某个字,也会远程调用了 API ,返回结果到下拉选项中。可以在数据库里增加更多的电影信息,来自行体验。

 

接下来,我们来完成这个电影动态信息的添加 API 接口。我们需要注意与 EasyUI 定义的参数对应:请求的 URL 路径以及返回的对象。

需要注意返回的 map 的键是 flag。 

 

我们在 Controller 层创建类:MovieDynamicController,用来处理电影动态信息的请求,注意:不同的类、接口,请放在对应的包下,现在开始养成编码的好习惯,早日成为合格架构师!

完整代码如下:

package com.movie.controller.admin;

import com.movie.entity.MovieDynamicEntity;
import com.movie.manage.MovieDynamicManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-22 下午 11:46
 */
@RestController
@RequestMapping(value = "/admin/movieDynamic")
public class MovieDynamicController {

    @Autowired
    private MovieDynamicManage movieDynamicManage;

    //保存电影动态信息
    @ResponseBody
    @RequestMapping("/save")
    public Map<String,Object> save(MovieDynamicEntity entity){
        Map<String,Object> map = new HashMap<>();
        boolean flag = movieDynamicManage.save(entity);
        map.put("flag",flag);
        return map;
    }
}

然后,编写 MovieDynamicManage 接口,完整代码:

package com.movie.manage;

import com.movie.entity.MovieDynamicEntity;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-22 上午 11:32
 */
public interface MovieDynamicManage {

    //保存电影动态信息
    boolean save(MovieDynamicEntity entity);

}

然后,编写 MovieDynamicManage 接口的实现类 MovieDynamicManageImpl,完整代码:

package com.movie.manage.impl;

import com.movie.database.service.MovieDynamicService;
import com.movie.entity.MovieDynamicEntity;
import com.movie.manage.MovieDynamicManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-22 上午 11:36
 */
@Service
public class MovieDynamicManageImpl implements MovieDynamicManage {

    @Autowired
    private MovieDynamicService movieDynamicService;

    //新增电影信息
    @Override
    public boolean save(MovieDynamicEntity entity) {
        boolean flag = false;
        try {
            int count = movieDynamicService.insert(entity);
            if (count > 0) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
}

然后,编写 MovieDynamicService 类,完整代码:

package com.movie.database.service;

import com.movie.database.dao.MovieDynamicDao;
import com.movie.entity.MovieDynamicEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-22 下午 12:27
 */
@Service
public class MovieDynamicService {

    @Autowired(required = false)
    private MovieDynamicDao movieDynamicDao;

    //新增电影动态信息。
    //@Transactional(readOnly = false) //readOnly 的事务默认为 false,有读写的操作,可以不设置
    public int insert(MovieDynamicEntity entity){
        return movieDynamicDao.insert(entity);
    }

}

然后,编写 MovieDynamicDao 接口,完整代码:

package com.movie.database.dao;

import com.movie.entity.MovieDynamicEntity;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author biandan
 * @signature 让天下没有难写的代码
 * @create 2019-11-22 下午 12:33
 */
@Mapper
public interface MovieDynamicDao {

    //新增电影动态信息
    int insert(MovieDynamicEntity entity);

}

OK,我们起服务,做一下测试。

①电影名称可以使用我们的搜索功能。

②动态信息随你喜欢填入:《少年的你》主演: 周冬雨/易烊千玺/尹昉/黄觉

③详细网址(EasyUI 帮我们做 URL 检查了)可以去优酷复制一段网址粘贴过来:https://v.youku.com/v_show/id_XNDQxNTU1MzM4MA==.html?spm=a2h0k.11417342.soresults.dposter&s=36df45e4a1a84b2baa39

点击保存,我们在后台打个断点,看下数据,自动封装成动态信息的实体给我们:

我们去数据库看下数据,正如我们预期的一致:

OK,下一篇博客继续讲解 EasyUI DataGrid 数据网格控件。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值