三种跨域解决方案:HttpClient、注解、网关

  • 注解:@CrossOrigin
  • 网关整合
  • Httpclient

为什么会有跨域问题

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

常见的跨域解决方式

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

注解:@CrossOrigin

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

网关整合

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

(1)路由

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

(2)断言

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

(3)过滤器

一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的 Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理

Spring cloud Gateway发出请求。然后再由Gateway Handler Mapping中找到与请 求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器链将请求发 送到实际的服务执行业务逻辑,然后返回。

项目中使用

新建模块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 {
    @Bean
    public 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去掉

Httpclient

常见的使用场景:多系统之间接口的交互、爬虫

http原生请求,获取百度首页代码

public class HttpTest {
    @Test
    public 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
    //httpclient
    JSONObject 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 {
    @Autowired
    private 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();
    }
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152002.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

穿越时空:未来云计算的奇妙世界

文章目录 1. 云计算与智能家居2. 云计算与无人驾驶3. 云计算与虚拟现实4. 云计算与人工智能未来展望 &#x1f389;欢迎来到云计算技术应用专栏~穿越时空&#xff1a;未来云计算的奇妙世界 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&am…

Android 12 客制化修改初探-Launcher/Settings/Bootanimation

Android 12 使用 Material You 打造的全新系统界面&#xff0c;富有表现力、活力和个性。使用重新设计的微件、AppSearch、游戏模式和新的编解码器扩展您的应用。支持隐私信息中心和大致位置等新的保护功能。使用富媒体内容插入功能、更简便的模糊处理功能、经过改进的原生调试…

Redis分布式锁(上)

不论面试还是实际工作中&#xff0c;Redis都是避无可避的技术点。在我心里&#xff0c;MySQL和Redis是衡量一个程序员是否“小有所成”的两把标尺。如果他能熟练使用MySQL和Redis&#xff0c;以小化大&#xff0c;充分利用现有资源出色地完成当下需求&#xff0c;说明他已经成长…

生命在于学习——主板跳线的学习

一、前言 好吧&#xff0c;又是一个我之前没接触过的东西&#xff0c;秉持遇到什么就学什么的精神&#xff0c;来学&#xff01; 我一发小来找我&#xff0c;问我关于跳线的事情&#xff0c;我就一个表情&#xff1a; 好吧&#xff0c;我承认&#xff0c;纵观我23岁&#xf…

【通往架构师之路】并没有捷径可走,除非站在巨人的肩膀之上

通往架构师之路 市面有流传《人人都是产品经理》&#xff0c;却很少听到《人人都是架构师》这种说法&#xff0c;大概是因为架构师在整个研发体系上来说&#xff0c;总是比较稀缺的吧。本文结合工程的需要&#xff0c;给大家推荐10本通过架构师之路的绝佳图书&#xff0c;希望对…

第二证券:今日投资前瞻:小米汽车引关注 全球风光有望持续高速发展

昨日&#xff0c;两市股指盘中轰动上扬&#xff0c;深成指、创业板指一度涨超1%。到收盘&#xff0c;沪指涨0.55%报3072.83点&#xff0c;深成指涨0.72%报10077.96点&#xff0c;创业板指涨0.53%报2015.36点&#xff0c;北证50指数涨2.64%&#xff1b;两市算计成交9900亿元&…

智慧城市大脑数据中台解决方案:PPT全套37页,附下载

关键词&#xff1a;智慧城市大脑解决方案&#xff0c;数据中台解决方案&#xff0c;智慧城市建设&#xff0c;数据中台建设&#xff0c;智慧城市大脑建设&#xff0c;数据中台建设架构 一、智慧城市大脑数据中台建设背景 智慧城市大脑数据中台是一个面向城市级数据管理、开发和…

PowerConsume功耗计算器

嵌入式低功耗产品开发&#xff0c;功耗计算器资源-CSDN文库 PowerConsume使用说明 安装说明 需要安装在无空格等特殊字符的路径&#xff0c;不推荐安装在C盘。 功能说明 已知条件 电池容量 各状态的电流和运行时间 自动计算出设备运行时间 启动界面如下 添加状态 在空白处…

深入解析Vue中的keep-alive组件:优化组件切换与DOM渲染!

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、K…

超详细 | 萤火虫算法原理及其实现(Matlab)

群智能(Swarm Intelligence&#xff0c;SI)是一类分散自组织系统的集体智能行为的总称&#xff0c;该表述最早在1989年由Gerardo Beni在分子自动机系统中提出。SI系统可视作一组简单的个体&#xff0c;其个体与个体、个体与环境之间存在交互作用&#xff0c;最终表征出智能行为…

通往优秀软件架构师之路:掌握技术核心,修炼基础原理【文中送书,十本任选】

通往优秀软件架构师之路&#xff1a;掌握技术核心&#xff0c;修炼基础原理 《高并发架构实战&#xff1a;从需求分析到系统设计》《架构师的自我修炼&#xff1a;技术、架构和未来》《中台架构与实现&#xff1a;基于DDD和微服务》《分布式系统架构&#xff1a;架构策略与难题…

Python利器:Requests-HTML——网络爬虫的得力助手

概要 在Python的世界里&#xff0c;网络爬虫是一个非常热门的领域。而在这个领域中&#xff0c;Requests-HTML是一个强大的工具&#xff0c;它能够让我们轻松地处理HTML页面&#xff0c;从而获取需要的数据。本文将详细介绍Requests-HTML的特点、使用方法和一些实际应用案例&a…

JS-项目实战-删除库存记录

1、fruit.js function $(name) {if (name) {//假设name是 #fruit_tblif (name.startsWith("#")) {name name.substring(1); //fruit_tblreturn document.getElementById(name);}} }//当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取…

为什么都说学医的转行网络安全行业更容易些?

网络系统坏了&#xff0c;被入侵破坏了&#xff0c;找安全工程师防护修补。如果没有修好&#xff0c;我可以不给钱&#xff0c;再找一家能修好的。但是看病就不一样了&#xff0c;就算医生没有给我治好病&#xff0c;也照样要收医疗费。 这样的类比乍一听上去好像挺有道理&…

Redis集群介绍及安装Redis7.2.3集群

概念&#xff1a; 【Redis】高可用之三&#xff1a;集群&#xff08;cluster&#xff09; - 知乎 实操&#xff1a; Redis集群三种模式 主从模式 优势&#xff1a; 主节点可读可写 从节点只能读&#xff08;从节点从主节点同步数据&#xff09; 缺点&#xff1a; 当主节点…

自动驾驶大模型,是怎么学习「世界知识」的?

近期&#xff0c;科技产业大佬不约而同地发出一个非常强烈的信号&#xff1a;自动驾驶走向完全的成熟&#xff0c;必须要被AI大模型重构。 中国工程院院士、清华大学教授、清华智能产业研究院&#xff08;AIR&#xff09;院长张亚勤认为&#xff0c;「自动驾驶是高度复杂的、最…

2023 年 数维杯(D题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看数维杯D题&#xff01; 问题一&#xff1a;最佳清…

python3.8 安装 ssl 模块 和 _ctypes 模块

这文章目录 前情提要安装 openssl-1.1.1重新编译安装 python3.8-rpath 编译选项介绍python3.8 跟 python3.10 的区别那要怎么解决这个问题呢&#xff0c;我想到有四种解决方案&#xff1a; 前情提要 我在之前给 python3.10 安装 ssl 模块后以为该步骤 “对于 python3.6、pytho…

wpf devexpress 自定义统计

总计统计和分组统计包含预定义总计函数。这些函数允许你计算如下&#xff1a; 数据列的数量&#xff08;Count&#xff09; 最大和最小值(Max和Min) 总计和平均值&#xff08;Sum和Average&#xff09; 处理GridControl.CustomSummary 事件或者使用 GridControl.CustomSumm…

Ubuntu 22.04 LTS ffmpeg mp4 gif 添加图片水印

ffmpeg编译安装6.0.1&#xff0c;参考 Ubuntu 20.04 LTS ffmpeg gif mp4 互转 许编译安装ffmpeg &#xff1b;解决gif转mp4转换后无法播放问题-CSDN博客 准备一个logo MP4添加水印 ffmpeg -i 2.mp4 -vf "movielogo.png[watermark];[in][watermark]overlayx10:y10[out]&…