本文介绍了春季休息和Jsonp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让我的Spring休息控制器返回 jsonp ,但我没有快乐

I am trying to get my Spring rest controller to return jsonp but I am having no joy

完全相同的代码可以正常工作我想返回json但是我要求返回 jsonp
我已经在转换器中添加了我找到了在线执行jsonp转换的源代码

The exact same code works ok if I want to return json but I have a requirement to return jsonpI have added in a converter I found source code for online for performing the jsonp conversion

我使用的是Spring版本4.1.1.RELEASE和Java 7

I am using Spring version 4.1.1.RELEASE and Java 7

非常感谢任何帮助

以下是有问题的代码

mvc-dispatcher-servlet.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">


  <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
       <property name="favorPathExtension" value="false" />
       <property name="favorParameter" value="true" />
       <property name="parameterName" value="mediaType" />
       <property name="ignoreAcceptHeader" value="false"/>
       <property name="useJaf" value="false"/>
       <property name="defaultContentType" value="application/json" />

       <property name="mediaTypes">
            <map>
                <entry key="atom"  value="application/atom+xml" />
                <entry key="html"  value="text/html" />
                <entry key="jsonp" value="application/javascript" />
                <entry key="json"  value="application/json" />
                <entry key="xml"   value="application/xml"/>
            </map>
        </property>
  </bean>

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="contentNegotiationManager" ref="contentNegotiationManager" />
        <property name="viewResolvers">
            <list>
                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
                <bean
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/templates/slim/${views.template.directory}/" />
                    <property name="suffix" value=".jsp" />
                </bean>
            </list>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="com.webapp.handler.MappingJacksonJsonpView" />
            </list>
        </property>
    </bean>

</beans>

com.webapp.handler.MappingJacksonJsonpView

package com.webapp.handler;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

public class MappingJacksonJsonpView extends MappingJackson2JsonView {
    /** Local log variable. **/
    private static final Logger LOG = LoggerFactory.getLogger(MappingJacksonJsonpView.class);

    /**
     * Default content type. Overridable as bean property.
     */
    public static final String DEFAULT_CONTENT_TYPE = "application/javascript";

    @Override
    public String getContentType() {
        return DEFAULT_CONTENT_TYPE;
    }

    /**
     * Prepares the view given the specified model, merging it with static
     * attributes and a RequestContext attribute, if necessary.
     * Delegates to renderMergedOutputModel for the actual rendering.
     * @see #renderMergedOutputModel
     */
    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        LOG.info("Entered render Method :{}", request.getMethod());

        if("GET".equals(request.getMethod().toUpperCase())) {
            LOG.info("Request Method is a GET call");

            Map<String, String[]> params = request.getParameterMap();

            if(params.containsKey("callback")) {
                String callbackParam = params.get("callback")[0];
                LOG.info("callbackParam:{}", callbackParam);
                response.getOutputStream().write(new String(callbackParam + "(").getBytes());
                super.render(model, request, response);
                response.getOutputStream().write(new String(");").getBytes());
                response.setContentType(DEFAULT_CONTENT_TYPE);
            }
            else {
                LOG.info("Callback Param not contained in request");
                super.render(model, request, response);
            }
        }

        else {
            LOG.info("Request Method is NOT a GET call");
            super.render(model, request, response);
        }
    }
}

控制器方法输入问题

 @RequestMapping(value = { "/sources"}, method = RequestMethod.GET,
        produces={MediaType.ALL_VALUE,
        "text/javascript",
        "application/javascript",
        "application/ecmascript",
        "application/x-ecmascript",
        "application/x-javascript",
        MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public Object getSources(@PathVariable(value = API_KEY) String apiKey,
        @RequestParam(value = "searchTerm", required = true) String searchTerm,
        @RequestParam(value = "callBack", required = false) String callBack) {
    LOG.info("Entered getSources - searchTerm:{}, callBack:{} ", searchTerm, callBack);

    List<SearchVO> searchVOList = myServices.findSources(searchTerm);

    if (CollectionUtils.isEmpty(searchVOList)) {
        LOG.error("No results exist for the searchterm of {}", searchTerm);
        return searchVOList;
    }

    LOG.debug("{} result(s) exist for the searchterm of {}", searchVOList.size(), searchTerm);

    LOG.info("Exiting getSources");
    return searchVOList;
}

** Jquery Ajax代码**

**Jquery Ajax Code **

$.ajax({
                type: "GET",
                url: "http://localhost:8080/my-web/rest/sources,
                data: {
                    "searchTerm": request.term
                },
                //contentType: "application/json; charset=utf-8",
                //dataType: "json",
                contentType: "application/javascript",
                dataType: "jsonp",
                 success: function(data) {
                    alert("success");
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert("Failure");
                }
            });

我得到的错误堆栈跟踪的片段如下:

A snippet of the error stacktrace that I get is as follows

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:168) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:198) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:na]


推荐答案

正如spring.io :

As stated on the spring.io blog regarding the Spring 4.1 release:



@ControllerAdvice
private static class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        super("callback");
    }

}



采取Javadoc来自:

Javadoc taken from MappingJackson2JsonView:

你不需要实现这个你自己的东西。只需重用Spring Framework中的位。

You don't need to implement this stuff by yourself. Just reuse the bits from the Spring Framework.

以下简单的Spring Boot应用程序演示了如何使用在Spring MVC 4.1中构建JSONP支持。
示例至少需要Spring Boot 1.2.0.RC1。

Following simple Spring Boot application demonstrates use of build in JSONP support in Spring MVC 4.1.Example requires at least Spring Boot 1.2.0.RC1.

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

import java.util.Collections;

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RestController
@SpringBootApplication
class Application {

    @JsonAutoDetect(fieldVisibility = ANY)
    static class MyBean {
        String attr = "demo";
    }

    @ControllerAdvice
    static class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
        public JsonpAdvice() {
            super("callback");
        }
    }

    @Bean
    public HttpMessageConverters customConverters() {
        return new HttpMessageConverters(false, Collections.<HttpMessageConverter<?> >singleton(new MappingJackson2HttpMessageConverter()));
    }

    @RequestMapping
    MyBean demo() {
        return new MyBean();
    }

    @RequestMapping(produces = APPLICATION_JSON_VALUE)
    String demo2() {
        return "demo2";
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

URL http:// localhost:8080 / demo?callback = test 将POJO转换为 JSONP 响应:

URL http://localhost:8080/demo?callback=test converts a POJO into a JSONP response:

test({"attr":"demo"});

URL http:// localhost:8080 / demo2?callback = test String 转换为 JSONP 回复:

URL http://localhost:8080/demo2?callback=test converts a String into a JSONP response:

test("demo2");

这篇关于春季休息和Jsonp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 07:52