web.xml
, 그이상의 버전 - @WebServlet
)web.xml
, 그이상의 버전 - @WebServlet
)생성 - init
요청 - service
, doXXX
소멸 - destroy
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
}
static이 없음 - 인스턴스 객체라는것
근데 우리는 서블릿클래스의 객체를 생성한 적이 없다
⇒ 우리 외 누군가가 대신 생성해줬을것 = Container의 역할!!
// url-pattern과 value라는 속성은 그 의미가 같다
@WebServlet(value= {"/desc.do"})
// 싱글밸류로 쓸수있다
@WebServlet({"/desc.do"})
// 엘리먼트가 하나면 이렇게 써도되는것
@WebServlet("/desc.do")
모든 do 계열의 메소드는 405 메소드를 만든다. (지금은 super땜에 나오는중)
@WebServlet(value= {"/desc.do"})
public class DescServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Desc Servlet");
}
}
이녀석의 객체를 WAS가 생성해준것
확인해볼까
@WebServlet(value= {"/desc.do"})
public class DescServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Desc Servlet");
}
public DescServlet() {
super();
System.out.println(this.getClass().getName());
}
}
this의 getClass로 접근한건 바로 여기
WAS는 싱글톤으로 관리하니까 메모리상 올라가있는 객체를 가비지 컬렉션 시켜야 새 로그가 찍힐수있으니 리스타트
이런식으로 출력되는 패스를 퀄리파이드 네임이라고 한다
근데 새로고침 많이해서 요청 여러번해도 저건 한번출력된더
→ 서블릿의 객체가 단한번 생성됐다 (= WAS가 싱글톤으로 관리한다)
@WebServlet(value= {"/desc.do"})
public class DescServlet extends HttpServlet{
public DescServlet() {
super();
System.out.println(this.getClass().getName()+"생성");
}
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println(this.getClass().getName()+"초기화");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("요청처리시작");
super.service(req, resp);
System.out.println("요청처리종료");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Desc Servlet");
}
@Override
public void destroy() {
super.destroy();
System.out.println(this.getClass().getName()+"소멸");
}
}
새로고침 한번
새로고침 여러번
띄어쓰기 하나 추가하고 콘솔창보면
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Desc Servlet");
System.out.println("doGet() 실행");
}
여기만 수정하고 다시 실행
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("요청처리시작");
**super.service(req, resp); <= 얘는 뭐하고 있는걸까?**
System.out.println("요청처리종료");
}
내부에소 doget
을 호출하고있는것!
do 계열 메소드는 7개나 되는데 저중 뭘 호출하는지 어케알지?
http
요청의 method
(7개)를 파악하고 해당 callback
을 호출
즉 요청을 열어서 보고 메소드를 파악해서 호출해주는것
http
에서 요청이 어떤식으로 패키징 되느냐?
서블릿의 인스턴스 생성시점을 정함
보통 청이 처음 발생할때 생성되나 이걸 설정하면 서버 구동 즉시 인스턴스가 생성됨
@WebServlet(value= {"/desc.do"}, loadOnStartup=1)
// 숫자는 우선순위를 표시한다.
새로고침 안했는데 생성
이걸로 나중에 데이터베이스와 연결을 수행할거임 (드라이버 로딩작업)
<servlet>
<servlet-name>DescServlet</servlet-name>
<servlet-class>kr.or.ddit.servlet01.DescServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<load-on-startup></load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DescServlet</servlet-name>
<url-pattern>/desc.do</url-pattern>
</servlet-mapping>
작성에 제약이 많아서 사용 안하기 시작~
xml 대체 - JSON 또는 어노테이션인것임!
web.xml에 이러던걸 그냥 어노테이션으로 대체
@WebServlet(value= {"/desc.do"}, loadOnStartup=1, initParams= {@WebInitParam(name="param1",value="value1")})
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println(this.getClass().getName()+"초기화");
}
어떤메소드를 쓰면 초기화 파라미터를 떠낼 수 있을까?
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println(this.getClass().getName()+"초기화");
String initValue = config.getInitParameter("param1");
System.out.println("param1의 값 - "+initValue);
}
왜오류나 미친놈아
어노테이션과 xml 둘다 살려놓고 실행하면 오류뜸
urlpattern이 둘 다에 매핑되어있다는 오류 ~
어노테이션 지우고
다른 서블릿도 같은 url 매핑시키면
url매핑이 같아서 오류난다고 콘솔에 나타난다!
이런 오류를 잡는 가장 좋은 방법
프로젝트 익스플로러에서
매핑 쉽게 확인 가능
알아서 어노테이션 달아서 만들어진다
package kr.or.ddit.servlet01;
import java.io.IOException;
import java.io.PrintWriter;
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("/korean.do")
public class KoreanServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data = "한글 로우 데이터";
StringBuffer html = new StringBuffer();
html.append("<html>");
html.append("<body>");
html.append(String.format("<h4>%s</h4>",data));
html.append("</body>");
html.append("</html>");
PrintWriter out = response.getWriter();
out.println(html);
out.close();
}
}
혀튼 나온 결과 인코딩이 안되어있다 개발자도구 켜서 네트워크의 request헤더 보면 특이하대
네이버를 보면 컨텐츠타입이 정의되어있는데 우린 이게 없어서그럼
MIME (Multi-purpose Internet Mail Extension)
: P2P 사이에서 전송되는 컨텐츠의 타입(형식)
문법 - mainType/subType[;charset=encoding]
ex) text/javascript, text/html, text/css, text/plain;charset=utf-8, image/jpeg, video/mp4
1바이트의 아스키코드는 부호코드 하나 뺴고 7비트 사용가능, 2의 7승으로는 한글 표현 불가 최소 2바이트는 필요하다
클라이언트의 브라우저한테 UTF-8로 설정된상태임을 알려줘야함
현재 응답데이터가 html 소스인 상태니까.. 그안에 utf-8로된 특수문자가 있고
마임으로 표현하면 text/html;charset=utf-8;
@WebServlet("/korean.do")
public class KoreanServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String mime = "text/html;charset=utf-8";
response.setContentType(mime);
String data = "한글 로우 데이터";
StringBuffer html = new StringBuffer();
html.append("<html>");
html.append("<body>");
html.append(String.format("<h4>%s</h4>",data));
html.append("</body>");
html.append("</html>");
PrintWriter out = response.getWriter();
out.println(html);
out.close();
}
}
파일리소스를 웹 리소스인것처럼 스트리밍 해주기………
내보내려는 컨텐츠는 html이 아닌 이미지데이터임
// 내가 푼 풀이
@WebServlet("/image.do")
public class ImageStreamingServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 클라이언트에 이미지파일 전달하는 서블릿
resp.setContentType("image/png");
// 클라이언트에게 원시데이터를 전달할 수 있는 출력스트림을 반환받아 저장
ServletOutputStream out = resp.getOutputStream();
// 이미지파일의 경로 저장
String filePath ="D:/contents/cheezDug.png";
// 이미지파일을 읽기위한 입력스트림 생성및 저장
FileInputStream in = new FileInputStream(filePath);
// 입력스트림에서 원시데이터를 읽어 출력스트림으로 저장 (파일전송)
while(true) {
int readByte = in.read();
if(readByte==-1) break;
out.write(readByte);
}
// 입력스트림 제거
in.close();
}
}
@WebServlet("/image.do")
public class ImageStreamingServlet extends HttpServlet{
private ServletContext application;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
application = getServletContext();
}
@Override
// 서블릿 컨텍스트는 싱글톤
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File source = new File("D://contents/cheezDug.png");
String mime = application.getMimeType(source.getName());
resp.setContentType(mime);
FileInputStream fis = new FileInputStream(source);
OutputStream os = resp.getOutputStream();
byte[] buffer = new byte[1024];
int length = -1;
while((length = fis.read(buffer))!=-1){
os.write(buffer,0,length);
}
fis.close();
os.close();
}
}
이렇게 했더니
클래스에도 생긴다
배포 후 남아있는건 코드가 아니라 빌드 안의 클래시스임 그래서 저거를 쓰는거…
또 붙여넣기 한판 해주고
독베이스
저 붙여넣기 한게 아닌 이 경로의 파일들을 사용하는것!!!!
그래서 저 이미지를 쓰려면 주소가 필요
혀튼 같은파일이 세군데 있음
순서대로
웹리소스는 웹을 통해 바로 서비스되는 리소스이다
웹에서 주소를 통해 다이렉트로 접근 (왜? url 가지고있으니까)
크라이언트는 url을 이용해서 was에 접귾래서,… 웹리소스를 받아옴…
1본이나 3번에 존재하는 자원을 서비스하려면 그를 대신 읽어줄 수있느 어플맅케ㅣㅇ션이 핋요하다(WAS)
@WebServlet("/image.do")
public class ImageStreamingServlet extends HttpServlet{
private ServletContext application;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
application = getServletContext();
}
@Override
// 서블릿 컨텍스트는 싱글톤
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String srcPath = "/kr/or/ddit/images/cat1.jpg";
String filePath = this.getClass().getResource(srcPath).getFile(); // 파일시스템상 절대경로
File source = new File(filePath);
String mime = application.getMimeType(source.getName());
resp.setContentType(mime);
FileInputStream fis = new FileInputStream(source);
OutputStream os = resp.getOutputStream();
byte[] buffer = new byte[1024];
int length = -1;
while((length = fis.read(buffer))!=-1){
os.write(buffer,0,length);
}
fis.close();
os.close();
}
또는 이렇게
@WebServlet("/image.do")
public class ImageStreamingServlet extends HttpServlet{
private ServletContext application;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
application = getServletContext();
}
@Override
// 서블릿 컨텍스트는 싱글톤
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String srcPath = "/kr/or/ddit/images/cat1.jpg";
/* String filePath = this.getClass().getResource(srcPath).getFile(); // 파일시스템상 절대경로
File source = new File(filePath);*/
String mime = application.getMimeType(srcPath);
resp.setContentType(mime);
InputStream is = ImageStreamingServlet.class.getResourceAsStream(srcPath);
//FileInputStream fis = new FileInputStream(source);
OutputStream os = resp.getOutputStream();
byte[] buffer = new byte[1024];
int length = -1;
while((length = is.read(buffer))!=-1){
os.write(buffer,0,length);
}
is.close();
os.close();
}
}
웹리소스인 얘네들은 중가 ㄴ서블릿 필요없음
새로 만들기
얘도 웹 리소스에 해당한다
근데 위의 웹리소스와는 다르게 외부클라이언트의 접근이 불가능하다(web-inf아래에있어서)
웹리소스일지라도 중간객체가 필요한 부분도 있으 수 있다
inner안의걸 서비스 해보자
@WebServlet("/image.do")
public class ImageStreamingServlet extends HttpServlet{
private ServletContext application;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
application = getServletContext();
}
@Override
// 서블릿 컨텍스트는 싱글톤
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//String srcPath = "/kr/or/ddit/images/cat1.jpg";
String webPath = "/WEB-INF/inner/cat1.jpg";
// => 웹리소스... 근데 얘는 web-inf라서 접근불가... 접근 가능한애들도 있지 당연~
/*String filePath = this.getClass().getResource(srcPath).getFile(); // 파일시스템상 절대경로
File source = new File(filePath);*/
String mime = application.getMimeType(webPath);
resp.setContentType(mime);
//InputStream is = ImageStreamingServlet.class.getResourceAsStream(srcPath);
InputStream is = application.getResourceAsStream(webPath);
//FileInputStream fis = new FileInputStream(source);
OutputStream os = resp.getOutputStream();
byte[] buffer = new byte[1024];
int length = -1;
while((length = is.read(buffer))!=-1){
os.write(buffer,0,length);
}
is.close();
os.close();
}
}