【问题标题】:Spring Boot Controller does not recognize Path Variable as optionalSpring Boot Controller 不将路径变量识别为可选
【发布时间】:2022-01-03 15:37:47
【问题描述】:

使用 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' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "img".

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

【问题讨论】:

    标签: javascript java spring-boot fetch-api


    【解决方案1】:

    您只定义了资源/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 {
    
        }
      }
    

    【讨论】:

    • 啊谢谢,伙计!我实际上认为将 @RequestMapping("/api/v1/student/img") 注释添加到我的控制器类中会将其设置为所有映射的资源,然后是任何其他映射,例如@GetMapping("/{studentId}") 将被添加。但看来你是对的,我必须添加额外的斜线。非常感谢!
    • 不需要同时使用required = falseOptional
    【解决方案2】:

    /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

    【讨论】:

      【解决方案3】:

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

      如果您使用的是 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();
              }
          }
      

      【讨论】:

        【解决方案4】:

        试试这个。

        在这里你可以找到一些例子 ==> 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();
                }
        
            }
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-10-29
          • 2017-05-17
          • 1970-01-01
          • 2018-01-31
          • 2011-12-12
          • 1970-01-01
          • 2021-08-28
          • 1970-01-01
          相关资源
          最近更新 更多