简体   繁体   中英

Spring MVC 3.0: How to validate path variable that is global to all request mappings efficiently?

I'm trying to get my feet wet with Spring MVC 3.0, and while I can get it to work, I can't seem to handle this particular scenario efficiently.

I have a controller with that handles "/{studyName}/module" prefix, and it looks something like this:-

@Controller
@RequestMapping(value = "/{studyName}/module")
public class ModuleController {

    @RequestMapping(...)
    public ModelAndView getA(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getB(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getC(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getD(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }
}

The problem with this code is, I have the studyName validation scattered all over the methods and possibly in other Controllers' methods too. Is there a way I can perform validation on studyName path variable all in one spot without using something like AOP? How do you handle validation like this?

Thanks.

Right now, it's a little tricky to make this happen automatically, but it is possible. You should use a Bean validation (JSR-303) provider that implements appendix C. Currently that's Apache BeanValidation or Hibernate Validator 4.2 (which is in beta).

Add your chosen bean validation implementation to the classpath. This will be the implementation of JSR-303 that Spring MVC uses.

Second, annotate the method parameter with @Valid and any constraint annotations, like @NonNull.

This will look something like:

public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) {

That should work. You'd then need to check your Spring errors for any problems.

Alternatively, if you don't make use of any other Spring parameters, you can register a validator with an InitBinder like so:

@InitBinder
public void initBinder(WebDataBinder binder) {
  binder.setValidator(new StudyNameValidator());
}

Create a class StudyName then have a WebArgumentResolver registered for StudyName and have your validation take place there.

   public ModelAndView getA(@PathVariable StudyName studyName){
      ...
   }

   public class StudyNameResolver implements WebArgumentResolver{
      //have resolveArgument method do validation if resolved to a StudyName
   }

I am starting to use spring 3 and I do like your solution of validating in this way: public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) {

However, once the pathvariable is invalid (in this case studyName = null) how do you catch and display that error?

I have tried to use binding result but it just doesn't work. In addition, do you know how to display the error on the jsp?

Thanks

Create a simple validation class:

public class StudyValidator {
    public boolean validateStudy(String studyName) {
        //your validate logic here
    }
}

then inject it into the ModuleController :

class ModuleController {
    private StudyValidator sv = new StudyValidator(); //use spring injection to populate.
    boolean validStudy(String studyName) {
        return sv.validateStudy(studyName);
    }
}

Simples.

Hmmm, not sure if it would work, but you might be able to the @Valid annotation as briefly mentioned in this link on validators.

Good Luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM