# varStatus
< c : forEach > 태그에 사용할 수 있는 속성 중에는 varStatus 속성이 있다.
varStatus 속성은 배열이나 컬렉션과 같은 집합체에서
항목의 인덱스 값을 사용해야 할 경우가 생기는데 이 때 사용하게 된다.
varStatus 속성은 인덱스(index)는 물론 반복 횟수(count) 등과 같은 반복 상태에 관련된 정보를 프로퍼티로 알려준다.
- 프로퍼티 설명
① index : items에 지정한 집합체의 현재 반복 중인 항목의 index를 알려준다.
0부터 순서가 부여된다. // ≒ 배열
② count : 루핑을 돌 때 현재 몇 번째를 반복 중인지 알려준다.
1부터의 순서가 부여된다.
③ first : 현재 루프가 처음인지 여부를 알려준다.
첫 번째일 경우에는 true 아니면 false를 리턴한다.
④ last : 현재 루프가 마지막인지 여부를 알려준다.
마지막일 경우에는 true 아니면 false를 리턴한다.
ex)
- Test.jsp
<%@page import="java.util.HashMap"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<c:set var="mapTest" value="<%=new HashMap<String, String>()%>"/>
<c:set target="${mapTest}" property="key1" value="value1"/>
<c:set target="${mapTest}" property="key2" value="value2"/>
<c:set target="${mapTest}" property="key3" value="value3"/>
<hr>
<c:forEach var="map" items="${mapTest}" varStatus="status">
<c:if test="${status.first}"> 첫 번째입니다<br> </c:if>
<c:if test="${status.last}"> 마지막입니다<br> </c:if>
${status.index }
${status.count }
${map.key }
${map.value }
<br>
</c:forEach>
</body>
</html>
Q1. JSTL을 이용하여 HashMap 변수를 mapTest라는 이름으로 생성하고 다음 값을 넣자.
Key에 "key1" Value에 "value1"
Key에 "key2" Value에 "value2"
그리고 JSTL을 이용하여 그 값들을 출력해 보자.
A.
- JSTLTest15.jsp
<%@page import="java.util.HashMap"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<!-- Map 선언 -->
<c:set var="mapTest" value="<%=new HashMap<String, String>()%>" />
<!-- Map 에 값 넣기 -->
<c:set target="${mapTest}" property="key1" value="value1" />
<c:set target="${mapTest}" property="key2" value="value2" />
${mapTest.key1}<!-- value1 이 출력됨 -->
${mapTest.key2}<!-- value2 이 출력됨 -->
<c:forEach var="mapTest" items="${mapTest}">
${mapTest.key}<!-- key1, key2 ... 이 출력됨 -->
${mapTest.value}<!-- value1, value2 ... 이 출력됨 -->
</c:forEach>
</body>
</html>
Q2. 다음을 JSTL을 이용하여 코딩하시오.
① 'varName'이라는 변수를 선언하고 값을 'varValue'를 주시오.
그리고 그 값을 출력하시오.
② 'varName'이라는 변수를 삭제하시오. 그리고 그 값을 출력하시오.
③ 2를 0으로 나누었을 때의 에러를 처리하시오. 그리고 그 것의 에러 메세지를 출력하시오.
④ 1+2가 3과 같다면 "1+2=3"이라고 출력하시오.
⑤ 1+2가 3과 같지 않다면 "1+2 != 3" 이라고 출력하시오.
⑥ 반복문을 이용하여 0부터 30까지 출력하는데 3씩 증가한 값을 출력하시오.
A.
- JSTLTest1.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<c:set var='varName' value='varValue'/>
<c:out value='${varName}'/><br>
${varName }<br>
<c:remove var="varName" />
<c:out value="${varName }"/><br>
${varName }
<c:catch var="error"> // 자바의 try catch와 동일 , 에러 발생 시 error변수에 저장됨
<%= 10/0 %>
</c:catch>
<c:out value="${error.message}" /><br> // 에러에 해당하는 메시지를 출력
<c:if test="${1+2==3}">
1+2=3<br>
</c:if>
<c:if test="${1+2!=3}">
1+2 != 3<br>
</c:if>
<c:forEach var="i" begin="0" end="30" step="3">
${i }
</c:forEach>
</body>
</html>
# 파일 업로드
enctype : 전송되는 parameter의 형식을 알려주는 것이다.
일반적으로는 복합형식이 아닌 일반 text 데이터만 전송되기 때문에 아무런 지정이 필요없다.
그러나 file과 같이 일반 text 형식이 아닌 것이 전송시에 포함되어 있으면
그 상황을 서버에 미리 알려 주어 전송 되어온 내용을 누락시키지 않도록 만들어 주어야 한다.
이러한 형식 지정은 smtp(simple mail transfer protocol)의 규약에서 사용하는 방식으로
웹에서도 유사한 방법으로 전송타입을 지정한다.
또한 multipart의 전송시에는 반드시 POST 방식의 전송이 필요하다.
GET 방식은 데이터의 길이에 제약을 받기 때문이다.
- FileUploadTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>데이터와 파일전송</title>
</head>
<body>
<h2>데이터와 파일 전송 메뉴입니다</h2>
<form method="post" action="FileUploadResult" enctype="multipart/form-data">
보낸이 : <input type="text" name="sender"/><br/>
파일명 : <input type="file" name="attach"/><br/>
<!-- 파일을 첨부할 경우에는 input type을 file로 지정한다. -->
<input type="submit" value="전송"/>
</form>
</body>
</html>
- FileUploadResult.java
package com.superman.ex;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/FileUploadResult")
public class FileUploadResult extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//multipart의 전송을 수용하기 위해 post 메서드를 정의한다.
request.setCharacterEncoding("UTF-8");
//전송된 내용의 한글 처리를 위해 지정한다.
ServletInputStream p_in = request.getInputStream();
//전송되어 온 내용을 Stream으로 읽기 위한 객체를 선언한다.
response.setContentType("text/html;charset=UTF-8");
//출력 MIME을 지정한다.
ServletOutputStream p_out = response.getOutputStream();
//전송되어 온 내용을 그대로 사용자에게 출력하기 위한 객체를 선언한다.
p_out.write("Start!!!<br/>".getBytes()); // String을 Byte형 배열로 바꿔주는 것
while(true) {
//전송된 모든 내용을 출력할 때까지 반복 수행한다.
int x = p_in.read();
if(x == -1) break; // 더 이상 읽을 내용이 없다는 의미
//전송이 끝나면 탈출한다.
p_out.write((char)x);
//전송되어 온 내용을 문자로 변환 후 출력한다.
}
p_out.write("<br/>End!!!".getBytes());
p_in.close();
p_out.close();
}
}
http://www.servlets.com/cos/ 접속
왼쪽 메뉴바에서 com.oreilly.servlet 클릭
아래쪽 cos-26Dec2008.zip 클릭
cos-26Dec2008\lib 에있는 cos.jar를 톰캣에 lib에 복사 또는 WebContent에 WEB-INF에 lib에 복사
- fileForm.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<form action="fileFormOk.jsp" method="post" enctype="multipart/form-data">
이름 : <input type="text" name="name"><br />
파일1 : <input type="file" name="file1"><br />
<!-- 파일2 : <input type="file" name="file2"><br /> -->
<input type="submit" value="File Upload">
</form>
</body>
</html>
- fileFormOK.jsp
<%@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"%>
<%
// request.getSession().getServletContext().getRealPath("/");
String path = application.getRealPath("fileFolder");
int size = 1024 * 1024 * 10; //10M - 최대 사이즈
String file = "";
String oriFile = "";
try{
MultipartRequest multi = new MultipartRequest(request, path, size, "utf-8", new DefaultFileRenamePolicy());
String name = multi.getParameter("name");
System.out.println("이름 " + name);
Enumeration files = multi.getFileNames(); // 폼 요소 중 input 태그 속성이 file로 된 파라미터의 이름들을 반환
// upload 된 파일이 없으면 비어있는 Enumeration을 반환
while(files.hasMoreElements())
{
String str = (String)files.nextElement();
file = multi.getFilesystemName(str); // 사용자가 지정해서 서버에 실제로 업로드된 파일명 반환
// 파일명이 중복되는 경우 변경된 파일명 반환
oriFile = multi.getOriginalFileName(str); // 사용자가 업로드한 실제 파일명을 반환.
// 이때의 파일명은 파일 중복을 고려한 파일명 변경 전의 이름을 말한다.
System.out.println("저장된 경로 " + path + " 저장된 이름 " + file + " 원본이름 " + oriFile);
}
} catch (Exception e) {
e.printStackTrace();
}
%>
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
file upload success!
</body>
</html>
#MIME
우리가 익히 알고 있는 웹 프로그램은 그 자체가 주로 HTML과 같은 형태를 띤다.
그래서 보통 서블릿과 같은 웹 프로그램을 웹 페이지로 착각하는 경우가 많다.
그러나 서블릿은 그 자체가 웹 페이지일 수도 있지만 이미지일 수도 있고, MS 워드일 수도 있다.
무슨 말인고 하니 MIME의 설정에 따라 웹 서버가 서블릿을 전혀 다른 형태로 인식할 수 있다는 것이다.
ex)
- IMGServlet.java
package com.superman.ex;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/IMGServlet")
public class IMGServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private File image;
//이미지 파일의 객체를 선언한다.
public void init() {
//초기화 메서드를 통해 이미지 파일을 연결한다.
ServletContext context = this.getServletContext();
String path = context.getRealPath("/images");
//실제 이미지가 있는 위치를 지정한다.
//WebContent 폴더에 images 폴더를 생성한 후 원하는 그림 파일을 미리 저장해 두어야 한다.
image = new File(path, "wonder.jpg");
//저장해 둔 경로의 해당 파일을 지정한다.
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//일반적으로 이미지를 읽을 때에는 GET 방식 호출이 대부분이므로 doGet 메서드를 작성한다.
response.setContentType("image/jpg");
//현재 Servlet의 MIME을 image/jpg로 지정하여 파일의 확장자 명과 동일하게 만든다.
//실제 gif나 jpg 등 이미지 관련 데이터들은 정확한 MIME을 지정하지 않고
//같은 image 계열의 MIME을 지정해도 정상 출력이 이루어 진다.
//그러나 실행 조건이나 속도 등에서 차이가 있기 때문에 정확한 MIME 지정을 습관화 하자.
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(image)));
//지정된 파일로 부터 데이터를 읽을 객체를 선언한다.
ServletOutputStream out = response.getOutputStream();
//읽은 데이터를 출력할 Servlet의 출력 객체를 Stream 객체로 지정한다.
//일반적으로는 PrintWriter를 사용하지만 image나 application과 같은 데이터의 경우에는
//각 byte에 더 중요한 의미가 있고 깨질 우려가 있기 때문에 Stream 출력객체를 사용해야 한다.
byte[] data = new byte[512];
//한번에 읽을 수 있는 byte 수를 512byte로 제한 한다.
while(true) {
int x = in.read(data, 0, data.length);
//최대 512byte 씩 데이터를 읽는다.
//x에는 읽은 개수가 저장된다.
if(x == -1) break;
//더이상 읽을 데이터가 없으면 빠져 나간다.
out.write(data, 0, x);
//읽은 개수 만큼 출력한다.
out.flush();
//클라이언트로 전송한다.
//flush()는 현재 버퍼에 있는 내용을 상대측으로 비워 내는 역할을 하는 메서드이다.
}
in.close();
out.close();
//모든 입출력 스트림을 종료한다.
}
}
- MIMETest1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Image Print!</title>
</head>
<body>
<h2>이미지 출력!</h2>
<img src="IMGServlet"/>
<!-- 이미지 객체를 출력하는 태그 사용 -->
</body>
</html>
- SNDServlet.java
package com.superman.ex;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/SNDServlet")
public class SNDServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private File file;
//사운드 파일 객체
public void init() {
String path = "/sounds";
String filename = "bgsnd.wma";
ServletContext context = this.getServletContext();
path = context.getRealPath(path);
//실제 경로를 획득한다.
file = new File(path, filename);
//file 객체를 생성한다.
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//이미지와 마찬가지로 사운드로 GET 방식 호출이 발생한다.
if(file.getName().endsWith(".au") || file.getName().endsWith(".snd")) {
response.setContentType("audio/basic");
//사운드에 대한 기본 MIME을 지정한다. basic은 확장자 au와 snd를 지원하는 MIME이다.
//사운드를 지원하는 MIME은 60여 가지이다.
//더 많은 MIME을 찾고자 한다면 인터넷에서 MIME Type이라고 검색하면 확인할 수 있다.
}
else if(file.getName().endsWith(".wma")){
//확장자가 wma 라면 다음과 같은 MIME을 사용한다.
response.setContentType("audio/x-ms-wma");
}
else if(file.getName().endsWith(".mp3")){
//확장자가 wma 라면 다음과 같은 MIME을 사용한다.
response.setContentType("audio/x-mpeg-3");
}
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
//사운드 파일에 대한 입력 객체를 생성한다.
ServletOutputStream out = response.getOutputStream();
//이 파일 역시 Stream 형태의 출력 객체를 생성해야 정상적으로 표현된다.
byte[] data = new byte[512];
//한번에 읽을 수 있는 최대 byte 수를 512bytes로 설정한다.
while(true) {
int cnt = in.read(data, 0, data.length);
if(cnt == -1) break;
out.write(data, 0, cnt);
out.flush();
}
//파일로 부터 데이터를 읽어 출력한다.
in.close();
out.close();
//Stream 들을 종료한다.
}
}
- MIMETest2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>사운드 출력!</h2>
<embed src="SNDServlet">
</body>
</html>
// 보안 상의 이유로 무조건 바로 실행되지 않게 바뀌는 추세이다.
# LOG : 서버를 실행해서 특정 동작을 할때마다 데이터의 변화를 파일이나 콘솔에 남기는 것
JSP 배포방법
프로젝트명 - 오른쪽 마우스 클릭 - EXPORT WAR FILE // war 파일로 배포
Destination : Browse 클릭 C:\apache-tomcat-9.0.33\webapps 지정
ex)
- LogJspTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%
log("JSP 로그를 남겨봅시다.");
try{
int num = 10 / 0;
} catch(ArithmeticException e){
log("연산오류가 발생했습니다.", e);
}
// C:\apache-tomcat-9.0.38\logs 에 저장
%>
</body>
</html>
서버 실행 시 연동 서버를 멈추게 해야 함
# 톰캣 서버를 위한 JAVA_HOME 설정 방법
- 자바홈 패스 추가 순서
컴퓨터 → 속성 → 고급 시스템 설정 → 고급 → 환경 변수 → 시스템 변수 → 새로 만들기 →
변수 이름 : JAVA_HOME
변수 값 : C:\Program Files\Java\jdk-14.0.1 (해당 주소 복사 후 붙여넣기 하기)
→ 확인 → 확인 → 확인
- 추가 이후 서버 실행 방법
$ cd C:\apache-tomcat-9.0.38\bin // 톰캣 서버 설치 경로로 이동
$ startup // 서버실행 시
$ shutdown // 서버종료 시
// 서버 실행 기록은 아래의 주소를 통해 log로 확인할 수 있다.
// localhost:8080/LogTest/LogJspTest.jsp (파일 이름으로 서버에 접속하는 방법)
#MVC 용어 정리
- DAO, DTO, VO
객체명칭 | 특징 |
DAO (Data Access Object) |
데이터베이스의 Data에 접근하기 위한 객체 데이터베이스 접근 로직과 비즈니스 로직을 구분하기 위한 것이다 |
DTO (Data Transfer Object) |
계층 간 데이터 교환을 위한 자바빈즈(Java Beans) 전송되는 데이터의 컨테이너 데이터베이스 레코드의 데이터를 매핑하기 위한 객체 보통 특별한 로직이 없고 data를 위한 getter와 setter만 있다 ex) 장소 이동을 위한 교통수단 |
VO (Value Object) |
데이터 그 자체로 DTO와 비슷하나 입력된 데이터는 같은 시스템 내에서 불변(ReadOnly)라는 차이점이 있다. (↔ DTO는 다른 시스템으로 전달 시 사용하며 가변적(setter)) |
- MVC 패턴 : 프로그램 디자인 패턴 중 하나이다.
① Model : DB연결파트(DAO), DB의 데이터(VO, DTO)
② View : 프레젠테이션 로직 (주로 jsp 등으로 개발함)
③ Controller : 비즈니스 로직(주로 Servlet 등으로 개발함)
- Programming Architecture(프로그래밍 아키텍쳐)
로직 명칭 | 특징 |
비즈니스 로직 (Business Logic) |
클라이언트(사용자)에게 보이지 않는 부분 데이터를 처리하는 응용프로그램의 일부분 주로 DB 처리 작업을 하며 Servlet 등으로 구현한다 Server Side Script(Language) - Java 사용 |
프레젠테이션 로직 (Presentation Logic) |
클라이언트(사용자)에게 보이는 부분 출력화면을 구성하는 응용프로그램의 일부분으로 JSP 등으로 구현한다 Client Side Script(Language) : HTML, CSS, JS 사용 |
모델명 | 설명 | 장점 | 단점 |
Model 1 | 비즈니스 로직과 프레젠테이션 로직이 한 파일에 혼재하는 구조 |
초기 개발이 쉽다 구조가 단순해 직관적이다 |
로직의 혼재로 유지보수가 어렵다 재사용성이 낮다 분업이 어렵다 |
Model 2 | 비즈니스 로직과 프레젠테이션 로직을 서로 다른 파일에 작성하는 구조 |
분업에 적절하다 | Model 2 개발방식에 대한 이해도와 기본 지식이 요구된다 |
# JSP(Java Server Page)
Servlet의 확장기술로 브라우저에 표현하기 위한 HTML 코드에 JAVA 코드를 혼용하여 사용할 수 있다.
이를 통해 디자인과 로직 개발을 분업화하여 효율적 코드를 생산할 수 있게 한다.
- JSP 동작 구조
① 클라이언트가 브라우저를 통해 서버에 HTTP 프로토콜 요청
② 서버가 컨테이너에 처리 요청하며, 컨테이너는 해당 파일을 찾음
③ 찾은 파일을 서블릿으로 변환
이미 변환된 파일인 경우 바로 ⑤ 실행
④ 서블릿 파일을 실행가능한 class 파일로 컴파일
⑤ 컴파일된 class 파일을 메모리에 적재 후 실행 결과를 웹 서버에 넘김
⑥ 웹서버는 브라우저가 인식할 수 있는 정적 페이지를 구성해 클라이언트에 응답
- JSP 기술을 활용한 개발 구조화와 업무 분업화
분업화를 위하여 MVC(Model-View-Controller)패턴 이라는 개념이 생겨났고 효율적인 코드의 생산이 가능해졌다.
Model 1, Model 2의 2가지 모델이 존재하며 장단점을 고려하여 시스템을 구성해야 한다.
// Model 1
JSP, Servlet, Bean 등으로 구성되는 형태로 JSP에는 프리젠테이션 레이어 & 비즈니스 레이어를 포함하고
업무부분을 JavaBean이나 Servlet에서 구현하기도 한다.
Model-View-Controller로 구분하기 모호하나 위와 같이 JSP에서는 주로 View와 Controller의 역할을 한다.
JavaBean(Servlet)에서는 주로 Model의 역할을 하지만 Controller의 역할을 하기도 한다.
[ 장점 ]
페이지 흐름이 단순해 개발팀원의 수준이 높지 않아도 가능하기 때문에 중소형 프로젝트에 적합하다.
[ 단점 ]
웹어플리케이션이 복잡해 질수록 유지 보수가 힘들어진다.
완벽히 분리되지 않아 디자이너와 개발자가 원활히 의사소통 되지 않으면 충돌이 발생할 수 있다.
// Model 2
① 클라이언트가 브라우저를 통해 서버에 HTTP 프로토콜 요청
② Controller는 Model에게 데이터 조회, 비즈니스 로직의 처리를 요청
③ Model로부터 정보를 받아 View에게 전달
④ 컨트롤러에서 전달받은 모델의 DTO 정보를 view 페이지에 참조
⑤ DAO를 통해 DB와 연결한 뒤 DTO 혹은 VO로 DB와 Model 간에 데이터 전달
⑥ View는 정적데이터를 구성해 클라이언트에 응답
[ 장점 ]
각 역할 별로 구분되어 있어 개발자와 디자이너의 작업이 분리되어 역할과 책임 구분이 명확해진다.
로직과 디자인 개발이 분리되어 있기 때문에 웹어플리케이션이 구조화되어 유지보수 및 확장이 용이해진다.
[ 단점 ]
구조화를 위해 개발의 복잡도가 증가함에 따라 개발기간도 증가한다.
개발팀원이 MVC구조에 대한 높은 수준의 이해가 필요하다.
# 도로명 주소
duam 도로명 주소
http://postcode.map.daum.net/guide
도로명 주소 api
https://www.juso.go.kr/addrlink/devAddrLinkRequestGuide.do?menu=roadApi
ex)
- AddressTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko-kr">
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<input type="text" id="sample4_postcode" placeholder="우편번호">
<input type="button" onclick="sample4_execDaumPostcode()" value="우편번호 찾기"><br>
<input type="text" id="sample4_roadAddress" placeholder="도로명주소">
<input type="text" id="sample4_jibunAddress" placeholder="지번주소">
<span id="guide" style="color:#999;display:none"></span>
<input type="text" id="sample4_detailAddress" placeholder="상세주소">
<input type="text" id="sample4_extraAddress" placeholder="참고항목">
<script src="https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
//본 예제에서는 도로명 주소 표기 방식에 대한 법령에 따라, 내려오는 데이터를 조합하여 올바른 주소를 구성하는 방법을 설명합니다.
function sample4_execDaumPostcode() {
new daum.Postcode({
oncomplete: function(data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 도로명 주소의 노출 규칙에 따라 주소를 표시한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
var roadAddr = data.roadAddress; // 도로명 주소 변수
var extraRoadAddr = ''; // 참고 항목 변수
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if(data.buildingName !== '' && data.apartment === 'Y'){
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if(extraRoadAddr !== ''){
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('sample4_postcode').value = data.zonecode;
document.getElementById("sample4_roadAddress").value = roadAddr;
document.getElementById("sample4_jibunAddress").value = data.jibunAddress;
// 참고항목 문자열이 있을 경우 해당 필드에 넣는다.
if(roadAddr !== ''){
document.getElementById("sample4_extraAddress").value = extraRoadAddr;
} else {
document.getElementById("sample4_extraAddress").value = '';
}
var guideTextBox = document.getElementById("guide");
// 사용자가 '선택 안함'을 클릭한 경우, 예상 주소라는 표시를 해준다.
if(data.autoRoadAddress) {
var expRoadAddr = data.autoRoadAddress + extraRoadAddr;
guideTextBox.innerHTML = '(예상 도로명 주소 : ' + expRoadAddr + ')';
guideTextBox.style.display = 'block';
} else if(data.autoJibunAddress) {
var expJibunAddr = data.autoJibunAddress;
guideTextBox.innerHTML = '(예상 지번 주소 : ' + expJibunAddr + ')';
guideTextBox.style.display = 'block';
} else {
guideTextBox.innerHTML = '';
guideTextBox.style.display = 'none';
}
}
}).open();
}
</script>
</body>
</html>
# ID 중복 체크
ex)
- idCheckForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko-kr">
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<h3> 아이디 중복체크 </h3>
<form method="post" action="idChecOK.jsp" onsubmit="return blankCheck(this)">
아이디 : <input type="text" name="id" maxlength="10" autofocus>
<input type="submit" value="중복확인">
</form>
<script>
function blankCheck(f){
var id=f.id.value;
id=id.trim();
if(id.length<5){
alert("아이디는 5자 이상 입력해주십시오.");
return false;
}
return true;
}
</script>
</body>
</html>
- idChecOK.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko-kr">
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<h3>아이디 중복 확인 결과</h3>
<%
String id=request.getParameter("id");
// int cnt = dao.duplecateID(id); // 데이터베이스 내 id 여부 체크하는 것
int cnt = 0;
out.println("입력 ID : <strong>" + id + "</stong>");
if(cnt==0){
out.println("<p>사용 가능한 아이디입니다.</p>");
out.println("<a href='javascript:apply(\"" + id + "\")'>[적용]</a>");
%>
<script>
function apply(id){
opener.document.memberRegister.id.value=id;
window.close(); //창닫기
}
</script>
<%
}else{
out.println("<p style='color: red'>해당 아이디는 사용하실 수 없습니다.</p>");
}
%>
<hr>
<a href="javascript:history.back()">[다시시도]</a>
<a href="javascript:window.close()">[창닫기]</a>
</body>
</html>
- member.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko-kr">
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<form name="memberRegister" method="post" action="IDCheckOK.jsp">
id : <input type="text" name="id" readonly> <input type="button" onClick="idCheck()" value="중복확인"><br>
password : <input type="password" name="password"><br>
<input type ="submit" value="전송">
</form>
<script>
function idCheck()
{
window.open("idCheckForm.jsp", "idCheckForm", "width=400, height=300");
}
</script>
</body>
</html>
- window.open() : 웹브라우저에서 새창을 열기 위해서 사용
ex) 홈페이지 공지 팝업창
var 반환값 = window.open(주소, 이름, 속성, 히스토리 항목);
var ret = window.open(url, name, specs, replace);
① 반환값(ret)
새로 만들어진 창 객체가 반환된다.
창의 생성에 실패하면 null을 반환한다.
이 객체를 통해서 새창을 제어할 수 있다.
// ret.close();로 창을 닫을 수 있다.
② url : 새창에 보여질 주소
선택적인 값으로 비워두면 빈창(about:blank)이 보인다.
③ name : 새로 열릴 창의 속성 또는 창의 이름을 지정
선택적인 값으로 기본값은 "_blank" 이다.
값 명칭 | 설명 |
_blank | 기본값, 새 창이 열림 |
_parent | 부모 프레임에 열림 |
_self | 현재 페이지를 대체 |
_top | 로드된 프레임셋 대체 |
name (임의의 이름) |
새 창이 열리고 창의 이름 지정 동일한 이름에 다시 open() 하는 경우 기존 열린 창의 내용 변경됨 다른 이름 사용 시 또 다른 새 창이 열림 |
④ specs
선택적인 값으로 창의 크기, 스크롤 여부, 리사이즈 가능 등의 속성을 지정
명칭 | 설명 | 사용여부 및 표시방법 |
channelmode | 전체화면으로 창이 열림 IE에서만 동작 |
yes, no |
directories | 디렉토리 버튼의 표시여부 (사용X) | yes, no |
fullscreen | 전체 화면 모드 IE에서만 동작 |
yes, no |
location | 주소 표시줄 사용여부 지정 Opera에서만 동작 |
yes, no |
menubar | 메뉴바 사용여부 지정 | yes, no |
resizable | 창의 리사이즈 가능 여부 지정 IE에서만 동작 |
yes, no |
scrollbars | 스크롤바 사용여부 지정 IE, Firefox, Opera에서 동작 |
yes, no |
status | 상태바 보여줄지 여부 지정 | yes, no |
titlebar | 타이틀바 보여줄지 여부 지정 호출 응용 프로그램이 HTML 응용 프로그램이거나 신뢰할 수 있는 대화 상자가 아닌 경우 무시 |
yes, no |
toolbar | 툴바 보여줄지 여부 지정 IE, Firefox에서 동작 |
yes, no |
height | 창 높이 지정 | pixels |
width | 창 너비 지정 | pixels |
left | 창 화면 왼쪽 위치 지정 음수 사용 불가 |
pixels |
top | 창 화면 위쪽 위치 지정 음수 사용 불가 |
pixels |
⑤ replace : 히스토리 목록에 새 항목을 만들지, 현재 항목을 대체할지 지정
- true : 현재 히스토리를 대체합니다.
- false : 히스토리에 새 항목을 만듭니다.
ex) popup.html 을 지정된 크기의 창에 팝업하는 것
var win = window.open("/popup.html", "PopupWin", "width=500, height=600");
ex) 빈 창을 열고 내용을 동적으로 적는 것
var win = window.open("", "PopupWin", "width=500, height=600");
win.document.write("<p>새 창에 표시 될 내용 부분</p>");
ex) 창 컨트롤을 모두 활성화
var win = window.open("/popup.html", "_blank", "toolbar=yes, scrollbars=yes, resizable=yes, top=500, left=500, width=400, height=400");
# 페이징 : 불러올 데이터를 각 페이지로 분할하여 편리하게 볼 수 있게 하는 기법
ㄴ ex) 게시판 내 페이지 이동
"select * from 테이블명 order by 게시글번호 desc limit 시작 행, 출력할 갯수;
ex)
"select * from board order by num desc limit" + curPage*sizeOfPage+", "+sizeOfPage;
'Web > JSP' 카테고리의 다른 글
[필기정리] Day107-1 - filter class, listener class, ContextParam 등 (0) | 2020.11.24 |
---|---|
[실습문제] Day86 - MVC Model2를 활용한 회원형 게시판 만들기 (0) | 2020.10.28 |
[필기정리] Day84-2 - EL 문제, JSTL 등 (0) | 2020.10.26 |
[필기정리] Day84-1 - EL(Expression Language), ContextParam 등 (0) | 2020.10.26 |
[필기정리] Day83 - MIME, Proxy server, http 응답코드 등 (0) | 2020.10.26 |