我的控制器。请注意自定义@Exists
注释:
@RestController
public class ClientApiController {
@RequestMapping(path = "/{client}/someaction", method = RequestMethod.GET)
String handleRequest(@Exists Client client) {
// ...
}
}
Exists
注释:
/**
* Indicates that a controller request mapping method parametet should not be
* null. This is meant to be used on model types to indicate a required entity.
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Exists {}
将String
从路径变量转换为Client
实例的转换器:
@Component
public class StringToClient implements Converter<String, Client> {
@Autowired
private ClientDAO clientDAO;
@Override
public Client convert(String source) {
return clientDAO.getClientById(source);
}
}
用于触发404的ResourceNotFoundException
例外
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
}
我的控制器方法根据需要接收转换后的客户端。如果URL中使用的client
id与客户端匹配,则一切正常。如果id不匹配,则client
参数在<{1}}控制器方法中为 为空(使用默认构造函数)。null
我现在无法工作的是声明性检查客户端是否为空(即id指的是现有客户端)。如果它为null,则应抛出handle()
。检查方法体中的参数是否为null并抛出我的自定义ResourceNotFoundException
很容易,但重复性(如this一样)。此外,这种声明方法应该适用于实现接口ResourceNotFoundException
的所有模型类,因此它可以用于多种模型类型。
我搜索过Spring文档,但我还没有找到如何实现这一目标。我需要在类型转换之后和控制器的ModelWithId
方法之前插入一些处理。
我正在使用Spring Boot 1.3.3
答案 0 :(得分:2)
在类型转换之后和控制器方法之前有一个验证。您可以实现自定义验证器并在其中引发异常。将新验证程序添加到DataBinder
,并将方法的参数标记为@Validated
:
@RestController
public class ClientApiController {
@InitBinder
public void initBinder(DataBinder binder){
binder.addValidators(new Validator() {
@Override
public boolean supports(Class<?> aClass) {
return aClass==Client.class;
}
@Override
public void validate(Object o, Errors errors) {
Client client = (Client)o;
if(client.getId()==null) throw new ResourceNotFoundException();
}
});
}
@RequestMapping(path = "/{client}/someaction", method = RequestMethod.GET)
String handleRequest(@Validated @Exists Client client) {
// ...
}
@RequestMapping(path = "/{client}/anotheraction", method = RequestMethod.GET)
String handleAnotherRequest(@Validated @Exists Client client) {
// ...
}
}
当然,您可以将验证器声明为单独的类,并在其他控制器中重复使用它。实际上,您可以在转换器中直接引发异常,但有可能在您的应用程序的其他位置无需例外地进行转换。