我有一个如下的全局异常处理程序:-
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
@ExceptionHandler(value= {HttpMessageNotReadableException.class})
public final ResponseEntity<ErrorDetails> validationException(HttpMessageNotReadableException ex, WebRequest request) {
System.out.println("This was called.");
if(ex.getCause() instanceof CsvRequiredFieldEmptyException){
CsvRequiredFieldEmptyException csvExp = (CsvRequiredFieldEmptyException) ex.getCause();
String exceptionDtls = csvExp.getMessage().concat(" ").concat(" at line number "+csvExp.getLineNumber()+ " in the csv filw.");
ErrorDetails errorDetails = new ErrorDetails(LocalDate.now(),exceptionDtls, request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
}
我通过使用TestRestTemplate进行集成测试来调用其余的API。
ResponseEntity<?> response = restTemplate.exchange(ITestUtils.createURLWithPort(postUrlCsv,
host,port ), HttpMethod.POST,listingDocEnt, String.class);
@Test
public void uploadListingCsvTest_Returns400BadReq_WhenCodeMissing() throws HttpMessageNotReadableException {
// Step 1 : Create the Http entity object which contains the request body and headers.
HttpEntity<ListingList> listingDocEnt = new HttpEntity<ListingList>(createTestDataForNewVehicleListingCodeMissing(),
getHttpHeaderCsv());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
List<HttpMessageConverter<?>> csvMessgeonverter = new ArrayList<>();
csvMessgeonverter.add(new CsvHttpMessageConverter<>());
csvMessgeonverter.add(converter);
TestRestTemplate restTemplate = new TestRestTemplate();
restTemplate.getRestTemplate().setMessageConverters(csvMessgeonverter);
ResponseEntity<?> response = restTemplate.exchange(ITestUtils.createURLWithPort(postUrlCsv,
host,port ), HttpMethod.POST,listingDocEnt, String.class);
// Check if the response is not null and the http status code is - 201 Created.
Assert.assertNotNull(response);
Assert.assertEquals(HttpStatus.BAD_REQUEST,response.getStatusCode());
}
我的rest API具有自定义HttpMessageConverter,如下所示,它将输入请求csv转换为rest控制器中的java对象。此自定义消息转换器具有方法readInternal,该方法抛出异常HttpMessageNotReadableException,但仍未调用异常处理程序方法'validationException'。 Junit只会崩溃而失败。
public class CsvHttpMessageConverter<T, L extends ListParam<T>>
extends AbstractHttpMessageConverter<L> {
public CsvHttpMessageConverter () {
super(new MediaType("text", "csv"));
}
@Override
protected boolean supports (Class<?> clazz) {
return ListParam.class.isAssignableFrom(clazz);
}
@Override
protected L readInternal (Class<? extends L> clazz,HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
Class<T> t = toBeanType(clazz.getGenericSuperclass());
strategy.setType(t);
CSVReader csv = new CSVReader(new InputStreamReader(inputMessage.getBody()));
CsvToBean<T> csvToBean = new CsvToBean<>();
List<T> beanList = null;
try {
beanList = csvToBean.parse(strategy, csv);
} catch(Exception exception){
throw new HttpMessageNotReadableException("Exception while parsing the CSV file.",exception.getCause());
}
try {
L l = clazz.newInstance();
l.setList(beanList);
return l;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
@Override
protected void writeInternal (L l, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(toBeanType(l.getClass().getGenericSuperclass()));
OutputStreamWriter outputStream = new OutputStreamWriter(outputMessage.getBody());
StatefulBeanToCsv<T> beanToCsv =
new StatefulBeanToCsvBuilder(outputStream)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withMappingStrategy(strategy)
.build();
try {
beanToCsv.write(l.getList());
} catch (CsvDataTypeMismatchException e) {
throw new HttpMessageNotWritableException("Exception while parsing the CSV file.",e);
} catch (CsvRequiredFieldEmptyException e) {
throw new HttpMessageNotWritableException("Exception while parsing the CSV file.",e);
}
outputStream.close();
}
@SuppressWarnings("unchecked")
private Class<T> toBeanType (Type type) {
return (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
有没有一种方法,当使用TestRestTemplate调用Spring Rest API时,我们可以在出现异常时调用异常处理程序方法吗?
答案 0 :(得分:0)
我认为这里的问题是HttpMessageNotReadableException不是由Controller引发的,而是由Spring基础结构在调用控制器之前引发的。
但是@ControllerAdvice仅处理Controller引发的异常。
在Spring的DispatcherServlet中,还有一个ErrorHandler在这种情况下被调用。也许这是您的解决方案?
以下是一些有关此的信息: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#going-deeper