web-dev-qa-db-fra.com

Le déclencheur 404 dans le contrôleur Spring-MVC?

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.

174
NA.

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(); 
        }
    }
}
302
axtavt

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.

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-arguments

37
matt b

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);

    ...

  }
25
michal.kreuzman

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 )

23
Lu55

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é .

15
user957654

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);
        }
    }
}
10
Ralph

À 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:

9
Joni

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); 
    }

}
7
user1121883

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.

7
mmatczuk

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.

3
pilot

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.

2
AbdusSalam

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)

0
Rajith Delantha

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);
    }
}
0
Jason

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;
        }
}
0
Atish Narlawar