当前位置: 首页 > news >正文

长沙的在线商城网站建设网站建设的发展目标

长沙的在线商城网站建设,网站建设的发展目标,传奇世界网页版单机,推广方式的英文文章目录 一. 实战-我的B站1. 功能演示2. 设计数据类数据展示路径参数 3. 设计 Service 类静态资源映射读取文件的时机Stream API 改进 二. MySQL 数据库1. 数据库必要性2. MySQL 安装下载压缩包初始化数据库运行服务器运行客户端 3. 初步使用4. datagrip添加数据源导入数据用 … 文章目录 一. 实战-我的B站1. 功能演示2. 设计数据类数据展示路径参数 3. 设计 Service 类静态资源映射读取文件的时机Stream API 改进 二. MySQL 数据库1. 数据库必要性2. MySQL 安装下载压缩包初始化数据库运行服务器运行客户端 3. 初步使用4. datagrip添加数据源导入数据用 datagrip 导入数据用 mysql 工具导入数据 5. MyBatis 入门准备工作Java BeanMapper 接口单元测试 6. 查询视频Mapper 接口Java BeanServiceController 7. 发布视频上传分块合并分块上传封面发布视频 一. 实战-我的B站 1. 功能演示 从这节课开始我们来做一个实战练习我的 B 站。我们从播放视频页面开始做做了适当简化说明一点这个页面的所有图标动画等都是自己做的虽然丑了点但不会侵权。先来看看页面效果 左侧可以播放视频并包含了视频的信息右侧是视频选集一个视频可以包含多集点击后可以切换到第一集、第二集等等 整个程序分成前端页面部分和后端 java 代码两部分。页面部分你就当是前端妹妹给你做好了我们是后端 java 程序员需要用面向对象的思想和 Spring Boot 与前端对接。从哪儿开始呢 2. 设计数据类 之前讲过任何程序都分成数据和逻辑两部分我们之前也讲了数据和逻辑的分离数据部分对应 Java Bean逻辑部分对应 Service我们的代码开发就可以从设计 Java Bean 和 Service 类开始。 先从 Java Bean 开始分析通过这个页面查看它的组成就可以看出来将来 Java Bean 的组成我们这个页面主要展现的是视频信息有哪些视频信息呢 开始抽象每一集抽象为 Play 类整个视频抽象为 Video 类 public class Play {private String id;private String title;private String url;LocalTime duration;// ... }其中 url 对应视频实际名称截图中没有体现 public class Video {private ListPlay playList;private String bv;private String type; // 类型: 自制、转载private String category; // 分区: 生活、游戏、娱乐、知识、影视、音乐、动画、时尚、美食、汽车、运动、科技、动物圈、舞蹈、国创、鬼畜、纪录片、番剧、电视剧、电影private String title; // 总标题, 最多 80 字private String cover; // 封面private String introduction; // 简介, 最多 250 字private LocalDateTime publishTime; // 发布时间private ListString tagList; // 最多 10 个// ... }其中 type 和 category 页面展示暂时没有用上bv 号生成有一定规则目前暂时用字符串 123 … 来表示必须有对应的 get 方法 有同学问Video 和 Play 中这些属性名能不能改成其它的答案是可以改但你这边改了前端页面也得跟着改。因为前端页面中使用对象时属性名与后端 JavaBean 代码的属性名是一一对应的 数据展示 前端约定 输入 http://localhost:8080/video/1 显示 1 号视频输入 http://localhost:8080/video/2 显示 2 号视频 页面上需要的是 Video 对象我们先返回固定的 Video 对象试试 Controller public class VideoController {RequestMapping(/video/1)ResponseBodypublic Video t1() {ListPlay plays List.of(new Play(P1, 二分查找-演示, LocalTime.parse(00:05:46), 1_1.mp4),new Play(P2, 二分查找-实现, LocalTime.parse(00:06:47), 1_2.mp4));return new Video(1, 面试专题-基础篇, LocalDateTime.now(), 1.png, 祝你面试游刃有余,List.of(面试, Java, 计算机技术), plays, 自制, 科技-计算机技术);}RequestMapping(/video/2)ResponseBodypublic Video t2() {ListPlay plays List.of(new Play(P1, Java中的线程状态, LocalTime.parse(00:09:45), 2_1.mp4),new Play(P2, 代码演示1, LocalTime.parse(00:07:05), 2_2.mp4),new Play(P3, 代码演示2, LocalTime.parse(00:05:01), 2_3.mp4));return new Video(2, 面试专题-并发篇, LocalDateTime.now(), 2.png, 祝你面试游刃有余,List.of(面试, Java, 计算机技术), plays, 自制, 科技-计算机技术);} }路径参数 还有一个未解决的问题就是前端页面中不同的 URL 路径对应不同的视频 http://localhost:8080/video/1 显示 1 号视频http://localhost:8080/video/2 显示 2 号视频… 后端 Java 代码每个 URL 路径都用了一个方法来返回视频但是不可能无限增加方法得找一个办法把多个路径映射到一个方法这就是接下来要介绍的路径参数 首先改动 RequestMapping(/video/{bv}) 这里 bv 就是一个路径参数前端 URL 是 /video/1bv 值就是1前端 URL 是 /video/2bv 值就是 2其次需要在代码中获取实际的 bv 值给方法加一个参数参数名也叫 bv参数前加 PathVariable 表示该参数从路径中获取 如果不加 PathVariable参数实际是从 ? 后获取 Controller public class VideoController {// 路径参数// 1. RequestMapping(/video/{bv})// 2. PathVariable String bv, PathVariable 表示该方法参数要从路径中获取RequestMapping(/video/{bv}) // 1, 2, 3...ResponseBodypublic Video t(PathVariable String bv) {if(bv.equals(1)) {ListPlay plays List.of(new Play(P1, 二分查找-演示, LocalTime.parse(00:05:46), 1_1.mp4),new Play(P2, 二分查找-实现, LocalTime.parse(00:06:47), 1_2.mp4));return new Video(1, 面试专题-基础篇, LocalDateTime.now(), 1.png, 祝你面试游刃有余,List.of(面试, Java, 计算机技术), plays, 自制, 科技-计算机技术);}if (bv.equals(2)) {ListPlay plays List.of(new Play(P1, Java中的线程状态, LocalTime.parse(00:09:45), 2_1.mp4),new Play(P2, 代码演示1, LocalTime.parse(00:07:05), 2_2.mp4),new Play(P3, 代码演示2, LocalTime.parse(00:05:01), 2_3.mp4));return new Video(2, 面试专题-并发篇, LocalDateTime.now(), 2.png, 祝你面试游刃有余,List.of(面试, Java, 计算机技术), plays, 自制, 科技-计算机技术);}return null;}3. 设计 Service 类 现有代码的缺点是 把数据写死在了 java 代码当中如果将来想对数据新增、修改、删除、代码也得跟着变动。解决方法是把数据存储在独立的文件当中不与 java 代码混在一起。我们现在写的这种根据视频编号返回视频对象的代码属于数据的查询、数据的增、删、改、查属于业务逻辑的范畴应该把这部分代码转移到业务逻辑类中 这些视频内容不应当固定在代码里而是存于 p.csv 文件中读取方式如下 try {ListString data Files.readAllLines(Path.of(data, p.csv));// ... } catch (IOException e) {throw new RuntimeException(e); }这里 readAllLines() 方法的作用就是读取文件的所有行Path.of 用来告知要读取的目录和文件名readAllLines() 方法执行时可能出现 IOException例如文件不存在IOException 是编译异常处理没必要不处理又会有语法上连锁反应这里有一个小技巧 就是把编译异常转换成 RuntimeException 重新抛出避免了连锁反应 设计 Service 如下 Service public class VideoService1 {// 查询方法根据视频编号查询 Video 对象public Video find(String bv) { // bv 参数代表视频编号 1try {ListString data Files.readAllLines(Path.of(data, p.csv)); // 1 ~ 7// String line 就是读到的文件中的每一行数据for (String line : data) {String[] s line.split(,);if(s[0].equals(bv)) { // 找到了String[] tags s[7].split(_);// playList 暂时用空集合return new Video(s[0], s[3], LocalDateTime.parse(s[6]), s[4], s[5], List.of(tags), List.of(), s[1], s[2]);}}// 没有找到return null;} catch (IOException e) {// RuntimeException 运行时异常, 把编译时异常转换为运行时异常throw new RuntimeException(e);}} }补充 playList Service public class VideoService1 {// 查询方法根据视频编号查询 Video 对象public Video find(String bv) { // bv 参数代表视频编号 1try {ListString data Files.readAllLines(Path.of(data, p.csv)); // 1 ~ 7// String line 就是读到的文件中的每一行数据for (String line : data) {String[] s line.split(,);if(s[0].equals(bv)) { // 找到了String[] tags s[7].split(_);return new Video(s[0], s[3], LocalDateTime.parse(s[6]), s[4], s[5], List.of(tags), getPlayList(bv), s[1], s[2]);}}// 没有找到return null;} catch (IOException e) {// RuntimeException 运行时异常, 把编译时异常转换为运行时异常throw new RuntimeException(e);}}// 读取选集文件 v_1.csvprivate ListPlay getPlayList(String bv) {try {ListString vdata Files.readAllLines(Path.of(data, v_ bv .csv));ListPlay list new ArrayList();for (String vline : vdata) {String[] ss vline.split(,);list.add(new Play(ss[0], ss[1], LocalTime.parse(ss[3]), ss[2]));}return list;} catch (IOException e) {throw new RuntimeException(e);}} }静态资源映射 像图片、视频这样的文件它们内容都不会轻易变动所以有个叫法称为静态资源另外由于它们占用的空间较大不太适合与其它程序代码打包在一起。但如果它们不在这个位置我还想通过 url 访问这些文件该怎么找到它们呢前面我们说过这些文件放在 static 目录下就能通过 url 找到static 就是这些文件的起点比如 在浏览器中输入一个 url 地址 http://localhost:8080/play/1_1.mp4 找的是 static 为起点 play 目录下的 1_1.mp4 这个文件http://localhost:8080/play/0a7ea914523dcf380d8bdbff506f19b4.mp4 怎样能找到服务器 d:\aaa 目录下的同名文件呢 这就需要让一个 url 地址与服务器的一个磁盘目录相关联具体做法是 SpringBootApplication // 支持 SpringBoot 功能的应用程序 public class Module5App implements WebMvcConfigurer {public static void main(String[] args) {SpringApplication.run(Module5App.class, args); // 运行 SpringBoot 程序}// 作用把 url 路径和 磁盘路径做一个映射// http://localhost:8080/play/xxx static/play// http://localhost:8080/play/xxx d:/aaaOverridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// url 路径 磁盘路径registry.addResourceHandler(/play/**).addResourceLocations(file:d:\\aaa\\);} }读取文件的时机 每次查询都应当读取一次视频文件吗 如果视频文件固定的话没必要次次读取给 Service 添加初始化方法 准备一个 MapString, Video key 使用 bv 号value 是 Video 对象 Service public class VideoService1 {PostConstruct // 这是一个初始化方法在对象创建之后只会调用一次public void init() { // 初始化try {ListString data Files.readAllLines(Path.of(data, p.csv)); // 1 ~ 7for (String line : data) {String[] s line.split(,);String[] tags s[7].split(_);Video video new Video(s[0], s[3], LocalDateTime.parse(s[6]), s[4], s[5], List.of(tags), getPlayList(s[0]), s[1], s[2]);map.put(s[0], video);}} catch (IOException e) {throw new RuntimeException(e);}}// List, Map/*1 - Video 12 - Video 2...*/MapString, Video map new HashMap();// 调用多次// 查询方法根据视频编号查询 Video 对象public Video find(String bv) {return map.get(bv);}// 读取选集文件 v_1.csvprivate ListPlay getPlayList(String bv) {try {ListString vdata Files.readAllLines(Path.of(data, v_ bv .csv));ListPlay list new ArrayList();for (String vline : vdata) {String[] ss vline.split(,);list.add(new Play(ss[0], ss[1], LocalTime.parse(ss[3]), ss[2]));}return list;} catch (IOException e) {throw new RuntimeException(e);}} }Stream API 改进 完整代码 Service public class VideoService2 {// 将一行字符串变成 Video 对象Video string2Video(String string) {String[] s string.split(,);String[] tags s[7].split(_);return new Video(s[0], s[3], LocalDateTime.parse(s[6]), s[4], s[5], List.of(tags),getPlayList(s[0]), s[1], s[2]);}// 读取 playListListPlay getPlayList(String bv) {try (StreamString data Files.lines(Path.of(data, v_ bv .csv))) {return data.map(this::string2Play).collect(Collectors.toList());} catch (IOException e) {throw new RuntimeException(e);}}// 将一行字符串变成 Play 对象Play string2Play(String string) {String[] ss string.split(,);return new Play(ss[0], ss[1], LocalTime.parse(ss[3]), ss[2]);}// Video 对象中哪部分作为 map 的 keyString key(Video video) {return video.getBv();}// Video 对象中哪部分作为 map 的 valueVideo value(Video video) {return video;}PostConstructpublic void init() {try (StreamString data Files.lines(Path.of(data, p.csv))) {map data.map(this::string2Video).collect(Collectors.toMap(this::key, this::value));} catch (IOException e) {throw new RuntimeException(e);}}MapString, Video map new HashMap();public Video find(String bv) {return map.get(bv);} }Stream API 有两套方法 第一套化整为零把聚焦点集中在每个元素上 .map() 方法需要参数个数为一返回值为一的方法this::string2Play 称之为方法引用它符合 map() 方法所需把字符串转为 Play 对象this::string2Video 也是类似的它符合 map() 方法所需把字符串转为 Video 对象 第二套化零为整把元素通过收集器收集为需要的 List 或是 Map 等 collect 作用是将元素手机为 List 或 MapCollectors.toList() 是将多个元素收集为 ListCollectors.toMap() 是将多个元素收集为 Map需要指明如何从元素Video获取 key 和 value 二. MySQL 数据库 1. 数据库必要性 读取 csv 文件的数据虽然看着也不难但要新增、修改、删除就比较麻烦了而且即便是查询我们现在这种一次性地把文件的所有行都读取也只适合数据量较小的情况下可以想象如果数据量非常庞大不说别的这种做法很容易撑爆内存。 因此我们需要一个更专业的能够对文件数据进行增删改查的软件这就是数据库。数据库有很多种这里介绍其中最为流行的数据库MySQL MySQL 相对于普通文件对数据处理的特点如下 通过 C/S 模式支持多个客户端同时访问数据库服务器对数据的增删改查操作被抽象为了 SQL 语言隐藏底层复杂性对数据的完整性、并发性、安全性都有很好的处理 并发性普通文件虽然支持两个人同时读取但如果两个人都要修改呢处理不当就会造成混乱而数据库能够保证多个人的修改操作能够有序进行 我们常说的 MySQL其实主要是指 MySQL Server将来要操作数据需要通过 MySQL Client 客户端连接至数据库服务器真正干活的是 Server客户端负责发送命令客户端可以有多个发送的命令称为 SQL 语句SQL 语句就能对数据进行增删改查 Java 代码当然也可以充当客户端同样由 Java 代码执行 SQL 语句对数据进行操作。但 SQL 语句查询到的数据并不能自动封装为 Java Bean 对象因此我们要借助一些框架来完成数据与 Java Bean 对象之间的转换操作这就是后面要学习的 MyBatis 框架它可以更方便实现数据和 Java Bean 对象之间的转换。 因此我们接下来的学习顺序是 MySQL 服务器的安装使用、SQL 语句的语法以及 MyBatis 框架 2. MySQL 安装 下载压缩包 首先到 oracle 官网 进入 MySQL 下载页面 选择软件 选择平台 下载 初始化数据库 解压缩配置 PATH 环境变量添加 MySQL解压目录\bin 到环境变量 注意 如果用 cmd那么改完环境变量只要打开新的 cmd 窗口就可以立刻生效如果用 Fluent Terminal改完之后需要注销当前用户才能生效 初始化需要执行 mysqld --initialize会生成初始数据库在 MySQL解压目录\data 目录下这时候需要查看一个名为 *.err 的文件内部含有临时密码把它记录下来如图 运行服务器 以命令行窗口方式运行服务器 mysqld --console这种方式好处是 窗口打开服务器运行窗口关闭服务器停止 还有一种方式是把 MySQL 安装为系统服务要以管理员权限启动 cmd mysqld --install net start mysql这样每次开机就会自动启动 MySQL 服务程序 运行客户端 打开一个新窗口运行客户端登录至服务器 mysql -uroot -p Enter password: 临时密码-u 之后跟的是用户名root 是 MySQL 的管理员用户-p 表示接下来要输入密码密码就是在前面步骤里让你记录的临时密码首先做的一件事应该是把临时密码改掉 alter user rootlocalhost identified by root;作用就是将本地 root 用户的密码改为 root当然改成别的密码也行改成 root 只是为了好记改完后输入 quit 退出重新登录测试是否修改正确 3. 初步使用 mysql 分成库和表库用来包含表表用来存储数据这里的表就和我们常见的二维表格类似 查看库 show databases;创建库 create database 库名;切换库 use 库名;查看表 show tables;创建表语法 create table 表名 (字段名1 类型 [约束],字段名2 类型 [约束],... );例 create table student(id int primary key,name varchar(10) );插入数据语法 insert into 表名(字段1, 字段2 ...) values (值1, 值2 ...) insert into student(id, name) values (1, 张三); insert into student(id, name) values (2, 李四); insert into student(id, name) values (3, 王五);查询数据语法 select 字段1, 字段2 ... from 表 where 条件 select id,name from student;按编号查询数据 select id,name from student where id 1;修改数据语法 update 表 set 字段1值1, 字段2值2 where 条件 update student set name张小三 where id 1;删除数据语法 delete from 表 where 条件 delete from student where id 3;4. datagrip 可以用 JetBrain 出品的 datagrip以可视化的方式管理库表 用它的意义在于界面看起来更友好一些前面讲的 insert、delete、update、select 还是需要熟练掌握 添加数据源 选择数据库的类型 配置界面 导入数据 用 datagrip 导入数据 将文件的列与数据库表的列对应起来 用 mysql 工具导入数据 导入数据服务器和客户端运行时都要添加 --local_infile1 参数 1.txt 1,张三 2,李四 4,王五用下面的语句 load data local infile 1.txt replace into table student fields terminated by , lines terminated by \r\n;5. MyBatis 入门 准备工作 pom.xml 中加入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd...dependencies...dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.2.2/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope/dependency/dependencies.../projectapplication.properties 中配置数据库连接信息 spring.datasource.urljdbc:mysql://localhost:3306/test spring.datasource.usernameroot spring.datasource.passwordrootJava Bean Java Bean 用来存数据 public class Student {private int id;private String name;public Student() {}public Student(int id, String name) {this.id id;this.name name;}public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;} }Mapper 接口 Mapper 接口用来增删改查 Mapper // 这是一个专用于增删改查的接口 // 实现类(mybatis 和 spring), 可以通过 Autowired 依赖注入获取实现类对象 public interface StudentMapper {Select(select id, namefrom student)ListStudent findAll();// 根据编号查询学生Select(select id, namefrom studentwhere id#{id})Student findById(int id); // id1,2,3...// 新增学生/*Insert(insert into student(id, name)values (#{id}, #{name}))void insert(Param(id) int i, Param(name) String n);*/Insert(insert into student(id, name)values (#{id}, #{name}))void insert(Student stu);// 修改学生Update(update student set name#{name}where id#{id})void update(Student stu);Delete(delete from student where id#{id})void delete(int id); }注意事项 Mapper 方法如果只有一个参数那么它可以不加特殊说明就与 SQL 语句中 #{} 相对应Mapper 方法如果有多个参数要使用 Param 注解将方法参数与 SQL 语句中 #{} 相对应Mapper 方法如果用 Java Bean 作为参数那么 Java Bean 的字段名与 SQL 语句中 #{} 相对应 字段是私有的本质上用的的字段对应的 public 的 get 方法获取值然后给 #{} 赋值 同一个 Mapper 接口中方法不能重名 单元测试 // 单元测试 SpringBootTest public class TestStudentMapper {AutowiredStudentMapper studentMapper;Test // 测试查询所有public void test1() {System.out.println(1);ListStudent all studentMapper.findAll();for (Student stu : all) {System.out.println(stu.getId() stu.getName());}}Test // 测试根据id查询public void test2() {System.out.println(2);Student stu studentMapper.findById(4);System.out.println(stu); // System.out.println(stu.getId() stu.getName());}Testpublic void test3() { // studentMapper.insert(5, 钱七);Student stu new Student(6, 周八);studentMapper.insert(stu);}Testpublic void test4() {Student stu new Student(1, 张小三);studentMapper.update(stu);}Testpublic void test5() {studentMapper.delete(5);}}注意事项 SpringBootTest 用来把单元测试类与 SpringBoot 整合有了它才能用 Spring 的依赖注入等功能Test 标注的方法是单元测试方法可以作为独立的运行入口要求 最好是 public无返回值方法名任意无参 单元测试的好处是每个方法都可以作为独立的测试入口互不干扰 6. 查询视频 Mapper 接口 Mapper public interface VideoMapper {// 根据 bv 号查询视频Select(select bv,type,category,title,cover,introduction,publish_time,tagsfrom videowhere bv#{bv})Video findByBv(String bv);/*数据库习惯 underscore 下划线分隔多个单词 如 publish_timeJava 习惯 驼峰命名法 camel case 如 publishTimeJava面试_求职_计算机技术_面试技巧 字符串List*/ }要在查询时执行【下划线-驼峰命名转换】需要在 application.properties 中加入配置 #...mybatis.configuration.map-underscore-to-camel-casetrueMapper public interface PlayMapper {// 查询某个视频的选集Select(select id, title, duration, urlfrom playwhere bv#{bv})ListPlay findByBv(String bv); }Java Bean Java Bean 需要添加 tags 字段以便与数据库的 tags 列相对应原本的 getTagList 方法用来把字符串转换为 ListString public class Video {// ...private String tags;public String getTags() {return tags;}public void setTags(String tags) {this.tags tags;}public ListString getTagList() {String tags this.tags; // Java面试_求职_计算机技术_面试技巧if (tags null) {return List.of();}String[] s tags.split(_);return List.of(s);}}Service /*** 从数据库中获取视频数据*/ Service public class VideoService2 {Autowiredprivate VideoMapper videoMapper;Autowiredprivate PlayMapper playMapper;// 根据 bv 号查询视频public Video find(String bv) {Video video videoMapper.findByBv(bv);if (video null) {return null;}ListPlay playList playMapper.findByBv(bv);video.setPlayList(playList);return video;} }Controller Controller public class VideoController {RequestMapping(/video/{bv})ResponseBodypublic Video t(PathVariable String bv) {return videoService2.find(bv);}Autowiredprivate VideoService2 videoService2; }7. 发布视频 原始发布功能预览 我的 B 站发布功能预览 功能1 选中 mp4 视频文件分块上传至服务器服务器在上传过程中返回进度当前分块/总分块%所有分块上传完毕后服务器合并当前文件 功能2 客户端会截取每个选集的第一帧作为候选封面单击候选封面后会将该图片上传至服务器并返回图片名 功能3 所有信息填写完毕后点击发布会将视频以及选集数据发送给服务器服务器将数据保存至数据库并返回视频的 bv 号客户端根据此 bv 号跳转 上传分块 请求/upload 路径 请求数据 i 第几块从1开始chunks 总块数data 分块数据url 视频文件名 响应数据 要一个 mapkey 是 url 视频文件名value 是上传进度以百分比表示 代码 Controller public class UploadController {Value(${video-path})private String videoPath;RequestMapping(/upload)ResponseBody// MultipartFile 专用于上传二进制数据的类型public MapString, String upload(int i, int chunks, MultipartFile data, String url)throws IOException {data.transferTo(Path.of(videoPath, url .part i));return Map.of(url, (i * 100.0 / chunks) %);}// ... }Value(“${video-path}”) 表示它标注的字段的值来自于 application.properties 配置文件 # ...video-pathd:\\aaa\\data.transferTo 作用是将上传的临时文件 MultipartFile 另存为一个新的文件 计算百分比时要先乘 100.0 这个 double 值把整个运算提升为小数运算否则整数除法算不出带小数的百分比值 spring 上传单个文件的最大值上限为 1MB要调整的话在 application.properties 中配置 # ...spring.servlet.multipart.max-file-size8MB合并分块 请求/finish 请求数据 chunks 总块数url 视频文件名 响应数据无 代码 Controller public class UploadController {RequestMapping(/finish)ResponseBodypublic void finish(int chunks, String url) throws IOException {try (FileOutputStream os new FileOutputStream(videoPath url)) {// 写入内容for (int i 1; i chunks; i) { // 1,2,3Path part Path.of(videoPath, url .part i);Files.copy(part, os);part.toFile().delete(); // 删除 part 文件}}}// ... }FileOutputStream 文件输出流它的作用是创建新文件并写入内容它会占用外部资源用完需要 closetry-with-resource 语法能够帮我们添加 finally 语句块并调用资源的 close 方法Files.copy 接收两个参数 参数一是代表原始文件的 Path 对象参数二就是代表了目标文件的文件输出流对象 上传封面 请求/uploadCover 请求数据 data 封面图片数据cover 图片名 响应数据 要一个 mapkey 固定为 cover值是图片名 代码 Controller public class UploadController {Value(${img-path})private String imgPath;RequestMapping(/uploadCover)ResponseBodypublic MapString, String uploadCover(MultipartFile data, String cover) throws IOException {data.transferTo(Path.of(imgPath, cover));return Map.of(cover, cover);}// ... }Value(“${img-path}”) 表示它标注的字段的值来自于 application.properties 配置文件 img-pathd:\\img\\发布视频 请求/publish 请求数据json {title:反射,type:自制,category:科技-计算机,cover:封面图片名.png,tags:面试_java_反射,introduction:简介...,playList: [{id:P1,title:标题1,url:视频文件名.mp4,duration:03:30},{id:P2,title:标题2,url:视频文件名.mp4,duration:03:30},{id:P3,title:标题3,url:视频文件名.mp4,duration:04:49},{id:P4,title:标题4,url:视频文件名.mp4,duration:08:19}] }响应数据 要一个 mapkey 固定为 bv值是视频 bv 号 代码 Mapper public interface VideoMapper {// ...Insert(insert into video(type, category, title, cover,introduction, publish_time, tags)VALUES (#{type}, #{category}, #{title}, #{cover},#{introduction}, #{publishTime}, #{tags}))void insert(Video video);// 获取最近生成的自增主键值Select(select last_insert_id())int lastInsertId();// 更新 bv 号Update(update video set bv#{bv} where id#{id})void updateBv(Param(bv) String bv, Param(id) int id); }PlayMapper Mapper public interface PlayMapper {// ...Insert(insert into play(id,title,duration,url,bv) values (#{p.id},#{p.title},#{p.duration},#{p.url},#{bv}))void insert(Param(p) Play play, Param(bv) String bv); }VideoService2 Service public class VideoService2 {Autowiredprivate VideoMapper videoMapper;Autowiredprivate PlayMapper playMapper;// 发布视频public String publish(Video video) {video.setPublishTime(LocalDateTime.now()); // 设置发布事件// 1. 向 video 表插入视频videoMapper.insert(video);// 2. 生成 bv 号int id videoMapper.lastInsertId();String bv Bv.get(id);// 3. 更新 bv 号videoMapper.updateBv(bv, id);// 4. 向 play 表插入所有视频选集for (Play play : video.getPlayList()) {playMapper.insert(play, bv);}return bv;}// ... }其中 bv 号使用工具方法 Bv.get(id) 提供并不是重点 VideoController Controller public class VideoController {// ...Autowiredprivate VideoService2 videoService2;RequestMapping(/publish)ResponseBodypublic MapString,String publish(RequestBody Video video) {String bv videoService2.publish(video);return Map.of(bv, bv);} }
http://www.zqtcl.cn/news/626553/

相关文章:

  • 个人备案网站沭阳哪里可以做网站
  • 环球资源网站什么时候做的搜索引擎优化名词解释
  • 名者观看网站做商城网站还要服务器
  • 网站建设课程考核方案广州 天河网站设计
  • 写作网站哪个比较赚钱小红书推广运营
  • 明年做啥网站能致富网站 公众号 建设方案
  • wordpress怎么修改网站标题做招投标应该了解的网站
  • 大庆市网站建设公司dooplay主题wordpress
  • 小学网站建设实施方案手机网站策划书方案
  • 延边网站建设国外设计公司网站欣赏
  • 团队介绍网站建设武功县住房和城乡建设局官网站
  • 如何用模板做网站爱采购官网首页
  • 网站开发存在的问题wordpress 怎么登陆后台
  • 网站建设动态部分实训报告wordpress 普通文本 quot
  • 常州微信网站建设流程本地主机做网站服务器
  • 阿里巴巴seo排名优化seo搜索引擎优化实战
  • 做班级网站的目的企点财税
  • 品牌建设网站特点有哪些企业可以做招聘的网站
  • wordpress 做网站seo全称英文怎么说
  • 宁波建网站哪家值得信赖wordpress 默认图片路径
  • 网站代运营公司天津手机版建站系统
  • 公司网站怎么做才高大上大数据营销的含义
  • 做网站点做关于什么的网站
  • 网站建设服务费税率多少汕头模板建站流程
  • 网站 建设实验小结做淘宝客优惠券网站还是APP赚钱
  • 付银行的网站建设费的会计科目网站建设前端
  • 做网站题材海南网站建设软件
  • 门户网站建设 考核从零开始学做网站cdsn
  • 百胜网站建设秀屿区建设局网站
  • 公司招聘做哪家网站建筑网站开发