Comment obtenir un contrôleur Spring 3.0 pour déclencher un 404?
J'ai un contrôleur avec @RequestMapping(value = "/**", method = RequestMethod.GET)
et pour certains RL accédant au contrôleur, je veux que le conteneur fournisse un 404.
Depuis le printemps 3.0, vous pouvez également lancer 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();
}
}
}
Réécrivez la signature de votre méthode afin qu'elle accepte HttpServletResponse
en tant que paramètre afin de pouvoir appeler setStatus(int)
dessus.
Je voudrais mentionner qu'il existe une exception (pas seulement) pour 404 par défaut fournie par Spring. Voir documentation Spring pour plus de détails. Donc, si vous n'avez pas besoin de votre propre exception, vous pouvez simplement faire ceci:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
Depuis Spring 3.0.2, vous pouvez retourner ResponseEntity <T> à la suite de la méthode de l'automate:
@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 plus flexible que l'annotation @ResponseBody - voir autre question )
vous pouvez utiliser le @ ControllerAdvice pour gérer vos exceptions. Le comportement par défaut de la classe annotée @ControllerAdvice assistera tous les contrôleurs connus.
donc, il sera appelé quand un contrôleur que vous avez génère une erreur 404.
comme ce qui suit:
@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 fichier web.xml, comme suit:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
J'espère que ça t'as aidé .
Si votre méthode de contrôleur est quelque chose comme la gestion de fichier, alors ResponseEntity
est très pratique:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
À 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:
Bien que la réponse indiquée soit correcte, il existe un moyen d'y parvenir sans exception. Le service est de retour Optional<T>
de l’objet recherché et mappé sur HttpStatus.OK
si trouvé et à 404 si 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 recommande de jeter 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 d'écrire quoi que ce soit dans le flux de sortie du servlet.
C'est un peu tard, mais si vous utilisez Spring Data REST , il y a déjà org.springframework.data.rest.webmvc.ResourceNotFoundException
Il utilise également @ResponseStatus
annotation. Il n'est plus nécessaire de créer une exception d'exécution personnalisée.
De plus, si vous souhaitez renvoyer le statut 404 de votre contrôleur, il vous suffit 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 si vous souhaitez renvoyer un 404 à partir 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 la façon la plus simple de le faire, mais cela a certaines limites. Supposons que si vous souhaitez ajouter le même style pour cette page, vous avez ajouté d'autres pages. De cette façon, vous ne pouvez pas cela. Vous devez utiliser le @ResponseStatus(value = HttpStatus.NOT_FOUND)
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);
}
}
Configurer web.xml avec les paramètres
<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;
}
}