Risultato INPUT di Struts2: come funziona? Come vengono gestiti gli errori di conversione / convalida?

Domanda principale

Il stream di lavoro dovrebbe essere così: se si immette una stringa diversa da un numero, prima deve passare attraverso un intercettore di eccezione e quando passa attraverso l’interceptor param, durante la conversione in tipo int, non sarà in grado di farlo usando Integer.parseInt e si verificherà un’eccezione; questa eccezione (ovvero NumberFormatException ) non dovrebbe essere inserita in Value Stack? Perché non mostra NumberFormatException e mostra il risultato anche se il risultato non dovrebbe essere stampato?

Domanda laterale

Ogni volta che aggiungo un alfabeto nel modulo, è cambiato a zero …? Perchè così ?

index.jsp

       

divide.java

 package actions; public class divide { int number1,number2,result; public String execute() throws Exception { result=number1/number2; return "success"; } public int getNumber1() { return number1; } public void setNumber1(int number1) { this.number1 = number1; } public int getNumber2() { return number2; } public void setNumber2(int number2) { this.number2 = number2; } public int getResult() { return result; } } 

result.jsp

   the result of division is    

gestore jsp

   following exception occured during the processing    

struts.xml

       /result.jsp /handler.jsp    

Domanda principale:

Il stream di lavoro dovrebbe essere così, se si immette una stringa diversa da un numero, prima deve passare attraverso un intercettore di eccezione e quando passa attraverso l’interceptor param, durante la conversione in tipo int, non sarà in grado di farlo usando Integer. parseInt e si verificherà un’eccezione, quell’eccezione che è l’eccezione di formato numerico dovrebbe essere inserita nello stack di valori? quindi perché non mostra numberformatexception e mostra il risultato anche se il risultato non dovrebbe essere stampato al suo posto?

Concetto

Struts 2 gestisce automaticamente sia gli errori di conversione che gli errori di convalida : non genera un’eccezione, perché non sta bloccando errori , ma errori di input , quindi il modo migliore per procedere è informare l’utente che l’input inviato è sbagliato, chiedendogli per un nuovo input valido. Per ottenere ciò, viene restituito un risultato INPUT, mentre l’eccezione viene ignorata.

Worflow dettagliato

  1. Parameters Interceptor tenta di impostare i parametri. Se viene rilevata una RuntimeException (come NumberFormatException ) e devMode è true , viene aggiunto un messaggio di errore agli Action Errors , altrimenti l’eccezione viene semplicemente ingerita. Dal codice sorgente:

     for (Map.Entry entry : acceptableParameters.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); try { newStack.setParameter(name, value); } catch (RuntimeException e) { if (devMode) { String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage() }); LOG.error(developerNotification); if (action instanceof ValidationAware) { ((ValidationAware) action).addActionMessage(developerNotification); } } } } 
  2. Conversion Errors Interceptor verifica se si è verificato un errore di conversione: per ognuno trovato, aggiunge un Field Error ; salva inoltre i valori originali in modo tale che eventuali richieste successive per tale valore restituiscano il valore originale anziché il valore nell’azione . Dalla documentazione:

    Questo intercettore aggiunge qualsiasi errore trovato nella mappa conversionErrors di ActionContext come errore di campo (a condizione che l’azione implementa ValidationAware). Inoltre, qualsiasi campo che contiene un errore di convalida ha il suo valore originale salvato in modo che eventuali richieste successive per tale valore restituiscano il valore originale anziché il valore nell’azione. Questo è importante perché se il valore “abc” viene inviato e non può essere convertito in un int, vogliamo visualizzare di nuovo la stringa originale (“abc”) piuttosto che il valore int (probabilmente 0, che avrebbe molto poco senso per l’utente).

  3. Il Validation Interceptor esegue tutte le convalide richieste (definite in XML, Annotazioni o tramite i metodi validate() o validateXXX() dell’azione), aggiungendo uno o più messaggi di errore agli Field Errors per ogni campo che non supera uno o più criteri di convalida .

  4. Workflow Interceptor controlla se ci sono Field Errors (entrambi provenienti da errori di conversione o errori di convalida). Se non vengono rilevati errori, continua la catena al prossimo Interceptor. Se uno o più errori vengono trovati, restituisce un risultato INPUT.

Per garantire il funzionamento di questo meccanismo, è necessario definire questi quattro Interceptor nell’ordine corretto nello Stack personalizzato, se non si utilizza lo Stack predefinito degli interettori (non è necessario fare diversamente). Da struts-default.xml :

   ^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*    input,back,cancel,browse   input,back,cancel,browse   

Domanda laterale:

Ogni volta che aggiungo un alfabeto nel modulo, è cambiato a zero …? Perchè così?

La risposta originale era: il framework non è stato in grado di impostare una String in un campo int quando si invia la richiesta al server e quando si recupera il valore nella pagina risultante, richiama il Getter di quella variabile; poiché hai definito un int e non un Integer , e un int non può essere nullo, restituirà il valore predefinito per un int : 0 .

Ma non stavo ricordando che Conversion Interceptor afferma (leggi il punto 2) per salvare i valori originali, per fornirli nelle successive richieste future, al posto dei valori Action (che sarebbero null o 0). Questo è anche menzionato in Gestione conversione errori di tipo :

La gestione degli errori di conversione dei tipi fornisce un modo semplice per distinguere tra un problema di convalida dell’input e un problema di conversione del tipo di input.

Qualsiasi errore che si verifica durante la conversione di tipo può o non desidera essere segnalato. Ad esempio, segnalare che l’input “abc” non può essere convertito in un numero potrebbe essere importante. D’altro canto, segnalare che una stringa vuota, “”, non può essere convertita in un numero potrebbe non essere importante, specialmente in un ambiente web in cui è difficile distinguere tra un utente che non immette un valore e non inserisce un valore vuoto.

Invece, stavo ricordando bene il comportamento descritto nella tua domanda. Quindi questo caso è già stato gestito … perché non funziona allora? Il colpevole, nel mio caso (e probabilmente il tuo), era l’attributo value :

Questo ti darà 0 quando pubblichi abc :

  

perché si verifica un ulteriore errore di conversione.

Questi due casi funzionano invece come descritto sopra, dandovi abc quando postate abc :

   

conclusioni

  • Assicurarsi che lo Stack dell’intercettore sia configurato correttamente e
  • controlla attentamente il tuo codice (che probabilmente non è quello pubblicato qui) per vedere cosa stai facendo con il tuo attributo value .

A scopo di test, prova a rimuovere inizialmente l’attributo value , per vederlo funzionante nel modo giusto, quindi inizia a cercare il bug.