Spring Boot 控制器无法将路径变量识别为可选

问题描述 投票:0回答:4

使用 Spring Boot,我实现了一个 RestController,如下所示:

@RestController
@RequestMapping("/api/v1/student/img")
@CrossOrigin("*")
public class ProfilePictureController {

    @GetMapping( "/{studentId}")
    public void getProfilePicture(@PathVariable(required = false) Long studentId, HttpServletResponse response) throws IOException {
        Optional<ProfilePicture> profilePicture;
        if (studentId != null) {
            profilePicture= studentService.getProfilePictureByStudentId(studentId);
        } else {
            profilePicture= studentService.getProfilePicture(1L);
        }
        if (profilePicture.isPresent()) {
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(profilePicture.get().getImage());
            outputStream.close();
        }
    }

我的 ProfilePicture 类包含一个变量“image”,其类型为 byte[]。我正在尝试检索这个变量。

无论如何,问题是我的控制器似乎没有将我的 PathVariable 视为可选。如果我使用 fetch-API 发送具有以下 URL 的 GET 请求:

const url = "http://localhost:8080/api/v1/student/img/" 

我收到错误:

'java.lang.String' 为所需类型 'java.lang.Long';嵌套异常 是 java.lang.NumberFormatException: 对于输入字符串:“img”

有谁知道可能是什么问题吗?

javascript java spring-boot fetch-api
4个回答
2
投票

您只定义了资源

/api/v1/student/img/{studentId}
,但没有定义资源
/api/v1/student/img/

因此,如果您按照您提到的那样调用

/api/v1/student/img/
,它应该返回 404 Not Found 但不是您提到的以下错误:

“java.lang.String”为所需类型“java.lang.Long”;嵌套异常 是 java.lang.NumberFormatException: 对于输入字符串:“img”。

我相信您实际上是在打电话给

/api/v1/student/img/img
。由于
img
不是 Long,因此会出现错误。

如果您只想在没有任何 StudentId 的情况下调用

/api/v1/student/img/
,您应该为其定义另一个资源(见下文)。从技术上讲,它们是不同的资源。

@RestController
@RequestMapping("/api/v1/student/img")
@CrossOrigin("*")
public class ProfilePictureController {

    @GetMapping( "/{studentId}")
    public void getProfilePicture(@PathVariable(required = false) Long studentId, HttpServletResponse response) throws IOException {

    }


    @GetMapping
    public void getProfilePicture(HttpServletResponse response) throws IOException {
   
    }

  }

或者在

@GetMapping
上定义两个资源路径,并在参数上使用
Optional
:

@RestController
@RequestMapping("/api/v1/student/img")
@CrossOrigin("*")
public class ProfilePictureController {

    @GetMapping( {"/", "/{studentId}"})
    public void getProfilePicture(@PathVariable(required = false) Optional<Long> studentId, HttpServletResponse response) throws IOException {

    }
  }

1
投票

/api/v1/student/img/
/api/v1/student/img/{studentId}
不匹配。所以你的映射将不起作用。

除了其他 anwser 之外,我认为处理此问题的最佳方法是向同一方法添加另一个映射。

@GetMapping( {"/","/{studentId}"})
    public void getProfilePicture(@PathVariable(required = false) Long studentId, HttpServletResponse response) throws
        IOException {

    }

在此处了解更多信息https://medium.com/latesttechupdates/define-spring-optional-path-variables-1188fadfebde


0
投票

您不能有可选的路径变量,但您可以有两个调用相同服务代码的控制器方法: 但是

如果您使用 Java 8 及更高版本和 Spring 4.1 及更高版本,您可以使用 Spring MVC 中的 @RequestParam、@PathVariable、@RequestHeader 和 @MatrixVariable 支持的 java.util.Optional

@RestController
@RequestMapping("/api/v1/student/img")
@CrossOrigin("*")
public class ProfilePictureController {

    @GetMapping( "/{studentId}")
    public void getProfilePicture(@PathVariable Optional<Long> type studentId, HttpServletResponse response) throws IOException {
        Optional<ProfilePicture> profilePicture;
        if (studentId.isPresent()) {
            profilePicture= studentService.getProfilePictureByStudentId(studentId.get());
        } else {
            profilePicture= studentService.getProfilePicture(1L);
        }
        if (profilePicture.isPresent()) {
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(profilePicture.get().getImage());
            outputStream.close();
        }
    }

0
投票

试试这个。

在这里您可以找到一些示例==> https://www.baeldung.com/spring-pathvariable

@GetMapping( {"/","/{studentId}"})
    public void getProfilePicture(@PathVariable Long studentId, HttpServletResponse response) throws
        IOException {

        Optional<ProfilePicture> profilePicture;
        if (studentId != null) {
            profilePicture= studentService.getProfilePictureByStudentId(studentId);
        } else {
            profilePicture= studentService.getProfilePicture(1L);
        }
        if (profilePicture.isPresent()) {
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(profilePicture.get().getImage());
            outputStream.close();
        }

    }

© www.soinside.com 2019 - 2024. All rights reserved.