jsonp
这段代码的目的是实现一个自定义的 JSONP(JSON with Padding)响应体处理器,利用 AbstractJsonpResponseBodyAdvice
中的功能,根据请求参数将 JSON 对象包装成 JSONP 格式,从而支持跨域请求。
代码分析
import org.springframework.http.HttpOutputMessage;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
@ControllerAdvice
public class MyJsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public MyJsonpAdvice() {
// 指定支持的回调参数名称和媒体类型
super("callback", "json");
}
@Override
protected void writeResponseBody(Object responseBody, HttpOutputMessage outputMessage) throws Exception {
// 调用父类的方法以生成 JSONP 格式
super.writeResponseBody(responseBody, outputMessage);
}
}
主要功能
-
@ControllerAdvice
:- 使得这个类可以作为一个全局的控制器建议(Advice),可以对所有被
@RequestMapping
注解标注的方法进行预处理和后处理。
- 使得这个类可以作为一个全局的控制器建议(Advice),可以对所有被
-
构造函数参数:
super("callback", "json")
:"callback"
: 指定请求参数名,表示请求中应该提供一个名为callback
的参数,客户端通过这个参数指定回调函数名称。"json"
: 指定支持的媒体类型,这里表示适用于 JSON 媒体类型的请求。
-
writeResponseBody
方法:- 这个方法被重写以实现自定义的响应体写入逻辑。在这里,它调用父类的实现,即将响应对象封装为 JSONP 格式,形式上是
callbackFunction({"key": "value"})
。
- 这个方法被重写以实现自定义的响应体写入逻辑。在这里,它调用父类的实现,即将响应对象封装为 JSONP 格式,形式上是
拦截的控制器方法示例
这个 JSONP 适配器会拦截所有返回 JSON 格式响应的方法。以下是一些可能触发它的示例控制器方法:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/data")
public MyResponse getData(@RequestParam String param) {
// 假设 MyResponse 是一个 POJO,用于返回 JSON 数据
return new MyResponse(param);
}
}
请求示例
假设上面的 MyController
有一个方法 getData
,客户端可能会发起以下请求以调用 JSONP:
GET /data?callback=myCallbackFunction
处理流程
-
请求到达:
- 当客户机发出上述请求时,Spring MVC 将查找处理此请求的控制器方法(在本例中是
getData
),并调用该方法。
- 当客户机发出上述请求时,Spring MVC 将查找处理此请求的控制器方法(在本例中是
-
JSON 响应处理:
getData
方法返回一个MyResponse
对象,该对象最终会转换为 JSON 格式。
-
进入
MyJsonpAdvice
:- 由于请求中包含
callback
参数,MyJsonpAdvice
被 Spring MVC 的处理链调用。在这里,writeResponseBody
将自动被调用。
- 由于请求中包含
-
JSONP 格式响应:
writeResponseBody
方法将会把返回的 JSON 对象包装成 JSONP 格式。最终的响应形式类似于:
myCallbackFunction({"param": "value"});
-
跨域请求成功:
- 由于将 JSON 数据包装在一个 JavaScript 函数调用中,这种响应可以被浏览器正确处理,从而解决了同源策略限制。
总结
通过实现 MyJsonpAdvice
,您可以使 Spring 应用能够支持 JSONP 格式的响应,从而允许跨域请求。在函数式编程风格的现代 Web 开发中,尽管 JSONP 的使用有所减少(主要由于 CORS 的出现),它仍然是一些场景中的重要技术。