java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > httpServletRequest.getParameter获取不到参数

解决httpServletRequest.getParameter获取不到参数的问题

作者:和代码去流浪

这篇文章主要介绍了解决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.headersContent-Type中搜索charset=截取出来的。

如果里面不包含编码格式,那么就会使用默认字符集ISO-8859-1到这里为止,整个过程已经很清晰了。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文