最近項(xiàng)目中引入了SpringBoot恃疯,目的是做到前后端分離開(kāi)發(fā)。但實(shí)際過(guò)程中出現(xiàn)了很多問(wèn)題墨闲,其中比較令人頭疼的就是跨域問(wèn)題今妄。
場(chǎng)景再現(xiàn)
創(chuàng)建SpringBoot項(xiàng)目,引入Web鸳碧、JPA和MySQL
后臺(tái)接口代碼如下:
@RequestMapping(value = "/l", method = RequestMethod.POST)
@ResponseBody
public List<String> add(List<String> list) {
return list;
}
前臺(tái)請(qǐng)求代碼如下:
<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>
前臺(tái)報(bào)錯(cuò)如下:
POST http://localhost:8080/main/l 500 ()
后臺(tái)報(bào)錯(cuò)如下:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface
這里出現(xiàn)的錯(cuò)誤原因是因?yàn)樵诮邮諗?shù)組時(shí)后臺(tái)必須使用@RequestBody注解
后臺(tái)代碼調(diào)整如下:
@RequestMapping(value = "/l", method = RequestMethod.POST)
@ResponseBody
public List<String> add(@RequestBody List<String> list) {
return list;
}
再次請(qǐng)求
前臺(tái)報(bào)錯(cuò)如下:
POST http://localhost:8080/main/l 415 ()
狀態(tài)碼415盾鳞,數(shù)據(jù)類(lèi)型有問(wèn)題。
查看POST的數(shù)據(jù)
可以看到FormData的數(shù)據(jù)全部是undefined
前臺(tái)代碼調(diào)整如下:
<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>
再次請(qǐng)求
前臺(tái)報(bào)錯(cuò)如下:
POST http://localhost:8080/main/l 415 ()
再次查看POST數(shù)據(jù)瞻离,發(fā)現(xiàn)數(shù)據(jù)已經(jīng)正常了
到這里其實(shí)我是懵逼的腾仅,因?yàn)槲艺伊苏粋€(gè)上午的資料,完全不知道事出何因套利。
最后我想到了contentType
于是再次調(diào)整前臺(tái)代碼如下:
<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>
再次請(qǐng)求
前臺(tái)報(bào)錯(cuò)如下:
OPTIONS http://localhost:8080/main/l net::ERR_ABORTED
查看POST數(shù)據(jù)
發(fā)現(xiàn)請(qǐng)求方法變成了Request Method:OPTIONS
然后我又查了好久推励,發(fā)現(xiàn)是跨域的問(wèn)題鹤耍,于是在后臺(tái)添加跨域配置如下:
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);
}
}
再次請(qǐng)求
終于成功了。真是內(nèi)牛滿面
總結(jié)
使用Ajax請(qǐng)求SpringBoot開(kāi)發(fā)的后臺(tái)接口時(shí)一定要注意:
前臺(tái):
1吹艇、一定要添加
contentType: "application/json;charset=UTF-8"
2惰蜜、對(duì)于數(shù)組,一定要使用
JSON.stringify(list)
進(jìn)行字符串格式化
后臺(tái):
1受神、一定要在List<E>數(shù)據(jù)類(lèi)型前面添加@RequestBody注解
2抛猖、一定要進(jìn)行跨域訪問(wèn)配置
最后
還有一點(diǎn)是關(guān)于csrf的,如果遇到此問(wèn)題只需要添加如下配置類(lèi)關(guān)閉該功能即可鼻听。
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();
}
}
喜歡的請(qǐng)關(guān)注哦财著!