Skip to main content
 首页 » 编程设计

forms之在 Spring-mvc 中, View 中的属性名称必须始终与模型中的属性名称匹配

2025年01月19日24bjzhanghao

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

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

请您参考如下方法:

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

用户 Controller

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

Is there a way I can use annotation to handle the difference or I have to always match names?



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

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

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

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

抽象 Controller
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 。