将表单提交给 spring 控制器时出现 NumberFormatException

NumberFormatException when form is submited to spring controller

在我当前的 spring 项目中,当我尝试提交此表单时:

 <form role="form" class="form" action="/Destaque/cadastra" method="post" enctype="multipart/form-data">
<field-box>
  <div>
    <div>              
      <div>
        <label>Produto</label><select class="form-control" name="listaDeProdutos[]" multiple="multiple" rows="7"><option value="1">one</option><option value="2">two</option><option value="3">three</option><option value="4">four</option><option value="5">five</option><option value="6">six</option><option value="7">seven</option><option value="8">eight</option><option value="9">nine</option><option value="10">ten</option><option value="11">eleven</option><option value="12">twelve</option></select>
      </div>
    </div>
  </div>
</field-box>
<field-box>
        <label>Titulo</label><input type="text" class="form-control" name="titulo" />
</field-box>
<field-box>
        <label>Resumo</label><input type="text" class="form-control" name="resumo" />
</field-box>
<field-box>
        <label>Valor</label><input type="text" class="form-control valida" pattern="[0-9]{2}.[0-9]{2}" name="valor" />
</field-box>
<field-box>
        <label>Descrição</label><textarea class="summernote" name="descricao"></textarea>
</field-box>
<field-box>
        <label>Capa do destaque</label><input type="file" class="form-control" name="icone" />
</field-box>
<field-box>
        <label>Validade</label><input type="text" class="form-control valida" pattern="[0-9]{2}/[0-9]{2}/[0-9]{4}" name="validade" />
</field-box>
<field-box>
        <label>destaque ativo</label><input type="checkbox" name="ativo" />
</field-box>

<button type="submit" class="btn btn-default">Cadastrar</button>

<div id="yes" class="alert alert-success" role="alert" style="display: none;">
  <button type="button" class="close" data-hide="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
  <span class="text">Cadastro efetuado com sucesso</span>
</div>

<div id="not" class="alert alert-danger" role="alert" style="display: none;">
  <button type="button" class="close" data-hide="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
  <span class="text"></span>
</div>

到这个实体类:

@Entity
@Form
@FormPublic
@Order(value = 5)
public class Destaque extends Model {
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Order(value = 1)
  private Integer id;

  @ManyToMany
  @JoinTable(name="listaDeProdutosEmDestaque", joinColumns={@JoinColumn(name="fk_destaque")}, inverseJoinColumns={@JoinColumn(name="fk_produto")})
  @LazyCollection(LazyCollectionOption.FALSE)
  @Order(value = 2)
  @Select(label = "Produto", classe=Produto.class)
  private List<Produto> listaDeProdutos;

  @Order(value = 3)
  @Input(label = "Titulo")
  @Column(length = 100)
  private String titulo;

  @Order(value = 4)
  @Input(label = "Resumo")
  @Column(length = 100)
  private String resumo;

  @Order(value = 5)
  @Input(label = "Valor", pattern = "[0-9]{2}.[0-9]{2}")
  private Float valor;

  @Order(value = 6)
  @Textarea(label = "Descrição")
  @Column(length = 131072)
  private String descricao;

  @OneToOne
  @JoinColumn(name = "banner")
  @Order(value = 7)
  @Input(label = "Capa do destaque", type="file")
  private Picture icone;

  @Order(value = 8)
  @Input(label = "Validade", pattern = "[0-9]{2}/[0-9]{2}/[0-9]{4}")
  private Date validade;

  @Order(value = 9)
  @Checkbox(label = "destaque ativo")
  private Boolean ativo;
}

我收到这个错误:

java.lang.NumberFormatException: For input string: ""
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Integer.parseInt(Integer.java:504)
        at java.lang.Integer.parseInt(Integer.java:527)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:993)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:926)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
        at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:749)
        at org.springframework.validation.DataBinder.doBind(DataBinder.java:645)
        at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:189)
        at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:106)
        at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.bindRequestParameters(ServletModelAttributeMethodProcessor.java:150)
        at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
        at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
        at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
        at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

有人能看出这里出了什么问题吗?

ps.: 提交是用这个方法处理的:

控制器:

  @RequestMapping(value = "cadastra", method=RequestMethod.POST)
  @ResponseBody
  public void cadastra(@ModelAttribute("object") E object, BindingResult result, @RequestParam(value="icone", required=false) MultipartFile icone, @RequestParam(value="fotos", required=false) MultipartFile fotos[], @RequestParam(value="arquivo", required=false) MultipartFile arquivo[]) throws Exception {
    serv.cadastra(object);
    serv.upload(object, icone);
    serv.upload_multiplo(object, fotos);
    serv.upload_jar(object, arquivo);
  }

服务

  @PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
  @Transactional
  public void cadastra(E object) {
    dao.insert(object);
  }

dao 类:

public void insert(E object) {
    EntityManager entityManager = getEntityManager();
    entityManager.getTransaction().begin();
    entityManager.persist(object);
    entityManager.getTransaction().commit();
    entityManager.close();
}

根据堆栈跟踪(java.lang.NumberFormatException: For input string: ""),似乎发生的情况是当您提交表单时,表单的数字输入之一仍然是空白,因此当您尝试投射字符串输入一个数字,它抛出错误。

这可以通过将表单的数字输入默认为数字(例如,零)来解决,这样表单就不会提交空数字输入。

我设法解决了这个问题,将这个 属性 编辑器 class 添加到项目中:

@Component
public class ProdutoEditor extends PropertyEditorSupport {
  @Override
  public void setAsText(String text) {
    if (!text.equals("")) {
      ProdutoService serv = new ProdutoService();
      ApplicationContextHolder.getContext().getAutowireCapableBeanFactory().autowireBean(serv);
      Produto produto = serv.getObject(text);
      setValue(produto);
    } else {
      setValue(null);
    }
  }
}

使用此 select 代码:

<select class="form-control" name="listaDeProdutos" multiple="multiple" rows="7">
    ...
    <option value="1">one</option>
    ...
</select>