请求报文转换
HttpMessageConverter 将请求报文转换为Java对象,或将Java对象转换为响应报文2个注解和2个类型
@RequestBody,@ResponseBody
RequestEntity,ResponseEntity
RequestEntity
org.springframework.http.RequestEntity:表示完整的请求报文(用的少,几乎不用)
该类型用于获取完整的请求报文,一般用在控制器方法的形参位置,不用是因为,都有更方便的方式来获取
- 其中getHeaders()获取请求报文的请求头信息
- 其中getBody()获取请求报文的请求体信息
public String testRequestEntity(RequestEntity<String> entity){
//获取请求报文的请求头信息
HttpHeaders httpHeaders = entity.getHeaders();
//)获取请求报文的请求体信息
String body = entity.getBody();
return "success";
}
@RequestBody
@RequestBody 将请求体和形参绑定,可以自动将json格式的请求体转换为java对象
post请求体中存储的数据有两种:
1. name=value&name=value:直接通过控制器方法形参就可以获取
2. json格式的请求参数 {key:value,key:value}:不能直接通过控制器方法的形参获取
对于json格式的请求参数,通过@RequestBody注解标识的控制器方法的形参直接将json格式的请求参数转换为java对象
但是要满足三个条件:
* a>导入jackson的依赖
springmvc默认使用jackson处理json
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
* b>SpringMVC的配置文件中设置开启mvc的注解驱动,才有jackson相关的处理器
会在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串
<mvc:annotation-driven />
* c>在控制器方法的形参位置,设置json格式的请求参数要转换成的java类型(实体类或map)的参数,并使用@RequestBody注解标识
下面这种方式,是能获取请求体中的json字符串,但是没啥卵用
@RequestMapping("/test/requestBody")
public String testRequestBody(@RequestBody String body){
System.out.println(body);
return "success";
}
@RequestBody后边一般跟的是实体类对象或者map集合
@RequestMapping("/test/json/requestBody")
@ResponseBody
public String testRequestBody(@RequestBody Map<String, Object> map) throws IOException {
System.out.println(map);
return "hello,axios";
}
//有实体类则用实体类
public void testRequestBody(@RequestBody User user, HttpServletResponse response) throws IOException {
System.out.println(user);
response.getWriter().print("hello,axios");
}
<input type="button" value="测试@RequestBody获取json格式的请求参数" @click="testRequestBody()"><br>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
testRequestBody(){
axios.post("/maven_springmvc/test/json/requestBody",
{username:"admin",password:"123456"}).then(response=>{
console.log(response.data);
});
},
}
});
</script>
测试结果:
响应报文转换
ResponseEntity
ResponseEntity 设置响应到浏览器的响应报文
ResponseEntity类型用在控制器方法的返回值,返回的ResponseEntity就是响应到浏览器的响应报文。用的最多的地方就是文件下载。
new ResponseEntity(响应体,响应头,响应状态码);
@RequestMapping("/download")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("picture");
//D:\workspaces\maven_springmvc\target\maven_springmvc-1.0-SNAPSHOT\picture
realPath = realPath + File.separator + "guanxiaotong.jpg";
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组,is.available()获取字节输入流所对应文件所有的字节数
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=guanxiaotong.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
MultiValueMap 可以用来获取请求头,也可以用来设置响应头
attachment:以附件方式下载
文件下载:文件由服务器复制到浏览器
ResponseEntity<byte[]> 泛型指响应体的类型,字节数组
文件下载
Content-Disposition
@ResponseBody
@ResponseBody可以将标注方法的返回值直接作为响应报文的响应体响应到浏览器
若需要响应到浏览器一个json格式的数据,此时要满足三个条件:
a>导入jackson的依赖(同上)
b>SpringMVC的配置文件中设置开启mvc的注解驱动(同上)
c>在控制器方法上,使用@ResponseBody注解进行标识
@ResponseBody测试一:
返回一个字符串
不加该注解
@RequestMapping("/test/responseBody") public String testResponseBody(){ return "success"; }
意思是跳转到"success.html"页面
--------
加了@ResponseBody注解之后
@RequestMapping("/test/responseBody") @ResponseBody public String testResponseBody(){ return "success"; }
意思是给浏览器回写数据
@ResponseBody测试二:
返回一个java对象
方法可以返回值为void,也能给浏览器回写数据。用response的输入流
public void testRequestBody(@RequestBody User user, HttpServletResponse response) throws IOException { System.out.println(user); response.getWriter().print("hello,axios"); }
使用@ResponseBody:在控制器方法中,只需要将要转换为json的java对象作为方法的返回值,就会自动转换为json字符串,并响应到浏览器
@RequestMapping("/test/responseBody") @ResponseBody public Employee testResponseBody(@RequestBody Employee employee){ System.out.println(employee); return employee; }
@ResponseBody将该对象以json格式返回给了浏览器,打印显示在浏览器控制台如下:
上面方法倘若不加@ResponseBody注解,则响应的是Employee对象的内存地址或者是重写toString后的内容。
@ResponseBody测试三:
返回一个List集合
list集合,响应给浏览器在浏览器控制台打印的就是json数组
@RequestMapping("/test/responseBody") @ResponseBody public List<Employee> testResponseBody(@RequestBody Employee employee){ Employee e1 = new Employee(1001,"狂野猩","123456",23); Employee e2 = new Employee(1002,"猛虎王","123456",23); Employee e3 = new Employee(1003,"暴龙神","123456",23); List<Employee> list = Arrays.asList(e1, e2, e3); System.out.println(employee); return list; }
@RestController
复合注解@RestController
就相当于为类添加了@Controller注解,并且为类中的每个方法添加了@ResponseBody注解
文件上传
poi:通过java代码操作办公软件
文件上传的步骤:
1、导入commons-fileupload的依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2、在SpringMVC的配置文件“springMVC.xml”中设置文件上传解析器,BeanId是固定的,且必须设置。MultipartResolver是接口,得用它的实现类
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
3、在页面中设置form表单,表单中设置文件域并且form的提交方式必须为post,form中必须设置属性enctype="multipart/form-data",表示以二进制传输数据,默认是name=value&name=value
<form th:action="@{/up}" method="post" enctype="multipart/form-data">
头像:<input type="file" name="photo"><input type="submit" value="上传">
</form>
页面效果:
4、可以在控制器方法的形参位置,获取封装了上传的文件封装的MultipartFile对象,通过此对象可以获取文件相关信息
MultipartFile 封装了请求数据中的文件,此时这个文件存储在内存中或临时的磁盘文件中,需要将其转存到一个合适的位置,因为请求结束后临时存储将被清空。在 MultipartFile 接口中有如下方法:
- String getName(); // 获取参数的名称
- String getOriginalFilename(); // 获取文件的原名称
- String getContentType(); // 文件内容的类型
- boolean isEmpty(); // 文件是否为空
- long getSize(); // 文件大小
- byte[] getBytes(); // 将文件内容以字节数组的形式返回
- InputStream getInputStream(); // 将文件内容以输入流的形式返回
- void transferTo(File dest); // 将文件内容传输到指定文件中
- 看着这么多代码,实际上都是为了给transferTo()方法传参的。
- 往哪上传:以后会上传到七牛云或者文件服务器,但是现在只能传到部署路径。
- 写到某个文件中,而不是写到某一个目录中。
- MultipartFile是SpringMVC封装上传文件的类型
@RequestMapping("/up") public String testUp(MultipartFile photo, HttpSession session) throws IOException { //获取ServletContext ServletContext servletContext = session.getServletContext(); //获取当前web应用的真实路径 String photoPath = servletContext.getRealPath("photo"); //获取服务器中photo目录所对应的文件 File file = new File(photoPath); //判断file所对应的目录是否存在,若不存在则创建 if(!file.exists()){ file.mkdir(); } //获取上传的文件的文件名 String fileName = photo.getOriginalFilename(); //获取随机序列UUID String uuid = UUID.randomUUID().toString(); //获取上传的文件的后缀名 String hzName = fileName.substring(fileName.lastIndexOf(".")); //获取新的文件名 fileName = uuid + hzName; //获取上传文件的最终位置 String finalPath = photoPath + File.separator + fileName; //上传文件 photo.transferTo(new File(finalPath)); return "success"; }
上传成功:
这个UUID就很灵性: