SpringMVC
@Controller
注解,用于标识该类交给SpringMVC管理,然后再由SpringMVC交给Spring管理
@ResponseBody
注解的作用其实是将java对象转为json格式的数据,将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
@RequestMapping
设置请求路径
参数接收
简单参数的传递
使用形参的方式,方法的参数列表中形参的名字与前端传过来的参数名一致,Spring会自动注入
/**
* /findUserByNA?name=tomcat&age=18
* @param name Spring会自动把请求地址里面对应的参数的值注入此形参中
* @param age Spring会自动把请求地址里面对应的参数的值注入此形参中,并做类型转换
* @return
*/
@RequestMapping("/findUserByNA")
public String getUserByNameAndAge(String name,Integer age){
return "数据添加成功!"+name+":"+age;
}
对象方式传参
POJO对象
使用POJO对数据进行封装
要求
- 有get/set方法
- 数据类型全部使用引用类型,不要使用基本数据类型
- 实现序列化接口
使用对象来接收前端传来的参数时,会使用反射的形式把有值的通过对象的相应的set方法设置到对象中,没有对应方法的值会被丢弃,若有未传参的属性,则得到对象的对应属性为默认值null;
/**
* /add?name=张三丰&age=18&set=男
*
* @param user
* @return
*/
@GetMapping("/add")
public User addUser(User user) {
return userService.addUser(user);
}
同名参数
前端传进来的是同名的一组值,则使用对应数据类型的数组来接收
/**
* 同名提交的参数
* /hobys?hoby=tomcat&hoby=java
* /hobys?hoby=tomcat,java,c,mysql
*
* @param hoby
* @return
*/
@GetMapping("/hobys")
public String addHobys(String[] hoby) {
return Arrays.toString(hoby);
}
restFul风格
- 定义
参数写在路径里面的形式
http请求类型
请求头 | 类型说明 |
---|---|
OPTIONS | 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送’*'的请求来测试服务器的功能性。 |
HEAD | 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。 |
GET | 向特定的资源发出请求。 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 |
PUT | 向指定资源位置上传其最新内容。 |
DELETE | 请求服务器删除Request-URI所标识的资源。 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
CONNEC | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 |
- 要求:
- 参数位置固定
- 各参数间使用/分隔
- 适用于get post put delete
- 前端请求格式:
http://localhost:8080/user/r/tomcat/18/男
更多方式参考1.3.2. Request Mapping https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc
- 后端接收方式
@RequestMapping("/r/{name}/{age}/{sex}")
public String restFulMethod1(@PathVariable String name,@PathVariable Integer age,@PathVariable String sex) {
return name+":"+age+":"+sex;
}
//如果参数名称与User类定义的属性名字一致,则可以使用对象接收
@RequestMapping("/r/{name}/{age}/{sex}")
public User restFulMethod1(User user) {
return user;
}
JSON数据交换
- 定义:轻量级的数据交换格式。(JavaScript Object Notation,JS对象简谱)它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。
-
对象(object) 是一个无序的“
key:value
对”集合。一个对象以{
开始,}
结束。每个key
后跟一个:
(冒号);“key:value
对”之间使用,
(逗号)分隔。
-
数组(array) 是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
-
值(value) 可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。
-
字符串(string) 是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。
JSON的字符串(string)与C或者Java的字符串非常相似。
-
数值(number) 也与C或者Java的数值非常相似。只是JSON的数值没有使用八进制与十六进制格式。
流程梳理
-
前端发请求给后端,后端发响应给前端
-
@ResponseBody
注解,如果返回值是对象,则格式化为json后再响应。否则直接响应返回值。 -
@RestController
注解作用于类上时,等同于同时施加了@Controller
和@ResponseBody
两个注解
@Controller
@ResponseBody
public class UserServiceController {}
上面的代码与下面这段代码效果一致
@RestController
public class UserServiceController {}
- 关于路径,方法最终的请求路径是施加在类上面的路径与施加在方法上的路径拼接后的值
施加在类上面的路径一般做为公共前辍来使用。如下两段代码中addUser()
方法的访问路径都是/user/add
@RestController
@RequestMapping("/user")
public class UserServiceController {
@GetMapping("/add")
public User addUser(User user) {
return user;
}
}
@RestController
@RequestMapping("/user/")
public class UserServiceController {
@GetMapping("add")
public User addUser(User user) {
return user;
}
}
- 注意:SpringMVC中请求路径不能完全重复,否则会报错
Ajax
功能和作用:Ajax主要实现前后端交互,提高用户有页面与服务器这间交互效率。
关于回调函数:在知乎上看到一个回答
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。
链接:https://www.zhihu.com/question/19801131/answer/13005983
跨域解决方案:
@CrossOrigin
定义当 前controller中定义的方法可以处理跨域的请求,即收到跨域过来的请求时也会正常返回结果,且浏览器里面的函数也可以正常收到此数据。- jsonp 据说用的少了,需要寻找新的解决方案
Axios测试
第一步:Hbuilder里面建立如下结构
添加Axios引用
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
- 创建一个controller用来访问
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 本类用于
*
* @author SJXQ
* @version 2021/12/1 15:27
*/
@RestController
@CrossOrigin
@RequestMapping("/axios/")
public class AxiosController {
@Autowired
UserService userService;
/**
* url:/axios/getUserById?id=0
* @param id
* @return
*/
@RequestMapping("getUserById")
public User getUserById(Integer id) {
return userService.getUserById(id);
}
/**
* url:/axios/getUser-0.json
* @param id
* @return
*/
@RequestMapping("getUser-{id}.json")
public User getUserById2(@PathVariable Integer id){
return userService.getUserById(id);
}
/**
* url:/axios/getUserByNA?
* @param age
* @param name
* @return
*/
@RequestMapping("getUserByNA")
public List<User> getUserByNA(String name,Integer age){
return userService.getUserByNA(name, age);
}
/**
* 根据姓名和性别查询用户列表
* @param name
* @param sex
* @return
*/
@RequestMapping("/findUserByNS/{name}/{sex}")
public List<User> findUserByNS(@PathVariable String name,@PathVariable String sex){
return userService.getUserByNameAndSex(name, sex);
}
@RequestMapping(value = "saveUser", method = RequestMethod.POST)
public User saveUser(@RequestBody User user) {
return userService.addUser(user);
}
@PutMapping("updateUser")
public String modifyUser(@RequestBody User user) {
userService.addUser(user);
return "更新成功!";
}
@DeleteMapping("updateUser")
public User deleteUser(@RequestBody User user){
return userService.deleteUser(user);
}
}
前端有如下三种请求方式
- 第一种:参数直接拼到请求的url里面
axios.get("http://localhost:8080/axios/getUserById?id=0")
.then(res => {
console.log(res);
});
- 第二种:请求的参数使用对象来传递,在
axios
里面使用params
来指定
/**
* 1.get请求 对象传参
* 2.语法说明:
* 关键字: params : 对象信息
*/
let user2 = {name:"tomcat",age:100}
let url2 = "http://localhost:8080/axios/getUserByNA"
axios.get(url2,{params:user2})
.then(function(promise){
console.log(promise.data)
})
- 第三种:对于restFul风格的API可以使用Javascript的模板字符串来拼接
/**
*需求: 利用restFul的风格实现前后端交互.
* URL: http://localhost:8080/axios/findUserByNS/tomcat/男
* 难点:
* 1.tomcat/男直接写死在url地址中. 后期扩展不方便
* 模版字符串写法:ES6引入的新功能
* 语法:
* 1. 使用反引号 ``
* 2. 作用: 1.可以保证字符串的格式
* 2.可以动态获取变量的值
*/
let user3 = {name: "tomcat", sex: "男"}
let url3 = `http://localhost:8080/axios/findUserByNS/${user3.name}/${user3.sex}`
let html = `<div>
<p>AAA</p>
<p>BBB</p>
</div>
`
axios.get(url3)
.then(function(promise){
console.log(promise.data)
})
注意:此处then里面得到的实际上是一个promise对象,请求所获得的数据被封装到了此对象的data属性里面
//axios.get(url).then(function(promise){console.log(promise);})
{
"data": {
"id": 0,
"name": "张三丰",
"age": 18,
"sex": "男"
},
"status": 200,
"statusText": "",
"headers": {
"content-type": "application/json"
},
"config": {
"url": "http://localhost:8080/axios/getUserById?id=0",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*"
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
},
"request": {}
}
第四种 post请求
let url1 = "http://localhost:8080/axios/saveUser";
let user1 = {id: 5,name: "大黄",age: 3, sex: '母'};
axios.post(url1, user1).then(function(promise) {
console.log(promise.data);
});
嵌套请求的问题,就是下一个请求的参数依赖于当前请求的结果
async
用来标识函数
await
用来标识ajax请求
// async用来标识这是一个异步函数,即执行到此函数后,会创建一个子线程来执行此函数,主线程继续向下执行
async function getHello(){
//
let promise = await axios.get("/web/hello");
console.log(promise);
}
解构赋值的方式取值
async function getHello(){
//解构赋值
let {data,status} = await axios.get();
console.log(data);
console.log(status);
}
请求类型
注解 | 请求类型 |
---|---|
@PostMapping | post |
@GetMapping | get |
@PutMapping | put |
@DeleteMapping | delete |
也可以统使用@RequestMapping
注解,通过设置属性的方式来限定请求类型
服务端限定仅处理post请求,以下两种方式都可以限定请求类型
@RequestMapping(value = "saveUser",method = RequestMethod.POST)
@PostMapping("saveUser")
常见错误
报错代码 | 解读 | 服务器错误提示信息 |
---|---|---|
405 | 请求路径对了,但是请求类型不致,比如saveUser 仅处理post请求,但是发的是get请求就会报这个错 | type=Method Not Allowed, status=405 |
400 | 请求参数类型不匹配,比如后端需要接收的是一个json,但实际传进来的是key=v1&k2=v2这种形式 | type=Bad Request, status=400 |
404 | 请求路径找不到 | type=Not Found, status=404 |