Spring REST Service Controller not being validate

2019-09-19 05:11发布

问题:

@Controller
@EnableWebMvc
@Validated
public class ChildController extends ParentController<InterfaceController> implements InterfaceController{

    @Override
    @RequestMapping(value = "/map/{name}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
    @ResponseStatus( HttpStatus.OK)
    @ResponseBody   
    public List<Friends> getAllFriendsByName(
        @Valid
        @Size(max = 2, min = 1, message = "name should have between 1 and 10 characters")
        @PathVariable("name") String name,
        @RequestParam(value="pageSize", required=false) String pageSize,
        @RequestParam(value="pageNumber", required=false) String pageNumber,            
        HttpServletRequest request) throws BasicException {

    //Some logic over here;

    return results;
    }

@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleResourceNotFoundException(ConstraintViolationException e) {
    Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
    StringBuilder strBuilder = new StringBuilder();
    for (ConstraintViolation<?> violation : violations ) {
        strBuilder.append(violation.getMessage() + "\n");
    }
    return strBuilder.toString();
}

Hi, I am trying to do pretty basic validation for a spring request parameter but it just doesn't seem to call the Exception handler, could someone point me into the right direction

P.S. I keep getting NoHandlerFoundException

回答1:

Spring doesn't support @PathVariable to be validated using @Valid. However, you can do custom validation in your handler method or if you insist on using @Valid then write a custom editor, convert your path variable value to an object, use JSR 303 bean validation and then use @Valid on that object. That might actually work.

Edit: Here's a third approach. You can actually trick spring to treat your path variable as a model attribute and then validate it. 1. Write a custom validator for your path variable 2. Construct a @ModelAttribute for your path variable and then use @Validator (yes not @Valid as it doesn't let you specify a validator) on that model attribute.

@Component
public class NameValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }
    @Override
    public void validate(Object target, Errors errors) {
        String name = (String) target;
        if(!StringUtils.isValidName(name)) {
            errors.reject("name.invalid.format");
        }
    }
}

@RequestMapping(value = "/path/{name}", method = RequestMethod.GET)
public List<Friend> getAllFriendsByName(@ModelAttribute("name") @Validated(NameValidator.class) String name) {
    // your code

    return friends;
}

@ModelAttribute("name")
private String nameAsModelAttribute(@PathVariable String name) {
    return name;
}