카테고리 없음

서블릿

logloglog 2020. 12. 28. 14:02
에러핸들링.. 서블릿에 예외가 발생할때...에러가 발생하는 시점에 필요한 예외정보를 얻어낼수있다. 예외를 담당할 서블릿을 만들어서 어떤 예외가 발생했는지등으로 리퀘스트 객체에서 꺼내올수있음.
예외에 대한 정보는 리퀘스트가 가지고잇음

쿠키 : 브라우저에 저장하는 작은 정보조각
쿠키를 브라우저쪽에 필요한정보들(서버가 필요한)을 저장하는 기술
쿠키를 저장하기위해선 쿠키객체를 하나 만들고, 키밸류 세팅하고 유효기간도.. 그후에 resp객체에 addCookie
헤더에 셋쿠키라는 헤더가 만들어서 리스판스 하기위한 준비임..?
브라우저는 셋쿠키라는 헤더값 받아서브라우저내에 쿠키를 생성함.

사용자가 쿠키를 헤더에 세팅해서 던져주면 톰캣에서 읽을수가있어야함 사실 톰캣은 자동으로 읽어서 req,resp에 세팅을 해놓음.. 꺼내는 방법은 req.겟쿠키스 <<<필요한 쿠키타입의 배열로 받을수잇음

쿠키를 브라우저쪽에 생성해놓은걸 삭제할수도있어야함.. > 꺼내온 쿠키의 객체의 setmaxage를 0으로 .. 한 후에 다시 addcookie하면 됨. 

민감한 정보는 서버에 저장하는게 낫다. 서버쪾에 저장하기위해 사용하는 객체 < http세션이라는 인터페이스타입의 객체.. 세션객체를 만들기위해서 req.getsession 호출( new 가 아니다)

서버단에 저장하는것이기떄문에 쿠키보다는 보안에 덜 취약하다.
세션 제거법은 3가지가 잇음
1. web.xml에 세션 타임아웃 (분단위)
2. maxinactiveinterval << 접근안한다는뜻 (초단위)
3. 세션객체.invalidate <<보통 로그아웃할때 사용

브라우저창 다 닫아버려도 삭제됨

서블릿 필터 : 그 전까지는 서블릿(자바컴포넌트. 동적인 컨텐츠를 만들어주기위한 ..)을 봤고 지금은 서블릿필터임
사용자가 요청하고, 요청에대해서 리스판서해주는데 req와 resp 사이에 필터를 해주는것
인코딩등 공통되고 반복적인 작업등을 필터로 해결해줄수있다.


package kr.or.ddit.basic;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class T07_ServletFilter implements Filter{
	//서블릿이 아니고 필터임 그래서 filter라고하는 인터페이스
	/**
	 * 서블릿 필터에 대하여... (사용자요청정보를 처리해주는게 서블릿임. 근데 그 서블릿이 엄청마니만들어질텐데. 이제 어떤고민이생겼냐면.... 공통기능
	 * 예를들자면 인코딩하는작업을 매번해야하는데... 그걸 필터에서 가로채서 해줄수있음... 
	 * 1. 사용목적
	 * - 클라이언트의 요청을 수행하기 전에 가로채 필요한 작업을 수행할 수 있다.
	 * - 클라이언트에 응답정보를 제공하기 전에 응답정보에 필요한 작업을 수행할 수 있다.
	 * 
	 * 2. 사용 예
	 * - 인증필터
	 * - 데이터 압축 필터
	 * - 인토딩 필터
	 * - 로깅 및 감사처리 필터
	 * - 이미지 변환 필터 등
	 * 
	 */
	
	@Override
	public void destroy() {
		//필터객체가 웹컨테이너에 의해 서비스로부터 제거되기 전에 호출됨.
		//등록해놓은 서블릿객체가 컨테이너로부터 제거될떄 디스트로이 실행되는거임
		System.out.println("T07_ServletFilter = > destroy() 호출됨");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) //http서블릿보다 상위개념
			throws IOException, ServletException {
		//요청응답할때 서블릿작업전, 후의 작업을 여기서 해줄수있음
		System.out.println("필터 시작!!");
		// 클라이언트 IP주소 가져오기
		String ipAdress = req.getRemoteAddr();
		
		System.out.println("IP주소 : " + ipAdress + "\n포트번호 : " + req.getRemotePort() + "\n현재시간: "+ new Date().toString());
		//필터체인을 실행한다 (req, resp객체 전달)
		fc.doFilter(req, resp);//중요한거!! filter >>>> 서블렛모여있는곳으로 보내는거임 ! 그래서 파라미터 담아서 보내는것
		//결국 서블렛입장에서는 필터의 존재를 모르고 그냥 브라우저가 요청한거랑 똑같은데 사실 중간에 필터가 거른거임
		//콜스택에 호출된 상태로 기다림... 서블릿이 처리 다하고
		System.out.println("필터처리 완료...");
		//resp될때 여기서부터 다시 시작임 // 응답을 톰캣이 받기 전에 이게 아직 종료가 되지않았기때문에 여기로 돌아오는것
		
		//어떤 고객기 로드를 남겨달라고 하면 모든 서블릿 다 까가지고 해야하는데, 이걸 필터에서 모든 요청을 거르니까 필터에 실행하면 됨
		//이런 목적으로 쓰는게 필터임
		//이름이 필터체인인 이유는 필터를 여러개를 둘 수 있는거임
		
		
	}
	

	@Override
	public void init(FilterConfig  config) throws ServletException {
		System.out.println("T07_ServletFilter => init()호출됨!");
		//초기화 파라미터 정보 가져오기
		String initParam = config.getInitParameter("init-param");//파라미터값을 객체가만들어진시점에 넣어줄수잇따.
		//config << 위에서받은 필터컨피그라는 객체고 물론 톰캣이 던져준거임
		//같은방식으로 db접속정보같은걸 설정해줄수있음.. 
		
		System.out.println("init-param : "+ initParam);
	}
}

init()이랑 destroy() 이렇게 추가하고

web.xml에 서블릿마냥 추가해주러감

 

언제동작시킬지는 filter-mapping

 

/* 은 모든요청.. 사용자로부터 들어오는 모든요청은 다 얘를 거친다.

 

init메서드에서 아까

이렇게 꺼내올라면 미리 세팅해줘야함

 

실행하면

예전에 했던거 암거나 실행>

순서를 보면,

요청전에 필터가 가로채서 먼저 필터시작!!이 된거임

 

dofilter로 원래 서블릿에게 req,resp 넘겨주니까

그때서야 service()부터 시작임 (원래 라이프사이클 작업)

다하고 돌아올때 "필터처리완료"

 

서버중지시키면 destroy호출됨

 



필터를 여러개 걸 수 있다.

 

선언한 순서대로

log filter 먼저, exeTimeFilter 그 다음

 


인코딩처리하는 필터도 만들어보자

package kr.or.ddit.basic;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class CharacterEncoding implements Filter{

	private String encoding; //인코딩 정보
	
	@Override
	public void destroy() {
		
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc)
			throws IOException, ServletException {
		System.out.println("request 인코딩 설정 : " + encoding);
		req.setCharacterEncoding(this.encoding);//인코딩 설정
		resp.setCharacterEncoding(encoding);
		
		fc.doFilter(req, resp);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		if(config.getInitParameter("encoding") == null) {
			this.encoding = "UTF-8";
		}
	}

}

init부분은 나중에 utf말고 다른걸로 바꾸고싶을떄! 저걸 이용하면 된다. 

 

해보려는데

주석처리하고
안꺠진다


리스너를 배울거임

dololak.tistory.com/616

 

[서블릿/JSP] 리스너(Listner)란? 이벤트 리스너의 개념 설명. 구현 및 등록하기

리스너란? 이벤트, 리스너, 이벤트핸들러 간략 개념정리 리스너는 단어의 뜻으로 보자면 (소리를) 듣는 사람, 청취자입니다. 프로그래밍에서의 리스너는 무언가 소리를 듣는 사람을 뜻하기 보다

dololak.tistory.com

우리느 톰켓에 서블릿도 만들고 필터도 만들고하는데,

(이벤트는 어트리뷰트를 추가하거나 제거하고 라이프사이클이 돌고...이런일련의 사건들)

이 톰켓에 어떤 이벤트(행ㅇ위)가 발생할수있음.. 그런 이벤트에 따라서 내가 뭔가 해줘야하는 일이 발생할수있음

ex ) req객체에 특정한 속성값을 추가했을대, 그 추가되는 정보를 db에 인서트 시켜줘야하는 상황이 발생할수있는데

그럴때는 이벤트기반으로 뭔가 처리하도록 로직을 세워야함

 

굵직굵직한 이벤트에 따라서 내가 뭔가 작업할것들을 이벤트리스너로 작업해놓으면 톰켓이 그 특정이벤트 걸리면 그 메서드 찾아서 호출한다.

 

 


리스너 먼저 만들자

package kr.or.ddit.basic;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener 
		, ServletContextAttributeListener{

	@Override
	public void contextDestroyed(ServletContextEvent sce) {//서블릿컨텍스트가 제거되었을때호출
		System.out.println("[MyServletContextListener] contextDestroyed() 호출됨 (서블릿 컨텍스트가 제거되었음)"
				);
	}

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("[MyServletContextListener] contextInitialized() 호출됨 (서블릿 컨텍스트가 초기화되었음)");
	}

	@Override
	public void attributeAdded(ServletContextAttributeEvent scae) {
		System.out.println("[MyServletContextListener] attributeAdded() 호출됨" + scae.getName());
	}

	@Override
	public void attributeRemoved(ServletContextAttributeEvent scae) {
		System.out.println("[MyServletContextListener] attributeRemoved() 호출됨"  + scae.getName());
	}

	@Override
	public void attributeReplaced(ServletContextAttributeEvent acae) {
		System.out.println("[MyServletContextListener] attributeReplaced() 호출됨"  + scae.getName());
	}

}

ㄷ등록

 

 

서블릿컨텍스트

서블릿컨테이너 즉 톰캣과 커뮤니케이션하는 메서스들을 정의해놓은 인터페이스. 웹어플리케이션 하나당 한개의 context가 만들어짐. 즉 서블릿컨텍스트라는 객체는 톰캣과 필요한 작업을 하기위해 만들어진 객체고, 반드시 위으 인터페이스에 구현한 메서드를 구현해야 servletCOntext객체가 된다. 이건 애플리케이션당 1개가 만들어짐

서클릿컨텍스트 객체라면

 

여러 메서드들이있따.
get, set 어트리뷰트 가능

서블릿컨텍스트객체 (쉽게말하면 애플리케이션 관리하기 위한 객체) 는 톰캣이 만들어진 시점에 앱당 1개가 만들어지고, 톰캣이 중지되면 (컨테이너가 사라지면) 사라진다.

 

마치 전역변수 느낌남.. 서블릿컨텍스트에 집어넣으면 오랫동안 살아있으니까..

 

애플리케이션 전체를 관통하는.. 그런 정보를 넣어두면 좋다.

 

애플리케이션 전반에 관련된 관리하는 객체 >> 서블릿컨텍스트

 


서버 재시작해보자

 

초기화 후 , 어떤 어트리뷰트가 추가되었음

jasper.compiler.TldLocationsCache 라고 적혀잇는데, 우리는모르지만 jsp관련된 뭔가 속성을 추가했나봄.. 암튼 리스너를 등록해놔서 알수있는거임

 


실제 이벤트 발생시켜보자

package kr.or.ddit.basic;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//등록귀찮으니까 어노테이션.. 밸류는 하나만 잇으면 생략가능하니까
//value = "/ServletContextListenerTest" 이거에서 밸류생략가능
@WebServlet("/ServletContextListenerTest")
public class T09_ServletContextListenerTest extends HttpServlet{
//ServletContext관련된 리스너라는 의미의 이름임
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//서블릿컨텍스트에 한번 어트리뷰트를 에드도 해보고 리부므보 해보려고함. 이벤트발생시마다 감지하는지 궁금하니까
		//req객체통애서 서블릿컨텍스트에 접근하는 방법
		req.getServletContext().setAttribute("ATTR1", "속성1");//속성값 추가 (attr1번에 속성1이라는 속성값추가)
		req.getServletContext().setAttribute("ATTR1", "속성11");//속성값 변경
		req.getServletContext().setAttribute("ATTR2", "속성2");//속성값 추가
		
		//httpServlet에서 제공하는 메서드 이용하는 방법도있다. 속성값 삭제해보자
		getServletContext().removeAttribute("ATTR1");
		
	
	}
}


이번에는 서블릿리퀘스트 관련된 리스너를 구현해보자 (방금까지는 서블릿ㅌ컨텍스트 관련된 리스너엿음)

 

package kr.or.ddit.basic;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyServletRequestListener implements ServletRequestListener, ServletRequestAttributeListener{

	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		System.out.println("[MyServletRequestListener] requestDestroyed() 호출됨 (httpservletrequest가 제거되었음)");

	}

	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		System.out.println("[MyServletRequestListener] requestInitialized() 호출됨 (httpservletrequest가 초기화었음)");

	}

	@Override
	public void attributeAdded(ServletRequestAttributeEvent srae) {
		System.out.println("[MyServletRequestListener] attributeAdded() 호출됨 (httpservletrequest 어트리뷰트가 추가되었음)"+ srae.getName() + " : " +srae.getValue());

	}

	@Override
	public void attributeRemoved(ServletRequestAttributeEvent srae) {
		System.out.println("[MyServletRequestListener] attributeRemoved() 호출됨 (httpservletrequest 어트리뷰트가 제거되었음)"+ srae.getName() + " : " + srae.getValue());

	}

	@Override
	public void attributeReplaced(ServletRequestAttributeEvent srae) {
		System.out.println("[MyServletRequestListener] attributeReplaced() 호출됨 (httpservletrequest 어트리뷰트가 변경되었음)"+ srae.getName() + " : " + srae.getValue());

	}

}
		<listener>
		<display-name>MyServletRequestListener</display-name>
		<listener-class>kr.or.ddit.basic.MyServletRequestListener</listener-class>
	</listener>

서블릿을 만들어줘야함

 

package kr.or.ddit.basic;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//등록귀찮으니까 어노테이션.. 밸류는 하나만 잇으면 생략가능하니까
//value = "/ServletContextListenerTest" 이거에서 밸류생략가능
@WebServlet("/MyServletRequestListener")
public class T10_ServletRequestListenerTest extends HttpServlet{
//ServletContext관련된 리스너라는 의미의 이름임
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//서블릿컨텍스트에 한번 어트리뷰트를 에드도 해보고 리부므보 해보려고함. 이벤트발생시마다 감지하는지 궁금하니까
		//req객체통애서 서블릿컨텍스트에 접근하는 방법
		req.setAttribute("ATTR1", "속성1");//속성값 추가 (attr1번에 속성1이라는 속성값추가)
		req.setAttribute("ATTR1", "속성11");//속성값 변경
		req.setAttribute("ATTR2", "속성2");//속성값 추가
		
		//httpServlet에서 제공하는 메서드 이용하는 방법도있다. 속성값 삭제해보자
		req.removeAttribute("ATTR1");
		
	
	}
}


 

이번엔 세션 리스너

 

package kr.or.ddit.basic;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MySessionAttributeListener implements HttpSessionAttributeListener{

	@Override
	public void attributeAdded(HttpSessionBindingEvent hsbe) {
		System.out.println("[MySessionAttributeListener] attributeAdded() 호출됨.. Session attribute 추가되었음)"+ hsbe.getName() + " : " +hsbe.getValue());
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent hsbe) {
		System.out.println("[MySessionAttributeListener] attributeRemoved() 호출됨 ..Session attribute 제거되었음)"+ hsbe.getName() + " : " +hsbe.getValue());

	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent hsbe) {
		System.out.println("[MySessionAttributeListener] attributeReplaced() 호출됨.. Session attribute 변경되었음)"+ hsbe.getName() + " : " +hsbe.getValue());

	}

}

 

등록..

package kr.or.ddit.basic;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//등록귀찮으니까 어노테이션.. 밸류는 하나만 잇으면 생략가능하니까
//value = "/ServletContextListenerTest" 이거에서 밸류생략가능
@WebServlet("/MySessionAttributeListener")
public class T11_HttpSessionListenerTest extends HttpServlet{
//ServletContext관련된 리스너라는 의미의 이름임
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//서블릿컨텍스트에 한번 어트리뷰트를 에드도 해보고 리부므보 해보려고함. 이벤트발생시마다 감지하는지 궁금하니까
		//req객체통애서 서블릿컨텍스트에 접근하는 방법
	
		req.getSession().setAttribute("ATTR1", "속성1");//속성값 추가 (attr1번에 속성1이라는 속성값추가)
		req.getSession().setAttribute("ATTR1", "속성11");//속성값 변경
		req.getSession().setAttribute("ATTR2", "속성2");//속성값 추가
		
		//httpServlet에서 제공하는 메서드 이용하는 방법도있다. 속성값 삭제해보자
		req.getSession().removeAttribute("ATTR1");
		
	
	}
}

 


세션관련된거긴한데

 

package kr.or.ddit.basic;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class MySessionBindingListener implements HttpSessionBindingListener {

	@Override
	public void valueBound(HttpSessionBindingEvent hsbe) {//bind : 값에 매핑해주는거
		//어떤값이 바인딩될때호출되는거 >> 언제쓰는건가? 
		String attrName = hsbe.getName();
		System.out.println("[MySessionBindingListener]"+this.hashCode() + "객체가 "+ attrName + "으로 바인딩 됨.");
	}

	@Override
	public void valueUnbound(HttpSessionBindingEvent hsbe) {
		String attrName = hsbe.getName();
		System.out.println("[MySessionBindingListener]"+this.hashCode() + "객체가 "+ attrName + "으로 언바인딩 됨.");
	}

}

ㅎ해놓고

 

T11로 다시

 

package kr.or.ddit.basic;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//등록귀찮으니까 어노테이션.. 밸류는 하나만 잇으면 생략가능하니까
//value = "/ServletContextListenerTest" 이거에서 밸류생략가능
@WebServlet("/MySessionAttributeListener")
public class T11_HttpSessionListenerTest extends HttpServlet{
//ServletContext관련된 리스너라는 의미의 이름임
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//서블릿컨텍스트에 한번 어트리뷰트를 에드도 해보고 리부므보 해보려고함. 이벤트발생시마다 감지하는지 궁금하니까
		//req객체통애서 서블릿컨텍스트에 접근하는 방법
	
		req.getSession().setAttribute("ATTR1", "속성1");//속성값 추가 (attr1번에 속성1이라는 속성값추가)
		req.getSession().setAttribute("ATTR1", "속성11");//속성값 변경
		req.getSession().setAttribute("ATTR2", "속성2");//속성값 추가
		
		//httpServlet에서 제공하는 메서드 이용하는 방법도있다. 속성값 삭제해보자
		req.getSession().removeAttribute("ATTR1");
		
		//http세션 영역내에 HttpSessionBindingListener를 구현한 객체 바인딩 되면 호출됨
		MySessionBindingListener bindingListener = new MySessionBindingListener();//이행위가 바인딩행위임
		//그냥 바인딩오브젝트를 구현할떄.. 바인딩리스너 임플받은 객체가 세션에 등록하고 리무브하는걸 모니터링하고싶음..?
		req.getSession().setAttribute("obj", bindingListener);//세션에 바인딩타입의객체를 추가
		req.getSession().removeAttribute("obj");//세션에 바인딩타입의객체를 리무브
		
	
	}
}

왜 바인딩에 맞춰서 어트리뷰트가 에드되고 리무브되는지 모르겟음

바인드리스너를 구현한 객체가 세션에 추가되는시점이 바인딩??

 

어트리뷰트는 세션에 추가되고 삭제되는 행위자체가 관심이있는거임

바인딩리스너는 어떤객체(세션바인딩리스너를구현한객체)가 추가되면 바로알고싶은거임

 

특정한 객체가 올때만 내가관심이있어 하면 바인딩리스너

속성이 추가삭제될때를 알고싶으면 어트리뷰트리스너

 

나머지는 다 web.xml에 리스너로 등록을하지만

바인딩리스너는 구현한 객체가세션에 에드만되면? 

 

바인딩....

 

사실지금배운리스너들 안볼수도있는데 대표적인것만 살펴본거임

리스너가 ㅜ머하는지 개념만 알고있따면 어떠한 리스너가 오든지 거기에 맞춰서 구현만하면됨

 

 


서블렛 굵직한건 끝남

 

이제 이미지를 다운로드하는 예제를 보자

 

package kr.or.ddit.basic;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 서블릿을 이용한 이미지 출력 예제 
 * (ServletOutputStream 을 이용한 이미지 출력 예제)
 */
@WebServlet("/ImageServlet")
public class T12_imageServlet extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//컨텐트 타입 설정
		resp.setContentType("image/jpeg");
		
		ServletOutputStream out = resp.getOutputStream();
		FileInputStream fis = new FileInputStream("d:/D_Other/Tulips.jpg");
		
		BufferedInputStream bis = new BufferedInputStream(fis);
		BufferedOutputStream bos = new BufferedOutputStream(out);
		
		int bytes = 0; //읽은 바이트 수
		while((bytes = bis.read()) != -1) {
			bos.write(bytes);
		}
		
		bis.close();
		bos.close();
	}
	
}

그동안 html만 했었는데 이번엔 바이트타입을 직접 쏴준거고, content타입을 image로 알려줬기때문에 image나온거임

 

근데 erd파일이나 아래한글같은 파일은 못연다.. 그러건 파일을 그냥 다운로드해야함

파일 다운로드를 처리하는걸 해보자


package kr.or.ddit.basic;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/DownloadServlet")
public class T13_DownloadServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String fileName = "Tulips.jpg"; //다운로드할 파일명
		
		//파일 다운로드 처리를 위한 응답헤더 정보 설정하기
		resp.setContentType("application/octet-stream");
		//마인타입을 application/octet-stream 으로 하면 이진타입의 어쩌구.. 
		resp.setHeader("Content-Disposition", "attachment; filename=\""+fileName+"\"");
		
		/**
		 * Content-Disposition 헤더에 대하여..
		 * 1. response header에서 사용되는 경우 ... ex)파일 다운로드
		 * Content-Disposition : inline (default)
		 * Content-Disposition : attachment // 파일 다운로드
		 * Content-Disposition : attachment; filename="파일명"
		 * 
		 * 2. multipart body를 위한 헤더정보로 사용되는 경우.. ex)파일 업로드
		 * Content-Disposition : form-data
		 * Content-Disposition : form-data; name="filedName"
		 * Content-Disposition : form-data; name="filedName"; filename="파일명"
		 */
		
		
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:/D_Other/"+fileName));
		BufferedOutputStream bos = new BufferedOutputStream(resp.getOutputStream());
		
		int bytes = 0; //읽은 바이트 수
		while((bytes = bis.read()) != -1) {
			bos.write(bytes);
		}
		
		bis.close();
		bos.close();
		
	}
}