一、什么是前后端分离架构
1、传统web系统开发网站架构
分成三层架构:
com.xxx.dao:数据库访问层
com.xxx.service:业务逻辑层
com.xxx.controller:控制层(需要控制页面跳转)
2、微服务架构
前后端分离,专业的人做专业的事情。
前端:前端工程师 vue ajax
后端:后端工程师 go java php
前端工程师承接了controller层页面的部分。
二、什么是网站跨域问题
1、网站访问
2、跨域问题,发生在浏览器中安全策略
跨域问题是浏览器的一种安全策略,访问需要遵循同源策略。
发生了跨域的问题:
可以请求到后端,但是无法获取到响应结果。
前端vue地址为:vue.xxx.com
后端接口地址为:api.xxx.com
前端访问后端就不同源了。发送ajax请求的域名,和浏览器的域名不一样,浏览器会有一个保护机制。浏览器发送请求给后端,后端响应结果,浏览器会拦截。
3、同源策略
(1)浏览器访问的地址【协议://ip:端口】
(2)在该页面中访问ajax请求【协议://ip:端口】必须要与我们浏览器所访问的【协议://ip:端口】一致。
(3)如果不一致的话,则会发生跨域问题,浏览器触发保护机制,获取不到该请求的响应结果。
三、什么情况下不会发生跨域问题
1、nginx转发
nginx发现html开头,转发到前端服务器。
nginx发现api开头,转发到后端服务器。
四、跨域有哪些解决方案
解决跨域的问题:
1、使用解决跨域的注解@CrossOrigin,底层就是在响应头中设置允许跨域的参数
2、过滤拦截器aop,nginx、网关在响应头中设置允许跨域的参数
3、使用nginx保证html与ajax接口,同协议、同ip(域名)、同端口
4、Jsonp解决跨域的问题,不能使用post请求,只支持get请求,很少使用
五、@CrossOrigin解决跨域的原理
1、@CrossOrigin底层在响应头中,加上了一个参数
Access-Control-Allow-Origin: *
2、解决跨域问题原理
就是在接口响应头,允许前端跨域访问该接口。
- HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
- response.setHeader("Access-Control-Allow-Origin", "*");
六、自己封装一个@MyCrossOrigin注解
1、注解底层原理实现
aop+反射机制
2、pom文件添加依赖
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-aopartifactId>
- dependency>
3、添加注解类MyCrossOrigin.java
- package com.example.annotation;
-
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface MyCrossOrigin {
-
- }
4、添加注解处理类MyCrossOriginAop.java
- package com.example.annotation;
-
- import javax.servlet.http.HttpServletResponse;
-
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- @Aspect
- @Component
- public class MyCrossOriginAop {
-
- @Before(value = "@annotation(com.example.annotation.MyCrossOrigin)")
- public void before() {
- //如果接口上有加上该注解MyCrossOrigin,自动走前置通知的代码
- System.out.println("----------前置通知----------");
- HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
- response.setHeader("Access-Control-Allow-Origin", "*");
- }
- }
5、在方法上使用@MyCrossOrigin注解
- package com.example.web;
-
- import java.util.HashMap;
-
- import javax.servlet.http.HttpServletResponse;
-
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- import com.example.annotation.MyCrossOrigin;
-
- @RestController
- public class CORSController {
-
- @RequestMapping("/hello2")
- @MyCrossOrigin
- public HashMap
hello2() { - HashMap
result = new HashMap<>(); - result.put("code", "200");
- result.put("msg", "ok");
-
- // HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
- // response.setHeader("Access-Control-Allow-Origin", "*");
-
- return result;
- }
- }
七、项目比较小的前后端分离方案
1、注解@CrossOrigin
2、过滤器—自己拦截每个请求
3、在每个接口中加上Access-Control-Allow-Origin
代码冗余,不推荐
八、项目比较大的前后端分离方案
1、基于nginx
2、基于网关
3、nginx反向代理