Step-by-Step
[Spring] 9. 안드로이드 통신 - HttpUrlConnection 본문
안드로이드 스튜디오에서 Spring으로 데이터를 전송한 후 DB에 넣는 작업을 하려한다.
++ Retrofit2로 성공했다! 코드는 없지만 마지막에 간단히 설명하려고 한다
HttpURLConnection
HTTP 통신을 가능하게 해주는 클래스
- Header : 데이터 정보
- Body : 데이터
나는 Class를 만들어서 내부 메소드에 연결 코드를 저장하고.
Activity에서 객체 만들어서 호출하였다.
[Activity 부분 - POST]
Thread th = new Thread(new Runnable() {
@Override
public void run() {
SpringConnection sc = new SpringConnection();
UserDTO userDTO = new UserDTO(UserId,Name,Email,Password);
String Message = sc.HttpConnPOSTUser("Controller에 들어가는 Path", userDTO);
System.out.println(Message);
}
});
th.start();
- Button에 onClickListener를 넣어주어 오버라이드된 Onclick 메소드 안에 넣어주었다
- Thread를 생성하여 안에서 실행되며, HttpConnPOSTUser은 메소드 이름이며 인자도 내가 설정한 파라미터대로 넣어준다
[POST]
public String HttpConnUser(String path, UserDTO userDTO) {
// private static final 써서 전역 필드값으로 설정하기
String HOST = "http://IP주소:포트번호";
public String HttpConnPOSTUser(String path, UserDTO userDTO) {
String result = "";
try {
String URL = HOST + path; // 최종 URL 설정
URL urls = new URL(URL); // URL 객체 만들때, 생성자 인자로 URL 넣어주기
HttpURLConnection conn = (HttpURLConnection) urls.openConnection();
StringBuilder sb = new StringBuilder();
if (conn != null) {
conn.setConnectTimeout(10000); // 서버에 연결되는 TIMEOUT 설정
conn.setRequestMethod("POST"); // HTTP 통신 방식 설정
conn.setRequestProperty("Content-Type", "application/json"); // 보낼 타입
conn.setUseCaches(false);
conn.setDoOutput(true); // POST로 데이터 넘겨줄때 사용
conn.setDoInput(true); // InputStream으로 서버 응답 받음
JSONObject jsonObject = new JSONObject(); // 보낼 데이터 JSONObject에 담기
jsonObject.put("userId", userDTO.getUserId());
jsonObject.put("name", userDTO.getName());
jsonObject.put("email", userDTO.getEmail());
jsonObject.put("password", userDTO.getPassword());
OutputStream os = conn.getOutputStream(); //RequestBody에 Data 담기
os.write(jsonObject.toString().getBytes()); //Data 세팅
os.flush(); // RequestBody에 Data 입력
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { //연결 성공시
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[1024];
int nLength;
while ((nLength = is.read(byteBuffer, 0, byteBuffer.length)) != -1) {
baos.write(byteBuffer, 0, nLength);
}
byte[] byteData = baos.toByteArray();
JSONObject responseJSON = new JSONObject(new String(byteData));
// 필요한 정보 추출
result = responseJSON.get("Name").toString();
result = responseJSON.get("Message").toString();
}
// 연결 끊기
conn.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
[Activity부분 - GET]
Thread th = new Thread(new Runnable() {
@Override
public void run() {
SpringConnection sc = new SpringConnection();
String query = "?userId="+UserId; //쿼리 만들어줌
String Message = sc.HttpConnGETUser("Controller path값"+query);
System.out.println(Message);
}
});
th.start();
- 여기는 POST는 body에 담을 값도 넣어줬는데 여긴 그냥 쿼리로 만들어서 넣어줌
[GET]
public String HttpConnGETUser(String path) {
String result = "";
try {
String URLs = HOST + path;
URL urls = new URL(URLs);
HttpURLConnection conn = (HttpURLConnection) urls.openConnection();
StringBuilder sb = new StringBuilder();
if (conn != null) {
conn.setConnectTimeout(10000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// GET은 Body에 담을 내용이 없어서 setOutput은 따로 설정 안함
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[1024];
int nLength;
while ((nLength = is.read(byteBuffer, 0, byteBuffer.length)) != -1) {
baos.write(byteBuffer, 0, nLength);
}
byte[] byteData = baos.toByteArray();
JSONObject responseJSON = new JSONObject(new String(byteData));
result = responseJSON.get("Message").toString();
}
conn.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
++ 이런식으로 먼저 설정해 놓고, 팀원이 코딩하고 있는 안드로이드 코드 git clone해서 적용하려고 했는데,,
안드로이드는 렉이 엄~~~~청 심하고...ㅠㅠㅠㅠ 에뮬레이터는 작동도 하지 않고...흑흑
사실 이 부분은 내가 따로 새로운 프로젝트를 만들어서 해본 것이었다.
사실상 Java이니만큼 객체지향의 장점을 살리려면 retrofit으로 작성하는게 맞다!
Retrofit2로 최근에 성공했기 때문에 간략하게 말하면
1) @Body 형식으로 보내는 것은 직렬화 해서 보내지기 때문에 Spring에서 @RequestBody로 안읽혔다
- @Field를 이용하여 key - value 형식으로 보내고
- Spring에서는 @RequestBody 어노테이션을 제거하여 받았더니 성공하였다!
2) GET 방식은 Spring으로 받을 때 @RequestParam("key값")을 사용하였다
3) Spring으로 데이터를 보낼때는 key값을 소문자로 보내자
- 자꾸 null값이 들어오길래 구글링 해봤는데
- Spring 은 JSON 데이터를 매핑하기 위한 Message Converter 로 Jackson 을 사용하고
- 내가 받는 DTO 부분을 lombok을 이용하면 이상한 제약이 생기게 된다 (아래 블로그 참조)
https://bcp0109.tistory.com/309
- 이부분은 중요하니 두고두고 봐야겠다!!!!!!!!!!!
4) 응답 메세지는 String으로 전해줬다
- org.json.simple의 JSONObject를 사용하면 응답 메세지가 잘 전달 되지 않았다
- gson을 이용한 JsonObject를 이용하였다 (위의 JSONObject랑 다름 . 철자가 같아서 검색하기 힘들었다ㅠㅠ)
Gson gson = new Gson();
JsonObject resultJSON = new JsonObject();
resultJSON.addProperty("message", "This ID is available.");
return gson.toJson(resultJSON);
이런식으로 JsonObject에 값을 넣고 gson.toJson을 이용하여 return 하였는데, 해당 값의 타입은 String이다 ★
암튼 retrofit2은 성공하기만 하면 짱이다
HttpUrlConnection은 연결은 정말 잘 되었지만, 코드가 너무 길다..
하지만 여러 데이터타입으로 주고받아도 에러가 거의 나지 않았다 그건 좋았음!
'프로젝트 > Eggo (Mobile App)' 카테고리의 다른 글
[Spring] 11. Android - Spring - DB - Python 데이터 주고받기 (0) | 2022.05.21 |
---|---|
[Spring] 10. DB에 이미지 저장 - BLOB (+ Python에서 열기) (0) | 2022.05.21 |
[Spring] 8. 날씨 API 받아오기 (0) | 2022.05.19 |
[Spring] 7. 비밀번호 인코딩 & SMTP로 임시 비밀번호 전송 (0) | 2022.05.18 |
[Spring] 6. 응답표준 (1) (0) | 2022.04.29 |