文档章节

121 项目 021 spring mvc jsonp 解决方案汇总

小代码2016
 小代码2016
发布于 2017/03/04 23:26
字数 1061
阅读 16
收藏 0

本文使用代码

nginx.conf

    # manage.myjd.com
    server {
        listen       80;
        server_name  manage.myjd.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;


            proxy_set_header X-Forwarded-Host $host;
          proxy_set_header X-Forwarded-Server $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
          proxy_pass http://127.0.0.1:8081;
          proxy_connect_timeout 600;
          proxy_read_timeout 600;
        }
    }

    # www.myjd.com
    server {
        listen       80;
        server_name  www.myjd.com myjd.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;


            proxy_set_header X-Forwarded-Host $host;
          proxy_set_header X-Forwarded-Server $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
          proxy_pass http://127.0.0.1:8082;
          proxy_connect_timeout 600;
          proxy_read_timeout 600;
        }
    }

manage.myjd.com

这个项目提供了一个 resultful api,mvc的配置和一般的配置没有什么区别,代码如下:

package com.laolang.demo.jsondemo.manage.api;

import com.laolang.demo.jsondemo.manage.domain.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("api/user")
@Controller
public class ApiUserController {

    @RequestMapping(value = "{id}",method = RequestMethod.GET)
    public ResponseEntity<User> findUserById( @PathVariable("id") Long id) {
        try {
            User user = new User();
            user.setId(id);
            user.setUserName("xiaodaima");
            user.setNickName("小代码");
            user.setAge(26);

            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
}

www.myjd.com

这是调用manage.myjd.com的另一个项目,后台代码就不需要写了,只需要写一个前台页面的调用jsonp的js部分即可

    $(function () {
        $.ajax({
            url: "http://manage.myjd.com/api/user/" + 1,
            dataType: "jsonp",
            type: "GET",
            statusCode: {
                200: function (data) {
                    console.log(data);
                }
            }
        });
    });

jsonp 调用问题

如果此时打开www.myjd.com的首页的话,就会出现以下问题:

输入图片说明

打开network发现它返回的还是json数据

输入图片说明

解决方案一

判断是否有callback参数

package com.laolang.demo.jsondemo.manage.api;

import com.google.gson.Gson;
import com.laolang.demo.jsondemo.manage.domain.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("api/user")
@Controller
public class ApiUserController {

    // 由于返回的是一段js脚本,所以此处必须返回 String
    @RequestMapping(value = "{id}",method = RequestMethod.GET)
    public ResponseEntity<String> findUserById( @PathVariable("id") Long id,String callback) {
        try {
            User user = new User();
            user.setId(id);
            user.setUserName("xiaodaima");
            user.setNickName("小代码");
            user.setAge(26);

            Gson gson = new Gson();
            String jsonData = gson.toJson(user);

            // 如果是jsonp调用,则返回 jsonp 数据
            if(StringUtils.isNotEmpty(callback)){
                return ResponseEntity.ok(callback + "(" + jsonData + ");");
            }

            // 返回正常的json数据
            return ResponseEntity.ok(jsonData);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
}

此时在打开前台页面,错误就没了,也返回了正常的jsonp数据

输入图片说明

但是这这种案明显不够完美,还需要自己手动判断

方案二

可参考如下博客

springmvc支持json和jsonp类型数据

Spring MVC 4.1 支持jsonp

此时你需要添加一个类

package com.laolang.demo.jsondemo.manage.bean;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

@ControllerAdvice(basePackages = "com.laolang.demo.jsondemo.manage.api")
public class JsonpSupportAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpSupportAdvice() {
        //参数包含callback的时候 使用jsonp的反馈形式
        super("callback");
    }
}

api service的controller也和之前的一样了

package com.laolang.demo.jsondemo.manage.api;

import com.google.gson.Gson;
import com.laolang.demo.jsondemo.manage.domain.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("api/user")
@Controller
public class ApiUserController {

    // 此时可以直接返回对象,也不需要判断callback参数是否存在
    @RequestMapping(value = "{id}",method = RequestMethod.GET)
    public ResponseEntity<User> findUserById( @PathVariable("id") Long id) {
        try {
            User user = new User();
            user.setId(id);
            user.setUserName("xiaodaima");
            user.setNickName("小代码");
            user.setAge(26);

            Gson gson = new Gson();
            String jsonData = gson.toJson(user);

            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
}

方案三

以上两种方案有一个共同的缺点,那就是只能通过GET获取数据,当然这也是jsonp的缺点。spring 4.2 之后增加了 Cross Origin Resource Sharing 的支持,可以通过GET、POST等方式获取数据。

方案三的具体使用方法可参考:

Spring通过CROS协议解决跨域问题

Ajax跨域问题在SpringMVC中的解决方案总结

Spring MVC 4.2 增加 CORS 支持

从零开始学 Java - Spring MVC 实现跨域资源 CORS 请求

SpringMVC开启CORS支持

需要注意的是,你不仅要升级spring 的版本,还需要升级jackson的版本

示例:

api service 的代码

package com.laolang.demo.jsondemo.manage.api;

import com.google.gson.Gson;
import com.laolang.demo.jsondemo.manage.domain.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("api/user")
@Controller
public class ApiUserController {

    @RequestMapping(value = "{id}",method = {RequestMethod.GET,RequestMethod.POST})
    public ResponseEntity<User> findUserById( @PathVariable("id") Long id) {
        try {
            User user = new User();
            user.setId(id);
            user.setUserName("xiaodaima");
            user.setNickName("小代码");
            user.setAge(26);

            Gson gson = new Gson();
            String jsonData = gson.toJson(user);

            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
}

其实和之前的方案二的代码没有太大的区别,只是增加POST请求的支持

api service 的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		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">


    <context:component-scan base-package="com.laolang.demo.jsondemo.manage.web,com.laolang.demo.jsondemo.manage.api"></context:component-scan>

    <mvc:annotation-driven>

    </mvc:annotation-driven>
    <mvc:cors>
        <mvc:mapping path="/api/**"
                     allowed-origins="*"
                     allowed-methods="POST, GET, OPTIONS, DELETE, PUT"
                     allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
                     allow-credentials="true"/>
    </mvc:cors>


    <bean id="beetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration" init-method="init">

    </bean>
    <bean id="viewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">
        <property name="contentType" value="text/html;charset=UTF-8"/>
    </bean>
</beans>

前台js代码

    $(function () {
        $.ajax({
            url: "http://manage.myjd.com/api/user/" + 1,
            dataType: "json",
            type: "POST",
            success : function(data){
                console.info(data);
                if(data.status == 200){
                    console.log(data);
                }
            }
        });
    });

效果

输入图片说明

© 著作权归作者所有

小代码2016
粉丝 42
博文 328
码字总数 153495
作品 0
安阳
程序员
私信 提问
Spring MVC通过CROS协议解决跨域问题

现在接手学校网络中心的一个项目,根据团队成员的实际情况以及开发需要,老师希望做到前后端完全分离。后台使用java提供restful API 作为核心,前台无论PC或者移动端可以共用一个核心。前期解...

vstaryw
2016/07/18
102
0
搞定所有的跨域请求问题 : jsonp & CORS

原文出处:JavaDoop 网上各种跨域教程,各种实践,各种问答,除了简单的 jsonp 以外,很多说 CORS 的都是行不通的,老是缺那么一两个关键的配置。本文只想解决问题,所有的代码经过亲自实践。...

JavaDoop
2017/11/30
0
0
Spring、Spring Boot与Spring MVC

总论 Spring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等。但他们的基础都是Spring的ioc和aop。ioc提供了依赖注入的容器,aop解决了面向横切面的编程;然后在此二者的基础上...

临江仙卜算子
2018/05/08
0
2
Web Service 那点事儿(4)—— 使用 CXF 开发 REST 服务

现在您已经学会了如何使用 CXF 开发基于 SOAP 的 Web 服务,也领略了 Spring + CXF 这个强大的组合,如果您错过了这精彩的一幕,请回头看看这篇吧: [Web Service 那点事儿(2) —— 使用 ...

黄勇
2014/07/23
0
43
自建配置中心加持需求及解决思路

接上篇:https://my.oschina.net/u/3345762/blog/913605 上周自建的配置中心已推广至7个项目组中,其中已有2个项目应用至其生产环境,迎来了第一批内部客户,在使用的过程中还是出现了很多我...

打破突破
2017/06/17
0
1

没有更多内容

加载失败,请刷新页面

加载更多

Jenkins系列_插件安装及报错处理

进入Jenkins之后我们可以进行插件的安装,插件管理位于以下模块: 发现上面报了一堆错误,是因为插件的依赖没有安装好,那么这一节,就先把这些错误解决掉吧。解决完成后,也就基本会使用插件...

shzwork
今天
2
0
mysql mysql的所有查询语句和聚合函数(整理一下,忘记了可以随时看看)

查询所有字段 select * from 表名; 查询自定字段 select 字段名 from 表名; 查询指定数据 select * from 表名 where 条件; 带关键字IN的查询 select * from 表名 where 条件 [not] in(元素...

edison_kwok
昨天
9
0
解决多线程并行加载缓存问题(利用guava实现)

依赖 com.google.guava:guava:20.0 import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import j......

暗中观察
昨天
3
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
昨天
2
0
组装一台工作游戏两用机

一、配置清单如下: 分类 项目 价格(元) 主板 华硕(ASUS)TUF Z370-PLUS GAMING II 电竞特工 Z370二代 支持9代CPU 1049 CPU 英特尔(Intel) i7 8700K 酷睿六核 盒装CPU处理器 2640 风扇 九...

mbzhong
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部