因为安全因素,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 });
相关推荐
1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析...
SpringMVC4.x案例和配置,配合博客园java web 之 SpringMVC4.x配置的案例程序,包含了SpringMVC4.x的配置和SpringMVC案例
springmvc 和 spring,都是5.0版本,hibernate5.x版本,详细curd,实体反转。
以前都是用SSH,第一次使用spring+springMVC+mybatis自己做的测试练习,主要是配置注解的使用,加了稍微详细的注释说明。另外在测试ehcache的时候也继承进去了,紧做练习参考. 环境:tomcat使用7.x,JDK1.7开发工具...
基于springmvc3.2.x +tomcat8.0 ,使用ajax 发送restful请求处理数据
SpringMVC笔记.pdf
spring5.x+springmvc5.x+mybatis3.5x+tomcat9+jdk8+maven 项目框架2.0版本demo代码,主要用于自用,备份留底,版本后期将持续跟新
使用maven搭建整合这三个框架,导入myeclipse即可测试使用
springMVC 5.x上传下载: 1)隐藏资源方式下载 2)防止盗链下载 3)多文件上传 4)单文件上传 5)混合上传
springMVC整合FastJson实现RestFul风格API 源代码
SpringMVC笔记,记录的比较完整,参考价值较高,大家共同进步
spring5.x+springmvc5.x+mybatis3.5x+tomcat9+jdk8+maven 项目框架demo代码,主要用于自用,备份留底,版本后期将持续跟新
SpringMVC(.html),SpringMVC(.html),SpringMVC(.html)
尚硅谷佟刚SpringMVC 4.X视频教程---对应课件信息
springmvc基础 包含代码+知识点+详细解释 ...4. springmvc和mybatis整合 5. springmvc注解开发 常用的注解学习 参数绑定(简单类型、pojo、集合类型) 自定义参数绑定 6. springmvc和struts2区别
springMVC整合FastJson实现RestFul风格API涉及jar包
用springmvc框架为别人提供一个接口,返回一串json数据。jsonp服务端。需要调用接口代码也可以联系我。idea。
框架springmvc3.2+spring3.2+mybatis3.11整合附带jar包 附带jar包,直接导入myeclipse就能使用
本文件为一个基本的项目配置,包括springmvc的基本配置,数据库连接池(c3p0)、事务管理、缓存、拦截器的配置。部分采用xml配置,部分采用注解。