1. ajax跨域的是利用了动态加载js文件没有跨域限制的特性。
2. 服务端返回jsonp格式的文本:xx({weather:"晴天",temp:"30C",:wind:"东南风"});
这本质上是一个函数调用语句,实参为json对象,函数名为xx。
3. 客户端:利用jquery插件:jquery.jsonp-2.4.0.js
代码:
<script type="text/javascript">
function xx(data)
{ alert(data); if(data) { var weatherStr = "今日天气: "; weatherStr += data.weather + " "; weatherStr += data.temp + " "; weatherStr += data.wind + "<br/>"; alert(weatherStr); document.getElementById("weather_zone").innerHTML = weatherStr; } } function getCurrentDayWeather() { var currentDayWeatherUrl = "";$.jsonp({url: 'http://localhost:9090/httpapi/service/weather/detail/101190501.json?callback=xx'});
} </script>
4. 服务端RestEasy的使用:
@Component("weatherService")
@Transactional@Path("weather")public class WeatherService{ @Autowired private WeatherDao weatherDao = null; public Weather queryById(String id) { Weather weather = weatherDao.get(id); return weather; } @GET @Path("/detail/{cityCode}.json") @Produces("application/json") public Weather getCurrentDayWeather(@PathParam("cityCode") String cityCode) { Weather weather = weatherDao.get(DateTimeUtil.getCurrentDay() + "_" + cityCode); if (null == weather || StringUtils.isEmpty(weather.getWeather())) { Weather emptyWeather = new Weather(); emptyWeather.setWeatherId(DateTimeUtil.getCurrentDay() + "_" + cityCode); emptyWeather.setWeather("暂无实况"); emptyWeather.setTemp("暂无实况"); emptyWeather.setWind("暂无实况"); return emptyWeather; } return weather; }这个Rest接口只能返回 json,不能返回jsonp。
RestEasy官方文档的21.2小结有几句话,基本是一句带过:
21.2. JSONP Support
If you're use Jackson is supported right away. If the media type of the response is json and a callback query parameter is given, the response will be a javascript snippet with a method call of the method defined by the callback parameter. For example:
GET /resources/stuff?callback=processStuffResponse
will produce this response:
processStuffResponse()
This supports the default behavior of .
You can change the name of the callback parameter by setting the callbackQueryParameter property.
我用了Jackson ,可是总返回不了jsonp,老是返回json。
后来google到了老外的帖子(),
发现可能是我的RestEasy版本低的问题,我的是2.3.3,说高版本的支持的,我懒得换高版本,于是把那个帖子中老外DIY的代码拿来用了:
思路是自己建个Filter,Wrap HttpServletRequest和HttpSerletResponse,自己把返回的json转成jsonp。
代码如下:
I make draft workaround for this problem. Try it. This solution takes data via http get parameters and translate to virtual POST request. JQuery: function call(){ var val ='{"routes":[{"arrivalAddress":{"fullAddress":"DME"},"destinationAddress":{"fullAddress":"SVO"}}],"carsCount":"1"}';var jHandler ="doMap";$.getJSON("http://xxx:yyy/app-0.0.0.1/rest/requestPrice?callback="+ jHandler +"&json="+ encodeURIComponent(val)+"&jsoncallback=?",null,null,"json");}function doMap(obj){ alert(obj);} Declaration in Service interface @POST @Path("requestPrice") @Produces("application/json") @Consumes("application/json") PriceResponse requestPrice(PriceRequest request)throwsServiceException; Filter class: import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;import java.io.*;import java.util.Enumeration;import java.util.HashMap;import java.util.Iterator;import java.util.Map;publicclassJSONPRequestFilterimplementsFilter{ privateString callbackParameter;publicvoid doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throwsIOException,ServletException{ if(!(request instanceofHttpServletRequest)){ thrownewServletException("This filter can "+" only process HttpServletRequest requests");}finalHttpServletRequest httpRequest =(HttpServletRequest) request;finalHttpServletResponse httpResponse =(HttpServletResponse) response;if(isJSONPRequest(httpRequest)){ RequestWrapper requestWrapper =newRequestWrapper(httpRequest); requestWrapper.setContentType("application/json; charset=UTF-8"); requestWrapper.setHeader("cache-control","no-cache"); requestWrapper.setHeader("accept","application/json"); requestWrapper.setCharacterEncoding("UTF-8"); requestWrapper.setBody(httpRequest.getParameter("json"));finalByteArrayOutputStream baos =newByteArrayOutputStream();HttpServletResponseWrapper responseWrapper =newHttpServletResponseWrapper(httpResponse){ @OverridepublicServletOutputStream getOutputStream()throwsIOException{ returnnewServletOutputStream(){ @Overridepublicvoid write(int b)throwsIOException{ baos.write(b);}};}@OverridepublicPrintWriter getWriter()throwsIOException{ returnnewPrintWriter(baos);}publicString getData(){ return baos.toString();}}; chain.doFilter(requestWrapper, responseWrapper); response.getOutputStream().write((getCallbackParameter(httpRequest)+"(").getBytes()); response.getOutputStream().write(baos.toByteArray()); response.getOutputStream().write(");".getBytes()); response.setContentType("text/javascript");}else{ chain.doFilter(request, response);}}privateString getCallbackMethod(HttpServletRequest httpRequest){ return httpRequest.getParameter(callbackParameter);}privateboolean isJSONPRequest(HttpServletRequest httpRequest){ String callbackMethod = getCallbackMethod(httpRequest);return(callbackMethod !=null&& callbackMethod.length()>0);}privateString getCallbackParameter(HttpServletRequest request){ return request.getParameter(callbackParameter);}publicvoid init(FilterConfig filterConfig)throwsServletException{ callbackParameter = filterConfig.getInitParameter("callbackParameter");}publicvoid destroy(){ }void printRequest(HttpServletRequest request)throwsIOException{ { System.out.println("--------------Headers---------------");Enumeration en = request.getHeaderNames();while(en.hasMoreElements()){ String val = en.nextElement().toString();System.out.println(val +" :");Enumeration en1 = request.getHeaders(val);while(en1.hasMoreElements()){ System.out.println("\t"+ en1.nextElement());}}}{ System.out.println("------------Parameters--------------");Enumeration en = request.getParameterNames();while(en.hasMoreElements()){ String val = en.nextElement().toString();System.out.println(val +" :");String[] en1 = request.getParameterValues(val);for(String val1 : en1){ System.out.println("\t"+ val1);}}}System.out.println("---------------BODY--------------");BufferedReader is = request.getReader();String line;while((line = is.readLine())!=null){ System.out.println(line);}System.out.println("---------------------------------");System.out.println("ContentType: "+ request.getContentType());System.out.println("ContentLength: "+ request.getContentLength());System.out.println("characterEncodings: "+ request.getCharacterEncoding());System.out.println("AuthType: "+ request.getAuthType());System.out.println("ContextPath: "+ request.getContextPath());System.out.println("Method: "+ request.getMethod());}publicstaticclassRequestWrapperextendsHttpServletRequestWrapper{ Map web.xml
| |||
|
1 | An enhancement to support JSONP is scheduled to be released in RESTEasy 2.3.6 Final/3.0-beta-4 (). I was able to "backport" it my project which uses RESTEasy 2.3.5 by simply copying . RESTEasy automatically picks up the new provider based on the annotation. It works automatically by wrapping your results in a js callback once it sees a query parameter named "callback" in the url. This is compatible with what JQuery sends to the server for JSONP requests. |