面试官:项目中如何解决跨域问题(HttpClient、注解、网关)

news2024/12/27 16:14:09

为什么会有跨域问题

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

常见的跨域解决方式

  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框 架中的ServerWebExchangeSpring Cloud Gateway中的断言函数允许开发者去定义匹配来自 于http request中的任何信息,比如请求头和参数等。

(3)过滤器

一个标准的Spring webFilterSpring cloud gateway中的filter分为两种类型的 Filter,分别是Gateway FilterGlobal 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. 如果需要发送请求参数,可调用HttpGetHttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

  4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse

  5. 调用HttpResponsegetAllHeaders()getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponsegetEntity()方法可获取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();
    }
}

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kafka安装及配置过程

kafka安装及配置过程 kafka 依赖于 zookeeper&#xff0c;zookeeper的安装可看&#xff1a;ZooKeeper的安装和配置过程 先说明一下&#xff0c;集群主机分别是&#xff1a;192.168.127.129&#xff0c;192.168.127.130&#xff0c;192.168.127.131 安装 kafka可以通过官网下…

Polardb 如何替换MYSQL 之 IMCI 列式(2)系统的核心与关键

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群。 本期继续上…

如何docker安装es和kibana以及ik分词器

推荐用portainer进行可视化 1.创建网络--让es和kibana容器互联 docker network create es-net 2.部署单点es docker run -d \ --name es \ -e "ES_JAVA_OPTS-Xms512m -Xmx512m" \ -e "discovery.typesingle-node" \ -v es-data:/usr/sha…

Java垃圾回收机制

Java垃圾回收机制 垃圾回收算法为什么垃圾回收回收哪些内存如何回收Marking-Sweep&#xff08;标记-清除法&#xff09;Marking-Compat&#xff08;标记-整理法&#xff09; 内存分代年轻代 Minor gc和Major gc的区别常见回收器Serial Garbage CollectorParallel Garbage Colle…

InnoDB的表空间

独立表空间结构 区概念 连续的64个页就是一个区&#xff0c;也就是说一个区默认用1MB空间大小。表空间由若干个连续的区&#xff08;物理位置上的连续&#xff09;组成的&#xff0c;256的区被划分成一组。 其中&#xff0c;extent0~extent256个区算是第一组&#xff0c;exten…

基于微信小程序的家政服务预约系统的设计与实现

基于微信小程序的家政预约系统,有效解决了人们网上随时预约家政服务的问题。依托于新的小程序开发环境,解决了"跨系统开发"这个难题,在一个"类操作底层"开发基于微信小程序的家政服务应用。功能模块包括:家政服务项目展示模块,服务报价模块,用户留言评价模…

零门槛,手把手教你玩转ChatGPT,顺滑般国内使用chatGPT

国内是可以玩ChatGPT的&#xff0c;只需要去官网注册一个OpenAI帐号&#xff0c;然后使用第三方接码平台获取短信验证码&#xff0c;就可以成功注册帐号&#xff0c;注册成功之后国内就可以随意使用chatGPT啦。 国内怎么玩chatGPT如下&#xff1a; 官方原版 一、注册OpenAI账…

ansible——编写循环和条件任务

环境&#xff1a;RH294 1. 以student用户的身份并使用student作为密码登录workstation ssh studentworkstation 在workstation上&#xff0c;运行lab control-flow start命令&#xff0c;此命令会创建control-flow工作目录 lab control-flow start 2. 切换到/home/studen…

Python中PIL库的常用用法示例

Python中的PIL&#xff08;Python Imaging Library&#xff0c;已更名为Pillow&#xff09;是一个功能强大的图像处理库。以下是一些常用的PIL功能及相应的代码示例&#xff1a; 1. 打开和保存图像&#xff1a; from PIL import Image# 打开图像 image Image.open("exam…

B+G双轮驱动,税友股份迎来数字化东风

配图来自Canva可画 不知不觉之间&#xff0c;国内的数字经济已经蔚然成潮。据相关部门的统计数据显示&#xff0c;去年国内数字经济规模已经达到了50万亿&#xff0c;占到了国内GDP总量的40%以上&#xff0c;增速更是持续领先于GDP增速。与此同时&#xff0c;随着数字中国战略…

权限提升:网站漏洞(提权思路.)

权限提升&#xff1a;网站漏洞 权限提升简称提权&#xff0c;由于操作系统都是多用户操作系统&#xff0c;用户之间都有权限控制&#xff0c;比如通过 Web 漏洞拿到的是 Web 进程的权限&#xff0c;往往 Web 服务都是以一个权限很低的账号启动的&#xff0c;因此通过 Webshell …

The Foundry Modo 16 for Mac v16.1v3 含历史版本

The Foundry MODO是一个功能强大的3D建模、动画和渲染软件&#xff0c;被广泛应用于游戏开发、电影制作、产品设计和建筑可视化等领域。 以下是一些MODO的优点&#xff1a; 1. 强大的建模工具&#xff1a;MODO提供了一系列丰富的建模工具&#xff0c;包括多边形建模、NURBS建…

mysql索引失效的坑

目录 前言 博客文章分享 对索引字段做函数操作 隐式类型转换 隐式字符编码转换 原因分析 解决方法&#xff1a; 前言 在MySQL中&#xff0c;有时候会因为语句使用不当导致sql不走索引&#xff0c;从而使数据库的压力变大。本篇分享一下sql不走索引的坑&#xff0c;让大家…

Nginx 和Rewrite

系列文章目录 文章目录 系列文章目录一、常规的nginx正则表达式1.location和rewrite的区别2.常用的nginx的正则表达式3.nginx里面的优先级 二、rewrite1.Rewrite2.实验 总结 一、常规的nginx正则表达式 1.location和rewrite的区别 从功能看 rewrite 和 location 似乎有点像&a…

GPT-2隐私泄露论文阅读:Extracting Training Data from Large Language Models

文章目录 论文地址:原文阐释&#xff1a;渔樵问对&#xff1a;原理梗概预防策略隐私策略这个新颖的攻击方式是什么&#xff1f;三种典型采样策略&#xff1a;隐私风险文章第5页第二段中提到的 memorized training exam ple 是什么意思 ThreatModel &Ethics什么是文本的zlib…

【Apache 网页与安全优化】

1.网页压缩 检查是否安装 mod_deflate 模块 apachectl -t -D DUMP_MODULES | grep "deflate"如果没有安装mod_deflate 模块&#xff0c;重新编译安装 Apache 添加 mod_deflate 模块 systemctl stop httpd.service cd /usr/local/httpd/conf mv httpd.conf httpd.c…

数字硬件建模SystemVerilog-通信总线建模 --Interface端口的概念

来到了SV最后一部分&#xff0c;预计三篇文章&#xff0c;两周更完&#xff0c;所有的思维导图如下&#xff1a; 概述 SystemVerilog Interface是modport的一种&#xff0c;但比简单的输入、输出或输入输出端口的功能更多。在其最简单的形式中&#xff0c;Interface端口将相关的…

关于户外旋转LED显示屏的核心技术

户外旋转LED显示屏因可视范围达360的新颖结构&#xff0c;并且成本低廉&#xff0c;而得到了迅速的发展。虽然看着外观与普通LED显示屏没有什么大的异样&#xff0c;但为使设计的户外旋转LED显示屏具有较好的显示效果&#xff0c;背后也是需要通过众多工程技术人员克服技术难点…

git lfs简易使用教程

参考资料&#xff1a; https://zzz.buzz/zh/2016/04/19/the-guide-to-git-lfs/ 这篇随笔简单记录一下git lfs的使用教程&#xff0c;只记录最为常用的部分&#xff0c;并阐述原理&#xff0c;方便后面查阅。 首先说明一下git lfs的原理&#xff0c;看名称&#xff1a;git lfs。…

电力监控系统在智能建筑电气节能中的应用

摘要&#xff1a;电力监控系统在智能建筑中被广泛使用&#xff0c;其以及时、稳定、安全、便捷的优点提高了电能使用效率&#xff0c;节约了成本。借助电力监控系统能准确判断故障发生原因和位置&#xff0c;为智能建筑的安全性和智能化发展提供了有力的支持 关键词&#xff1…