Dynamic Web Project 생성하고, 

src/ 폴더 아래에는 java와 properties 파일을 

WebContent/ 폴더 아래에는 WEB-INF 폴더와 jsp, 이미지, CSS 등을 복사하시면 될 것입니다. 


Maven web프로젝트 생성시에는 

main/java/src/ 에 java 파일을 

main/java/resources/ 폴더에 properties 파일과 xml 파일을 

main/webapp/ 폴더 아래에는 WEB-INF 폴더와 jsp, 이미지, CSS 등을 복사하시면 될 것입니다. 


related:

http://www.okjsp.net/seq/244872

아프리카 방송에서 사용했던 내용입니다.

http://afreeca.com/kenuheo






JSP 시작하기

  • 시작 전 확인
    • 필요지식
      • HTML
      • Java
        • Java Server Pages
    • + - 배우는 것
      • 동적인 HTML
      • 서버 기술
      • JSP와 서블릿
        • JavaEE의 일부
    • + - JSP 트렌드
      • + - 국내 기업용 시장 장악
        • 전자정부 표준프레임워크
        • http://www.egovframe.go.kr
        • Spring + Eclipse + maven + template wizard
      • + - JavaEE 7 기능 점차 지원
        • http://www.eclipse.org/jetty/documentation/current/jetty-javaee.html
      • + - 서블릿 컨테이너 임베디드
        • Maven
        • 스프링 부트
      • + - 웹서버와 연동 없이 단독 웹 처리
        • + - 아주 초창기
          • + - 톰캣3이 느려서
            • 아파치랑 연결해서 사용
            • AJP
            • mod_jk
        • + - 톰캣4 부터
          • + - 카탈리나 엔진
            • LTE 빠름
            • 커넥터가 병목이 될 수 있다
            • 혼자써라
          • 예) OKJSP 하루 12만PV 2.2만UV 톰캣 혼자
    • + - Browser와 서버의 런타임 환경
      • request ->
      • <- response
      • JS vs JSP
        • JS와 JSP 사이에 변수 공유 
          • JSP는 서버에서 실행
          • JS는 브라우저에 실행
    • + - polyglot 다언어
      • JSP 파일 하나에
        • 6가지 문법
        • JSP
          • JSTL
            • SQL
        • Expression Language
        • Java
        • HTML
        • JavaScript
        • CSS
    • + - HTTP
      • GET
      • POST
      • 쿠키
    • + - HTML
      • + - html 기본 구조
        • DOCTYPE과 html
        • <head>
        • <body>
      • <h1> ~ <h6>
      • <p>
      • <img>
      • <form>
      • + - <input>
        • text
        • button
        • textarea
        • checkbox, radio
    • JavaScript
    • + - CSS
      • selector
      • box model
      • position
  • JSP개발환경
    • JDK
      • http://java.sun.com
      • + - 환경변수
        • JAVA_HOME
        • PATH
          • %JAVA_HOME%\bin; 추가
        • 글로벌 CLASSPATH 환경변수는 이제 안 씀
    • IDE
      • 이클립스
        • JavaEE 패키지
        • Japan Advanced ... 미러에서 다운로드
      • NetBeans
      • IntelliJ(JavaEE 기능 유료)
  • 시작하기
    • 동적으로 HTML을 만드는 법
      • Servlet
      • JSP
    • 표현식(expressions)
    • 스크립틀릿(scriptlets)
    • 지시자(directives)
    • 선언(declarations)
    • 태그
    • 세션
    • 빈(beans)
    • 태그 라이브러리  


요즘은 정말 스택오버플로우의 코드조각을 많이 참고합니다.

2000년에 만들어진 cos.jar를 보내드리고, 아파치 커먼스의 업로드 컴포넌트를 사용해 봤습니다.


https://github.com/kenu/oksample/tree/master/commons-fileup


/**
* code from: http://stackoverflow.com/questions/15432024/how-to-upload-a-file-using-commons-file-upload-streaming-api
*/
@WebServlet("/upload4")
public class UploadServlet4 extends HttpServlet {
        private static final long serialVersionUID = 1L;

        protected void doPost(HttpServletRequest request,
                        HttpServletResponse response) throws ServletException, IOException {
                PrintWriter out = response.getWriter();
                response.setHeader("Content-Type", "text/html");
                out.print("Request content length is " + request.getContentLength()
                                + "<br/>");
                out.print("Request content type is "
                                + request.getHeader("Content-Type") + "<br/>");
                boolean isMultipart = ServletFileUpload.isMultipartContent(request);
                if (isMultipart) {
                        ServletFileUpload upload = new ServletFileUpload();
                        try {
                                FileItemIterator iter = upload.getItemIterator(request);
                                FileItemStream item = null;
                                String name = "";
                                InputStream stream = null;
                                while (iter.hasNext()) {
                                        item = iter.next();
                                        name = item.getFieldName();
                                        stream = item.openStream();
                                        if (item.isFormField()) {
                                                out.write("Form field " + name + ": "
                                                                + Streams.asString(stream) + "<br/>");
                                        } else {
                                                name = item.getName();
                                                System.out.println("name==" + name);
                                                if (name != null && !"".equals(name)) {
                                                        String fileName = new File(item.getName())
                                                                        .getName();
                                                        out.write("Client file: " + item.getName()
                                                                        + " <br/>with file name " + fileName
                                                                        + " was uploaded.<br/>");
                                                        File file = new File(getServletContext()
                                                                        .getRealPath("/" + fileName));
                                                        FileOutputStream fos = new FileOutputStream(file);
                                                        long fileSize = Streams.copy(stream, fos, true);
                                                        out.write("Size was " + fileSize + " bytes <br/>");
                                                        out.write("File Path is " + file.getPath()
                                                                        + "<br/>");
                                                }
                                        }
                                }
                        } catch (FileUploadException fue) {
                                out.write("fue!!!!!!!!!");
                        }
                }
        }
}


맥에서 java8 현재 RC1을 사용하고 있는데, jsp가 컴파일이 안 되는 이슈가 있네요.


HTTP Status 500 - Unable to compile class for JSP: An error occurred at line: 1 in the generated java file The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files Stacktrace:


type Exception report

message Unable to compile class for JSP: An error occurred at line: 1 in the generated java file The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files Stacktrace:

description The server encountered an internal error (Unable to compile class for JSP: An error occurred at line: 1 in the generated java file The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files Stacktrace:) that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: 1 in the generated java file
The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files

Stacktrace:
	org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:102)
	org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:331)
	org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:469)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:378)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:353)
	org.apache.jasper.compiler.Compiler.compile(Compiler.java:340)
	org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:357)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

note The full stack trace of the root cause is available in the Apache Tomcat/7.0.28 logs.


Apache Tomcat/7.0.28

환장했습니다.

이클립스에서 톰캣의 런타임 JRE를 java7으로 강제 지정하니 잘 동작합니다.
ctrl+3 에서 runtime 으로 검색하고 Preferences > Runtime Environments 선택합니다.


톰캣을 선택하고 Edit... 버튼을 클릭합니다.


JRE: 항목이 Java SE 8로 되어 있군요. SE(시)8


Workbench default JRE 는 이클립스 워크스페이스에서 기본 지원하는 버전을 사용하는데, 그냥 맘편하게 Java SE 7 으로 지정하는 것도 나쁘지 않습니다. 기본환경이 언제 저를 배신할 지 모르기 때문이죠.


정식 Java SE 8이 나오면 제대로 잘 되기를 바래봅니다.

아, 오라클



2009년 okjsp의 6월 게릴라 세미나입니다.
이클립스 웹개발에 대한 최신 업그레이드 내용을 담았습니다.

강사: 허광남(okjsp.pe.kr 운영자)
일시: 2009년 6월 20일 오전 10:00~오전 12:00
장소: 토즈 강남대로점 (강남역6번출구 교보타워 옆건물)

회비: 20,000원(당일 현장 수납합니다.)

이클립스 웹개발 강의 목차
-. 이클립스 JEE 개발환경구축
-. 이클립스와 톰캣 DBCP의 연결
-. JPetStore 스프링,iBatis 샘플 코드 네비게이션
-. Firebug를 통한 디버깅
-. Selenium 웹UI 자동화 테스트
-. 이클립스 3.5 What's new

신청: http://www.onoffmix.com/e/kenu/925


본 강의는 실습강의가 아닙니다.
JSP tag file은 jsp spec 2.0부터 소개된 기술이죠. JSP로 서블릿을 자동생성하듯이 태그 파일로 커스텀 태그를 자동 생성해서 쓰게 됩니다.
이런 태그 파일을 이용해서 반복적으로 사용되는 Ajax함수를 자동 생성하고, 쉽게 사용할 수 있도록 설명한 글을 소개합니다.
http://www.ibm.com/developerworks/kr/library/wa-aj-simplejava1/

서블릿, 자바로 웹 애플리케이션을 만들기 위해 최초로 나온 기술입니다. 이후 JSP로 서블릿의 약점을 보완했지만, 스트럿츠, 스프링 등의 프레임워크가 득세하면서 다시 관심을 받게 됩니다. 하지만 예전처럼 순수 서블릿의 활용은 많이 없어졌습니다. 프레임워크에 종속된 개발을 많이 하게 되죠.

일단 가장 간단한 서블릿을 만들어보겠습니다. servlet이라는 Dynamic Web Project를 만들고 프로젝트 이름에서 New > Servlet 을 선택합니다. src 아래서는 Servlet 항목이 나오지 않습니다.

사용자 삽입 이미지

net.okjsp 패키지에 HelloServlet 이라고 이름을 주었습니다. *Servlet과 같이 서블릿 클래스의 명명규칙을 가져가는 것이 좋습니다.
사용자 삽입 이미지

URL mapping 이라는 것이 있습니다. 스트럿츠 이후 *.do 라는 매핑이 유명해졌는데, 서블릿 컨테이너에서 들어온 request URL의 패턴에 따라서 매칭되는 서블릿을 호출하게 됩니다. /hello 라는 URL mapping을 추가합니다.
사용자 삽입 이미지

패키지 익스플로러에 HelloServlet.java 파일이 생겼습니다.
사용자 삽입 이미지

함께 생성된 소스입니다. 일반적으로 주소를 치고 들어가는 것은 GET방식으로 호출합니다. 때문에 doGet() 이라는 메소드가 호출이 됩니다. doPost() 메소드는 form 태그에서 method="post" 와 같이 호출할 때 실행이 됩니다. POST방식의 호출이죠.
사용자 삽입 이미지

doGet() 내용을 다음과 같이 적어줍니다.

  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out.println("<h1>Hello World</h1>");
  out.close();


실행은 JSP와 동일합니다. HelloServlet 파일을 선택하고 Run As > Run on Server 로 실행합니다.

사용자 삽입 이미지

기본 매핑에 따라서 http://localhost:8080/servlet/HelloServlet 주소로 실행이 됩니다.
사용자 삽입 이미지


http://localhost:8080/servlet/hello 로 다시 접속을 해도 같은 서블릿이 실행됩니다.
사용자 삽입 이미지


서블릿의 단점이라 한다면 태그가 문자열 안에 들어가기 때문에 " 는 \" 로 표기해야하고 번잡스러워집니다. html 소스가 바뀌면 일이 커지죠. 때문에 JSP 기술이 나오게 된 것이구요.

하지만 JSP가 Javascript를 비롯해 비즈니스 로직과 프리젠테이션 코드들의 스파게티 소스로 변해가자 로직은 Servlet에서 처리하고 결과값을 JSP에서 보여주는 형식으로 즉 MVC(Model View Controller) 형태의 코드로 관리되는 쪽으로 변해왔습니다. MVC 프레임워크들의 탄생 배경이죠.

이클립스를 사용해서 개발을 하는 것은 기존 텍스트 에디터를 이용해서 작업하는 것과 많은 차이를 갖고 있다. 특히 웹 애플리케이션 개발에서는 더 많은 차이가 있게 되는데, 우선 언급해 볼 것이 서비스에 구성된 디렉토리와 개발에 사용되는 디렉토리의 차이점이다.

웹 애플리케이션은 서블릿 스펙에 따라서 디렉토리가 정해진 규칙을 갖고 있다.

/WEB-INF/ 브라우저를 통해서 접근이 불가능한 웹 애플리케이션 핵심정보들을 포함하고 있는 디렉토리
/WEB-INF/classes/ 패키지에 따른 디렉토리별 class파일과 properties 파일이 위치하는 곳
/WEB-INF/lib/ 웹 애플리케이션에서 사용되는 jar 파일이 존재하는 곳
/META-INF/context.xml 톰캣에서 사용되는 manager를 통한 배포용 웹 애플리케이션 Context정보 파일
브라우저를 통해서 접근 가능한 리소스들은 그 외의 디렉토리에 놓으면 된다.
특히 브라우저의 JVM 위에서 돌아가는 애플릿 class와 관련 jar 들은 /WEB-INF/ 밖에 위치해야 한다.
이 디렉토리들을 묶어서 Context 라고 얘기한다.

서비스와 관련된 디렉토리 구조가 위와 같고, 개발용 디렉토리 구조는 java 파일이라는 특징 때문에 다음과 같이 구성한다.

/src 패키지에 따른 디렉토리별 java 파일과 properties 파일이 존재하는 곳
/WebContent/ 앞에 언급한 브라우저를 통해서 접근 가능한 리소스들. 웹 애플리케이션의 컨텍스트 루트 디렉토리에 해당.
/WebContent/WEB-INF/ 앞에 언급했던 /WEB-INF/ 디렉토리와 같은 성격
/build/classes  /src 하위 자바파일의 컴파일된 class 들이 놓이는 곳. properties 파일은 자동 복사되는 곳.


개발 디렉토리와 WAS의 서비스되는 디렉토리의 매핑 즉 자연스런 연결은 빌드 툴인 ant를 통하거나 Eclipse같은 IDE에서 자동으로 해준다.

이클립스의 경우 Servers 라는 프로젝트가 웹 프로젝트와 별개로 생성이 된다. 여기에서 설정되는 서버의 세팅은 기본적으로 설치된 세팅과 별도로 운영된다. 즉 톰캣이 설치된 디렉토리의 conf 에 있는 설정과는 별개로 Servers하위의 서버별 server.xml 의 파일에 설정된 내용으로 동작이 된다는 뜻이다.
<%= request.getRealPath("/") %> 를 통해서 확인해 보면 이클립스에서 운영하는 디렉토리가 완전히 엉뚱한 곳에 존재함을 알 수 있다. 웹 프로젝트에서 파일을 변경하면 자동으로 파일이 해당 위치로 복사된다.


관련자료:
http://tomcat.apache.org/tomcat-4.1-doc/appdev/index.html 영문
http://www.apache-korea.org/tomcat/tomcat-4.1-doc/appdev/index.html 번역문

구걸 등의 검색결과에서 저장된 페이지는 유용합니다만 저장된 페이지의 내용이 바뀐 경우 구걸에 구걸하는 골때리는 상황이 연출됩니다.
이럴 때 해당 게시물이 404 (Not Found) 또는 410 (Gone) 으로 표시 되어야 하는데, 컨트롤러에 다음과 같은 코드를 추가했습니다.

  public void doGet(HttpServletRequest req, HttpServletResponse res)
                        throws IOException {
...
    if ("106835".equals(req.getParameter("seq"))) {
     res.sendError(404,"File Not Found");
     return;
    }

굵게 표시한 부분이 404 상태코드를 날리면서 메시지도 File Not Found 라고 표시되게 만들어줍니다. 게시물 죽은척하는 코드입니다.

확인 : http://www.okjsp.pe.kr/seq/106835

역시 웹에는 숨겨진 세상이 많습니다.

처음으로 JSP를 만들어보겠습니다. WebConent 디렉토리를 마우스 오른버튼으로 클릭해서 New > JSP 항목을 선택합니다.

JSP는 WebContent 아래 만듭니다.

JSP는 WebContent 아래 만듭니다.


New JavaServer Page 창이 뜹니다. Java하고 Server하고 찰싹 붙어있네요. 자바서버의 페이지라는 뜻이겠죠. 그래서 확장자는 자동으로 붙여줍니다. simple이라고 입력하면 .jsp는 자동으로 붙여서 파일이 생깁니다. Next 버튼을 클릭해서 다음으로 이동합니다.

확장자는 알아서 만들어 줍니다.

확장자는 알아서 만들어 줍니다.


+ Recent posts