Réponses:
Depuis Spring 3.0, vous pouvez également lever une exception déclarée avec @ResponseStatus
annotation:
@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
est que vous définissez tout un tas de classes d'exceptions bien typées et bien nommées, chacune avec ses propres @ResponseStatus
. De cette façon, vous dissociez votre code de contrôleur du détail des codes d'état HTTP.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
avec une implémentation vide.
À partir de Spring 5.0, vous n'avez pas nécessairement besoin de créer des exceptions supplémentaires:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
En outre, vous pouvez couvrir plusieurs scénarios avec une seule exception intégrée et vous avez plus de contrôle.
Voir plus:
Réécrivez la signature de votre méthode afin qu'elle accepte HttpServletResponse
comme paramètre, afin que vous puissiez l'appeler setStatus(int)
.
setStatus(int)
javadoc déclare comme suit: Si cette méthode est utilisée pour définir un code d'erreur, le mécanisme de page d'erreur du conteneur ne sera pas déclenché. S'il y a une erreur et que l'appelant souhaite invoquer une page d'erreur définie dans l'application Web, elle sendError
doit être utilisée à la place.
Je voudrais mentionner qu'il y a une exception (pas seulement) pour 404 par défaut fournie par Spring. Voir la documentation Spring pour plus de détails. Donc, si vous n'avez pas besoin de votre propre exception, vous pouvez simplement le faire:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
il n'y a pas de traitement de demande de mon point de vue. Pensez-vous qu'il est préférable / plus propre d'utiliser votre propre exception annotée @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
Depuis Spring 3.0.2, vous pouvez renvoyer ResponseEntity <T> à la suite de la méthode du contrôleur:
@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> est une annotation plus flexible que @ResponseBody - voir une autre question )
vous pouvez utiliser @ControllerAdvice pour gérer vos exceptions. Le comportement par défaut de la classe annotée @ControllerAdvice aidera tous les contrôleurs connus.
il sera donc appelé lorsqu'un contrôleur dont vous disposez lance une erreur 404.
comme ceci:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
et mappez cette erreur de réponse 404 dans votre web.xml, comme suit:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
J'espère que cela pourra aider .
Si votre méthode de contrôleur est pour quelque chose comme la gestion de fichiers, alors ResponseEntity
c'est très pratique:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Bien que la réponse marquée soit correcte, il existe un moyen d'y parvenir sans exception. Le service renvoie Optional<T>
l'objet recherché et est mappé à HttpStatus.OK
s'il est trouvé et à 404 s'il est vide.
@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);
}
}
Je recommanderais de lancer HttpClientErrorException , comme ceci
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Vous devez vous rappeler que cela ne peut être fait qu'avant que quoi que ce soit ne soit écrit dans le flux de sortie du 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
C'est un peu tard, mais si vous utilisez Spring Data REST il existe déjà org.springframework.data.rest.webmvc.ResourceNotFoundException
Il utilise également des @ResponseStatus
annotations. Il n'est plus nécessaire de créer une exception d'exécution personnalisée.
De plus, si vous souhaitez renvoyer l'état 404 de votre contrôleur, tout ce dont vous avez besoin est de le faire
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
En faisant cela, vous recevrez une erreur 404 au cas où vous voudriez renvoyer un 404 de votre contrôleur.
Vous pouvez simplement utiliser web.xml pour ajouter un code d'erreur et une page d'erreur 404. Mais assurez-vous que la page d'erreur 404 ne doit pas se trouver sous WEB-INF.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
C'est le moyen le plus simple de le faire, mais cela a certaines limites. Supposons que si vous souhaitez ajouter le même style pour cette page que vous avez ajouté d'autres pages. De cette façon, vous ne pouvez pas faire ça. Vous devez utiliser le@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
partir du code du contrôleur. De l'extérieur, la réponse ne ressemble pas à une 404 normale qui n'a touché aucun contrôleur.
Configurer web.xml avec le paramètre
<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>
Créer un nouveau contrôleur
/**
* 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;
}
}
Parce qu'il est toujours bon d'avoir au moins dix façons de faire la même chose:
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);
}
}