Spring @MVC and @RequestParam validation

2020-02-20 05:47发布

问题:

I would like to use the @RequestParam annotation like so:

@RequestMapping
public void handleRequest( @RequestParam("page") int page ) {
   ...
}

However, I want to show page 1 if the user fiddles with the URL parameters and tries to go to page "abz" or something non-numerical. Right now, the best I can get Spring to do is return a 500. Is there a way to override this behavior cleanly without having to take in the parameter as a String?

I looked at the @ExceptionHandler annotation, but it doesn't seem to do anything when I set I use @ExceptionHandler(TypeMismatchException.class). Not sure why not.

Suggestions?

P.S. Bonus question: Spring MVC is called Spring MVC. Is Spring MVC with annotations just called Spring @MVC? Google treats them as the same name, which is annoying.

回答1:

Since Spring 3.0, you can set a ConversionService. @InitBinder's value specifies a particular parameter to apply that service to:

@InitBinder("page")
public void initBinder(WebDataBinder binder) {
    FormattingConversionService s = new FormattingConversionService();
    s.addFormatterForFieldType(Integer.class, new Formatter<Integer>() {
        public String print(Integer value, Locale locale) {
            return value.toString();
        }

        public Integer parse(String value, Locale locale)
                throws ParseException {
            try {
                return Integer.valueOf(value);
            } catch (NumberFormatException ex) {
                return 1;
            }
        }
    });
    binder.setConversionService(s);
}


回答2:

The ConversionService is a nice solution, but it lacks a value if you give an empty string to your request like ?page= The ConversionService is simply not called at all, but page is set to null (in case of Integer) or an Exception is thrown (in case of an int)

This is my preferred solution:

@RequestMapping
public void handleRequest( HttpServletRequest request ) {
    int page = ServletRequestUtils.getIntParameter(request, "page", 1);
}

This way you always have a valid int parameter.