파일 업로드와 파일 다운로드에 대한 발행글입니다.

 

 


 

 

 

파일 업로드 기능은 Commons FileUpload 라이브러리가 가장 많이 사용됩니다.

스프링 프레임워크에서도 사용되는 매우 안정적인 라이브러리이지만,

Servlet 3.0부터 @MultipartConfig 어노테이션과 javax.servlet.http.Part 인터페이스를 사용하여 보다 쉽게 파일 업로드 기능을 구현할 수 있습니다.

 

 


 

 

@MultipartConfig Attribute

사용 가능 속성 목록
  • maxFileSize : 업로드 파일 최대크기값, 기본값은 -1 (크기 제한 없음)
  • maxRequestSize : HTTP 요청의 최대크기값, 기본값은 -1 (크기 제한 없음)
  • location : 파일 저장 경로, 파일은 Part의 write 메서드가 호출될 때 저장됨

 

 

 

Part Interface Method

사용 가능 메서드 목록
  • String getName() : HTML 태그의 <form> 태그 이름을 반환한다. 태그명이 파트 이름이 됨
  • String contentType() : 파일의 contentType을 반환한다.
  • Collection getHeaderNames() : Part의 모든 헤더명을 반환한다.
  • getHeader(name) : 설정한 헤더의 값을 리턴한다.
  • writer(path) : 업로드한 파일을 출력한다.
  • delete() : 파일과 임시 파일을 삭제한다.
  • InputStream getInputStream() : 업로드한 파일의 내용을 InputStream 객체로 반환한다.

 

 

 

서블릿 컨테이너는 다운로드중인 임시 파일을 생성하고 저장합니다.

대량의 파일 업로드가 여러 사용자에 의해 발생할 때, 임시 파일로 인해 스토리지가 고갈되므로 delete()라는 커맨드를 사용해서 임시파일을 삭제해야합니다.

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Cookie  (0) 2023.09.15
Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12

 

 

 

쿠키는 세션 트래킹 수행 시, 사용되는 작은 데이터 조각에 해당합니다.

 

 


 

쿠키는 응답 메세지의 헤더에 할당됩니다. 

 

 

쿠키 예시 ( 각 쿠키의 구분자는 세미콜론(;) )
Set-Cookie: name1=value1;name2=value2;...

 

 

쿠키를 응답 문서의 헤더에 할당하여 전송하면, 클라이언트의 쿠키 스토리지에 저장하며

이를 활용하여 클라이언트의 쿠키 스토리지를 이용한 세션 트래킹도 가능합니다.

 

이렇게 쿠키는 클라이언트가 웹 서버로 요청을 전송할 때, 반드시 요청 메세지의 헤더에 저장해서 보내야 합니다.

이는 웹 브라우저의 표준 동작 방식입니다.

 

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

파일 업로드, 다운로드  (0) 2023.09.15
Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12

 

 

 

세션 트래킹(Session Tracking)은 가상의 연결에 기반한 클라이언트의 상태를 지속적으로 모니터링하는 것을 의미합니다.

 

 

 


 

 

세션 트래킹의 목적

HTTP(Hyper Text Trasfer Protocol)은 하나의 요청과 하나의 응답으로 이루어진 전송 프로토콜입니다.

즉 HTTP는 상태 정보를 유지할 수 없는 프로토콜이므로, 이를 보완하기 위해 세션 트래킹이라는 추상적인 개념을 도입했습니다.

 

이러한 세션 트래킹의 핵심은 인증 관리입니다.

세션 트래킹은 클라이언트의 인증 상태와 인가 상태의 변화를 지속적으로 모니터링하며 접근 제어를 하는 것을 목적으로 합니다.

 

 

 

 

세션 식별자

동시에 요청을 보내는 수 많은 클라이언트를 고유하게 식별해야만 각 클라이언트의 상태를 트래킹할 수 있습니다.그래서 세션 ID를 통해 각 클라이언트를 식별하여 트래킹을 수행합니다.

 

간단한 서블릿 코드를 작성하고 cmd를 통해 세션 ID를 확인합니다.
@Log4j2
@NoArgsConstructor

@WebServlet("/TTT")
public class TTTServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

	
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) 
        throws ServletException, IOException {
        log.trace("service(req, res) invoked.");
		
		
        HttpSession session = req.getSession();
		
    } //service

} // end class

 

 

즉, 최초로 요청을 전송한 클라이언트에게 서버가 쿠키를 통해 세션 ID를 부여하고 한번 세션 ID를 부여받은 클라이언트는 다음 요청 전송 시, 요청 헤더에 세션 ID를 함께 할당하여 전송합니다.그럼 서버는 해당 요청과 세션 ID를 함께 수신함으로서, 세션 트래킹이 수행되며 이러한 세션 ID는 서블릿의 공유 데이터 영역인 Session Scope에 할당됩니다.

 

[서블릿] - 쿠키

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

파일 업로드, 다운로드  (0) 2023.09.15
Cookie  (0) 2023.09.15
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12

 

 

 

FrontController, Command 디자인 패턴에 대한 발행글입니다.

 


 

 

 

FrontController

FrontController는 클라이언트의 요청을 처리하기 위한 최초 진입점을 정의하는 디자인패턴입니다.

모든 사용자의 요청을 한 곳에 집중시켜 중복된 코드를 제거하고 요청을 분산시키는 방식으로 동작합니다.

 

FrontController 패턴을 적용한 서블릿에서 고려해야 되는 사항은 클라이언트가 어떤 동작을 요청했는지 식별할 수 있어야 합니다.

 

클라이언트 요청 식별 매커니즘
http://서버IP번호:포트번호/context명/식별값

 

클라이언트는 명시적으로 URL에 식별값을 추가하고 요청하고, 서블릿은 '식별값'을 비교해서 어떤 요청인지를 구별합니다.

여기서 '식별값'은 임의의 문자열값입니다. 일반적으로 "XXX.do" 같은 방식으로 지정합니다.

 

 

 

Command

Command는 클라이언트의 요청을 클래스 객체로 처리하는 것을 의미합니다.객체의 형태로 사용하면 서로 다른 클라이언트의 요청값을 필요에 의해서 저장하거나 취소가 가능하며요청을 처리할 작업을 일반화시켜 요청의 종류와 무관하게 프로그램 작성이 가능하게 구현할 수 있습니다.

 

구현방법은 Command 패턴을 적용한 Service 클래스를 추가하며 이름은 "XXXXService" 처럼 짓습니다.
EX) InsertService  |  DeleteService  |  UpdateService  |  SelectService

 

Command 패턴을 적용한Service 클래스는 작업 수행을 요청하는 객체인 서블릿실제 작업을 수행하는

객체

분리시켜주기 때문에 관계를 느슨하게 할 수 있습니다.

 

 

 

 

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Cookie  (0) 2023.09.15
Session Tracking  (0) 2023.09.14
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12
Connection Pool  (0) 2023.09.08

[ 최종 수정일 : 2023년 09월 20일 ]

 

 

 

 

요청 포워딩을 구현하는 방법은 두 가지가 있습니다.

  • RequestDispatcher 클래스를 활용한 forwarding
  • RequestDispatcher 클래스를 활용한 include
  • HttpServletResponse 클래스를 활용한 redirect

 


 

Request Forwarding - (RequestDispatcher)


클라이언트가 서블릿에 요청을 전송하면 request 객체가 자동으로 생성됩니다.

이때 request 객체를 활용해서 응답을 처리하는 웹 컴포넌트에게 요청을 위임하는 것이 요청 포워딩입니다.

 

RequestDispatcher Request Forwaridng의 기본적인 Syntax입니다.
RequestDistatcher dis = request.getRequestDispatcher(target);
dis.forward( request, response );

 

요청 포워딩을 수행한 웹 컴포넌트의 모든 응답은 모두 자동 취소됩니다.

만약 워딩 수행 전, 버퍼가 플러싱되면 요청 포워딩은 수행되지 않습니다.

 

 

 

 

Request Include - (RequestDispatcher)


웹 페이지 내에서 다른 리소스를 현재 페이지에 포함시키는 방법입니다.

일반적으로 스크립팅 언어(JSP, PHP 등)을 활용하여 웹 페이지의 일부분을 동적으로 구현할 때 사용합니다.

 

RequestDispatcher Request Include의 기본적인 Syntax입니다.
RequestDistatcher dis = request.getRequestDispatcher(target);
dis.include( request, response );

 

쉽게 말해, A 서블릿의 로직 수행 결과를 B 서블릿으로 요청을 넘길 때, 로직 수행 결과를 포함해서 넘겨주게 됩니다.

 

 

 

Request Redirection - (HttpServletResponse)


요청 포워딩과 비슷하게 다른 컴포넌트에게 요청을 위임하는 방식입니다.

요청 포워딩과 차이점은 응답을 먼저 하고 요청을 위임하기 때문에, 동일한 request가 아니라 새로운 request 객체가 생성됩니다.따라서 웹 브라우저의 URL 값이 변경되고 속성에 설정된 값을 가져오지 못합니다.

그래서 삭제 단위가 브라우저인 Session Scope에 저장해야 합니다.

 

Request Redirect의 기본적인 Syntax입니다.
HttpSession session = req.getSession();
session.sendRedirect("/target");

 

즉, 클라이언트는 서블릿에게 요청을 전송하고 응답을 받으면 JSP에 재요청을 하고 응답을 받는 원리로 수행됩니다.

 

 

 

 

 

 

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12
Connection Pool  (0) 2023.09.08
톰캣 사양 별 DTD  (0) 2023.09.05

 

 

 

DTO (Data Transfer Object), DAO (Data Access Object), VO (Value Object)는 3계층 아키텍처에서 사용됩니다.

 

 


 

 

1. 3-Tire Architecture

 웹 애플리케이션을 설계하고 개발할 때, 구조적 명료성과 유지보수를 위해 일반적으로 3계층 아키텍처(3-Tire Architecture)를 사용합니다. 3계층 아키텍처에서 두 가지 패턴은 데이터의 전송 및 캡슐화를 담당하게 됩니다.

 

 다음은 3계층 아키텍처의 구성요소입니다.

 

  • 프레젠테이션 계층(Presentation Layer)
    이 계층에서는 사용자의 입력을 받아 처리하고 사용자에게 결과를 표시합니다.

  • 비즈니스 계층(Business Logic Layer)
    애플리케이션의 다양한 비즈니스 로직이 구현되어 있는 계층입니다.

  • 영속성 계층(Persistence Layer)
    데이터베이스에 접근하여 데이터의 CRUD 연산을 처리하는 계층입니다.

 

위 3계층 아키텍처를 기반으로 DTO와 DAO를 알아보겠습니다.

 

 


2. DTO (Data Transfer Object)

 DTO는 일반적으로 Presentation, Business Layer에서 활용됩니다.

클라이언트의 요청을 DTO에 저장하고 DAO에게 DTO를 인자값으로 주면서 데이터 조작을 요청합니다.

이 때, DTO는 서블릿 공유 컨테이너의 Rquest Scope에 위치하므로 요청에 대한 응답을 전송하는 즉시 DTO는 파괴됩니다.

 

 

 

3. DAO (Data Access Object)

 DAO는 DTO를 기반으로 데이터베이스에 접근하여 데이터를 CRUD하고, 그 조작 결과를 VO(Value Object)로 반환합니다.

 

 

 

4. VO (Value Object)

VO는 Business Layer에서 DAO에게 요청한 값을 받아올 때 사용하며,  DAO는 데이터 조작을 통해 얻은 데이터를 반환할 때 VO를 통해 반환합니다.  즉, VO의 필드들은 DQL문장들의 결과셋으로 이루어진다고 할 수 있습니다.

 

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
Connection Pool  (0) 2023.09.08
톰캣 사양 별 DTD  (0) 2023.09.05

 

 

 

[2023_08_09] 해당 발행글은 Oracle을 기준으로 작성되었습니다.

 

 

 

 

Connection Pool은 연결 객체를 생성하고 영구소멸하는 것이 아니라 대여와 반납의 개념으로 이루어집니다.

 

 

 


 

 

Connection Pool은 DataSource Interface의 규격대로 DataSource를 제공합니다.

이러한 DataSource는 Tomcat같은 WAS 내부에서 생성하게 됩니다.

 

WAS가 DataSource를 생성하는 방법은 두 가지가 있습니다.

 

  • Global DataSource
  • 애플리케이션 별 Local DataSource

 

Global DataSource는 표준에 따라 생성 후 제공하지만, 각 벤더의 WAS마다 설정방법이 모두 다르기 때문에

WAS가 바뀌어도 소스를 변경할 필요가 없는 Local DataSource를 사용하는 것을 권장합니다.

 

 

다음 경로에 프로젝트 내에 META-INF 폴더를 만들고 context.xml을 생성합니다.

 

 


 

 

기초적인 context.xml Syntax입니다.

 

<?xml version="1.0" encoding="UTF-8"?>

<Context>

    <!-- <Resource 
        name="jdbc/OracleLocalDB" 
        auth="Container"
        type="javax.sql.DataSource"
        username="이름작성"
        password="비밀번호작성"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@db이름?TNS_ADMIN=db설치주소"
        maxTotal="8"
        maxIdle="2"
    /> -->

    <Resource 
        name="jdbc/OracleCloudATP" 
        auth="Container"
        type="javax.sql.DataSource"
        username="이름작성"
        password="비밀번호작성"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@tns_name?TNS_ADMIN=클라우드지갑주소"
        maxTotal="8"
        maxIdle="2"
    />

<!--     <Resource 
        name="jdbc/OracleLocalDBWithDriverSpy" 
        auth="Container"
        type="javax.sql.DataSource"
        username="이름작성"
        password="비밀번호작성"
        driverClassName="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"
        url="jdbc:log4jdbc:oracle:thin:@db이름?TNS_ADMIN=db설치주소"
        maxTotal="8"
        maxIdle="2"
    /> -->

    <Resource 
        name="jdbc/OracleCloudATPWithDriverSpy" 
        auth="Container"
        type="javax.sql.DataSource"
        username="이름작성"
        password="비밀번호작성"
        driverClassName="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"
        url="jdbc:log4jdbc:oracle:thin:@tns_name?TNS_ADMIN=클라우드지갑주소"
        maxTotal="8"
        maxIdle="2"
    />

</Context>

 

주석된 부분은 LocalDB이므로 필요하신 분은 주석 해제 후 개발환경에 맞게 작성하시면 됩니다.

 

 


 

 

위의 코드를 참고해서 Connection Pool을 두개를 사용하겠습니다.이제 Eclipse에서 Tomcat Server를 실행하고 Servlet을 작성합니다.

 

Servlet을 작성할 때, LifeCycleMethods를 모두 생성합니다.

 

 

다음 코드를 작성합니다.

 

@Log4j2
@NoArgsConstructor

@WebServlet("/UsingDataSource")
public class UsingDataSourceServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    // 의존성 주입
    @Resource(name="jdbc/OracleCloudATP")
    private DataSource dataSource;


    public void init(ServletConfig config) throws ServletException {
        log.trace("init({}) invoked.", config);
		
        Objects.requireNonNull(dataSource);
        log.info("\t + dataSource: " + dataSource);
    } // init()


    public void destroy() {
        log.trace("destroy() invoked.");
    } // destroy()


    protected void service(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {
        log.trace("service(req, res) invoked.");
		
        try {
            Connection conn = this.dataSource.getConnection();
			
            try(conn){
                Objects.requireNonNull(conn);
                log.info("\t + conn: {}", conn);
            } // try
			
        } catch (SQLException e) {
            throw new IOException(e);
        } // try-catch
		
    } // service()

} // end class

 

@Resource 어노테이션은 지정된 자원의 레퍼런스를 획득 후 DataSource의 필드에 의존성 주입을 하게 됩니다.

이제 서버에 작성된 Servlet을 올릴 때마다, Connection Pool에 Data Resource를 계속해서 추가하게 됩니다.

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12
톰캣 사양 별 DTD  (0) 2023.09.05

 

 

 

web.xml을 웹 애플리케이션의 설정파일이라고 할 수 있습니다.

즉, 웹 애플리케이션에 포함된 모든 종류의 구성요소(Servlet, JSP와 같은 Component)를 설정합니다.

 

 


 

 

사양에 따라 web.xml을 설정해야 합니다.

 

 

# Tomcat 9.0

<?xml version="1.0" encoding="UTF-8"?>

    <web-app 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

 

 

# Tomcat 8.0

<?xml version="1.0" encoding="UTF-8"?>

    <web-app 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

 

 

# Tomcat 7.0

<?xml version="1.0" encoding="UTF-8"?>

    <web-app 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

 

 

 

web.xml에서 설정 이후, 지역 설정 Project Facets에서 잘 적용됐는지 확인할 수 있습니다.

 

 

 

 

 

 

'웹 표준 > Servlet' 카테고리의 다른 글

Session Tracking  (0) 2023.09.14
FrontController, Command Patterns  (0) 2023.09.13
Request  (0) 2023.09.13
DTO, DAO, VO  (0) 2023.09.12
Connection Pool  (0) 2023.09.08

+ Recent posts