【问题标题】:Cannot return String from @RestController method无法从 @RestController 方法返回字符串
【发布时间】:2022-01-23 00:54:54
【问题描述】:

我正在使用 Spring Boot 2.4.5、MyBatis 3.5.6 和 Java 8。当尝试从 @RestController 返回字符串时,返回的 HttpErrorResponse 中显示一个模糊的错误。

该方法尝试通过 MyBatis 获取值,即 DAO 对象中充当@Mapper 的方法。

我的控制器方法:

@RestController
@RequestMapping("/api/myAPI")
public class MyController{
    @Resource
    private MyService service;

    @GetMapping(value = "myString")
    public String getBillingCompany() {
        return this.service.getDAO().getMyString();
    }
}

我的 DAO:

@Repository
@Mapper
public interface MyDAO{
    String getMyString();
}

...和 ​​MyBatis 映射器:

<mapper namespace="com.package.MyDAO">
    <select id="getMyString" resultType="String">
        SELECT 'My desired result' FROM A_TABLE
    </select>
    ...
</mapper>

HttpErrorResponse:

HttpErrorResponse: {
    "headers": {
        "normalizedNames": {},
        "lazyUpdate": null
    },
    "status": 200,
    "statusText": "OK",
    "url": "http://localhost:4200/api/myAPI/myString",
    "ok": false,
    "name": "HttpErrorResponse",
    "message": "Http failure during parsing for http://localhost:4200/api/myAPI/myString",
    "error": {
        "error": {  SyntaxError: Unexpected number in JSON at position 2
                    at JSON.parse (<anonymous>)
                    at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:18158:51)
                    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:21266:35)
                    at Object.onInvokeTask (http://localhost:4200/vendor.js:74037:33)
                    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:21265:40)
                    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (http://localhost:4200/polyfills.js:21033:51)
                    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:21348:38)
                    at invokeTask (http://localhost:4200/polyfills.js:22516:18)
                    at XMLHttpRequest.globalZoneAwareCallback (http://localhost:4200/polyfills.js:22553:25)
                 },
        "text": "My desired result"
    }
}

尽管如此,如果我要求控制器和 DAO 方法返回一个int,一切都会完美无缺。

因此,我怀疑问题与非原始类型“命名空间”有关,因此我尝试在 MyBatis 配置中设置typeAlias,但无济于事:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias type="java.lang.String" alias="String"/>
    </typeAliases>
</configuration>

无论如何,我的印象是 MyBatis 和 Spring 都应该已经足够聪明,可以知道 String 是什么。我过去成功返回了对象集合(Maps 和 Lists)和 POJO。

关于我缺少或没有看到的任何想法?提前致谢。

编辑: 到目前为止,唯一对我有用的东西类似于@emeraldjava 提出的建议。我在依赖项中的现有包装器上构建了一个包装器,在我的前面获取data

@RestController
@RequestMapping("/api/myAPI")
public class MyController{
    @Resource
    private MyService service;

    @GetMapping(value = "myString")
    public Result<String> getBillingCompany() {
        return new Result<>(this.service.getDAO().getMyString());
    }
}
public class Result<T> extends ServiceResult {
    public Result(T data) {
        this.setData(data);
    }
}

依赖项中已经存在的包装器:

public class ServiceResult {
    private Object data;

    ...

    public void setData(Object data) {
        this.data = data;
    }

    public Object getData() {
        return this.data;
    }
}

【问题讨论】:

  • 我对 mybatis 不熟悉,只是想规范一些事情——你有 getMyString() 返回的字符串样本吗?我会想象 StringHttpMessageConverter 会启动并将字符串写为文本/纯文本,但该错误有效负载很有趣。好奇是否存在堆栈跟踪,好奇如果将生成文本纯文本添加到 GetMapping 会发生什么。

标签: spring rest java-8 mybatis primitive-types


【解决方案1】:

我建议您将 Controller 方法更新为包装字符串的 ResponseEntity。

@RestController
@RequestMapping("/api/myAPI")
public class MyController{
    @Resource
    private MyService service;

    @GetMapping(value = "myString")
    public ResponseEntity getBillingCompany() {
        return new ResponseEntity<Object>(this.service.getDAO().getMyString(), HttpStatus.OK);
    }
}

【讨论】:

  • 刚刚试了一下,没有成功。不过感谢您的帮助!
【解决方案2】:

我认为问题在于您要查询的表有多行,因此您的查询结果将是一个字符串列表,每个元素都包含“我想要的结果”,其中列表的大小是等于表中的行数。为了强制单个结果,只需将查询更改为:

<select id="getMyString" resultType="String">
        SELECT MAX('My desired result') FROM A_TABLE
</select>

【讨论】:

  • 试过了,还是一样的结果:(
  • 一切看起来都正确。既然您说您尝试使用整数并且它有效,那么可能是使用旧依赖项的问题?我会尝试重新加载它们,并重建项目
猜你喜欢
  • 1970-01-01
  • 2016-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
相关资源
最近更新 更多