SpringMVC中,为我们提供了一个AbstractJsonpResponseBodyAdvice的类用来支持jsonp的数据(SpringBoot接收解析web请求是依赖于SpringMVC实现的)。怎么用AbstractJsonpResponseBodyAdvice来支持跨域请求呢?
package portal.controller;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ControllerAdvice(basePackages = { "controller.test1","controller.test1" })
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback", "jsonp");
}
}
@ControllerAdvice
,控制器增强。除了上面的应用,我们通常会配合@ExceptionHandler注解进行统一的异常处理。
@ControllerAdvice(basePackages = { "controller.test1","controller.test1" })
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleBizExp(HttpServletRequest request, Exception ex){
//异常的处理逻辑;
return null;
}
}
JSONP实现原理:
1、JSONP发出的是Script请求,不是XHR请求,所以浏览器是不会去拦截和校验。
2、普通请求返回是JSON对象,而JSONP返回是一个可执行的JS脚本。
3、前端发出的请求的URL会拼接上callBack(该值是前后端定义好一个标识字符串)后端请求中发现了该参数,就确定这是一个JSONP请求,会把返回参数有JSON包装成JS脚本的形式响应返回。URL前端拼接的callBack参数的值作为函数名,接口返回的JSON作为函数的入参。
Ajax是如何帮助我们发送JSONP请求?
JSONP请求,是Ajax动态创建一个Script标签,<script type="text/javascript" src= "http://zjhtest/api/test?callback=jsonp"> 该类型发出的是script请求,所以浏览器不会去拦截校验(类似于<img src = ""/>标签)。该动态生成的script标签特点:创建完,发送完,销毁掉。
弊端:
1、服务端需要改动来支持JSONP请求(服务提供方是别人就无法改动)
2、只支持GET请求,即使将请求方式指定为POST,发出去的请求也是GET请求。
3、发送的是script请求,而不是XHRHttpRequest请求,XHR请求的相关特性无法使用。