Usando Spring Boot, implementé un RestController así:
@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(); } }Mi clase ProfilePicture contiene una variable "imagen", que es de tipo byte[]. Estoy tratando de recuperar esta variable.
De todos modos, el problema es que mi controlador no parece tratar mi PathVariable como opcional. Si utilizo fetch-API para enviar una solicitud GET con la siguiente URL:
const url = "http://localhost:8080/api/v1/student/img/" ,
Estoy recibiendo un error:
'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "img" .
¿Alguien sabe cuál podría ser el problema?
Solo define el recurso /api/v1/student/img/{studentId} pero NO el recurso /api/v1/student/img/ .
Entonces, si solo llama a /api/v1/student/img/ como mencionó, debería devolverle 404 Not Found pero no el siguiente error que mencionó:
'java.lang.String' al tipo requerido 'java.lang.Long'; la excepción anidada es java.lang.NumberFormatException: para la cadena de entrada: "img".
Creo que en realidad estás llamando a /api/v1/student/img/img en su lugar. Como img no es Long y de ahí el error.
Si solo desea llamar a /api/v1/student/img/ sin ninguna ID de estudiante, debe definir otro recurso para ello (consulte a continuación). Técnicamente, son recursos diferentes.
@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 { } } O definiendo dos rutas de recursos en @GetMapping con Optional en el parámetro:
@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 { } }/api/v1/student/img/ no coincide con /api/v1/student/img/{studentId} . Entonces su mapeo no funcionará.
Además de otras respuestas, en mi opinión, la mejor manera de manejar esto es agregar otro mapeo al mismo método.
@GetMapping( {"/","/{studentId}"}) public void getProfilePicture(@PathVariable(required = false) Long studentId, HttpServletResponse response) throws IOException { }Obtenga más información aquí https://medium.com/latesttechupdates/define-spring-opcional-ruta-variables-1188fadfebde
No puede tener variables de ruta opcionales, pero puede tener dos métodos de controlador que llamen al mismo código de servicio: pero
Si está usando Java 8 y superior y Spring 4.1 y superior, puede usar java.util.Optional que es compatible con @RequestParam, @PathVariable, @RequestHeader y @MatrixVariable en Spring MVC
@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(); } }