【发布时间】:2016-07-11 10:57:42
【问题描述】:
我是 Spring Boot 的新手,但是在阅读了几个小时关于 Spring Boot REST 中异常处理的帖子和博客之后,没有人写任何关于处理自定义转换器抛出的此类异常的文章,我决定在这里写。
我基于简单地从 IntelliJ 生成的 Spring Boot 开发小型 REST 应用程序。示例方法如下所示
@RestController
@RequestMapping("/resources")
public class CVResourceService {
private final TechnologyRepository technologyRepository;
private final ProjectRepository projectRepository;
@Autowired
public CVResourceService(TechnologyRepository technologyRepository, ProjectRepository projectRepository) {
this.technologyRepository = technologyRepository;
this.projectRepository = projectRepository;
}
@RequestMapping(value = "/users/{guid}/projects/langs/{lang}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Collection getUserProjects(@PathVariable("guid") GUID userGUID, @PathVariable("lang") Language language) {
return ProjectDTOAssembler.toDTOs(projectRepository.findOne(userGUID, language));
}
}
因为guid 和lang 都是字符串,我希望这些信息从一开始就具有强类型,所以我为GUID 和Language 类型创建了简单的转换器并将其注册到Application 类中:
public final class GUIDConverter implements Converter{
@Override
public GUID convert(String source) {
return GUID.fromString(source);
}
}
public class LanguageConverter implements Converter{
@Override
public Language convert(String source) {
Language language = Language.of(source);
if (language == null) { throw new WrongLanguagePathVariableException(); }
return language;
}
}
GUID 从方法工厂抛出异常,
...
public static GUID fromString(String string) {
String[] components = string.split("-");
if (components.length != 5)
throw new IllegalArgumentException("Invalid GUID string: " + string);
return new GUID(string);
}
...
Language return null 所以我从转换器抛出自定义异常。
在应用程序中注册:
@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new GUIDConverter());
registry.addConverter(new LanguageConverter());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
使用@ResponseStatus、@ControllerAdvice 和@ExpectationHandler 处理所有类型的异常我无法在 Controller 中捕获转换器的异常来重写(或更好的映射)“状态”、“错误”、“异常”和json 错误响应原始字段对我的值的“消息”。可能是因为在调用我的 REST 方法之前引发了异常。我也尝试了ResponseEntityExceptionHandler 的解决方案,但它根本不起作用。
对于正确语言为en 的请求http://localhost:8080/resources/users/620e643f-406f-4c69-3f4c-3f2c303f3f3f/projects/langs/end,响应异常为:
{
"timestamp": 1458812172976,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.method.annotation.MethodArgumentTypeMismatchException",
"message": "Failed to convert value of type [java.lang.String] to required type [com.cybercom.cvdataapi.domain.Language]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.PathVariable com.cybercom.cvdataapi.domain.Language] for value 'end'; nested exception is com.cybercom.cvdataapi.interfaces.rest.converter.WrongLanguagePathVariableException",
"path": "/resources/users/620e643f-406f-4c69-3f4c-3f2c303f3f3f/projects/langs/end"
}
自定义异常仅在message 字段的最后一个位置,但当然应该与我的自定义消息交换。自定义异常应该在exception 字段中,现在是 Spring 异常。这当然是目标,但不知道如何在这种情况下实现它。
请解决我的问题,即捕获转换器抛出的异常并将它们映射为可以使用@ControllerAdvice 和控制器抛出的异常的方式。
提前谢谢。
【问题讨论】:
-
请在您的问题中添加例外
标签: java rest exception-handling spring-boot converter