package spring_learning;
import java.io.PrintWriter;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
//API 전용 컨트롤러
//API사용시 @Controller를 사용하는게 아니라 @RestController를 사용
@CrossOrigin(origins="*", allowedHeaders = "*")
@RestController
public class api_controller {
PrintWriter pw = null; //front-end가 값을 가져갈 수 있도록 함
@Resource(name="macbook_member_DTO")
macbook_member_DTO dto;
@Resource(name="user_DAO")
user_DAO dao;
//1차 배열
@GetMapping("/api_data1.do")
public String api_data(HttpServletResponse res) throws Exception{
res.setContentType("text/html;charset=utf-8");
/*
JSONArray : []
JSONObject : {} => 키를 생성
JSONArray 두가지 라이브러리
org.json : put 사용
org.json.simple : add 사용
=> 나머지는 똑같이 사용
*/
/*
//1차 배열 형태 : ["a","b","c","d"]
JSONArray ja = new JSONArray();
ja.put("a");
ja.put("b");
ja.put("c");
ja.put("d");
//api의 출력은 printwriter가 기본! => HttpServletResponse 사용, 언어셋 설정, I/O니까 예외처리
this.pw = res.getWriter();
this.pw.print(ja);
this.pw.close();
*/
/*
//1차 키배열 형태 : {"data":["a","b","c","d"]}
JSONArray ja = new JSONArray();
ja.put("a");
ja.put("b");
ja.put("c");
ja.put("d");
JSONObject jo = new JSONObject();
jo.put("data", ja);
this.pw.print(jo);
this.pw.close();
*/
return null;
}
//2차 배열
@GetMapping("/api_data2.do")
public String api_data2(HttpServletResponse res) throws Exception{
res.setContentType("text/html;charset=utf-8");
this.pw = res.getWriter();
//JSON만들땐 안에거 먼저 만들고 밖에거 만듦
/*
//2차 배열 [ ["홍길동","강감찬"] ] => 중괄호 2개니까 Array 두개
JSONArray ja = new JSONArray();
ja.put("홍길동");
ja.put("강감찬");
JSONArray ja2 = new JSONArray();
ja2.put(ja2);
this.pw.print(ja2);
this.pw.close();
*/
//2차 키배열 : [ {"member":["홍길동","강감찬"]} ]
JSONArray ja = new JSONArray();
ja.put("홍길동");
ja.put("강감찬");
JSONObject jo = new JSONObject();
jo.put("member", ja);
JSONArray ja2 = new JSONArray();
ja.put(jo);
this.pw.print(ja2); //맨 마지막 JSON 객체를 출력
this.pw.close();
//객체들 원래 필드에 올려서 써야함
return null;
}
//배열의 내용을 JSON으로 만들기
@GetMapping("/api_data3.do")
public String api_data3(HttpServletResponse res) throws Exception{
res.setContentType("text/html;charset=utf-8");
this.pw = res.getWriter();
String db[] = {"hong","홍길동","hong@nate.com","서울","01012345678"};
JSONObject jo = new JSONObject();
jo.put("id", db[0]);
jo.put("name", db[1]);
jo.put("email", db[2]);
jo.put("area", db[3]);
jo.put("phone", db[4]);
this.pw.print(jo);
JSONArray ja = new JSONArray();
ja.put(jo);
JSONObject jo2 = new JSONObject();
jo2.put("myinfo", ja);
this.pw.print(jo2);
this.pw.close();
return null;
}
// 응용문제
@GetMapping("/api_data4.do")
//이것이 Spring에서 CORS 해결하는 방식 => 컨트롤러위에 쓰기!!!!(메소드위에 쓰면 그 메소드만 적용됨)
//Spring, Spring-boot 에서의 CORS 해결 코드
@CrossOrigin(origins="*", allowedHeaders = "*")
public String api_data4(HttpServletResponse res) throws Exception {
/*
//아래 두줄 CORS 해결 : BUT 이것은 Servlet 형태 (구닥다리!)
res.addHeader("Access-Control-Allow-Origin", "*"); // 모든 아이피 허용
res.addHeader("Access-Control-Allow-Credentials", "true");
*/
res.setContentType("text/html;charset=utf-8");
this.pw = res.getWriter();
String data[][] = { { "모니터", "키보드", "마우스" }, { "NEW", "BEST", "NEW" } };
int w = 0;
String keyname = ""; //서브키 (안에있는키)
JSONObject alldata = new JSONObject(); //대표키 오브젝트
JSONObject jb = new JSONObject();
while (w < data.length) {
JSONArray ja = new JSONArray(); //데이터 배열[]
for (int f = 0; f < data[w].length; f++) {
ja.put(data[w][f]);
}
// System.out.println(jo);
//데이터
if(w==0){
keyname = "product_name";
}else {
keyname = "product_ico";
}
jb.put(keyname, ja);
// System.out.println(jb);
w++;
}
alldata.put("product",jb); //대표키 생성은 최종 반복문 다음에 코드를 작성
System.out.println(alldata);
this.pw.print(alldata);
this.pw.close();
return null;
}
//MySQL DB에서 가져오기
@GetMapping("/api_data5.do")
public String api_data5(HttpServletResponse res) throws Exception {
res.setContentType("text/html;charset=utf-8");
this.pw = res.getWriter();
/*
//이런 형태로 출력하기
{"member":
[
{"midx":5,"mid":"user05","mname":"Eve","memail":"eve@example.com"},
{"midx":4,"mid":"user04","mname":"Diana","memail":"diana@example.com"},
{"midx":3,"mid":"user03","mname":"Charlie","memail":"charlie@example.com"},
{"midx":2,"mid":"user02","mname":"Bob","memail":"bob@example.com"},
{"midx":1,"mid":"user01","mname":"Alice","memail":"alice@example.com"}
]
}
*/
// 데이터 가져오기
List<macbook_member_DTO> result = this.dao.all_list();
// 반복문 돌리기
int w = 0;
JSONObject alldata = new JSONObject(); //{}
JSONArray datas = new JSONArray(); //[]
JSONObject jo = null; //{}
while (w < result.size()) {
jo = new JSONObject();
jo.put("midx", result.get(w).midx);
jo.put("mid", result.get(w).mid);
jo.put("mname", result.get(w).mname);
jo.put("memail", result.get(w).memail);
datas.put(jo);
w++;
}
alldata.put("member", datas);
this.pw.print(alldata);
this.pw.close();
return null;
}
}
1. JSON API ?
- JSON API: 웹 애플리케이션 데이터 주고받기 위한 표준
- JSON: 가벼운 데이터 교환 형식
- Spring, Spring Boot: JSON API 만들 때 유용함
- JSON으로 데이터를 프론트에서 찍으면 다른사람들이 데이터 크롤링을 못해감 //개발자도구에 아무고토 안뜸 GOOD
2. JSON API 기본 설정 (Spring)
> json 검색 > 자바,심플뜨는데 둘다쓰면 좋고 둘중에 하나써도됨 > 우리는 둘다써봄 >
자바 > https://mvnrepository.com/artifact/org.json/json/20250107
심플 > https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1
> 복사해서 pom.xml에 붙여넣기
만약 프론트가 xml api 쓴다 > https://mvnrepository.com/artifact/xml-apis/xml-apis
<dependency> <!-- JSON IN JAVA (API, .JSON파일) -->
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20250107</version>
</dependency>
<dependency> <!-- JSON SIMPLE (API, .JSON파일) -->
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
- pom.xml: 의존성 추가 필요
3. API 컨트롤러 만들기
package spring_learning;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@RestController
public class ApiController {
@GetMapping("/api/data")
public String getData(HttpServletResponse response) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
// JSON 데이터 생성
JSONObject json = new JSONObject();
json.put("message", "Hello, World!");
pw.print(json.toString());
pw.close();
return null;
}
}
- @RestController: API 컨트롤러임을 선언
- @GetMapping("/api/data"): /api/data 경로로 GET 요청이 들어오면 getData 메서드를 실행
- HttpServletResponse: 클라이언트에게 응답을 보내기 위한 객체
- JSONObject: JSON 객체를 생성하고 데이터를 추가하는 데 사용
- response.setContentType("application/json;charset=utf-8"): 응답의 Content-Type을 JSON으로 설정
4. 다양한 형태의 JSON 데이터 생성하기
JSONArray array = new JSONArray();
array.put("apple");
array.put("banana");
array.put("orange");
JSONObject json = new JSONObject();
json.put("fruits", array);
- 1차원 배열: JSONArray 사용
- 1차원 키배열: JSONObject 사용
JSONArray array1 = new JSONArray();
array1.put("apple");
array1.put("banana");
JSONArray array2 = new JSONArray();
array2.put("orange");
array2.put("grape");
JSONArray array2d = new JSONArray();
array2d.put(array1);
array2d.put(array2);
JSONObject json = new JSONObject();
json.put("fruits", array2d);
- 2차원 배열: JSONArray 중첩 사용
import java.util.List;
// ...
@GetMapping("/api/members")
public String getMembers(HttpServletResponse response) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
List<Member> members = memberDao.getAllMembers(); // 데이터베이스에서 회원 정보 가져오기
JSONArray jsonArray = new JSONArray();
for (Member member : members) {
JSONObject json = new JSONObject();
json.put("id", member.getId());
json.put("name", member.getName());
json.put("email", member.getEmail());
jsonArray.put(json);
}
JSONObject result = new JSONObject();
result.put("members", jsonArray);
pw.print(result.toString());
pw.close();
return null;
}
- 데이터베이스 연동: 데이터베이스 데이터 select 해오기 => JSON 형식으로 변환
5. CORS 설정
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class ApiController {
// ...
}
- @CrossOrigin: CORS 활성화
- 프론트엔드 애플리케이션 다른 도메인에서 API 호출 시 필요
6. View에서 출력
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>개인정보 확인 (API를 이용하여 데이터 출력)</title>
</head>
<body>
아이디 : <div id="mid"></div><br>
이름 : <div id="mname"></div><br>
이메일 : <div id="memail"></div><br>
지역 : <div id="marea"></div><br>
연락처 : <div id="mphone"></div><br>
</body>
<script>
var http, data;
http = new XMLHttpRequest();
http.onreadystatechange = function(){
if(http.readyState==4 && http.status==200){
//this.response 는 백에서 만든 배열이 문자열로 날아옴
//JSON.parse : API에서 받은 문자열을 배열화 시키는 함수
//JSON.parse로 딸깍하면 자동으로 배열로 만들어짐 (이 함수는 자스에서만 쓰임)
console.log(JSON.parse(this.response));
data = JSON.parse(this.response);
view();
}
}
//http://localhost:8080/spring_learning
http.open("GET","./api_data3.do",false);
http.send();
//배열을 받아서 찍기 (인자값 안쓰고 전역변수)
function view(){ //원래 반복문 돌림
document.getElementById("mid").innerText = data["myinfo"][0]["id"];
document.getElementById("mname").innerText = data["myinfo"][0]["name"];
document.getElementById("memail").innerText = data["myinfo"][0]["email"];
document.getElementById("marea").innerText = data["myinfo"][0]["area"];
document.getElementById("mphone").innerText = data["myinfo"][0]["phone"];
}
</script>
</html>
- XMLHttpRequest: API 호출을 위한 객체 생성
- onreadystatechange: API 응답 처리 함수 정의
- http.readyState == 4 && http.status == 200: API 호출 성공 여부 확인
- JSON.parse(this.response): API 응답 문자열을 JSON 객체로 변환
- view(): 변환된 JSON 데이터를 HTML에 표시하는 함수 호출
- http.open("GET", "./api_data3.do", false): API 호출 설정 (GET 방식, 동기 방식)
- http.send(): API 호출 실행
- view() 함수: JSON 데이터를 HTML 요소에 삽입
7. 추가 팁
- Jackson 라이브러리: 객체 JSON 변환 또는 JSON 객체 변환 쉬움
- API 문서화: Swagger 또는 OpenAPI 사용