-
JSP: FrontController 직접 구현해보기JAVA 2021. 7. 26. 11:02
Spring 의 FrontController 이해하기
// FronctController.java package com.stone.mvc.control; import java.io.IOException; import java.util.Map.Entry; import java.util.Set; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.stone.mvc.util.ViewResolver; //FrontController @WebServlet("*.do") public class FrontController extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. uri path 만 제거 String uri= request.getRequestURI(); String 요청작업DotDo=uri.substring(5);//"/mvc/"5글자 다음 인덱스인 6째부터(zero base면 5가 6번째임) while(true) { // 2. 요청작업 구하기 int lastIdx=요청작업DotDo.indexOf(".do");//".do" 시작인덱스 String 요청작업=요청작업DotDo.substring(0,lastIdx);//".do"문자열 제거 // 3. 요청과 컨트롤 객체 매핑 IControl control= ControlProvider.getControlProvider().getControl(요청작업); //해당 커트롤러 요청처리 ModelAndView 모델과지정된뷰명 = control.process(request, response); Set<Entry<String,Object> > entry들= 모델과지정된뷰명.model.entrySet(); for(Entry<String,Object> entry : entry들 ){ request.setAttribute(entry.getKey(), entry.getValue()); } // 4. 경로에 따른 제어 if(모델과지정된뷰명.viewName.contains("redirect:/")) { 요청작업DotDo = 모델과지정된뷰명.viewName.substring("redirect:/".length());//"redirect:/"문자열 제거 response.sendRedirect(요청작업DotDo); break;//이미 제어권이 넘어가므로 큰 의미는 없다. } if(모델과지정된뷰명.viewName.contains("forward:/")) { 요청작업DotDo = 모델과지정된뷰명.viewName.substring("forward:/".length());//"forward:/"문자열 제거 System.out.println(요청작업DotDo); continue;//요청작업 구하기부터 다시함 } // 5. view로 forward RequestDispatcher rd =request.getRequestDispatcher(ViewResolver.getJspViewName(모델과지정된뷰명.viewName)); rd.forward(request, response); break;//포워드시 이미 제어권이 넘어가므로 큰 의미는 없다. } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response ); } }
// ControlProvider.java class BasicControlProvider { HashMap<String, IControl> controls = new HashMap<String, IControl>(); BasicControlProvider(){ controls.put("prepare_board", new 게시물등록준비()); controls.put("add_board", new 게시물등록()); // 추가사항 controls.put("prepare_member", new 회원등록준비()); controls.put("add_member", new 회원등록()); controls.put("info_member", new 회원정보준비()); controls.put("inquery_address", new 우편번호조회준비()); controls.put("inquery_id", new 아이디중복검사준비()); } public IControl getControl(String work) { return controls.get(work); } } public class ControlProvider { static BasicControlProvider controlProvider = new BasicControlProvider(); public static BasicControlProvider getControlProvider() { return controlProvider; } }
회원등록
>> 회원등록준비.java
public class 회원등록준비 implements IControl{ public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView(); HttpSession session = request.getSession(); // 로그인해서 없는 카테고리지만 어떻게 주소를 찾아 들어올 경우 돌려보내기 if(!(session.getAttribute("no") == null)) { mv.setViewName("index"); } mv.setViewName("회원등록창"); return mv; } }
>> 회원등록창.jsp
<body> <form action="add_member" onsubmit="return 회원등록하다()" method="post" enctype="multipart/form-data"> <h1>회원등록</h1> <!--기초내용 --> 성명 <input type = "text" name = "name" id="name"><br> // 추가사항 프로필<img id="myimg"/><br> <input type="file" id="profile" name="profile"/> 우편번호 <input type = "text" name = "post" id="post" readonly="readonly"><input type="button" onclick="조회창을띄우다()" value="조회"><br> 주소 <input type = "text" name = "address" id="address" readonly="readonly"> <br> 상세주소 <input type = "text" name = "detailaddress"> <br> 전화번호 <input type="text" name="tel"/><br> 이메일 <input type="text" name="email1"/>@ <select name="email2"> <option value="google.com">google.com</option> <option value="naver.com">naver.com</option> <option value="daum.com">daum.com</option> </select> <br> 아이디 <input type="text" name="id" id="id" readonly="readonly"> <input type="button" onclick="아이디중복검사창을띄우다()" value="조회"><br> 패스워드 <input type="password" name="password" id="password1"/><br> 패스워드재입력 <input type="password" id="password2"/><br> <input type="submit" value="등록" /> </form> </body> <script> /* 우편번호,주소 */ function 조회창을띄우다(){ window.open("inquery_address","","width=450,height=300"); } function 주소를받다(우편번호, 주소){ let txt우편번호 = document.querySelector("#post"); txt우편번호.value = 우편번호; let txt주소 = document.querySelector("#address"); txt주소.value = 주소; } /* 아이디 */ function 아이디중복검사창을띄우다(){ window.open("inquery_id","","width=450,height=300"); } function 아이디를받다(id){ let txtID = document.querySelector("#id"); txtID.value = id; } /* 필수입력, 비밀번호확인 */ function 회원등록하다(){ // 필수 입력확인 var txt성명 = document.querySelector("#name"); if(txt성명.value == ""){ alert("성명은 필수 입력입니다."); return false; } var txt아이디 = document.querySelector("#id"); if(txt아이디.value == ""){ alert("아이디은 필수 입력입니다."); return false; } var txt패스워드 = document.querySelector("#password1"); if(txt패스워드.value == ""){ alert("패스워드은 필수 입력입니다."); return false; } // 비밀번호 동일 확인 var txt패스워드2 = document.querySelector("#password2"); if(txt패스워드.value != txt패스워드2.value){ alert("패스워드가 동일하지 않습니다."); return false; } return true; } // 추가사항 function 그림파일읽어출력하기(event){ var 그림파일 = event.target.files[0]; if(!그림파일.type.match('image.*')){ alert("그림파일을 선택해주세요."); } var 파일리더 = new FileReader(); 파일리더.onload = function(event2){ var myimg = document.querySelector("#myimg"); img.src = event2.currentTarget.result; } 파일리더.readAsDataURL(그림파일); } document.querySelector("#myfile").addEventListener("change",그림파일읽어출력하기); </script>
>> 회원등록.java
public class 회원등록 implements IControl{ public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { Member member = null; String folder = "D:\\dojihye\\testFolder"; File file = new File(folder); if(!file.exists()) { try { file.mkdir(); } catch (Exception e) { System.err.println("이미 존재하는 폴더입니다."); } } // try 문안에서와 밖에서 사용해야하니 위에서 선언 ModelAndView mv = new ModelAndView(); MemberDAO dao = new MemberDAO(); try { // MultipartRequest 가 null 일때 String folder 즉, 폴더지정을 잘했는지 확인 MultipartRequest mr = new MultipartRequest(request, folder, 1024*1204*5,"utf-8",new DefaultFileRenamePolicy()); member = new Member(); member.setName(mr.getParameter("name")); member.setPost(mr.getParameter("post")); member.setAddress(mr.getParameter("address")); member.setDetailaddress(mr.getParameter("detailaddress")); // 이메일 주의 member.setEmail(mr.getParameter("email1")+"@"+mr.getParameter("email2")); member.setTel(mr.getParameter("tel")); member.setId(mr.getParameter("id")); member.setPassword(mr.getParameter("password")); member.setState(mr.getParameter("state")); member.setSize(mr.getParameter("size")); File pro = mr.getFile("profile"); // input 태그에 name 이 profile 인지 확인. 아니면 가져오는 것도 없어서 길이도 없으니 오류 byte[] profile = new byte[(int) pro.length()]; FileInputStream is = new FileInputStream(pro); is.read(profile); member.setProfile(profile); } catch (Exception e) { // profile 에 이미지 미등록시 오류가 나니 없어도 save 하도록 똑같이 코드작성 // e.printStackTrace(); mv.addObject("member", member); mv.setViewName("회원등록결과통보"); dao.save(member); return mv; } dao.save(member); mv.addObject("member", member); mv.setViewName("회원등록결과통보"); return mv; } }
>> 회원등록결과통보.jsp
<body> ${member.name} 님 회원등록 감사합니다! <br /> <a href="index?no=-1">index</a> </body>
>> 인덱스화면가기.java
public class 인덱스화면가기 implements IControl{ public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView(); HttpSession session = request.getSession(); int no = 0; if(!(session.getAttribute("no") == null)){ no = Integer.valueOf((String)session.getAttribute("no")); } mv.addObject("no", no); mv.setViewName("index"); return mv; } }
>> index.jsp
<body> index 입니다. <br /> <%if(request.getParameter("msg") != null){%> ${msg} <% }%> <%if(login){%> <a href="info_member">회원정보보기</a> <% }%> </body>
회원정보
>> 회원정보준비.java
public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView(); HttpSession session = request.getSession(); int no = (Integer)session.getAttribute("no"); if(no>0) { MemberDAO dao = new MemberDAO(); Member member = dao.findByNo(no); mv.addObject("member", member); mv.setViewName("회원정보보기"); }else { mv.addObject("msg", "로그인이 필요합니다."); mv.setViewName("index"); } return mv; }
>> 회원정보보기.jsp
<body> name: ${member.name} <br /> profile: <img src="profile?no=${member.no}"> <br /> post: ${member.post} <br /> address: ${member.address} <br /> detailaddress: ${member.detailaddress} <br /> tel: ${member.tel} <br /> email: ${member.email} <br /> id: ${member.id} <br /> password: ${member.password} <br /> rdate: ${member.rdate} <br /> state: ${member.state} <br /> size: ${member.size} <br /> </body>
>> 프로필보기.java
public class 프로필보기 implements IControl{ public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { int no = Integer.valueOf(request.getParameter("no")); ModelAndView mv = new ModelAndView(); mv.addObject("no", no); mv.setViewName("profile"); return mv; } }
>> profile.jsp
<%@ page trimDirectiveWhitespaces="true" %> <% // 바이너리로 응답 (html 응답) 모든 파일은 다 바이너리(byte)규격 이다. int no = Integer.valueOf(request.getParameter("no")); MemberDAO dao = new MemberDAO(); Member member = dao.findByNo(no); response.setContentType("image/jpeg"); ServletOutputStream os = response.getOutputStream(); try{ byte[] profile = member.getProfile(); os.write(profile); }catch(Exception e){ // 회원 이미지가 없어 null 예외 뜰 경우 images 폴더에 저장해둔 기본 유저이미지를 읽어 write한다. String path = request.getRealPath("images"); File file = new File(path + "\\hoteIindexImg.png"); byte[] image = new byte[(int)file.length()]; //일단 file 크기만큼의 byte 배열을 만든다. FileInputStream 입력스트림 = new FileInputStream(file); 입력스트림.read(image); os.write(image); } %>
우편번호 API (다음 무료 API)
https://postcode.map.daum.net/guide
원하는 폼에 예제파일보기 누르고 코드 그대로 복사해 넣으면 끝!
>> 조회창 예시
<h1>우편번호조회</h1> <input type="text" id="sample4_postcode" placeholder="우편번호"> <input type="button" onclick="sample4_execDaumPostcode()" value="우편번호 찾기"><br> <input type="text" id="sample4_roadAddress" placeholder="도로명주소"> <input type="text" id="sample4_jibunAddress" placeholder="지번주소"> <span id="guide" style="color:#999;display:none"></span> <input type="text" id="sample4_detailAddress" placeholder="상세주소"> <input type="text" id="sample4_extraAddress" placeholder="참고항목"> <input type="button" onclick="주소값주기()" value="확인"/> <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script> <script> //본 예제에서는 도로명 주소 표기 방식에 대한 법령에 따라, 내려오는 데이터를 조합하여 올바른 주소를 구성하는 방법을 설명합니다. function sample4_execDaumPostcode() { new daum.Postcode({ oncomplete: function(data) { // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분. // 도로명 주소의 노출 규칙에 따라 주소를 표시한다. // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다. var roadAddr = data.roadAddress; // 도로명 주소 변수 var extraRoadAddr = ''; // 참고 항목 변수 // 법정동명이 있을 경우 추가한다. (법정리는 제외) // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다. if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){ extraRoadAddr += data.bname; } // 건물명이 있고, 공동주택일 경우 추가한다. if(data.buildingName !== '' && data.apartment === 'Y'){ extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName); } // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다. if(extraRoadAddr !== ''){ extraRoadAddr = ' (' + extraRoadAddr + ')'; } // 우편번호와 주소 정보를 해당 필드에 넣는다. document.getElementById('sample4_postcode').value = data.zonecode; document.getElementById("sample4_roadAddress").value = roadAddr; document.getElementById("sample4_jibunAddress").value = data.jibunAddress; // 참고항목 문자열이 있을 경우 해당 필드에 넣는다. if(roadAddr !== ''){ document.getElementById("sample4_extraAddress").value = extraRoadAddr; } else { document.getElementById("sample4_extraAddress").value = ''; } var guideTextBox = document.getElementById("guide"); // 사용자가 '선택 안함'을 클릭한 경우, 예상 주소라는 표시를 해준다. if(data.autoRoadAddress) { var expRoadAddr = data.autoRoadAddress + extraRoadAddr; guideTextBox.innerHTML = '(예상 도로명 주소 : ' + expRoadAddr + ')'; guideTextBox.style.display = 'block'; } else if(data.autoJibunAddress) { var expJibunAddr = data.autoJibunAddress; guideTextBox.innerHTML = '(예상 지번 주소 : ' + expJibunAddr + ')'; guideTextBox.style.display = 'block'; } else { guideTextBox.innerHTML = ''; guideTextBox.style.display = 'none'; } } }).open(); } function 주소값주기(){ var 우편번호 = document.querySelector("#sample4_postcode").value; var 도로명주소 = document.querySelector("#sample4_roadAddress").value + document.querySelector("#sample4_extraAddress").value; var 지번주소 = document.querySelector("#sample4_jibunAddress").value; var 상세주소 = document.querySelector("#sample4_detailAddress").value; opener.주소를받다(우편번호, 도로명주소, 지번주소, 상세주소); close(); } </script>
'JAVA' 카테고리의 다른 글
로그인아웃, session (0) 2021.07.26 redirect, forward,spring 서두 (0) 2021.07.26 이미지업로드: inputStream,outputStream, cos.jar-MultipartRequest (0) 2021.07.25 ModelAndView (0) 2021.07.25 MVC 3 Tier,인터페이스정의서,AJAX-JSON사용,BLOB(image) (0) 2021.07.25