2010-12-09 7 views
1

OS: Windows Vista, Framework: Jqgrid (späteste), Frühling (späteste), JQuery (späteste) Ich benutze Jqgrid, um ein Formular zum Frühlings-Controller zu posten, um zu bestehen. Wenn der Spring-Controller versucht, die Anforderungsparameter automatisch an das Domänenobjekt zu binden, löst er eine Ausnahme aus, wenn er versucht, den Datentyp "Date" zu binden. Ich verwende das JSon-Format für die Übertragung von Daten. Das Jqgrid zeigt das Datum korrekt an. Die Übertragungszeichenfolge enthält '& -quot;' Zeichen vor und nach dem Datum, das die Ausnahme verursacht. Ich weiß nicht, wie man das Escape-Zeichen von Jqgrid entfernt. Ich weiß nicht, wie ich die Saite abfangen kann, bevor Spring eine Chance bekommt, automatisch zu binden. Danke im Vorraus für deine Hilfe.Jqgrid Frühling Datum bindende Ausnahme

public class JsonDateSerializer extends JsonSerializer<Date> { 
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
AtOverride 
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) 
     throws IOException, JsonProcessingException { 
    String formattedDate = dateFormat.format(date); 
    gen.writeString(formattedDate); 
} 

}

Mein Controller-Klasse hat initBinder Methode.

 @InitBinder 
public void initBinder(WebDataBinder binder) { 
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    dateFormat.setLenient(false); 
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); 
    binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); 
} 

Exception stack trace 
nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value &quot;2010-12-01 11:10:00&quot; from type 'java.lang.String' to type 'java.util.Date'; nested exception is java.lang.IllegalArgumentException] 
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:820) 
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359) 

Antwort

1

Ich werde versuchen, ein Tutorial auf meinem Blog einzurichten, wenn ich die Zeit heute bekomme.

Meine JSP-Datei ist nur eine einfache JSP-Datei mit Ihrer typischen JqGrid Erklärung:

<script type="text/javascript"> 
jq(function() { 
    // This is the grid 
    jq("#grid").jqGrid({ 
     url:'/myapp/users', 
     datatype: 'json', 
     mtype: 'GET', 
     colNames:['Id','Username','First Name'], 
     colModel:[ 
      {name:'id',index:'id', width:55,editable:false,editoptions:{readonly:true,size:10},hidden:true}, 
      {name:'firstName',index:'firstName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}}, 
      {name:'lastName',index:'lastName', width:80, align:"right",editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}} 
     ], 
     postData: { 
      // Here you can post extra parameters 
      // For example using JQuery you can retrieve values of other css elements 
     }, 
     rowNum:10, 
     rowList:[10,20,30], 
     height: 200, 
     autowidth: true, 
     rownumbers: true, 
     pager: '#pager', 
     sortname: 'id', 
     viewrecords: true, 
     sortorder: "asc", 
     caption:"Users", 
     emptyrecords: "Empty records", 
     loadonce: false, 
     loadComplete: function() { 
      // Here you can provide extra functions after the grid is loaded completely 
      // Like auto-height function 
     }, 
     jsonReader : { 
      root: "rows", 
      page: "page", 
      total: "total", 
      records: "records", 
      repeatitems: false, 
      cell: "cell", 
      id: "id" 
     } 
    }); 

    // This is the pager 
    jq("#grid").jqGrid('navGrid','#pager', 
      {edit:false,add:false,del:false,search:true}, 
      { }, 
      { }, 
      { }, 
      { 
       sopt:['eq', 'ne', 'lt', 'gt', 'cn', 'bw', 'ew'], 
       closeOnEscape: true, 
        multipleSearch: true, 
        closeAfterSearch: true } 
    ); 

    // Custom Add button on the pager 
    jq("#grid").navButtonAdd('#pager', 
      { caption:"Add", 
       buttonicon:"ui-icon-plus", 
       onClickButton: addRow, 
       position: "last", 
       title:"", 
       cursor: "pointer" 
      } 
    ); 

    // Custom Edit button on the pager 
    jq("#grid").navButtonAdd('#pager', 
      { caption:"Edit", 
       buttonicon:"ui-icon-pencil", 
       onClickButton: editRow, 
       position: "last", 
       title:"", 
       cursor: "pointer" 
      } 
    ); 

    // Custom Delete button on the pager 
    jq("#grid").navButtonAdd('#pager', 
     { caption:"Delete", 
      buttonicon:"ui-icon-trash", 
      onClickButton: deleteRow, 
      position: "last", 
      title:"", 
      cursor: "pointer" 
     } 
    ); 


    // Toolbar Search 
    jq("#grid").jqGrid('filterToolbar',{stringResult: true,searchOnEnter : true, defaultSearch:"cn"}); 

}); 

Beachten Sie hier verwende ich jQuerys noConflict Methode. Da ich ein anderes JavaScript-Framework verwende, das $ verwendet, zwang ich JQuery, eine andere Kennung für sich selbst zu verwenden. Ich nahm jq und hier ist die Erklärung:

<script type="text/javascript"> 
    var jq = jQuery.noConflict(); 
</script> 

Die Javascript ist oben auf dem Kopfteil Ihrer JSP deklariert werden. Der kritische Teil der JqGrid-Deklaration ist der jsonReader und der -Datentyp. Stellen Sie sicher, dass der Name des ColModel mit Ihren Modelleigenschaften übereinstimmt.

+0

Beachten Sie auch die URL. Das ist die URL, die Ihr Raster füllen sollte. – chris

+0

Wo ist dein Blog? – blong

0

Sie wahrscheinlich StringTrimmerEditor zweiten Konstruktor zu löschen, diese zusätzlichen Zeichen

StringTrimmerEditor(String charsToDelete, boolean emptyAsNull) 

Basierend auf dem Frühling docs verwenden:

charsToDelete - auf eine Reihe von Zeichen zu löschen, zusätzlich einen Eingabe-String trimmen. Nützlich zum Löschen von unerwünschten Zeilenumbrüchen. Z.B. "\ r \ n \ f" löscht alle neuen Zeilen und Zeilenvorschübe in einem String.

Ich benutze auch die neueste Version von JqGrid und Spring 3, aber die Art, wie ich die Parameter behandelt, scheint einfacher zu sein. Hier ist, wie ich es gemacht habe:

@Controller 
@RequestMapping("/json") 
public class JsonController { 

     @RequestMapping(method = RequestMethod.GET) 
     public @ResponseBody JsonResponse getAll(
       @RequestParam("_search") String search, 
       @RequestParam(value="filters", required=false) String filters, 
       @RequestParam(value="datefrom", required=false) String datefrom, 
       @RequestParam(value="dateto", required=false) String dateto, 
       @RequestParam(value="page", required=false) String page, 
       @RequestParam(value="rows", required=false) String rows, 
       @RequestParam(value="sidx", required=false) String sidx, 
       @RequestParam(value="sord", required=false) String sord 
     ) { ... } 

Alle Parameter werden als normale Strings übergeben. Die Date von und Dateto sind benutzerdefinierte Parameter, die ich von der JqGrid übergeben. Das Datum stammt aus einem Datepicker des JQuery und über JqGrid postdata übergeben:

postData: { 
      datefrom: function() { return jq("#datepicker_from").datepicker("getDate"); }, 
      dateto: function() { return jq("#datepicker_to").datepicker("getDate"); } 
     }, 

JsonResponse ist eine einfache POJO, die ich verwendet, um die Suchparameter durch eine JqGrid bestanden zur Karte:

public class JsonResponse { 

/** 
* Current page of the query 
*/ 
private String page; 

/** 
* Total pages for the query 
*/ 
private String total; 

/** 
* Total number of records for the query 
*/ 
private String records; 

/** 
* An array that contains the actual data 
*/ 
private List<MyDTO> rows; 

public JsonResponse() { 
} 

public String getPage() { 
    return page; 
} 

public void setPage(String page) { 
    this.page = page; 
} 

public String getTotal() { 
    return total; 
} 

public void setTotal(String total) { 
    this.total = total; 
} 

public String getRecords() { 
    return records; 
} 

public void setRecords(String records) { 
    this.records = records; 
} 

public List<MyDTO> getRows() { 
    return rows; 
} 

public void setRows(List<MyDTO> rows) { 
    this.rows = rows; 
} 

}

MyDTO ist ein einfaches DTO-Objekt.

In meinem Frühling applicationContext.xml, muss ich nur noch die folgende erklären:

<mvc:annotation-driven/> 

Und hinzugefügt, um den Jackson jar von JSON zu POJO für die Umwandlung und umgekehrt

den String Datum konvertieren Ein echtes Date, ich benutzte die große Joda-Bibliothek. Natürlich können Sie das Standarddatum von JDK verwenden.

+0

Danke Chris für den Vorschlag. Ich werde sie ausprobieren. Ich habe noch eine Anfrage. Da Sie auch Jqgrid/Spring verwenden, wird es möglich sein, Beispielcode für die folgenden Teile zu teilen?Obwohl ich die Dokumentation von Jqgrid durchgelesen habe, ist es nicht klar, was der beste Weg ist, um es zu implementieren. Es wird hilfreich sein, sich Ihren Code anzusehen und zu verstehen, wie Sie ihn implementiert haben. – Jayaprakash

+0

1. JSP-Seite mit JQgrid-Aufruf und allen zugehörigen Funktionen/Formulardefinitionen. 2. Spring Controller für Suchen und Hinzufügen/Ändern von Methoden. Wie binden Sie? 3. Wie benutzt man Jackson zum Serialisieren/Deserialisieren? Ich weiß, es ist ein bisschen Ärger, aber es wird sehr nützlich für mich sein, wenn Sie bieten können. Vielen Dank im Voraus, JP – Jayaprakash

+0

Ich habe ein paar Beispielcode hinzugefügt. Ich hoffe, du wirst ihnen folgen können. Beginnen Sie mit der JSP, dann mit der Spring XML-Konfiguration und dann mit dem Controller. Ich bin mir nicht sicher, ob mein Weg der beste Weg ist, aber ich denke, es ist einfach genug :) – chris

0

Wenn Sie auf meiner JSP bemerken, fügte ich benutzerdefinierte Schaltflächen hinzu. Die onClickButton ruft eine andere Javascript-Funktion auf. Zum Beispiel auf der Add Taste, habe ich die AddRow-Funktion. Hier ist die Funktionsdeklaration:

function addRow() { 

    // Get the currently selected row 
    jq("#grid").jqGrid('editGridRow','new', 
      { url: "/myapp/users/add", 
        editData: { 
        // Here you add extra post parameters 
       }, 
       recreateForm: true, 
       beforeShowForm: function(form) { 
        // Here you can add, disable, hide elements from the popup form 
       }, 
       closeAfterAdd: true, 
       reloadAfterSubmit:false, 
       afterSubmit : function(response, postdata) 
       { 
        // This is a callback function that will evaluate the response sent by your Controller 
        var result = eval('(' + response.responseText + ')'); 
        var errors = ""; 

        if (result.success == false) { 
         // Do whatever you like if not successful 
        } else { 
         // Do whatever you like if successful 
        } 

        // only used for adding new records 
        var new_id = null; 

        // Then this will be returned back to the popup form 
        return [result.success, errors, new_id]; 
       } 
      }); 

} 

Beachten Sie die URL:

url: "/myapp/users/add" 

Dies ist die Abbildung auf Ihrem Controller, der die Additionsanforderung

0

Jetzt behandelt, für die Jackson-Serialisierung/Deserialisierung Sie werden überrascht sein, wie einfach es ist.

Stellen Sie zuerst sicher, dass Sie die neueste Jackson-Bibliothek in Ihrem Klassenpfad haben. Als nächstes öffnen Sie Ihre Spring-XML-Konfigurations, und fügen Sie den folgenden:

<mvc:annotation-driven/> 

Das ist es

Stellen Sie sicher, ist :) Sie die neuesten Abhängigkeit Gläser haben. Ich benutze Frühling 3.0.4. Es gibt schon 3.0.5. Stellen Sie außerdem sicher, dass Sie die neueste aspectjweaver.jar haben. Wenn Sie wissen wollen, was in diesem mvc-Annotation-getriebenen Tag ist, suchen Sie einfach im Web und Sie werden sehen, was es enthält. Im Grunde deklariert es automatisch einen HTTPMessageConverter für JSON und verwendet standardmäßig Jackson.

+0

Danke! eine Tonne Chris :) Das wird mir wirklich sehr helfen! Nochmals vielen Dank und das ist großartig! – Jayaprakash

+0

Ich stimme auch zu, dass das Tutorial eine großartige Idee ist! Viele Leute werden davon sicher profitieren :) – Jayaprakash

+0

Ich habe das Tutorial unter http://krams915.blogspot.com/2010/12/jqgrid-and-spring-3-mvc-integration.html – chris

0

Für Controller, hier ist die Zuordnung zum/myapp/users/hinzufügen Anfrage:

@Controller 
@RequestMapping("/myapp/users") 
public class UserController { 

    @RequestMapping(value = "/add", method = RequestMethod.POST) 
    public @ResponseBody JsonGenericResponse addAsJson(
      @RequestParam("id") String id, 
      @RequestParam("firstName") String firstName, 
      @RequestParam("lastName") String lastName 
    ) { 

      // Validate input 

      // Process data. Call a service, etc. 

      // Send back a response 
      // JsonGenericResponse is a custom POJO 
      // Jackson will automatically serialize/deserialize this POJO to a JSON 
      // The @ResponseBody annotation triggers this behavior 

      JsonGenericResponse response = new JsonGenericResponse(); 
      response.setSuccess(false); 
      response.setMessage("Error in server"); 

      return response; 
    } 
} 

Hier ist der JsonGenericResponse:

public class JsonGenericResponse { 

private Boolean success; 
private List<String> message; 

public JsonGenericResponse() { 
    message = new ArrayList<String>(); 
} 

public Boolean getSuccess() { 
    return success; 
} 

public void setSuccess(Boolean success) { 
    this.success = success; 
} 

public List<String> getMessage() { 
    return message; 
} 

public void setMessage(String message) { 
    this.message.add(message); 
} 

}

Es ist nur wirklich eine einfache POJO .

Um die Antwort in Ihrer JSP zu verarbeiten, verwenden Sie JavaScript in Ihrem JqGrid. Die Antwort wird an den Anrufer (in diesem Fall das Formular zum Hinzufügen) gesendet. Hier ist ein Beispiel JavaScript, das die Antwort verarbeitet:

   if (result.success == false) { 
        for (var i = 0; i < result.message.length; i++) { 
         errors += result.message[i] + "<br/>"; 
        } 
       } else { 
        jq("#dialog").text('Entry has been edited successfully'); 
        jq("#dialog").dialog( 
          { title: 'Success', 
           modal: true, 
           buttons: {"Ok": function() { 
            jq(this).dialog("close");} 
           } 
          }); 
       } 

       return [result.success, errors, null]; 
+0

Es tut mir leid für die Formatierung. Es ist schwierig, das JavaScript zu formatieren, das ich direkt von meiner JSP-Seite kopiert habe. – chris

Verwandte Themen