2010-12-07 19 views
4

Dans le corps de la requête http, la façon dont le mot de passe est transmis est "pass = 1111", mais dans le bean, le mot de passe défini est "private string password". ou je dois correspondre toujours des noms?Dans Spring-mvc les noms d'attribut dans la vue doivent toujours correspondre aux noms de propriété dans le modèle?

La demande Http est comme ce

curl -H "Accept:text/html" -H "Content-Type application/x-www-form-urlencoded" -d 'email=test%40gmail.com&pass=1111&passconfirm=1111&name=x+y' "http://localhost:8080/project/register" 

méthode Handler est

@RequestMapping(method = RequestMethod.POST, headers = "content-type=application/x-www-form-urlencoded") 
public String register(@ModelAttribute UserAccountBean account) ... 

UserAccountBean est

public class UserAccountBean2 { 
    @NotNull 
    @Size(min = 1, max = 25) 
    private String name; 

    @NotNull 
    @Size(min = 4, max = 8) 
    private String password; 

    @NotNull 
    private String email; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getPassword() 
    { 
     return password; 
    } 

    public void setPassword(String password) 
    { 
     this.password = password; 
    } 

    public String toString() { 
     return new ToStringCreator(this).append("name", name).append("password", password).toString(); 
    } 

    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 
} 
+0

Voir http://stackoverflow.com/q/8986593 pour de très belles solutions à ce problème ... – Simon

Répondre

3

Utilisation annotation @RequestParam dans la méthode annotée de @InitBinder, et régler manuellement la valeur de consigne.

UserController

@InitBinder(value="user") 
    public void bind(WebDataBinder dataBinder, WebRequest webRequest, @RequestParam(value="pass", required=false) String password) { 
     User user = (User) dataBinder.getTarget(); 
     user.setPassword(password); 
    } 

Est-il possible que je peux utiliser l'annotation pour gérer la différence ou je dois correspondre toujours des noms?

AFAIK il n'y a pas d'annotation prête à l'emploi dans Spring MVC qui peut résoudre votre problème; vous avez besoin d'une configuration personnalisée pour gérer la situation.

WebModelAttribute

@Target({ElementType.METHOD, ElementType.PARAMETER}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface WebModelAttribute { 
String modelAttributeName(); 
    WebParameterMapping[] parameterMappings(); 
} 

WebParameterMapping

@Target({ElementType.METHOD, ElementType.PARAMETER}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface WebParameterMapping { 
    String webProperty(); 
    String beanProperty(); 
} 

UserController

@Controller 
public class UserController extends AbstractController { 

    @Override 
    @InitBinder(value="user") 
    @WebModelAttribute(modelAttributeName="user", parameterMappings={@WebParameterMapping(webProperty="pass", beanProperty="password")}) 
    protected void bindWebParameters(WebDataBinder dataBinder, WebRequest webRequest, WebParameterResolver mappingResolver) { 
     super.bindWebParameters(dataBinder, webRequest, mappingResolver); 
    } 

AbstractController

public class AbstractController { 

    protected void bindWebParameters(WebDataBinder dataBinder, WebRequest webRequest, WebParameterResolver mappingResolver) { 
     if(mappingResolver != null && dataBinder.getTarget() != null && dataBinder.getObjectName().equals(mappingResolver.getModelAttributeName())) { 
      String[] allowedFields = mappingResolver.getAllowedFields(dataBinder.getAllowedFields()); 
      String[] disallowedFields = mappingResolver.getDisallowedFields(dataBinder.getDisallowedFields()); 

      dataBinder.setAllowedFields(allowedFields); 
      dataBinder.setDisallowedFields(disallowedFields); 

      dataBinder.bind(mappingResolver.getPropertyValues(dataBinder, webRequest)); 
     } 
    } 

} 

WebParameterResolver

public class WebParameterResolver { 

    private String modelAttributeName; 
    private WebParameterMapping[] parameterMappings; 

    public WebParameterResolver(String modelAttributeName, 
      WebParameterMapping[] parameterMappings) { 
     this.modelAttributeName = modelAttributeName; 
     this.parameterMappings = parameterMappings; 
    } 

    public String getModelAttributeName() { 
     return modelAttributeName; 
    } 

    public String[] getDisallowedFields(String[] existingDisallowedFields) { 
     List<String> disallowedFields = new ArrayList<String>(); 
     for (WebParameterMapping parameterMapping : parameterMappings) { 
      disallowedFields.add(parameterMapping.webProperty()); 
     } 
     if (existingDisallowedFields != null) { 
      for (String disallowedField : existingDisallowedFields) { 
       disallowedFields.add(disallowedField); 
      } 
     } 
     return disallowedFields.toArray(new String[disallowedFields.size()]); 
    } 

    public String[] getAllowedFields(String[] existingAllowedFields) { 
     List<String> allowedFields = new ArrayList<String>(); 
     for (WebParameterMapping parameterMapping : parameterMappings) { 
      allowedFields.add(parameterMapping.beanProperty()); 
     } 
     if (existingAllowedFields != null) { 
      for (String allowedField : existingAllowedFields) { 
       allowedFields.add(allowedField); 
      } 
     } 
     return allowedFields.toArray(new String[allowedFields.size()]); 
    } 

    public MutablePropertyValues getPropertyValues(WebDataBinder dataBinder, 
      WebRequest webRequest) { 
     MutablePropertyValues propertyValues = new MutablePropertyValues(); 
     for (WebParameterMapping parameterMapping : parameterMappings) { 
      String[] values = webRequest.getParameterValues(parameterMapping.webProperty()); 
      if (values == null || values.length == 0) { 
       // do nothing 
      } else if (values.length == 1) { 
       propertyValues.add(parameterMapping.beanProperty(), values[0]); 
      } else { 
       propertyValues.add(parameterMapping.beanProperty(), values); 
      } 
     } 
     dataBinder.bind(propertyValues); 
     return propertyValues; 
    } 

} 

CustomArgumentResolver

public class CustomArgumentResolver implements WebArgumentResolver { 

    @Override 
    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception { 

     if(methodParameter.getParameterType().equals(WebParameterResolver.class)) { 
      WebModelAttribute webModelAttribute = methodParameter.getMethod().getAnnotation(WebModelAttribute.class); 
      if(webModelAttribute == null) { 
       throw new RuntimeException("method must have WebModelAttribute"); 
      } 
      return new WebParameterResolver(webModelAttribute.modelAttributeName(), webModelAttribute.parameterMappings()); 
     } 

     return UNRESOLVED; 
    } 

} 

haricots.xml

<bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="customArgumentResolvers" ref="timetracking.annotations.CustomArgumentResolver"/> 
    </bean> 
<bean name="timetracking.annotations.CustomArgumentResolver" 
     class="timetracking.annotations.CustomArgumentResolver" /> 

Vous pouvez également avoir une méthode public static void bindWebParameters(...) dans une classe d'aide; vous n'avez donc pas à étendre le AbstractController à chaque fois.

0

Il n'existe aucune solution basée sur des annotations dans la version 3.0. Il suffit de fournir la méthode supplémentaire getPass() setPass (chaîne de caractères) et vous devez l'activer.

4

On peut y parvenir avec celle-ci:

@RequestMapping(method = RequestMethod.POST, headers = "content-type=application/x-www-form-urlencoded") 
public String register(@ModelAttribute("userAccountBean") UserAccountBean account) ... 

@ModelAttribute("userAccountBean") 
public UserAccountBean getUserAccountBean(HttpServletRequest req) { 
    UserAccountBean uab = new UserAccountBean(); 
    uab.setPassword(req.getParameter("pass")); 
    return uab; 
}