美文网首页springboot
使用Ajax请求SpringBoot接口引发的跨域惨案

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

作者: Alibct | 来源:发表于2017-11-25 18:10 被阅读112次

    最近项目中引入了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();
        }
    }
    

    喜欢的请关注哦!

    相关文章

      网友评论

        本文标题:使用Ajax请求SpringBoot接口引发的跨域惨案

        本文链接:https://www.haomeiwen.com/subject/mtwcbxtx.html