使用Springboot接收前端Ajax发送的json
原创
©著作权归作者所有:来自51CTO博客作者cerana的原创作品,请联系作者获取转载授权,否则将追究法律责任
1. 后端Springboot
通过 https://start.spring.io/ 获得项目框架。在eclipse中导入下载的Maven项目。
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
@RestController
public class GetJsonReq {
@CrossOrigin
@RequestMapping(value = "/simple")
// json的结构和内部字段名称可以与POJO/DTO/javabean完全对应
public Map<String, String> getJsonBean(@RequestBody Beauty beauty) {
Map<String, String> result = null;
if (beauty != null) {
System.out.println("美女的名字:" + beauty.getName());
System.out.println("美女的年龄:" + beauty.getAge());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("美女出道日期:" + sdf.format(beauty.getDate()));
System.out.println("美女的收入:" + beauty.getSalary());
result = new HashMap<>();
result.put("code", "1");
result.put("msg", "ok");
}
return result;
}
@CrossOrigin
@RequestMapping(value = "/complex")
//json的结构较为复杂,不直接与POJO/DTO/javabean对应。
public Map<String, String> getJsonComplex(@RequestBody JSONObject param) {
Map<String, String> result = null;
if (param != null) {
JSONObject master = param.getJSONObject("master");
Beauty beauty = (Beauty) JSONObject.toJavaObject(master, Beauty.class);
System.out.println(beauty);
JSONArray mm = param.getJSONArray("MM");
for (int i = 0; i < mm.size(); i++) {
// 这里不能使用get(i),因为get(i)只会得到键值对。
JSONObject json = mm.getJSONObject(i);
Beauty bt = (Beauty) JSONObject.toJavaObject(json, Beauty.class);
System.out.println(bt);
}
result = new HashMap<>();
result.put("code", "1");
result.put("msg", "ok");
}
return result;
}
}
- POJO/DTO/JavaBean
注意Date字段要如何处理。
public class Beauty {
private String name;
private int age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date date;
private double salary;
public Beauty() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Beauty [name=" + name + ", age=" + age + ", date=" + date + ", salary=" + salary + "]";
}
}
- 将JSON转为Java对象使用@RequestBody 注解;将Java对象转换为JSON使用@ResponseBody注解。
一旦使用@ResponseBody注解返回流程将不在经过视图解析器,而是直接将数据写入到输出流中,通过response的body返回数据。如果处理请求方法返回的是 String 时@ResponseBody 注解不会进行 JSON 转换。响应的 Content-Type 为 text/plain;charset=ISO-8859-1。如果处理请求方法返回的是除了 String 类型以外的其他Object 类型时,@ResponseBody注解会进行 JSON 转换。响应的 Content-Type 为 application/json。
响应体的字符编码需要在@RequestBody 注解中设定:
//@RequestMapping(value = "/addUsers",produces = "text/plain;charset=utf-8") 返回String
//@RequestMapping(value = "/addUsers",produces = "application/json;charset=utf-8") 返回json对象
@RequestMapping(value = "/addUsers",produces = MediaType.APPLICATION_JSON_VALUE+";charset=utf-8")
@ResponseBody
@CrossOrigin(origins ="http://localhost:8888")
public Object addUsers(@RequestBody Users users)throws Exception{
System.out.println(users);
return users;
}
2. 前端通过Ajax发送json
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>发送json</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<script type="text/javascript">function send1() {
var beauty = JSON.stringify({ //将JSON对象转换为字符串
"name": "小甜甜",
"age": 26,
"salary": 200000,
"date": "2019-08-05 08:04:13"
});
$.ajax({
type: 'POST',
url: "http://localhost:8080/simple",
data: beauty, //beauty是字符串
contentType: "application/json",
dataType: "json",
success: function(message) {
alert(JSON.stringify(message)) //将JSON对象转换为字符串
}
});
};
function send2() {
var beauty = JSON.stringify({
"MM": [{
"name": "春花",
"age": 27,
"salary": 20000,
"date": "2017-05-19 09:33:14"
}, {
"name": "秋香",
"age": 30,
"salary": 30000,
"date": "2019-10-21 17:04:33"
}],
"master": {
"name": "小甜甜",
"age": 26,
"salary": 200000,
"date": "2019-08-05 08:04:13"
}
});
$.ajax({
type: "POST",
url: "http://localhost:8080/complex",
contentType: "application/json; charset=utf-8",
data: beauty,
dataType: "json",
success: function(message) {
alert("提交成功" + JSON.stringify(message));
},
error: function(message) {
alert("提交失败" + JSON.stringify(message));
}
});
}</script>
<input type="button" name="btn1" id="s1" onclick="send1()" value="发送简单json" />
<br />
<hr />
<input type="button" name="btn2" id="s2" onclick="send2()" value="发送复杂json" />
</body>
</html>
这里要注意:
- script标签引入js的形式必须是双标签,形如:
<script src="…js" …></script>
如果是形如<script src="…js" … />的单标签,将无法引入js。 - 页面提交的数据默认content-type是application/x-www-form-urlcoded的编码(键值对)。而@RequestBody注解只有在编码为application/json时才能将JSON 格式的数据转为 Java 对象。
- 对于jQuery一般是使用$.ajax来发送json请求,因为只有它可以设置编码格式(application/json)。
- HTML5中如何实现JSON对象与字符串之间的相互转换?
//string -> json
JSON.parse("...")
//json -> string
JSON.stringify(obj)
3. 跨域访问
- 同源策略
ajax请求须受到同源策略的影响。 - 跨域请求
在 JavaScript 的请求中当一个请求 URL 的协议、域名、端口三者之间任意一个与当前页面 URL 不同时即为跨域。 - ajax请求如何受同源策略限制
一个页面的URL(origin)与同一页面中ajax访问的URL出现跨域时,ajax请求被服务器端block。 - 处理方式
前端:jsonp(json with padding)
jsonp的原理就是script标签不受同源策略的影响,所以通过script的src属性来实现跨域。
//原生js
var script = document.createElement("script");
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
//在页面中,返回的JSON作为参数传入回调函数中
functionhandleResponse(response){
// 对response数据进行操作代码
}
//jQuery GET
$.ajax({
async : true,
url : "https://api.douban.com/v2/book/search",
type : "GET",
dataType : "jsonp", // 返回的数据类型,设置为JSONP方式
jsonp : 'callback', //指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback
jsonpCallback: 'handleResponse', //设置回调函数名
data : {
q : "javascript",
count : 1
},
success: function(response, status, xhr){
console.log('状态为:' + status + ',状态是:' + xhr.statusText);
console.log(response);
}
});
//jQuery POST
$.ajax({
url:'http://localhost:8888/other/other.jsp',
type:'post',
data:{'params':'fromjsonp'},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
success: function(data){
alert("through jsonp,receive data from other domain : "+data.result);
},
error: function(){
alert('fail');
}
});
后端:@CrossOrigin
@Controller
@RequestMapping("/user")
public class UsersController {
@RequestMapping(value = "/addUsers",produces = MediaType.APPLICATION_JSON_VALUE+";charset=utf-8")
@ResponseBody
//限定发送 ajax的页面的初始url,即origins(可多个origin url)。其他的不受理。
//不给出origins则处理所有origin url的跨域 ajax请求。
@CrossOrigin(origins ="http://localhost:8888")
public Object addUsers(@RequestBody Users users)throws Exception{
System.out.println(users);
return users;
}
}
4. 使用Java如何模拟客户端发送json的http请求?