解决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
到这里为止,整个过程已经很清晰了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。