什么是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://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 |
no |
Other model map properties conversion |
|
|
Convert class types |
optional |
always |
Properties located by |
optional |
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的基础.
详细信息参考如下资料:
配置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地址
问答
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/