Respuestas:
Desde Spring 3.0 también puede lanzar una excepción declarada con @ResponseStatus
anotación:
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
@Controller
public class SomeController {
@RequestMapping.....
public void handleCall() {
if (isFound()) {
// whatever
}
else {
throw new ResourceNotFoundException();
}
}
}
@ResponseStatus
es que usted define un montón de clases de excepciones bien tipadas y bien nombradas, cada una con la suya propia @ResponseStatus
. De esa manera, desacoplas el código de tu controlador del detalle de los códigos de estado HTTP.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
con una implementación vacía.
A partir de Spring 5.0, no necesariamente necesita crear excepciones adicionales:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Además, puede cubrir múltiples escenarios con una excepción incorporada y tiene más control.
Ver más:
Vuelva a escribir su firma de método para que acepte HttpServletResponse
como parámetro, de modo que pueda invocarlo setStatus(int)
.
setStatus(int)
javadoc dice lo siguiente: si este método se usa para establecer un código de error, entonces el mecanismo de la página de error del contenedor no se activará. Si hay un error y la persona que llama desea invocar una página de error definida en la aplicación web, sendError
debe usarse en su lugar.
Me gustaría mencionar que hay una excepción (no solo) para 404 por defecto proporcionada por Spring. Consulte la documentación de Spring para más detalles. Entonces, si no necesita su propia excepción, simplemente puede hacer esto:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
de mi punto de vista, no hay manejo de solicitudes. ¿Crees que es mejor / más limpio usar tu propia Excepción anotada @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
Desde Spring 3.0.2 puede devolver ResponseEntity <T> como resultado del método del controlador:
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
if (isFound()) {
// do what you want
return new ResponseEntity<>(HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
(ResponseEntity <T> es una anotación más flexible que @ResponseBody - vea otra pregunta )
puede usar el @ControllerAdvice para manejar sus Excepciones. El comportamiento predeterminado de la clase anotada @ControllerAdvice ayudará a todos los Controladores conocidos.
por lo que se llamará cuando cualquier controlador que tenga arroje un error 404.
como el siguiente:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
y mapee este error de respuesta 404 en su web.xml, como el siguiente:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
Espero que ayude .
Si su método de controlador es para algo como el manejo de archivos, entonces ResponseEntity
es muy útil:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Si bien la respuesta marcada es correcta, hay una manera de lograr esto sin excepciones. El servicio devuelve Optional<T>
el objeto buscado y esto se asigna a HttpStatus.OK
si se encuentra y a 404 si está vacío.
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
return service.find(param).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
@Service
public class Service{
public Optional<Object> find(String param){
if(!found()){
return Optional.empty();
}
...
return Optional.of(data);
}
}
Recomiendo lanzar HttpClientErrorException , como este
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Debe recordar que esto solo se puede hacer antes de escribir algo en la secuencia de salida del servlet.
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
Esto es un poco tarde, pero si está utilizando Spring Data REST, entonces ya existe. org.springframework.data.rest.webmvc.ResourceNotFoundException
También utiliza @ResponseStatus
anotaciones. Ya no es necesario crear una excepción de tiempo de ejecución personalizada.
Además, si desea devolver el estado 404 de su controlador, todo lo que necesita es hacer esto
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
Al hacer esto, recibirá un error 404 en caso de que desee devolver un 404 desde su controlador.
Simplemente puede usar web.xml para agregar código de error y página de error 404. Pero asegúrese de que la página de error 404 no debe ubicarse en WEB-INF.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
Esta es la forma más sencilla de hacerlo, pero tiene algunas limitaciones. Suponga que si desea agregar el mismo estilo para esta página que agregó otras páginas. De esta manera no puedes hacerlo. Tienes que usar el@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
el código del controlador. Ahora, desde el exterior, la respuesta no se ve diferente a un 404 normal que no golpeó ningún controlador.
Configure web.xml con la configuración
<error-page>
<error-code>500</error-code>
<location>/error/500</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
Crear nuevo controlador
/**
* Error Controller. handles the calls for 404, 500 and 401 HTTP Status codes.
*/
@Controller
@RequestMapping(value = ErrorController.ERROR_URL, produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public class ErrorController {
/**
* The constant ERROR_URL.
*/
public static final String ERROR_URL = "/error";
/**
* The constant TILE_ERROR.
*/
public static final String TILE_ERROR = "error.page";
/**
* Page Not Found.
*
* @return Home Page
*/
@RequestMapping(value = "/404", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView notFound() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current.");
return model;
}
/**
* Error page.
*
* @return the model and view
*/
@RequestMapping(value = "/500", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView errorPage() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current, due to the recent site redesign.");
return model;
}
}
Porque siempre es bueno tener al menos diez formas de hacer lo mismo:
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Something {
@RequestMapping("/path")
public ModelAndView somethingPath() {
return new ModelAndView("/", HttpStatus.NOT_FOUND);
}
}