关于跨域问题详解

news/2025/2/22 5:35:01/

关于跨域问题详解

1 为什么会有跨域问题

  因为浏览器的同源政策,就会产生跨域。比如说发送的异步请求是不同的两个源,就比如是不同的两个端口或者不同的两个协议或者不同的域名。由于浏览器为了安全考虑,就会产生一个同源政策,不是同一个地方出来的是不允许进行交互的。

2 常见的跨域解决方案

  跨域的解决方案主要包括以下几种:

  1. 在控制层加入允许跨域的注解@CrossOrigin。
  2. 使用httpclient,不依赖浏览器。
  3. 使用网关Gateway。

2.1 注解:@CrossOrigin

  在控制层加入允许跨域的注解,即可完成一个项目中前后端跨域的问题。

2.2 网关整合

  Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix 、Zuul,其不仅提供统一的路由方式,并且还基于Filter链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等。

2.2.1 路由

  路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配。

2.2.1 断言

  java8中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于http request中的任何信息,比如请求头和参数等。

2.2.3 过滤器

  一个标准的Spring WebFilter。Spring Cloud Gateway中的filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mtNOu9iU-1684916784133)(media/16849132170240/16849149415442.jpg)]
  Spring Cloud Gateway发出请求。然后再由Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器链将请求发送到实际的服务执行业务逻辑,然后返回。

2.2.4 项目中使用

  新建模块service_gateway

<dependencies>
<!-- 公共模块依赖 --><dependency><groupId>com.lzq</groupId><artifactId>service_utils</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- 服务注册 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
</dependencies>

  配置文件

#服务端口
server.port=9090# 服务名
spring.application.name=service-gateway
# nacos服务地址 默认8848
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8888
#使用服务发现路由
spring.cloud.gateway.discovery.locator.enabled=true
#设置路由id
spring.cloud.gateway.routes[0].id=service-hosp
#设置路由的uri  lb负载均衡
spring.cloud.gateway.routes[0].uri=lb://service-hosp
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[0].predicates= Path=/*/hosp/**#设置路由id
spring.cloud.gateway.routes[1].id=service-cmn
#设置路由的uri
spring.cloud.gateway.routes[1].uri=lb://service-cmn
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[1].predicates= Path=/*/cmn/**
#设置路由id
spring.cloud.gateway.routes[2].id=service-hosp
#设置路由的uri
spring.cloud.gateway.routes[2].uri=lb://service-hosp
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[2].predicates= Path=/*/userlogin/**

  创建启动类

@SpringBootApplication
public class ApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(ApiGatewayApplication.class, args);}
}

  修改前端.evn文件,改成访问网关端口号
  做集群部署时,他会根据名称实现负载均衡
  跨域理解:发送请求后,网关过滤器会进行请求拦截,将跨域放行,转发到服务器中
  跨域配置类

@Configuration
public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}

  若之前采用注解跨域,需要将@CrossOrigin去掉

2.3 HttpClient

  常见的使用场景:多系统之间接口的交互、爬虫
  http原生请求,获取百度首页代码

public class HttpTest {@Testpublic void test1() throws Exception {String url = "https://www.badu.com";URL url1 = new URL(url);//url连接URLConnection urlConnection = url1.openConnection();HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;//获取httpURLConnection输入流InputStream is = httpURLConnection.getInputStream();//转换为字符串InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);BufferedReader br = new BufferedReader(reader);String line;//将字符串一行一行读取出来while ((line = br.readLine())!= null){System.out.println(line);}}
}
//设置请求类型
httpURLConnection.setRequestMethod("GET");
//请求包含 请求行、空格、请求头、请求体
//设置请求头编码
httpURLConnection.setRequestProperty("Accept-Charset","utf-8");

  使用HttpClient发送请求、接收响应:

  1. 创建HttpClient对象。
  2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
  3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
  4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
  5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
  6. 释放连接。无论执行方法是否成功,都必须释放连接

  集成测试,添加依赖

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
@Test
public void test2(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient client = HttpClients.createDefault();String url = "https://www.baidu.com";//构造httpGet请求对象HttpGet httpGet = new HttpGet(url);//响应CloseableHttpResponse response = null;try {response = client.execute(httpGet);// 获取内容String result = EntityUtils.toString(response.getEntity(), "utf-8");System.out.println(result);} catch (Exception e) {e.printStackTrace();}finally {//关闭流if (client != null){try {client.close();} catch (IOException e) {e.printStackTrace();}}}
}

  项目中使用,系统调用平台接口保存信息,根据传入josn数据保存信息
  系统中

@RequestMapping(value="/hospital/save",method=RequestMethod.POST)
public String saveHospital(String data, HttpServletRequest request) {try {apiService.saveHospital(data);} catch (YyghException e) {return this.failurePage(e.getMessage(),request);} catch (Exception e) {return this.failurePage("数据异常",request);}return this.successPage(null,request);
}

  saveHospital方法

@Override
public boolean saveHospital(String data) {JSONObject jsonObject = JSONObject.parseObject(data);Map<String, Object> paramMap = new HashMap<>();paramMap.put("hoscode","10000");paramMap.put("hosname",jsonObject.getString("hosname"))//图片paramMap.put("logoData", jsonObject.getString("logoData"));//  http://localhost:8201/api/hosp/saveHospital//httpclientJSONObject respone =HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveHospital");System.out.println(respone.toJSONString());if(null != respone && 200 == respone.getIntValue("code")) {return true;} else {throw new YyghException(respone.getString("message"), 201);}
}

  HttpRequestHelper工具类

/*** 封装同步请求* @param paramMap* @param url* @return*/
public static JSONObject sendRequest(Map<String, Object> paramMap, String url){String result = "";try {//封装post参数StringBuilder postdata = new StringBuilder();for (Map.Entry<String, Object> param : paramMap.entrySet()) {postdata.append(param.getKey()).append("=").append(param.getValue()).append("&");}log.info(String.format("--> 发送请求:post data %1s", postdata));byte[] reqData = postdata.toString().getBytes("utf-8");byte[] respdata = HttpUtil.doPost(url,reqData);result = new String(respdata);log.info(String.format("--> 应答结果:result data %1s", result));} catch (Exception ex) {ex.printStackTrace();}return JSONObject.parseObject(result);
}

  HttpUtil工具类

public static byte[] send(String strUrl, String reqmethod, byte[] reqData) {try {URL url = new URL(strUrl);HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();httpcon.setDoOutput(true);httpcon.setDoInput(true);httpcon.setUseCaches(false);httpcon.setInstanceFollowRedirects(true);httpcon.setConnectTimeout(CONN_TIMEOUT);httpcon.setReadTimeout(READ_TIMEOUT);httpcon.setRequestMethod(reqmethod);httpcon.connect();if (reqmethod.equalsIgnoreCase(POST)) {OutputStream os = httpcon.getOutputStream();os.write(reqData);os.flush();os.close();}BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"utf-8"));String inputLine;StringBuilder bankXmlBuffer = new StringBuilder();while ((inputLine = in.readLine()) != null) {  bankXmlBuffer.append(inputLine);  }  in.close();  httpcon.disconnect();return bankXmlBuffer.toString().getBytes();} catch (Exception ex) {log.error(ex.toString(), ex);return null;}}

  对应平台接口

@RestController
@RequestMapping("/api/hosp")
public class ApiController {@Autowiredprivate HospitalService hospitalService;@ApiOperation(value = "上传医院")@PostMapping("saveHospital")public R saveHospital(HttpServletRequest request) {//通过request取到前端接口传过来的值Map<String, String[]> parameterMap = request.getParameterMap();//将数组值转换成一个值Map<String, Object> paramMap = HttpRequestHelper.switchMap(parameterMap);//将map集合转成josn字符串String mapStr = JSONObject.toJSONString(paramMap);//josn字符串转成对象Hospital hospital = JSONObject.parseObject(mapStr, Hospital.class);//加入MongoDB中hospitalService.saveHosp(hospital);return R.ok();}
}

  即可完成不同系统中的相互调用


http://www.ppmy.cn/news/78119.html

相关文章

分享Java代码中一些常见的炫技代码写法,请各位点赞、收藏

以下是一些常见的例子。请记住&#xff0c;这些写法通常是为了展示技术的巧妙和灵活性&#xff0c;但并不一定适用于所有情况。在实际项目中&#xff0c;可读性和可维护性应始终是首要考虑因素。 流式操作&#xff08;Stream API&#xff09;&#xff1a; List<Integer>…

【源码笔记】print、printf与println

文章目录 导读问题发现printprintlnprintf总结 导读 一直用着的 2020 2020 2020科技版在今天终于再也没办法用科技打开了&#xff0c;虽然用VScode能进行一定的操作&#xff0c;但还是由于被IDEA惯坏了&#xff0c;新建任何东西都得折腾一下。最终&#xff0c;用上了 2023.1 2…

java_配置文件_xml

XML配置文件是什么 做数据交互的媒介,用于传输数据,解决硬编码问题 注意事项: 1.一个xml文件只有一个根节点(可以是任意名字) 2.所有标签都是成对出现 3.标签不能嵌套使用 4.标签里面可以有属性值 示例: <?xml version"1.0" encoding"UTF-8" s…

基于 Bert 论文构建 Question-Answering 模型

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 摘要 本文拜读了提出 Bert 模型的论文&#xff0c;考虑了在 Bert 中算法模型的实现.比较了 Bert 与其他如 Transformer、GPT 等热门 NLP 模型.BERT 在概念上很简单&#xff0c;在经验上也很强大。它推动了 11 项自然语言处理任…

详解知识蒸馏原理和代码

目录 知识蒸馏原理概念技巧举例说明KL 散度及损失 KD训练代码导入包网络架构teacher网络student网络 teacher网络训练定义基本函数训练主函数 student网络训练&#xff08;重点&#xff09;理论部分定义kd的loss定义基本函数训练主函数 绘制结果teacher网络的暗知识softmax_t推…

【多微电网】基于粒子群优化算法的面向配电网的多微电网协调运行与优化(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【iOS】—— iOS中的相关锁

文章目录 自旋锁1.OSSpinLock2.os_unfair_lock3.atomic 互斥锁pthread_mutexsynchronizedobjc_sync_enterobjc_sync_exit注意事项 NSLockNSRecursiveLock信号量条件锁NSConditionNSConditionLock 读写锁总结 锁作为一种非强制的机制&#xff0c;被用来保证线程安全。每一个线程…

CleanMyMac X4.13.5中文版Mac电脑优化软件

CleanMyMac X4.13.5是一款Mac电脑优化软件&#xff0c;旨在提高Mac电脑的性能、稳定性和安全性。它可扫描您的Mac电脑&#xff0c;并删除不需要的文件、清理缓存、卸载不必要的应用程序、优化启动项、检测并删除恶意软件等。此外&#xff0c;它还可以帮助您管理您的文件&#x…