前后端分离跨域问题
后端配置跨域过滤器
/** imports **/
/**
* 跨域过滤器 (解决浏览器访问跨域问题)
*
* @author LPxz
* @since 2021/01/14
*/
// @Order里边的数字越小代表越先被该Filter过滤,@WebFilter代表这是个Filter类并把这个类注入到容器中
@Order(1)
@WebFilter(filterName = "oneFilter", urlPatterns = "/*")
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
// 不使用*,自动适配跨域域名,避免携带Cookie时失效
String origin = request.getHeader("Origin");
if (!StringUtils.isEmpty(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
// 自适应所有自定义头
String headers = request.getHeader("Access-Control-Request-Headers");
if (!StringUtils.isEmpty(headers)) {
response.setHeader("Access-Control-Allow-Headers", headers);
response.setHeader("Access-Control-Expose-Headers", headers);
}
// 允许跨域的请求方法类型
response.setHeader("Access-Control-Allow-Methods", "*");
// 预检命令(OPTIONS)缓存时间,单位:秒
response.setHeader("Access-Control-Max-Age", "3600");
// 明确许可客户端发送Cookie,不允许删除字段即可
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
/*
注册过滤器:
@Bean
public FilterRegistrationBean registerFilter() {
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
bean.addUrlPatterns("/*");
bean.setFilter(new CorsFilter());
// 过滤顺序,从小到大依次过滤
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
*/
}
注意还要在启动类中加入注解 @ServletComponentScan
:
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
fetch 方式
在前端修改请求头,然后在后端加上 @CrossOrigin
注解,可直接加在方法上,加在类上对应所有方法。
import React, {Component} from 'react'
class Page1 extends Component{
constructor(props){
super(props);
this.state = {
mytext: []
}
}
getData(){
//修改请求头
let myHeaders = new Headers({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
});
fetch('http://127.0.0.1:8080/hello',{
method:'GET',
headers: myHeaders,
mode: 'cors',
//转或称字符串格式
}).then(res=>res.json()).then(
data=>{
console.log(data);
// eslint-disable-next-line
data.map((key)=>{
this.setState({
mytext: [...this.state.mytext, key]
})
})
}
)
}
//React周期函数,防止死循环,在组建被渲染前调用
componentWillMount(){
this.getData();
}
render() {
return (
<React.Fragment>
<ul>
{
this.state.mytext.map((key, index)=>{
return <li key={index}>{key.name}</li>
})
}
</ul>
</React.Fragment>
)
}
}
export default Page1;
import com.jarvis.springboot_mybatis.Entity.User;
import com.jarvis.springboot_mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import java.util.List;
@Controller
@CrossOrigin
public class MybatisController {
@Autowired
private UserMapper userMapper;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
@ResponseBody
public List<User> hello(){
List<User> user = userMapper.queryUserList();
System.out.println(user);
return user;
}
}
XMLHttrRequest 方式
这种方式在前端不用配置,需要在后端设置请求头,请求的时候需要将 localhost 改成 127.0.0.1,要不然因为不识别会报错,setResponse 需要和 Origin 保持一致(F12)。
true 和 false 那是发不发送 cookie,自行解决。
import React, {Component} from 'react'
class Page2 extends Component{
constructor(props){
super(props)
this.state = {
service: [],
}
}
componentDidMount() {
//ajax方法去服务器取数据,异步true
const xhr = new XMLHttpRequest()
xhr.open("GET", "http://127.0.0.1:8080/Page22", true)
//根据情况选择是否要随get请求发送用于身份认证的信息
xhr.withCredentials = false
xhr.send()
xhr.onreadystatechange = () =>{
/**
* 0 UNSENT- open()尚未被调用
1 OPENED- send()尚未被调用
2 HEADERS_RECEIVED- send()已被调用,并且头和状态可用
3 LOADING下载;- responseText的保持部分数据
4 - 的操作完成
*/
// eslint-disable-next-line
if (xhr.readyState == XMLHttpRequest.DONE) {
// eslint-disable-next-line
if (xhr.status == 200) {
let gotService = JSON.parse(xhr.responseText)
this.setState({
service: gotService
})
}
} else {
console.log(xhr.readyState + "---加载中")
}
}
}
render() {
const serviceShows = this.state.service.map((user, index)=>{
return (
<tr key={index}>
<td>{user.id}</td>
<td>{user.username}</td>
<td>{user.name}</td>
</tr>
)
})
return (
<table>
<tbody>
{serviceShows}
</tbody>
</table>
)
}
}
export default Page2;
import com.jarvis.springboot_mybatis.Entity.User;
import com.jarvis.springboot_mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Controller
@CrossOrigin
public class MybatisController {
@Autowired
private UserMapper userMapper;
@RequestMapping(value = "/Page22", method = RequestMethod.GET)
@ResponseBody
public List<User> helloPage2(HttpServletResponse response){
List<User> user = userMapper.queryUserList();
System.out.println(user);
// response.setHeader("Access-Control-Allow-Credentials","True");
response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:3000");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
return user;
}
}
前后端分离跨域问题
http://lpxz.work/posts/42396/