카테고리 없음

ㅇㄴ

logloglog 2021. 1. 4. 14:18

서블릿이용해서 MVC패턴에 맞춰서 해보자

mvc패턴할떄 커맨드패턴을 이용해서 하고있는거임

처리한 커맨드객체를 만들엉서 커맨드객체로하여금 사용자요청을처리하게함 > 유지보수위해

기존의 커맨드를 수정하지않고 새로운 커맨드 (핸들러)를 추가해서 확장할수있는거임

기능은 계속 확장되지만 기존소스는 건들필요가없다.

이런 부분을 수정할 필요가 없는거임

.do 로 끝나는거는 무조건 웹컨트롤럴가서 실제 커맨드객체찾아서 그 커맨드가 그 객체.process해서 프로세스하게끔


update

 

업데이트 요청이 들어올거라는걸 아니까 요청에따른 핸들러 > 핸들러.properties 

 

누가 ubdate.do 요청을 하면 어디로갈지 정해줌

 


잠깐,.. 목록볼때 list.do 를 치면 웹컨트롤러가 어? 목록 보여ㅈ달라는거네 > listhandler 호출, 뿌릴 데이터필요하니까 select로 목록 조회해서 모델을 세팅해서 실제 뷰를 처리하기위해서 jsp에 포워딩 시켜서 해당 데이터 객체를 req객에체 set시켜서 보이는거임 근데 어떤문제가 생기냐면

list.do대신 list.jsp 를 치면

무조건 컨트롤러를 타고 뷰단에 필요한 정보를 뿌리는게 원래의도인데... 위는 좀 아닌것같음

그래서 저 짓을 못하게 하기 위해서 jsp페이지를 아무도 못찾게 숨길거임 어디다? web-inf밑에다

 

 

 

이렇게 경로를 만들어놓으면 list.jsp가 뷰화면인걸 알더라도 접근할 방법이 없음

.do로 접근하눈 수밖에없다.


이렇게 바꾸자마자 list 관련된 핸들러에게 알려줘야함

서버 내에서는 이렇게 접근 가능하다

나머지도 만져줌

 


 

 

package kr.or.ddit.member.handler;

import java.net.URLEncoder;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.vo.MemberVO;

public class UpdateMemberHandler implements CommandHandler{//커맨드 객체로 사용할꺼니까 임플리먼트
	private static final String VIEW_PAGE = "WEB-INF/views/member/updateForm.jsp";// 업뎃핸들러에서 어디페이지로 이동할지
	@Override
	public boolean isRedirect(HttpServletRequest req) {
		//어떨댄 리다이렉트 어떨텐 포워드인지
		if(req.getMethod().equals("GET")) {//겟방식이면 업데이트하는 화면으로 이동해야하고, url은 그대로 update.do일거임
			//유알엘 그대로 화면은 업데이트폼화면으로 이동 >> 포워드방식
			return false;
		}else {
			return true;//트루면 리다이렉트 하겠다
			
		}
	}

	IMemberService memberService = MemberServiceImpl.getInstance();
	@Override
	public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
		//얘도 인서트랑 마찬가지로 첨에 get인지 post인치.. 일단 뷰페이지 먼저 상수로 정의하고
		
		//메서드 방식이 겟이면 업데이트폼 보여줄거고 포스트면 실제로 업데이트 시켜줄거임
		if(req.getMethod().equals("GET")) {
			//얘는 인서트랑 좀 다른게, 업데이트는 기존에 있던놈이고 인서트는 새로운놈.. 업데이트는 일단 디비가져와서셀렉해서 기존의 데이터 보여줘야함
			//바로 화면으로 가는것보다는 화면구성시 사용할 데이터를 조회하는게 먼저일듯
			String memId = req.getParameter("memId");//업데이트는 특정사용자를 특정해서 업뎃하는거기때문데에
			
			//1. 회원정보 조회
			MemberVO mv = new MemberVO();
			mv.setMemId(memId);
			
			//기존의 아이디값을 이용한 서치를 써먹으려고.. 걔의 리턴타입이 List니까
			//한건일수도 여러건일수도있지만
			List<MemberVO> memList =  memberService.getSearchMember(mv);
			//해당아이디에 해당하는 사용자 정보를 li;st로 가져올거임
			
			//2. request객체에 회원정보 저장
			req.setAttribute("memVO", memList.get(0));
			
			//이제 화면으로 가야함
			return VIEW_PAGE;
			
		}else if(req.getMethod().equals("POST")) {
			// 사용자가 업데이트 화면에서 필요한 데이터 수정한 다음에 summit버튼 누른시점
			//해당사용자가 보내준 정보 이용해서 업데이트 작업 해주면 됨
			//사용자가 보낸 데이터를 하나하나 받아올거임
			
			//1. 요청 파라미터 정보 가져오기
			String memId = req.getParameter("memId");
			String memName = req.getParameter("memName");
			String memTel = req.getParameter("memTel");
			String memAddr = req.getParameter("memAddr");
			
			//2. 회원정보 수정
			MemberVO mv = new MemberVO();
			mv.setMemId(memId);
			mv.setMemName(memName);
			mv.setMemTel(memTel);
			mv.setMemAddr(memAddr);
			
			
			// 필요한정보 세팅끝낫으니 업데이트 서비스 호출하면됨
			int cnt = memberService.updateMember(mv);
			
			String msg = "";
			
			if(cnt > 0) {
				msg = "성공";
			}else {
				msg = "실패";
			}
			
			//목록 조회 화면으로 이동
			//리다이렉트 url만들기
			String redirectUrl = req.getContextPath() + "/member/list.do?msg=" + URLEncoder.encode(msg, "UTF-8");
			
			return redirectUrl;
			
		}
		return null;
	}

}

 

이제 화면을 만들어야함

<%@page import="kr.or.ddit.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%//필요한거 정리 하고 하자
//     핸들러에서 setAttribute로 넣어놓은걸 꺼내자
 	MemberVO memVO = (MemberVO) request.getAttribute("memVO");
    
    %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title> 회원정보 변경</title>
</head>
<body>
 	<form action="update.do" method="post">
 	
 		<input type="hidden" name="memId" value="<%=memVO.getMemId()%>">
 		<table>
			
			<tr>
				<td>이름 :</td>
				<td><input type="text" name="memName" value="<%=memVO.getMemName()%>"></td>
			</tr>
			<tr>
				<td>전화번호 :</td>
				<td><input type="text" name="memTel" value="<%=memVO.getMemTel()%>"></td>
			</tr>
			<tr>
				<td>주소 :</td>
				<td><textarea name="memAddr"><%=memVO.getMemAddr()%></textarea></td>
			</tr>
		</table>
 		<input type="submit" value="회원정보 수정"> 
 	</form>
</body>
</html>

delete

 

딜리트는 상세보기에서 수정옆에있다.


package kr.or.ddit.member.handler;

import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;

public class DeleteMemberHandler implements CommandHandler {

	@Override
	public boolean isRedirect(HttpServletRequest req) {
		
		
		return true;//항상 리다이렉트가 되어야함 
	}

	@Override
	public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
		//1. 요청 파라미터 정보 가져오기
		String memId = req.getParameter("memId");
		
		//2. 서비스 객체 생성하기
		IMemberService memberService = MemberServiceImpl.getInstance();
		
		//3. 회원정보 삭제
		int cnt = memberService.deleteMember(memId); //객체로 넣지않고 스트링으로
		
		String msg = "";
		
		if(cnt > 0) {
			msg = "성공";
		}else {
			msg = "실패";
		}
		
		//4. 목록 조회화면으로 이동
		 //  리다이렉트 해줘야함
		String redirectUrl = req.getContextPath() + "/member/list.do?msg="+URLEncoder.encode(msg,"UTF-8");
		
		return redirectUrl;
	}

}

 

 

 

 

COS  ㅍ이용한 파일업로드랑 commons 이용한 파일업로드 배웠었는데 commons 이용한 파일업로드를 해볼거임 (두번째 방법)

 

 

FileUploadRequestWrapper.java
0.01MB

 

 

 

유틸패키지에 넣고

 

이 두개 자르파일 넣어주고

 

 

HttpServletRequestWrapper를 이용하면 (저걸 extends하면 HttpServletRequestWrapper타입의 객체가 됨) 그 객체도 동일하게 HttpServletRequest타입의 객체가 됨. 이걸 이용해서 우리만의 커스텀된 객체를 만들수있음

리퀘스트랩퍼를 통래서 랩핑된 객체를 쉽게 만들 수 있다

물론 resp쪽 객체를 쉽게 커스텀하고싶다면

HttpServletResponseWrapper 도 있다.

 

얘는 대략적으로 뭐하는 함수인지 알면 된다.. 갖다쓰기용

 

멀티파트인 경우 파싱하는 기능까지있는 커스텀 리퀘스트객체인거임

 

 

멀티파트로 던지는 순간 getparameter로 안가져와짐 그래서 멀티파트일떄도 똑같이 가져올수있게 통일하기위해서 세팅을 해주는거임

 

파라미터 담을 용도

파일이 아닌 다른 폼데이터들도 request.getparameter로 갖고올수있게 하려고

 

fileItemMap : 멀티파트는 파일업로드때문에 만들어낸건데, 파일이면 파일아이템맵에, 일반 폼데이터는 파라미터맵에넣을거임

 

 

파일업로드 하려고 하는거임 이거 지금...

파일업로드할때 차이점 : 파일업로드든 아니든 req가 오는데 data 인코딩 방식이 달라지는거임

req.getparameter로 보통 꺼내면 되는데 이게 멀티파트로 던져지는 순간 그게 안됨

암튼 이런 부분 (인코딩이 달라져서 바뀌는 부분 ) 을 랩퍼로 오리지날을 감싸서

멀티파트일때도 멀티파트가 아닌것처럼 기능을 할수있도록 기능을 정의해서 사용을 하려고 하는거임

 

파일업로드시 파일아이템 객체를 가지고잇어야함 그 객체에 writeto 등의 메서드가 다 있기때문에

그걸 맵에 담았음

 ( fileitemmap)


insert에 활용해보자

 

 

insert.form

적절하게 멀티파트를 파싱하는 작업이 필요한데 그걸 wrapper로 작업을 하려고 한다.

 

래퍼클래스를 만든거임

req를 넣는게아니고 wr

 

이제 getparameter이용해서 쉽게 가져올수있음

 

더 향상된 객체를 넣은거임

 

완전히 멀티파트를 파싱할수있는..게됨

 

여기까지 됐으면 이제 insert작업하려고하니까

첨부파일을 위한 VO도 만들어야함

 

파일테이블.txt
0.00MB

 

 

저장파일은 stre~ 실제이름은 orignl~ 별도임

원래이름이랑 저장이름을 별도로 해줘야함

file extsn 은 말그대로 확장자

file cn : content 파일 내용 설명하는 ..

file_size : 말그대로 저장하는 파일 사이즈

 

 

package kr.or.ddit.vo;

import java.util.Date;

public class AtchFileVO {
	
	private long atchFileId;	// 첨부파일ID
	private int fileSn;			// 파일 순번
	private Date creatDt;		//생성일자
	private String useAt;// 사용여부	//사용여부
	private String fileStreCours;	//파일저장경로
	private String streFileNm;		//저장파일명
	private String orignlFileNm;	//실제파일명
	private String fileExtsn;		//파일확장자
	private String fileCn;			//파일내용
	private long fileSize;			//파일 크기
	public long getAtchFileId() {
		return atchFileId;
	}
	public void setAtchFileId(long atchFileId) {
		this.atchFileId = atchFileId;
	}
	public int getFileSn() {
		return fileSn;
	}
	public void setFileSn(int fileSn) {
		this.fileSn = fileSn;
	}
	public Date getCreatDt() {
		return creatDt;
	}
	public void setCreatDt(Date creatDt) {
		this.creatDt = creatDt;
	}
	public String getUseAt() {
		return useAt;
	}
	public void setUseAt(String useAt) {
		this.useAt = useAt;
	}
	public String getFileStreCours() {
		return fileStreCours;
	}
	public void setFileStreCours(String fileStreCours) {
		this.fileStreCours = fileStreCours;
	}
	public String getStreFileNm() {
		return streFileNm;
	}
	public void setStreFileNm(String streFileNm) {
		this.streFileNm = streFileNm;
	}
	public String getOrignlFileNm() {
		return orignlFileNm;
	}
	public void setOrignlFileNm(String orignlFileNm) {
		this.orignlFileNm = orignlFileNm;
	}
	public String getFileExtsn() {
		return fileExtsn;
	}
	public void setFileExtsn(String fileExtsn) {
		this.fileExtsn = fileExtsn;
	}
	public String getFileCn() {
		return fileCn;
	}
	public void setFileCn(String fileCn) {
		this.fileCn = fileCn;
	}
	public long getFileSize() {
		return fileSize;
	}
	public void setFileSize(long fileSize) {
		this.fileSize = fileSize;
	}
	
	
	
	
	
}

 

파일 관련된

xml도 만들어야함

 

sqlmap에 있음

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
			PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
			"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="atchFile">

 	<resultMap class="kr.or.ddit.vo.AtchFileVO" id="atchFileMap">
 	<result property = "atchFileId" column="ATCH_FILE_ID"		/>
	<result property = "fileSn" column="FILE_SN"           />
	<result property = "creatDt" column="CREAT_DT"          />
	<result property = "useAt" column="USE_AT"            />
	<result property = "fileStreCours" column="FILE_STRE_COURS"   />
	<result property = "streFileNm" column="STRE_FILE_NM"      />
	<result property = "orignlFileNm" column="ORIGNL_FILE_NM"    />
	<result property = "fileExtsn" column="FILE_EXTSN"        />
	<result property = "fileCn" column="FILE_CN"           />
	<result property = "fileSize" column="FILE_SIZE"         />
 </resultMap>
 
 <select id = "getAtchFileList" resultMap = "atchFileMap">
 	select * from atch_file
 	where atch_file_id = #atchFileId# and file_sn=#fileSn#
 </select>
 
 
 <insert id="insertAtchFile" parameterClass="kr.or.ddit.vo.AtchFileVO">
 	<selectKey keyProperty="atchFileId" resultClass="long">
 		select ATCH_FILE_SEQ.nextval from dual
 	</selectKey>
 	
 	insert into atch_file (
 	
 	ATCH_FILE_ID
	,FILE_SN
	,CREAT_DT
	,USE_AT
	,FILE_STRE_COURS
	,STRE_FILE_NM
	,ORIGNL_FILE_NM
	,FILE_EXTSN
	,FILE_CN
	,FILE_SIZE
 	)
 	value(
 	#atchFileId#
 	,#fileSn#
 	,#creatDt#
 	,#useAt#
 	,#fileStreCours#
 	,#streFileNm#
 	,#orignlFileNm#
 	,#fileExtsn#
 	,#fileCn#
 	,#fileSize#
 	)
 </insert>
 
</sqlMap>





 

 

파일을 다룰 쿼리는 다 짰음

 

파일을 다운하기위해선 셀렉트

업로드는 인서트

 

 

이제 쿼리를 바탕으로 파일 업로드 관련된 , 혹은 파일정보를 CRUD 할 dao랑 service 만들어야함

그담에 서비스 통해서 업로드 시키면 된다.

 

내일은 하던거 마저 해서 파일업로드 작업할거고 

페이징처리....