さまざまなコントローラーメソッドのバリデーターをカスタマイズする可能性がある場合、この検証アプローチがあれば答えを得たいと思います。
シンプルなバリデーター
@Component
public class UserDtoValidator implements Validator {
@Autowired
UserService userService;
@Override
public boolean supports(Class<?> aClass) {
return UserDto.class.isAssignableFrom(aClass);
}
@Override
public void validate(Object target, Errors errors) {
UserDto userDto = (UserDto) target;
}
//how to make 'if' below to be applied only for certain method in controller
//in this case for controller createUser method
if (userService.findByUserName(userDto.getUserName())!=null) {
throw new InvalidPayloadException("Creating user requires unique userName");
}
//second 'if' for controller updateUser method
if (userService.findByUserName(userDto.getUserName())==null) {
throw new InvalidPayloadException("Updating unexisting users is not allowed");
}
}
}
コントローラ:
ここでは、バリデーターに対して 2 つの反対の状況があります。
1 一意の userName を持つユーザーの作成
2 ユーザーの更新 - 必須の userName
@Controller
@RequestMapping(value = "/api/users")
public class ApiUserController extends ExceptionsResolver {
@Autowired
private UserService userService;
@Autowired
private UserDtoValidator userDtoValidator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(userDtoValidator);
}
@RequestMapping(consumes = "application/json", produces = "application/json", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity createUser(@Valid @RequestBody UserDto userDto) throws JsonProcessingException {
userService.saveUser(userDto);
return new ResponseEntity(userDto, HttpStatus.ACCEPTED);
}
@RequestMapping(value = "/{userName}", consumes = "application/json", method = RequestMethod.PUT)
@ResponseBody
public ResponseEntity<UserDto> updateUser(@Valid @RequestBody UserDto userDto, @PathVariable String userName) {
return new ResponseEntity("User updated", HttpStatus.ACCEPTED);
}
}
ところで、PUT が新規作成する必要があることはわかっていますが、ここでは更新目的で PUT だけが必要です。