跨域问题的产生
因为浏览器的同源政策,就会产生跨域。比如说发送的异步请求是不同的两个源,就比如是不同的的两个端口或者不同的两个协议或者不同的域名。由于浏览器为了安全考虑,就会产生一个同源政策,不是同一个地方出来的是不允许进行交互的。
常见的跨域解决方式
- 在控制层加入允许跨域的注解
@CrossOrigin
- 使用
httpclient
,不依赖浏览器
- 使用网关
Gateway
1、注解:@CrossOrigin
在控制层加入允许跨域的注解,即可完成一个项目中前后端口跨域的问题
2、网关整合
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <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>
|
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| server.port=9090
spring.application.name=service-gateway
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8888
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.routes[0].id=service-hosp
spring.cloud.gateway.routes[0].uri=lb://service-hosp
spring.cloud.gateway.routes[0].predicates= Path=/*/hosp/**
spring.cloud.gateway.routes[1].id=service-cmn
spring.cloud.gateway.routes[1].uri=lb://service-cmn
spring.cloud.gateway.routes[1].predicates= Path=/*/cmn/**
spring.cloud.gateway.routes[2].id=service-hosp
spring.cloud.gateway.routes[2].uri=lb://service-hosp
spring.cloud.gateway.routes[2].predicates= Path=/*/userlogin/**
|
创建启动类
1 2 3 4 5 6
| @SpringBootApplication public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
|
修改前端.evn
文件,改成访问网关端口号
做集群部署时,他会根据名称实现负载均衡
跨域理解:发送请求后,网关过滤器会进行请求拦截,将跨域放行,转发到服务器中
跨域配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @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
去掉
3、Httpclient
常见的使用场景:多系统之间接口的交互、爬虫
http原生请求,获取百度首页代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class HttpTest { @Test public void test1() throws Exception { String url = "https://www.badu.com"; URL url1 = new URL(url); URLConnection urlConnection = url1.openConnection(); HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection; 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
发送请求、接收响应
- 创建
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
对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
- 释放连接。无论执行方法是否成功,都必须释放连接
集成测试,添加依赖
1 2 3 4 5 6 7
| <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @Test public void test2(){ CloseableHttpClient client = HttpClients.createDefault(); String url = "https://www.baidu.com"; 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数据保存信息
系统中
1 2 3 4 5 6 7 8 9 10 11
| @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
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @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")); 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
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public static JSONObject sendRequest(Map<String, Object> paramMap, String url){ String result = ""; try { 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
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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; } }
|
对应平台接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @RestController @RequestMapping("/api/hosp") public class ApiController { @Autowired private HospitalService hospitalService; @ApiOperation(value = "上传医院") @PostMapping("saveHospital") public R saveHospital(HttpServletRequest request) { Map<String, String[]> parameterMap = request.getParameterMap(); Map<String, Object> paramMap = HttpRequestHelper.switchMap(parameterMap); String mapStr = JSONObject.toJSONString(paramMap); Hospital hospital = JSONObject.parseObject(mapStr, Hospital.class); hospitalService.saveHosp(hospital); return R.ok(); } }
|
即可完成不同系统中的相互调用