Coming from .NET and Node I really have a hard time to figure out how to transfer this blocking MVC controller to a non-blocking WebFlux annotated controller? I've understood the concepts, but fail to find the proper async Java IO method (which I would expect to return a Flux or Mono).
@RestController
@RequestMapping("/files")
public class FileController {
@GetMapping("/{fileName}")
public void getFile(@PathVariable String fileName, HttpServletResponse response) {
try {
File file = new File(fileName);
InputStream in = new java.io.FileInputStream(file);
FileCopyUtils.copy(in, response.getOutputStream());
response.flushBuffer();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
There are several reasons for this: Spring MVC can't run on Netty. both infrastructure will compete for the same job (for example, serving static resources, the mappings, etc) mixing both runtime models within the same container is not a good idea and is likely to perform badly or just not work at all.
Running the Spring WebFlux Spring Boot App If you have Spring support in Eclipse, then you can run above class as Spring Boot App. If you like to use command line, then open terminal and run command mvn spring-boot:run from the project source directory.
Overview. Spring 5 includes Spring WebFlux, which provides reactive programming support for web applications. In this tutorial, we'll create a small reactive REST application using the reactive web components RestController and WebClient. We'll also look at how to secure our reactive endpoints using Spring Security.
First, the way to achieve that with Spring MVC should look more like this:
@RestController
@RequestMapping("/files")
public class FileController {
@GetMapping("/{fileName}")
public Resource getFile(@PathVariable String fileName) {
Resource resource = new FileSystemResource(fileName);
return resource;
}
}
Also, not that if you just server those resources without additional logic, you can use Spring MVC's static resource support. With Spring Boot, spring.resources.static-locations
can help you customize the locations.
Now, with Spring WebFlux, you can also configure the same spring.resources.static-locations
configuration property to serve static resources.
The WebFlux version of that looks exactly the same. If you need to perform some logic involving some I/O, you can return a Mono<Resource>
instead of a Resource
directly, like this:
@RestController
@RequestMapping("/files")
public class FileController {
@GetMapping("/{fileName}")
public Mono<Resource> getFile(@PathVariable String fileName) {
return fileRepository.findByName(fileName)
.map(name -> new FileSystemResource(name));
}
}
Note that with WebFlux, if the returned Resource
is actually a file on disk, we will leverage a zero-copy mechanism that will make things more efficient.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With