请求&&响应知识点
json概念
常见的json框架
- fastjson ==》 alibaba的产品
- Gson==》谷歌的产品
前端角度
//json语法格式
{
"名字":"值",
"名字":"值",
}
//例子
var stu={
"name":"张三",
"age":18,
"pet"//宠物:{
"name":"小黄",
"type":狗,
},
"hobbeies":["抽烟","喝酒","烫头"],
"girlFGriends":[
{"name":"如花","age":88}
]
}
字符串和对象的转换
<body>
<script>
//json和jason字符串
//var person = {"bane":"tin"} 这个person是对象
//var person = '{"bane":"tin"}' 这个person是字符串
var person = {"bane":"tin"}
var jsonStr=JSON.stringify(person) //对象转字符串
alert(jsonStr)
/* var person1 = '{"bane":"tin"}' //字符串转成对象
var jsonObj = JSON.parse(person1)
alert(jsonObj) */
</script>
</body>
</html>
后端角度
json对象:不存在
java对象,存在
java如何处理我们的json格式的字符串
- 把json字符串转换成java对象
- 把java对象转换成json字符串
==》新的框架jackson
对象和字符串的转换使用的技术是Jackson框架
Jackson
Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架
早期框架SpringMVC==》表现型框架(web层)==》这个框架默认处理json使用的就是jackson
对象转JSON格式字符串的转换
将对象转换为json格式的字符串
public class JackSonTest {//转换为json格式的字符串
@Test
public void testJackSonTest() throws Exception{
ArrayList<String > hobbies = new ArrayList<>();
hobbies.add("抽烟");
hobbies.add("喝酒");
hobbies.add("烫头");
Student student = new Student();
student.setSid(2);
student.setStuName("张三");
student.setGender(1);
student.setAddress("xxxxxx");
student.setHobbies(hobbies);
//初始化转换json对象
ObjectMapper objectMapper = new ObjectMapper();
//将对象转换成为json格式的字符串
String s = objectMapper.writeValueAsString(student);
System.out.println(s);
//将集合转换为json格式的字符串
System.out.println("===============================");
String s1 = objectMapper.writeValueAsString(hobbies);
System.out.println(s1);
}
}
回显内容如下;
{"sid":2,"stuName":"张三","address":"xxxxxx","gender":1,"hobbies":["抽烟","喝酒","烫头"]}
===============================
["抽烟","喝酒","烫头"]
将集合转换为json格式的字符串
public class JackSonTest {//转换为json格式的字符串
@Test
public void testJackSonTest() throws Exception{
ArrayList<String > hobbies = new ArrayList<>();
hobbies.add("抽烟");
hobbies.add("喝酒");
hobbies.add("烫头");
ObjectMapper objectMapper = new ObjectMapper();
//将集合转换为json格式的字符串
String s1 = objectMapper.writeValueAsString(hobbies);
System.out.println(s1);
}
}
回显内容
["抽烟","喝酒","烫头"]
Map集合转换为json格式字符串
public void testMap()throws Exception{
HashMap<Object, Object> map = new HashMap<>();
map.put("username","zhangsan");
map.put("password","123123");
map.put("status",1);
map.put("creaTime", new Date());
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(map);
System.out.println(s);
}
运行结果:
{"password":"123123","creaTime":1689683632477,"username":"zhangsan","status":1}
结论:
- 对象==》json对象 {}
- map==》json对象 {}
- List==》json数组 [{},{}]
JSON格式字符串转对象
类格式的字符串转换为json格式
public class JackSonTest2 {
String jsonStr = "{\"sid\":2,\"stuName\":\"张三\",\"address\":\"xxxxxx\",\"gender\":1,\"hobbies\":[\"抽烟\",\"喝酒\",\"烫头\"]}\n";
@Test
public void readObject() throws Exception {
//初始化jackson
ObjectMapper objectMapper = new ObjectMapper();
//读数据
Student student = objectMapper.readValue(jsonStr, Student.class);
System.out.println(student);
}
}
回显结果
Student(sid=2, stuName=张三, address=xxxxxx, gender=1, hobbies=[抽烟, 喝酒, 烫头])
使用map进行json格式字符串转换为对象
public class JackSonTest2 {
String jsonStr = "{\"sid\":2,\"stuName\":\"张三\",\"address\":\"xxxxxx\",\"gender\":1,\"hobbies\":[\"抽烟\",\"喝酒\",\"烫头\"]}\n";
@Test
public void readObject() throws Exception {
//初始化jackson
ObjectMapper objectMapper = new ObjectMapper();
//读数据
Map map = objectMapper.readValue(jsonStr, Map.class);
System.out.println(map);
}
}
使用map集合对未定义的类进行转换为对象
public class JackSonTest2 {
String aStu = "{\"password\":\"123123\",\"creaTime\":1689686523611,\"username\":\"zhangsan\",\"status\":1}\n";
@Test
public void readObject() throws Exception {
//初始化jackson
ObjectMapper objectMapper = new ObjectMapper();
//读数据
Map map1 = objectMapper.readValue(aStu, Map.class);
System.out.println(map1);
}
}
回显结果:
{password=123123, creaTime=1689686523611, username=zhangsan, status=1}
使用json数组转为对象
:::info
- 什么时候使用TypeReference?==》当你明确需要它把结果给你封装到一个具体的类中
- TypeReference是抽象类。抽象类中的匿名内部类
- 查看这个对象是哪个类的。
student.stream().forEach(stu -> {
System.out.println(stu.getClass().getCanonicalName());
});
public class JackSonTest2 {
String jsonArr = "[{\"sid\":1,\"stuName\":\"zhangsan\",\"hobbies\":[\"抽烟\",\"喝酒\"]},{\"sid\":1,\"stuName\":\"zhangsan\",\"hobbies\":[\"抽烟\",\"喝酒\"]}]";
public void redList() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//用来把JSON数组转换为对象
//什么时候使用TypeReference?==》当你明确需要它把结果给你封装到一个具体的类中
//TypeReference是抽象类。抽象类中的匿名内部类
List<Student> student = objectMapper.readValue(jsonArr, new TypeReference<List<Student>>() {});
System.out.println(student);
//查看这个对象是哪个类的。
student.stream().forEach(stu -> {
System.out.println(stu.getClass().getCanonicalName());
});
}
}
jackson总结
[]: 是数组 List/set
{} 是对象 map/类.class
使用步骤:
- 导入坐标
- 写代码
核心的代码:把对象转换成json格式字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(对象);
- 结论:
- list/set转换出来的都是json数组
- Map/具体对象 转化出来的都是json对象
读数据,将json格式字符串转换成java对象
//读取单个对象
OBjeckMapper objectMapper = new ObjectMappertaining();
类 对象 = objectMapper.readValue(json字符串, 类.class);//map.class 自己写的类.class
//读取多个对象 ==>
OBjeckMapper objectMapper = new ObjectMappertaining();
//下面的api里面传的是一个匿名内部类
//告诉jackson回头读取出来的数据转成指定的格式List<类/map>
objectMapper2.readValue(json字符串, new TypeReference<List<类/map>>() {});
请求
请求的方式
:::info
@RequestMapping这个注解,我们通过get请求和post请求访问目标接口,都会被触发,实际情况我们的需求,只能通过特定的请求方式去访问我们的服务器.
:::
对于@RequestMapping进行了扩展,多出来了如下4个注解
- @GetMapping 只服务get请求
- @PostMapping 只服务post请求
- @PutMapping 只服务PUT请求
- @DeleteMapping 只服务DELETE请求
@postMapping 存在请求体
页面浏览器除了表单其他的不可以发起请求,要求请的要么是ajax要么是postman
简单请求(简单参数 K=V参数)
:::info
简单参数:在向服务器发起请求时,向服务器传递的是一些普通的请求数据。
:::
@Documentd:系统注解,用来生成文档。用来生成javac
原始API方式进行请求
注意:原生的没有提供KV格式的请求方式
@PostMapping("/login2")
public String login(HttpServletRequest request){
//这里使用的是原生api去处理,获取提交的参数
String username = request.getParameter("username");
System.out.println("username=>" + username);
return "ok";
注意:下面代码更改后的可以发送kv格式的请求
在原生的之前处理过程如下
@PostMapping("/login3")
public String login(HttpServletRequest request) throws IOException {
//这里使用的是原生api去处理,读取的请求体
String requestBody = request.getReader().readLine(); //username=tom&password=123 //{"username":"tom","password":"123"}
System.out.println(requestBody);
return "ok";
}
参数在请求体中。
所有的数据都在请求体中。
在postman中发起请求,查看后台获取数据情况
在postman中发起KV格式请求,查看后台获取数据情况
SpringBoot方式进行请求
// @PostMapping("/login")
// public String login(String username,String password){
// System.out.println(username+"==="+password);
// return "ok";
// }
@PostMapping("/login4")
public User login(@RequestBody String jsonStr) throws IOException {
//{"username":"tom","password":"123"} => json格式的字符串
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(jsonStr, User.class);
System.out.println(user);
return user;
}
@PostMapping("/login1")
public Result login(User user) {//用key和value的方式
System.out.println(user);
return user;
}
@PostMapping("/login")
public String login(@RequestBody Map map) throws IOException {
//{"username":"tom","password":"123"} => json格式的字符串
System.out.println(map);
return "user";
}
这是一个对象,多有可以用map和user类
参数名不一致问题
:::info
结论:对于简单参数来讲,请求参数名和controller方法中的形参名不一致时,无法接收到请求数据
:::
那么如果我们开发中,遇到了这种请求参数名和controller方法中的形参名不相同,怎么办?
解决方案:可以使用Spring提供的@RequestParam注解完成映射
结论:对于简单参数来讲,请求参数名和controller方法中的形参名不一致时,无法接收到请求数据
那么如果我们开发中,遇到了这种请求参数名和controller方法中的形参名不相同,怎么办?
解决方案:可以使用Spring提供的@RequestParam注解完成映射
@RequestMapping("/login")
public String login(@RequestParam("name") String username,@RequestParam("pass") String password){
//boot帮助咱们简化的版本
//获取用户名和密码
System.out.println(username + "=======================" +password);
return "login : "+username;
}
复杂请求(实体参数)
结论1:复杂参数尽量不要再get请求中传递,因为在get请求中,对于中文和特殊字符会及逆行URL编码,建议使用post请求发送这类发杂参数。
结论2:
如果是key-value的数据,后台是:
public void login(String username,String password){}
public void login(User user){}
//请求: 地址?id=1,2,3,4
@GetMapping()
public String demo(@RequestParam List<Integer> ids){
return "ok";
}
如果是json格式的数据则:
- 首先 必须有请求体
- 只要是json请求 就需要@RequestBody
@PostMapping()
public String demo(@RequestBody User user){
return "ok";
}
@PostMapping()
public String demo(@RequestBody List<User> list){
return "ok";
}
路径请求
路径参数: 特点:
@GetMapping("/findById/{id}")
public String findById(@PathVariable Integer id){
System.out.println(id);
return "ok";
}
@PostMapping("/save/{name}/{age}")
public String saveStu(@PathVariable("age") int age,@PathVariable("name")String name){
System.out.println(age +" ===="+ name );
return "ok";
}
响应
boot响应
结果:
@ResponseBody:响应体只要加上这个注解,返回结果就会放到响应体中。
@RestController:这个注解加载类上代表里边的方法都存在这个注解了 @Documented
@Controller
@ResponseBody
结论:一个方法加了一个注解@ResponseBody注解,意味着这个方法返回值会被方程响应体会返回给页面。这个方法放在了类中,代表这个所有都有这个注解了
只要是返回页面的数据的内容,,boot框架会统一帮咱们转换json格式的字符串返回给页面
三层架构
真实开发中,不可能把所有业务都写到一个类中,要拆分代码
三层架构:
- 表现层(web层):和前端交互。直白点就是xxx.controller
- 业务层(service层):核心业务实现的地方(学习阶段,代码最少的地方!!!开发阶段,代码最多的地方)
- 数据处理层(dao层,翻译过来database access object):和数据库进行交互。
- dao还有一个名字叫mapper==》映射(mybatis架构)
xxxController:
持有service对象
service.方法()
xxxService:
持有mapper对象
mapper.方法()
xxxMapper:
查询数据库;
@Component
@RestController
@RequestMapping("/user")
public class UserController {
UserService userService = new UserService();
@GetMapping("/findAll")
public List<User> findAll(){
List<User> list = userService.findAll();
return list;
}
@PostMapping("/update")
public Map updata(@RequestBody User user){
userService.update(user.getUsername());
HashMap hashMap = new HashMap();
hashMap.put("code",200);
return hashMap;
}
}
public class UserService {
UserDao userDao = new UserDao();
public List<User> findAll(){
return userDao.findAll();
}
public void update(String username){
userDao.update(username);
}
}
@Component
@Repository
public class UserDao {
public List<User> findAll(){
//todo 去查询数据库 SELECT * FROM t_user
ArrayList<User> list = new ArrayList<User>();
list.add(new User("tom"));
list.add(new User("jack"));
list.add(new User("rose"));
return list;
}
public void update(String username){
System.out.println("修改用户名为"+username);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component//程序启动时,会创建一个User对象放到spring容器中
public class User {
private String username;
}
SpringIOC/DI
IOC:控制反转
直白点就是不再自己new对象,让spring帮你创建
本质:不再自己new对象,让spring创建对象。Spring如何创建对象呢?也是new 走的实际是反射,关键对象创建以后放入spring的容器中,后续我们要对象让spring要。
IOC==》三层的对象和特定对象需要创建ioc创建,实体类不能用!!!
实体类还是自己new对象
使用方法:在目标类上 加注解@Component
@Component==> spring帮我们创建对象
在spring的优化下我们针对@Component注解,进行了优化,提供语义化的注解
我们后期IOC通常应用 三层对象和配置对象上,其他情况我们还是自己new对象(例如pojo)
- @Controller通常放在web层的Controller
- @Service通常放在service层下的实现类上
@SpringBootTest(classes = BootApplication.class)
public class IOCTest {
@Autowired //找spring容器要
UserService userService;
//找spring容器要对象
// @Autowired
// //Dog dog;
// UserController userController;
//
// @Autowired
// UserService userService;
//
// @Autowired
// UserDao userDao;
@Test
public void testIOC(){
System.out.println(userService);
//多态
//Animal dog = new Dog();
}
}
DI:依赖注入
Spring创建对象的时候,给对象赋值。