解决httpServletRequest.getParameter获取不到参数的问题
作者:和代码去流浪
httpServletRequest.getParameter获取不到参数
用httpServletRequest.getParameter接收post请求参数,发送端content Type必须设置为application/x-www-form-urlencoded;否则会接收不到
@RequestMapping(value = "/a2")
@ResponseBody
public String hello3(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String string = httpServletRequest.getParameter("json");
System.out.println(string);
return "hahah";
}用@RequestBody接收请求可以用任意类型的content Type
@RequestMapping(value = "/a")
@ResponseBody
public void hello1(@RequestBody String string) {
System.out.println(string);
}
application/x-www-form-urlencoded通过表单提交,在sevlet实现中,mutipart/form-data和application/x-www-form-urlencoded会被特殊处理,请求参数将被放置于request.paramter,这是一个map。
我们可以从map中获取参数进行验证,或者其他拦截需求,map的获取类似hibernate的延迟加载,当调用request.getparamter()方法,servlet才会从请求流中读取请求参数加载入map。
InputStream也会存有这份数据,但如果这份数据被读取,那么到了controller层将无法读出数据,同样,拦截之后到达controller层时请求数据已经被加载入了controller层方法实参,实参对象需要有set方法,框架会以反射的方式调用属性的set方法注入数据,数据只会被注入到已有的属性。
当以application/json的content-type传送数据,被传送的对象只需被json序列化。
当以application/x-www-form-urlencoded的方式传送数据。
请求的内容需要以..=..&..=..的格式提交,在请求体内内容将会以”&”和“ = ”进行拆分。
HttpServletRequest.getParameter 乱码情况,源码解析
出现这种情况,一般的解决办法,如:HttpServletRequest.setCharacterEncoding("utf-8")是无效的。
因为HttpServletRequest在实例化的时候是根据请求的Content-Type读取编码如果Content-Type的值找不到那么就会用默认是编码格式ISO-8859-1
源码如下
org.apache.catalina.connector.Request
package org.apache.catalina.connector;
public class Request
@Override
public String getParameter(String name) {
if (!parametersParsed) {
parseParameters();
}
return coyoteRequest.getParameters().getParameter(name);
}
/**
* Parse request parameters.
*/
protected void parseParameters() {
parametersParsed = true;
Parameters parameters = coyoteRequest.getParameters();
boolean success = false;
try {
// Set this every time in case limit has been changed via JMX
parameters.setLimit(getConnector().getMaxParameterCount());
// getCharacterEncoding() may have been overridden to search for
// hidden form field containing request encoding
String enc = getCharacterEncoding();
boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
if (enc != null) {
parameters.setEncoding(enc);
if (useBodyEncodingForURI) {
parameters.setQueryStringEncoding(enc);
}
} else {
parameters.setEncoding
(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
if (useBodyEncodingForURI) {
parameters.setQueryStringEncoding
(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
}
}
.....
省略
.....
}
/**
* Get the character encoding used for this request.
*/
public String getCharacterEncoding() {
if (charEncoding != null)
return charEncoding;
charEncoding = ContentType.getCharsetFromContentType(getContentType());
return charEncoding;
}
}org.apache.tomcat.util.http.ContentType
package org.apache.tomcat.util.http;
public class ContentType {
/**
* Parse the character encoding from the specified content type header.
* If the content type is null, or there is no explicit character encoding,
* <code>null</code> is returned.
*
* @param contentType a content type header
*/
public static String getCharsetFromContentType(String contentType) {
if (contentType == null) {
return (null);
}
int start = contentType.indexOf("charset=");
if (start < 0) {
return (null);
}
String encoding = contentType.substring(start + 8);
int end = encoding.indexOf(';');
if (end >= 0) {
encoding = encoding.substring(0, end);
}
encoding = encoding.trim();
if ((encoding.length() > 2) && (encoding.startsWith("\""))
&& (encoding.endsWith("\""))) {
encoding = encoding.substring(1, encoding.length() - 1);
}
return (encoding.trim());
}
}org.apache.coyote.Constants
package org.apache.coyote;
public final class Constants {
// -------------------------------------------------------------- Constants
public static final String Package = "org.apache.coyote";
public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1";
...
省略
...
}org.apache.catalina.connector.Request.java为实际实现类,剩下你见到的乱七八糟的都是他的装饰类。
可以见到,getParameter的时候会先判断是否曾经解析过编码。
如果从来未使用getParameter的话,会先对数据进行编码格式设置。
这也就为什么,setCharacterEncoding一定要在getParameter之前。
方法parseParameters里有这么一行代码String enc = getCharacterEncoding();这行代码决定了post的编码格式,我们再往里面跑可以看到。
org.apache.tomcat.util.http.ContentType.java类的getCharsetFromContentType方法中,编码格式是由http.headers的Content-Type中搜索charset=截取出来的。
如果里面不包含编码格式,那么就会使用默认字符集ISO-8859-1到这里为止,整个过程已经很清晰了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
