2010-07-12 4 views
28

avec Spring 3, j'aime créer un gestionnaire d'exception en utilisant l'annotation ExceptionHandler qui traitera "aucune page trouvée (404)" demandes. J'utilise le code suivant pour le faire. Mais lorsque je pointe vers une URL qui n'existe pas, le gestionnaire d'exceptions par défaut défini par Spring est appelé. Il se peut que je gère l'exception NoSuchRequestHandlingMethodException. Si c'est le cas, quelle exception devrais-je enregistrer?Spring 3 - Créer ExceptionHandler pour NoSuchRequestHandlingMethodException

Pourriez-vous s'il vous plaît jeter un oeil au code suivant et voir ce que je fais mal?

REMARQUE: Si je change l'exception dans le @ExceptionHandler à NullPointerException et créer un RequestMapping jeter un pointeur nul, cela fonctionnera.

import org.springframework.stereotype.Controller; 
    import org.springframework.web.bind.annotation.ExceptionHandler; 
    import org.springframework.web.bind.annotation.RequestMapping; 

    import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException; 

    import org.apache.commons.logging.Log; 
    import org.apache.commons.logging.LogFactory; 
    import org.springframework.web.servlet.ModelAndView; 

    @Controller 
    public class GeneralHandler { 
     private final Log logger = LogFactory.getLog(getClass()); 

     @ExceptionHandler(NoSuchRequestHandlingMethodException.class) 
     public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) { 
     ModelAndView mav = new ModelAndView(); 
     logger.error("Exception found: " + ex); 
     return mav; 
     } 
    } 

Répondre

41

@ExceptionHandler méthodes -annotated sont invoquées lorsqu'une méthode @RequestMapping sur cette même classe lève une exception. Donc, lorsque vous avez ajouté le mappage qui a lancé le NullPointerException, cela a fonctionné, car la méthode mappée et le gestionnaire d'exceptions étaient ensemble dans la même classe. Lorsqu'aucun mappage n'est trouvé, Spring n'a aucun moyen d'associer le NoSuchRequestHandlingMethodException à votre @ExceptionHandler, car il n'a pas réussi à faire correspondre la requête à une méthode de gestionnaire. Ce n'est pas mentionné explicitement dans les docs, mais c'est le comportement que j'ai observé.

Si vous voulez gérer cette exception spécialement, vous devrez utiliser le HandlerExceptionResolver approach plutôt que la technique plus spécialisée @ExceptionHandler.

+2

Merci. J'utiliserai l'approche HandlerExceptionResolver. – sgsweb

+0

ça a marché pour vous? J'ai toujours le même problème – SJS

2

Vous pouvez aller avec l'approche this, c'est une excellente idée et fonctionne, nécessité de lancer des exceptions seulement avec Handler particulier rend @ExceptionHandler pas si utile que ça en a l'air.

16

Au printemps 3.2, vous pouvez utiliser @ContollerAdvice d'avoir un ExceptionHandler pour tous vos contrôleurs comme ceci:

@ControllerAdvice 
public class GeneralHandler { 

    @ExceptionHandler 
    public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) { 
     ModelAndView mav = new ModelAndView(); 
     ... 
     return mav; 
    } 
} 

Vous pouvez même ajouter des annotations à retourner JSON sérialisé

@ExceptionHandler 
    @ResponseBody 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    public RestError resolveBindingException (MethodArgumentNotValidException methodArgumentNotValidException, Locale locale) 
    { 
     BindingResult bindingResult = methodArgumentNotValidException.getBindingResult(); 
     return getRestError(bindingResult, locale); 
    } 
+0

C'est à peu près ce que j'ai fini par faire, mais comme j'utilisais aussi ContentNegotiatingViewResolver, j'ai fini par attraper 'Exception', puis en enveloppant cela dans une classe avec des annotations de sérialisation JSON et XML et en retournant ça au lieu de ModelAndView, le client finit par obtenir la version sérialisée de l'objet wrapper. –

Questions connexes