2016-05-02 18 views
1

Wir verwenden Federschuh für unsere Anwendung. Ich versuche, das lokalisierte Ergebnis in der Antwort zurückzugeben, wenn der Restdienst basierend auf dem Accept-Language-Header aufgerufen wird. Wenn der Accept-Language-Header beispielsweise lautet: zh, ja; q = 0.8, de. Die Antwort wird also auf Chinesisch sein, da wir dies unterstützen.Spring Boot Exception Handling

Aber wenn Accept-Language Header ist: zh1, ja; q = 0.8, de. Dann bekomme ich Interner Serverfehler wie unten, weil er @ExceptionHandler nicht aufrufen kann Ich bekomme keine Antwort, die ich mag. Im Folgenden finden Sie, was ich

{ 
    "timestamp": 1462213062585, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "java.lang.IllegalArgumentException", 
    "message": "java.lang.IllegalArgumentException: range=zh1", 
    "path": "/user/v1//paymentmethods/creditdebitcards" 
} 

Stattdessen bekommen das ist, was ich da für alle anderen Ausnahmen werfen wollen wir damit umgehen und eine ähnliche Reaktion werfen.

{ 
    "operation": { 
    "result": "ERROR", 
    "errors": [ 
     { 
     "code": "1000", 
     "message": "An unidentified exception has occurred.", 
     "field": "" 
     } 
    ], 
    "requestTimeStampUtc": "2016-05-02T18:22:03.356Z", 
    "responseTimeStampUtc": "2016-05-02T18:22:03.359Z" 
    } 
} 

Im Folgenden sind meine Klassen, wenn der Header falsch ist (wie ZH1, ja; q = 0,8, en) dann die Parse-Methode unter wirft 500 Fehler wie oben.

public class SmartLocaleResolver extends AcceptHeaderLocaleResolver { 

    @Autowired 
    ExceptionHandling exceptionHandling; 

    @Autowired 
    MessageHandler messageHandler; 

    @Override 
    public Locale resolveLocale(HttpServletRequest request) { 
     try { 
      List<LanguageRange> list = Locale.LanguageRange.parse(request.getHeader("Accept-Language")); 
      if (!list.isEmpty()) { 
       for (LanguageRange s : list) { 
        if (ApplicationConstants.LOCALE.contains(s.getRange())) { 
         return Locale.forLanguageTag(s.getRange()); 
        } 
       } 
      } 
     } catch (IllegalArgumentException e) { 
      throw new IllegalArgumentException(e); 
     } 
     return request.getLocale(); 
    } 

Unten ist die Exceptionklasse

@EnableWebMvc 
@ControllerAdvice 
public class ExceptionHandling extends ResponseEntityExceptionHandler { 
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandling.class); 

    @Autowired 
    private MessageHandler  messageHandler; 

    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 
    @ExceptionHandler(value = { UnsupportedMediaTypeException.class, InvalidMediaTypeException.class }) 
    public void unsupportedMediaTypeException() { 

    } 

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
    @ExceptionHandler(value = Exception.class) 
    public @ResponseBody OperationsErrorBean handleglobalException(final HttpServletRequest request, 
      final Exception ex) { 
     LOGGER.error("Unhandled Exception Occurred: ", ex); 
     return errorResponse("1000", messageHandler.localizeErrorMessage("error.1000"), "", request.getRequestURI(), 
       request.getAttribute("startTime").toString()); 

    } 
} 

Das ist mein ApplicationConfig.java Klasse ist

@Configuration 
@ComponentScan("com.hsf") 
@EnableWebMvc 
public class ApplicationConfig extends WebMvcConfigurerAdapter { 

    @Value("${spring.application.name}") 
    String appName; 

    @Bean 
    public AlwaysSampler defaultSampler() { 
     return new AlwaysSampler(); 
    } 

    @Override 
    public void addInterceptors(final InterceptorRegistry registry) { 

     if (StringUtils.isNotBlank(appName)) { 
      MDC.put("AppName", appName); 

     } else { 
      MDC.put("AppName", "APPNAME_MISSING"); 
     } 

     registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/user/v1/**"); 
    } 

    @Bean 
    public LocaleResolver localeResolver() { 
     return new SmartLocaleResolver(); 
    } 

    @Bean 
    public DispatcherServlet dispatcherServlet() { 
     final DispatcherServlet servlet = new DispatcherServlet(); 
     servlet.setDispatchOptionsRequest(true); 
     return servlet; 
    } 

    @Bean 
    public MessageSource messageSource() { 
     final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
     messageSource.setBasenames("classpath:i18n/messages"); 
     // If true, the key of the message will be displayed if the key is not 
     // found, instead of throwing an exception 
     messageSource.setUseCodeAsDefaultMessage(true); 
     messageSource.setDefaultEncoding("UTF-8"); 
     // The value 0 means always reload the messages to be developer friendly 
     messageSource.setCacheSeconds(10); 
     return messageSource; 
    } 

} 
+0

Die ExceptionHandling-Klasse behandelt Exception.class, während Ihr Programm IllegalArgumentException auslöst. Seltsam, wie Sie IllegalArugmentException fangen und dann die gleiche Ausnahme neu? Sie sollten es einfach erneut werfen oder gar nicht fangen. –

+0

@ExceptionHandler Annotation sollte in der Lage sein, eine Liste von Ausnahmen zu behandeln? –

+0

@MinhKieu Ich habe alle von ihnen versucht, dieser Code im Catch-Block ist im Grunde versucht ich meine Antwort zu ändern. Ich habe die Dinge, die du bereits erwähnt hast, ausprobiert. Das verursacht kein Problem. Das Problem tritt auf, wenn die Anfrage gemacht wurde. Es wird zuerst zur SmartLocalResolver-Klasse und dann zur ExceptionHander-Klasse aufgerufen. Die Lösung für mein Problem ist ExceptionHandler-Klasse muss vor SmartLocalResolver aufgerufen werden. Aber ich bin mir nicht sicher, wie es im Moment aussieht. – Arun

Antwort

0

Ich habe die Accept-Language-Prüfung im Interceptor und ich werfe eine benutzerdefinierte Ausnahme, die ich erstellt habe, wenn es eine Ausnahme gibt, die den Header analysiert. So werfe ich eine 400 Bad-Anfrage mit einer richtigen Antwort, die ich anzeigen möchte.

public class RequestInterceptor extends HandlerInterceptorAdapter { 
      @Override 
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception { 

       final String startTime = DateUtils.getUTCDate(); 

       request.setAttribute("startTime", startTime); 


       **try { 
        Locale.LanguageRange.parse(request.getHeader("Accept-Language")); 
       } catch (IllegalArgumentException e) { 
        throw new InvalidAcceptLanguageException(); 
       }** 

       return true; 

      } 
     } 

Ich habe eine Methode in meiner Exceptionhandling Klasse hinzugefügt InvalidAcceptLanguageException zu werfen.

@EnableWebMvc 
@ControllerAdvice 
public class ExceptionHandling extends ResponseEntityExceptionHandler { 
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandling.class); 


    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ExceptionHandler(value = InvalidAcceptLanguageException.class) 
    @ResponseBody 
    public OperationsErrorBean invalidAcceptLanguageException(final HttpServletRequest request, final Exception ex) { 
     return errorResponse("N/A", "Accept-Language is not in correct format", "", request.getRequestURI(), 
       request.getAttribute("startTime").toString()); 
    } 
} 
3

Die @ExceptionHandler Anmerkung für die unsupportedMediaTypeException Methode nicht IllegalArgumentException enthält, statt:

@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 
@ExceptionHandler(value = { UnsupportedMediaTypeException.class, 
    InvalidMediaTypeException.class }) 
public void unsupportedMediaTypeException() { } 

es sein sollte:

@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 
@ExceptionHandler(value = { UnsupportedMediaTypeException.class, 
    InvalidMediaTypeException.class, IllegalArgumentException.class }) 
public void unsupportedMediaTypeException() { } 

Da es auch Umgang mit einer Vielzahl von Sprachen scheint eine der Anforderungen Ihrer Anwendung ist schlage ich vor, eine eigene Runtime für diese Situation InvalidAcceptLanguageException anstelle der Verwendung eines generischen IllegalArgumentException für diesen Zweck zu erstellen .

+0

Wenn ich IllegalArgumentException hinzufüge.class es gibt mir den Status als 415 nicht unterstützten Medientyp, aber in dem Moment, als ich den Körper dieser Methode unsupportedMediaTypeException() hinzufügen, um eine sinnvolle Antwort in den Protokollen Fehler beim Aufruf @ExceptionHandler Methode – Arun

+0

Ich habe ApplicationConfig.java Klasse hinzugefügt. Mein Denken ist SmartLocaleResolver wird zuerst aufgerufen und ExceptionHandling-Klasse wird später aufgerufen. Also konnte ich den Fehler 500 nicht überschreiben und die Antwort ändern. – Arun