文章目录
前言
文章主要会对SpringMVC4.1版本提供的AbstractJsonpResponseBodyAdvice类,以及高版本SpringMVC弃用该类后如何继续支持JSONP数据跨域方式
一、SpringBoot跨域请求支持JSONP
项目中有可能会遇到跨域请求,所以需要组装支持跨域请求的JSONP数据,在SpringMVC 4.1版本中为我们提供了AbstractJsonpResponseBodyAdvice 类来支持跨域请求。由于使用JSONP数据方式是不安全的spingboot2.0开始已经不推荐了, Spring 5.07 和4.3.18开始已经弃用AbstractJsonpResponseBodyAdvice,在版本5.1中被完全移除,并且建议使用Cross-Origin方式来支持(文章这里就不展开)。这里主要对于AbstractJsonpResponseBodyAdvice 方式如何使用以及高版本弃用后旧的项目如何继续支持展开。
1.AbstractJsonpResponseBodyAdvice 类支持JSONP
代码如下(示例):
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
import com.alone.jpa.controller.UserController;
//只对UserController生效
@ControllerAdvice(basePackageClasses = {
UserController.class})
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
2. 实现ResponseBodyAdvice 类方式
代码如下(示例):
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alone.jpa.controller.UserController;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.regex.Pattern;
//只对UserController生效
@ControllerAdvice(basePackageClasses = {
UserController.class})
public class Jsonp implements ResponseBodyAdvice {
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) serverHttpRequest).getServletRequest();
HttpServletResponse response = ((ServletServerHttpResponse) serverHttpResponse).getServletResponse();
String value = servletRequest.getParameter("callback");
if (value != null) {
if (this.isValidJsonpQueryParam(value)) {
JSONPObject jsonp = new JSONPObject(value);
String text = JSON.toJSONString(o, new SerializerFeature[0]);
String jsonpText = new StringBuilder(jsonp.getFunction()).append("(").append(text).append(")").toString();
byte[] bytes = jsonpText.getBytes(Charset.forName("UTF-8"));
OutputStream out = null;
try {
out = response.getOutputStream();
out.write(bytes);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return o;
}
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return true;
}
protected boolean isValidJsonpQueryParam(String value) {
return CALLBACK_PARAM_PATTERN.matcher(value).matches();
}
}
2.1.普通请求
请求:
http://localhost:8080/alone-server/user/get?userNumber=1
返回结果:
{
"id":1,"userNumber":1,"nickName":"nick","sex":0,"avatar":null,"mobile":"","email":""}
2.2.跨域请求
请求:
http://localhost:8080/alone-server/user/get?userNumber=1&callback=jsonp_00011100123456789874
返回结果:
jsonp_00011100123456789874({
"email":"","id":1,"mobile":"","nickName":"nick","sex":0,"userNumber":1})