Spring Json View(Spring+Json)

Spring json-view 为Spring-MVC提供了对JavaScript Object Notation (json) 的支持,它深入地集成在Spring MVC模块里,能够适用于所有标准的控制器类。

什么是Spring Json View?

 

Spring json-view  为Spring-MVC提供了对JavaScript Object Notation (json) 的支持,它深入地集成在Spring MVC模块里,能够适用于所有标准的控制器类。

在Web 2.0 Ajax 时代里常见的方式是客户(浏览器)和服务器的交互。在Java服务器端通常把Spring MVC看成是一个标准的web框架。他们尝试通过Spring MVC和Json方式的视图结合成为一个方案,比如Json-Lib-Ext-Spring

在我们第一个Web2.0工程里我们寻找一种方式使用服务器端Spring-MVC的知识接收和响应Ajax请求。但是没有一个令苛刻的Spring MVC开发者们感到满意。所以我们开始探索Spring Json-View用于支持所有Spring MVC特性。 

spring-json 1.0 增加到Maven2的下载库,地址如下:

http://repo1.maven.org/maven2

http://spring-json.sourceforge.net/repository

下  载

哪些不同点? 

Spring Json View 深入地集成在Spring MVC模块里。它能够适用于所有的SpringMVC支持(如SimpleFormController)的标准控制器类。

 

配置

它通过SpringXml方式配置

 

绑定

它支持用Spring方式把Bean属性转换到View里。(请参见SimpleFormController的initBinder()方法)

集成了普遍的Json组件。它现在默认支持Sojo,当然还有JsonLib

 

校验

它支持用ValidatorBeans Spring 方式的校验

 

错误处理

它支持Spring方式错误处理,包括全局、字段和绑定错误。

 

异常处理

它使用 JsonExceptionResolver支持 Spring 方式的异常处理。

 

通过它你只要改变视图而不必改变后台编码就能把典型Spring应用转换为典型Web2.0应用。

 

文档中心

 

Spring json-view  为Spring-MVC提供了对JavaScript Object Notation (json) 的支持,它能让你像平时使用spring-mvc一样使用。现在它能够让你的基于Ajax的前端工具更容易提取(服务器端)数据。

基本上,它是通过AbstractView实现的。现在它增加了Spring BindingResult(结果绑定),Field 和GlobalErrors(字段和公共错误信息),完成校验和一个将属性值转换成显示字符串的属性编辑器。但是它也可以提供一些有用的特性为Ajax-Frameworks服务。比如,类似prototype的错误处理。当然还有转换成Json 字符串的Model。

 

查看演示程序可以获得实用的例子。

 

------------------------目录---------------------------- 

绑定

   1.用法说明

   2.JsonStringWriter

       1.SojoJsonStringWriter

       2.JsonlibJsonStringWriter

   3.比较 

校验

   1. Spring MVC 校验样例

错误处理

    1.配置概述

    2.Http状态错误

    3.模型标记错误

    4.自主实现的Json错误处理器

异常处理

    1.配置概述

    2.Json错误处理器

    3.Json异常处理器

       1.ExceptionMessageExceptionHandler(异常消息异常处理器)

       2.StackTraceExceptionHandler (堆栈异常处理器)

       3.自定义实现JsonExceptionHandler 

其它配置

    1.容器类型支持(ContentType)

2.编码支持(Encoding ) 

 

绑定-数据类型转换

 

1.用法说明

   2.JsonStringWriter

       2.1.SojoJsonStringWriter

       2.2.JsonlibJsonStringWriter

   3.比较

 

1. 用法说明

你可以从Spring Command 和FormController中实现你知道的绑定方式。通常你在ServletRequestDataBander中用控制器的初始绑定方法定义一个自定义对象.

 

你能绑定的CustomEditor包括默认的Spring-MVC提供了如下对象绑定到CustomEditor:

  • 像java.util.Date普通数据类型的类
  • 能按CommensBeanUtils-Syntax匹配ComandBean字段的类  

     @Override
     protected void initBinder(HttpServletRequest request, 
                        ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
        binder.registerCustomEditor(Date.class, "birthday", editor);
     }

2. JsonStringWriter

JsonStringWriter 控制 模型/Command对象间值的转换,当然,还有生成Json字符串。JsonStringWriter 最大限度地保持着这种在Spring MVC所知道的自定义编辑器的注册方式。在已经存在Json库的那些数据格式转换的特性没有找到完全符合我们需要的特性。在另外协助的库支持的特殊特性你又不得不使用。所以你将发现依照JsonStringWriter的实现绑定支持的不同。在下面的章节你会发现它们如何帮助你去选择一个JsonStringWriter。 

2.1 SojoJsonStringWriter - Sojo Json 支持

SojoJsonWriter 是Spring Json-View 的默认实现。它是一个通过Sojo Json 方式传输和接近默认Spring-MVC绑定方式的整合方案。

你可以按如下方式绑定自定义编辑器:

   1.  像java.util.Date普通数据类型的类

   2. 能按CommensBeanUtils-Syntax匹配ComandBean字段的类  
   3. 可选:像那些附加referenceData-method的Model中任意其它类

2.2 JsonlibJsonStringWriter -  Json-Lib支持

JsonlibJsonStringWriter 提供了Json-Lib框架到Spring Json-View的集成。我没有发现它有按CommensBeanUtils-Syntax匹配ComandBean实现本地化属性的方法。但是你可以通过注册一个JsonlibJsonWriterConfiguratorTemplat从而操纵Json-Lib框架。它被封装在一个net.sf.json.JsonConfig对象里。更多信息请参见Json-lib 主页。

你可以按如下方式绑定自定义编辑器:

   1. 像java.util.Date普通数据类型的对象  (it converts the howl model map.)
   2. 可选:通过JsonlibJsonWriterConfiguratorTemplate注册一个自定义的"net.sf.json.JsonConfig" 对象。 

3 比较

 

SojoJsonStringWriter

JsonlibJsonStringWriter

Supported library

SOJO-0.5.0

JSON-lib-2.2.1

Default Writer

yes

no

ComandBean conversion

 

 

Convert class types

yes

yes

Properties located by Commons BeanUtils syntax

yes
explicit Collection conversion

no

Other model map properties conversion

 

 

Convert class types

optional

always

Properties located by
Commons BeanUtils syntax

optional
explicit Collection conversion

no

JsonWriterConfiguratorTemplate

optional

optional

 
SojoJsonWriter - Sojo Json 支持

   1. 绪论
   2. 简单绑定
   3. 使用CommandBean-Property绑定
   4. 转换所有Model Values.
         1. Model-Map通过CustomEditor转换所有值

         2. Model-Map通过CustomEditor转换特殊值

 

1. 绪论

SojoJsonWriter 是Spring Json-View 的默认实现。它是一个通过Sojo Json 方式传输和接近默认Spring-MVC绑定方式的整合方案。

你可以按如下方式绑定自定义编辑器:

   1.  像java.util.Date普通数据类型的类 
   2. 能按CommensBeanUtils-Syntax匹配ComandBean字段的类

   3. 可选:像那些附加referenceData-method的Model中任意其它类 

注意: 
        Spring Json View 不能绑定如下例Bean中Collection类型中的属性

        * Spring提供的写法:

          bean.list.property

          这个语法是找出conllection中从0-n的所有属性
        * Spring Json View 能找出像下面这样使用解释型索引的Collection-Beans的属性:

          bean.list[0].property

          bean.set[1].list[2].property

2. 简单绑定 

initBinder 源文件:
=================

@Override
protected void initBinder(HttpServletRequest request, 
                        ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);

结果:
=======

{"command":{
            "birthday":"30-01-2008",
            "marriage":"30-01-2008",
            "placeofbirth":"Sydney"
}}

3. 使用CommandBean-Property绑定

CommonsBeanUtils-Syntax 找出CommandBean中的属性

initBinder 源文件:
==================
@Override
protected void initBinder(HttpServletRequest request, 
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, "birthday", editor);

结果:
======

{"command":{
          "birthday":"30-01-2008",
          "marriage":"Wed Jan 30 00:00:00 GMT 2008",
          "placeofbirth":"Sydney"
}} 

4. 转换所有Model的值

SojoJsonStringWriter 已经提供对非CommandBean-Values在Model Map 随意的转换。你可以利用这个特性在view.xml用JsonWriter- Bean设置convertAllMapValues 属性。

你能在一个CustomEditor定义的字段利用non_commandbean_key找到它们。

    * (name_in_model_map_key).property
    * (key).list[1].property 

配置文件

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
        <property name="jsonWriter"><ref bean="jsonWriter"/></property>
    </bean>
   
    <bean name="jsonWriter"
          class="org.springframework.web.servlet.view.json.writer.sojo.SojoJsonStringWriter">
        <property name="convertAllMapValues"><value>true</value></property>
    </bean>
</beans> 

4.1 Model-Map通过CustomEditor转换所有值 

initBinder 源文件:
==================
@Override
protected void initBinder(HttpServletRequest request, 
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
}
       
结果:
=======

{"signdate":"30-01-2008",
 "command":{
            "birthday":"30-01-2008",
            "marriage":"30-01-2008",
            "placeofbirth":"Sydney"
}}

 

4.2 Model-Map通过CustomEditor转换特殊值

initBinder 源文件:
==================
@Override
protected void initBinder(HttpServletRequest request, 
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, "birthday", editor);
        binder.registerCustomEditor(Date.class, "(signdate)", editor);
}       
结果:
=======

{"signdate":"30-01-2008",
 "command":{
            "birthday":"30-01-2008",
            "marriage":"Wed Jan 30 00:00:00 GMT 2008",
            "placeofbirth":"Sydney"
}}

 

 
JsonlibJsonWriter - Json-Lib支持

   1. 绪论

   2. 使用
   3. 绑定

   4. 注册 JsonlibJsonWriterConfiguratorTemplates

 

1. 绪论

   JsonlibJsonWriter的绑定能力是相当弱的.

   1.你仅仅能在所有Model Map绑定像java.util.Date普通数据类型的类 (你不能具体制定到单个Bean的属性或者Collection 的索引!!!)

   2. 在“model-map to json”转换的过程中你能通过注册JsonlibJsonWriterConfiguratorTemplate订制一个JsonConfig对象。JsonlibJsonWriterConfiguratorTemplate 使你能够使用一些Json-Lib的高级特性,比如你能使用过滤或者触发一些事件。

 

注意:

    JsonlibJsonWriter会 注册一个自己的JsonValueProcessor 并用JsonValueProcessorMatcher匹配。

      * JsonValueProcessor 使JsonlibJsonWriter 能够把自定义编辑器注册到它的一个初始化方法里。

      * JsonValueProcessorMatcher 会匹配JsonValueProcessor所有的值。JsonValueProcessor来决定值是否需要转换。如果你想注册一个自定义的JsonValueProcessor或者 BeanProcessor,请记住,在某种程度上您并不能按你期望的可能来改变JsonlibJsonWriter 的行为,最好多测试你的程序。

      * 你注册的自定义行为不会影响"request-attribute to CommandBean"的绑定和转换方式。

 

2. 使用

   注册一个JsonlibJsonStringWriter-Bean到JsonView。

 

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
            <property name="jsonWriter"><ref bean="jsonlibJsonWriter"/></property>
    </bean>
        <bean name="jsonlibJsonWriter" class="org.springframework.web.servlet.view.json.writer.jsonlib.JsonlibJsonStringWriter"/>
</beans> 

3. 绑定

initBinder 源文件:
=================

@Override
protected void initBinder(HttpServletRequest request, 
                        ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
}

结果:
=======

{"signdate":"30-01-2008",
 "command":{
            "birthday":"30-01-2008",
            "marriage":"30-01-2008",
            "placeofbirth":"Sydney"
}} 

4. 注册JsonlibJsonWriterConfiguratorTemplates

如果你想使用JsonlibJsonWriterConfiguratorTemplate,你不得不

   1.   在JsonlibJsonStringWriter设置"enableJsonConfigSupport"属性。
   2.   实现JsonlibJsonWriterConfiguratorTemplate抽象类。
   3.    注册JsonlibJsonWriterConfiguratorTemplate到JsonWriterConfiguratorTemplateRegistry,它会优先把一个JsonlibJsonWriterConfiguratorTemplate 注册一个初始化绑定方法里,但是也你能在任何你能发送请求的控制器方法里注册它。这和在基于控制器接口的实现时处理请求的方法是一样的。


4.1 在Spring 配置文件里设置 "enableJsonConfigSupport"属性

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
            <property name="jsonWriter"><ref bean="jsonlibJsonWriter"/></property>
    </bean>
       
        <bean name="jsonlibJsonWriter" class="org.springframework.web.servlet.view.json.writer.jsonlib.JsonlibJsonStringWriter">
        <property name="enableJsonConfigSupport"><value>true</value></property>
    </bean>
</beans> 

4.2 注册 JsonlibJsonWriterConfiguratorTemplate

initBinder 源文件:
==================
@Override
protected void initBinder(HttpServletRequest request,  ServletRequestDataBinder binder) throws Exception{
    JsonWriterConfiguratorTemplateRegistry registry = JsonWriterConfiguratorTemplateRegistry.load(request);            
    registry.registerConfiguratorTemplate(
         new JsonlibJsonWriterConfiguratorTemplate(){
                @Override
                public JsonConfig getJsonConfig() {
                    JsonConfig config =  new JsonConfig();                         
                    // Exclude all date properties
                    config.setJsonPropertyFilter( new PropertyFilter(){ 
                    public boolean apply( Object source, String name, Object value ) { 
                          if( value != null && Date.class.isAssignableFrom( value.getClass() ) ){ 
                              return true; 
                          } 
                          return false; 
                       } 
                    }); 
                    return config;
                }
         }
   );
}

结果:
=======

{
 "command":{
            "placeofbirth":"Sydney"
}} 

校验

来自Post的请求校验的非常容易。仅仅需要按Spring方式注册一个校验器。Spring Json View 在返回Json字符串数据时增加字段错误处理

校验器

用Validaor-Interface实现一个自己校验器类

 

public class SpringJsonValidator implements Validator {

public void validate(Object obj, Errors errors) {

SpringJsonForm form = (SpringJsonForm) obj;

if (form.getPlaceofbirth() == null || "".equals(form.getPlaceofbirth())) {

errors.rejectValue("placeofbirth", "error.no.placeofbirth", null, "Placeofbirth required.");

}

}

@Override

public boolean supports(Class clazz) {

return SpringJsonForm.class.equals(clazz);

}

}

 

Spring ApplicationContext

 

在SimpleFormController中添加校验器

 

<beans>

<bean name="simpleJsonPostFormController"

class="org.thing.spring.json.controller.SimpleJsonPostFormController">

<property name="commandClass">

<value>org.thing.spring.json.controller.SpringJsonForm</value>

</property>

<property name="formView"><value>jsonView</value></property>

<property name="successView"><value>jsonView</value></property>

<property name="validator"><ref bean="validator"/></property>

</bean>

<bean name="validator" class="org.thing.spring.json.controller.SpringJsonValidator"/>

</beans>

结果

Spring Json View  增加Json response 字段错误提示。

{"command":{

"birthday":"08-02-2008",

"placeofbirth":""

},

"failure":"true",

"hasGlobalErrors":"false",

"hasFieldErrors":"true",

"fielderrors":{

"placeofbirth":"Please enter a a place of birth!"

}} 

错误处理

错误处理在控制器向Model中增加一些公共或字段级错误(绑定的结果集)后触发。

 

配置

HttpStatusError

ModelFlagError 

自主实现的JsonErrorHandler

 

1. Spring配置文件:view.xml

把错误(公共级别的和字段级别的)配置好后转换成一个json字符串,所有注册的Json错误处理器在他们被添加按规则触发。

下列是JsonErrorHadnders的实现:

HttpStatusError

用response.setStatus(errorCode)设置一个新返回状态;一些Ajax框架比如prototype.js中触发成功状态使用返回状态编码是200-299,失败状态使用>=300,

默认编码为311.

ModelFlagError

在Model里增加一个简单键值对。一些Web2.0 表现层框架需要一个标记来判断服务器端的操作是否成功或失败。比如Ext框架需要一个failure=true 或者 success=true

默认标记是failure=true

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

<property name="jsonErrors">

<list>

<ref bean="statusError" />

<ref bean="modelflagError" />

</list>

</property>

</bean>

<bean name="statusError"

class="org.springframework.web.servlet.view.json.error.HttpStatusError"/>

<bean name="modelflagError"

class="org.springframework.web.servlet.view.json.error.ModelFlagError"/>

</beans>

结果:

=======

Response-Status : 311

{"command":{

"birthday":"30-01-2008",

"placeofbirth":"Sydney"

},

"failure":"true",

"hasGlobalErrors":"true",

"globalerrors": ["errormessage1","errormessage2"],

"hasFieldErrors":"true",

"fielderrors":{

"birthday":"Please enter a valide date!"

}} 

2. HttpStatusError

你能在HttpStatusError Bean的错误编码属性里自定义状态错误编码到响应信息里。

 

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

<property name="jsonErrors">

<list>

<ref bean="statusError" />

</list>

</property>

</bean>

<bean name="statusError"

class="org.springframework.web.servlet.view.json.error.HttpStatusError">

<property name="errorCode"><value>999</value></property>

</bean>

</beans>

结果:

=======

Response-Status : 999

{"command":{

"birthday":"30-01-2008",

"placeofbirth":"Sydney"

},

"hasGlobalErrors":"true",

"globalerrors": ["errormessage1","errormessage2"],

"hasFieldErrors":"true",

"fielderrors":{

"birthday":"Please enter a valide date!"

}}

3. ModelFlagError

你能在ModelFlagError Bean以键值对方式设置到Model里。 

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

<property name="jsonErrors">

<list>

<ref bean="statusError" />

<ref bean="modelflagError" />

</list>

</property>

</bean>

<bean name="modelflagError"

class="org.springframework.web.servlet.view.json.error.ModelFlagError">

<property name="name"><value>failure</value></property>

<property name="value"><value>true</value></property>

</bean>

</beans> 

结果:

=======

Response-Status : 200

{"command":{

"birthday":"30-01-2008",

"placeofbirth":"Sydney"

},

"failure":"true",

"hasGlobalErrors":"true",

"globalerrors": ["errormessage1","errormessage2"],

"hasFieldErrors":"true",

"fielderrors":{

"birthday":"Please enter a valide date!"

}}

4. 自定义实现JsonErrorHandler

你也可以实现JsonErrorHandler,来用一些完全不同的方式重构。

public class MyErrorHandler implements JsonErrorHandler {

public void triggerError(Map model, RequestContext rc, BindingResult br,

HttpServletRequest request, HttpServletResponse response)

throws Exception{

// Do something ...

}

异常处理

Spring Json-View 提供HandlerExceptionResolver (JsonExceptionResolver)在Controller操作的期间捕获并抛出异常。

 

配置

JsonErrorHandler

JsonExceptionHandler

ExceptionMessageExceptionHandler(异常消息异常处理器)

StackTraceExceptionHandler (堆栈异常处理器)

自定义实现JsonExceptionHandler 

1. 配置:Spring ApplicationContext

你几乎只需要注册一个JsonErrorHandlers 或者 JsonExceptionHandler 就可以来操作函数中的响应以便抛出异常。 

注意:

把JsonExceptionResolver 注册在ApplicationContext.xml,

而不是view.xml!!!,不然会找不到它。

JsonErrorHandlers

JsonErrorHandlers 发响应到客户端因为有些产生了错误。详细信息参见Errorhandling

HttpStatusError

用response.setStatus(错误编码)设置一个Response-Status。  

ModelFlagError

在Model中添加一个简单键值对。 

JsonExceptionHandler

JsonExceptionHandler负责把Java异常对象转换成一个Json字符串。 

ExceptionMessageExceptionHandler

添加一个Java异常到Model里。默认的ModelKey是"exception.message ". ExceptionMessageExceptionHandler 用"Exception Classname : Exception Message "格式设置错误信息。

比如 : "java.lang.IllegalArgumentException : Please set Parameter "

StackTraceExceptionHandler  

把完整的堆栈异常添加到Model.默认的ModelKey是"exception.stacktrace".当replaceLineBreakes=true时表示可用Html</br>标记代替"/n",默认replaceLineBreakes=false。

<beans>

<bean id="exceptionResolver"

class="org.springframework.web.servlet.view.json.exception.JsonExceptionResolver">

<property name="exceptionView"><value>jsonView</value></property>

<property name="errorHandler">

<list>

<ref bean="statusError" />

<ref bean="modelFlagError" />

</list>

</property>

<property name="exceptionHandler">

<list>

<ref bean="exceptionMessageExceptionHandler" />

<ref bean="stackTraceExceptionHandler" />

</list>

</property>

</bean>

<bean name="exceptionMessageExceptionHandler"

class="org.springframework.web.servlet.view.json.exception.ExceptionMessageExceptionHandler" />

<bean name="stackTraceExceptionHandler"

class="org.springframework.web.servlet.view.json.exception.StackTraceExceptionHandler" />

<bean name="statusError"

class="org.springframework.web.servlet.view.json.error.HttpStatusError"/>

<bean name="modelFlagError"

class="org.springframework.web.servlet.view.json.error.ModelFlagError"/>

</beans> 

结果:

=======

Response-Status : 311

{

"failure":"true",

"exception.message":"java.lang.Exception: You throw an exeption !",

"exception.stacktrace": "java.lang.Exception: You throw an exeption !

/n/tat org.thing.spring.json.controller.[...]

/n/tat org.springframework.web.servlet.mvc.[...]

[...]"

}

2. ExceptionMessageExceptionHandler

你也可以自己订制Model-key方式的异常信息。默认是exception.message

<beans>

<bean id="exceptionResolver"

class="org.springframework.web.servlet.view.json.exception.JsonExceptionResolver">

<property name="exceptionView"><value>jsonView</value></property>

<property name="exceptionHandler">

<list>

<ref bean="exceptionMessageExceptionHandler" />

</list>

</property>

</bean>

<bean name="exceptionMessageExceptionHandler"

class="org.springframework.web.servlet.view.json.exception.ExceptionMessageExceptionHandler">

<property name="modelKey"><value>myKey</value></property>

</bean>

</beans>

结果:

=======

Response-Status : 200

{

"myKey":"java.lang.Exception: You throw an exeption !"

}

3. StackTraceExceptionHandler

你能订制Model-Key的堆栈跟踪异常(默认是exception.stacktrace);你也能用Html视图模式展现它,replaceLineBreakes=true可用Html</br>标记代替"/n",默认replaceLineBreakes=false 

<beans>

<bean id="exceptionResolver"

class="org.springframework.web.servlet.view.json.exception.JsonExceptionResolver">

<property name="exceptionView"><value>jsonView</value></property>

<property name="exceptionHandler">

<list>

<ref bean="stackTraceExceptionHandler" />

</list>

</property>

</bean>

<bean name="stackTraceExceptionHandler"

class="org.springframework.web.servlet.view.json.exception.StackTraceExceptionHandler">

<property name="replaceLineBreakes"><value>true</value></property>

<property name="modelKey"><value>myKey</value></property>

</bean>

</beans>

结果:

=======

Response-Status : 200

{

"myKey": "java.lang.Exception: You throw an exeption !

</br>/tat org.thing.spring.json.controller.[...]

</br>/tat org.springframework.web.servlet.mvc.[...]

[...]"

}

4. Custom implementation of JsonExceptionHandler

你也可以自己实现JsonExceptionHandler,并用一些完全不同的方式重构。

public class MyExceptionHandler implements JsonExceptionHandler {

public void triggerException(Exception exception, Map model,

HttpServletRequest request, HttpServletResponse response)

throws Exception{

// Do something ...

}

其它配置 

ContentType 内容类型

Encoding 字符编码 

1. Content type

你可以像下面展现的那样,在JsonView设置contentType的值来改变输出内容的文本类型。 

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

<property name="contentType"><value>application/json</value></property>

</bean>

</beans>

2. Encoding

你可以像下面展现的那样,在JsonView设置encoding的值来改变输出内容的字符编码。

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

<property name="encoding"><value>ISO-8859-1</value></property>

</bean>

</beans> 

演示程序 

关于 

这个演示程序显示了下列用例生成的Json-Result方式的结果集

用Controller-Interface方式提交Get请求 [快速开始]

用Command-Controller方式提交Post请求 [快速开始]

用SimpleForm-Controller方式提交GET/Post请求[快速开始]

使用JsonExceptionResolver抛出异常捕获信息的请求 [快速开始]

 

安装

仅仅需要在这里下载war并部署到你的应用服务器.这里的测试环境建立在apache-tomcat-5.5.25.

 

快速开始

首先要了解Spring-MVC的基础.

详细信息参考如下资料:

          Springframework Doku

          Spring-MVC Step-by-Step

 

配置Spring Json-View非常容易,只需要注册一个XML视图解析器

[也可查看演示程序]

Spring ApplicationContext

<beans>

[...]

<bean name="viewResolver"

class="org.springframework.web.servlet.view.XmlViewResolver" />

[...]

</beans>

Spring view.xml

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"/>

</beans>

 

快速开始-用Controller-Interface提交Get请求

 

Spring中不支持Controller-Interface的验证或绑定。它却能容易地处理来自Get方式的请求。

这个示例在Controller中仅仅返回一个用Model-Map产生的Json字符串,没有错误包含或者格式转换。

[也可查看演示程序]

 

Spring ApplicationContext

 

<beans>

<bean name="simpleJsonGetController"

class="org.thing.spring.json.controller.SimpleJsonGetController"/>

<bean name="urlMapping"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="mappings">

<props>

<prop key="/hello.json">simpleJsonGetController</prop>

</props>

</property>

</bean>

<bean name="viewResolver"

class="org.springframework.web.servlet.view.XmlViewResolver" />

</beans>

Spring view.xml

<beans>

<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"/>

</beans>

 

form.html

 

<head>

<title>

First Test Spring Json Demo

</title>

<script type="text/javascript" src="script/prototype.js"></script>

<script type="text/javascript" src="script/behaviour.js"></script>

<script type="text/javascript" src="script/behaviour-roles.js"></script>

<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"/>

</head>

</head>

<body>

<h1>Spring JSON DEMO</h1>

<h2>Spring Ajax Get (ControlerInterface)</h2>

<b>firstname : </b><span id="firstname"></span><br/>

<b>secondname : </b><span id="secondname"></span><br/>

</br>

<button id="getName">get name</button>

<button id="clearName">clear name</button><br/>

</body>

 

JavaScript behaviour-roles.js

 

var printResult = function(transport){

var result =

"Status : " + transport.status

+ "/n"

+ "/n"

+ "Json-Result:"

+ "/n" + transport.responseText;

alert(result);

};

var myrules = {

'button#getName' : function(element){

element.onclick = function(){

new Ajax.Request('hello.json', { method:'get',

onSuccess: function(transport, json){

var json = transport.responseText.evalJSON();

printResult(transport);

$('firstname').innerHTML = json.firstname;

$('secondname').innerHTML = json.secondname;

}

});

}

},

'button#clearName' : function(element){

element.onclick = function(){

$('firstname').innerHTML = '';

$('secondname').innerHTML = '';

}

}

};

Behaviour.register(myrules);

 

Controller 源码

 

public class SimpleJsonGetController implements Controller {

public ModelAndView handleRequest(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

Map model = new HashMap();

model.put("firstname", "Peter");

model.put("secondname", "Schmitt");

return new ModelAndView("jsonView", model);

}

}

 

结果

 

 Status : 200

 Result:

           {"firstname":"Peter","secondname":"Schmitt"}

 

 

快速开始- 用Command-Controller提交Post请求

 

Command-Controller提供一个完整的CommandBean,Spring对它提供校验和绑定支持。但是你不得不在你的控制器类里添加校验和绑定处理。它处理简单的Post请求非常容易。这个示例在Command-Controller中仅仅返回一个用Model-Map产生的Json字符串,没有错误包含或者格式转换。

 [也可查看演示程序]

 

 Spring ApplicationContext

 

<beans>

    <bean name="simpleJsonPostFormController"

          class="org.thing.spring.json.controller.SimpleJsonPostFormController">

            <property name="commandClass">

                <value>org.thing.spring.json.controller.SpringJsonForm</value>

            </property>

    </bean>

    <bean name="urlMapping"

          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

        <property name="mappings">

            <props>

                <prop key="/hello.json">simpleJsonPostCommandController</prop>

           </props>

        </property>

    </bean>

    <bean name="viewResolver"

        class="org.springframework.web.servlet.view.XmlViewResolver" />

</beans> Spring view.xml<beans>

    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"/>

</beans>

 

 form.html

<head>

        <title>

                First Test Spring Json Demo

        </title>

        <script type="text/javascript" src="script/prototype.js"></script>

        <script type="text/javascript" src="script/behaviour.js"></script>

        <script type="text/javascript" src="script/behaviour-roles.js"></script>

        <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"/>

</head>

</head>

<body>

        <h1>Spring JSON DEMO</h1>

        <h2>Spring Ajax Post (SimpleFormControler and CommandController)</h2>

        <form method="post" id="form">

                <input id="placeofbirth" type="text" name="placeofbirth" ><br>

                <input id="birthday" type="text" name="birthday" ><br/>

                <br/>

                <b>place of birth : </b><span id="t_placeofbirth"></span><br/>

                <b>birthday : </b><span id="t_birthday"></span><br/>

       

        </form>

        <br/>

        <button id="clearData">clear name</button>

        <button id="cc_postData">send data to CommandController</button>

</body>

 

JavaScript behaviour-roles.js

 

var printResult = function(transport){

                var result =

                        "Status : " + transport.status

                        + "/n"

                        + "/n"

                        + "Json-Result:"

                        + "/n" + transport.responseText;

                alert(result);

};

var myrules = {

        'button#clearData' : function(element){

                element.onclick = function(){

                        $('t_placeofbirth').innerHTML = '';

                        $('t_birthday').innerHTML = '';

                        $('error').innerHTML = '';

        },

        'button#cc_postData' : function(element){

                element.onclick = function(){

                        new Ajax.Request('hello.json', {

                                method:'post',

                                parameters: $('form').serialize(false),

                                onSuccess: function(transport){

                                        var json = transport.responseText.evalJSON();

                                        printResult(transport);

                                        $('t_placeofbirth').innerHTML = json.placeofbirth;

                                        $('t_birthday').innerHTML = json.birthday;

                                        $('error').innerHTML = '';

                        },

                        onFailure: function(transport){

                                printResult(transport);

                                addErrors(transport);

                        }

                       

                        });

                }

        }

};

Behaviour.register(myrules);

 

CommandBean

 

public class SpringJsonForm {

        private String placeofbirth;

        private Date birthday;

       

       

        public String getPlaceofbirth() {

                return placeofbirth;

        }

        public void setPlaceofbirth(String placeofbirth) {

                this.placeofbirth = placeofbirth;

        }

        public Date getBirthday() {

                return birthday;

        }

        public void setBirthday(Date birthday) {

                this.birthday = birthday;

        }

}

 

控制器源码

 

 public class SimpleJsonPostCommandController extends AbstractCommandController {

        @Override

        protected void initBinder(HttpServletRequest request, 

                        ServletRequestDataBinder binder) throws Exception{

                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");

                CustomDateEditor editor = new CustomDateEditor(dateFormat, true);

                binder.registerCustomEditor(Date.class, editor);

        }

       

        @Override

        protected ModelAndView handle(HttpServletRequest request,

                        HttpServletResponse response, Object command,

                        BindException exception) throws Exception {

               

                SpringJsonForm bean = (SpringJsonForm) command;

               

                ModelAndView modelAndView = new ModelAndView("jsonView");

               

                modelAndView.addObject("birthday",  bean.getBirthday());

                modelAndView.addObject("placeofbirth",  bean.getPlaceofbirth());

                return modelAndView;

        }

}

 

结果 

 

Status : 200

 

 Result:

 {"placeofbirth":"Sydney","birthday":"Wed Jan 30 00:00:00 GMT 2008"}

 

 

快速开始-用SimpleForm-Controller提交GET/POST请求

 

 Command-Controller提供一个完整的CommandBean,Spring对它提供校验和绑定支持。这个示例在Command-Controller中返回一个用Model-Map产生的Json字符串,返回信息中包含字段错误、全局错误和绑定。支持CommandBean属性类型转换。Get请求需要依赖formBackingObject方法Post请求需要依赖onSubmitAction方法详细信息参见文档

[也可查看演示程序]

 

Spring ApplicationContext

 

 <beans>

    <bean name="simpleJsonPostFormController"

         class="org.thing.spring.json.controller.SimpleJsonPostFormController">

            <property name="commandClass">

                <value>org.thing.spring.json.controller.SpringJsonForm</value>

            </property>

        <property name="formView"><value>jsonView</value></property>

        <property name="successView"><value>jsonView</value></property>

    </bean>

    <bean name="urlMapping"

          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

        <property name="mappings">

            <props>

                <prop key="/hello.json">simpleJsonPostFormController</prop>

           </props>

        </property>

    </bean>

    <bean name="viewResolver"

        class="org.springframework.web.servlet.view.XmlViewResolver" />

</beans>Spring view.xml<beans>

    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

            <property name="jsonErrors">

                <list>

                        <ref bean="statusError" />

                        <ref bean="modelflagError" />

                </list>

        </property>

    </bean>

   

    <bean name="statusError"

          class="org.springframework.web.servlet.view.json.error.HttpStatusError">

          <property name="errorCode"><value>311</value></property>

    </bean>

    <bean name="modelflagError"

          class="org.springframework.web.servlet.view.json.error.ModelFlagError">

          <property name="name"><value>failure</value></property>

          <property name="value"><value>true</value></property>

    </bean>

       

</beans>

 

form.html

 

<head>

        <title>

                First Test Spring Json Demo

        </title>

        <script type="text/javascript" src="script/prototype.js"></script>

        <script type="text/javascript" src="script/behaviour.js"></script>

        <script type="text/javascript" src="script/behaviour-roles.js"></script>

        <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"/>

</head>

</head>

<body>

        <h1>Spring JSON DEMO</h1>

        <h2>Spring Ajax Post (SimpleFormControler and CommandController)</h2>

        <form method="post" id="form">

                <input id="placeofbirth" type="text" name="placeofbirth" ><br>

                <input id="birthday" type="text" name="birthday" ><br/>

                <br/>

                <b>place of birth : </b><span id="t_placeofbirth"></span><br/>

                <b>birthday : </b><span id="t_birthday"></span><br/>

       

        </form>

        <br/>

        <span id ="error" ></span>

        <br/>

        <button id="clearData">clear name</button>

        <<button id="sfc_postData">send data to SimpleFormController</button>

</body>

 

JavaScript behaviour-roles.js

 

var printResult = function(transport){

                var result =

                        "Status : " + transport.status

                        + "/n"

                        + "/n"

                        + "Json-Result:"

                        + "/n" + transport.responseText;

                alert(result);

};

var addErrors = function(transport){

        var json = transport.responseText.evalJSON();

       

        var error = "Errorhandler Info: </br>"

        + "failture: " + json.failure +"</br>"

        + "status : + " + transport.status +"</br>"

        +"</br>"

        +"Spring Errorhandling: </br>"

        + "hasGlobalErrors : " + json.hasGlobalErrors +"</br>"

        + "</br>"

        + "hasFieldErrors : " + json.hasFieldErrors +"</br>"$$

        if(json.fielderrors.birthday)

                error = error + "birthday : " + json.fielderrors.birthday +"</br>"$$

        if(json.fielderrors.placeofbirth)

                error = error + "placeofbirth : " + json.fielderrors.placeofbirth +"</br>"$$

       

        $('error').innerHTML = error;

};

var myrules = {

        'button#clearData' : function(element){

                element.onclick = function(){

                        $('t_placeofbirth').innerHTML = '';

                        $('t_birthday').innerHTML = '';

                        $('error').innerHTML = '';

        },

        'button#sfc_postData' : function(element){

       

            new Ajax.Request('hello1.json', {

                                method:'get',

                                onSuccess: function(transport){

                                        var json = transport.responseText.evalJSON();

                                        printResult(transport);

                                $('placeofbirth').value = json.command.placeofbirth;

                                $('birthday').value = json.command.birthday;

                        },

                        onFailure: function(transport){

                                var json = transport.responseText.evalJSON();

                                        printResult(transport);

                                        addErrors(transport);

                        }

                       

                        });

           

                element.onclick = function(){

                        new Ajax.Request('hello1.json', {

                                method:'post',

                                parameters: $('form').serialize(false),

                                onSuccess: function(transport){

                                        var json = transport.responseText.evalJSON();

                                        printResult(transport);

                                        $('t_placeofbirth').innerHTML = json.command.placeofbirth;

                                $('t_birthday').innerHTML =  json.command.birthday;

                                $('error').innerHTML = '';

                        },

                        onFailure: function(transport){

                                var json = transport.responseText.evalJSON();

                                        printResult(transport);

                                        addErrors(transport);

                        }

                       

                        });

                }

        }

};

Behaviour.register(myrules);

 

CommandBean

 

public class SpringJsonForm {

        private String placeofbirth;

        private Date birthday;

       

       

        public String getPlaceofbirth() {

                return placeofbirth;

        }

        public void setPlaceofbirth(String placeofbirth) {

                this.placeofbirth = placeofbirth;

        }

        public Date getBirthday() {

                return birthday;

        }

        public void setBirthday(Date birthday) {

                this.birthday = birthday;

        }

}

 

控制器源码

 

public class SimpleJsonPostFormController extends SimpleFormController {

        protected void initBinder(HttpServletRequest request,  ServletRequestDataBinder binder) throws Exception{

                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");

                CustomDateEditor editor = new CustomDateEditor(dateFormat, true);

                binder.registerCustomEditor(Date.class, editor);

        }

        @Override

        protected Object formBackingObject(HttpServletRequest request)

                        throws Exception {

                SpringJsonForm bean = new SpringJsonForm();

                bean.setBirthday(new Date());

                bean.setPlaceofbirth("Sydney");

                return bean;

        }

        public void onSubmitAction(Object command, BindException errors) {

                SpringJsonForm bean = (SpringJsonForm) command;

        }

}

 

结果 

 

GET-Response  Status : 200

 

 Result:

 {"firstname":"Peter","secondname":"Schmitt"}POST Response Response-Status : 311

{"command":{

            "birthday":"30-01-2008",

            "placeofbirth":"Sydney"

           },

 "failure":"true",

 "hasGlobalErrors":"true",

 "globalerrors": ["errormessage1","errormessage2"], 

 "hasFieldErrors":"true",

 "fielderrors":{

             "birthday":"Please enter a valide date!"

}}

 

 

快速开始-使用JsonExceptionResolver抛出异常捕获信息的请求

 

实现异常处理是通过异常分析处理分析器来完成:JsonExceptionResolver。你仅仅需要注册一个JsonErrorHandlers或者JsonExceptionHandler操作一个返回信息以便抛出异常。 JsonErrorHandlers 发响应到客户端因为有些产生了错误。详细信息参见ErrorhandlingJsonExceptionHandler 转换java.lang.Exception对象并添加到Json字符串。详细信息参见Exceptionhandling

[也可查看演示程序]

 

Spring ApplicationContext

 

 <beans>

    <bean name="viewResolver"

        class="org.springframework.web.servlet.view.XmlViewResolver" />

   

    <bean name="throwExceptionGetController"

        class="org.thing.spring.json.controller.ThrowExceptionGetController"/>

       

    <bean id="exceptionResolver"

        class="org.springframework.web.servlet.view.json.exception.JsonExceptionResolver">

        <property name="exceptionView"><value>jsonView</value></property>

                <property name="errorHandler">

                <list>

                        <ref bean="statusError" />

                        <ref bean="modelflagError" />

                </list>

        </property>

        <property name="exceptionHandler">

                <list>

                        <ref bean="stackTraceExceptionHandler" />

                        <ref bean="exceptionMessageExceptionHandler" />

                </list>

        </property>

        </bean>

   

        <bean name="statusError"

              class="org.springframework.web.servlet.view.json.error.HttpStatusError"/>

       

        <bean name="modelflagError"

              class="org.springframework.web.servlet.view.json.error.ModelFlagError"/

       

        <bean name="stackTraceExceptionHandler"

              class="org.springframework.web.servlet.view.json.exception.StackTraceExceptionHandler"/>

       

        <bean name="exceptionMessageExceptionHandler"

              class="org.springframework.web.servlet.view.json.exception.ExceptionMessageExceptionHandler"/>

</beans>

Spring view.xml

<beans>

    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">

            <property name="jsonErrors">

                <list>

                        <ref bean="statusError" />

                        <ref bean="modelflagError" />

                </list>

        </property>

    </bean>

   

    <bean name="statusError"

          class="org.springframework.web.servlet.view.json.error.HttpStatusError">

          <property name="errorCode"><value>311</value></property>

    </bean>

    <bean name="modelflagError"

          class="org.springframework.web.servlet.view.json.error.ModelFlagError">

          <property name="name"><value>failure</value></property>

          <property name="value"><value>true</value></property>

    </bean>

       

</beans>

 

form.html

 

<head>

        <title>

                First Test Spring Json Demo

        </title>

        <script type="text/javascript" src="script/prototype.js"></script>

        <script type="text/javascript" src="script/behaviour.js"></script>

        <script type="text/javascript" src="script/behaviour-roles.js"></script>

        <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"/>

</head>

</head>

<body>

        <h1>Spring JSON DEMO</h1>

        <h2>Exception-Handling by JsonExceptionResolver</h2>

        <button id="throwException">throw exception</button>

</body>

 

JavaScript behaviour-roles.js

 

var printResult = function(transport){

                var result =

                        "Status : " + transport.status

                        + "/n"

                        + "/n"

                        + "Json-Result:"

                        + "/n" + transport.responseText;

                alert(result);

};

var myrules = {

        'button#throwException' : function(element){

                element.onclick = function(){

                        new Ajax.Request('exception.json', {

                                method:'get',

                                parameters: {throwException: 'true'},

                                onFailure: function(transport){

                                var json = transport.responseText.evalJSON();

                                        printResult(transport);

                        }

                        });

                }

        }

       

};

Behaviour.register(myrules);

 

控制器源码

 

public class ThrowExceptionGetController implements Controller {

        /** Logger for this class and subclasses */

        protected final Log logger = LogFactory.getLog(getClass());

        public ModelAndView handleRequest(HttpServletRequest request,

                        HttpServletResponse response) throws Exception {

                if(request.getParameter("throwException")!= null)

                        throw new Exception("You throw an exeption !");

               

                Map model = new HashMap();

                model.put("exception", "false");

                return new ModelAndView("json1", model);

        }

}

 

结果

 

 GET-Response

 

 Response-Status : 311

{

        "failure":"true",

        "exception.message":"java.lang.Exception: You throw an exeption !",

        "exception.stacktrace":

                        "java.lang.Exception: You throw an exeption !

                        /n/tat org.thing.spring.json.controller.[...]

                        /n/tat org.springframework.web.servlet.mvc.[...]

                        [...]"

}

 

 

下载

在这里下载

 

SVN地址

View-SVN 

 

问答

 

Spring Json-view提供所有的我们知道的Spring-MVC特征吗?

是的,几乎支持所有。Spring Json View能唯一绑定ConllectionBean的详细属性(参见文档Binding部分) 

 

Spring Json-view 直接输出到Json结果集吗? 

不,还没有。暂时它是先产生一个字符串再写到输出流里。  

 

Spring Json View使用哪一个Json引擎 

sojo,详情参见http://sojo.sourceforge.net/ 

json-lib,详情参见http://json-lib.sourceforge.net/

 

 
posted @ 2012-02-21 08:12  张良  阅读(4397)  评论(0编辑  收藏  举报