假设在电脑的磁盘D盘根目录有一个图片文件叫doge.jpg,现在要通过本地服务接口把文件上传,控制器的代码如下:
@PostMapping(value = "/file1") public String file1(@RequestPart(name = "file1") MultipartFile multipartFile) { String content = String.format("name = %s,originName = %s,size = %d", multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getSize()); log.info(content); return content; }控制台输出是:
name = file1,originName = doge.jpg,size = 68727可能有点疑惑,参数是怎么来的,我们可以用Fildder软件抓个包看下:
可知MultipartFile实例的主要属性分别来自Content-Disposition、Content-Type和Content-Length,另外,InputStream用于读取请求体的最后部分(文件的字节序列)。参数处理器用到的是RequestPartMethodArgumentResolver(记住一点,使用了@RequestPart和MultipartFile一定是使用此参数处理器)。在其他情况下,使用@RequestParam和MultipartFile或者仅仅使用MultipartFile(参数的名字必须和POST表单中的Content-Disposition描述的name一致)也可以接收上传的文件数据,主要是通过RequestParamMethodArgumentResolver进行解析处理的,它的功能比较强大,具体可以看其supportsParameter方法,这两种情况的控制器方法代码如下:
@PostMapping(value = "/file2") public String file2(MultipartFile file1) { String content = String.format("name = %s,originName = %s,size = %d", file1.getName(), file1.getOriginalFilename(), file1.getSize()); log.info(content); return content; } @PostMapping(value = "/file3") public String file3(@RequestParam(name = "file1") MultipartFile multipartFile) { String content = String.format("name = %s,originName = %s,size = %d", multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getSize()); log.info(content); return content; } 其他参数其他参数主要包括请求头、Cookie、Model、Map等相关参数,还有一些并不是很常用或者一些相对原生的属性值获取(例如HttpServletRequest、HttpServletResponse或者它们内置的实例方法等)不做讨论。
请求头请求头的值主要通过@RequestHeader注解的参数获取,参数处理器是RequestHeaderMethodArgumentResolver,需要在注解中指定请求头的Key。简单实用如下:
控制器方法代码:
@PostMapping(value = "/header") public String header(@RequestHeader(name = "Content-Type") String contentType) { return contentType; } CookieCookie的值主要通过@CookieValue注解的参数获取,参数处理器为ServletCookieValueMethodArgumentResolver,需要在注解中指定Cookie的Key。控制器方法代码如下:
@PostMapping(value = "/cookie") public String cookie(@CookieValue(name = "JSESSIONID") String sessionId) { return sessionId; } Model类型参数Model类型参数的处理器是ModelMethodProcessor,实际上处理此参数是直接返回ModelAndViewContainer实例中的Model(具体是ModelMap类型),因为要桥接不同的接口和类的功能,因此回调的实例是BindingAwareModelMap类型,此类型继承自ModelMap同时实现了Model接口。举个例子:
@GetMapping(value = "/model") public String model(Model model, ModelMap modelMap) { log.info("{}", model == modelMap); return "success"; }注意调用此接口,控制台输出INFO日志内容为:true。还要注意一点:ModelMap或者Model中添加的属性项会附加到HttpRequestServlet实例中带到页面中进行渲染,使用模板引擎的前提下可以直接在模板文件内容中直接使用占位符提取这些属性值。
@ModelAttribute参数@ModelAttribute注解处理的参数处理器为ModelAttributeMethodProcessor,@ModelAttribute的功能源码的注释如下:
Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view.
简单来说,就是通过key-value形式绑定方法参数或者方法返回值到Model(Map)中,区别下面三种情况:
@ModelAttribute使用在方法(返回值)上,方法没有返回值(void类型), Model(Map)参数需要自行设置。
@ModelAttribute使用在方法(返回值)上,方法有返回值(非void类型),返回值会添加到Model(Map)参数,key由@ModelAttribute的value指定,否则会使用返回值类型字符串(首写字母变为小写,如返回值类型为Integer,则key为integer)。
@ModelAttribute使用在方法参数中,则可以获取同一个控制器中的已经设置的@ModelAttribute对应的值。