遇到的第一个难题:文件上传
问题一:无法读到文件内容
Javabean也配置了,前端也设置了content-type,后端也试了好几种注解方式……(参考网上各种示例),参考的github代码avinashbabudonthu/SpringBootFileUpload可以运行,正确的数据格式如下:
![http request](https://github.com/SherryLang/javalearning/blob/master/issueImages/http-request.png?raw=true)
对照发现自己前端发的数据格式并没有问题,但是后端的接口中一直读不到文件的数据(file=null)……
![fileupload-FILE=NULL](https://github.com/SherryLang/javalearning/blob/master/issueImages/fileupload-FILE=NULL.png?raw=true)
于是找后端的接口问题,重建controller也没搞定,于是在师父指导下查找对照环境配置,发现application.properties中有两个变量没有加,分别是:
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=10MB
同时删除之前从网上copy的config文件,代码如下:
package com.hikvision.rensu.cert.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@Configuration
public class FileUploadConfig {
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setResolveLazily(true);
resolver.setMaxInMemorySize(40960);
resolver.setMaxUploadSize(50*1024*1024);
return resolver;
}
}
操作之后就读到文件了。之前带文件的http请求肯定是因为不符合某些条件被拦截了。
后来发现单独删除config文件就可以搞定,和application.properties中的配置无关(不过还是加上比较好,毕竟对文件大小限制了一下更加可靠咯。
问题二:返回数据格式错误415
然而还没结束。使用前后端分离架构之后,函数返回的字符串是对了(“file upload success”),但是前端依旧是报错415。
error:"Unsupported Media Type"
exception:"org.springframework.web.HttpMediaTypeNotSupportedException"
message:"Content type 'multipart/form-data;boundary=----WebKitFormBoundaryXmBj0U01YEMQfmml;charset=UTF-8' not supported"
path:"/inspections/save.do"
status:415
timestamp:1495022474079
后端的整个过程都正常,返回String对象也很合理,肯定是不符合前端处理的数据格式,看了一下以前工程的代码,是包装成Json数据返回,于是找办法包装成Json对象。
查了半天,还是segmentfault的一个帖子解决了我的问题,兴奋!
在你的Controller上加上@RestController注解就行了,springboot会自动帮你转换为json;
用上述方法,整个controller里都会返回Json,在方法上加上@responsebody,就只有方法返回Json对象
想起以前做前端的时候,接口中写上@responsebody的,都是以Json数据返回,这次问题解决之后真是印象深刻了。
后续问题
如何包装Json数据,加入status状态码、错误信息等内容?
自定义返回结果类,继承Json对象?
常见注解 @RequestMapping
, @RequestParam
, @RequestBody
另外,几个controller中的注解作用如下:
@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性,下面分成三类进行说明:
1. value, method
value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
2. consumes,produces
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3. params,headers
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@RequestParam
这个注解用来绑定单个请求数据,既可以是url中的参数,也可以是表单提交的参数和上传的文件
它有三个属性,value用于设置参数名,defaultValue用于对参数设置默认值,required为true时,如果参数为空,会报错
springMVC默认根据参数名字来绑定,而不是参数位置
使用包装类型,否则如果不传值,会报错
使用@RequestParam(value="")来改变参数名字
使用@RequestParam(defaultValue=""),不传参时,使用默认值
使用@RequestParam(required=true),强制必须传参数
示例:
@RequestMapping(value = "/hello1.htm")
public String hello1(ModelMap modelMap,Integer param1, int param2) {
modelMap.addAttribute("param1", param1);
modelMap.addAttribute("param2", param2);
return "hello";
}
请求为:http://localhost:8080/hello1.htm?param1=1¶m2=2
如果页面上表单里的参数和代码里的参数名不一样,用注解@RequestParam:
@RequestMapping(value = "/hello1.htm")
public String hello1(ModelMap modelMap, @RequestParam(value = "paramTest") Integer param1, Integer param2) {
modelMap.addAttribute("param1", param1);
modelMap.addAttribute("param2", param2);
return "hello";
}
@RequestBody
该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;
它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。
示例代码
// JS代码
var cartId = 1;
$.ajax({
url: ctx + '/management/cart/delete',
async: false,
cache: false,
type: "POST",
contentType: "application/json",
data: cartId,
success: function (data) { },
error: function (xhr) { }
});
// Java代码
@ResponseBody
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public int delete(@RequestBody Integer id) {
return 0;
}
@RequestBody 接收的是一个Json对象的字符串,而不是一个Json对象。 然而在ajax请求往往传的都是Json对象,后来发现用 JSON.stringify(data)的方式就能将对象变成字符串。同时ajax请求的时候也要指定contentType:"application/json"
这样就可以轻易的将一个对象或者List传到Java端,使用@RequestBody即可绑定对象或者List.
var params = [1,2,3];
$.ajax({
url: ctx + '/management/cart/delete',
async: false,
cache: false,
type: "POST",
contentType: "application/json",
data: JSON.stringify(params),
success: function (data) { },
error: function (xhr) { }
});
@ResponseBody
@RequestMapping(value = "/deletes", method = RequestMethod.POST)
public int deletes(@RequestBody List<Integer> ids) {
return 0;
}
参考资料:
http://www.cnblogs.com/samwang88/p/6598919.html
http://blog.csdn.net/walkerjong/article/details/7946109
http://blog.csdn.net/u010412719/article/details/69710480
http://www.cnblogs.com/nicekk/p/6072130.html