11. 서블릿과 JSP 01

JSP와 서블릿은 거의 유사하며, 이를 발전시킨 형태가 Spring이라고 보면 됨.
Spring역시 서블릿을 통해 동작함.

java는 단일상속이므로 되도록이면 상속을 하지않고 구현하는게 좋음.(여지를 남겨둔다고 생각하면 편함)
controller는 서블릿보다 더욱 발전된 형태임.

서블릿과 컨트롤러 비교예제

서블릿

@WebServlet("/rollDice2")
public class TwoDiceServlet extends HttpServlet {
    int getRandomInt(int range) {
	return new Random().nextInt(range)+1;
    }

    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        int idx1 = getRandomInt(6);
        int idx2 = getRandomInt(6);

        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        // 이하생략
       }
}

컨트롤러

@Controller		// ctrl + shift + o => 자동 import
public class TwoDice {
	@RequestMapping("/rollDice")
	public static void main(HttpServletResponse response) throws IOException {
		int idx1 = (int)(Math.random()*6)+1;
		int idx2 = (int)(Math.random()*6)+1;
		
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		
        PrintWriter out = response.getWriter();
        // 이하생략
    }
}

위 두 클래스는 같은 기능을 함.
서블릿을 사용할때는 HttpServlet의 상속이 필요.

서블릿의 생명주기

요청이 왔을때 서블릿 인스턴스가 존재하면 init()과정을 생략.
존재하지 않을 경우 서블릿 클래스 로딩 & 인스턴스 생성
init()
service()
응답
서블릿이 메모리에서 내려갈때 destroy() 실행

서블릿은 기본적으로 싱글톤 구조로, 1개의 인스턴스만을 가진다.
=> 하나의 객체를 요청마다 재활용하는 형태.

JSP

<%! 내용 %> : 클래스 영역
<% 내용 %> : service 메서드 영역

JSP에는 생성하지 않아도 사용할 수 있는 기본객체가 존재.
예) request, response, session ...

-towDice.jsp-

<%@ page contentType="text/html;charset=utf-8"%>
<%@ page import="java.util.Random" %>
<%-- <%! 클래스 영역 %> --%>
<%!  
	int getRandomInt(int range){
		return new Random().nextInt(range)+1;
	}
%>
<%-- <%  메서드 영역 - service()의 내부 %> --%>
<%
	int idx1 = getRandomInt(6);
	int idx2 = getRandomInt(6);
%>
<html>
<head>
	<title>twoDice.jsp</title>
</head>
<body>
	<img src='resources/img/dice<%=idx1%>.jpg'>
	<img src='resources/img/dice<%=idx2%>.jpg'>
</body>
</html>


servlet으로 만든 twoDice와 비교한 사진.

서블릿과 Spring 차이

서블릿과 Spring은 동일하게 싱글톤 디자인패턴을 가지지만 초기화에 있어서는 약간 다름.
서블릿: lazy - init (지연된 초기화)
Spring: early - init (요청이 오지 않아도 미리 객체를 만들어두고 초기화를 해두도록 개선)

둘 다 장/단점이 있음.
서블릿역시 Spring처럼 미리 초기화하는 방법이 있음. 위는 기본값 이야기임.


12. 서블릿과 JSP 02

유효범위와 속성

HTTP의 특징

  • 상태정보를 저장하지 않음 = stateless
    상태정보를 저장하기 위해 저장소가 필요한데, 총 4개의 저장소가 존재함.
    접근범위와 생존기간에 따라 4가지로 분류됨.
    저장소의 역할: lv(지역변수)를 저장함.

저장소의 종류
1) pageContext : 같은 페이지내에서만 참조가능. 보통 EL${} 때문에 사용.
2) application : WebApp전체에서 접근가능. 저장은 하나만 가능. 공통저장소.
3) session : 클라이언트마다 하나씩 있는 개별저장소.
4) request : 요청이 처리되는 동안만 유지되는 객체.
forward(데이터를 다른 페이지로 전달시키는 것)시 가장 먼저 고려해볼 저장소.

session은 클라이언트의 숫자대로 객체를 생성하므로 최대한 적은 값을 저장하는게 좋음.
4개의 저장소 중 가장 서버 메모리 부담이 높다.

보통은 jsp페이지 하나가 요청받은 값을 출력하지만 간혹 필요한 jsp페이지간에 데이터를 옮겨주는 작업을 forward라고 함.


13. 서블릿과 JSP 03

URL패턴

@WebServlet으로 서블릿을 URL에 맵핑할때 사용

우선순위. 종류URL pattern매칭URL
1. exact mapping 정확한 주소로 매핑/login/hello.dohttp://localhost/ch2/login/hello.do
2. path mapping 경로로 매핑/login/*http://localhost/ch2/login/
3. extension mapping 확장자 매핑*.dohttp://localhost/ch2/hi.do
4. default mapping 모든주소와 매핑되는 기본형/http://localhost/ch2/

/는 모든 요청을 받지만 우선순위가 가장 낮음

=> Spring에서는 @RequestMapping을 사용.
Spring에서도 마찬가지로 URL패턴이 존재함.
이에 대해서는 추후 강의내용에서 공부예정.

Spring에서는 서블릿에서 사용하는 1, 2, 3번패턴을 사용하지 않기때문에 DispatcherServlet이 모든요청을 받아 내부적으로 각 유형별 분배를 하게 됨.
servlet은 요청에 따라 서블릿이 분류를 진행하는것과 차이가 있음.

EL

Expression Language
쉽게 말하자면 <%=값%> => ${} 로 간단히 사용하는 방법.
지역변수(lv)는 바로 사용할 수 없으며, 저장 후 사용해야한다.
EL은 null을 출력하지 않음.

EL의 경우 "1" + 1의 결과가 2이니 주의.
계산 시 null은 0으로 취급됨.
empty => null 또는 빈 컬렉션배열일때 true, 아닐때 false를 반환. 피연산자가 비었는지를 체크함.
단, 그렇다고해서 null과 빈 컬렉션배열이 같은것은 아님.


자동으로 생성된 class파일 및 src파일을 삭제.
컴파일 과정에서 문제가 생길 경우 해준 뒤 다시 실행해주면 됨.

예제

-Person.class-

public class Person { 
	private Car car = new Car(); 
	public  Car getCar() { return car; }
}  

-Car.class-

public class Car    { 
	private String color = "red"; 
	public String getColor() { return color; }
}

-el.jsp-

<%@ page contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="c"   uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page import="com.fastcampus.ch2.*" %>
<%
	Person person = new Person();
	request.setAttribute("person", person);
	request.setAttribute("name", "남궁성");   
	request.setAttribute("list", new java.util.ArrayList());	
%>
<html>  
<head>   
	<title>EL</title>   
</head>  
<body>   
	person.getCar().getColor()=<%=person.getCar().getColor()%> <br>
	person.getCar().getColor()=${person.getCar().getColor()} <br>
	person.getCar().getColor()=${person.car.color} <br>    
	name=<%=request.getAttribute("name")%> <br>   
	name=${requestScope.name} <br>
	name=${name} <br>
	id=<%=request.getParameter("id")%> <br>
	id=${pageContext.request.getParameter("id")} <br>
	id=${param.id} <br>
	"1"+1 = ${"1"+1} <br>
	"1"+="1" = ${"1"+="1"} <br>
	"2">1 = ${"2">1} <br>   
	null = ${null}<br>
	null+1 = ${null+1} <br>
	null+null = ${null+null} <br>
	"" + null = ${""+null} <br>   
	""-1 = ${""-1} <br> 
	empty null=${empty null} <br>
	empty list=${empty list} <br>
	null==0 = ${null==0} <br>
	null eq 0 = ${null eq 0} <br>
	name == "남궁성"=${name=="남궁성"} <br>
	name != "남궁성"=${name!="남궁성"} <br>
	name eq "남궁성"=${name eq "남궁성"} <br>  
	name ne "남궁성"=${name ne "남궁성"} <br>  
	name.equals("남궁성")=${name.equals("남궁성")} <br>   
</body>
</html>


14. 서블릿과 JSP 04

JSTL

JSP Standard Tag Library

<%@ taglib prefix="c"   uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

위 두 태그를 추가하여 라이브러리를 추가해야 함.
prefix="c"는 코어 라이브러리, prefix="fmt"은 포멧라이브러리

<%=값%> => ${} (EL)
<%코드%> => JSTL

예제

-jstl.jsp-

<%@ page contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="c"   uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
	<title>JSTL</title>
</head>
<body>
<c:set var="to"   value="10"/>
<c:set var="arr"  value="10,20,30,40,50,60,70"/> 
<c:forEach var="i" begin="1" end="${to}">
	${i}
</c:forEach>
<br>
<c:if test="${not empty arr}">
	<c:forEach var="elem" items="${arr}" varStatus="status">
		${status.count}. arr[${status.index}]=${elem}<BR>
	</c:forEach>
</c:if>	
<c:if test="${param.msg != null}">
	msg=${param.msg} 
	msg=<c:out value="${param.msg}"/>
</c:if>
<br>
<c:if test="${param.msg == null}">메시지가 없습니다.<br></c:if>
<c:set var="age" value="${param.age}"/>
<c:choose>
	<c:when test="${age >= 19}">성인입니다.</c:when>
	<c:when test="${0 <= age && age < 19}">성인이 아닙니다.</c:when>
	<c:otherwise>값이 유효하지 않습니다.</c:otherwise>
</c:choose>
<br>
<c:set var="now" value="<%=new java.util.Date() %>"/>
Server time is <fmt:formatDate value="${now}" type="both" pattern="yyyy/MM/dd HH:mm:ss"/>	
</body>
</html>

Filter

공통적인 요청 전처리와 응답 후처리에 사용됨.
로깅, 인코딩 등.

-PerformanceFilter.java-

package com.fastcampus.ch2;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

// 필터를 적용할 요청의 패턴 지정 - 모든 요청에 필터를 적용.
@WebFilter(urlPatterns="/*")
public class PerformanceFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// 초기화 작업
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 1. 전처리 작업
		long startTime = System.currentTimeMillis();

		// 2. 서블릿 또는 다음 필터를 호출
		chain.doFilter(request, response); 
		
		// 3. 후처리 작업
		System.out.print("["+((HttpServletRequest)request).getRequestURI()+"]");
		System.out.println(" 소요시간="+(System.currentTimeMillis()-startTime)+"ms");
	}

	@Override
	public void destroy() {
		// 정리 작업
	}

}


각각
http://localhost:8090/ch2/
http://localhost:8090/ch2/jstl.jsp
http://localhost:8090/ch2/el.jsp
페이지를 차례로 실행시켰을때의 결과.
필터를 이용해 페이지 로드에 걸리는 소요시간을 보는 예제클래스.

profile
천 리 길도 가나다라부터

0개의 댓글

Powered by GraphCDN, the GraphQL CDN