【问题标题】:In Spring-mvc the attribute names in view have to always match the property names in model?在 Spring-mvc 中,视图中的属性名称必须始终与模型中的属性名称匹配?
【发布时间】:2011-05-21 18:44:18
【问题描述】:

在http请求正文中,传递密码字符串的方式是“pass=1111”,但是在bean中定义密码的方式是“私有字符串密码”。有没有办法可以使用注释来处理区别还是我必须始终匹配名称?

Http请求是这样的

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"

处理方法是

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

UserAccountBean 是

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;
    }
}

【问题讨论】:

标签: forms spring-mvc


【解决方案1】:

3.0 中没有基于注释的解决方案。

只需提供额外的 getPass() setPass(String pass) 方法,你就应该被设置。

【讨论】:

    【解决方案2】:

    你可以用这个来实现它:

    @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;
    }
    

    【讨论】:

      【解决方案3】:

      在@InitBinder注解的方法中使用@RequestParam注解,并手动设置所需的值。

      用户控制器

          @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);
          }
      

      有没有办法可以使用注释来 处理差异,否则我必须 总是匹配名称?

      AFAIK 在 Spring MVC 中没有现成的注解可以解决你的问题;您需要自定义设置来处理这种情况。

      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();
      }
      

      用户控制器

      @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;
          }
      
      }
      

      beans.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" />
      

      你也可以在一些辅助类中使用public static void bindWebParameters(...) 方法;所以你不必每次都扩展 AbstractController。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-02
        • 2021-02-02
        • 1970-01-01
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        • 2021-12-03
        相关资源
        最近更新 更多