WEB Application

TIL 웹 프로그래밍 (Filter, Wrapper, JAVA 파일 업로드)

Tech Signal 2020. 9. 26. 21:46

<필터 체인, wrapper들을 이용한 웹 진행 순서>

- 필터 체인 통과 -> FileUploadRequestWrapper덕에 원본 요청이 바뀜. -> PartWrapper로 파트 나누고 wrapping -> Front Controller에서는 req가 FileUploadRequestWrapper 가 되어 들어옴. 그안에는 partWrapperMap이 들어있음 -> HandlerInvoker -> FileUploadController

- FileUploadCheckFilter: Request header에서 MIME에 multipart가 있는지 체크하는 필터.

- 파라미터 대신 multipart로 되어있으면 part API 써야하는데 얘 어려우니 Part Wrapper를 쓰자. 


CommandHandler 만들 때 중요한 점

1. 필요한건 invoker로부터 핸들러 메소드의 파라미터 형태로 받아야한다.

2. controller는 invoker한테 무조건 logical view name을 return 해줘야 한다. 

invoker가 commandHandler를 호출할 땐 직접적으로 부르지않고 reflection을 사용한다. (이유: 커맨드 핸들러 각각 시그니처가 다르기 때문에)


이미지 받아올 때 주의할 점   

Domain Layer: 클라이언트 data 또한 받아야함. 

이미지를 받아오려면 & 파일을 전송하려면 part로 보내야한다. 그 part는 1개의 input 태그를 대신함. = PartWrapper 타입으로 받아와야함. -> form의 method=POST로 바꾸고, enctype="multipart/form-data"


- Web.xml에서 servlet mapping 부분에 <multipart-config></multipart-config> 넣어줘야 part api (Since 3.0 ) 가능

- file객체: filesystem상의 실제 경로가 필요


<회원의 프로필 사진 받아 저장하기>

방법 요약(클릭!)

- 이미지 설명(위에서 아래로 보세요): 요청은 FileUploadRequestWrapper에 의해 감싸지고, 그 안에는 멀티파트 안의 파트 하나하나를 뜻하는 partWrapperMap이 생긴다. 그 맵의 value가 PartWrapper인데, 원래 파일 이름, 파트, 실제 저장명 등으로 구성된다.

- 클라이언트가 업로드하는 파일의 경우, DB도 서버도 아닌 Middle Tier 'prodImages' 폴더에 binary데이터로 저장된다. 실제 db 에는 경로, 이름과 같은 metadata만 있게 된다.

- 이미지의 경우 DB에서는 B(inary)LOB 타입으로 - Domain Layer에서는 byte[]

private Byte[] mem_img; //DB가 보내주는 data 
private PartWrapper mem_image; //클라이언트가 보내주는 part data 받기위함


<트랜잭션 관리 유의할 것>

서비스에서 dao.insertProd 할때 이미지 저장은 쿼리 동작 후에 해줘야함. 이유: 롤백이 불가능하기 때문에 


<서버 사이드에서 처리할 수 있는 이벤트 종류>

LifeCycle, Change Attribute

  1. request: initialize, destroy, add/remove/replace attribute 

  2. session: initialize, destroy, add/remove/replace attribute 

  3. application(ServletContext): initialize, destroy, add/remove/replace attribute 

공통점: scope라는 map을 하나씩 가지고 있다.  

 

이벤트 처리 방법

1. 이벤트의 타겟 결정( 버튼으로)

2. 처리할 이벤트 결정(클릭)

3. 이벤트 핸들러 구현(함수) : 자바(or JSP)에서는 별개의 Listener 객체 구현

4. 타겟에 핸들러를 부착 (onclick): web.xml 에서 listener라는 엘리먼트 사용 

 

ServletContextListener: S context 의 lifecycle이 변경될 때. 모든 이벤트 중에서 application의 init이 가장 먼저 시작된다.

이클립스에서 리스너 생성 시 선택할 수 있는 옵션들

- 한 사이트에서 총 누적 방문자 알고 싶을 때: sessionCreated()

- 한 사이트에서 현재 방문자 알고 싶을때 : sessionCreated() / sessionDestroyed()

- 접속자 식별하려면 누군가 로그인했을 때 : session scope에 authMember가 만들어짐 sessionScope에 authMember가 add됐을 때 회원 접속자 리스트 세야함. -> authMember사라짐(logout): attributeRemoved()


<Listener 객체를 이용한 동시 접속자 리스트>

접속자 모음을 List로 하면 한 유저가 브라우저 여러개로 들어왔을 경우 인덱스가 여러개가 되거나 달라져서 안됨. => set이나 map 써야함

 

접속자 실시간으로 체크하는 법 : Long polling, 매 1초마다 서버로 비동기 요청을 날려 데이터를 가져오는 방법

=> 서버가 매 1초마다 새로운 요청을 감당하느라 힘듦 


<EL: Expression Language>  

★ EL 자세한 설명, 요약 보러가기 클릭 ★

 

정규표현식을 사용해 한번에 바꿔주면 훨씬 편합니다!