背景
最近在学习Spring Boot,跟着官方demo学习还是会遇到不少坑,写个文章记录下,以便日后查阅。
核心功能
使用@Controller注解声明接受请求,调用@Autowired自动注入的servcie来保存上传的文件,同时提供文件下载功能。
使用thymeleaf模板来处理html页面请求。
用@ConfigurationProperties注解来声明属性,配置文件存放目录。
核心代码
控制层
在控制器中@Controller注解来表明这是一个控制层bean,可以接受http请求;
使用@Autowired注解来自动注入service类,用来执行对文件的操作;
分别使用@GetMapping和@PostMapping来接受GET、POST方法;
通过 return "uploadForm"; 的样子,交给模板引擎thymeleaf去处理,返回template目录下的uploadForm.html文件,并“注入”响应的属性 如files、message等。
@Controller // 控制器注解
public class FileUploadController {
private final StorageService storageService; // 下面自动注入
@Autowired
public FileUploadController(StorageService storageService) {
this.storageService = storageService;
}
@GetMapping("/")
public String listUploadedFiles(Model model) throws IOException {
model.addAttribute("files", storageService.loadAll().map(
path -> MvcUriComponentsBuilder.fromMethodName(FileUploadController.class,
"serveFile", path.getFileName().toString()).build().toString())
.collect(Collectors.toList()));
return "uploadForm"; // 由模板引擎负责返回 uploadForm.html,在template目录下。
}
@GetMapping("/files/{filename:.+}") // 下载文件
@ResponseBody
public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
Resource file = storageService.loadAsResource(filename);
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getFilename() + "\"").body(file);
}
@PostMapping("/")
public String handleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
storageService.store(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/"; // 跳转到 get的请求里(上面的listUploadedFiles方法)
}
}
服务层
这个类主要用来执行一些文件处理操作,没什么特殊的,
比较坑的是,因为用到配置属性,仅仅用Autowired来注入还是不行的, 还必须使用 @EnableConfigurationProperties(StorageProperties.class) 来声明配置属性类,这个比较坑。。
@Service //声明service
@EnableConfigurationProperties(StorageProperties.class) // 允许使用配置注解
public class FileSystemStorageService implements StorageService {
private final Path rootLocation;
@Autowired // 自动注入
public FileSystemStorageService(StorageProperties properties) {
this.rootLocation = Paths.get(properties.getLocation());
}
属性配置
使用@ConfigurationProperties声明这是一个属性配置类,参数声明顶级命名空间。
比较坑的是, 需要在pom.xml里引入以下依赖:
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional> true </optional>
</dependency>
然后就可以正常使用了。。。
@ConfigurationProperties("storage")
public class StorageProperties {
/**
* Folder location for storing files
*/
private String location = "upload-dir";
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
以上配置完成后,可以在application.properties 文件里添加 storage.location = myFiles
来指明文件存储路径。。。
其它坑
在学习的过程中可能会出现 “Re-run spring boot configuration annotation”的错误,这个就是因为在service中只用Autowired去自动注入了,而没有使用 EnableConfigurationProperties 去声明属性配置类。 像上面说的一样声明就可以正常运行了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。