0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_ro2CN3Fa 来源:CSDN技术社区 作者:远走与梦游 2022-11-09 17:23 次阅读

为什么会有跨域问题

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

常见的跨域解决方式

在控制层加入允许跨域的注解 @CrossOrigin

使用httpclient,不依赖浏览器

使用网关 Gateway

注解:@CrossOrigin

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

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

网关整合

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将会对请求和响应进行修改处理

496f0014-50e9-11ed-a3b6-dac502259ad0.png

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

项目中使用

新建模块service_gateway


 

com.lzq
service_utils
0.0.1-SNAPSHOT


org.springframework.cloud
spring-cloud-starter-gateway

 

com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery


配置文件

#服务端口
server.port=9090

> 基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
>
> * 项目地址:
> * 视频教程

# 服务名
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
publicclassApiGatewayApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(ApiGatewayApplication.class,args);
}
}

修改前端.evn文件,改成访问网关端口号

做集群部署时,他会根据名称实现负载均衡

跨域理解:发送请求后,网关过滤器会进行请求拦截,将跨域放行,转发到服务器中

跨域配置类

@Configuration
publicclassCorsConfig{
@Bean
publicCorsWebFiltercorsFilter(){
CorsConfigurationconfig=newCorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");

UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource(newPathPatternParser());
source.registerCorsConfiguration("/**",config);

returnnewCorsWebFilter(source);
}
}

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

Httpclient

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

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

publicclassHttpTest{
@Test
publicvoidtest1()throwsException{
Stringurl="https://www.badu.com";
URLurl1=newURL(url);
//url连接
URLConnectionurlConnection=url1.openConnection();
HttpURLConnectionhttpURLConnection=(HttpURLConnection)urlConnection;
//获取httpURLConnection输入流
InputStreamis=httpURLConnection.getInputStream();
//转换为字符串
InputStreamReaderreader=newInputStreamReader(is,StandardCharsets.UTF_8);
BufferedReaderbr=newBufferedReader(reader);
Stringline;
//将字符串一行一行读取出来
while((line=br.readLine())!=null){
System.out.println(line);
}
}
}
//设置请求类型
httpURLConnection.setRequestMethod("GET");
//请求包含请求行、空格、请求头、请求体
//设置请求头编码
httpURLConnection.setRequestProperty("Accept-Charset","utf-8");

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

创建HttpClient对象。

创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

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

调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

释放连接。无论执行方法是否成功,都必须释放连接

集成测试,添加依赖


org.apache.httpcomponents
httpclient
4.5.13

@Test
publicvoidtest2(){
//可关闭的httpclient客户端,相当于打开一个浏览器
CloseableHttpClientclient=HttpClients.createDefault();
Stringurl="https://www.baidu.com";
//构造httpGet请求对象
HttpGethttpGet=newHttpGet(url);
//响应
CloseableHttpResponseresponse=null;
try{
response=client.execute(httpGet);
//获取内容
Stringresult=EntityUtils.toString(response.getEntity(),"utf-8");
System.out.println(result);
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭流
if(client!=null){
try{
client.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}

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

系统中

@RequestMapping(value="/hospital/save",method=RequestMethod.POST)
publicStringsaveHospital(Stringdata,HttpServletRequestrequest){
try{
apiService.saveHospital(data);
}catch(YyghExceptione){
returnthis.failurePage(e.getMessage(),request);
}catch(Exceptione){
returnthis.failurePage("数据异常",request);
}
returnthis.successPage(null,request);
}

saveHospital方法

@Override
publicbooleansaveHospital(Stringdata){
JSONObjectjsonObject=JSONObject.parseObject(data);
MapparamMap=newHashMap<>();
paramMap.put("hoscode","10000");
paramMap.put("hosname",jsonObject.getString("hosname"))
//图片
paramMap.put("logoData",jsonObject.getString("logoData"));
//http://localhost:8201/api/hosp/saveHospital
//httpclient
JSONObjectrespone=
HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveHospital");
System.out.println(respone.toJSONString());

if(null!=respone&&200==respone.getIntValue("code")){
returntrue;
}else{
thrownewYyghException(respone.getString("message"),201);
}
}

HttpRequestHelper工具类

/**
*封装同步请求
*@paramparamMap
*@paramurl
*@return
*/
publicstaticJSONObjectsendRequest(MapparamMap,Stringurl){
Stringresult="";
try{
//封装post参数
StringBuilderpostdata=newStringBuilder();
for(Map.Entryparam:paramMap.entrySet()){
postdata.append(param.getKey()).append("=")
.append(param.getValue()).append("&");
}
log.info(String.format("-->发送请求:postdata%1s",postdata));
byte[]reqData=postdata.toString().getBytes("utf-8");
byte[]respdata=HttpUtil.doPost(url,reqData);
result=newString(respdata);
log.info(String.format("-->应答结果:resultdata%1s",result));
}catch(Exceptionex){
ex.printStackTrace();
}
returnJSONObject.parseObject(result);
}

HttpUtil工具类

publicstaticbyte[]send(StringstrUrl,Stringreqmethod,byte[]reqData){
try{
URLurl=newURL(strUrl);
HttpURLConnectionhttpcon=(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)){
OutputStreamos=httpcon.getOutputStream();
os.write(reqData);
os.flush();
os.close();
}
BufferedReaderin=newBufferedReader(newInputStreamReader(httpcon.getInputStream(),"utf-8"));
StringinputLine;
StringBuilderbankXmlBuffer=newStringBuilder();
while((inputLine=in.readLine())!=null){
bankXmlBuffer.append(inputLine);
}
in.close();
httpcon.disconnect();
returnbankXmlBuffer.toString().getBytes();
}catch(Exceptionex){
log.error(ex.toString(),ex);
returnnull;
}
}

对应平台接口

@RestController
@RequestMapping("/api/hosp")
publicclassApiController{
@Autowired
privateHospitalServicehospitalService;
@ApiOperation(value="上传医院")
@PostMapping("saveHospital")
publicRsaveHospital(HttpServletRequestrequest){
//通过request取到前端接口传过来的值
MapparameterMap=request.getParameterMap();
//将数组值转换成一个值
MapparamMap=HttpRequestHelper.switchMap(parameterMap);
//将map集合转成josn字符串
StringmapStr=JSONObject.toJSONString(paramMap);
//josn字符串转成对象
Hospitalhospital=JSONObject.parseObject(mapStr,Hospital.class);
//加入MongoDB中
hospitalService.saveHosp(hospital);
returnR.ok();
}
}

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

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 浏览器
    +关注

    关注

    1

    文章

    1016

    浏览量

    35280
  • spring
    +关注

    关注

    0

    文章

    338

    浏览量

    14311
  • httpclient
    +关注

    关注

    0

    文章

    3

    浏览量

    1854

原文标题:三种跨域解决方案:HttpClient、注解、网关

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    FPGA设计中解决时钟方案

    介绍3时钟处理的方法,这3方法可以说是FPGA界最常用也最实用的方法,这三种方法包含了单bit和多bit数据的
    的头像 发表于 11-21 11:13 3838次阅读
    FPGA设计中解决<b class='flag-5'>跨</b>时钟<b class='flag-5'>域</b>的<b class='flag-5'>三</b>大<b class='flag-5'>方案</b>

    时钟解决方案

    在很久之前便陆续谈过亚稳态,FIFO,复位的设计。本次亦安做一个简单的总结,从宏观上给大家展示时钟解决方案
    的头像 发表于 01-08 09:42 863次阅读
    <b class='flag-5'>跨</b>时钟<b class='flag-5'>域</b>的<b class='flag-5'>解决方案</b>

    如何处理好FPGA设计中时钟问题?

    时钟处理是 FPGA 设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个 FPGA 初学者的必修课。如果是还在校生,时钟
    发表于 09-22 10:24

    探寻FPGA中三种时钟处理方法

    时钟处理是 FPGA 设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个 FPGA 初学者的必修课。如果是还在校生,时钟
    发表于 10-20 09:27

    三种时钟处理的方法

      时钟处理是FPGA设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个FPGA初学者的必修课。如果是还在校生,时钟
    发表于 01-08 16:55

    三种FPGA界最常用的时钟处理法式

    时钟处理是FPGA设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个FPGA初学者的必修课。如果是还在校生,时钟
    发表于 02-21 07:00

    如何处理好FPGA设计中时钟间的数据

    介绍3时钟处理的方法,这3方法可以说是FPGA界最常用也最实用的方法,这三种方法包含了单bit和多bit数据的
    发表于 07-29 06:19

    三种电源方案

    三种电源方案   电源+充电线路方案               &
    发表于 11-13 15:05 1095次阅读

    三种3D眼镜解决方案

    介绍了三种3D眼镜解决方案,MSP430方案,TPS65835方案,射频穿梭3D电视眼镜。
    发表于 09-14 10:23 36次下载
    <b class='flag-5'>三种</b>3D眼镜<b class='flag-5'>解决方案</b>

    三种pads解决方案的对比

    三种解决方案交付核心能力来加速你的设计周期,提高生产率,提高质量。了解每个解决方案当你开始你的比较过程。
    的头像 发表于 10-30 07:06 3437次阅读

    揭秘FPGA时钟处理的大方法

    时钟处理是 FPGA 设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个 FPGA 初学者的必修课。如果是还在校生,时钟
    的头像 发表于 12-05 16:41 1616次阅读

    介绍3方法时钟处理方法

    介绍3时钟处理的方法,这3方法可以说是FPGA界最常用也最实用的方法,这三种方法包含了单bit和多bit数据的
    的头像 发表于 09-18 11:33 2.2w次阅读
    介绍3<b class='flag-5'>种</b>方法<b class='flag-5'>跨</b>时钟<b class='flag-5'>域</b>处理方法

    三种时钟处理的方法

    时钟处理是FPGA设计中经常遇到的问题,而如何处理好时钟间的数据,可以说是每个FPGA初学者的必修课。如果是还在校生,时钟
    的头像 发表于 10-18 09:12 7552次阅读

    刺激能量收集发展的三种解决方案

    新技术星期二:刺激能量收集发展的三种解决方案
    的头像 发表于 12-30 09:40 554次阅读

    菱M70 PLC增加注解三种方法简析

    菱M70 PLC增加注解三种方法
    的头像 发表于 02-26 09:59 1049次阅读
    <b class='flag-5'>三</b>菱M70 PLC增加<b class='flag-5'>注解</b>的<b class='flag-5'>三种</b>方法简析