我正在尝试使用@ResponseBody实现Spring Web MVC @ExceptionHandler,以返回包含验证错误的对象。 (Strategy E documented here)。
在Spring 3.0.x中,有一个已确认bug,已经解决,禁止此操作正常。我正在使用Spring 3.1.2,而不应该遇到那个。
然而,我遇到了一个异常“无法找到可接受的代表”。
以下是例外:
[10/21/12 12:56:53:296 CDT] 00000045 ExceptionHand E redacted.loggi
ng.jdk14.LogWrapper error Failed to invoke @ExceptionHandler method: public
redacted.model.view.ValidationErrorResponse redacted.controller.Re
stController.handleValidationException(redacted.util.ValidationExceptio
n,javax.servlet.http.HttpServletResponse)
Originating Class/Method:redacted.web.ui.filter.AccessControlFilter.pr
ocessFilter()
org.springframework.web.HttpMediaTypeNotAccepta
bleException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessage
ConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMeth
odProcessor.java:115)
这是代码:
@ExceptionHandler(ValidationException.class)
@ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
@ResponseBody
public ValidationErrorResponse handleValidationException(ValidationException ex, HttpServletResponse response) {
List<ValidationError> errs = new LinkedList<ValidationError>();
for (ObjectError er : ex.getErrors()) {
errs.add(new ValidationError(er.getObjectName(), er.getDefaultMessage()));
}
return new ValidationErrorResponse(errs);
}
@RequestMapping(value = "/search")
@ResponseBody
public SearchResult search(@Valid @ModelAttribute SearchRequest searchRequest, BindingResult bResult) {
if (bResult.hasErrors()) {
throw new ValidationException(bResult.getAllErrors());
}
return searchService.search(searchRequest);
}
有什么想法吗?
答案 0 :(得分:1)
如果你正在读这篇文章,你可能会对我如何使用它有一些疑问。简短的回答是我不知道。我从这里恢复了我的代码并重新实现(实际上是复制并粘贴了控制器位),它突然开始工作了。
如果您使用的是Spring 3.1.2,则@ExceptionHandler和@ResponseBody可以正常工作。
我暂时解释为什么最初不起作用的原因是它可能是用户错误或错误(非常复杂,这个应用程序很大)我正在使用的部署脚本。
答案 1 :(得分:1)
当我需要为一个以“/blah/blah.xml”之类的已知扩展名结尾的请求返回JSON错误响应时,我遇到了这个问题。在这种情况下,Spring支持基于扩展的表示匹配,并忽略Accept标头(最新的Spring 4.1.5也是如此)。
无论请求是什么,我都使用以下内容来“锁定”JSON响应。
@Configuration
@EnableWebMvc
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
configurer.ignoreAcceptHeader(true);
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
答案 2 :(得分:0)
问题似乎是Spring不会如何将ValidationErrorResponse
转换为,例如它应该将其转换为JSON,还是XML或其他东西?尝试返回ResponseEntity,因为您可以直接控制内容类型。
protected ResponseEntity<ValidationErrorResponse> createResponseEntity(ValidationErrorResponse restApiError)
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// assuming your ValidationErrorResponse object has an http code stored in it
HttpStatus responseStatus = HttpStatus.valueOf(restApiError.getHttpStatus());
ResponseEntity<RestApiError> result = new ResponseEntity<>(restApiError, headers, responseStatus);
return result;
}
我在我的应用程序中使用类似的东西,我也有一堆我可以抛出的RuntimeExceptions,其中包含足够的信息,能够生成正确的错误响应。