目录
一、处理JSON
1、加入jackson的jar
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
2、添加@ResponseBody注解,返回集合对象。
@ResponseBody
@RequestMapping("/testJson")
public List<User> testJson() {
List<User> list = new ArrayList<>();
list.add(new User(1, "Tom", "123456", "tom@atguigu.com", 13));
list.add(new User(2, "Jaer", "123456", "tom@atguigu.com", 11));
list.add(new User(3, "Nitty", "123456", "tom@atguigu.com", 12));
return list;
}
3、返回数据:
二、HttpMessageConverter<T>
HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息。
HttpMessageConverter<T>接口定义的方法:
- Boolean canRead(Class<?> clazz,MediaType mediaType): 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
- Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。
- LIst<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。
- T read(Class<? extends T> clazz,HttpInputMessage inputMessage):将请求信息流转换为 T 类型的对象。
- void write(T t,MediaType contnetType,HttpOutputMessage outputMessage):将T类型的对象写到响应流中,同时指定相应的媒体类型为 contentType。
1、源码解析装配Converters
查看DispatcherServlet的doDispatch方法,找到handlerAdapters属性,展开找到RequestMappingHandlerAdapter,找到其中的messageConverters,查看装配的Converters:
加入 jackson jar 包后, HttpMessageConverter装配的增加第六个Converter。
2、使用 HttpMessageConverter<T>
使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
- – 使用 @RequestBody / @ResponseBody 对处理方法进行标注
- – 使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值
当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的
HttpMessageConverter 将报错
@RequestBody 和 @ResponseBody 不需要成对出现
1、@RequestBody、@ResponseBody示例,实现文件上传效果:
@ResponseBody
@RequestMapping("/testHttpMessageConverter")
public String testHttpMessageConverter(@RequestBody String body){
System.out.println(body);
return "helloworld! " + new Date();
}
<form action="testHttpMessageConverter" method="POST" enctype="multipart/form-data">
File: <input type="file" name="file"/>
Desc: <input type="text" name="desc"/>
<input type="submit" value="Submit"/>
</form>
2、ResponseEntity实现文件下载效果:
@RequestMapping("/testResponseEntity")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{
byte [] body = null;
ServletContext servletContext = session.getServletContext();
InputStream in = servletContext.getResourceAsStream("/files/abc.txt");
body = new byte[in.available()];
in.read(body);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename=abc.txt");
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);
return response;
}
<a href="testResponseEntity">Test ResponseEntity</a>
三、文件上传下载
1、环境配置
加入支持的jar:
<!-- 文件上传下载 -->
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
配置MultipartFile
<!-- 配置文件上传下载 MultipartResolver -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为1024 -->
<property name="maxInMemorySize" value="4096"></property>
<!-- 设定文件上传的最大值为10MB,10*1024*1024 -->
<property name="maxUploadSize" value="10485760000"></property>
<!-- 延迟文件解析,懒加载,当调用DefaultMultipartHttpServletRequest的getMultipartFiles()方法时才解析请求数据-->
<property name="resolveLazily" value="true"></property>
<!-- 上传文件的临时路径 -->
<property name="uploadTempDir" value="files/"></property>
</bean>
2、上传单个文件
页面代码:
<form action="SpringMVC/testFileUpload" method="POST" enctype="multipart/form-data">
File: <input type="file" name="file"/>
Desc: <input type="text" name="desc"/>
<input type="submit" value="testFileUpload"/>
</form>
后台:
@RequestMapping("/testFileUpload")
public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file") MultipartFile file)
throws IOException {
if (!file.isEmpty()) {
/*
* MultipartFile 常用方法
*/
// 获取参数的名称
String name = file.getName();
// 获取文件的原名称
String originalFilename = file.getOriginalFilename();
// 文件内容的类型
String contentType = file.getContentType();
// 文件是否为空
boolean empty = file.isEmpty();
// 文件大小
long size = file.getSize();
// 将文件内容以字节数组的形式返回
byte[] bytes = file.getBytes();
// 将文件内容以输入流的形式返回
InputStream inputStream = file.getInputStream();
System.out.println(name + "\n" + originalFilename + "\n" + contentType + "\n" + empty + "\n" + size + "\n"
+ inputStream);
/*
* 存放上传的文件
*/
String path = "D:/temp/";
String fileName = file.getOriginalFilename();
File temp = new File(path, fileName);
file.transferTo(temp);
}
return "success";
}
3、上传多个文件
页面代码:
<form method="POST" action="SpringMVC/testFileUpload2" enctype="multipart/form-data">
File1: <input type="file" name="files"/><br/>
File2: <input type="file" name="files"/><br/>
Desc: <input type="text" name="desc"/>
<input type="submit" value="testFileUpload2"/>
</form>
后台:
@RequestMapping("/testFileUpload2")
public String testFileUpload2(@RequestParam("desc") String desc, @RequestParam("files") MultipartFile[] files)
throws IOException {
String path = "D:/temp/";
// 判断file数组不能为空并且长度大于0
if (files != null && files.length > 0) {
// 循环获取file数组中得文件
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
// 保存文件
String fileName = file.getOriginalFilename();
File temp = new File(path, fileName);
file.transferTo(temp);
}
}
return "success";
}
4、下载
1、方式一:
@RequestMapping("/testFileDownload")
public ResponseEntity<byte[]> downloadResumeFile() throws Exception {
// 下载文件名称
String fileName = "新建文本文档.txt";
// 下载文件路径
String realPath = "D:/temp";
File file = new File(realPath + File.separator + fileName);
InputStream in = new FileInputStream(file);// 将该文件加入到输入流之中
byte[] body = null;
// 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数
body = new byte[in.available()];
// 读入到输入流里面
in.read(body);
// 下载显示的文件名,解决中文名称乱码问题
fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
HttpHeaders headers = new HttpHeaders();
// 设置响应头// 通知浏览器以attachment(下载方式)打开图片
headers.add("Content-Disposition", "attachment;filename=" + fileName);
HttpStatus statusCode = HttpStatus.OK;// 设置响应吗
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(body, headers, statusCode);
return responseEntity;
}
2、方式二:
@RequestMapping(value = "/download")
public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename,
Model model) throws Exception {
// 下载文件路径
String path = request.getServletContext().getRealPath("/images/");
File file = new File(path + File.separator + filename);
HttpHeaders headers = new HttpHeaders();
// 下载显示的文件名,解决中文名称乱码问题
String downloadFielName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
// 通知浏览器以attachment(下载方式)打开图片
headers.setContentDispositionFormData("attachment", downloadFielName);
// application/octet-stream : 二进制流数据(最常见的文件下载)。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}