JSONP 与 Spring 3.0 和 Jackson

发布于 2024-12-08 11:50:42 字数 247 浏览 0 评论 0原文

要使用 Spring 3.0 返回 JSON 响应,只需在 @Controller 内添加 @ResponseBody 注释以及 @RequestMapping 即可。如果加载了 MapppingJacksonJson 库并且客户端使用 application/json 发送 Accept 标头,它将起作用。

JSONP 怎么样?是否可以退货以及如何退货?

To return a JSON response with Spring 3.0 is enough to add a @ResponseBody annotation along with the @RequestMapping inside a @Controller. Provided that MapppingJacksonJson library is loaded and that the client sends Accept header with application/json, it will work.

What about JSONP? Is it possible to return it and how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苹果你个爱泡泡 2024-12-15 11:50:42

这篇博文展示了一个正确且紧凑的解决方案:Implementing JSONP in Spring MVC 3.0.x

这个对于 Spring 3.1 效果更好:Spring 3.1 中的 XML、JSON、JSON-P Web 服务端点

对于 Spring 3.2,这是一个基于 Jackson2 的 JSONP 转换器:

import java.io.IOException;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;

public class MappingJackson2JsonpHttpMessageConverter
    extends MappingJackson2HttpMessageConverter {

    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {
        JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
        JsonGenerator jsonGenerator = this.getObjectMapper().getFactory().createJsonGenerator(outputMessage.getBody(), encoding);        

        try {
            String jsonPadding = "callback";            

            // If the callback doesn't provide, use the default callback
            if (object instanceof IJsonpObject) {
                String jsonCallback = ((IJsonpObject)object).getJsonCallback();
                if (jsonCallback != null) {
                    jsonPadding = jsonCallback;
                }
            }            

            jsonGenerator.writeRaw(jsonPadding);
            jsonGenerator.writeRaw('(');
            this.getObjectMapper().writeValue(jsonGenerator, object);
            jsonGenerator.writeRaw(");");
            jsonGenerator.flush();
        } catch (JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }
}

要添加它,请将此 bean 放入您的配置中:

import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.google.common.collect.Lists;

public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters( List<HttpMessageConverter<?>> converters ) {
        MappingJackson2JsonpHttpMessageConverter converter = new MappingJackson2JsonpHttpMessageConverter();

        converter.setSupportedMediaTypes( Lists.newArrayList(
            new MediaType( "application", "x-javascript" ),
            new MediaType( "application", "javascript" ),
            new MediaType( "text", "javascript" )
        ) );

        converters.add( converter );
    }

}

This blog post shows a correct and compact solution: Implementing JSONP in Spring MVC 3.0.x

This one works better for Spring 3.1: XML, JSON, JSON-P Web Service Endpoints in Spring 3.1

For Spring 3.2, here is a Jackson2 based JSONP converter:

import java.io.IOException;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;

public class MappingJackson2JsonpHttpMessageConverter
    extends MappingJackson2HttpMessageConverter {

    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {
        JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
        JsonGenerator jsonGenerator = this.getObjectMapper().getFactory().createJsonGenerator(outputMessage.getBody(), encoding);        

        try {
            String jsonPadding = "callback";            

            // If the callback doesn't provide, use the default callback
            if (object instanceof IJsonpObject) {
                String jsonCallback = ((IJsonpObject)object).getJsonCallback();
                if (jsonCallback != null) {
                    jsonPadding = jsonCallback;
                }
            }            

            jsonGenerator.writeRaw(jsonPadding);
            jsonGenerator.writeRaw('(');
            this.getObjectMapper().writeValue(jsonGenerator, object);
            jsonGenerator.writeRaw(");");
            jsonGenerator.flush();
        } catch (JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }
}

To add it, put this bean in your configuration:

import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.google.common.collect.Lists;

public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters( List<HttpMessageConverter<?>> converters ) {
        MappingJackson2JsonpHttpMessageConverter converter = new MappingJackson2JsonpHttpMessageConverter();

        converter.setSupportedMediaTypes( Lists.newArrayList(
            new MediaType( "application", "x-javascript" ),
            new MediaType( "application", "javascript" ),
            new MediaType( "text", "javascript" )
        ) );

        converters.add( converter );
    }

}
森林迷了鹿 2024-12-15 11:50:42

Spring 4.1 开始,您可以通过以下方式轻松做到这一点:

@RestController
public class MyController {
    @RequestMapping("/endpoint")
    MappingJacksonValue getData(@RequestParam String callback) {
        MappingJacksonValue value = new MappingJacksonValue(new MyPojo());
        value.setJsonpFunction(callback);
        return value;
    }
}

Since Spring 4.1 you can easy do it this way:

@RestController
public class MyController {
    @RequestMapping("/endpoint")
    MappingJacksonValue getData(@RequestParam String callback) {
        MappingJacksonValue value = new MappingJacksonValue(new MyPojo());
        value.setJsonpFunction(callback);
        return value;
    }
}
╭ゆ眷念 2024-12-15 11:50:42

我一直在寻找一种更简单的 OOB 方法来实现 JSONP 方法(JSONP/CORS 应该是内置的 IMO...不需要任何自定义代码)...从未找到任何...但在与 Spring 团队联系后,它事实证明,JSONP 现在通过 MappingJacksonJsonView 在 4.0.5 中支持 OOB和稍后将介绍内置支持CORS。

I was looking for a simpler, OOB approach for JSONP approach (JSONP/CORS should be built-in IMO...not require any custom code)...never found any...but after reaching out with the Spring team, it turns out that JSONP is now supported OOB in 4.0.5 via MappingJacksonJsonView and built-in supportCORS to follow later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文