location.href遇到的400错误

版权声明:转载请注明出处 https://blog.csdn.net/h2604396739/article/details/84954626

其实需求很简单,就是点击按钮后,向后台传入查询条件,然后根据查询条件获取满足条件的记录通过excel下载。

方案一:使用ajax方式不可以原因
导出excel算是文件下载了,后台需要向前台(浏览器)写文件流,而ajax请求获取的数据的都是字符串(此点当时在调试页面的时候,Response响应中满是乱码的字符串文本),它没法解决后台返回的文件流,但是浏览器可以。
换句话说 ajax貌似实现不了文件下载的功能,所以使用window.location.href直接地址重定向


方案二:location.href  
js请求如下:
location.href='/userFilter/exportUserPage.action?parameterMap='+ JSON.stringify(json);
后台接收代码
    @RequestMapping(value="/exportUserPage.action")
    public  void exportUserPage(@RequestBody Map parameterMap, HttpServletResponse response,HttpServletRequest request){

//业务代码 
    }
400错误一
页面显示如下:
HTTP Status 400 – Bad Request
Type Status Report

Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
服务器不能或不会处理请求,因为某些东西被认为是客户端错误(例如,格式错误的请求语法、无效的请求消息框架或欺骗性的请求路由)。

怎么理解@RequestBody????
@RequestBody使用方式:
@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。

    通过@requestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分别绑定到对应的字符串上。
    例如说以下情况:
    $.ajax({
        url:"/login",
        type:"POST",
        data:'{"userName":"admin","pwd","admin123"}',
        content-type:"application/json charset=utf-8",
        success:function(data){
          alert("request success ! ");
        }
    });

    @requestMapping("/login")
    public void login(@requestBody String userName,@requestBody String pwd){
      System.out.println(userName+" :"+pwd);
    }
    这种情况是将JSON字符串中的两个变量的值分别赋予了两个字符串,但是呢假如我有一个User类,拥有如下字段:
      String userName;
      String pwd;
    那么上述参数可以改为以下形式:@requestBody User user 这种形式会将JSON字符串中的值赋予user中对应的属性上
    需要注意的是,JSON字符串中的key必须对应user中的属性名,否则是请求不过去的。
借鉴与:http://www.cnblogs.com/qiankun-site/p/5774300.html

解决方案去掉后台处理的@RequestBody Map parameterMap
修改后的前后端代码如下:

js请求:
location.href='/userFilter/exportUserPage.action?parameterMap='+ JSON.stringify(json);
后台接收代码
    @RequestMapping(value="/exportUserPage.action")
    public  void exportUserPage( HttpServletResponse response,HttpServletRequest request){
    }
400错误二
前端:Failed to load resource: the server responded with a status of 400 ()
后台: java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986,
翻译:请求目标中发现无效字符。在RFC 7230和RFC 3986中定义了有效字符。

必须指出的是这个错是tomcat报的。。。。。。

接下来我们来看看RFC 3986中到底是怎么规范的
RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。RFC3986文档对Url的编解码问题做出了详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。
US-ASCII字符集中没有对应的可打印字符:Url中只允许使用可打印字符。US-ASCII码中的10-7F字节全都表示控制字符,这些字符都不能直接出现在Url中。同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,因此也不可以放在Url中

这个问题其实就是你传入的url和参数中存在不符合规范的字符。

解决方案:
encodeURI(),用来encode整个URL,不会对下列字符进行编码:+ : / ; ?&。它只会对汉语等特殊字符进行编码 
encodeURIComponent (),用来enode URL中想要传输的字符串,它会对所有url敏感字符进行encode 

所以
js中:
     location.href=encodeURI('/userFilter/exportUserPage.action?parameterMap='+ JSON.stringify(json));
后台:
    @RequestMapping(value="/exportUserPage.action")
    public  void exportUserPage( HttpServletResponse response,HttpServletRequest request){

        Map parameterMap = new HashMap();

        try {
            // 前端编码,这里需要解码取值,parameterMap对应前端参数的名称
            String value = URLDecoder.decode(request.getParameter("parameterMap"), "UTF-8");
            System.out.println("value");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

 
其实本质上还是对http的知识不了解,导致前后端的数据无法正确对应导致的,所以推荐书籍:

《图解Http》
http权威指南
tcp/ip详解

完整的实现excel下载功能的代码可以借鉴:https://blog.csdn.net/h2604396739/article/details/84954817

猜你喜欢

转载自blog.csdn.net/h2604396739/article/details/84954626