ServerSocket ss = ...;
while(true){
Socket s = ss.accept(); <-- 계속 받음
.
.
.
}
Socekt s = new Socket(IP, Port); <- 소켓 생성 즉시 server에서 ss.accpet()
.
.
.
s.close();
캡슐화: 복잡한 코드가 안보이도록 클래스 안에 메서드로 감춘다.
해당 기능이 필요한 경우 간단히 메서드 호출로 처리한다.
board.dao.BoardDaoProxy 클래스 추가
board.dao.BoardDaoProxyTest 클래스 추가
BoardDaoProxy class
package com.bitcamp.board.dao;
// BoardDao와 통신을 담당할 대행 객체
// 모든 out은 서버로 보내는 것이다.
public class BoardDaoProxy {
String dataName;
DataInputStream in;
DataOutputStream out;
public BoardDaoProxy(String dataName, DataInputStream in, DataOutputStream out) {
this.dataName = dataName;
this.in = in;
this.out = out;
}
public boolean insert(Board board)throws Exception {
out.writeUTF(dataName);
out.writeUTF("insert");
out.writeUTF(new Gson().toJson(board)); // json을 서버로 보내기
// 서버로부터 요청했던 데이터 읽어오기
return in.readUTF().equals("success");
}
public boolean update(Board board) throws Exception{
out.writeUTF(dataName);
out.writeUTF("update");
out.writeUTF(new Gson().toJson(board));
return in.readUTF().equals("success");
}
public Board findByNo(int boardNo) throws Exception{
out.writeUTF(dataName);
out.writeUTF("findByNo");
out.writeInt(boardNo);
if(in.readUTF().equals("fail")) {
return null;
}
return new Gson().fromJson( in.readUTF(), Board.class);
}
public boolean delete(int boardNo) throws Exception{
out.writeUTF(dataName);
out.writeUTF("delete");
out.writeInt(boardNo);
return in.readUTF().equals("success");
}
public Board[] findAll() throws Exception{
out.writeUTF(dataName);
out.writeUTF("findAll");
if(in.readUTF().equals("fail")) {
return null;
}
return new Gson().fromJson( in.readUTF(), Board[].class);
}
}
package com.bitcamp.board.dao;
public class BoardDaoProxyTest {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("127.0.0.1", 8888);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream())) {
BoardDaoProxy boardDao = new BoardDaoProxy("board", in, out);
// 테스트1) 목록 가져오기
Board[] boards = boardDao.findAll();
for (Board b : boards) {
System.out.println(b);
}
System.out.println("---------------------------------");
// 테스트2) 상세 데이터 가져오기
Board board = boardDao.findByNo(3);
System.out.println(board);
System.out.println("---------------------------------");
// 테스트3) 데이터 등록하기
board = new Board();
board.title = "xxxx";
board.content = "xxxxxxxxxx";
board.viewCount = 11;
board.createdDate = System.currentTimeMillis();
board.writer = "hong";
board.password = "1111";
System.out.println(boardDao.insert(board));
System.out.println("---------------------------------");
// 데이터 등록 확인
boards = boardDao.findAll();
for (Board b : boards) {
System.out.println(b);
}
System.out.println("---------------------------------");
// 테스트4) 데이터 변경하기
board = boardDao.findByNo(3);
board.title = "okokok";
board.content = "nononono";
System.out.println(boardDao.update(board));
System.out.println("---------------------------------");
// 데이터 변경 확인
board = boardDao.findByNo(3);
System.out.println(board);
System.out.println("---------------------------------");
// 테스트5) 데이터 삭제하기
System.out.println(boardDao.delete(3));
System.out.println("---------------------------------");
// 데이터 삭제 확인
boards = boardDao.findAll();
for (Board b : boards) {
System.out.println(b);
}
System.out.println("---------------------------------");
out.writeUTF("exit");
}
}
}
board.dao.BoardDaoProxy 클래스 추가
board.handler.BoardHandler 클래스를 사용한다.
BoardHandler class
*
* 게시글 메뉴 처리 클래스
*/
package com.bitcamp.board.handler;
public class BoardHandler extends AbstractHandler {
private BoardDaoProxy boardDao;
public BoardHandler(String dataName, DataInputStream in, DataOutputStream out) {
// 수퍼 클래스의 생성자를 호출할 때 메뉴 목록을 전달한다.
super(new String[] {"목록", "상세보기", "등록", "삭제", "변경"});
boardDao = new BoardDaoProxy(dataName, in, out);
}
@Override
public void service(int menuNo) {
try {
switch (menuNo) {
case 1: this.onList(); break;
case 2: this.onDetail(); break;
case 3: this.onInput(); break;
case 4: this.onDelete(); break;
case 5: this.onUpdate(); break;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void onList() throws Exception {
Board[] boards = boardDao.findAll();
if (boards == null) {
System.out.println("목록을 가져오는데 실패했습니다!");
return;
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("번호 제목 조회수 작성자 등록일");
for (Board board : boards) {
Date date = new Date(board.createdDate);
String dateStr = formatter.format(date);
System.out.printf("%d\t%s\t%d\t%s\t%s\n",
board.no, board.title, board.viewCount, board.writer, dateStr);
}
}
private void onDetail() throws Exception {
int boardNo = 0;
while (true) {
try {
boardNo = Prompt.inputInt("조회할 게시글 번호? ");
break;
} catch (Exception ex) {
System.out.println("입력 값이 옳지 않습니다!");
}
}
Board board = boardDao.findByNo(boardNo);
if (board == null) {
System.out.println("해당 번호의 게시글이 없습니다!");
return;
}
System.out.printf("번호: %d\n", board.no);
System.out.printf("제목: %s\n", board.title);
System.out.printf("내용: %s\n", board.content);
System.out.printf("조회수: %d\n", board.viewCount);
System.out.printf("작성자: %s\n", board.writer);
Date date = new Date(board.createdDate);
System.out.printf("등록일: %tY-%1$tm-%1$td %1$tH:%1$tM\n", date);
}
private void onInput() throws Exception {
Board board = new Board();
board.title = Prompt.inputString("제목? ");
board.content = Prompt.inputString("내용? ");
board.writer = Prompt.inputString("작성자? ");
board.password = Prompt.inputString("암호? ");
board.viewCount = 0;
board.createdDate = System.currentTimeMillis();
if (boardDao.insert(board)) {
System.out.println("게시글을 등록했습니다.");
} else {
System.out.println("게시글 등록에 실패했습니다!");
}
}
private void onDelete() throws Exception {
int boardNo = 0;
while (true) {
try {
boardNo = Prompt.inputInt("삭제할 게시글 번호? ");
break;
} catch (Exception ex) {
System.out.println("입력 값이 옳지 않습니다!");
}
}
if (boardDao.delete(boardNo)) {
System.out.println("삭제하였습니다.");
} else {
System.out.println("해당 번호의 게시글이 없습니다!");
}
}
private void onUpdate() throws Exception {
int boardNo = 0;
while (true) {
try {
boardNo = Prompt.inputInt("변경할 게시글 번호? ");
break;
} catch (Throwable ex) {
System.out.println("입력 값이 옳지 않습니다!");
}
}
Board board = boardDao.findByNo(boardNo);
if (board == null) {
System.out.println("해당 번호의 게시글이 없습니다!");
return;
}
board.title = Prompt.inputString("제목?(" + board.title + ") ");
board.content = Prompt.inputString(String.format("내용?(%s) ", board.content));
String input = Prompt.inputString("변경하시겠습니까?(y/n) ");
if (input.equals("y")) {
if (boardDao.update(board)) {
System.out.println("변경했습니다.");
} else {
System.out.println("변경 실패입니다!");
}
} else {
System.out.println("변경 취소했습니다.");
}
}
}
implementation project(':app-common') // 폴더 이름
id 'java-library' // app 이 아니라 다른 프로젝트에 의해서 공유 되어짐
// Eclipse IDE에서 사용할 프로젝트 정보 설정하기
eclipse {
project {
name = "board-app-common"
// 프로젝트 이름을 지정하지 않으면 build.gradle 파일이 있는
// 폴더 이름을 프로젝트 이름을 사용한다.
}
...
}
com.bitcamp.board.ServerApp 클래스 변경
이전 ServerApp class
public class ServerApp {
public static void main(String[] args) {
System.out.println("[게시글 데이터 관리 서버]");
try (ServerSocket serverSocket = new ServerSocket(8888);) {
System.out.println("서버 소켓 준비 완료!");
...
while (true) {
try (Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());) {
System.out.println("클라이언트와 연결 되었음!");
while (true) {
// 클라이언트와 서버 사이에 정해진 규칙(protocol)에 따라 데이터를 주고 받는다.
String dataName = in.readUTF();
if (dataName.equals("exit")) {
break;
}
Servlet servlet = servletMap.get(dataName);
if (servlet != null) {
servlet.service(in, out);
} else {
out.writeUTF("fail");
}
}
System.out.println("클라이언트와 연결을 끊었음!");
} // 안쪽 try
}
} catch (Exception e) {
e.printStackTrace();
} // 바깥 쪽 try
System.out.println("서버 종료!");
}
}
public class ServerApp {
public static void main(String[] args) {
System.out.println("[게시글 데이터 관리 서버]");
try (ServerSocket serverSocket = new ServerSocket(8888);) {
System.out.println("서버 소켓 준비 완료!");
...
while (true) {
try (Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());) {
System.out.println("클라이언트와 연결 되었음!");
// 클라이언트와 서버 사이에 정해진 규칙(protocol)에 따라 데이터를 주고 받는다.
String dataName = in.readUTF();
if (dataName.equals("exit")) {
break;
}
Servlet servlet = servletMap.get(dataName);
if (servlet != null) {
servlet.service(in, out);
} else {
out.writeUTF("fail");
}
System.out.println("클라이언트와 연결을 끊었음!");
} // 안쪽 try
}
} catch (Exception e) {
e.printStackTrace();
} // 바깥 쪽 try
System.out.println("서버 종료!");
}
}
package com.bitcamp.board.dao;
// BoardDao와 통신을 담당할 대행 객체
//
public class BoardDaoProxy {
...
public boolean insert(Board board) throws Exception {
try (Socket socket = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());) {
out.writeUTF(dataName);
out.writeUTF("insert");
out.writeUTF(new Gson().toJson(board));
return in.readUTF().equals("success");
}
}
public boolean update(Board board) throws Exception {
try (Socket socket = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());) {
out.writeUTF(dataName);
out.writeUTF("update");
out.writeUTF(new Gson().toJson(board));
return in.readUTF().equals("success");
}
}
public Board findByNo(int boardNo) throws Exception {
try (Socket socket = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());) {
out.writeUTF(dataName);
out.writeUTF("findByNo");
out.writeInt(boardNo);
if (in.readUTF().equals("fail")) {
return null;
}
return new Gson().fromJson(in.readUTF(), Board.class);
}
}
public boolean delete(int boardNo) throws Exception {
try (Socket socket = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());) {
out.writeUTF(dataName);
out.writeUTF("delete");
out.writeInt(boardNo);
return in.readUTF().equals("success");
}
}
public Board[] findAll() throws Exception {
try (Socket socket = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());) {
out.writeUTF(dataName);
out.writeUTF("findAll");
if (in.readUTF().equals("fail")) {
return null;
}
return new Gson().fromJson(in.readUTF(), Board[].class);
}
}
}
게시판 메뉴를 실행하여 목록을 볼 때 작동 순서
DataName: "board"
와 value: new BoardServlet("board")
execute()
를 호출한다.dataName: "board"
와 IP, Port를 넘겨준다.DataInputStream in
과 DataOutputStream Out
을 만든다.dataName: "board"
와 "findAll"
명령어를 Gson을 이용해서 전달한다.accept()
를 통해 Client에서의 socket을 받고, DataInputStream in
과 DataOutputStream Out
을 만든다.dataName: "board"
를 입력받아 in
을 통해 dataName에 맞는 servlet 클래스인 BoardServlet의 service()
를 호출한다.service()
의 파라미터로 in
, out
을 넘겨준다.dataName
을 이용한 json fileName
을 넘겨준다.load()
를 통해 json 파일을 로딩한다.findAll()
메소드를 이용한다.in
을 통해 json 형태로 받아와서 그 결과 데이터 값을 다시 변환하여 Board객체형태로 BoardHandler에게 리턴해준다.+