【问题标题】:Data binding without using spring taglib for a variable begining with underscore "_"对以下划线“_”开头的变量不使用 spring taglib 的数据绑定
【发布时间】:2013-01-04 13:40:08
【问题描述】:

我的 html 是在没有使用 spring taglib 的情况下构建的,现在我想将表单的参数绑定到我的控制器中的一个对象。 我在绑定以下划线“_”开头的属性时遇到问题

目前我的表单是这样的

<form method="post" action="${pageContext.request.contextPath}/test.form">
          <input type="text" name="_NumeroPage" />
      <input type="text" name="_Tri" />
      <input type="text" name="_SensTri" />
      <input type="text" name="codePays" />
</form>

我的对象的相关部分是

Class TestForm{
private String _NumeroPage;
private String _Tri;
private String _SensTri;
private String codePays ;
// getter and setter
}

我的控制器是

@RequestMapping(value={"/test","/test.form"})
public String paginerSequencesSuiviMulticanal(TestForm formulaire, Model model, HttpSession session){

        model.addAttribute("_NumeroPage", formulaire.get_NumeroPage());
        model.addAttribute("_Tri", formulaire.get_Tri());
        model.addAttribute("_SensTri", formulaire.get_SensTri());
        model.addAttribute("codePays", formulaire.getCodePays());

    return "/result";
}

我该如何绑定它。目前,_NumeroPage、_Tri、SensTri 的绑定不会发生,但它确实绑定了 codePays。 是否有解决方法来绑定以下划线字符“”开头的属性?

【问题讨论】:

    标签: html spring data-binding spring-mvc


    【解决方案1】:

    您可能可以深入研究 Spring 中的 bean 属性访问器代码并找出原因(在粗略检查代码或文档中找不到任何东西),但似乎更简单的解决方案是 在涉及数据绑定的类和字段中使用带前导下划线的名称。

    【讨论】:

    • 我想我知道答案了。这是因为 spring 使用下划线绑定 chekbox static.springsource.org/spring/docs/3.0.x/…" 复选框标记遵循现有的 Spring 约定,为每个复选框包含一个以下划线 ("_") 为前缀的隐藏参数。
    • 问题是我正在处理一个已迁移到 spring 的旧项目。并且有太多带有“”的变量无法更改。在一个完美的世界中,我永远不会使用“”来命名 java 中属性的开头 ^_^ 我必须为此找到解决方法...
    • 你可能会花费更多的时间来尝试解决这个问题,而不是仅仅更改所有字段并获取/设置方法名称以符合约定,所以我会这样做。当然,这可能是无聊的工作,但所有体面的 IDE:s 都具有重构支持,因此您可以轻松地重命名方法和字段,并且 IDE 将自动重命名所有出现的事件。最后,您将花费更少的时间,并且您将获得更好的代码。当你可以重构时,不要做丑陋的黑客攻击。
    【解决方案2】:

    您可以尝试创建ServletRequestDataBinder 的自定义子类,它将以下划线开头的请求参数映射到不带下划线的字段。然后您必须创建一个自定义的ServletRequestDataBinderFactory 来创建一个子类。接下来,您需要创建 RequestMappingHandlerAdapter 的自定义子类并将其注册到 Spring MVC。这将允许您继续在 HTML 中使用下划线,而不必在 POJO 字段名称中使用下划线。

    自定义 ServletRequestDataBinder:

    public class MyCustomServletRequestDataBinder extends
      ExtendedServletRequestDataBinder {
      public MyCustomServletRequestDataBinder(Object target) {
        super(target);
      }
    
      public MyCustomServletRequestDataBinder(Object target, String objectName) {
        super(target, objectName);
      }
    
      @Override
      protected void addBindValues(MutablePropertyValues mpvs,
          ServletRequest request) {
        super.addBindValues(mpvs, request);
    
        addUnderscoreBindValues(mpvs, request);
      }
    
      protected void addUnderscoreBindValues(MutablePropertyValues mpvs,
          ServletRequest request) {
        // go through each parameter and check if it starts with an underscore (_)
        // if it starts with an underscore, add it to mpvs under the name without
        // the underscore
        @SuppressWarnings("unchecked")
        Map<String, Object> parameterMap = request.getParameterMap();
        for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {
          if (StringUtils.startsWith(entry.getKey(), "_")) {
            mpvs.add(StringUtils.removeStart(entry.getKey(), "_"), entry.getValue());
          }
        }
      }
    }
    

    自定义 ServletRequestDataBinderFactory:

    public class MyCustomServletRequestDataBinderFactory extends
        ServletRequestDataBinderFactory {
      /**
       * Create a new instance.
       * @param binderMethods one or more {@code @InitBinder} methods
       * @param initializer provides global data binder initialization
       */
      public MyCustomServletRequestDataBinderFactory(
          List<InvocableHandlerMethod> binderMethods,
          WebBindingInitializer initializer) {
        super(binderMethods, initializer);
      }
    
      /**
       * Returns an instance of {@link MyCustomServletRequestDataBinder}.
       */
      @Override
      protected ServletRequestDataBinder createBinderInstance(Object target,
          String objectName, NativeWebRequest request) {
        return new MyCustomServletRequestDataBinder(target, objectName);
      }
    }
    

    自定义RequestMappingHandlerAdapter:

    public class MyCustomRequestMappingHandlerAdapter extends
        RequestMappingHandlerAdapter {
      public MyCustomRequestMappingHandlerAdapter() {
        super();
      }
    
      /**
       * {@inheritDoc} Creates an instance of
       * {@link MyCustomServletRequestDataBinderFactory}.
       */
      @Override
      protected ServletRequestDataBinderFactory createDataBinderFactory(
          List<InvocableHandlerMethod> binderMethods) throws Exception {
        return new MyCustomServletRequestDataBinderFactory(binderMethods,
            getWebBindingInitializer());
      }
    }
    

    然后注册自定义的HandlerAdapter:

    @Configuration
    @Import(ValidationConfiguration.class)
    @ComponentScan(basePackageClasses = ControllerScanMarker.class)
    public class MyCustomHandlerConfig extends WebMvcConfigurationSupport {
      /**
       * {@inheritDoc} Returns the subclass
       * {@link MyCustomRequestMappingHandlerAdapter} in place of the default
       * {@link RequestMappingHandlerAdapter}.
       */
      @Override
      @Bean
      public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        ...
        RequestMappingHandlerAdapter adapter = new MyCustomRequestMappingHandlerAdapter();
    
        // set additional adapter fields here...
        ...
        return adapter;
      }
    }
    

    我很确定在默认请求参数绑定期间可能有更简单的方法来修改/添加附加值,但我不记得另一个钩子在哪里。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-26
      • 2018-06-10
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多