[    JSP MVC패턴을 이용한 게시판 만들기 1(개요)    ]



 

전체적인 게시판 설게 구성도

 

클라이언트(브라우저에서의) 모든 요청은 FrontController에서 받게 되고, 요청을 받은 FrontController는 요청 분석을 해 필요한 처리르 담당하는 Command 객체를 지정하게 된다.

 

Command 객체들은 Service 인터페이스를 implements해 관리하며, 처리 요청을 받은 Command객체 내부에서는 DAO를 통해 DB에서 원하는 정보를 꺼내와 리턴하게 되고

 

꺼내온 정보를 담은 뒤 FrontController에서는 RequestDispatcher 를 이용해 forward시켜 원하는 화면(jsp 파일)으로 이동시켜 준다.

 

 

[ 테스트용 데이터베이스 구성 ]

 

STUDENT 테이블을 생성하고, mysql에서 auto_increment에 해당하는 sequence를 생성해 주도록 한다. 시퀀스는 삽입할 때마다 자동으로 컬럼을 증가시켜 넣어야하는 경우 주로 사용되는데

대표적으로 nextval : 다음에 삽입될 인덱스 번호, currval : 현재 마지막에 삽입된 인덱스 번호

등을 사용할 수 있다.

아래의 코드는 STUDENT 테이블을 생성하고 id를 기본키로 지정했고, 시퀀스를 이용해서 테스트용 데이터를 삽입했다

 

create table STUDENT(
  id varchar2(50) primary key,
  name varchar2(20) not null,
  address varchar2(100)
);

commit;

create sequence STUDENT_seq;

insert into STUDENT(id,name,address) values(STUDENT_seq.nextval,'hyr','seoul');

commit;

select * from STUDENT;

 

[    JSP FrontController 패턴, Command 패턴, RequestDispatcher를 이용한 forward에 대하여...    ]





- FrontController 패턴이란?

모든 요청을 하나의 서블릿 파일에서 받아서 처리하는 방식


- Command 패턴?

FrontController에서 받은 요청을 분석해 어떤 처리가 필요한지에 따라서 각 처리에 필요한 Command 객체를

할당해 그곳에서 처리한 뒤 필요한 데이터를 가지고 FrontContrller로 보내주고 그 데이터를 request 객체 등에

세팅해 RequestDispatcher 객체를 통해서 화면 전환시 request, response 객체를 함께 전달해주는 방식

이때, RequetDispatcher 객체의 특징!!

: 현재 페이지의 request, response 객체를 그대로 전달할 수 있다.!



- frontControllerEx.jsp
: 하나는 insert.do로 하나는 delete.do 라는 uri로 요청을 하고 있다. 단 둘 다 .do로 끝나는 패턴을 채택하고 있다.
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
     
    <a href="insert.do">insert</a>
    <a href="<%=request.getContextPath()%>/delete.do">delete</a>



- FrontController.java
.do로 끝나는 모든 요청을 받을 수 있도록 @WebServlet을 통해 서블릿 맵핑이 되어 있다.
또한, get방식이든 post 방식이든 모두 actionDo라는 메서드를 수행하도록 되어 있고 해당 메서드에서는
요청받은 uri를 가지고 와서 어떤 작업이 필요한지 command를 분석한다.

분석하고 처리에 필요한 Service를 지정해 해당 service에서는 dao에 접근해 데이터를 처리하고 FrontController로 반환해준다.
service를 통해 가지고 온 데이터는 request 객체에 저장하고
해당 requets 객체와 response객체를 데이터를 뿌려줄 화면으로 전달하기 위해
RequestDispatcher 객체를 사용해서 전달해준다.
이 객체의 특징은 현재 페이지의 request, response 객체를 그대로 전달할 수 있다는 점이다!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.java.controller;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
 
import javax.servlet.RequestDispatcher;
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("*.do") // (.do로 끝나는)모든 요청이 이 FrontController 서블릿으로 올 수 있도록 함
public class FrontController extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public FrontController() {
        super();
    }
 
    // get요청이든 post요청이든 다 이 메서드를 수행하도록 함
    private void actionDo(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        System.out.println("actionDo");
         
        // 화면으로 포워딩 시키기 위한 객체
        RequestDispatcher dispatcher = null;
         
        // 요청한 uri를 가져옴
        String uri = request.getRequestURI();
        System.out.println("uri : " + uri);
        // 컨텍스트 패스를 가져옴
        String conPath = request.getContextPath();
        // 전체 uri에서 컨텍스트 패스를 제외한 뒷 부분을 가져옴
        String command = uri.substring(conPath.length());
        System.out.println("command : " + command); // ex) /insert.do
         
        if( command.equals("/memberAll.do") ){
            response.setContentType("utf-8");
            PrintWriter writer = response.getWriter();
            writer.println("<head></head>");
             
            // memberAll 에 해당하는 요청시 해당 요청을 담당할 커맨드 객체를 지정해 줌(서비스)
            Service service = new MemberCommand();
            // 서비스에서 해당하는 데이터를 dao를 통해 가져온다.(실질 처리)
            ArrayList<StudentDTO> dtos = (ArrayList<StudentDTO>)service.execute(request, response);
             
            for(int i=0; i<dtos.size(); i++){
                StudentDTO dto = dtos.get(i);
                String name = dto.getName();
                String addr = dto.getAddress();
                int age = dto.getAge();
            }
             
            // 이런식으로 화면 전환하기 전에 request 등의 공유객체에 데이터를 세팅해주는대
            // 지금은 테스트용이라 requestName 을 임의로 지정했지만
            // 본래 service에서 가져온 데이터를 세팅해준다.
            request.setAttribute("requestName", "requestValue");
            request.setAttribute("dtos", dtos);
             
            // 화면으로 이동시키기 위한 RequestDispatcher 객체를 생성함
                // 인자로는 이동할 jsp의 uri를 넣어줌
                // RequestDispatcher의 가장 큰 특징은!!
                        // 현재 페이지의 request, response 객체를 그대로 가지고 다른 요청 페이지로 이동할 수 있다는점!!
            dispatcher = request.getRequestDispatcher("/dispatcherJsp.jsp");
            // 이동할 때 현재 페이지의 request, response 객체를 함께 전달해줌.
            dispatcher.forward(request, response);
             
             
        }else if ( command.equals("/insert.do") ){
            System.out.println("insert");
            System.out.println("------------");
        }else if( command.equals("/update.do") ){
            System.out.println("update");
            System.out.println("------------");
        }else if( command.equals("/delete.do") ){
            System.out.println("delete");
            System.out.println("------------");
        }
    }
     
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        actionDo(request,response);
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        actionDo(request,response);
    }
 
}


- Service 인터페이스
: 다형성 적인 측면과 코드의 관리적 측면 때문에 모든 커맨드 객체들을 포함할 수 있도록 Service 인터페이스를 만들고
모든 Command 객체들은 이 Service 인터페이스를 implements 하도록 구현한다. 이때 execute 메서드를 재구현 할 수 있도록
execute 메서드를 선언해 놓는다.
1
2
3
4
5
6
7
8
9
package com.java.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public interface Service {
    // 모든 커맨드 객체들이 상속해 사용하게 될 execute 메서드
    public Object execute(HttpServletRequest request, HttpServletResponse response);
}


- 각 처리에 필요한 Command 클래스 중 하나
: Service 인터페이스를 구현하고 execute 메서드를 재정의한다.
실재로 이 커맨드 객체에서 dao를 통해 DB에 접근해서 원하는 데이터를 가지고 오는 작업을 해야하지만
현재 코드에서는 생략하도록 하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.java.controller;
 
import java.util.ArrayList;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
// Service 인터페이스를 implements 해서 execute 메서드를 구현한다.
public class MemberCommand implements Service {
 
    @Override
    public Object execute(HttpServletRequest request,
            HttpServletResponse response) {
        // dao를 통한 db에 접근해 데이터들을 가지고옴...
        ArrayList<StudentDTO> dtos = null;
        // 본래 null이 아닌 dao객체를 통해 쿼리 수행을 해서 가져온 데이터를 넘긴다.
        return dtos;
    }
 
}


- FrontController에서 request 객체에 세팅한 값들을 가지고오는 페이지이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
 
    requestName : <%=request.getAttribute("requestName") %>
     
    <%
/*      // jsp페이지에서도 가능
        RequestDispatcher dispatcher = request.getRequestDispatcher("/");
        dispatcher.forward(request, response);
 */
        %>



[    JSP JSTL(Java Standard Tag Liarary)    ]


JSTL은 Java Standard Tag Libarary의 약자로

EL가 같이 사용되어 스크립트릿과 태그를 번갈아 가며 작업할 때의 불편함을 없애기 위해 나왔다.

아래는 사용 예제이다.

하지만, 그 전에 

1. http://tomcat.apache.org/taglibs/standard/ 로 들어간다.


가장 안정적인 버전은 JSTL 1.1 버전이니, 이걸 다운받도록 한다.


2. binaries를 클릭하고, 1.1.1.zip을 받는다.




 다운을 받고 압축을 풀어 lib 폴더에 들어간다.


 두 파일을 복사하여 STS 프로젝트의 WebContent 폴더안의 Web-INF 안의 lib 폴더에 복사한다.


이렇게 까지 하면 세팅 완료 이제 jstl을 사용할 수 있다.


jstl을 사용하려면 <%@taglib 을 등록해주어야 한다. 여기서는 대표적으로 코어(c) 태그 라이브러리만 예제를 사용해 보겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<!-- jstl을 사용하기 위해선 임포트한다고 생각하면 됨(필수) -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
 
    변수 정의 : <c:set var="name" value="nameValue" /><br/>
    값 출력   : <c:out value="${name}" /><br/>
    변수 제거 : <c:remove var="name"/>
                <c:out value="${name}" /><br/>
                <c:if test="${2<3}">
    조건문    :        <c:out value="${'조건문'}" /><br/>
                </c:if>
                <c:forEach var="temp" begin="1" end="10" step="2" varStatus="condi">
                    ${condi.index} : ${temp}<br/>
                </c:forEach>
 
    switch case 문 :
                <c:choose>
                    <c:when test="${1<2}">
                        1
                    </c:when>
                    <c:when test="${2<3}">
                        2
                    </c:when>
                </c:choose>
                 
    response.sendRedirect :        
                <c:redirect url="http://www.naver.com"></c:redirect>
                


[    JSP EL(Expression Language) 표현언어    ]




EL : Expression Language 표현언어로 표현식, 액션태그를 통해 출력하는 것을 좀더 편리하게 출력할 수 있도록 해준다.



예제를 보기 전에 프로젝트 전체에서 사용할 초기화 변수를 web.xml에 등록하고
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex4</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
   
  <!-- 프로젝트 초기화 파라미터 값 세팅 -->
  <context-param>
    <description>전체 프로젝트에 적용되는 초기화 파라미터</description>
    <param-name>contextParamName</param-name>
    <param-value>contextParamValue</param-value>
  </context-param>
  <!-- end of context-param -->
   
</web-app>



객체를 쉽게 가져올 수 있음을 테스트하기 위해 StudentDTO 빈즈를 만들어 놓고...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package ex4.com.java.study;
 
public class StudentDTO {
    /*
        [   자바 빈즈  ]
        : 그냥 단순히 DTO, VO 개념임...
        StudentDTO 이게 DTO이고 jsp단에서 useBean이 객체 생성
        setProperty, getProperty를 통해 값을 가져올 수 있음.
        단, 네이밍 규칙은 지켜줘야 함
    */
    private String id;
    private String name;
    private String address;
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    @Override
    public String toString() {
        return "StudentDTO [id=" + id + ", name=" + name + ", address="
                + address + "]";
    }
}



본격적인 EL 예제)
ELPractice.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    EL 이란?
        : EL은 표현식, 액션태그 등을 대신해서 출력을 편리하게 해주는 표현 언어입니다.
     
    사용 예제)
        정수 : ${10}<br/>
        실수 : ${10.56}<br/>
        문자열 : ${"abcd"}<br/>
        boolean : ${true}<br/>
        3항연산자 : ${(1<2) ? 2 : 1}<br/>
         
        <jsp:useBean id="studentDTO" class="ex4.com.java.study.StudentDTO"></jsp:useBean>
        <jsp:setProperty property="id" value="류큐규"  name="studentDTO"/>      
     
        getProperty액션 태그를 통해 dto 필드변수 값 가져오기 : <jsp:getProperty property="id" name="studentDTO"/><br/>
         
        EL을 통해 간단하게 가져오기 : ${studentDTO.id}<br/>
     
    **[EL의 내장 객체]**
     
        - applicationScope : application 내장 객체로 프로젝트 전체에서 공유된다.
        - sessionScope      : session 객체로 브라우저 마다 생성되고 공유된다.
        - pageScope          : 현재 페이지에서만 공유되는 pageContext 객체이다.
        - requestScope      : request 내장 객체
        - param                : request로 전달한 데이터를 request.getParameter("name")으로 가져오는 파라미터 값을 가져오는 객체
        - paramValues       : 체크박스처럼 다수의 값을 전달한 값을 가져올 때 사용하는 객체
        - initParam           : web.xml에서 설정한 초기화 변수 값을 가져올 때 사용하는 내장객체
         
        <%
            application.setAttribute("applicationName", "applicationVal");
            session.setAttribute("sessionName", "sessionVal");
            pageContext.setAttribute("pageName", "pageVal");
            request.setAttribute("requestName", "requestVal"); // 이건 request.getParameter로 가져오는 것과 다름
            // 이건 request.getAttributes로 가져와야함
            // 폼이나 get방식으로 쿼리에 붙여 전달하는게 getParameter고 EL로는 param 객체를 이용함
        %>
         
         
        <form action="ELPractice2.jsp" method="GET">
            이름 : <input type="text" name="name">
            <input type="submit" value="전송" />
        </form>
        



- ELPractice2.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    application 값 : ${applicationScope.applicationName }<br/>
    session 값      : ${sessionScope.sessionName }<br/>
    page 값           : ${pageScope.pageName }<br/>
    request 값      : ${requestScope.requestName }<br/> <!-- request.setAttribute로 설정한걸 가져오는 것!! -->
     
    param 값        : ${param.name } <!-- form을 통해 넘긴 데이터를 가져온다. -->
     
    initParam 값  : ${initParam.contextParamName }<!-- web.xml에 설정한 전체 프로젝트의 초기화 파라미터 값을 가져옴 -->



[ JSP 파일업로드 ]




jsp에서 파일업로드를 지원하는 라이브러리는 다양한 것들이 있지만 대표적인 것이 cos.jar이다.

해당 라이브러리를 다운받는 사이트는 http://servlets.com/cos/   에서 스크롤을 내리다보면 다운로드가 있다.

해당 파일을 다운로드해서 압축을 풀어 lib에 들어가보면 cos.jar파일이 보이는데 해당 파일을

자신의 프로젝트의 WEB-INF/lib 폴더에 넣고 동기화를 해주면 된다.


- [ 파일 업로드 폼 ] : fileUploadForm.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일 업로드 폼</title>
</head>
 
<h3>파일 업로드 폼</h3>
<center>
    <!--
        파일업로드를 위해선 반드시 method="post" enctype="Multipart/form-data"여야함!
     -->
    <form action="fileUpload.jsp" method="post" enctype="Multipart/form-data">
        올린 사람 : <input type="text" name="name" /><br/>
        제목        : <input type="text" name="subject" /><br/>
        <!--
            파일 업로드는 input type="file"로 지정한다.
         -->
        파일명1 : <input type="file" name="fileName1" /><br/>
        <input type="submit" value="전송" />  
        <input type="reset" value="취소" />
    </form>
</center>



이때, 파일을 저장할 디렉토리가 필요함으로 프로젝트 WebContent 하위에 uploadFile 폴더를 하나 만들자

이제 이 폴더에 업로드한 파일이 저장되도록 할 것인데, 프로젝트 내에 위치했다해서 워크스페이스 내에 있는 것이 아니다!!

실제 파일의 위치는 자신의 톰캣 서버 내의 프로젝트 폴더 내에 위치하고 있다는 점을 알아야한다.

만약 정확히 모르겠다면 jsp페이지에서 절대경로를 찍어보면 된다.




- fileUpload.jsp 
: 파일 업로드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<%@page import="java.io.File"%>
<%@page import="java.util.Enumeration"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<%
    // request.getRealPath("상대경로") 를 통해 파일을 저장할 절대 경로를 구해온다.
    // 운영체제 및 프로젝트가 위치할 환경에 따라 경로가 다르기 때문에 아래처럼 구해오는게 좋음
    String uploadPath = request.getRealPath("/uploadFile");
    out.println("절대경로 : " + uploadPath + "<br/>");
     
    int maxSize = 1024 * 1024 * 10; // 한번에 올릴 수 있는 파일 용량 : 10M로 제한
     
    String name = "";
    String subject = "";
     
    String fileName1 = ""; // 중복처리된 이름
    String originalName1 = ""; // 중복 처리전 실제 원본 이름
    long fileSize = 0; // 파일 사이즈
    String fileType = ""; // 파일 타입
     
    MultipartRequest multi = null;
     
    try{
        // request,파일저장경로,용량,인코딩타입,중복파일명에 대한 기본 정책
        multi = new MultipartRequest(request,uploadPath,maxSize,"utf-8",new DefaultFileRenamePolicy());
         
        // form내의 input name="name" 인 녀석 value를 가져옴
        name = multi.getParameter("name");
        // name="subject" 인 녀석 value를 가져옴
        subject = multi.getParameter("subject");
         
        // 전송한 전체 파일이름들을 가져옴
        Enumeration files = multi.getFileNames();
         
        while(files.hasMoreElements()){
            // form 태그에서 <input type="file" name="여기에 지정한 이름" />을 가져온다.
            String file1 = (String)files.nextElement(); // 파일 input에 지정한 이름을 가져옴
            // 그에 해당하는 실재 파일 이름을 가져옴
            originalName1 = multi.getOriginalFileName(file1);
            // 파일명이 중복될 경우 중복 정책에 의해 뒤에 1,2,3 처럼 붙어 unique하게 파일명을 생성하는데
            // 이때 생성된 이름을 filesystemName이라 하여 그 이름 정보를 가져온다.(중복에 대한 처리)
            fileName1 = multi.getFilesystemName(file1);
            // 파일 타입 정보를 가져옴
            fileType = multi.getContentType(file1);
            // input file name에 해당하는 실재 파일을 가져옴
            File file = multi.getFile(file1);
            // 그 파일 객체의 크기를 알아냄
            fileSize = file.length();
        }
    }catch(Exception e){
        e.printStackTrace();
    }
%>
<!--
    해당 페이지는 사용자에게 보여줄 필요가 없고 해당 정보를 전달만 해주면 되기 때문에 hidden으로 했다.
 -->
<form action="fileCheck.jsp" method="post" name="fileCheckFormName">
    <input type="hidden" value="<%=name%>" name="name" />
    <input type="hidden" value="<%=subject%>" name="subject" />
    <input type="hidden" value="<%=fileName1%>" name="fileName1" />
    <input type="hidden" value="<%=originalName1%>" name="originalName1" />
</form>
 
<!--
    a태그로 클릭시 파일체크하는 jsp페이지로 이동하도록 함
    javascript를 이용해서 onclick시 폼태그를 잡아와 submit()을 호출해 폼태그를 전송
 -->
<a href="#" onclick="javascript:document.fileCheckFormName.submit()">업로드 파일 확인하기 :<%=fileName1 %></a>




-fileCheck.jsp
: 파일 체크 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일체크 JSP 페이지</title>
</head>
 
    fileCheck jsp페이지
    <%
        // post방식에 대한 한글 인코딩 방식 지정 get방식은 서버의 server.xml에서 Connector태그에 URIEncoding="UTF-8" 추가
        request.setCharacterEncoding("UTF-8");
         
        // input type="name" 의 value값을 가져옴
        String name = request.getParameter("name");
        // input type="subject" 의 value값을 가져옴
        String subject = request.getParameter("subject");
        // 중복방지용으로 만들어져 넘겨진 파일명을 가져옴
        String fileName1 = request.getParameter("fileName1");
        // 본래의 파일명을 가져옴
        String originalName1 = request.getParameter("originalName1");
    %>
     
    <h3>업로드 파일 확인</h3>
    올린 사람 : <%=name %><br/>
    제목 : <%=subject %><br/>
     
    <!-- 파일 다운로드 링크 클릭시 다운로드 될 수 있도록 fileDown1.jsp 페이지에서 처리 뒤에 쿼리문자열을 통해 중복 방지용 이름 fileName1 값을 같이 넘겨준다. -->
    파일1 다운로드 : <a id="downA" href="#"><%=originalName1%></a>
    <script type="text/javascript">
        // 영문파일은 그냥 다운로드 클릭시 정상작동하지만 한글파일명을 쿼리문으로 날릴경우 인코딩 문제가 발생할 수 있다. 한글이 깨져 정상작동하지 않을 수 있음
        // 따라서, 쿼리문자열에 한글을 보낼 때는 항상 인코딩을 해서 보내주도록 하자.
        document.getElementById("downA").addEventListener("click", function(event) {
            event.preventDefault(); // a 태그의 기본 동작을 막음
            event.stopPropagation(); // 이벤트의 전파를 막음
            // fileName1을 utf-8로 인코딩한다.
            var fName = encodeURIComponent("<%=fileName1%>");
            // 인코딩된 파일이름을 쿼리문자열에 포함시켜 다운로드 페이지로 이동
            window.location.href = "fileDown1.jsp?file_name="+fName;
        });
    </script>








-fileDown1.jsp
: 파일 다운 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<%@page import="java.net.URLEncoder"%>
<%@page import="java.io.FileInputStream"%>
<%@page import="java.io.File"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일 다운로드 페이지</title>
</head>
 
<%
    // a태그의 href로 fileDown1.jsp?file_name="<%=fileName1 을 통해 전달한
    // 중복 방지 처리한 파일명 값을 가져온다.
    String fileName = request.getParameter("file_name");
     
    // 업로드한 폴더의 위치와 업로드 폴더의 이름을 알아야 한다.
    String savePath = "uploadFile"; // WebContent/uploadFile
    // 위의 폴더는 상대경로이고 절대경로 기준의 진짜 경로를 구해와야한다.
    String sDownPath = request.getRealPath(savePath);
     
    System.out.println("다운로드 폴더 절대 경로 위치 : " + sDownPath);
    System.out.println("fileName1 : " + fileName);
     
    // 저장되어 있는 폴더경로/저장된 파일명 으로 풀 path를 만들어준다.
        // 자바에서는 \를 표시하기 위해서는 \를 한번 더 붙여주기 때문에 \\로 해준다.
    String sFilePath = sDownPath + "\\" + fileName; // ex)c:\\uploadPath\\image.jpg
    System.out.println("sFilePath : " + sFilePath);
    // 풀 path에 대한걸 파일 객체로 인식시킨다.
    File outputFile = new File(sFilePath);
    // 저장된 파일을 읽어와 저장할 버퍼를 임시로 만들고 버퍼의 용량은 이전에 한번에 업로드할 수 있는 파일크기로 지정한다.
    byte[] temp = new byte[1024*1024*10]; // 10M
     
    // 파일을 읽어와야 함으로 inputStream을 연다.(풀패스를 가지는 파일 객체를 이용해 input스트림을 형성한다.)
    FileInputStream in = new FileInputStream(outputFile);
     
    // 유형 확인 : 읽어올 경로의 파일의 유형 -> 페이지 생성할 때 타입을 설정해야 한다.
    String sMimeType = getServletContext().getMimeType(sFilePath);
     
    System.out.println("유형 : " + sMimeType);
     
    // 지정되지 않은 유형 예외처리
    if ( sMimeType == null ){
        // 관례적인 표현
        sMimeType = "application.octec-stream"; // 일련된 8bit 스트림 형식
        // 유형이 알려지지 않은 파일에 대한 읽기 형식 지정
    }
     
    // 파일 다운로드 시작
    // 유형을 지정해 준다.
    response.setContentType(sMimeType); // 응답할 페이지가 text/html;charset=utf-8을
    // 파일 mime 타입으로 지정해 준다.
     
    // 업로드 파일의 제목이 깨질 수 있으므로 인코딩을 해준다.
    String sEncoding = new String(fileName.getBytes("euc-kr"),"8859_1");
    //String B = "utf-8";
    //String sEncoding = URLEncoder.encode(A,B);
     
    // 기타 내용을 헤더에 올려야 한다.
    // 기타 내용을 보고 브라우저에서 다운로드 시 화면에 출력시켜 준다.
    String AA = "Content-Disposition";
    String BB = "attachment;filename="+sEncoding;
    response.setHeader(AA,BB);
     
    // 브라우저에 쓰기
    ServletOutputStream out2 = response.getOutputStream();
     
    int numRead = 0;
     
    // 바이트 배열 temp의 0번부터 numRead번까지 브라우저로 출력
        // 파일이 위치한 곳에 연결된 inputStream에서 읽되 끝(-1) 전까지 while을 돈다.
    while((numRead = in.read(temp,0,temp.length)) != -1){ // temp 배열에 읽어올건데 0번째 인덱스부터 한번에 최대 temp.length 만큼 읽어온다.
        // 읽어올게 더이상 없으면 -1을 리턴하면서 while문을 빠져나감
         
        // 브라우저에 출력 : 근대 header 정보를 attachment로 해놓았음으로 다운로드가 된다.
        out2.write(temp,0,numRead); // temp배열에 있는 데이터의 0번째부터 최대 numRead만큼 출력한다.
    }
    // 자원 해제
    out2.flush();
    out2.close();
    in.close();
%>


'스터디 > JSP' 카테고리의 다른 글

JSP JSTL(Java Standard Tag Liarary)  (0) 2017.08.18
JSP EL(Expression Language) 표현언어  (0) 2017.08.16
JSP 커넥션 풀(Connection Pool)  (0) 2017.08.16
JSP DB(데이터베이스)  (0) 2017.08.14
JSP 자바 빈즈(JAVA BEANS)  (0) 2017.08.14
커넥션 풀이란?

: jsp에서 데이터베이스와 관련된 처리를 할 때 가장 오래 걸리는 부분이 커넥션(Connection)을 생성하는 부분이다.

많은 사용자들이 요청할수록 그것은 더 심한데 그럴 경우 서버가 처음 로딩될 때 미리 일정량의 Connection 객체를

커넥션 풀에 생성해 두고 그곳에서 가져다 사용하고 반납하는 개념이다.

이때, 커넥션 풀에 생성한 커넥션들을 관리하는 객체가 DataSource라는 객체이다.


구현 방법)

먼저, 서버가 로딩될 때 생성해야 함으로 server의 context.xml 파일에서 작업을 한다.



- context.xml
이곳에 아래의 소스코드를 추가한다.
driverClassName, url, username, passowrd 등은 우리가 디비 연결시 필수적으로 필요했던 항목이고
maxActive는 미리 생성해놀 커넥션의 수이다.
maxWiat의 경우 미리 생성한 커넥션 이상의 요청이 들어왔을 때 추가로 커넥션을 생성할 때 최대 기다릴 수 
있는 시간을 설정하는 것이다. 즉 timeout 을 설정
type은 커넥션을 관리하는 DataSource이다.
1
2
3
4
5
6
7
8
9
10
11
<Resource
        auth="Container"
        driverClassName = "oracle.jdbc.driver.OracleDriver"
        url="jdbc:oracle:thin:@localhost:1521:orcl"
        username="아이디"
        password="자기비밀번호"
        name="jdbc/Oracle11g"
        type="javax.sql.DataSource"
        maxActive="50"
        maxWait="1000"
    />

- db 객체를 얻어오는 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<%@page import="java.sql.Connection"%>
<%@page import="javax.sql.DataSource"%>
<%@page import="javax.naming.Context"%>
<%@page import="javax.naming.InitialContext"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<%
    // 컨텍스트 객체를 가져온다.
    Context context = new InitialContext();
    DataSource datasource = null;
    // 컨텍스트 객체에서 DataSource 객체를 찾아온다.
    datasource = (DataSource)context.lookup("java:comp/env/jdbc/Oracle11g"); // env이하에는 context.xml에서 설정한 name값이 온다.
    Connection conn = null;
    // datasource 객체에서 커넥션 객체를 가져온다.
    conn = datasource.getConnection();
    // 이후는 기존과 동일하게 사용하면 된다.
%>



'스터디 > JSP' 카테고리의 다른 글

JSP EL(Expression Language) 표현언어  (0) 2017.08.16
JSP 파일업로드  (2) 2017.08.16
JSP DB(데이터베이스)  (0) 2017.08.14
JSP 자바 빈즈(JAVA BEANS)  (0) 2017.08.14
JSP 에러페이지에 대하여...  (0) 2017.08.11
[    JSP DB(데이터베이스)    ]




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<%! // 선언부
    // 커넥션 객체 선언
    Connection conn = null;
    // 쿼리문에 대한 PreparedStatement 객체
    PreparedStatement pstmt = null;
    // 쿼리 실행 결과를 담고 있는 ResultSet 객체
    ResultSet rs = null;
     
    // 디비 접속 관련 정보
    String id = "scott"; // db 사용자 id
    String pw = "Dudfhd13"; // db 사용자 pw
    String driver = "oracle.jdbc.driver.OracleDriver"; // driver
    String url = "jdbc:oracle:thin:@localhost:1521:xe"; // db 접속 url -> localhost(주소 ip), xe-> DB이름
    String query = "insert into student(id,name,address) values(?,?,?)"; // preparedStatement를 이용할 땐 값은 ? 부분에 들어가게 됨(Statement보다 편리)
%>
 
<%
 
    try{
         
        // driver 로드
        Class.forName(driver);
        // DB Connection 객체 얻어오기
        conn = DriverManager.getConnection(url, id, pw);
        // transaction처리를 위해 자동으로 커밋되는 것을 false로 세팅
        conn.setAutoCommit(false);
        // PreparedStatement 객체 얻어오기
        PreparedStatement pstmt = conn.prepareStatement(query);
        // 위의 query에 ? 에 해당하는 곳에 값 대입 각 1,2,3은 첫번째 ? 두번째 ? 세번째 ?를 의미
        pstmt.setString(1, "firstId");
        pstmt.setString(2,"hyrName");
        pstmt.setString(3,"seoulAddress");
        // delete,update,insert 등의 작업시엔 executeUpdate()로 쿼리를 수행함 이때 처리된 튜플수가 반환됨
        // select문의 경우 executeQuery()메서드를 통해 쿼리를 수행
        int updateCnt = pstmt.executeUpdate();
        // commit
        conn.commit();
         
    }catch(Exception e){
        e.printStackTrace();
        // 처리에 실패한 경우 롤백
        conn.rollback();
    }finally{ // 자원 해제
        if ( rs != null ) rs.close();
        if ( pstmt != null ) pstmt.close();
        if ( conn != null ) conn.close();
    }
%>
 
<%
    // [ select 문으로 데이터 가져오기 ]
    try{
        Class.forName(driver);
        conn = DriverManager.getConnection(url,id,pw);
        conn.setAutoCommit(false);
        pstmt = conn.prepareStatement("select * from student");
        rs = pstmt.executeQuery();
        while(rs.next()){
            String id = rs.getString("id");
            String name = rs.getString("name");
            String addr = rs.getString("address");
            out.println("id : " + id + " name : " + name + " address : " + addr);
        }
        conn.commit();
    }catch(Exception e){
        e.printStackTrace();
        conn.rollback();
    }finally{
        if ( rs != null ) rs.close();
        if ( pstmt != null ) pstmt.close();
        if ( conn != null ) conn.close();
    }
%>


'스터디 > JSP' 카테고리의 다른 글

JSP 파일업로드  (2) 2017.08.16
JSP 커넥션 풀(Connection Pool)  (0) 2017.08.16
JSP 자바 빈즈(JAVA BEANS)  (0) 2017.08.14
JSP 에러페이지에 대하여...  (0) 2017.08.11
JSP 쿠키(cookie)에 대하여...  (0) 2017.08.11

[    JSP 자바 빈즈(JAVA BEANS)    ]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package ex4.com.java.study;
 
public class StudentDTO {
    /*
        [   자바 빈즈  ]
        : 그냥 단순히 DTO, VO 개념임...
        StudentDTO 이게 DTO이고 jsp단에서 useBean이 객체 생성
        setProperty, getProperty를 통해 값을 가져올 수 있음.
        단, 네이밍 규칙은 지켜줘야 함
    */
    private String id;
    private String name;
    private String address;
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    @Override
    public String toString() {
        return "StudentDTO [id=" + id + ", name=" + name + ", address="
                + address + "]";
    }
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <!--
        useBean 액션 태그
            : 사용할 객체를 지정하는 작업 class 속성에 명시한 클래스를 id로 지정한 이름으로 사용하겠다는 의미
            scope는 해당 객체의 유효범위를 지정함 => page, request, application 등..
     -->
    <jsp:useBean id="studentDTOId" class="ex4.com.java.study.StudentDTO" scope="page"></jsp:useBean>
     
    <!--
        setProperty 액션 태그
            : useBean에서 지정한 id에 해당하는 객체의 name 필드에 hyr을 대입함
            name 속성은 위에서 지정한 id이며
            property는 필드 변수 명
            value는 값을 의미한다.
     -->
    <jsp:setProperty property="name" value="hyr" name="studentDTOId"/>
 
    값 가져다 쓰기 : <jsp:getProperty property="name" name="studentDTOId"/><br/>

그렇다면 지금까지 살펴본 빈즈는 왜 사용하는 것일까?? 무엇인가 편리한게 있지 않을까?


그렇다. 빈즈를 이용하면 우리가 form 태그에서 input 태그 등을 이용해서 많은 값들을 submit으로 보낼 때


이러한 값들을 일일이 하나씩 request.getParameter("name") 등으로 가져오지 않고 한번에 빈즈 객체에 저장시킬 수 있다.


매우 편리하다!!


하지만, 조건이 있다. form태그에 있는 input 태그 등의 name값과 빈즈의 필드변수명이 일치해야만 한다.


아래의 예제를 보자.


-PeopleBeans 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.jsp.study;
 
public class PeopleBenas {
    // 자바 빈즈에서 필드변수명을 폼태그의 input 의 name과 일치시키면
    // 한번에 폼에서 전송한걸 세팅할 수 있음으로 이름을 같게 맞춰주자.
    private String name;
    private int age;
    private String address;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "PeopleBenas [name=" + name + ", age=" + age + ", address=" + address + "]";
    }
}


-beansMain.jsp : 폼태그가 있는 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<%
    request.setCharacterEncoding("UTF-8");
%>
    <form action="beans.jsp" method="post">
        이름 : <input type="text" name="name"/><br/>
        나이 : <input type="number" name="age" /><br/>
        주소 : <input type="address" name="address" /><br/>
        <input type="submit" value="전송" />
    </form>


-beans.jsp : 폼태그에서 서브밋해 데이터를 전달받을 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <!-- 빈즈 선언 -->
    <jsp:useBean id="peopleId" class="com.jsp.study.PeopleBenas"></jsp:useBean>
    <!--
        property에 * 를 주게 되면 폼태그에서 전달한게 한꺼번에 세팅되기 때문에 굉장히 간편하게 값을 세팅할 수 있다.
        단, 전제조건은 input의 name값과 beans class의 필드변수명들이 일치해야만 한다!!
     -->
    <jsp:setProperty property="*" name="peopleId"/>
     
    <%
        String name = peopleId.getName();
        int age = peopleId.getAge();
        String addr = peopleId.getAddress();
    %>
    이름 : <%=name %><br/>
    나이 : <%=age %><br/>
    주소 : <%=addr %><br/>



'스터디 > JSP' 카테고리의 다른 글

JSP 커넥션 풀(Connection Pool)  (0) 2017.08.16
JSP DB(데이터베이스)  (0) 2017.08.14
JSP 에러페이지에 대하여...  (0) 2017.08.11
JSP 쿠키(cookie)에 대하여...  (0) 2017.08.11
JSP에서의 세션(session)에 대해서...  (0) 2017.08.11
[    JSP 에러페이지에 대하여...    ]


jsp 페이지 처리 도중 404, 500에러 페이지가 뜨면 일반 사용자에게 불쾌감을 줄 수 있어

UI등을 꾸며놓은 친숙한 에러페이지를 띄우도록 할 수 있다.

두가지 방법이 있는데

1. page 지시자를 이용한 방법

2. web.xml에 error-page 를 등록하는 방법이 있다.

----------------------------------------------------------------------------------------------------------------------------


[  1. page 지시자의 errorPage와 isErrorPage 속성을 이용한 방법  ]
main.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!--
    [ 에러 페이지 ]
    1. page 지시자 errorPage 를 이용한 방법
    2. web.xml에 error-page 태그를 등록하는 방법
 -->
 <!-- 1
        해당 페이지에서 에러 발생시 띄워줄 에러 페이지를 page 지시자의 errorPage 속성에 명시해 준다.
  -->
<%@page errorPage="errorPage.jsp" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
 
    <%
        int num = 4/0; // 고의적으로 에러 발생시킴
    %>

errorPage.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
     
<!--
  
    에러가 발생시 띄우게 되는 페이지에는 page 지시자의 isErrorpage = "true"로 지정한다.
    지정하지 않으면 defaultfalse이기 때문에 에러페이지로 인식하지 않는다.
     
    isErrorPage를 true로 지정하면 exception 객체를 이용할 수 있게 된다.
    ex) exception.getMessage();
     
 -->   
<%@page isErrorPage="true" %>
<!--
    에러 코드 200번은 정상 페이지라는 의미인데, 가끔 자동으로 500 코드로 세팅되는 경우가 있어
    현재 에러 페이지는 정상적인 페이지다라는 세팅을 해주기 위해
    response.setStatus(200); 을 지정해 준다.
 -->
<%
    response.setStatus(200);
%>
 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
에러페이지입니다. 에러 내용은 <%=exception.getMessage() %>입니다.<br/>







[ 2. web.xml에 등록하는 방식 ]


main2.jsp

web.xml에 등록하는 방식일 때는 page지시자의 errorPage를 사용하면 안된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<!--
    web.xml을 이용해 예외페이지를 세팅할 때는 page지시자의 errorPage를 사용하면 안된다.
 -->
<a href="noPage.jsp">없는페이지 링크</a>



web.xml
error-page 태그내에 404에러일 때 띄울 페이지, 500에러일 때 띄울 페이지를 지정했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex3</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
   
  <error-page>
    <error-code>404</error-code>
    <location>/error404.jsp</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/error500.jsp</location>
  </error-page>
   
</web-app>



error404.jsp
실재 404 에러 발생시 띄울 페이지이다.
response.setStatus(200) 은 꼭 해주도록 하자. 자동으로 500으로 세팅되어 제대로 에러 페이지가 호출되지
않을 수 있기 때문
200번 상태코드는 현재 페이지가 정상적인 페이지라는 의미이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page isErrorPage="true" %>
<%
    response.setStatus(200);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
404 에러페이지입니다.



'스터디 > JSP' 카테고리의 다른 글

JSP DB(데이터베이스)  (0) 2017.08.14
JSP 자바 빈즈(JAVA BEANS)  (0) 2017.08.14
JSP 쿠키(cookie)에 대하여...  (0) 2017.08.11
JSP에서의 세션(session)에 대해서...  (0) 2017.08.11
JSP 액션 태그(forward,include,param)  (0) 2017.08.10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <%--
        [   쿠키   ]
         
        : 사용자 정보를 저장하는 것은 세션과 같지만 서버에서 생성되어 클라이언트 컴퓨터에 저장되기 때문에
        서버에 저장하는 세션에 비해 보안에 취약하고, 4kb정도의 용량으로 용량제한이 있다.
         
        http 특성상 요청하고 응답 후에 연결이 끊어지는데 연결이 끊어지고도 특정 정보를 유지하기 위해 사용된다.
 --%>
 
    <%
        // 1. 쿠키를 생성한다.(생성하며 key,value를 지정한다.)
        Cookie cookie = new Cookie("name", "황영롱");
        // 2. 유효시간을 설정한다. 쿠키가 유지되는 기간이다.(브라우저가 종료되도 해당 유효시간 동안은 유지된다.)
        cookie.setMaxAge(60 * 60 * 60); // 초단위
        // 쿠키가 적용될 경로를 지정하는데 / 해놓으면 컨텍스트패스 아래의 모든 페이지에 적용된다.
        cookie.setPath("/");
 
        // 3. response.addCookie()를 이용해 쿠키 정보를 반영한다.
        response.addCookie(cookie);
 
        // [쿠키 정보 꺼내오기]
        // request객체에서 전체 쿠키들을 가져온다.
        Cookie[] cookies = request.getCookies();
        for (int i = 0; i < cookies.length; i++) {
            if (cookies[i].getName().equals("name")) {
                String name = cookies[i].getValue();
            }
        }
 
        // [ 쿠키 삭제하기 ]
        // 쿠키삭제는 just 쿠키의 유효시간을 0으로 세팅하고 반영해주면 된다.
        cookies = request.getCookies();
        for (int i = 0; i < cookies.length; i++) {
            if (cookies[i].getName().equals("name")) {
                // 해당 쿠키를 삭제한다.
                cookies[i].setMaxAge(0); // 유효시간 0으로 세팅
                response.addCookie(cookies[i]); // 적용
            }
        }
    %>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
                                                <head>
                <script type="text/javascript">if (!window.T) { window.T = {} }
window.T.config = {"TOP_SSL_URL":"https://www.tistory.com","PREVIEW":false,"ROLE":"guest","PREV_PAGE":"","NEXT_PAGE":"","BLOG":{"id":2750468,"name":"rongscodinghistory","title":"악덕고용주의 개발 일기","isDormancy":false,"nickName":"고무곰(GomuGom)","status":"open","profileStatus":"normal"},"NEED_COMMENT_LOGIN":true,"COMMENT_LOGIN_CONFIRM_MESSAGE":"이 블로그는 로그인한 사용자에게만 댓글 작성을 허용했습니다. 지금 로그인하시겠습니까?","LOGIN_URL":"https://www.tistory.com/auth/login/?redirectUrl=http://rongscodinghistory.tistory.com/category/%25EC%258A%25A4%25ED%2584%25B0%25EB%2594%2594/JSP","DEFAULT_URL":"https://rongscodinghistory.tistory.com","USER":{"name":null,"homepage":null,"id":0,"profileImage":null},"SUBSCRIPTION":{"status":"none","isConnected":false,"isPending":false,"isWait":false,"isProcessing":false,"isNone":true},"IS_LOGIN":false,"HAS_BLOG":false,"IS_SUPPORT":false,"IS_SCRAPABLE":false,"TOP_URL":"http://www.tistory.com","JOIN_URL":"https://www.tistory.com/member/join","PHASE":"prod","ROLE_GROUP":"visitor"};
window.T.entryInfo = null;
window.appInfo = {"domain":"tistory.com","topUrl":"https://www.tistory.com","loginUrl":"https://www.tistory.com/auth/login","logoutUrl":"https://www.tistory.com/auth/logout"};
window.initData = {};
 
window.TistoryBlog = {
    basePath: "",
    token: "gk/HPpAJ+jTVNg/vu7Mt0WsUD+eakhN4KyZ3I5Ad58U+aowJCDEy0RwBVZqFVAMI"
};
var servicePath = "";
var blogURL = "";</script>
 
                 
                 
                 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
 
                <style type="text/css">.another_category {
    border: 1px solid #E5E5E5;
    padding: 10px 10px 5px;
    margin: 10px 0;
    clear: both;
}
 
.another_category h4 {
    font-size: 12px !important;
    margin: 0 !important;
    border-bottom: 1px solid #E5E5E5 !important;
    padding: 2px 0 6px !important;
}
 
.another_category h4 a {
    font-weight: bold !important;
}
 
.another_category table {
    table-layout: fixed;
    border-collapse: collapse;
    width: 100% !important;
    margin-top: 10px !important;
}
 
* html .another_category table {
    width: auto !important;
}
 
*:first-child + html .another_category table {
    width: auto !important;
}
 
.another_category th, .another_category td {
    padding: 0 0 4px !important;
}
 
.another_category th {
    text-align: left;
    font-size: 12px !important;
    font-weight: normal;
    word-break: break-all;
    overflow: hidden;
    line-height: 1.5;
}
 
.another_category td {
    text-align: right;
    width: 80px;
    font-size: 11px;
}
 
.another_category th a {
    font-weight: normal;
    text-decoration: none;
    border: none !important;
}
 
.another_category th a.current {
    font-weight: bold;
    text-decoration: none !important;
    border-bottom: 1px solid !important;
}
 
.another_category th span {
    font-weight: normal;
    text-decoration: none;
    font: 10px Tahoma, Sans-serif;
    border: none !important;
}
 
.another_category_color_gray, .another_category_color_gray h4 {
    border-color: #E5E5E5 !important;
}
 
.another_category_color_gray * {
    color: #909090 !important;
}
 
.another_category_color_gray th a.current {
    border-color: #909090 !important;
}
 
.another_category_color_gray h4, .another_category_color_gray h4 a {
    color: #737373 !important;
}
 
.another_category_color_red, .another_category_color_red h4 {
    border-color: #F6D4D3 !important;
}
 
.another_category_color_red * {
    color: #E86869 !important;
}
 
.another_category_color_red th a.current {
    border-color: #E86869 !important;
}
 
.another_category_color_red h4, .another_category_color_red h4 a {
    color: #ED0908 !important;
}
 
.another_category_color_green, .another_category_color_green h4 {
    border-color: #CCE7C8 !important;
}
 
.another_category_color_green * {
    color: #64C05B !important;
}
 
.another_category_color_green th a.current {
    border-color: #64C05B !important;
}
 
.another_category_color_green h4, .another_category_color_green h4 a {
    color: #3EA731 !important;
}
 
.another_category_color_blue, .another_category_color_blue h4 {
    border-color: #C8DAF2 !important;
}
 
.another_category_color_blue * {
    color: #477FD6 !important;
}
 
.another_category_color_blue th a.current {
    border-color: #477FD6 !important;
}
 
.another_category_color_blue h4, .another_category_color_blue h4 a {
    color: #1960CA !important;
}
 
.another_category_color_violet, .another_category_color_violet h4 {
    border-color: #E1CEEC !important;
}
 
.another_category_color_violet * {
    color: #9D64C5 !important;
}
 
.another_category_color_violet th a.current {
    border-color: #9D64C5 !important;
}
 
.another_category_color_violet h4, .another_category_color_violet h4 a {
    color: #7E2CB5 !important;
}
</style>
 
                 
<link rel="canonical" href="https://rongscodinghistory.tistory.com"/>
 
<!-- BEGIN STRUCTURED_DATA -->
<script type="application/ld+json">
    {"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":0,"item":{"@id":"https://rongscodinghistory.tistory.com/83","name":"JSP MVC패턴을 이용한 게시판 만들기 1(개요)"}},{"@type":"ListItem","position":1,"item":{"@id":"https://rongscodinghistory.tistory.com/80","name":"JSP FrontController 패턴, Command 패턴, RequestDispatcher를 이용한 forward에 대하여..."}},{"@type":"ListItem","position":2,"item":{"@id":"https://rongscodinghistory.tistory.com/79","name":"JSP JSTL(Java Standard Tag Liarary)"}},{"@type":"ListItem","position":3,"item":{"@id":"https://rongscodinghistory.tistory.com/78","name":"JSP EL(Expression Language) 표현언어"}},{"@type":"ListItem","position":4,"item":{"@id":"https://rongscodinghistory.tistory.com/77","name":"JSP 파일업로드"}},{"@type":"ListItem","position":5,"item":{"@id":"https://rongscodinghistory.tistory.com/76","name":"JSP 커넥션 풀(Connection Pool)"}},{"@type":"ListItem","position":6,"item":{"@id":"https://rongscodinghistory.tistory.com/73","name":"JSP DB(데이터베이스)"}},{"@type":"ListItem","position":7,"item":{"@id":"https://rongscodinghistory.tistory.com/72","name":"JSP 자바 빈즈(JAVA BEANS)"}},{"@type":"ListItem","position":8,"item":{"@id":"https://rongscodinghistory.tistory.com/70","name":"JSP 에러페이지에 대하여..."}},{"@type":"ListItem","position":9,"item":{"@id":"https://rongscodinghistory.tistory.com/69","name":"JSP 쿠키(cookie)에 대하여..."}},{"@type":"ListItem","position":10,"item":{"@id":"https://rongscodinghistory.tistory.com/68","name":"JSP에서의 세션(session)에 대해서..."}},{"@type":"ListItem","position":11,"item":{"@id":"https://rongscodinghistory.tistory.com/66","name":"JSP 액션 태그(forward,include,param)"}},{"@type":"ListItem","position":12,"item":{"@id":"https://rongscodinghistory.tistory.com/64","name":"JSP request,response 내장 객체"}},{"@type":"ListItem","position":13,"item":{"@id":"https://rongscodinghistory.tistory.com/63","name":"JSP 지시자(directive) : page지시자,include지시자,taglib 지시자"}},{"@type":"ListItem","position":14,"item":{"@id":"https://rongscodinghistory.tistory.com/62","name":"JSP 스크립트 요소(스크립트릿,선언식,표현식)"}},{"@type":"ListItem","position":15,"item":{"@id":"https://rongscodinghistory.tistory.com/60","name":"[ servlet 초기화 파라미터, 컨텍스트 파라미터, 서블릿 컨텍스트 리스너]"}},{"@type":"ListItem","position":16,"item":{"@id":"https://rongscodinghistory.tistory.com/58","name":"5. Servlet에서의 HTML Form태그, servlet Parameter, 한글처리"}},{"@type":"ListItem","position":17,"item":{"@id":"https://rongscodinghistory.tistory.com/56","name":"4. servlet의 라이프사이클(lifecycle)"}},{"@type":"ListItem","position":18,"item":{"@id":"https://rongscodinghistory.tistory.com/55","name":"3. servlet의 doGet(), doPost()와 PrintWriter 객체"}},{"@type":"ListItem","position":19,"item":{"@id":"https://rongscodinghistory.tistory.com/53","name":"2. [ Servlet Mapping에 관하여... ]"}},{"@type":"ListItem","position":20,"item":{"@id":"https://rongscodinghistory.tistory.com/52","name":"1. [ JSP 웹 기본 지식 및 작동 원리 ]"}}]}
</script>
<!-- END STRUCTURED_DATA -->
<link rel="stylesheet" type="text/css" href="//t1.daumcdn.net/tistory_admin/www/style/top/font.css"/>
 
                 
                </head>
<body>
<!--
    [   session ]
    : 사용자 정보를 저장한다. 서버에 저장한다. 용량 제한이 거의 없다. 세션보다 보안에 좋다.(쿠키는 클라이언트에 저장되어 서버요청시 네트워크를 통해
이동하기 때문에 중간에 와이어샤크 등으로 가져갈 수 있기 때매 보안에 안좋음...)
         
        웹브라우저가 기본 단위이다. 따라서 브라우저마다 세션이 생성된다.
        브라우저 종료시 소멸된다.
        브라우저 종료시에도 특정 정보를 계속 유지하려면 캐쉬를 사용하자.
 -->
    <%
        // request 객체를 통해 세션을 얻을 수도 있고...
        HttpSession mySession = request.getSession();
        // jsp에서는 바로 내장 session 객체를 통해 접근하면 된다.
         
        // 세션에 key,value 식으로 데이터를 저장할 수 있는대, 이때 key(String), value(Object)타입이다.
        session.setAttribute("age", 28);
        session.setAttribute("name", "hyr");
         
        // 브라우저만 같으면 다른 페이지에서 세션은 공유되기 때문에 다른 페이지에서 아래와 같은 getAttribute 메서드를 이용해 값을 꺼낼 수 있다.
        Object age = session.getAttribute("age");
        int ageVal = Integer.parseInt(age.toString());
        String name = (String)session.getAttribute("name");
        // 한번에 세션에 있는 전체 key들 가져오기
        Enumeration e = session.getAttributeNames();
        while(e.hasMoreElements()){
            String key = (String)e.nextElement();
            Object sessionVal = session.getAttribute(key);
        }
         
        // 세션의 고유 아이디 얻기
        String sessionId = session.getId();
         
        // 세션 유효시간 설정
        // 이렇게하거나 또는 web.xml에서 세션 timeout을 설정할 수도 있다.
        session.setMaxInactiveInterval(60*60);
         
        // [세션 삭제]
                // 세션의 특정 속성만 삭제하기
                session.removeAttribute("age");
                // 모든 세션 삭제하기
                session.invalidate();
    %>
 
                <div style="margin:0; padding:0; border:none; background:none; float:none; clear:none; z-index:0"></div>
<script type="text/javascript">window.roosevelt_params_queue = window.roosevelt_params_queue || [{channel_id: 'dk', channel_label: '{tistory}'}]</script>
<script type="text/javascript" src="//t1.daumcdn.net/midas/rt/dk_bt/roosevelt_dk_bt.js" async="async"></script>
 
                 
                <script>window.tiara = {"svcDomain":"user.tistory.com","section":"기타","trackPage":"글뷰_보기","page":"글뷰","key":"2750468","customProps":{"userId":"0","blogId":"2750468","entryId":"null","role":"guest","trackPage":"글뷰_보기","filterTarget":false},"entry":null,"kakaoAppKey":"3e6ddd834b023f24221217e370daed18","appUserId":"null"}</script>
<script src="https://t1.daumcdn.net/tistory_admin/frontend/tiara/v1.0.5/polyfills-legacy.js" nomodule="true" defer="true"></script>
<script src="https://t1.daumcdn.net/tistory_admin/frontend/tiara/v1.0.5/index-legacy.js" nomodule="true" defer="true"></script>
 
                </body>
</html>
actionTag.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
<!--
    [   액션 태그   ]
    1. forward 액션 태그
        : 현재 페이지에서 다른 페이지로 이동시킬 때 사용한다. 단! response.sendRedirect()와는 달리
            !! 페이지를 이동해도 URL이 바끼지 않고 페이지 이동 전 URL상태로 남아있게 되는게 특징이다.
            ex) A페이지에서 B페이지로 이동해도 주소창에는 A페이지 주소임
    2. include 액션 태그
        : include 지시자와 달리 동적으로 페이지에 소스코드를 붙여넣는 효과
        : forward와 include 액션 태그는 param 액션 태그를 통해 데이터를 전달할 수 있다.
    3. param 액션 태그
 -->
  
    <!-- 1. forward 액션 태그 -->
    <jsp:forward page="forward01.jsp">
        <!-- param을 통해 forward01.jsp로 age,name을 전달하고 있고, 해당 forward01.jsp에서는
            request.getParameter("age")등을 통해 데이터를 꺼내올 수 있다.
         -->
        <jsp:param value="28" name="age"/>
        <jsp:param value="이름" name="name"/>
    </jsp:forward>
     
    <!-- 2. include 액션 태그 -->
    <jsp:include page="include02.jsp" flush="false">
        <jsp:param value="seoul" name="local"/>
    </jsp:include>
     
    아래는 그대로 actionTag.jsp 페이지 내용이 바로 오게 된다.


forward01.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <%
        String age = request.getParameter("age");
        int ages = Integer.parseInt(age);
        String name = request.getParameter("name");
    %>
    <%=name %> : <%=age %>


include02.jsp
1
2
3
4
5
6
7
8
9
10
11
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    include02.jsp 페이지입니다.
    전달받은 값은 : <%=request.getParameter("local") %>입니다.



request 내장 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <%--
        [ request 내장 객체 ]
        : Client가 서버로 요청하는 것에 관한 다양한 정보를 제공하고,
            페이지간 이동시 파라미터 전달에 이용된다.
     --%>
     <%
        // post 방식에 대한 한글처리
        request.setCharacterEncoding("utf-8");
        // 요청한 url에 대한 컨텍스트 패스를 가져온다.  
        String contextPath = request.getContextPath();
        // 쿠키 정보를 가져온다.
        Cookie[] cookies = request.getCookies();
        // get,post,put,patch,delete와 같은 요청 방식을 가져온다.
        String getOrPost = request.getMethod();
        // 프로토콜 정보
        String protocol = request.getProtocol();
        // 요청 url 정보
        StringBuffer requestURL = request.getRequestURL();
        // 요청 uri 정보
        // url vs uri => url은 전체 주소이고 uri는 컨텍스트 패스 이하의 경로
        String requestURI = request.getRequestURI();
        // ?name="" 와 같은 쿼리 문자열 정보를 가져온다.
        String queryParam = request.getQueryString();
        out.println("요청 url 정보 : " + requestURL + "?" + queryParam);
         
         
        // form 태그의 name에 지정한 값 및 다른 페이지에서 전달한 변수를 request 객체를 통해 가져오기
        // getParameter("name값");
        String firstNameVal = request.getParameter("firstName");
        // getParameter("name값") => 체크박스처럼 하나의 name으로 여러 값이 전달되는 경우
        String[] hobbys = request.getParameterValues("hobbys");
        // getParameterNames() => 전달한 모든 name값들을 가져옴
        Enumeration e = request.getParameterNames();
        while(e.hasMoreElements()){
            String names = (String)e.nextElement();
            String val = request.getParameter(names);
            out.println("name값 : " + names + " 에 해당하는 값 : " + val);
        }
     %>


response 내장 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <%--
        [   response 객체   ]
        : 응답과 관련된 객체
     --%>
     <%
        response.setCharacterEncoding("utf-8");
        response.getCharacterEncoding();
        // response.addCookie(쿠키명); 쿠키를 반영
         
        // sendRedirect("이동하고자 하는 url")
        response.sendRedirect("http://www.google.com");
         
        String str = request.getParameter("age");
        int age = Integer.parseInt(str);
        if ( age >= 20){
            response.sendRedirect("pass.jsp?age="+age);
            // age를 쿼리문자열로 넘겼음으로 pass.jsp에서는 request 객체를 통해 age값을 꺼내올 수 있다.
        }else{
            response.sendRedirect("ng.jsp?age=" + age);
        }
     %>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!--
        [   지시자   ]
        1. page 지시자
            : 페이지 관련 설정
        2. include 지시자
            : 정적으로 다른 페이지를 현재 페이지에 추가할 때 사용(해당 페이지의 코드가 현재 페이지에 그대로 삽입된다 보면 됨.)
        3. taglib 지시자
            : jstl을 사용하기 위해 지정(jstl 부분에서 자세히 설명)
 -->
 <!-- [1. 페이지 지시자 ]
        대표 속성)
            - contentType : 응답할 html형식과 인코딩 형식 지정 -> text/html;charset=utf-8
            - pageEncoding : 현재 코드를 작성하고 있는 문서의 인코딩 방식을 지정
            - session : 현재 페이지에서 세션 사용 유무를 지정
            - import : java에서의 import와 같음
            - errorPage : 현재 페이지 처리 도중 에러가 발생시 띄울 에러 페이지를 지정한다.
            - isErrorPage : 현재 페이지가 에러 페이지가 맞는지 아닌지를 지정한다.(true/false)
            에러페이지를 지정할 때는
                현재 페이지에 errorPage 속성으로 띄울 에러 페이지를 지정하고,
                실재 에러 페이지에서는 isErrorPage = true를 설정해 주어야 한다.
  -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="true"%>
<%@page import="java.util.Arrays"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    <%
        int[] arr = {1,2,3,4};
        out.println(Arrays.toString(arr));
    %>
<!--    
    2. [include 지시자]
        : 정적으로 해당 부분에 다른 페이지의 소스코드가 그대로 붙는다고 생각하면 된다.
        주로, 변하지 않는 헤더와 푸터에 사용된다.
        단, 동적으로 소스코드를 붙일 수 있는 include 액션 태그처럼 파라미터를 전달할 수는 없다. 
-->
    <%@include file="include01.jsp"%><br/>
     
    이 아래는 다시 현재 페이지 내용이 이어서 붙는다.<br/>
 
     <!--
        이 주석은 HTML 주석으로 브라우저 관리자 도구를 통해 보면 해당 주석은 볼 수 있다.
     -->
     <%-- 이 주석은 JSP용 주석으로 서버 사이드 주석으로서 관리도구를 통해 볼 수 없다. --%>

include01.jsp
1
2
3
4
5
6
7
8
9
10
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
 
    이 페이지는 include01.jsp 페이지 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
                                                <head>
                <script type="text/javascript">if (!window.T) { window.T = {} }
window.T.config = {"TOP_SSL_URL":"https://www.tistory.com","PREVIEW":false,"ROLE":"guest","PREV_PAGE":"","NEXT_PAGE":"","BLOG":{"id":2750468,"name":"rongscodinghistory","title":"악덕고용주의 개발 일기","isDormancy":false,"nickName":"고무곰(GomuGom)","status":"open","profileStatus":"normal"},"NEED_COMMENT_LOGIN":true,"COMMENT_LOGIN_CONFIRM_MESSAGE":"이 블로그는 로그인한 사용자에게만 댓글 작성을 허용했습니다. 지금 로그인하시겠습니까?","LOGIN_URL":"https://www.tistory.com/auth/login/?redirectUrl=http://rongscodinghistory.tistory.com/category/%25EC%258A%25A4%25ED%2584%25B0%25EB%2594%2594/JSP","DEFAULT_URL":"https://rongscodinghistory.tistory.com","USER":{"name":null,"homepage":null,"id":0,"profileImage":null},"SUBSCRIPTION":{"status":"none","isConnected":false,"isPending":false,"isWait":false,"isProcessing":false,"isNone":true},"IS_LOGIN":false,"HAS_BLOG":false,"IS_SUPPORT":false,"IS_SCRAPABLE":false,"TOP_URL":"http://www.tistory.com","JOIN_URL":"https://www.tistory.com/member/join","PHASE":"prod","ROLE_GROUP":"visitor"};
window.T.entryInfo = null;
window.appInfo = {"domain":"tistory.com","topUrl":"https://www.tistory.com","loginUrl":"https://www.tistory.com/auth/login","logoutUrl":"https://www.tistory.com/auth/logout"};
window.initData = {};
 
window.TistoryBlog = {
    basePath: "",
    token: "gk/HPpAJ+jTVNg/vu7Mt0WsUD+eakhN4KyZ3I5Ad58U+aowJCDEy0RwBVZqFVAMI"
};
var servicePath = "";
var blogURL = "";</script>
 
                 
                 
                 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
 
                <style type="text/css">.another_category {
    border: 1px solid #E5E5E5;
    padding: 10px 10px 5px;
    margin: 10px 0;
    clear: both;
}
 
.another_category h4 {
    font-size: 12px !important;
    margin: 0 !important;
    border-bottom: 1px solid #E5E5E5 !important;
    padding: 2px 0 6px !important;
}
 
.another_category h4 a {
    font-weight: bold !important;
}
 
.another_category table {
    table-layout: fixed;
    border-collapse: collapse;
    width: 100% !important;
    margin-top: 10px !important;
}
 
* html .another_category table {
    width: auto !important;
}
 
*:first-child + html .another_category table {
    width: auto !important;
}
 
.another_category th, .another_category td {
    padding: 0 0 4px !important;
}
 
.another_category th {
    text-align: left;
    font-size: 12px !important;
    font-weight: normal;
    word-break: break-all;
    overflow: hidden;
    line-height: 1.5;
}
 
.another_category td {
    text-align: right;
    width: 80px;
    font-size: 11px;
}
 
.another_category th a {
    font-weight: normal;
    text-decoration: none;
    border: none !important;
}
 
.another_category th a.current {
    font-weight: bold;
    text-decoration: none !important;
    border-bottom: 1px solid !important;
}
 
.another_category th span {
    font-weight: normal;
    text-decoration: none;
    font: 10px Tahoma, Sans-serif;
    border: none !important;
}
 
.another_category_color_gray, .another_category_color_gray h4 {
    border-color: #E5E5E5 !important;
}
 
.another_category_color_gray * {
    color: #909090 !important;
}
 
.another_category_color_gray th a.current {
    border-color: #909090 !important;
}
 
.another_category_color_gray h4, .another_category_color_gray h4 a {
    color: #737373 !important;
}
 
.another_category_color_red, .another_category_color_red h4 {
    border-color: #F6D4D3 !important;
}
 
.another_category_color_red * {
    color: #E86869 !important;
}
 
.another_category_color_red th a.current {
    border-color: #E86869 !important;
}
 
.another_category_color_red h4, .another_category_color_red h4 a {
    color: #ED0908 !important;
}
 
.another_category_color_green, .another_category_color_green h4 {
    border-color: #CCE7C8 !important;
}
 
.another_category_color_green * {
    color: #64C05B !important;
}
 
.another_category_color_green th a.current {
    border-color: #64C05B !important;
}
 
.another_category_color_green h4, .another_category_color_green h4 a {
    color: #3EA731 !important;
}
 
.another_category_color_blue, .another_category_color_blue h4 {
    border-color: #C8DAF2 !important;
}
 
.another_category_color_blue * {
    color: #477FD6 !important;
}
 
.another_category_color_blue th a.current {
    border-color: #477FD6 !important;
}
 
.another_category_color_blue h4, .another_category_color_blue h4 a {
    color: #1960CA !important;
}
 
.another_category_color_violet, .another_category_color_violet h4 {
    border-color: #E1CEEC !important;
}
 
.another_category_color_violet * {
    color: #9D64C5 !important;
}
 
.another_category_color_violet th a.current {
    border-color: #9D64C5 !important;
}
 
.another_category_color_violet h4, .another_category_color_violet h4 a {
    color: #7E2CB5 !important;
}
</style>
 
                 
<link rel="canonical" href="https://rongscodinghistory.tistory.com"/>
 
<!-- BEGIN STRUCTURED_DATA -->
<script type="application/ld+json">
    {"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":0,"item":{"@id":"https://rongscodinghistory.tistory.com/83","name":"JSP MVC패턴을 이용한 게시판 만들기 1(개요)"}},{"@type":"ListItem","position":1,"item":{"@id":"https://rongscodinghistory.tistory.com/80","name":"JSP FrontController 패턴, Command 패턴, RequestDispatcher를 이용한 forward에 대하여..."}},{"@type":"ListItem","position":2,"item":{"@id":"https://rongscodinghistory.tistory.com/79","name":"JSP JSTL(Java Standard Tag Liarary)"}},{"@type":"ListItem","position":3,"item":{"@id":"https://rongscodinghistory.tistory.com/78","name":"JSP EL(Expression Language) 표현언어"}},{"@type":"ListItem","position":4,"item":{"@id":"https://rongscodinghistory.tistory.com/77","name":"JSP 파일업로드"}},{"@type":"ListItem","position":5,"item":{"@id":"https://rongscodinghistory.tistory.com/76","name":"JSP 커넥션 풀(Connection Pool)"}},{"@type":"ListItem","position":6,"item":{"@id":"https://rongscodinghistory.tistory.com/73","name":"JSP DB(데이터베이스)"}},{"@type":"ListItem","position":7,"item":{"@id":"https://rongscodinghistory.tistory.com/72","name":"JSP 자바 빈즈(JAVA BEANS)"}},{"@type":"ListItem","position":8,"item":{"@id":"https://rongscodinghistory.tistory.com/70","name":"JSP 에러페이지에 대하여..."}},{"@type":"ListItem","position":9,"item":{"@id":"https://rongscodinghistory.tistory.com/69","name":"JSP 쿠키(cookie)에 대하여..."}},{"@type":"ListItem","position":10,"item":{"@id":"https://rongscodinghistory.tistory.com/68","name":"JSP에서의 세션(session)에 대해서..."}},{"@type":"ListItem","position":11,"item":{"@id":"https://rongscodinghistory.tistory.com/66","name":"JSP 액션 태그(forward,include,param)"}},{"@type":"ListItem","position":12,"item":{"@id":"https://rongscodinghistory.tistory.com/64","name":"JSP request,response 내장 객체"}},{"@type":"ListItem","position":13,"item":{"@id":"https://rongscodinghistory.tistory.com/63","name":"JSP 지시자(directive) : page지시자,include지시자,taglib 지시자"}},{"@type":"ListItem","position":14,"item":{"@id":"https://rongscodinghistory.tistory.com/62","name":"JSP 스크립트 요소(스크립트릿,선언식,표현식)"}},{"@type":"ListItem","position":15,"item":{"@id":"https://rongscodinghistory.tistory.com/60","name":"[ servlet 초기화 파라미터, 컨텍스트 파라미터, 서블릿 컨텍스트 리스너]"}},{"@type":"ListItem","position":16,"item":{"@id":"https://rongscodinghistory.tistory.com/58","name":"5. Servlet에서의 HTML Form태그, servlet Parameter, 한글처리"}},{"@type":"ListItem","position":17,"item":{"@id":"https://rongscodinghistory.tistory.com/56","name":"4. servlet의 라이프사이클(lifecycle)"}},{"@type":"ListItem","position":18,"item":{"@id":"https://rongscodinghistory.tistory.com/55","name":"3. servlet의 doGet(), doPost()와 PrintWriter 객체"}},{"@type":"ListItem","position":19,"item":{"@id":"https://rongscodinghistory.tistory.com/53","name":"2. [ Servlet Mapping에 관하여... ]"}},{"@type":"ListItem","position":20,"item":{"@id":"https://rongscodinghistory.tistory.com/52","name":"1. [ JSP 웹 기본 지식 및 작동 원리 ]"}}]}
</script>
<!-- END STRUCTURED_DATA -->
<link rel="stylesheet" type="text/css" href="//t1.daumcdn.net/tistory_admin/www/style/top/font.css"/>
 
                 
                </head>
                                <body>
                 
                 
    <!--
        [ JSP 스크립트 요소 ]
        1. 스크립트릿 : jsp페이지 내에 자바 코드를 사용하기 위해 사용
        2. 선언식 : 전역변수, 함수를 선언하기 위해 사용
        3. 표현식 : 변수 출력 용(표현식은 끝에 ; 를 쓰지 않는다.)
     -->
     <%!
        // [선언식]
        int sum = 0;
     %>
     <%
        // [스크립트릿]
        for(int i=0; i<10; i++){
            sum += i;
        }
      
        out.println("out 내장객체를 이용한 문서 출력 : " + sum);
     %>
      
     표현식 : <%=sum %><br/>
 
                <div style="margin:0; padding:0; border:none; background:none; float:none; clear:none; z-index:0"></div>
<script type="text/javascript">window.roosevelt_params_queue = window.roosevelt_params_queue || [{channel_id: 'dk', channel_label: '{tistory}'}]</script>
<script type="text/javascript" src="//t1.daumcdn.net/midas/rt/dk_bt/roosevelt_dk_bt.js" async="async"></script>
 
                 
                <script>window.tiara = {"svcDomain":"user.tistory.com","section":"기타","trackPage":"글뷰_보기","page":"글뷰","key":"2750468","customProps":{"userId":"0","blogId":"2750468","entryId":"null","role":"guest","trackPage":"글뷰_보기","filterTarget":false},"entry":null,"kakaoAppKey":"3e6ddd834b023f24221217e370daed18","appUserId":"null"}</script>
<script src="https://t1.daumcdn.net/tistory_admin/frontend/tiara/v1.0.5/polyfills-legacy.js" nomodule="true" defer="true"></script>
<script src="https://t1.daumcdn.net/tistory_admin/frontend/tiara/v1.0.5/index-legacy.js" nomodule="true" defer="true"></script>
 
                </body>
</html>

[ servlet 초기화 파라미터, 컨텍스트 파라미터, 서블릿 컨텍스트 리스너]


1. 서블릿 초기화 파라미터

: 특정 서블릿에서만 사용될 수 있는 초기화 파라미터를 지정해서 가져다 사용할 수 있다.

2가지 방법)

1) web.xml의 servlet 태그 내에 정의하기

servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
   
  <servlet>
    <servlet-name>ServletInitParam</servlet-name>
    <servlet-class>com.jsp.study.ServletConfigTest</servlet-class>
    <init-param>
      <param-name>id</param-name>
      <param-value>sooingkr</param-value>
    </init-param>
    <init-param>
      <param-name>pw</param-name>
      <param-value>abcd</param-value>
    </init-param>
    <init-param>
      <param-name>path</param-name>
      <param-value>c:\</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletInitParam</servlet-name>
    <url-pattern>/ServletConfigTest</url-pattern>
  </servlet-mapping>
   
</web-app>

web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.jsp.study;
 
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;
 
public class ServletConfigTest extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public ServletConfigTest() {
        super();
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet");
         
        // [ 1. web.xml에 특정 servlet에 있는 init-param(서블릿 초기화 변수) 으로 설정한 값들 가져오기 ]
        String id = getInitParameter("id");
        String pw = getInitParameter("pw");
        String path = getInitParameter("path");
        ///////////////////////////////////////////////////////////////
        response.setContentType("text/html;charset=utf-8");
        System.out.println("id : " + id + " pw : " + pw + " path : " + path);
     
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
 
}



2) 어노테이션으로 @WebServlet(initParams={@WebInitParam(name="",value="")} 방식으로 지정하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.jsp.study;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
// 2. [ 어노테이션을 이용한 초기화 파라미터를 지정하는 방법 ] : initParams = {@WebInitParam(name="",value="")}
@WebServlet(urlPatterns={"/ServletInitParamAnno"}, initParams={@WebInitParam(name="id",value="aaaa")
,@WebInitParam(name="pw",value="pwValue")})
public class ServletInitParamAnno extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public ServletInitParamAnno() {
        super();
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = getInitParameter("id");
        String pw = getInitParameter("pw");
        System.out.println("id : " + id + " pw : " + pw);
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}



2. 모든 Servlet에서 사용할 수 있는 초기화 변수 설정하기(컨텍스트 파라미터)

: web.xml에 context-param 태그 내에 선언한다.

서블릿에서 가져다 사용할 때는 getServletContext() 를 가져온 뒤 getInitParameter("")을 사용해 값을 꺼내온다.

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!-- 모든 서블릿에서 사용할 수 있는 컨텍스트 파라미터 지정 -->
  <context-param>
    <param-name>contextParamId</param-name>
    <param-value>contextId</param-value>
  </context-param>
  <context-param>
    <param-name>contextParamPw</param-name>
    <param-value>contextParamPw</param-value>
  </context-param>
   
  <servlet>
    <servlet-name>ServletInitParam</servlet-name>
    <servlet-class>com.jsp.study.ServletConfigTest</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletInitParam</servlet-name>
    <url-pattern>/ServletConfigTest</url-pattern>
  </servlet-mapping>
</web-app>
servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.jsp.study;
 
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;
 
public class ServletConfigTest extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public ServletConfigTest() {
        super();
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet");
         
        // [ 모든 서블릿에서 공통으로 접근할 수 있는 컨텍스트 파라미터 가져오기 ]
        String paramId = getServletContext().getInitParameter("contextParamId");
        String paramPw = getServletContext().getInitParameter("contextParamPw");
        System.out.println("contextId : " + paramId + " contextPw : " + paramPw);
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
 
}





3. ServletContextListener 를 이용한 어플리케이션 시작과 종료 감시

: web.xml에 listener를 등록해 놓으면 어플리케이션 시작과 종료시에 contextDestroyed 메서드와

contextInitialized 메서드가 호출된다.

이는 각 서블릿의 init() 메서드보다 먼저 호출되는 것이며
최종적으로 destroy() 메서드보다 이후에 호출된다.

구현 방식은
ServletContextListener 인터페이스를 implement해서 클래스를 작성하고
해당 클래스를 web.xml에 리스너 태그 내에 등록한다.
servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.jsp.study;
 
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
 
public class ServletListenerTest implements ServletContextListener {
 
    @Override
    public void contextDestroyed(ServletContextEvent paramServletContextEvent) {
        // 어플리케이션 실행이 종료될 때 호출된다.
        System.out.println("contextDestroyed");
        // 서블릿의 destroy() 메서드가 호출된 이후에 최종적으로 어플리케이션 종료 때 호출됨.
    }
 
    @Override
    public void contextInitialized(ServletContextEvent paramServletContextEvent) {
        // 어플리케이션 실행될 때 호출된다. 즉, 각 서블릿의 init() 메서드가 호출되기 전에 호출됨
        System.out.println("contextInitialized");
    }
 
}
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <listener>
    <description>서블릿 리스너를 등록합니다. 어플리케이션의 시작과 종료를 감시함</description>
    <listener-class>com.jsp.study.ServletListenerTest</listener-class>
  </listener>
   
</web-app>





[HTML form 태그]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
 
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
 
    <form action="FormEx" method="post">
        이름 : <input type="text" name="name" size="10"/><br/>
        아이디 : <input type="text" name="id" size="10"/><br/>
        비밀번호 ; <input type="password" name="pw" size='10' /><br/>
        취미 : <input type="checkbox" name="hobby" value="read"/><br/>
        <input type="checkbox" name="hobby" value="cook"/>요리
        <input type="checkbox" name="hobby" value="run"/>조깅
        <input type="checkbox" name="hobby" value="swim"/>수영
        <input type="checkbox" name="hobby" value="sleep"/>취침
         
        <input type="radio" name="major" value="kor"/>국어
            <!-- checked="checked" : default로 체크되도록... -->
        <input type="radio" name="major" value="eng" checked="checked"/>영어
        <input type="radio" name="major" value="mat"/>수학
        <input type="radio" name="major" value="des"/>디자인
         
        <select name="protocol">
            <option value="http">http</option>
            <!-- selected="selected" : default로 선택된 상태이도록... -->
            <option value="ftp" selected="selected">ftp</option>
            <option value="smtp">smtp</option>
            <option value="pop">pop</option>
        </select>
         
        <input type="submit" value="전송" />
        <!-- type="reset" : 취소 -->
        <input type="reset" value="취소" />
    </form>



[Servlet]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.jsp.study;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
 
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("/FormEx")
public class FormEx extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public FormEx() {
        super();
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet");
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         
        System.out.println("doPost");
         
        // [ 한글처리 ]
        // 1."post"로 사용자가 서버로 요청한 문자열을 utf-8로 인코딩
        request.setCharacterEncoding("utf-8");
        // 2."get"방식 요청에 따른 한글처리는
        /*
         * server.xml 수정필요
         * <Connector URIEncoding="utf-8" 부분을 추가 />
         */
         
        // form태그내의 name에 해당하는 값들을 가지고옴 return타입은 String
        // request.getParameter("name");
        String name = request.getParameter("name");
        String id = request.getParameter("id");
        String pw = request.getParameter("pw");
         
        // request.getParameterValues("name"); => return String[] : checkbox등에 사용
        String[] hobbys = request.getParameterValues("hobby");
        String major = request.getParameter("major");
        String protocol = request.getParameter("protocol");
         
        // request.getParameterNames() : 넘긴 name값을 Enumeration 타입으로 반환함
        Enumeration<String> values = request.getParameterNames();
        while(values.hasMoreElements()){
            String param = values.nextElement();
            System.out.println(request.getParameter(param));
        }
         
        // 응답 문서 인코딩 타입 지정
        response.setContentType("text/html;charset=utf-8");
         
        // 문서 출력 스트림 객체 얻기
        PrintWriter writer = response.getWriter();
         
        writer.println("<head></head>");
        writer.println("이름 : " + name + "<br/>");
        writer.println("아이디 : " + id + "<br/>");
        writer.println("비밀번호 : " + pw + "<br/>");
        writer.println("취미 : " + Arrays.toString(hobbys) + "<br/>");
        writer.println("전공 : " + major + "<br/>");
        writer.println("프로토콜 : " + protocol + "<br/>");
        writer.println("");
        // 자원 해제
        writer.close();
 
    }
 
}



[    servlet의 라이프사이클(lifecycle)    ]




해당 jsp 페이지 요청시 servlet java 파일로 변환을 하고 컴파일 해 servlet class로 만들고 해당 객체를 생성하는데
한번 객체가 생성되고 나면 이후 다른 Client 요청은 멀티 쓰레드로 처리하게 된다.


Servlet의 라이프 사이클)

Servlet 객체 생성         -   최초 한번 생성
    |
@PostConstructor 호출 -   생성자 이후, init 메서드 이전에 호출
    |  
init() 메서드 호출         -   최초 한번 호출
    |
doGet()/doPost() 호출   -   요청시마다 호출
    |
destroy() 호출             -    마지막 한번(자원 해제)
    |
@PreDestroy 호출        -   destroy() 이후 호출


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.jsp.study;
 
import java.io.IOException;
 
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
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("/LifeCycleServlet")
public class LifeCycleServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public LifeCycleServlet() {
        super();
    }
 
    // 생성자 이후, init() 호출 직전에 호출된다.
    @PostConstruct
    public void postConstructMethod(){
        System.out.println("PostConstruct 호출");
    }
     
    // destroy() 호출 이후에 호출된다.
    @PreDestroy
    public void preDestroyMethod(){
        System.out.println("PreDestroy 호출");
    }
     
    /*
     * init()
     *      서블릿 객체가 생성되고 나서 <최초 한번만> 호출된다.
     */
    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("init() 호출");
    }
     
    /*
     * destroy()
     *      서버 종료와 같은 최후에 마지막 한번 호출된다. 자원 해제 등의 작업을 해준다.
     */
    @Override
    public void destroy() {
        super.destroy();
        System.out.println("destroy() 호출");
    }
     
    // doGet()
    //      요청시마다 호출된다.
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet() 호출");
    }
 
    // doPost()
    //      요청시마다 호출된다.
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doPost() 호출");
    }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.jsp.study;
 
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("/TestServlet") // 어노테이션을 이용한 uri 맵핑 방식
public class TestServlet extends HttpServlet { // 서블릿은 HttpServlet을 상속해서 구현됨
    private static final long serialVersionUID = 1L;
 
    public TestServlet() {
    }
 
    // doGet() : get 방식으로 호출시 호출되는 메서드
    /*
     * HttpServletRequest : request 객체 -> 사용자의 요청 정보를 알아낼 수 있다.
     * HttpServletResponse : response 객체 -> 응답에 관련된 객체이다.
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 응답할 문서 타입과 인코딩 방식을 지정
        response.setContentType("text/html;charset=utf-8");
        // 응답 문서에 출력하기 위한 PrintWriter 객체를 가지고 옴
        PrintWriter writer = response.getWriter();
         
        writer.println("");
            writer.println("");
                writer.println("<h1>문서에 출력</h1><br/>");
            writer.println("");
        writer.println("");
        // PrintWriter 객체 자원 해제
        writer.close();
    }
 
    // doPost() : post 방식으로 호출시 호출되는 메서드
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
 
}

[ Servlet Mapping ]



- Servlet 문서는 자바로 된 웹 프로그래밍 문서로서 MVC 패턴에서 Controller를 담당한다.


이때, 특정 URL로 요청시 해당 Servlet 문서가 동작할 수 있도록 Mapping(맵핑) 작업을 해주어야 하는데 이와 같은 작업에는

두가지 방식이 있다.


- [ Mapping 방식 ]

1. web.xml 에서 맵핑 설정하기


2. Annotation(어노테이션)을 이용하기


먼저, web.xml에서 맵핑을 설정할 경우

해당 Servlet 문서를 생성한 뒤, web.xml에 들어가서

다음과 같이 설정한다.

아래는 Helloworld라는 Servlet class 파일에 대한 맵핑을 설정한 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>ex</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
   
  <servlet>
    <servlet-name>hellWorldServlet</servlet-name> <!-- 이름 지정 -->
    <servlet-class>com.java.ex.Helloworld</servlet-class> <!-- Servlet class 지정 -->
  </servlet>
  <servlet-mapping>
    <servlet-name>hellWorldServlet</servlet-name>
    <url-pattern>/hw</url-pattern> <!-- http://localhost:80/ex/hw 로 맵핑된다. -> 컨텍스트패스/hw -->
  </servlet-mapping>
</web-app>


두번째로 어노테이션을 이용한 맵핑 방식이다.

@WebServlet 의 괄호 안에 맵핑할 URI 패턴을 적어준다.

현재 프로젝트의 컨텍스트 패스가 /ex임으로 http://localhost:80/ex/hw 로 해당 Servlet 문서가 맵핑된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.java.ex;
 
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("/hw") // 두번째, 어노테이션을 이용한 Servlet 맵핑 방법
public class Helloworld extends HttpServlet {
    private static final long serialVersionUID = 1L;
        
    public Helloworld() {
        super();
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
 
}



1. http://www.sba.seoul.kr:80/kr/index?contries=seoul

   ----   ------------------- -- ---------- ----------------

     1                2          3       4             5


1) 프로토콜 : 통신 규약 ex) http, https, FTP, SMTP ...

2) IP : 컴퓨터를 구분해주는 컴퓨터 주소 부분 but 쉽게 인식할 수 있도록 DNS로 표시

-> www.naver.com 등이 다 도메인이고 DNS를 통해 IP주소로 변환된다.

3) port : IP가 컴퓨터를 구분해 준다면 port는 해당 컴퓨터에서 프로그램을 구분해주는 주소 80번은 웹 default 포트이다.

4) context path 및 URI 부분

URL vs URI

: URL은 위와 같은 풀 경로를 가리키고 URI는 컨텍스트 패스 이후부터의 경로를 의미한다.

5) Query 문자열 : GET방식으로 데이터를 넘길 때 붙는 부분



2. [ 웹서버와 WAS(Web Application Server) 간의 차이 및 동작 방식 ]


- 웹서버 : 정적인 서비스를 지원해 준다. 단순히 HTML 문서 등을 응답할 때 사용

- WAS(Web Application Server) : 동적인 서비스를 지원해 준다. JSP페이지 등에서 DB 접근하고 특정 로직을 수행하는 등 동적인 처리후 응답을

   해줄 경우 이용된다.

=> WAS에서 웹서버의 역할을 할 수 있음에도 웹서버와 WAS를 분리시킨 이유?

: 간단 간단한 정적 페이지에 대한 요청을 웹서버가 처리해줌으로써 트래픽이 WAS로 전부 쏠리는 걸 분산시켜 처리하기 위해서


[ 기본적인 웹 동작 방식 ]

Client 브라우저(크롬,IE,사파리...) -request-> 웹서버 -> WAS(Web Application Server) -> DB

   <-response            <-                                        <-


3. [ JSP와 Servlet의 관계 ]


- JSP : 

HTML 문서 내에 자바 코드를 포함하는 문서로

- JSP페이지는 Servlet 으로 변환된다.

- MVC 패턴에서 View를 담당한다.


- Servlet :

JAVA언어로 웹프로그래밍 문서로

- MVC 패턴에서 Controller를 담당한다.



4. [ JSP에서의 MVC 패턴 ]


MVC 패턴

: Controller(Servlet 문서)

  Model <-> DB

  View(JSP 문서)

  로 분리하여 화면(View)와 데이터 처리를 분리시킨 방식으로 JSP에서는 Servlet이 Controller를 JSP 문서가 View를 

  담당하는 것이 일반적이다.



5. [ Client Request에 따른 JSP 처리 로직 ]


: Client Browser(크롬,IE,사파리...)에서 단순히 정적인 HTML 페이지 요청시 웹서버는 바로 HTML 페이지를 Response(응답)해 준다.

하지만, 동적인 작업이 필요한 특정 JSP페이지를 요청시(ex helloworld.jsp) 웹서버는 WAS로 요청을 보내게 되고

WAS는 컨테이너에 해당 JSP페이지에 대한 Servlet 객체가 있는지를 확인한다 있다면 해당 Servlet 객체의 doGET, doPOST 메서드를 통해

최종적으로 HTML 문서를 Client에게 응답하게 된다.


하지만, 요청한 JSP페이지에 대한 Servlet 객체가 존재하지 않는다면

우선, 요청한 JSP 페이지(helloworld.jsp)를 Servlet 자바 파일로 변환하게 된다.(helloworld_jsp.java)

그 뒤, 해당 Servlet 자바 파일을 컴파일 해 helloworld_jsp.class 와 같은 클래스 파일로 변환하게 되고

해당 class를 기반으로 Servlet 객체를 생성해 메모리에 적재하고 doGET, doPOST 메서드를 수행하여

최종적으로 Client 브라우저에 HTML 문서의 형태로 Response(응답)을 해주게 된다.




 


+ Recent posts