Content type ‘application/x-www-form-urlencoded;charset=UTF-8‘ not supported错误的多种解决方法及说明Content-Type

1.复现错误


今天写好导入hive表的接口,如下代码所示:

/**
 * hive表导入
 *
 * @author super先生
 * @datetime 2023/3/20:16:32
 * @return
 */
@ResponseBody
@PostMapping(value = "/xxx/importTables")
public ServiceStatusData localHiveImportTables(
    @RequestBody ImportTablesBo importTablesBo, 
    @RequestHeader("x-userid") Long userId) {
    
    
    
  logger.info("入参记录:importTablesBo={},userId={}", importTablesBo, userId);
  if (isBlank(importTablesBo.getHiveTableName())) {
    
    
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "hive表名不能为空", null);
  }
  if (isBlank(importTablesBo.getTableImportType())) {
    
    
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "导表类型不能为空", null);
  }
  if (isBlank(importTablesBo.getCron())) {
    
    
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "执行周期表达式不能为空", null);
  }
  if (null == importTablesBo.getDatasetId()) {
    
    
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "工作表id不能为空", null);
  }

  // TODO 调用service层的方法
  ......
  return new ServiceStatusData(ServiceStatusData.Status.Success, "", importTablesBo);
}

启动项目后,使用postman测试,却报出如下错误:

在这里插入图片描述

Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported的错误。

2. 分析错误


首先,将错误信息Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported翻译成中文,便是不支持内容类型'application/x-www-form-urlencoded;charset=UTF-8'

换句话说,我的后端接口导入hive表的接口,不支持application/x-www-form-urlencoded内容类型。

那么application/x-www-form-urlencoded是在哪里定义的呢?

当我在postman选中x-www-form-urlencoded,其便设置Content-Type的属性值为x-www-form-urlencoded,如下图所示:

在这里插入图片描述

x-www-form-urlencodedurl格式的编码,故而,传值为url格式,比如username=tom&pwd=123,一般使用qs库的qs.stringify()方法就能把json对象转换成url格式编码x-www-form-urlencoded

x-www-form-urlencodedpost的默认Content-Type

而我的后端使用@RequestBody来接参,而@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)。

因而,我的错误是:后端接参和前端传参类型不一致,导致后端无法接收到前端的参数,因而,可进行如下修改。

3. 解决错误


因为后端接参和前端传参类型不一致,导致后端无法接收到前端的参数,因而,可以有如下两种解决方法。

3.1 方法1:修改后端接参方式

\

前端的Content-Type的属性值不变,依旧为x-www-form-urlencoded,后端使用如下两种方式来接参:

  1. 后端使用HttpServletRequest类的request.getParameter()方法来接参,如下代码所示:
/**
 * hive表导入
 *
 * @author super先生
 * @datetime 2023/3/20:16:32
 * @return
 */
@ResponseBody
@PostMapping(value = "/xxx/importTables")
public ServiceStatusData localHiveImportTables(
    HttpServletRequest request, 
    @RequestHeader("x-userid") Long userId) {
    
    
    
  ImportTablesBo importTablesBo = new ImportTablesBo();
  importTablesBo.setHiveTableName(request.getParameter("hiveTableName"));
  importTablesBo.setTableImportType(request.getParameter("tableImportType"));
  importTablesBo.setPkColumn(request.getParameter("pkColumn"));
  importTablesBo.setIncrementColumn(request.getParameter("incrementColumn"));
  importTablesBo.setCron(request.getParameter("cron"));
  importTablesBo.setDatasetId(Long.valueOf(request.getParameter("datasetId")));
  logger.info("入参记录:importTablesBo={},userId={}", importTablesBo, userId);
  
  .....
  // TODO 调用service层的方法
  .....
  return new ServiceStatusData(ServiceStatusData.Status.Success, "", importTablesBo);
}

运行结果如下图所示:

在这里插入图片描述

  1. 后端也可以使用@RequestParam注解来接参,如下代码所示:
/**
 * hive表导入
 *
 * @author super先生
 * @datetime 2023/3/20:16:32
 * @return
 */
@ResponseBody
@PostMapping(value = "/xxx/importTables")
public ServiceStatusData localHiveImportTables(
    @RequestParam("hiveTableName") String hiveTableName,
    @RequestParam("tableImportType") String tableImportType,
    @RequestParam("pkColumn") String pkColumn,
    @RequestParam("incrementColumn") String incrementColumn,
    @RequestParam("cron") String cron,
    @RequestParam("datasetId") Long datasetId,
    @RequestHeader("x-userid") Long userId) {
    
    
    
  ImportTablesBo importTablesBo = new ImportTablesBo();
  importTablesBo.setHiveTableName(hiveTableName);
  importTablesBo.setTableImportType(tableImportType);
  importTablesBo.setPkColumn(pkColumn);
  importTablesBo.setIncrementColumn(incrementColumn);
  importTablesBo.setCron(cron);
  importTablesBo.setDatasetId(Long.valueOf(datasetId));
  logger.info("入参记录:importTablesBo={},userId={}", importTablesBo, userId);

  ......
  // TODO 调用service层的方法
  ......
  return new ServiceStatusData(ServiceStatusData.Status.Success, "", importTablesBo);
}

运行结果同上图一样,如下所示:

在这里插入图片描述

3.2 方法2:修改前端传参方式


不修改后端的代码,代码为复现错误中的代码。

既然@RequestBody用来接收前端传递给后端的json字符串,那么,只修改前端的传参方式。

postmanContent-Type的属性值修改为application/json,如下图所示:

在这里插入图片描述

请求参数如下代码所示:

{
    
    
    "hiveTableName": "project",
    "tableImportType": "1",
    "pkColumn": "id",
    "incrementColumn": "projectname",
    "cron": "0 0 11 * * ?",
    "datasetId": 2
}

运行结果如下图所示:

在这里插入图片描述

如果你是前端代码报出的这个错误,可以在前端代码中加上Content-Type: application/json; charset=UTF-8,如下代码所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>content-type为application/json</title>
    <script src="js/jquery-3.4.1.js"></script>
    <script>
        function importTables() {
     
     
            const importTablesReq = {
     
     
                "hiveTableName": "project",
                "tableImportType": "1",
                "pkColumn": "id",
                "incrementColumn": "projectname",
                "cron": "0 0 11 * * ?",
                "datasetId": 2
            };
            $.ajax({
     
     
                url: 'http://localhost:8080/.../importTables.do',
                type: 'post',
                headers: {
     
     
                    "x-userid": 1
                },
                data: JSON.stringify(importTablesReq),
                contentType: "application/json; charset=utf-8",
                success: function (data) {
     
     
                    console.log("data=", data)
                }
            });
        }
    </script>
</head>
<body>
<button type="button" onclick="importTables()">点击按钮获取值</button>
</body>
</html>

在这里插入图片描述

输出结果如下图所示:

在这里插入图片描述

4. 补充说明content-type


一般是指网页中存在的Content-Type(内容类型),用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些PHP网页点击的结果却是下载一个文件或一张图片的原因。

Content-Type标头告诉客户端实际返回的内容的内容类型。

4.1 语法格式

Content-Type: text/html; charset=utf-8

Content-Type: multipart/form-data; boundary=something

实例如下图:

在这里插入图片描述

4.2 常见的类型值

  1. 常见的媒体格式类型:

    • text/htmlHTML格式

    • text/plain :纯文本格式

    • text/xmlXML格式

    • image/gifgif图片格式

    • image/jpegjpg图片格式

    • image/pngpng图片格式

  2. application开头的媒体格式类型:

    • application/xhtml+xmlXHTML格式

    • application/xmlXML数据格式

    • application/atom+xmlAtom XML聚合格式

    • application/jsonJSON数据格式

    • application/pdfpdf格式

    • application/mswordWord文档格式

    • application/octet-stream : 二进制流数据(如常见的文件下载)

    • application/x-www-form-urlencoded<form encType=””>中默认的encTypeform表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

  3. 另外一种常见的媒体格式是上传文件之时使用的:

    • multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

5. 文末总结


正赶上最近ChatGPT比较火,可以借助其分析上述错误,其给出的回答如下:

在这里插入图片描述

读者可以作为简单参考。

猜你喜欢

转载自blog.csdn.net/lvoelife/article/details/129703400