Spring3.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要求的格式如下。

 

 

Js代码   收藏代码
  1. fn_name (myData)  

 

 

既然需要这样的结果,就构造这么一个数据载体

 

Java代码   收藏代码
  1. package org.soa.rest.jsonp;  
  2.   
  3. /** 
  4.  * Fastjson的JSONP消息对象 
  5.  * @author liuyi 
  6.  * 
  7.  */  
  8. public class JSONPObject {  
  9.   
  10.     private String function;//JSONP回调方法  
  11.     private Object json;//真正的Json对象  
  12.   
  13.     public JSONPObject(String function, Object json) {  
  14.         this.function = function;  
  15.         this.json = json;  
  16.     }  
  17.   
  18.     //getter setter  
  19. }  

 

 

Spring提供了灰常方便的注解@ResponseBody的方式返回json数据,在3.2之后的版本中,只要在spring-mvc的配置文件中加入

 

Java代码   收藏代码
  1. <mvc:annotation-driven>   

 

 

就默认使用jackson来进行处理底层的转换,这里我们使用FastJSON,因为需要支持jsonp所有需要对已有的转换器进行修改。
Java代码   收藏代码
  1. /** 
  2.  * 支持JSONP的Fastjson的消息转换器 
  3.  * @author liuyi 
  4.  * 
  5.  */  
  6. public class FastJsonHttpMessageConverter extends com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter {  
  7.     @Override  
  8.     protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {  
  9.         if (obj instanceof JSONPObject) {  
  10.             JSONPObject jsonp = (JSONPObject) obj;  
  11.             OutputStream out = outputMessage.getBody();  
  12.             String text = jsonp.getFunction() + "(" + JSON.toJSONString(jsonp.getJson(), getFeatures()) + ")";  
  13.             System.out.println(text);  
  14.             byte[] bytes = text.getBytes(getCharset());  
  15.             out.write(bytes);  
  16.         } else {  
  17.             super.writeInternal(obj, outputMessage);  
  18.         }  
  19.     }   
  20. }  

 

注册到spring中

 

Xml代码   收藏代码
  1. <bean id="fastJsonHttpMessageConverter"  
  2.     class="org.soa.rest.jsonp.FastJsonHttpMessageConverter">  
  3.     <property name="supportedMediaTypes">  
  4.         <list>  
  5.             <value>application/json;charset=UTF-8</value>  
  6.             <value>text/html;charset=UTF-8</value>  
  7.         </list>  
  8.     </property>  
  9.     <property name="features" >  
  10.        <list>  
  11.       <value>WriteNullBooleanAsFalse</value>  
  12.       <value>QuoteFieldNames</value>    
  13.                <value>WriteDateUseDateFormat</value>   
  14.                <value>WriteNullStringAsEmpty</value>    
  15.        </list>  
  16.     </property>  
  17. </bean>  

 

 

3.2之前在只需要加入下面这段配置自定义的转换器就能工作了
Xml代码   收藏代码
  1. !-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->  
  2.     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
  3.         <property name="messageConverters">  
  4.             <list>  
  5.                 <ref bean="fastJsonHttpMessageConverter" /><!-- json转换器 -->  
  6.             </list>  
  7.         </property>  

 

在3.2中测试上面放法失效,折腾了多久总算找到解决方式,需要加入以下配置,简单的说就是要把转化器配置在mvc:annotation-driven中。
Xml代码   收藏代码
  1. <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">  
  2.     <mvc:message-converters register-defaults="false">  
  3.         <ref bean="fastJsonHttpMessageConverter"/>  
  4.     </mvc:message-converters>  
  5. </mvc:annotation-driven>   
  6.   
  7.     <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">  
  8.     <property name="favorPathExtension" value="true" />  
  9.     <property name="ignoreAcceptHeader" value="false" />   
  10.     <property name="mediaTypes" >  
  11.         <value>  
  12.             json=application/json  
  13.             xml=application/xml  
  14.         </value>  
  15.     </property>  
  16. </bean>  

 

控制器中的代码
Java代码   收藏代码
  1. @ResponseBody  
  2. @RequestMapping(value="/sys/invoker"  
  3.                 ,method={RequestMethod.GET,RequestMethod.POST})  
  4. public JSONPObject login(@ModelAttribute SoaContext context,HttpServletRequest request,String callback) {  
  5.     final long begin  = System.currentTimeMillis();  
  6.     final Enumeration<String> names = request.getParameterNames();  
  7.     while (names.hasMoreElements()) {  
  8.         String key = names.nextElement();  
  9.         if(key.intern() == "method".intern() ||key.intern() == "service".intern()) continue;  
  10.         context.addAttr(key, request.getParameter(key));  
  11.     }  
  12.     context = soaManger.callNoTx(context);  
  13.     SoaLogger.debug(getClass(), "service {} in method {}执行时间{}ms",context.getService(),context.getMethod(), System.currentTimeMillis()-begin);  
  14.               //只要放回Jsonp对象即可  
  15.     return new JSONPObject(callback,context);  
  16. }  

 

客户端代码
Js代码   收藏代码
  1. (function() {  
  2.                 $.ajax({  
  3.                     url: "http://localhost:8080/soa-rest/sys/invoker?service=userService&method=page",  
  4.                     dataType: 'jsonp',  
  5.                     data: '',  
  6.                     jsonp: 'callback',  
  7.                     success: function(result) {  
  8.                             console.log(result);  
  9.                     },  
  10.                     timeout: 3000  
  11.                 });  

 

到此整合完成;
参考文档:http://stackoverflow.com/questions/14333709/spring-mvc-3-2-and-json-objectmapper-issue
完整列子:https://github.com/247687009/soa/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值