Spring

국비코딩 Mar13 | Datainputstream, ObjectoutputStream, 역직렬화, 코드리뷰

onnnzeoz 2023. 3. 13. 17:30

Datainputstream

데이터 타입 그 자체를 읽거나 쓸 수 있는 보조 스트림 

stream만으로는 java의 데이터타입인 boolean, double, String 등을 전송할 수 없음

 

이전까지는 static을 이용해서 데이터를 쓰고읽고했는데 이건 서버를 끄면 사라짐

이젠 파일시스템으로 저장할거임 -> 사라지지않음

 

ObjectoutputStream

data로는 모든 type을 보내기는 무리가 있다

그래서 사용한게 object를 다룰 수 있는 보조스트림

여기에는 객체, 배열, 컬렉션 등 다양한 데이터 형태가 들어 갈 수 있다

 

class의 경우는 직렬화를 하지않으면 전달되지 않

오른쪽은 역직렬화라고 부름

 


여기서 회원가입("/join')을 누르면
이런 창이 뜸, 이 정보들을 파일에 저장할거

- controller

@WebServlet(urlPatterns = {"/login","/join"})
public class MemberController extends HttpServlet {

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		
		String uri = req.getRequestURI();
		String ctx = req.getContextPath();
		String addr = uri.substring(ctx.length());		
		req.setCharacterEncoding("UTF-8");
		MemberModel model = new MemberModel();		
		String msg = "";
		
		if(addr.equals("/join")) {
			HashMap<String, String> param = new HashMap<String, String>();
			param.put("id", req.getParameter("id"));
			param.put("pw", req.getParameter("pw"));
			param.put("name", req.getParameter("name"));
			param.put("age", req.getParameter("age"));
			param.put("gender", req.getParameter("gender"));
			param.put("email", req.getParameter("email"));
			System.out.println(param);
			msg = model.join(param);
		}
		if(addr.equals("/login")) {
			String id = req.getParameter("id");
			String pw = req.getParameter("pw");
			System.out.println(id+"/"+pw);
			msg = model.login(id, pw);
		}
		
		req.setAttribute("msg", msg);
		RequestDispatcher dis = req.getRequestDispatcher("index.jsp");
		dis.forward(req, resp);

	}	

}

요청할 서버가 여러 개니까 uri와 contextpath 이용해서 주소구해줌

여기서는 switch가 아니라 if문을 사용했는데 login과 join에서 둘 다 id와 pw라는 이름을 사용해야해서임

만약 주소가 "/join"과 같다면 파라메터들을 가져올건데, 이 값들을 hashmap에 넣어서 깔끔하게 유연하게 정리해줘

key값과 value값 두 개를 가져와야 하니까 hashmap을 사용할거임, 사용하기 위해 객체화를 해줬고 데이터 타입으로는 string과 string. 변수 이름은 param이라고 했음 param의 메서드인 put을 이용해서 id라는 이름으로 getparameter로 가져온 id의 값을 넣어줬고 그 이후로 다 똑같이 값들을 param에 넣어줬음. 그리고 model에 있는 join메서드에 인자값으로 이 param을 넣어서 실행시킴. 그리고 이 결과를 msg에 담았음

 

-model

public class MemberModel {
	
	// 회원 정보를 회원아이디.dat 형태로 저장한다.
	
	public String join(HashMap<String, String> param) {
		//파일 저장(파일 쓰기)
		// 1. 파일 위치 지정 + 파일 객체화
		String path = "C:/img/temp/"+param.get("id")+".dat";
		File file = new File(path);		
				
		String msg = "이미 존재하는 아이디 입니다.";
		if(!file.exists()) {// 1-1. 같은 이름의 파일이 있으면 안된다.			
			try {
				// 2. 스트림 준비(주+보조)
				FileOutputStream fos = new FileOutputStream(file);
				DataOutputStream dos = new DataOutputStream(fos);
				// 3. 파일 쓰기
				dos.writeUTF(param.get("id"));
				dos.writeUTF(param.get("pw"));
				dos.writeUTF(param.get("name"));
				int age = Integer.parseInt(param.get("age"));
				dos.writeInt(age);
				dos.writeUTF(param.get("gender"));
				dos.writeUTF(param.get("email"));
				// 4. 내보내기
				dos.flush();
				// 5. 자원반납
				dos.close();
				msg = "회원가입이 완료 되었습니다.";
			} catch (Exception e) {
				e.printStackTrace();
				msg = "회원가입이 실패 하였습니다. 다시 시도해 주세요!";
			}	
		}
		return msg;
	}
	public String login(String id, String pw) {
		String msg = "아이디 또는 비밀번호를 확인해 주세요";		
		// 1. 파일 위치 지정 + 2. 객체화
		String path = "C:/img/temp/"+id+".dat";
		System.out.println(path);
		File file = new File(path);
		
		if(file.exists()) {			
			// 3. 스트림준비(주+보조)
			try {
				FileInputStream fis = new FileInputStream(file);
				DataInputStream dis = new DataInputStream(fis);
				// 4. 읽어오기(쓴 순서대로 읽어와야 한다.)
				String read_id = dis.readUTF();
				String read_pw = dis.readUTF();
				String read_name = dis.readUTF();
				int read_age = dis.readInt();
				String read_gender = dis.readUTF();
				String read_email = dis.readUTF();				
				System.out.println(
					read_id+"/"+read_pw+"/"+read_name+"/"+read_age+"/"+read_gender+"/"+read_email
				);				
				// 5. 자원반납
				dis.close();
				if(id.equals(read_id) && pw.equals(read_pw)) {
					msg = "로그인에 성공 했습니다.";
				}
							
			} catch (Exception e) {
				msg = "로그인 중 오류가 발생 했습니다. 잠시후 다시 시도해 주세요!";
				e.printStackTrace();
			}
		}
		return msg;
	}
}

model의 join메서드를 보면 HashMap<String, String>을 데이터 타입으로 가지고 있는 param 값을 매개변수로 갖는 join 메서드

여기서 이제 param의 값들을 파일에 저장을 해줄거임 

파일저장(파일쓰기) 순서

1. 파일 위치 지정, 객체화

2. 스트림가져와서

3. 쓰고

4. flush

5. close

 

1. 파일 위치 지정, 객체화

path라는 변수에 파일 경로를 넣어서 객체화를 해줄건데, 경로 뒤에다가 param의 id를 가져오고, .dat라는 확장자도 함께 붙여준다, 여기서 id도 붙이는 이유는 id는 중복이 되면 안되기 때문이다

만약 id가 중복이 되면 이미 존재하는 아이디라고 msg가 팝업될 것이다

만약 파일이 존재하지 않으면 

2. 스트림을 준비해줌

주 스트림인 fileOutputStream과 보조스트림인 dataOutputStream을 이용했습니다

DataOutputStream을 사용하는 이유는 자바의 데이터 타입인 string 타입을 전달하기 위해서입니다

3. 파일 쓰기

dos객체의 writeUTF 메서드를 사용해서 파일을 써줬는데 안에 들어갈 인자값으로는 id 파라메터를 비롯한 여러 파라메터들을 get이라는 메서드를 가져온 값을 넣었습니다

그리고 age는 int형식이어야하기 때문에  integer.parseint 를 걸어준 값을 변수 age에 담아줍니다

4. 파일을 내보내기 위해 flush를 사용하고

5. 자원을 반납하기 위해 close를 사용했다

 

여기까지 파일을 저장하고 나면 회원가입 완료 메시지를 출력한다

try-catch 모델을 이용해서 예외를 잡아줬는만약 오류가 나게 되면 회원가입 실패 메시지를 출력한다

 

return값으로는 msg!