【问题标题】:Can spring mvc trim all strings obtained from forms?spring mvc 可以修剪从表单获得的所有字符串吗?
【发布时间】:2011-02-11 02:38:30
【问题描述】:

我知道 struts2 默认配置会修剪所有从表单获取的字符串。

例如:

我输入

"whatever"
在表单中并提交,我会得到
"whatever"
字符串已被自动修剪

spring mvc也有这个功能吗?谢了。

【问题讨论】:

    标签: spring spring-mvc


    【解决方案1】:

    使用 Spring 3.2 或更高版本:

    @ControllerAdvice
    public class ControllerSetup
    {
        @InitBinder
        public void initBinder ( WebDataBinder binder )
        {
            StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
            binder.registerCustomEditor(String.class, stringtrimmer);
        }
    }
    

    使用 MVC 测试上下文进行测试:

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration
    public class ControllerSetupTest
    {
        @Autowired
        private WebApplicationContext   wac;
        private MockMvc                 mockMvc;
    
        @Before
        public void setup ( )
        {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
        }
    
        @Test
        public void stringFormatting ( ) throws Exception
        {
            MockHttpServletRequestBuilder post = post("/test");
            // this should be trimmed, but only start and end of string
            post.param("test", "     Hallo  Welt   ");
            ResultActions result = mockMvc.perform(post);
            result.andExpect(view().name("Hallo  Welt"));
        }
    
        @Configuration
        @EnableWebMvc
        static class Config
        {
            @Bean
            TestController testController ( )
            {
                return new TestController();
            }
    
            @Bean
            ControllerSetup controllerSetup ( )
            {
                return new ControllerSetup();
            }
        }
    }
    
    /**
     * we are testing trimming of strings with it.
     * 
     * @author janning
     * 
     */
    @Controller
    class TestController
    {
        @RequestMapping("/test")
        public String test ( String test )
        {
            return test;
        }
    }
    

    并且 - 正如 LppEdd 所要求的 - 它也适用于密码,因为在服务器端输入 [type=password] 和 input[type=text] 之间没有区别

    【讨论】:

    • 这是 Spring 3.2 或更高版本的最佳答案,尽管测试代码分散了其简单性。您只需要第一个代码块。其余代码并非特定于该问题。除了将其放入 ControllerAdvice 类之外,您还可以将其直接放入控制器类或控制器的基类中。
    • 同时使用 Spring Boot 1.3 和 Spring MVC 4.2
    • 密码呢?
    • 无法从 SpringTestRunner 测试这个? MockMVC 不采用此配置,必须通过调用 .setControllerAdvice(...) 显式添加它
    【解决方案2】:

    注册这个属性编辑器: org.springframework.beans.propertyeditors.StringTrimmerEditor

    AnnotionHandlerAdapter 示例:

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
      ...
      <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
          <property name="propertyEditorRegistrar">
             <bean class="org.springframework.beans.propertyeditors.StringTrimmerEditor" />
          </property>
        </bean>
      </property>
      ...
    </bean>
    

    【讨论】:

    • 我不确定你们是如何让它工作的,但是在 Spring Portlet MVC 中,这根本不会让步。首先,StringTrimmerEditor 没有实现 PropertyEditorRegistrar 接口,即使实现了,它也没有默认的无参数构造函数。我最终编写了自己的 StringTrimmerEditorRegistrar 并注入了 ConfigurableWebBindingInitializer,但我很想知道每个人是如何让它工作的?
    • StringTrimmerEditor 有两个构造函数,可以传布尔值或者字符串和布尔值,查看文档
    • 如果您使用 Spring 3.2 或更高版本,您可能需要查看 Janning 的答案。 (AnnotationMethodHandlerAdapter 现已弃用。)
    【解决方案3】:

    您还可以使用 Spring 的转换服务,它具有使用 &lt;mvc:annotation-driven/&gt; 和 Spring Webflow 的额外好处。与其他答案一样,主要缺点是这是一个全局更改,并且不能针对某些表单禁用。

    你需要一个转换器来做修剪

    public class StringTrimmingConverter implements Converter<String, String> {
    
        @Override
        public String convert(String source) {
           return source.trim();
        }
    
    }
    

    然后定义一个了解您的转换器的转换服务。

    <bean id="applicationConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
        <list>
            <bean class="mypackage.util.StringTrimmingConverter"/>
        </list>
        </property>
    </bean>
    

    并将其绑定到 mvc。

    <mvc:annotation-driven conversion-service="applicationConversionService"/>
    

    如果你使用 Spring Webflow,那么它需要一个包装器

     <bean id="defaultConversionService" class="org.springframework.binding.convert.service.DefaultConversionService">
        <constructor-arg ref="applicationConversionService"/>
    </bean>
    

    以及您的流程构建器上的设置

    <flow:flow-builder-services id="flowBuilderServices" conversion-service="defaultConversionService" development="true"  validator="validator" />
    

    【讨论】:

      【解决方案4】:

      您可以使用 Spring-MVC 拦截器

      public class TrimInterceptor extends HandlerInterceptorAdapter {
      
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              Enumeration<String> e = request.getParameterNames();
              while(e.hasMoreElements()) {
                  String parameterName = e.nextElement();
      
                  request.setParameter(parameterName, request.getParameter(parameterName).trim());
              }
      
              return true;
          }
      

      并设置您的 HandlerMapping 拦截器属性

      <bean id="interceptorTrim" class="br.com.view.interceptor.TrimInterceptor"/>
      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" p:interceptors-ref="interceptorTrim"/>
      }
      

      或者使用 Servlet 过滤器

      【讨论】:

      • 警惕这样的方法 - 用户可能会使用空格作为密码的第一个和/或最后一个字符。您上面的实现也不是空安全的。
      • HttpServletRequest 类没有 setParameter 方法
      【解决方案5】:

      只是为了适应Spring Boot定制了上面的代码,如果你想对表单中的某些字段进行显式修剪功能,可以如下所示:

      @Component
      @ControllerAdvice
      public class ControllerSetup {
          @InitBinder({"dto", "newUser"})
              public void initBinder(WebDataBinder binder) {
                binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
                binder.registerCustomEditor(String.class, "userDto.username", new StringTrimmerEditor(false));
                binder.registerCustomEditor(String.class, "userDto.password", new DefaultStringEditor(false));
                binder.registerCustomEditor(String.class, "passwordConfirm", new DefaultStringEditor(false));
              }
      }
      

      【讨论】:

        【解决方案6】:

        首先,修剪requestparam为String,你可以创建一个类并实现WebBingdingInitializer

         @ControllerAdvice
        public class CustomWebBindingInitializer implements WebBindingInitializer {
        
            @InitBinder
            @Override
            public void initBinder(WebDataBinder webDataBinder, WebRequest webRequest) {
                webDataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
            }
        }
        

        请使用 componentScan 使这个 Class 成为一个 Spring Bean。

        但是,我不知道如何修剪 requestBody JSON 数据中的字符串值。

        【讨论】:

          猜你喜欢
          • 2022-11-01
          • 1970-01-01
          • 2019-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多