종료하기 전 티스토리 네이버 로그아웃 할 것
1. 툴
동일
추가시:
2. 폴더
동일
추가시:
짤.egg
workspace_mvc.egg
홈페이지도 쓸 거면...!!
3. 사용할 사이트
동일
추가시:
4. 공부하는 것
[37] 서블릿을 이용한 다운로드
[01] 서블릿을 이용한 다운로드
1. servlet 원리
- JSP로는 해결이 어려운 그래픽, 네트워크등의 콤포넌트 제작이 가능함.
- 웹사이트의 속도 개선을 위해 JSP보다 서블릿을 사용할 수 있으나 개발과 유지보수가
매우 어려움.
- 서블릿은 닷넷의 DLL과 비슷한 작동을 함.
- JSP는 실행시 서블릿으로 컴파일(변경)되어 실행됩니다.
WTP상에서의 서블릿 변환 위치:
test.jsp -> test_005_jsp.java -> test_005_jsp.class -> binary compile후 실행
재실행
test_005_jsp.class -> binary compile후 실행
Windows: D:\rfid02\ws_web\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\jsp_pds\org\apache\jsp\pds\test
Linux:
/home/dev/ws_jsp/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/work/Catalina/localhost/www_jsp/org/apache/jsp
//외울 것!
- 서블릿의 생명주기: 관련 메소드가 자동으로 호출됨(CallBack Method).
. service()메소드에서 요청 처리를 하는 경우
init() ---> service() ---> destroy()
init() ---> doGet(), doPost() ---> destroy()
★ Tomcat 서버에서 jsp 파일이 실행되는 경로
-------------------------------------------
컴파일 순서: index.jsp ---> index_jsp.java ---> index_jsp.class 컴파일 ---> 실행
메소드 실행 순서: _jspInit() --> _jspService() --> _jspDestroy()
- 서블릿에서의 출력
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("euc-kr"); //한글처리 하려고! :>
out.println("서블릿에서의 출력 테스트");
// init = 응애 메소드 -.-) (최초에 한번 객체가 생성된 이후에 자동으로 호출되는 메소드 - 자기가 알아서)
// service = service가 호출되어지면 doGet이나 doPost를 자동으로 호출함! 방식의 차이임 -
get방식 호출은 doGet / post방식 호출은 doPost
Init(): 처음 호출시
destroy(): 마지막에 연결 객체 끊어줄 때 자동으로 호출되는 메소드
service: 서블릿을 요청할 때 마다 호출되는 메소드 - 얘는 요청해야만 호출됨 - doGet doPost service는 요청이 있어야만 호출된다.
response.setContentType("text/html~); 은 page지시자의 contenttype이랑 같은 거임
---------------------------------------------------------------------------------------------------------------
코드
package utility;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FileDownload extends javax.servlet.http.HttpServlet {
//public class FileDownload extends HttpServlet 이거랑 같은 거임! :>
//얘를 상속해야만 servlet인 것
// 서블릿 버전, 생략 가능
static final long serialVersionUID = 1L;
// web.xml에 접근 가능 - 서버하고 소통하려면 web.xml에 접근해야 한다.
private ServletConfig config = null;
// 기본 생성자
public FileDownload() {
super();
}
/**
* 톰캣 실행시 최초 1번만 실행 됩니다. init()은 생략가능
*
* @param config
* web.xml에 접근가능, 서블릿 환경 정보 저장 객체
*/
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
// Form - get 방식 처리
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
// Form - post 방식 처리
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
//위에 두 개... doGet이랑 doPost의 parameter를 보면 service()의 매개변수를 알 수 있음.
protected void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext ctx = config.getServletContext();
// 저장 폴더를 절대 경로로 변환
String dir = ctx.getRealPath(request.getParameter("dir"));
// 파일명 받기
String filename = request.getParameter("filename");
// 전체 절대 경로 조합
File file = new File(dir + "/" + filename);
String fileStr = dir + "/" + filename;
String contentType = getType(fileStr);
System.out.println("다운로드 타입: " + contentType);
String disposition = getDisposition(filename, getBrowser(request));
response.addHeader("Content-disposition", disposition);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setContentLength((int) file.length());
response.setContentType(contentType);
response.setHeader("Connection", "close");
// 파일을 읽어올 크기 지정
byte buffer[] = new byte[4096];
try {
if (file.isFile()) {
// 파일을 읽어 오는 역활
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
// 사이트에 접속된 접속자에게 출력
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
int read = 0;
// bis.read(buffer): 파일에서 4KB씩 읽어서
// buffer에 저장
// 파일의 끝이면 -1
while ((read = bis.read(buffer)) != -1) {
// 접속자로 출력
bos.write(buffer, 0, read);
} // while
bis.close();
bos.close();
}
} catch (Exception e) {
}
}
public String getType(String fileUrl) {
String type = "";
fileUrl = "file:" + fileUrl;
try {
URL u = new URL(fileUrl);
URLConnection uc = u.openConnection();
type = uc.getContentType();
} catch (Exception e) {
System.out.println(e.toString());
}
return type;
}
public String getBrowser(HttpServletRequest request) {
String header = request.getHeader("User-Agent");
if (header.indexOf("MSIE") > -1) {
return "MSIE";
} else if (header.indexOf("Chrome") > -1) {
return "Chrome";
} else if (header.indexOf("Opera") > -1) {
return "Opera";
}
return "Firefox";
}
public static synchronized String getDisposition(String filename, String browser) {
String dispositionPrefix = "attachment;filename=";
String encodedFilename = null;
try {
if (browser.equals("MSIE")) {
encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
} else if (browser.equals("Firefox")) {
encodedFilename =
"\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.equals("Opera")) {
encodedFilename =
"\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.equals("Chrome")) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < filename.length(); i++) {
char c = filename.charAt(i);
if (c > '~') {
sb.append(URLEncoder.encode("" + c, "UTF-8"));
} else {
sb.append(c);
}
}
encodedFilename = sb.toString();
} else {
System.out.println("Not supported browser");
}
} catch (Exception e) {
}
return dispositionPrefix + encodedFilename;
}
}
이것은 FileDownload.java
---------------------------------------------------------------------------------------------------------------
D:\javadb\web\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\Homepage\WEB-INF\classes
이렇게 WEB-INF에 있는 것은 브라우저에서 접근 불가능이지만
servlet은 가능! :>
new 이런거 안하고 톰캣이 알아서 객체를 생성함
web.xml이라는 곳에다가 서블릿의 객체를 생성해달라고 선언해놔야함
1. 브라우저에서 어떠한 뭐시기를 함
2. 서부릿에서 web.xml에다가 객체를 생성해달라고 부탁함
3. 톰캣이 객체를 생성함

저렇게 web-inf에다가 web.xml을 만들어준다
---------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>jsp_blog</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>
<session-config>
<session-timeout>30</session-timeout> <!-- 30분으로 연장한 것! 기준이 분임 :> -->
</session-config>
<!-- ************************************************************** -->
<!-- 파일 다운로드 서블릿 접속 주소가 http://127.0.0.1:8000/download로 시작하면 자동으로 utility.FileDownload
클래스가 작동되게 되어 있습니다. , 프로젝트 전체에서 사용가능 -->
<servlet><!-- 서블릿 이름과 서블릿 클래스 선언 -->
<servlet-name>FileDownload</servlet-name><!-- 이름은 아무거나 써도 됨 -->
<servlet-class>utility.FileDownload</servlet-class><!-- 이건 매우 중요함 -->
</servlet>
<!-- 요기까지 하면 톰캣에서 객체를 생성해달라고 요청하는 것입니다 :) 그래서 요기까지만 해도 사용은 가능함! -->
<!-- 근데 브라우저 상에서 요청을 해야 하니까 servlet-mapping을 해줘야 함 -->
<servlet-mapping><!-- URL상으로 접근해야하는 경로명 -->
<servlet-name>FileDownload</servlet-name><!-- 위에 객체랑 같은 이름 -->
<url-pattern>/download</url-pattern><!-- servlet 요청을 저 경로로 하겠다. -->
</servlet-mapping>
<!-- ************************************************************** -->
</web-app>
----------------------------------------------------------------------------------------------------------------------------------------------
아 수업 하니까 넘나 재밌습니다.
셀프 제작 넘나 힘든것
---------------------------------------------------------
INSERT INTO member(id, passwd, mname, tel, email, zipcode,
address1,address2, job, mdate, grade)
VALUES('admin', '1234', '관리자', '123-1234', 'admin@mail.com',
'123-123','서울시','종로구' ,'A01', sysdate, 'A');
member.sql에 이거 넣었음! :>
그리고 WebContent에 admin 이라는 폴더 만들어서 member의 list를 옮겼음
이건 코드 http://lectureblue.pe.kr/reqtiles/read.jsp?bbsno=107&nowPage=1&col=&word=&code=7
여깃거 볼 것... -.-
※※ 브라우저 주소창에서 직접 주소를 입력하여 회원목록 페이지를 요청시
권한이 없어도 그페이지가 열리는 버그발생
Filter를 이용해서 버그 수정 할 수 있다.
[02] Filter
- 접속자의 요청을 처리하기전에 필터링하여 정상적인 요청인지 확인하고
페이지를 전송해 줄 수 있습니다.
- 처리 결과를 접속자에게 전송하기전에 필요한 처리를 중간에서 가로채어
할 수 있습니다.
가로채기!
필터는 인터페이스! :>
뭔가 엄청 많이 합니다.
[38] [참고] 관리자 인증의 구현, Filter
[01] 회원목록 - 관리자만 접근해야 하므로 admin폴더를 만들고 list.jsp 구현
- member.sql에서 admin계정 추가
- 관리자 권한이 있어야만 메뉴에 회원목록이 보여짐
- menu/top.jsp 회원목록 메뉴 등록
<%@ page contentType="text/html; charset=UTF-8" %>
<%
String root = request.getContextPath();
String id=(String)session.getAttribute("id");
String grade=(String)session.getAttribute("grade");
%>
<html>
<head>
<style type="text/css">
ul#menu li{
display : inline;
}
ul#menu li a{
background-color: black;
color:white;
pading : 10px 20px;
text-decoration:none;
border-radius:4px 4px 0 0;
}
ul#menu li a:hover{
background-color: orange;
}
li#admin{
float:right;
padding-right: 30px
}
</style>
</head>
<body>
<!-- 상단 메뉴 -->
<div style="background-color: #EEEEEE;">
<table style="width: 100%">
<tr>
<td>
<img src="<%=root %>/menu/images/main-03.jpg" width='100%' height='100%'>
</td>
</tr>
<tr>
<td>
<ul id="menu">
<li><a href="<%=root %>/index.jsp">홈</a></li>
<%if(id==null){ %>
<li><a href="<%=root %>/member/loginForm.jsp">로그인</a></li>
<li><a href="<%=root %>/member/agreement.jsp">회원가입</a></li>
<li><a href="<%=root %>/member/idFindForm.jsp">아이디찾기</a></li>
<li><a href="<%=root %>/member/pwFindForm.jsp">비밀번호찾기</a></li>
<%}else{ %>
<li><a href="<%=root %>/member/logout.jsp">로그아웃</a></li>
<li><a href="<%=root %>/member/read.jsp">나의정보</a></li>
<li><a href="<%=root %>/member/updateForm.jsp">정보수정</a></li>
<li><a href="<%=root %>/member/deleteForm.jsp">회원탈퇴</a></li>
<li><a href="<%=root %>/member/updatePasswdForm.jsp">패스워드변경</a></li>
<%} %>
<li><a href="<%=root %>/bbs/list.jsp">게시판목록</a></li>
<li><a href="<%=root %>/memov3/list.jsp">메모목록</a></li>
<%if(id!=null && grade.equals("A")){ %>
<li id="admin"><a href="<%=root %>/admin/list.jsp">회원목록</a></li>
<%} %>
</ul>
</td>
</tr>
</table>
</div>
<!-- 상단 메뉴 끝 -->
<!-- 내용 시작 -->
- index.jsp 페이지의 변경 : 관리자로 로그인하였음을 나타냄
<%@ page contentType="text/html; charset=UTF-8" %>
<%
request.setCharacterEncoding("utf-8");
String id=(String)session.getAttribute("id");
String grade=(String)session.getAttribute("grade");
String title="나의 여행 블로그";
if(id!=null && grade.equals("A")){
title="관리자 페이지";
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
font-family: gulim;
font-size: 20px;
}
</style>
<link href="./css/style.css" rel="Stylesheet" type="text/css">
</head>
<!-- *********************************************** -->
<body leftmargin="0" topmargin="0">
<jsp:include page="/menu/top.jsp" flush="false"/>
<!-- *********************************************** -->
<DIV class="title"><%=title %></DIV>
<DIV class='content'>
<IMG src='./images/wol01.jpg' width='50%'><br>
<%
if (id == null){%>
<input type='button' value='로그인'
onclick="location.href='./member/loginForm.jsp'">
<%
}else{%>
<input type='button' value='로그아웃'
onclick="location.href='./member/logout.jsp'">
<%
}%>
</DIV>
<DIV class="bottom"></DIV>
<!-- *********************************************** -->
<jsp:include page="/menu/bottom.jsp" flush="false"/>
</body>
<!-- *********************************************** -->
</html>
※※ 브라우저 주소창에서 직접 주소를 입력하여 회원목록 페이지를 요청시
권한이 없어도 그페이지가 열리는 버그발생
Filter를 이용해서 버그 수정 할 수 있다.
[02] Filter
- 접속자의 요청을 처리하기전에 필터링하여 정상적인 요청인지 확인하고
페이지를 전송해 줄 수 있습니다.
- 처리 결과를 접속자에게 전송하기전에 필요한 처리를 중간에서 가로채어
할 수 있습니다.
1. request, response 객체를 최종적으로 처리되기 전에 변경 할 수 있는
기능를 제공합니다.
- 유형 1
jsp ---> request ---> Filter ---> JSP, Servlet, Beans
│
│
jsp <--- reponse <--- Filter <------┘
- 유형 2: Filter chain
jsp ---> request ---> Filter ---> Filter ---> JSP, Servlet, Beans
│
│
jsp <--- reponse <--- Filter <--- Filter <-------┘
2. 관련 인터페이스, 클래스
- javax.servlet.Filter Interface
. 필터 구현 인터페이스
- javax.servlet.ServletRequestWrapper class
. 요청 변경시 상속받아 구현
- javax.servlet.ServletResponseWrapper class
. 처리 결과 변경시 상속받아 구현
3. Filter Interface
- public void init(FilterConfig filterConfig) throws ServletException
. 필터 생성시 호출되며 초기화 합니다.
- public void doFilter(ServletRequest request, servletResponse response,
FilterChain chain) throws java.io.IOException, ServletException
. 필터와 관련된 로직을 구현합니다.
. chain을 따라 다음 필터로 이동하며, 체인의 가장 마지막에는 클라이언트가
요청한 파일이 위치합니다.
- public void destroy()
. 필터가 삭제될 때에 호출됩니다.
[02] Filter 로그인 실습
1. Filter 구현 java source
- 브라우저 주소창에서 직접 주소를 입력하여 페이지를 요청시
관리자 권한이 부족하면 자동으로 loginForm 페이지로 이동
>>>>> AdminLoginCheckFilter.java
package utility;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class AdminLoginCheckFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Filter가 요청 중간에서 request 객체를 추출합니다.
HttpServletRequest httpRequest = (HttpServletRequest)request;
// 새로운 세션을 생성하지않고 request 객체에서 기존의 세션 반환
HttpSession session = httpRequest.getSession(false);
// 로그인 하지 않았다고 가정
boolean login = false;
if (session != null) { // session 객체가 생성되어 있는지 확인
// 로그인을 했으면서 관리자인지 확인합니다.
if (session.getAttribute("id") != null
&& session.getAttribute("grade").equals("A")) {
login = true; // 관리자라면
}
}
// 정상적으로 로그인이 되었다면 요청 페이지로 이동합니다.
if (login) {
chain.doFilter(request, response); //요청 페이지로 이동
} else {
// 로그인이 안되었다면 로그인 페이지로 이동
RequestDispatcher dispatcher =
request.getRequestDispatcher("/member/loginForm.jsp");
dispatcher.forward(request, response);
}
}
public void destroy() {
}
}
2. WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>blog</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>AdminLoginCheckFilter</filter-name>
<filter-class>utility.AdminLoginCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminLoginCheckFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
</web-app>
>>>>> loginForm.jsp 의 <Form>tag의 action속성 경로 수정
<%@ page contentType="text/html; charset=UTF-8" %>
<%
String root = request.getContextPath();
request.setCharacterEncoding("utf-8");
String c_id="";//id저장여부
String c_id_val="";//id저장변수
Cookie[] cookies = request.getCookies();
Cookie cookie = null;
if(cookies!=null){
for(int i=0; i<cookies.length; i++){
cookie = cookies[i];
if(cookie.getName().equals("c_id")){
c_id = cookie.getValue();
}else if(cookie.getName().equals("c_id_val")){
c_id_val = cookie.getValue();
}
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
font-family: gulim;
font-size: 24px;
}
</style>
<link href="../css/style.css" rel="Stylesheet" type="text/css">
</head>
<!-- *********************************************** -->
<body leftmargin="0" topmargin="0">
<jsp:include page="/menu/top.jsp" flush="false"/>
<!-- *********************************************** -->
<DIV class="title">로그인</DIV>
<FORM name='frm' method='POST' action='<%=root %>/member/loginProc.jsp'>
<TABLE class='table'>
<TR>
<TH>아이디</TH>
<TD>
<input type="text" name="id" size="20" value="<%=c_id_val%>">
<input type="checkbox" name="c_id" value="Y"
<% if(c_id.equals("Y")){out.print("checked=checked ");} %>
/>ID저장
</TD>
</TR>
<TR>
<TH>비밀번호</TH>
<TD><input type="password" name="passwd" size="20"></TD>
</TR>
</TABLE>
<DIV class='bottom'>
<input type='submit' value='로그인'>
<input type='button' value='회원가입' onclick="location.href='agreement.jsp'">
</DIV>
</FORM>
<!-- *********************************************** -->
<jsp:include page="/menu/bottom.jsp" flush="false"/>
</body>
<!-- *********************************************** -->
</html>
원문 : Struts 처음 배우기 (손권남)
JSP/Servlet 에는 현재 작업중인 페이지에서 다른 페이지로 이동하는 두 가지 방식의 페이지 전환 기능이 있다. 하는 Forward 이고 하나는 Redirect 이다.
- Forward : Web Container 차원에서 페이지 이동만 있다. 실제로 웹 브라우저는 다른 페이지로 이동했음을 알 수 없다. 그렇기 때문에, 웹 브라우저에는 최초에 호출한 URL이 표시되고 이동한 페이지의 URL 정보는 볼수 없다. 동일한 웹 컨테이너에 있는 페이지로만 이동할수 있다. 현재 실행중인 페이지와 Forward에 의해 호출될 페이지는 request와 response 객체를 공유한다.
- Redirect : Web Container 는 Redirect 명령이 들어오면 웹 브라우저에게 다른 페이지로 이동하라고 명령을 내린다. 그러면 웹 브라우저는 URL을 지시된 주소로 바꾸고 그 주소로 이동한다. 다른 웹 컨테이너에 있는 주소로 이동이 가능하다. 새로운 페이지에서는 request 와 response 객체가 새롭게 생성된다.
출처:
http://uiandwe.tistory.com/381
------------------------------
MVC는 비번.. IOC
그리고 D:\javadb\web\workspace_mvc
만들었당 :>
그리고 저길로 workspace 바꾼 다음에 oracle 연결했음! :>
이건 좀 찍을까!
----------------------
이거 new Template임
<%@ page contentType="text/html; charset=UTF-8" %>
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
font-family: gulim;
font-size: 20px;
}
</style>
<link href="../css/style.css" rel="Stylesheet" type="text/css">
</head>
<!-- *********************************************** -->
<body>
<jsp:include page="/menu/top.jsp" flush="false"/>
<!-- *********************************************** -->
<DIV class="title"></DIV>
<FORM name='frm' method='POST' action='./.do'>
<TABLE class='table'>
<TR>
<TH></TH>
<TD></TD>
</TR>
</TABLE>
<DIV class='bottom'>
<input type='submit' value=''>
<input type='button' value='' onclick="location.href=''">
</DIV>
</FORM>
<!-- *********************************************** -->
<jsp:include page="/menu/bottom.jsp" flush="false"/>
</body>
<!-- *********************************************** -->
</html>
이런 Spring ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
[03] [MVC] Model 2(MVC:Model, View, Controller)의 이해, MVC 개발 순서
[01] Model 2(MVC:Model, View, Controller)의 이해

Model - Beans 같은 거
View - jsp html 같은 거 ㅋㅋㅋㅋㅋ
Controller - Servlet으로 생성할 거임여
- Web Application Framework의 발전 형태
CGI --> Servlet --+-> JSP --> MVC --> Framework --> Struts 1.X, WebWork --> Struts + WebWork --> Spring, Struts 2.0
|
+-> Beans --> Framework --> EJB 2.X --> Hibernate, IBatis --> EJB 3.0
//CGI에서 동시 접속자가 많아지면 깨꼬댁해서(메모리 과부하인것) - Servlet으로 발전함 :>!
//근데 서부릿이 넘나 안이뻐서 우리의친구 JSP가 나왔습니다
//HTML 안에 JSP가 포함된 거라 넘나 이쁜 것
//MVC는 MVC알못이랑 잘암이랑 같이 하면 암이 걸리는 것입니다
//1. 잘할것 2. 못하지않을것
//패턴을 알지 못하면 **같은 경우가 됩니다! :>
//그래서 이 **같은 거를 해결하려고 Framework를 만듬! :>
//이거 넘나 조은 것입니다 - MVC는 이상하게 짜도 ***안하는데 얘는 아예 안됨
//그리고 스트러치랑 웹워크를 합친게 쓰프링임미다
//그래서 쓰트러치 안배우고 쓰프링만 배움 우리의 친구임
//그래서 쓰트러치 2.0도 나왔는데 스프링만씀미다
//빈즈는 또 다른 우리의친구인데 - EJB라는 게 있는데 이게 가격이 창렬이라서 (기본 천만원ㅋㅋㅋㅋㅋㅋ)
그래서 아이바티쓰가 나왔는데 신상은 마이바티스임 아! 이게 아이바티스야? ㅋㅋㅋㅋㅋㅋ
//반가운것! :D 하이버네이트는 sql 자동 생성되는 넘나 좋은 것입니다
// 근데 나 가르치려면 돈 드니까 그냥 아이바티스나 마이바티스나 둘 중 하나 씀...
// 개발자 하기 넘나 힘든것 ㅋㅋㅋㅋㅋㅋㅋㅋ 뭘 다 해야 하네
- Client의 요청을 처리하는 객체를 Servlet Controller로 단일화해
인증, 권한, 국제화등 여러 통합된 기능을 쉽게 구현 할 수 있습니다.
- 비즈니스 로직을 처리하는 모델과 결과 화면을 보여주는 뷰(JSP)가
분리되어 있습니다.
- 모델과 뷰, 컨트롤러가 분리되어 있어 변경이 쉽고 유지 보수 비용을
획기적으로 절감할 수 있는 콤포넌트 기반 기술입니다.
. Model: JSP Beans(DTO, Manager Class, DAO), EJB
. View: JSP, HTML
. Controller: Servlet
//아까는 컨트롤러가 없어서 필터로 한번 걸렀음... 'ㅅ')...
- 개발인력이 MVC에 대한 이해가 제대로 서 있지 않으면 Model1보다
개발 속도가 느립니다. 하지만 이해를 하고 있다면 속도가 훨씬
빠르고 유지보수가 신속한 사이트를 제작할 수 있습니다.
- MVC 모델은 매우 유지보수성이 좋은 구조를 가지고 있으나 개발자가
web application의 기능을 전부 구현해야 함으로 많은 부담이 발생하게
되며 이런 프로젝트에서 공통적으로 쓰이는 기능을 구현해 솔루션화
한 프레임웍이 Spring, 스트럿츠(Struts) 입니다.
1. model1 과 model2의 비교
- JSP Model 1 - 장점
. 기본적인 HTML, JavaScript, JAVA만 알아도 배우기 쉽니다.
. 객체지향 원리를 잘 몰라도 기능을 구현 할 수 있습니다.
. 처리 로직이 jsp 페이지상에 JAVA 코드로 구현 되어 있습니다.
- JSP Model 1 - 단점
. 디자인(HTML, CSS, JavaScript)과 로직(JAVA)이 혼합되어 있어
소스 수정시 예상하지 못한 곳에서 많은 시간이 지연됩니다.
. 같은 JAVA코드가 여러 JSP페이지에 중복되어 있어 소스 수정이
어렵습니다.(SSI로 일부 해결 가능)
. 권한등의 구현시 모든 jsp페이지 상에 SSI등을 이용해 구현해야 합니다.
(Filter로 일부 해결 가능)
- JSP Model 1 변형
. Interface, Manager, DAO, DTO, Connection Pool, Filter등으로 JSP Model 1을 개선
할 수 있습니다.
- JSP Model 2 - 장점
. Client의 요청을 받는 부분, 처리 로직 부분, 뷰 부분이 분리되어 있어
유지보수가 편리 합니다.
. 모든 기능이 세분화해 구조를 이루고 있음으로 기능 확장이 용이합니다.
. 컨트롤러 서블릿에서 권한 및 인증 구현을 편리하게 할 수 있습니다.
- JSP Model 2 - 단점
. 디자인 패턴등의 개념과 자바언어를 잘 알고 있어야 합니다.
. Application이 처리 파트별로 나뉘어져 있음으로 개발 작업의 양이
많습니다.
. 디버깅 작업을 처리 파트별로 살펴야 함으로 어려운 부분이 있습니다.
. 개발자들이 MVC에대한 개념을 가지고 있어야 효과를 볼 수 있습니다.
※ Model1도 design pattern, beans, template적용등을 사용하여 어느정도
성능 향상을 가져올 수 있습니다. 하지만 프로젝트의 규모가 커지면
유지보수에 어려움이 발생하게 됩니다.
실제경로와 요청url경로를 잘 구분해야 한당 :>!
http://pc-cat.tistory.com/entry/160405-17%EC%9D%BC%EC%B0%A8
이거 model1 배울 때 그렸던 것!
- request 객체(JSP 내부 객체)
request 객체는 클라이언트로부터 값을 가져오는 목적으로 사용되나
값을 출력하는 목적으로도 사용됩니다.
- 컨트롤러(Controller)
. 어플리케이션의 흐름 제어나 사용자의 처리 요청을 구현합니다.
. 사용자 인증, 보안 설정이라든지 전체 어플리케이션에 영향을 미치는 요소를
구현 합니다.
. 사용자의 요청에 대해서 알맞은 모델을 사용하고 사용자에게 보여줄 뷰를 선택하기만
하면 됩니다.
. Servlet 으로 제작
- 모델(Model) = 빈즈! :D
. 비즈니스 로직과 관련된 부분만 처리합니다.
. 데이터베이스 관련 로직을 구현합니다.
. JSP Beans, EJB Component, DAO, DTO, Manager
- 뷰(View)
. 사용자에게 알맞은 화면을 보여주는 역활만 수행합니다.
. JSP, EL, JSTL, Custom Tag, XML

이건 servlet이 응답하는 거 같지만 내부적으로 jsp를 처리해 준 것
내가 외우실 것
4. Controller의 처리순서
Browser --------> Servlet(Controller)
1. HTTP 요청 받음, doGet(), doPost() 메소드 호출 - 서비스! :D
2. 클라이언트가 요구하는 기능을 분석(방명록의 경우 글쓰기등)
3. 요청한 비즈니스 로직을 처리하는 Model 사용, Business Logic Class
4. 결과를 request 또는 session의 setAttribute()메소드를 사용하여 저장
5. 알맞은 뷰 선택 후,
6. 뷰로 포워딩(또는 리다이렉트), jsp 페이지로 이동
↙
JSP
↙
HTTP 응답
↙
Browser
3번은 생략 가능! :D - 왜냐면 그냥 출력하는 경우도 있으니까! :>
근데 그냥 순서니까 외우는거시빈다
4번에 리퀘스트도 속성값 저장할 수 있는 것
5번에서는 서블릿이 뷰를 선택하시는것 - JSP친구들
6번에서 포워딩인지 리다이렉트인지 확인 해 보 ㅏ야 함!
리퀘스트 - 포워드 ㅇㅋ - 살아남아있다! :D
리다이렉트 - 세션만 ㅇㅋ
[02] MVC App 개발 순서
1. Web Application 개발 순서
① DBMS 설정
② DTO(Data Transfer Object) Class 제작
③ DAO(Data Access Object) Class 제작
④ Manager Class 제작
⑤ Mgr/DAO test
⑥ JSP 생성 연동
4번만 빼면 다 해본거십니다
2. MVC Web Application 개발 순서
① DBMS 설정
② DTO(Data Transfer Object) Class 제작
③ DAO(Data Access Object) Class 제작
④ Manager Class 제작
⑤ Mgr/DAO test
⑥ Servlet Controller 제작
⑦ Action Interface 제작
⑧ Action 구현 Class 제작
. Manager Class 연동
⑨ JSP 생성 연동
이제 6번인 서블렛 컨트롤러도 만들고 액션 인터페이스도 만듬!
액션이 뭐냐면 서블릿이 넘나 바쁘니까
서블릿에는 기본적인 부분만 놔두고
액션 인터페이스한테 위임을 시키는 거십니다
액션 인터페이스는 컨트롤러의 뻬이비인것
얘가 하는 걸 나눠서 합시다 입니다
[04] [MVC] Properties class, String class, Class class
[01] Properties Class의 사용
- 키와 값의 구조를 가지고 있으며 특정 객체를 생성하는 경우에 초기값으로 많이
사용합니다.
- 상속 구조
java.lang.Object
java.util.Dictionary<K,V>
java.util.Hashtable<Object,Object>
java.util.Properties<String,String>
얘는 맵 쓸 때 해본 우리의친구임
http://lectureblue.pe.kr/reqtiles/read.jsp?bbsno=135&nowPage=2&col=&word=&code=9
프로퍼티 만드러서 복붙할 때
#----------------------------------
# jdbc.properties
#----------------------------------
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:ora10g2
account=jsp21000_08_1
password=oracle
#driver=org.gjt.mm.mysql.Driver
#url=jdbc:mysql://127.0.0.1:3306/ojtdb?useUnicode=true&characterEncoding=euckr
#account=ojtuser
#password=1234
#driver=org.gjt.mm.mysql.Driver
#url=jdbc:mysql://127.0.0.1:3306/******?useUnicode=true&characterEncoding=euckr
#account=******
#password=******
요렇게 127.0.01로 바꿈!
아 뒤에 ora10g2랑 계정 패스워드도 바꿈
#----------------------------------
# jdbc.properties
#----------------------------------
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:XE
account=soldesk
password=1234
#driver=org.gjt.mm.mysql.Driver
#url=jdbc:mysql://127.0.0.1:3306/ojtdb?useUnicode=true&characterEncoding=euckr
#account=ojtuser
#password=1234
#driver=org.gjt.mm.mysql.Driver
#url=jdbc:mysql://127.0.0.1:3306/******?useUnicode=true&characterEncoding=euckr
#account=******
#password=******
------------------------
중요한 것: 프로퍼티는 문자열 타입의 키와 값을 가진다! :D
property는 keyset()
--------------------------
package test.properties2;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Iterator;
import java.util.Properties;
public class PropertyTest {
public static void main(String[] args) {
Properties prop = new Properties();
FileInputStream fis = null; // 파일을 읽어 오는 역활을 합니다.
// 경로 산출
File file = new File("jdbc.properties");
System.out.println("절대경로: " + file.getAbsoluteFile());
try {
fis = new FileInputStream(file);
//속성 파일을 객체로 로딩, 키와 문자열 값으로 저장됩니다.
prop.load(fis);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) try { fis.close(); } catch(IOException ex) {}
}
// properties 객체에서 키목록을 추출합니다.
// driver, url, account, password
Iterator keyIter = prop.keySet().iterator();
while( keyIter.hasNext() ) {
String key = (String)keyIter.next(); //키 추출
String value = prop.getProperty(key); //키에 따른 값 추출
System.out.println(key + "=" + value);
}
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";
String driver = "";
String url = "";
String account = "";
String password="";
driver = prop.getProperty("driver");
url = prop.getProperty("url");
account = prop.getProperty("account");
password = prop.getProperty("password");
try{
Class.forName(driver);
con = DriverManager.getConnection(url, account, password);
sql = "SELECT count(*) cnt FROM tab";
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
if (rs.next()){
System.out.print(account + " 계정의 테이블 갯수: ");
System.out.println(rs.getInt("cnt"));
}
}catch(Exception e){
System.out.println(e);
}
}
}
이거 돌렸을 때 오류나면
properties에 가서 빈 문자열 없애주면 됨니당 :D
출처: http://dlalsqhr.tistory.com/entry/webxml-%EC%84%A4%EC%A0%95
web.xml이란...
Web Application의 구조
Root
|
html img WEB_INF(web.xml)
| | |
classes tld lib
DD:(Deployment Descriptor)로 각 어플리케이션의 환경을 설정하는 부분을 담당한다. (deploy)'배치'
WAR 파일이 패키지 될 때 같이 포함되며 root directory 밑에 /WEB-INF 디렉토리에 위치한다.
web.xml 의 구조
xml 정의와 schema 선언
<?xml version="1.0" encoding="EUC-KR"?> |
위 스키마는 sun 사에서 미리 정의된것이다.
웹 어플리케이션의 환경 설정
<web-app> <servlet> <servlet-name> 사용되는 클래스명 </servlet-name> "가" <servlet-class>클래스 경로(패키지명.클래스) </servlet-class> "나" </servlet> <servlet-mapping> <servlet-name> 사용되는 클래스명 <servlet-name> "다" <url-pattern>서버에서 사용할 url-pattern ( /url )</url-pattern> "라" </servlet-mapping> 실행순서. 라 -->다--->가--->나(패키지명.클래스 실행) <mime-mapping> <extension>txt</extension> <mime-type>text/plain</mime-type> </mime-mapping> <welcome-file-list> <welcome-file>기본 파일 경로</welcome-file> <welcome-file>두번째 시작하는 파일 경로</welcome-file> </welcome-file-list> <taglib> <taglib-uri>태그라이브러리</taglib-uri> <taglib-location>경로</taglib-location> </taglib> </web-app> |
web.xml은 xml파일이다. 따라서 xml 작성과 동일한 규칙이 적용된다.
환경설정은 <web-app>으로 시작하고 </web-app>로 끝난다. 그외 삽입되는 요소로는 다음과 같다.
.ServletContext Init Parameters
.Session Configuration
.Servlet/JSP Definitions
.Servlet/JSP Mappings
.Mime Type Mappings
.Welcom File list
.Error Pages
web.xml의 elements의 순서각 element의 순서는 아래 순서에 따른다.
<icon?>, <display-name?>, <description?>, <distributable?>, <context-param*>, <filter*>, <filter-mapping*>, <listener*>, <servlet*>, <servlet-mapping*>, <session-config?>, <mime-mapping*>, <welcome-file-list?>, <error-page*>, <taglib*>, <resource-env-ref*>, <resource-ref*>, <security-constraint*>, <login-config?>, <security-role*>, <env-entry*>, <ejb-ref*>, <ejb-local-ref*> |
자주 쓰이는 elements 예제
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd> <web-app> <display-name>어플리케이션 이름</display-name> <description>어플리케이션 설명</desccription> <!-- 서블릿 매핑 : 보안과 주소를 간략화 하기 위해 사용 http://localhost/servlet/KCount 이렇게 사용가능 --> <servlet> <servlet-name>KCount</servlet-name> <servlet-class>kr.pe.kkaok.mycount.KCount</servlet-class> </servlet> <!-- load-on-startup 옵션은 서버 구동시 자동으로 시작 되도록 하는 것이다. --> <servlet> <servlet-name>PoolManager</servlet-name> <servlet-class>kr.pe.kkaok.jdbc.PoolManager</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- 서블릿 매핑 : 위에서 servlet 부분을 삭제한다. http://localhost/KCount 이렇게 사용가능 --> <servlet-mapping> <servlet-name>KCount</servlet-name> <url-pattern>/KCount</url-pattern> </servlet-mapping> <!-- /servlet/* 과 동일한 패턴의 요청이 들어오면 servlet으로 처리 --> <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping> <!-- 세션 기간 설정 --> <session-config> <session-timeout> 30 </session-timeout> </session-config> <!-- mime 매핑 --> <mime-mapping> <extension>txt</extension> <mime-type>text/plain</mime-type> </mime-mapping> <!-- 시작페이지 설정 --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- 존재하지 않는 페이지, 404에러시 처리 페이지 설정 --> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <!-- 태그 라이브러리 설정 --> <taglib> <taglib-uri>taglibs</taglib-uri> <taglib-location>/WEB-INF/taglibs-cache.tld</taglib-location> </taglib> <!-- resource 설정 --> <resource-ref> <res-ref-name>jdbc/jack1972</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> |
invoker 서블릿의 매핑이 보안문제로 막혀있어서 발생하는 문제로 $CATALINA_HOME/conf/web.xml를 열고 해당 부분의 주석을 제거한다. <!-- The mapping for the invoker servlet --> <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping> security-constraint 엘리먼트를 $CATALINA_HOME/conf/web.xml 파일의 welcome-file-list 엘리먼트 아래쪽 <web-app> 에 중첩되게 복사합니다. <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <security-constraint> <display-name>Default Servlet</display-name> <!-- Disable direct alls on the Default Servlet --> <web-resource-collection> <web-resource-name>Disallowed Location</web-resource-name> <url-pattern>/servlet/org.apac.
|
5. 수업
진도:
hw:
6. 할것
오늘은 http://luckybluegifs.co.vu/page/13
까지 봤습니다.
http://hong-fol.tistory.com/23
이거 참조할 것 ! :>
우리의친구 아카데미 인강좀 확인해 볼 것!