SpringMVC前后端参数交互
Controller中使用JSON方式有多种
关键在于ajax请求是将数据以什么形式传递到后台
HTTP请求中:
- 如果是get请求,那么表单参数以name=value&name1=value1的形式附到url的后面(QueryString Parameters),
- 如果是post请求,那么表单参数是在请求体中,也是以name=value&name1=value1的形式在请求体中(Form Data)
前端常用参数提交方式:
- POST + JSON字符串形式
- POST + JSON对象形式
- GET + 参数字符串
方式一: POST + JSON字符串形式,如下:
//前端
var data = {
userAccount: lock_username,
userPasswd:md5(lock_password).toUpperCase()
}
$.ajax({
url : ctx + "/unlock.do",
type : "POST",
data : JSON.stringify(data), //转JSON字符串
dataType: 'json',
contentType:'application/json;charset=UTF-8', //contentType很重要
success : function(result) {
console.log(result);
}
});
注意
1.json数据必须用JSON.stringify()方法转换成字符串
2.contentType不能省略
//后端
@RequestMapping(value = "unlock.do",method = RequestMethod.POST)
@ResponseBody
public Msg methodName(@RequestBody User user) {
logger.info("user:"+user);
return Msg.success();
}
注意
@RequestBody不可以省略,如果不加的话spring mvc后台无法接受data参数
@RequestParam 、@RequestBody 说明
@RequestParam用来处理ContentType: 为 application/x-www-form-urlencoded编码的内容
@RequestBody该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等
@RequestBody接收的是一个Json对象的字符串,而不是一个Json对象。在ajax请求往往传的都是Json对象,用 JSON.stringify(data)的方式就能将对象变成字符串。
参考资料: https://blog.csdn.net/HelloWorld20151118/article/details/77104047
方式二: POST + JSON对象形式,如下:
//请求数据,登录账号 +密码
ar data = {
userAccount: lock_username,
userPasswd:md5(lock_password).toUpperCase()
} $.ajax({
url : ctx + "/unlock.do",
type : "POST",
data : data, //直接用JSON对象
contentType : "application/x-www-form-urlencoded",
dataType: 'json',
success : function(result) {
console.log(result);
}
});
说明:
如果使用原生AJAX POST请求时,需要明确设置Request Header xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 因为原生AJAX默认使用的Content-Type是text/plain;charset=UTF-8,参数请求体在(Request Payload)中
如果使用jquery的$.ajax post请求是不需要明确设置 "contentType" 这个请求头,默认已经设置。
tomcat容器会对如下两种格式数据特殊处理:
- 表单提交且Content-Type为application/x-www-form-urlencoded,因为表单提交数据是键值对的方式;
- 文件上传做特殊处理;
tomcat容器对于Content-Type不是application/x-www-form-urlencoded的数据只能通过获取原始数据流的方式来进行解析,因为请求数据格式不固定,不一定是键值对的方式,所以服务器无法知道具体的处理方式;那么这样提交的参数我们该怎么获取呢?当然是使用最原始的方式,读取输入流来获取了(参考:FastJsonHttpMessageConverter),原始方式当然也可以接收Content-Type是application/x-www-form-urlencoded得POST请求数据
类名:org.apache.catalina.connector.Request
protected void parseParameters() {
this.parametersParsed = true;
Parameters parameters = this.coyoteRequest.getParameters();
boolean success = false;
try {
parameters.setLimit(this.getConnector().getMaxParameterCount());
String enc = this.getCharacterEncoding();
boolean useBodyEncodingForURI = this.connector.getUseBodyEncodingForURI();
if(enc != null) {
parameters.setEncoding(enc);
if(useBodyEncodingForURI) {
parameters.setQueryStringEncoding(enc);
}
} else {
parameters.setEncoding("ISO-8859-1");
if(useBodyEncodingForURI) {
parameters.setQueryStringEncoding("ISO-8859-1");
}
}
parameters.handleQueryParameters();
if(this.usingInputStream || this.usingReader) {
success = true;
return;
}
if(!this.getConnector().isParseBodyMethod(this.getMethod())) {
success = true;
return;
}
String contentType = this.getContentType();
if(contentType == null) {
contentType = "";
}
int semicolon = contentType.indexOf(59);
if(semicolon >= 0) {
contentType = contentType.substring(0, semicolon).trim();
} else {
contentType = contentType.trim();
}
// 这里是处理文件上传请求
if("multipart/form-data".equals(contentType)) {
this.parseParts(false);
success = true;
return;
}
// 这里如果contentType是非application/x-www-form-urlencoded请求直接返回,不再进行处理。
// 从上面代码可以看出,Content-Type==不是application/x-www-form-urlencoded==的POST请求是不会读取请求体数据和进行相应的参数处理的,即不会解析表单数据来放到request parameter map中。所以通过request.getParameter(name)是获取不到的。
if(!"application/x-www-form-urlencoded".equals(contentType)) {
success = true;
return;
}
int len = this.getContentLength();
if(len <= 0) {
if("chunked".equalsIgnoreCase(this.coyoteRequest.getHeader("transfer-encoding"))) {
Object formData1 = null;
Context context;
byte[] formData2;
try {
formData2 = this.readChunkedPostBody();
} catch (IllegalStateException var17) {
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
context = this.getContext();
if(context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var17);
}
return;
} catch (IOException var18) {
parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
context = this.getContext();
if(context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var18);
}
return;
}
if(formData2 != null) {
parameters.processParameters(formData2, 0, formData2.length);
}
}
} else {
int formData = this.connector.getMaxPostSize();
Context e;
if(formData >= 0 && len > formData) {
e = this.getContext();
if(e != null && e.getLogger().isDebugEnabled()) {
e.getLogger().debug(sm.getString("coyoteRequest.postTooLarge"));
}
this.checkSwallowInput();
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
return;
}
e = null;
byte[] e1;
if(len < 8192) {
if(this.postData == null) {
this.postData = new byte[8192];
}
e1 = this.postData;
} else {
e1 = new byte[len];
}
try {
if(this.readPostBody(e1, len) != len) {
parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE);
return;
}
} catch (IOException var19) {
Context context1 = this.getContext();
if(context1 != null && context1.getLogger().isDebugEnabled()) {
context1.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var19);
}
parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
return;
}
// 处理POST请求参数,把它放到requestparameter map中(即request.getParameterMap获取到的Map,request.getParameter(name)也是从这个Map中获取的)
parameters.processParameters(e1, 0, len);
}
success = true;
} finally {
if(!success) {
parameters.setParseFailedReason(FailReason.UNKNOWN);
}
}
}
protected int readPostBody(byte[] body, int len) throws IOException {
int offset = 0;
do {
int inputLen = this.getStream().read(body, offset, len - offset);
if(inputLen <= 0) {
return offset;
}
offset += inputLen;
} while(len - offset > 0);
return len;
}
类:com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter
@Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage ) throws IOException, HttpMessageNotReadableException {
return readType(getType(clazz, null), inputMessage);
}
private Object readType(Type type, HttpInputMessage inputMessage) throws IOException {
try {
InputStream in = inputMessage.getBody();
return JSON.parseObject(in, fastJsonConfig.getCharset(), type, fastJsonConfig.getFeatures());
} catch (JSONException ex) {
throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);
} catch (IOException ex) {
throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
}
}
原始方式接收数据,自己开发:
private String getRequestPayload(HttpServletRequest req) {
StringBuildersb = new StringBuilder();
try(BufferedReaderreader = req.getReader();) {
char[]buff = new char[1024];
intlen;
while((len = reader.read(buff)) != -1) {
sb.append(buff,0, len);
}
}catch (IOException e) {
e.printStackTrace();
}
returnsb.toString();
}
方式三: GET + 参数字符串请求
$.ajax({
url : ctx + "/unlock.do",
type : "GET",
dataType: "text",
data : "userAccount="+lock_username+"&userPasswd=" + hex_md5(lock_password).toUpperCase(),//等价于URL后面拼接参数
success : function(result) {
console.log(result);
}
});
或者
ar data = {
userAccount: lock_username,
userPasswd:md5(lock_password).toUpperCase()
}
$.ajax({
url : ctx + "/unlock.do",
type : "GET",
dataType: "text",
data : data,//等价于URL后面拼接参数
success : function(result) {
console.log(result);
}
});
jquery:GET方式(选项processData:true情况下) data请求中将附加在 URL 后


SpringMVC前后端参数交互的更多相关文章
- SpringMVC前后端分离交互传参详细教程
温故而知新,本文为一时兴起写出,如有错误还请指正 本文后台基于SpringBoot2.5.6编写,前端基于Vue2 + axios和微信小程序JS版分别编写进行联调测试,用于理解前后端分离式开发的交互 ...
- SpringMVC前后端数据交互总结
控制器 作为控制器,大体的作用是作为V端的数据接收并且交给M层去处理,然后负责管理V的跳转.SpringMVC的作用不外乎就是如此,主要分为:接收表单或者请求的值,定义过滤器,跳转页面:其实就是ser ...
- content-type常见类型辨析(以ajax与springmvc前后端交互为例)
博客搬家: content-type常见类型辨析(以ajax与springmvc前后端交互为例) 在http报文的首部中,有一个字段Content-type,表示请求体(entity body)中的数 ...
- 两种方法实现asp.net方案的前后端数据交互(aspx文件、html+ashx+ajax)
一个HTML页面只能显示HTML代码信息,不能与数据库进行数据的交互.asp.net方案提供了网页与数据库交互的方法,这里举出两种:①aspx文件 ②ashx文件+ajax技术 一.创建数据库 这里以 ...
- vue-resource的使用,前后端数据交互
vue-resource的使用,前后端数据交互 1:导入vue与vue-resource的js js下载: https://pan.baidu.com/s/1fs5QaNwcl2AMEyp_kUg ...
- 前后端API交互数据加密——AES与RSA混合加密完整实例
前言 前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用R ...
- 对GraphQL-BFF:微服务背景下的前后端数据交互方案的研究-------引用
随着多终端.多平台.多业务形态.多技术选型等各方面的发展,前后端的数据交互,日益复杂. 同一份数据,可能以多种不同的形态和结构,在多种场景下被消费. 在理想情况下,这些复杂性可以全部由后端承担.前端只 ...
- web前后端数据交互
前后端数据交互是每一名web程序员必须熟悉的过程,前后端的数据交互重点在于前端是如何获取后端返回的数据,毕竟后端一般情况下只需要将数据封装到一个jsonMap,然后return就完了.下面通过一个li ...
- 前后端数据交互(八)——请求方法 GET 和 POST 区别
WEB 开发同学一看 get 和 post 请求方法的区别,第一感觉都是 So easy! 学习ajax.fetch.axios时,发送网络请求携带参数时,都需要分别处理get和post的参数.所以我 ...
随机推荐
- PHP中global与$GLOBALS的区别
单一个global是一个关键字,通常附加在变量前,用于将变量声明至全局作用域: $GLOBALS是预定义的超全局变量,把变量扔到里边的话一样可以带到全局去. $GLOBALS 是一个关联数组,每一个变 ...
- JUnit中Assert简单介绍
junit中的assert方法全部放在Assert类中,总结一下junit类中assert方法的分类.1.assertTrue/False([String message,]boolean condi ...
- react使用总结
1.拿到页面首先需要设计好,每个组件该怎么实现,划分好组件可以减少重复代码,有的时候需要和后端确认才能形成正确的划分 2.页面上的需要展示的数据都是由后端数据而来,所以任何增删改查的数据都要从后端重新 ...
- JS window对象 userAgent 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串) 语法 navigator.userAgent
userAgent 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串) 语法 navigator.userAgent 几种浏览的user_agent.,像360的兼容模式用的是IE.极速模 ...
- Gym 102028J 扫描线/二维差分 + 解方程
题意:有一个二维平面,以及n个操作,每个操作会选择一个矩形,使得这个二维平面的一部分被覆盖.现在你可以取消其中的2个操作,问最少有多少块地方会被覆盖? 思路:官方题解简洁明了,就不细说了:https: ...
- nodejs fs.readFile
fs.readFile(path[, options], callback) path <string> | <Buffer> | <URL> | <inte ...
- leetcode-164周赛-1269-停在原地的方案数
题目描述: 自己的提交: class Solution: def numWays(self, steps: int, arrLen: int) -> int: l = min(steps,arr ...
- CTSC2019
(upd:随机立方体AC) 太菜了只会部分分.以后慢慢补坑吧…… 随机立方体: 30分: 正常人都能想到的的转移状态(我的确是弱智),从大往小填数,记录有多少个极大值点和三个方向上各占了多少.转移可以 ...
- js类数组转数组的方法(ArrayLike)
1. 什么是类数组ArrayLike(类数组 就是一个普通的 js对象) 类数组对象必须含有 length 属性,且元素属性名必须是数值或者可转换为数值的字符. 类数组对象不是数组对象,所以没有数 ...
- 十折交叉验证10-fold cross validation, 数据集划分 训练集 验证集 测试集
机器学习 数据挖掘 数据集划分 训练集 验证集 测试集 Q:如何将数据集划分为测试数据集和训练数据集? A:three ways: 1.像sklearn一样,提供一个将数据集切分成训练集和测试集的函数 ...