我按照本教程https://www.knowledgefactory.net/2021/09/spring-boot-webflux-video-streaming.html创建了一个视频流应用程序。 resources 文件夹内有一个子文件夹,里面有两个 MP4 文件。 当我在下一堂课中点击 getVideo 时,问题发生了:
package net.javaguides.springboot.implementations;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class StreamingService {
private static final String FORMAT = "classpath:videos/%s.mp4";
private ResourceLoader resourceLoader;
public Mono<Resource> getVideo(String title) {
return Mono.fromSupplier(() -> resourceLoader.getResource(String.format(FORMAT, title)));
}
}
控制器使用如下配置bean:
package net.javaguides.springboot.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import net.javaguides.springboot.implementations.StreamingService;
import reactor.core.publisher.Mono;
@Configuration
public class EndPointConfig {
@Autowired
private StreamingService service;
@Bean
public RouterFunction<ServerResponse> router() {
return RouterFunctions.route().GET("video/{title}", this::videoHandler).build();
}
private Mono<ServerResponse> videoHandler(ServerRequest serverRequest) {
String title = serverRequest.pathVariable("title");
return ServerResponse.ok().contentType(MediaType.valueOf("video/mp4")).body(service.getVideo(title),
Resource.class);
}
}
检索视频流的控制器端点如下:
@Controller
@AllArgsConstructor
public class VideoController {
private StreamingService streamingService;
@GetMapping(value = "video/{title}", produces = "video/mp4")
@ResponseBody
public Mono<Resource> getVideos(@PathVariable String title, @RequestHeader("Range") String range) {
System.out.println("Range in bytes = " + range);
return streamingService.getVideo(title);
}
@GetMapping("show")
public String show() {
return "video";
}
}
最后,应用程序有一个 html 文件,其中有一个 video 标签,其 src 属性指向控制器的 show 方法来显示播放器,如下所示:
<!DOCTYPE html>
<html
lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout_navigation.html}">
<head>
<meta charset="UTF-8">
<title>OBR-VIDEOTHEQUE</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="styles.css"> -->
<style type="text/css">
#video-player {
display: none;
}
#video-form {
width: 60%;
}
.error {
color: red;
}
.success {
color: green;
}
</style>
</head>
<body>
<section layout:fragment="content">
<meta charset="utf-8">
<div class="container mt-5">
<h2>Video streaming</h2>
<video src="video/movie" type="video/mp4" width="720" height="480" controls preload="none">
</video>
</div>
</section>
<section layout:fragment="footer">
<footer class="container py-5 text-center footer">
<div class="row">
<div class="col-md-12">
<p class="text-muted">© 2022. Tous
droits réservés.</p>
</div>
</div>
</footer>
</section>
<section layout:fragment="scripts">
<script th:src="@{/js/jQuery-min.js}"></script>
<script
type="text/javascript"
th:src="@{/js/dropdown.js}"></script>
<script th:src="@{/js/bootstrap.bundle.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/js/select2.min.js}"></script>
<!-- <script th:src="@{/js/main.js}"></script> -->
</section>
</body>
</html>
运行应用程序后,在网址中输入
http://localhost:8082/show
从该网址,视频播放器就会出现。当我点击播放按钮时,我收到 500 Error 消息:
java.lang.NullPointerException: null
at net.javaguides.springboot.implementations.StreamingService.lambda$0(StreamingService.java:17)
这是我尝试找出错误所在的第三天,但没有成功。 有人可以告诉我哪里出了问题吗?
您有一个未初始化的
ResourceLoader
。
更改这行代码
private ResourceLoader resourceLoader;
在这些中:
@Autowired
private ResourceLoader resourceLoader;
这将告诉 Spring Context 在您的属性中注入 ResourceLoader 的实例。