Jqgrid春天日期绑定异常

时间:2010-12-09 00:03:02

标签: spring jqgrid

操作系统:Windows Vista,框架:Jqgrid(最新),Spring(最新),JQuery(最新) 我正在使用Jqgrid将表单发布到Spring Controller以保持不变。当Spring控制器尝试将请求参数自动绑定到域对象时,它会在尝试绑定“Date”数据类型时抛出异常。我使用JSon格式传输数据。 Jqgrid正确显示日期。传输字符串包含'& -quot;'导致异常的日期之前和之后的字符。我不知道如何从Jqgrid中删除转义字符。我不知道在Spring有机会自动绑定之前如何拦截字符串。感谢您的帮助。

    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);
}

}

我的控制器类有initBinder方法。

        @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)

5 个答案:

答案 0 :(得分:1)

如果我今天有空的话,我会尝试在我的博客上设置教程。

我的JSP文件只是一个简单的JSP文件,带有典型的JqGrid声明:

<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"});

});

注意我在这里使用JQuery的noConflict方法。由于我有另一个使用 $ 的Javascript框架,我强迫JQuery为自己使用不同的标识符。我选择了jq,这是宣言:

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

上面的Javascript可以在JSP的head部分声明。 JqG​​rid声明的关键部分是 jsonReader 数据类型。确保colModel名称与您的模型属性匹配。

答案 1 :(得分:0)

你可能会使用StringTrimmerEditor的第二个构造函数删除那些额外的字符

StringTrimmerEditor(String charsToDelete, boolean emptyAsNull) 

基于Spring文档:

  

charsToDelete - 除了修剪输入字符串外,还要删除的一组字符。用于删除不需要的换行符。例如。 “\ r \ n \ f”将删除字符串中的所有新行和换行符。

我也使用最新版本的JqGrid和Spring 3,但我处理参数的方式似乎更简单。我是这样做的:

@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
        ) { ... }

所有参数都以普通字符串形式传递。 datefrom dateto 是我从JqGrid传递的自定义参数。日期来自JQuery的DatePicker,并通过JqGrid postData传递:

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

JsonResponse 是一个简单的POJO,我用它来映射JqGrid传递的搜索参数:

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 也是一个简单的DTO对象。

在我的Spring applicationContext.xml中,我只需要声明以下内容:

<mvc:annotation-driven/>

并添加了Jackson jar用于从JSON转换为POJO,反之亦然

要将String日期转换为实际日期,我使用了很棒的Joda库。但是,当然,您可以使用JDK的标准日期。

答案 2 :(得分:0)

如果您注意到我的JSP,我添加了自定义按钮。 onClickButton 调用另一个Javascript函数。例如,在添加按钮上,我有addRow功能。这是函数声明:

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];
                }
            });

}

记下网址:

url: "/myapp/users/add"

这是处理添加请求的控制器的映射

答案 3 :(得分:0)

现在,对于杰克逊序列化/反序列化,你会感到惊讶它是多么容易。

首先,确保您的类路径中有最新的Jackson库。接下来,打开Spring xml配置,并添加以下内容:

<mvc:annotation-driven/> 

就是这样:))

确保您拥有最新的依赖关系jar。我使用Spring 3.0.4。已经有3.0.5了。另外,请确保您拥有最新的aspectjweaver.jar。如果您想知道mvc-annotation驱动标签内部的内容,只需搜索网络,您就会看到它包含的内容。基本上它会自动为JSON声明一个HTTPMessageConverter,并默认使用Jackson。

答案 4 :(得分:0)

对于Controller,这是到/ myapp / users / add请求的映射:

@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;
    }
}

这是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);
}

}

这真的是一个简单的POJO。

在JSP中,要处理响应,请在JqGrid中使用JavaScript。响应将被发送回调用者(在这种情况下为添加表单)。以下是处理响应的示例JavaScript:

                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];