springboot

使用Ajax请求SpringBoot接口引发的跨域惨案

2017-11-25  本文已影响112人  Alibct

最近项目中引入了SpringBoot,目的是做到前后端分离开发。但实际过程中出现了很多问题,其中比较令人头疼的就是跨域问题。

场景再现

创建SpringBoot项目,引入Web、JPA和MySQL

后台接口代码如下:

@RequestMapping(value = "/l", method = RequestMethod.POST)
@ResponseBody
public List<String> add(List<String> list) {
    return list;
}

前台请求代码如下:

<script type="text/javascript">

    var list = [];
    list.push("我");
    list.push("是");
    list.push("大");
    list.push("帅");
    list.push("逼");

    postList(list);

    function postList(list) {
        $.ajax({
            type: "post",
            url: "http://localhost:8080/main/l",
            data: list,
            success: function (list) {
                console.log(list);
            },
            error: function (msg) {
                console.log(msg);
            }
        });
    }
</script>

前台报错如下:

POST http://localhost:8080/main/l 500 ()

后台报错如下:

org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface

这里出现的错误原因是因为在接收数组时后台必须使用@RequestBody注解

后台代码调整如下:

@RequestMapping(value = "/l", method = RequestMethod.POST)
@ResponseBody
public List<String> add(@RequestBody List<String> list) {
    return list;
}

再次请求

前台报错如下:

POST http://localhost:8080/main/l 415 ()

状态码415,数据类型有问题。

查看POST的数据

image.png

可以看到FormData的数据全部是undefined

前台代码调整如下:

<script type="text/javascript">

    var list = [];
    list.push("我");
    list.push("是");
    list.push("大");
    list.push("帅");
    list.push("逼");

    postList(list);

    function postList(list) {
        $.ajax({
            type: "post",
            url: "http://localhost:8080/main/l",
            data: JSON.stringify(list),
            success: function (list) {
                console.log(list);
            },
            error: function (msg) {
                console.log(msg);
            }
        });
    }
</script>

再次请求

前台报错如下:

POST http://localhost:8080/main/l 415 ()
image.png

再次查看POST数据,发现数据已经正常了

到这里其实我是懵逼的,因为我找了整整一个上午的资料,完全不知道事出何因。

最后我想到了contentType

于是再次调整前台代码如下:

<script type="text/javascript">

    var list = [];
    list.push("我");
    list.push("是");
    list.push("大");
    list.push("帅");
    list.push("逼");

    postList(list);

    function postList(list) {
        $.ajax({
            type: "post",
            url: "http://localhost:8080/main/l",
            contentType: "application/json;charset=UTF-8",
            data: JSON.stringify(list),
            success: function (list) {
                console.log(list);
            },
            error: function (msg) {
                console.log(msg);
            }
        });
    }
</script>

再次请求

前台报错如下:

OPTIONS http://localhost:8080/main/l net::ERR_ABORTED

查看POST数据

image.png

发现请求方法变成了Request Method:OPTIONS

然后我又查了好久,发现是跨域的问题,于是在后台添加跨域配置如下:

package com.semi.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1
        corsConfiguration.addAllowedHeader("*"); // 2
        corsConfiguration.addAllowedMethod("*"); // 3
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }
}

再次请求


image.png image.png

终于成功了。真是内牛满面

总结

使用Ajax请求SpringBoot开发的后台接口时一定要注意:
前台:
1、一定要添加

contentType: "application/json;charset=UTF-8"

2、对于数组,一定要使用

JSON.stringify(list)

进行字符串格式化

后台:
1、一定要在List<E>数据类型前面添加@RequestBody注解
2、一定要进行跨域访问配置

最后

还有一点是关于csrf的,如果遇到此问题只需要添加如下配置类关闭该功能即可。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

喜欢的请关注哦!

上一篇下一篇

猜你喜欢

热点阅读