2011-01-18 7 views
5

Sto usando l'editor di Spring CustomNumberEditor per legare i miei valori float e ho sperimentato che se nel valore non è un numero a volte può analizzare il valore e non viene restituito alcun errore.Spring CustomNumberEditor analizza numeri che non sono numeri

  • numero = 10 ...... allora il numero è 10 e non c'è nessun errore
  • numero = 10a ...... allora il numero è 10 e non c'è nessun errore
  • numero = 10a25 ...... allora il numero è 10 e non c'è nessun errore
  • numero = un ...... errore perché il numero non è valido

così sembra che l'editor analizza il valore fino a quando non può e omettere il resto. C'è un modo per configurare questo editor in modo che la validazione sia rigorosa (quindi i numeri come 10a o 10a25 causano errori) o devo costruire la mia implementazione personalizzata. Sto guardando qualcosa come impostare lentissimo su false in CustomDateEditor/DateFormat in modo che le date non possano essere analizzate alla più probabile.

Il modo in cui mi registro l'editor è:

@InitBinder 
public void initBinder(WebDataBinder binder){ 
    NumberFormat numberFormat = NumberFormat.getInstance(); 
    numberFormat.setGroupingUsed(false); 
    binder.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, numberFormat, true)); 
} 

Grazie.

risposta

4

Poiché si basa sulla classe NumberFormat, che interrompe l'analisi della stringa di input sul primo carattere non valido, penso che sarà necessario estendere la classe NumberFormat.

prima vista sarebbe

public class StrictFloatNumberFormat extends NumberFormat { 

    private void validate(in) throws ParseException{ 
    try { 
     new Float(in); 
    } 
    catch (NumberFormatException nfe) { 
     throw new ParseException(nfe.getMessage(), 0);  
    } 


    public Number parse(String in) throws ParseException { 
    validate(in); 
    super.parse(in); 
    } 
    ..... //any other methods 
} 
+0

Grazie. Ma se ho fatto la mia implementazione personalizzata penso di poter estendere la classe CustomNumberEditor e sovrascrivere il metodo setAsText controllando se il valore è un numero come fai tu e se sta succedendo con super.setAsText – Javi

7

Non si può fare questo whith NumberFormat.

La documentazione è chiaro su questo fatto:

/** 
* Parses text from the beginning of the given string to produce a number. 
* The method may not use the entire text of the given string. 
* <p> 
* See the {@link #parse(String, ParsePosition)} method for more information 
* on number parsing. 
* 
* @param source A <code>String</code> whose beginning should be parsed. 
* @return A <code>Number</code> parsed from the string. 
* @exception ParseException if the beginning of the specified string 
*   cannot be parsed. 
*/ 
public Number parse(String source) throws ParseException { 

Quando si acceept questa API sarebbe addirittura essere ancora valida per scrivere un parser che fa quello che si vuole e implementare l'interfaccia NumberFormat. Questo significa che devi impiantare il tuo editor di proprietà.

/* untested */ 
public class StrictNumberPropertyEditor extends PropertyEditorSupport { 

    @Override 
    public void setAsText(String text) throws IllegalArgumentException { 
     super.setValue(Float.parseFloat(text)); 
    } 

    @Override 
    public String getAsText() { 
     return ((Number)this.getValue()).toString(); 
    }  
} 
3

penso che l'approccio più elegante sarebbe quella di utilizzare NumberFormat.parse(String,ParsePosition), qualcosa di simile:

public class MyNumberEditor extends PropertyEditorSupport { 
    private NumberFormat f; 
    public MyNumberEditor(NumberFormat f) { 
     this.f = f; 
    } 

    public void setAsText(String s) throws IllegalArgumentException { 
     String t = s.trim(); 
     try { 
      ParsePosition pp = new ParsePosition(0); 
      Number n = f.parse(t, pp); 
      if (pp.getIndex() != t.length()) throw new IllegalArgumentException(); 
      setValue((Float) n.floatValue()); 
     } catch (ParseException ex) { 
      throw new IllegalArgumentException(ex); 
     } 
    } 

    ... 
}