SpringMVC3.2.x整合fastJson实现JSONP服务端
因为安全因素,ajax是不能进行跨域请求的,但是机智的程序员们发明了JSONP。Jsonp(JSON with Padding)是资料格式 json 的一种“使用模式”,可以让网页从别的网域获取资料。比如在www.baidu.com域名下可以请求google.com/v1/ajax.json。在前后分离开发的场景下,JSONP的意义重大呀。
由于使用angularJS对前后的开发进行了分离(页面和控制器跑在不同的服务器之中,java代码跑在jetty上,angularJS跑在nginx上),他们之间需要进行测试通信。这时候就得用到JSONP。
开始快乐的改造之旅,打算使用的技术就是fastJson+SpringMVC的组合,首先是3.2之前的整合方式,注意是3.2之前。目前最新版的Fastjson是不能直接支持JSONP的需要添加一些类来帮助完成。
首先是一个数据载体,因为jsonp要求的格式如下。
fn_name (myData)
既然需要这样的结果,就构造这么一个数据载体
package org.soa.rest.jsonp;
/**
* Fastjson的JSONP消息对象
* @author liuyi
*
*/
public class JSONPObject {
private String function;//JSONP回调方法
private Object json;//真正的Json对象
public JSONPObject(String function, Object json) {
this.function = function;
this.json = json;
}
//getter setter
}Spring提供了灰常方便的注解@ResponseBody的方式返回json数据,在3.2之后的版本中,只要在spring-mvc的配置文件中加入
<mvc:annotation-driven>
就默认使用jackson来进行处理底层的转换,这里我们使用FastJSON,因为需要支持jsonp所有需要对已有的转换器进行修改。
/**
* 支持JSONP的Fastjson的消息转换器
* @author liuyi
*
*/
public class FastJsonHttpMessageConverter extends com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter {
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
if (obj instanceof JSONPObject) {
JSONPObject jsonp = (JSONPObject) obj;
OutputStream out = outputMessage.getBody();
String text = jsonp.getFunction() + "(" + JSON.toJSONString(jsonp.getJson(), getFeatures()) + ")";
System.out.println(text);
byte[] bytes = text.getBytes(getCharset());
out.write(bytes);
} else {
super.writeInternal(obj, outputMessage);
}
}
}注册到spring中
<bean id="fastJsonHttpMessageConverter"
class="org.soa.rest.jsonp.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="features" >
<list>
<value>WriteNullBooleanAsFalse</value>
<value>QuoteFieldNames</value>
<value>WriteDateUseDateFormat</value>
<value>WriteNullStringAsEmpty</value>
</list>
</property>
</bean>3.2之前在只需要加入下面这段配置自定义的转换器就能工作了
!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="fastJsonHttpMessageConverter" /><!-- json转换器 -->
</list>
</property>在3.2中测试上面放法失效,折腾了多久总算找到解决方式,需要加入以下配置,简单的说就是要把转化器配置在mvc:annotation-driven中。
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="false">
<ref bean="fastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true" />
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes" >
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>控制器中的代码
@ResponseBody
@RequestMapping(value="/sys/invoker"
,method={RequestMethod.GET,RequestMethod.POST})
public JSONPObject login(@ModelAttribute SoaContext context,HttpServletRequest request,String callback) {
final long begin = System.currentTimeMillis();
final Enumeration<String> names = request.getParameterNames();
while (names.hasMoreElements()) {
String key = names.nextElement();
if(key.intern() == "method".intern() ||key.intern() == "service".intern()) continue;
context.addAttr(key, request.getParameter(key));
}
context = soaManger.callNoTx(context);
SoaLogger.debug(getClass(), "service {} in method {}执行时间{}ms",context.getService(),context.getMethod(), System.currentTimeMillis()-begin);
//只要放回Jsonp对象即可
return new JSONPObject(callback,context);
}客户端代码
(function() {
$.ajax({
url: "http://localhost:8080/soa-rest/sys/invoker?service=userService&method=page",
dataType: 'jsonp',
data: '',
jsonp: 'callback',
success: function(result) {
console.log(result);
},
timeout: 3000
});到此整合完成;
参考文档:http://stackoverflow.com/questions/14333709/spring-mvc-3-2-and-json-objectmapper-issue
完整列子:https://github.com/247687009/soa/
相关推荐
fengchao000 2020-06-17
adonislu 2020-05-16
zmosquito 2020-05-10
adonislu 2020-05-10
somebodyoneday 2020-04-22
fengchao000 2020-04-22
fengchao000 2020-04-11
Richardxx 2020-03-07
somebodyoneday 2020-03-06
fengchao000 2020-03-05
somebodyoneday 2020-02-16
xiaouncle 2020-02-13
baijinswpu 2020-01-29
fengchao000 2020-01-10
fengchao000 2019-12-25
newthon 2019-12-23
somebodyoneday 2013-07-11