作为学习JSONP的一部分,我正在进行如下的ajax调用:
var jsonp_url = "http://localhost:8080/test/ad";
$.getJSON(jsonp_url, function(data) {
$('#example-widget-container').html(data.html);
});
当我点击http://localhost:8080/test/ad时,它会返回:
? ( {'html': '<strong>Hello World!</strong>' } )
返回的Spring代码是:
@RequestMapping(method = RequestMethod.GET, value = "ad")
public void getAd(HttpServletResponse response){
PrintWriter out = null;
response.setContentType("text/javascript");
try {
out = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
}
out.write("? ( {'html': '<strong>Hello World!</strong>' } )");
}
执行时,我希望 Hello World!显示在<div id="example-widget-container"></div>
中,但不是,因为回调没有发生。
我错过了什么?
答案 0 :(得分:2)
$。getJSON除了正确的JSON fomat和callme({'html':'hello world'})不是json格式
正确的json格式是 {'html':'hello world'}
答案 1 :(得分:1)
你不想只想return "{'html': 'hello world' }";
吗?
答案 2 :(得分:1)
如果您要返回JSONP,请不要获取JSON ...试试这个
$.get("http://localhost:8080/test/ad", function(data) {
alert(data.html);
}, 'jsonp');
答案 3 :(得分:0)
callme函数在做什么?如果你要返回“callme({'html':'hello world'})”;然后在你的js代码警报中不会提醒“Hellow world”。你需要有data(),即运行callme函数
答案 4 :(得分:0)
我发现很多人对使用JSON的JSONP感到困惑。所以我分享了我认为正确的答案:
爪哇
@RequestMapping(method = RequestMethod.GET, value = "ad")
public void getAd(HttpServletRequest request, HttpServletResponse response){
ServletOutputStream out;
try {
out = response.getOutputStream();
response.setContentType("text/javascript; charset=utf-8");
out.println(request.getParameter("callback")+" ( {'html': '<strong>Hello World!</strong>' } )");
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
的Javascript
var jsonp_url = "http://localhost:8080/AppName/ad?callback=?";
$.getJSON(jsonp_url, function(data) {
$('#example-widget-container').html(data.html);
});
答案 5 :(得分:0)
使用Spring 3.0及更高版本实际上非常简单。在查看上面的示例时,我很困惑为什么要将spring控制器视为普通servlet并直接打印到响应流。这应该避免。只使用返回表示JSON数组的POJO并让JSON解析器创建响应,你会好得多。
第一个任务是让Spring返回JSON。通过将@ResponseBody添加到控制器可以轻松处理,告诉控制器将POJO序列化到客户端。如果您的类路径中有Jackson,则会使用使用mvc:annotation-driven启用的MappingJacksonHttpMessageConverter自动将其作为JSON发送。
但是JSON还不够。您需要JSON-P,假设客户端想要在跨域方案中使用JSON。这可以通过许多不同的方式实现。您可以使用Spring的DelegatingFilterProxy实现servlet过滤器。过滤器可以确定是否正在请求JSON-P,您可以相应地调整响应。
因此,对于我的用途,我更喜欢扩展Spring 3.0(+)MappingJacksonJsonView而不是过滤器,并检查请求参数是否包含“回调”键。如果我想要JSON或JSONP,我可以简单地向* .jsonp添加第二个servlet映射,并根据回调参数的存在发送JSON或JSONP。
以下是代码:
将以下内容放入您的控制器中:
@RequestMapping(value="/ad", method=RequestMethod.GET)
public ModelMap getAvailabilityModel(@RequestParam(required = false) String callback) {
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("html", "<strong>Hello World!</strong>");
return modelMap;
}
返回ModelMap甚至ModelAndView允许我根据servlet映射做不同的事情。
以下是处理JSON-P扩展的自定义视图(仅限guts,为简洁起见省略了一些覆盖):
public class MappingJacksonJsonpView extends MappingJacksonJsonView {
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if("GET".equals(request.getMethod().toUpperCase())) {
Map<String, String[]> params = request.getParameterMap();
if(params.containsKey("callback")) {
String callbackName = params.get("callback")[0];
response.getOutputStream().write(new String(callbackName + "(").getBytes());
log.info("GETTER Found for a .jsonp method, callback name is : " + callbackName);
super.render(model, request, response);
response.getOutputStream().write(new String(");").getBytes());
response.setContentType("application/javascript");
}
else {
super.render(model, request, response);
}
}
else {
super.render(model, request, response);
}
}
}
如果请求被映射到* .jsonp并且我看到一个带有“callback”作为键的请求参数,我假设JSON-P并且我在响应流的顶部用回调信息包装JSON。我会让Jackson JSON处理器处理在所有情况下将POJO转换为适当的JSON的细节。在我的控制器中,我只返回一个POJO或一个ModelMap;没有搞乱在响应中编写我自己的JSON。或者,我可以使用模型和视图返回类型。这将允许正确处理* .do vs * .json请求。使用Firebug确保您在响应头中获得正确的媒体类型,JSON的application / json和JSON-P的application / javascript。
这是JSON-P的输出,在http://localhost:8080/jsonpex/ad.jsonp?callback=xyz上有一个GET(注意带有xyz的包装器,用于JQuery吗?)
xyz({"html":"<strong>Hello World!</strong>"});
如果您取消请求参数,它将只返回JSON:http://localhost:8080/jsonpex/ad.jsonp
{"html":"<strong>Hello World!</strong>"}
最后,请确保正确连接新视图:
<!-- Add our new View to the Application Context -->
<beans:bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<beans:property name="order" value="1" />
<beans:property name="favorPathExtension" value="true"/>
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="json" value="application/json"/>
<beans:entry key="jsonp" value="application/javascript"/>
</beans:map>
</beans:property>
<beans:property name="defaultViews">
<beans:list>
<beans:bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<beans:bean class="com.yourpackagename.spring.web.servlet.view.jsonp.MappingJacksonJsonpView"/>
</beans:list>
</beans:property>
</beans:bean>
一些注意事项,我会尽量避免发回所有额外的HTML并尽可能地减少最小化,从而在要返回的数据之上完成工作的关键。我做了很多研究并尝试了很多方法;上面这个对我来说效果最好。我建议以下作为替代和额外的阅读,因为它们是导致我这个最终解决方案的原因(我不记得所有这些都很遗憾或者我会给予更多信任):
http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/
和过滤器解决方案:
旅行