onnnzeoz

api를 다른 서버에서 요청하기 위해

 

1. pom.xml - 서버끼리 통신할 수 있게 해주는 webflux 라이브러리 넣어주기

      <!-- 서버와 서버를 통신할 수 있게 해주는 -->
      <!-- web client(webflux) -->
      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-webflux</artifactId>
      </dependency>

2. index.html

클릭하면 getSend() 함수가 실행된다

이 함수는 ajax함수이고 요청주소가 '/get/send/'+$('#msg').val()이다

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
</head>
<body>	
	<h3>INDEX PAGE</h3>
	<input type="text" id="msg"/>
	<button onclick="getSend()">GET SEND</button>
	<br/><br/>
		<input type="number" id="cnt"/>
	<button onclick="postSend()">POST SEND</button>
	<P><button onclick="fluxTest()">FLUX TEST</button></P>
</body>
<script>
function getSend() {
	$.ajax({
		url:'/get/send/'+$('#msg').val(),
		type:'get',
		data: {},
		dataType: 'json',
		success:function(data){
			console.log(data);
		},
		error:function(e){
			console.log(e);
		}
		
	});
}
//숫자 전송 -> 숫자만큼 리스트를 가져온다
//헤더에 값을 넣어서 보낸다

function postSend() {
	$.ajax({
		url:'/post/send/'+$('#cnt').val(),
		type:'post',
		data: {},
		dataType: 'json',
		beforeSend:function(header){//전송하기 전에 체크 작업같은거 할때 beforesend 이용함
			console.log(header);
			header.setRequestHeader("Authorization","a12345")
		}, 
		success:function(data){
			console.log(data);
			
		},
		error:function(e){
			console.log(e);
		}
		
	});
}

function fluxTest() {
	$.ajax({
		url:'/get/fluxTest',
		type:'get',
		data: {},
		dataType: 'json',
		success:function(data){
			console.log(data);
		},
		error:function(e){
			console.log(e);
		}
		
	});
}

</script>
</html>

2. SendController

 

package kr.co.gudi.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import kr.co.gudi.service.SendService;

@RestController
public class SendController {
	
	Logger logger = LoggerFactory.getLogger(getClass());


	//생성자 주입
	private final SendService service;
	public SendController(SendService service) { //생성자에 넣어줌
		this.service = service;
	}
	
	@GetMapping(value="/get/send/{msg}")
	public HashMap<String, String> send(@PathVariable String msg){
		logger.info("가져온 msg : "+ msg);
		return service.getSend(msg);
	}
	
	@PostMapping(value="/post/send/{cnt}")
	public ArrayList<HashMap<String, Object>> postSend(@PathVariable String cnt, @RequestHeader HashMap<String, String> header){
		logger.info("header : {}",header);
		header.get("authorization");
		return service.postSend(cnt, header.get("authorization"));
		
		
	}
	
	@GetMapping(value="/get/fluxTest")
	public List<HashMap<String, Object>> fluxTest(){
		return service.fluxTest();
	}
}

3. SendService

package kr.co.gudi.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.BodyInserters.FormInserter;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Mono;

@Service
public class SendService {
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
	/*webclient는 spring 5.0부터 지원한다
	 *전에는 외부서버와 통신할 때 HttpConnection을 사용했었음 ->  RestTemplate로 바뀜 -> 지금은 WebClient(=webflux : 비동기라 속도면에서 우월, 순서없이 날라가는게 문제)
	 * webClient는 non-blocking(비동기) 방식을 지원하며, 속도가 빠르다
	 * */

	public HashMap<String, String> getSend(String msg) {
		//1. 전송 URL 설정
		WebClient client = WebClient.create("http://localhost");
		//2. 전송 방식을 선택 (get)		
		//3. 추구할 URL이 있다면 설정(없어도 됨)
        //client로 요청을 보낼때 get방식으로 보낼거고 uri를 추가요청할거고, retrieve는 응답의 body값을 가져올거고
        그렇게 가져온 body는 bodytoMono를 통해 mono로 바꾸는데 데이터타입은 hashMap인거임
		Mono<HashMap> mono = client.get().uri("/return/"+msg)
		.retrieve() //4. 전송(어떻게 보낼 것인지? 무엇을 받을 것이지?)
		.bodyToMono(HashMap.class); //5. 받아올 방식을 설정(형태, 처리방식)
		 HashMap<String, String> resp =  mono.block(); //그렇게 담아온 mono를 blcck을 통해 하나씩 빼냄
         logger.info("resp :{}",resp);
		 
		return resp;
	}

	public ArrayList<HashMap<String, Object>> postSend(String cnt, String key) {
		WebClient client = WebClient.create("http://localhost"); //이 url로 요청을 보내겠다는겁니다
		//post방식으로 보내자
		//get에서는 url에 파라메터를 보냈지만, post에서는 바디에 보내야 한다, 그래서 아래처럼 파라메터를 넣는다
		FormInserter<String> form = BodyInserters.fromFormData("cnt",cnt);
		//BodyInserters: 비동기 방식에서 body를 구성하기 위해서 사용
		//fromFormData: cnt 값을 body에 넣기 위해 사용
		//form.with("name",'kim');//cnt같은걸 여러개 넣고싶을 경우 form.with 사용
		
		Mono<ArrayList> mono = client.post().uri("/listReturn") 
		.header("authorization", key).body(form) //post방식으로 보낼 땐 header와 body가 필요하다
		.retrieve().bodyToMono(ArrayList.class);
		
		//block은 사용이 편리하지만 권고하지 않음(동기방식이라 비효율적, 요청량이 많으면 병목현상 일어나서 다른 방식 써야함)
		 //ArrayList<HashMap<String, Object>> resp =  mono.block();
		//어떻게 할거냐면 비동기로 받아놓고(flux) 줄을 세워서 하나씩(toStream,약간 forEach같은거, 1개짜리 배열이라고 생각) 맨 앞사람부터(findFirst) 가져와(get)
		ArrayList<HashMap<String, Object>> resp = mono.flux().toStream().findFirst().get();
		
		 logger.info("resp : {}",resp);
		
		return resp;
	}

	public List<HashMap<String, Object>> fluxTest() {
		WebClient client = WebClient.create("http://localhost"); //기본 url
		//json형태로 파라메터 보내기(json형태로 보내려면 hashmap 써야함)
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("age", 22);
		params.put("name", "Lee");
		params.put("married", false);
		params.put("scores", new int[] {80,90,100,80,70});
		
		//client를 post방식으로 보내는데 fluxReturn이라는 추가값/ json형태로 보낼 때는 bodyValue를 사용하면된다
		//받을 때는 @RequestBody로 받아야 한다
		//retrieve로 나옴 flux로 값을 받음 Stream으로 줄세우고 근데 arraytlist로도 받는다? collect를 통해 list 형태로 한꺼번에 가져온다
		List<HashMap<String, Object>> list = client.post().uri("fluxReturn").bodyValue(params).retrieve()
				.bodyToFlux(HashMap.class).toStream().collect(Collectors.toList());
		
		
		return list;
	}


}

4. ReceiveController

ArrayList<HashMap<String, Object>>

이런 데이터 타입 스는 이유는

여러 가지 값을 보낼건데 그안에있는 값들이 hashmap타입으로 key,value로 이루어져있기때문

package kr.co.gudi.controller;

import java.util.ArrayList;
import java.util.HashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController //여기에 response body 있는 덕분에 보내준 곳으로 다시 답 보냄
@CrossOrigin(value="*")
public class ReceiveController {

	Logger logger = LoggerFactory.getLogger(getClass());
			
	   @GetMapping(value="/return/{msg}")
	   public HashMap<String, String> getReturn(@PathVariable String msg){
	      logger.info("받은 메시지 : " + msg);
	      HashMap<String, String> result = new HashMap<String, String>();
	      result.put("your_msg", msg);
	      return result;
	   }
	   
	   //cnt로 그만큼 list를 만들어줌, list에 그 key값을 가진 회원 있어? 
	   @PostMapping(value="/listReturn")
	   public ArrayList<HashMap<String, Object>> postReturn(int cnt, 
			   @RequestHeader HashMap<String, String>header){
		   
		   logger.info("receive : "+cnt);
		   logger.info("receive key : "+header.get("authorization"));
		   
		   ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();
		   HashMap<String, Object> map = null;
		   for(int i = 1; i<=cnt; i++) {
			   map = new HashMap<String, Object>();
		         map.put("no", i);
		         map.put("name", "kim");
		         map.put("salary", i*100000000);
		         list.add(map);

		   }
		   
				return list;
		   
	   }
	   
	   @PostMapping(value="/fluxReturn")
	   public ArrayList<HashMap<String, Object>> fluxReturn(
			   @RequestBody HashMap<String, Object>params){
		   
		   logger.info("가져온 params : "+params);
		   
		   ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();
		   HashMap<String, Object> map = null;
		   for(int i = 1; i<=10; i++) {
			   map = new HashMap<String, Object>();
		         map.put("no", i);
		         map.put("name", "kim");
		         map.put("salary", i*100000000);
		         list.add(map);

		   }
		   
				return list;
		   
	   }
}

자세히 써놨으니 다 읽어볼것

'Spring Boot' 카테고리의 다른 글

crawling 크롤링  (0) 2023.06.08
dd  (0) 2023.06.05
WebClient  (0) 2023.05.31
필드 주입과 생성자 주입, rest, @RestController  (0) 2023.05.30
spring boot 스프링부트  (0) 2023.05.25
profile

onnnzeoz

@onnnzeoz

비전공자의 개발 공부 일지입니다 💦 국비 풀스택 과정 수강중