ssm学习笔记day04
RequestMapping
- 首先添加依赖
- Maven的配置
测试
在controller创建HelloController,如果只加@RequestMapping,默认跳转到新页面
如果要是加上@ResponseBody就把数据封装在包(JSON),标签@RestController是前后分离的注解(因为默认用@ResponseBody)
通配符
精度:'?' > '*' > '**'
例子:
/hell?
可以匹配 /hello 、 /hella 、/hellob,不可以匹配/helloo,因为oo是多个字符
/hell*
可以匹配/hello 、 /hella、/helloo等单层结构,/hello/a不可以
/hello/**
可以匹配所有/hello子层的结构
方法限定method
现在我们限定一个POST方式的Controller
测试需要用到Postman,因为浏览器不能自主Post,然后用Postman发送一个POST
可以看到POST结果返回成功,GET就返回405
方法类型
在 RequestMethod方法上有八种方法
参数限定params
http://localhost:8080/test02?age=18&username=zhangsan&gender=0
正常返回
测试
http://localhost:8080/test02?age=17&username=zhangsan&gender=0
异常,原因是age不为18。
http://localhost:8080/test02?age=18&gender=0
异常,原因是不包含username。
http://localhost:8080/test02?age=18&gender=0&username=wangwu
正常,顺序不影响结果
http://localhost:8080/test02?age=18&gender=1&username=wangwu
异常,原因是gender为1
请求头限定headers
内容类型限定consumes、produces
MediaType的类型
用json格式返回成功
用text格式返回415异常
produces限定类型,与consumes的区别是一个是消费者、一个是生产者,consumes是客户端到服务端的类型,produces是服务端到客户端的响应类型,即响应报文
请求实战演练
1.使用普通变量收集参数
/*没有携带自动封装为null,有就自动封装*/@RequestMapping("/handle01")public String test(String username ,String password ,String cellphone ,boolean agreement){System.out.println(username + " " + password + " " + cellphone + " " + agreement);return "ok";}
发送三次请求分别为
第一次:http://localhost:8080/handle01?username=zhangsan&password=123456&cellphone=23142234
第二次:http://localhost:8080/handle01?username=zhangsan&password=123456&cellphone=23142234&agreement=on
第三次:http://localhost:8080/handle01?username=zhangsan&cellphone=23142234
2.使用RequestParam明确收集参数
使用RequestParam明确收集参数默认必须携带,否则报错
ps:不管参数是放到url?后面还是请求体,都能被RequestParam接收
/*使用RequestParam明确收集参数默认必须携带如果不携带就炸了*/@RequestMapping("/handle02")public String handle02(@RequestParam("username") String name ,@RequestParam("password") String pwd ,@RequestParam("cellphone") String phone ,@RequestParam("agreement") boolean ok){System.out.println(name + " " + pwd + " " + phone + " " + ok);return "ok";}
发送http://localhost:8080/handle02?username=zhangsan&password=32451&cellphone=2341234&agreement=on
正常
发送http://localhost:8080/handle02?username=zhangsan&password=32451&agreement=on
则报错,因为没有携带cellphone信息
@RequestMapping("/handle02")public String handle02(@RequestParam("username") String name ,@RequestParam(value = "password" , defaultValue = "123456") String pwd ,@RequestParam(value = "cellphone" ) String phone ,@RequestParam(value = "agreement" , required = false) boolean ok){System.out.println(name + " " + pwd + " " + phone + " " + ok);return "ok";}
如果属性required=false表示可以不用携带参数、default表示添加默认值,也可以不用携带参数
发送http://localhost:8080/handle02?username=zhangsan&cellphone=2341234&agreement=on
返回zhangsan 123456 2341234 true
3.使用Pojo封装所有参数
Person.java
package com.atguigu.springmvc.bean;import lombok.Data;
import lombok.ToString;@Data
@ToString
public class Person {private String username ;private String password ;private String cellphone ;private boolean agreement ;}
@RequestMapping("/handle03")public String handle03(Person person){System.out.println(person.toString());return "ok";}
4.@RequestHeader
@RequestMapping("/handle04")public String handle04(@RequestHeader("host") String host){System.out.println(host);return "ok~"+host;}
5.获取Cookie的键值对
用@CookieValue(value = “value”)获取
@RequestMapping("/handle05")public String handle05(@CookieValue("haha") String haha){return "ok" + haha;}
发送一个含有value = haha的cookie的报文
结果正常返回,然后我就好奇如果用@RequestHeader(“Cookie”)会发生什么呢,让我们开始实验
@RequestMapping("/handle05")public String handle05(@CookieValue("haha") String haha,@RequestHeader("Cookie") String ck){System.out.println(haha + " " + ck);return "ok" + haha + " " + ck;}
结果如下
6.pojo级联封装复杂对象
package com.atguigu.springmvc.bean;import lombok.Data;import java.util.Arrays;@Data
public class Person {private String username ;private String password ;private String cellphone ;private boolean agreement ;private Address address ;private String sex ;private String[] hobby;private String grade;
}
@Data
class Address {private String province;private String city ;private String area;
}
如果遇到以下这种笔记复杂的对象,可以考虑级联(嵌套)封装
ps:由于一直返回地址,不知道什么地方出了问题,然后我就手动Data,即alt + insert
快捷键生成,代码如下。
package com.atguigu.springmvc.bean;import lombok.Data;import java.util.Arrays;public class Person {private String username ;private String password ;private String cellphone ;private Boolean agreement ;private Address address ;private String sex ;private String[] hobby;private String grade;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getCellphone() {return cellphone;}public void setCellphone(String cellphone) {this.cellphone = cellphone;}public Boolean getAgreement() {return agreement;}public void setAgreement(Boolean agreement) {this.agreement = agreement;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String[] getHobby() {return hobby;}public void setHobby(String[] hobby) {this.hobby = hobby;}public String getGrade() {return grade;}public void setGrade(String grade) {this.grade = grade;}@Overridepublic String toString() {return "Person{" +"username='" + username + '\'' +", password='" + password + '\'' +", cellphone='" + cellphone + '\'' +", agreement=" + agreement +", address=" + address +", sex='" + sex + '\'' +", hobby=" + Arrays.toString(hobby) +", grade='" + grade + '\'' +'}';}
}class Address {private String province;private String city ;private String area;public String getArea() {return area;}public void setArea(String area) {this.area = area;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}@Overridepublic String toString() {return "Address{" +"area='" + area + '\'' +", province='" + province + '\'' +", city='" + city + '\'' +'}';}
}
结果正常显示
7.@RequestBody接收json字符并转换
首先编写如下代码
@RequestMapping("/handle07")public String handle07(Person person){System.out.println(person);return "ok";}
用postman发送请求
返回的结果如下
这是因为不使用 @RequestBody 注解,将无法直接接收 JSON 格式的数据,当不使用@RequestsBody的时候,Spring会处理表单数据(form-data/x-www-form-urlencoded)或者url?name=value,即键值对。
现在给它加上一个@RequestBody
@RequestMapping("/handle07")public String handle07(@RequestBody Person person){System.out.println(person);return "ok";}
8.文件上传
- 文件上传的要求
method = post , enctype = “multipart/form-data” - 代码的编写
@RequestMapping("/handle08")public String handle08(Person person,@RequestParam("headerImg") MultipartFile headerImgFile,@RequestParam("lifeImg") MultipartFile[] lifeImgFile) throws IOException {//获取原始路径String originalFilename = headerImgFile.getOriginalFilename();long size = headerImgFile.getSize();InputStream inputStream = headerImgFile.getInputStream();System.out.println(originalFilename + "=>" + size);headerImgFile.transferTo(new File("D:\\javastudy\\img\\" + originalFilename));System.out.println("头像保存结束");if(lifeImgFile.length > 0){for(MultipartFile imgFile : lifeImgFile){imgFile.transferTo(new File("D:\\javastudy\\img\\" + imgFile.getOriginalFilename()));}System.out.println("生活照保存结束");}System.out.println(person);return "ok!!!";}
用MultipartFile的接收文件,MultipartFile的源代码如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.web.multipart;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;public interface MultipartFile extends InputStreamSource {String getName();@NullableString getOriginalFilename();@NullableString getContentType();boolean isEmpty();long getSize();byte[] getBytes() throws IOException;InputStream getInputStream() throws IOException;default Resource getResource() {return new MultipartFileResource(this);}void transferTo(File dest) throws IOException, IllegalStateException;default void transferTo(Path dest) throws IOException, IllegalStateException {FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));}
}
Test:
在properties中添加以下两句话可以修改传送文件大小
9.HttpEntity获取整个请求
@RequestMapping("/handle09")public String handle09(HttpEntity<String> entity){System.out.println("请求头"+entity.getHeaders());System.out.println("请求体"+entity.getBody());return "OK~~~";}
就是Entity是请求头、请求体的总和,用HttpEntity可以获得请求头和请求体。
10.原生api HttpServletRequestRequest、HttpServletResponse
@RequestMapping("/handle10")public String handle10(HttpServletRequest request, HttpServletResponse response){//原生api,HttpServletRequestRequest和HttpServletResponse 可以参考javawebString username = request.getParameter("username");System.out.println(username);return "OK~~~";}
获取HttpMethod方法
@RequestMapping("/handle10")public String handle10(HttpServletRequest request, HttpServletResponse response, HttpMethod method){System.out.println(method);//原生api,HttpServletRequestRequest和HttpServletResponse 可以参考javawebString username = request.getParameter("username");System.out.println(username);return "OK~~~";}
小结
响应实战演练
1.返回json
不加任何注释,默认返回json
package com.atguigu.springmvc.controller;import com.atguigu.springmvc.bean.Person;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ResponseTestController {@RequestMapping("/resp01")public Person resp01() {Person person = new Person();person.setUsername("zhangsan");person.setPassword("111");person.setCellphone("1234");person.setAgreement(true);person.setSex("男");person.setHobby(new String[]{"足球","篮球"});person.setGrade("三年级");return person;}
}
核心原因:@RestController包含@ReponseBody(返回json对象)
2.文件下载
@RequestMapping("/download")public ResponseEntity<byte[]> download() throws IOException {FileInputStream inputStream = new FileInputStream("D://javastudy//img//d2d0adc1a979dc30d622b1cb1596875f.png");byte[] bytes = inputStream.readAllBytes();return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(bytes.length)//文件处理方式.header("Content-Disposition" , "attachment;filename=haha.png").body(bytes);}
首先返回值为一个响应体为字节流的响应体,理由是可以调用响应头的文件类型,然后开始把自己想传输的文件整成一个文件流,然后在ResponseEnitity中配置整个响应的信息。
ps:ResponseEntity.ok()/contentType返回的都是ResponseEntity类,所以顺序先后不影响 , APPLICATION_OCTET_STREAM是八进制流文件。