ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 모델1, 모델2 방식의 JSP -22.06.03
    웹프로그래밍 2022. 6. 3. 14:28
    728x90

    모델1: 요청이 발생했을때 요청을 해결하는것이 같이 존재 

    모델2: 요청받고있는서블릿 객체 요청을 해결하는 jsp 각자 역할 분담

    +단일책임원칙의 책임을 분리의 개념도 같이 

    중프때 : 계층형(레이어드 아키텍쳐)

    컨테이너의 역할이 어떻게 달라지느냐에 따라...

    컨테이너의 작업 결과물이 어딘가에는 존재할것이다.

    JSP컨테이너 임

    <클래스패쓰의 종류>

    2. 현재위치

    3.웹으로 따지면 바로 여기

    4.웹아이엔에프 안의 클래스패스

     

    클래스패쓰리소스 관리되고 있음

    삭제하고 서버 중지 그리고 다시 서버 시작

    (standard.jsp)브라우저 새로고침 

    다시 생겼으며 

    최초의 요청 발생했을때 jsp소스 파싱해서 만들어낸다는것 컴파일해서 클래스를 만든다는것

    클래스의 인스턴스 생성해주고 그안에 콜백메서드를 호출한다 .

     

    스페이스바 치고 수정한것 처럼 다시 저장을 하고 브라우저 새로고침을 한다.

    수정된 상태로 결과물이 다시 만들어짐

    아무리 새로고침해도 시간은 안바뀜 한번 컴파일 하게되면 재반복적으로 사용된다는것을 알 수 있다.

    수정되기전 이전의 객체 계속 사용!!!! 싱글톤의 형태로 관리되고 있음

     

    **Servlet container의 역할 
    1. 이미 등록되고 매핑 걸려있는 서블릿을 대상으로 최초의 요청이 발생하면,
       1) 해당 서블릿의 싱글턴 객체 생성(두번째 요청에서는 생략)
       2) 해당 객체의 request callback(service->doXXX)을 호출하여 요청을 처리함.
       
    **JSP container 의 역할
    1. JSP 페이지를 대상으로 서블릿 소스를 생성
    2. 컴파일
    3. 해당 서블릿의 싱글턴 객체 생성.
    4. 해당 객체의 request callback(_JSPservice) 을 호출하여 요청을 처리함.


    <JSP에서 주석의 종류>

    1)HTML, javaScript, Css  =>응답데이터 나간이후에 해결, 프론트엔드 주석(3,4)
    2)Java(Single, multiline),JSP => 처리되는 시점은 서버사이드에서 싱글톤 객체가 실행이될때 ,백엔드 주석(1,2)

    2번이 좋음 왜? 클라이언트가 보지 않아서 보안에 유용, 1번은 네트워크 부하생김

    서버사이드에서 보면 정적인 코드들(pre, script...)

     

     

    수정을 해보자

    <model1ImageStreaming.jsp>

    <%@page import="java.util.LinkedHashMap"%>
    <%@page import="java.util.Map"%>
    <%@page import="java.io.File"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
     <head>
     	<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
     </head>
    	<body>
    		<%
    		
    // 		String pattern = "<option>%s</option>";
    // 		StringBuffer options = new StringBuffer();
    // 		for(File tmp:children) {
    // 			options.append(String.format(pattern,tmp.getName()));
    // 		}
    		
    		%>
    		<h4>이미지 선택</h4>
    		<%! 
    		public File[] getChildren(File folder){
    			
    			
    			File[] children = folder.listFiles((dir,name)->{
    				
    				String mime =getServletContext().getMimeType(name);  //톰켓의 mine-mapping 이용
    				return mime !=null && mime.startsWith("image/");
    			});
    			return children;
    		}
    		%>
    		
    		<form action="<%=request.getContextPath() %>/02/streaming.do" id="imageForm"> <!-- .은 02폴더가 됨 -->
    			<select name="image">
    			<% //서블릿 소스 파생시에 지역코드화(_JSPService)
    			
    			String folderPath="D:\\contents";  //파일시스템 리소스 url가지고 있지 않음 그래서 컨트롤러 역할을 하는 서블릿 만들고있음
    			File folder = new File(folderPath);
    			File[] children =getChildren(folder);
    			for(File tmp:children) {
    			%>
    			<option><%=tmp.getName() %></option>
    			<%} %>
    <%-- 		이것을 수정	<%=options %> --%>
    				
    			</select>
    			<input type="submit" value="전송"/>
    			<div id="imageArea">
    				<!-- http://localhost/WebStudy01/02/imageForm.tmpl여기서 파악 -->
    				<!-- <img src="./streaming.do?image=%v"/>-->
    			</div>
    			<script>
    			      let selectTag = $("select[name='image']").on("change",function(){
    			         $(this.form).trigger("submit");
    			         $(this.form).submit();
    			      });
    			         let imageArea = $("#imageArea");
    			      const SRCPTRN = "<%=request.getContextPath()%>/02/streaming.do?image=%v";
    			      $("#imageForm").on("submit", function(event){
    			      event.preventDefault();
    			         //<img src="./streaming.do?image=%v"/>
    			         let imageName = $(this.image).val();
    			         let imgTag = $("<img>").attr("src", SRCPTRN.replace("%v", imageName));
    			         imageArea.html(imgTag);
    			      return false;
    			   });
    			    </script>
    						
    			
    		</form>
    	</body>
    	
    </html>

    <%!  선언문애서 선언된 변수는 JSP페이지가 Servlet으로 파싱될때 서블릿의 멤버 변수가 된다.%>

    -전역변수 및 메소드를 선언할 수 있는 영역이며 선언된 변수와 함수는 JSP페이지가 서블릿코드로 변환이 되면 서블릿 클래스의 멤버변수와 메소드로 변환됩니다.

    <% 안에 선언된 모든 자바코드는 서블릿 소스 파생시에 지역코드화 %>

     


    scope개념

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%! //전역 메소드 선언 전역변수, 전역메소드 : 공통 사용(공유)
    	//전역변수로 공유 불가 A,B -> Scope로 데이터 공유 가능
    	//factorial은 인스턴스 메소드 임 클래스모름 왜? 컨테이너 역할 즉 개발자는 인스턴스 생성,획득할 수 없음 그래서 공유가 불가능하며 private든 public이든 상관없음
    private long factorial(int num){ 
    	if(num<0)
    		throw new IllegalArgumentException("음수에 대해서는 연산 불가");
            throw : Exception 발생, throws : Exception 처리
    	if(num ==0){
    		return 1;
    	}else{
    				return num*factorial(num-1);
    	}
    }
    
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    10! 연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <%
    	int number =10;
        long result= factorial(number);
        
    %>
    <h4>10! 연산 결과:<%=result %></h4>
    </body>
    </html>

    음수가 들어갔을때


    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%! //전역 메소드 선언 전역변수, 전역메소드 : 공통 사용(공유)
    	//전역변수로 공유 불가 A,B -> Scope로 데이터 공유 가능
    	//factorial은 인스턴스 메소드 임 클래스모름 왜? 컨테이너 역할 즉 개발자는 인스턴스 생성,획득할 수 없음 그래서 공유가 불가능하며 private든 public이든 상관없음
    private long factorial(int num){ 
    	if(num<0)
    		throw new IllegalArgumentException("음수에 대해서는 연산 불가");
    	if(num ==0){
    		return 1;
    	}else{
    				return num*factorial(num-1);
    	}
    }
    
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    10! 연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <!-- <form action="명령어_요청URL" method="파라미터 전송 방법 & 요청의 목적" enctype="요청 데이터의 표현 방식"></form> -->
    
    <form>
     <input type="number" name="number" min="0" />
     <input type="submit" value="=">
    </form>
    <%
    	int number =10;
        long result= factorial(number);
        
    %>
    <h4>10! 연산 결과:<%=result %></h4>
    </body>
    </html>

    폼에 액션이 없으면 

    =>상단의 주소를 그대로 액션에 반영 

    <다시 수정>

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%! //전역 메소드 선언 전역변수, 전역메소드 : 공통 사용(공유)
    	//전역변수로 공유 불가 A,B -> Scope로 데이터 공유 가능
    	//factorial은 인스턴스 메소드 임 클래스모름 왜? 컨테이너 역할 즉 개발자는 인스턴스 생성,획득할 수 없음 그래서 공유가 불가능하며 private든 public이든 상관없음
    private long factorial(int num){ 
    	if(num<0)
    		throw new IllegalArgumentException("음수에 대해서는 연산 불가");
    	if(num ==0){
    		return 1;
    	}else{
    				return num*factorial(num-1);
    	}
    }
    
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <!-- <form action="명령어_요청URL" method="파라미터 전송 방법 & 요청의 목적" enctype="요청 데이터의 표현 방식"></form> -->
    
    <form>
     <input type="number" name="number" min="0" />
     <input type="submit" value="=">
    </form>
    <%	
    	String param = request.getParameter("number");
    	int number =Integer.parseInt(param);
        long result= factorial(number);
        
    %>
    <h4>연산 결과:<%=result %></h4>
    </body>
    </html>

     

     

    =>이렇게 하면 null 잡을 수 있음

    근데 이제 다시 input을 number타입으로 바꾼다.


    클라이언트 보내는 모든 데이터는 검증이 필요함!!!! 그래서 검증 코드 작성 !

    <%@page import="java.util.Objects"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%! //전역 메소드 선언 전역변수, 전역메소드 : 공통 사용(공유)
    	//전역변수로 공유 불가 A,B -> Scope로 데이터 공유 가능
    	//factorial은 인스턴스 메소드 임 클래스모름 왜? 컨테이너 역할 즉 개발자는 인스턴스 생성,획득할 수 없음 그래서 공유가 불가능하며 private든 public이든 상관없음
    private long factorial(int num){ 
    	if(num<0)
    		throw new IllegalArgumentException("음수에 대해서는 연산 불가");
    	if(num ==0){
    		return 1;
    	}else{
    				return num*factorial(num-1);
    	}
    }
    
    %>
    <%
    String param = request.getParameter("number");
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <!-- <form action="명령어_요청URL" method="파라미터 전송 방법 & 요청의 목적" enctype="요청 데이터의 표현 방식"></form> -->
    
    <form>
     <input type="number" name="number" min="0" value="<%=Objects.toString(param,"")%>" />
     <input type="submit" value="=" >
    </form>
    <%	//클라이언트 보내는 모든 데이터는 검증이 필요함!!!!
    	// "\\d" : 숫자한글자 의미 *:반복자,숫자가 없어도됨,  +:숫자필요 
    	if(param!=null && param.matches("\\d+")){
    	int number =Integer.parseInt(param);
        long result= factorial(number);
     
    %>
    <h4>연산 결과:<%=result %></h4>
    <%
     }else if(param!=null && !param.matches("\\d+")){
    	 //클라이언트에게 잘못됐다는것을 에러메세지 
    	 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "펙토리얼 연산은 양수와 숫자만으로 처리");
    	 return;
     }
    %>
    </body>
    </html>

    => 쿼리 스트링이라함 

    <잘못된 요청을 했을때1>

    <잘못된 요청을 했을때2>


    <factorial.jsp> 가독성 떨어짐 , 책임이 분리가 안되어있기에 ...

    그래서 책임을 분리해보자!!!

     

    <form action="/04/factorial.do">

     클라이언트사이드 왜? html안에 들어있으니 자바스크립트안에 주소다 : 프론트엔드이므로 클라이언트 

    그런데  로컬호스트 이런건이미 클라이언트가 가지고 있으므로 WebStudy01만 알수 있도록 지정해줘야 한다.

     

    <form action="<%=request.getContextPath()%>/04/factorial.do">  이렇게 

     

    이제 모델 2방식으로 적용해보자 

     

     

    서블릿에서도 scope로 메소드 호출(공유)해야함 전역변수의 개념을 사용하지 않음

     

    <%@page import="java.util.Objects"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <!-- <form action="명령어_요청URL" method="파라미터 전송 방법 & 요청의 목적" enctype="요청 데이터의 표현 방식"></form> -->
    
    <form action="<%=request.getContextPath()%>/04/factorial.do"> 
     <input type="number" name="number" min="0" vlaue="" />
     <input type="submit" value="=" >
    </form>
    
    
    </body>
    </html>
    package kr.or.ddit.servlet04;
    
    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("/04/factorial.do")
    public class FactorialServlet extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    		//클라이언트 보내는 모든 데이터는 검증이 필요함!!!!
    		String param = req.getParameter("number");
    		if(param!=null && param.matches("\\d+")){
    			String pattern ="%d! =%d";
    			int number =Integer.parseInt(param);
    			//재귀 호출
    			long result= factorial(number);
    			String expression = String.format(pattern, number, result);
    			
    			// request(Map존재) scope사용
    			req.setAttribute("expression", expression);
    			//서버사이드 방식임 그래서 /WebStudy01없어야함
    			String view ="/WEB-INF/views/FactorialView.jsp";
    			req.getRequestDispatcher(view).forward(req, resp);
    					
    		}else if(param!=null && !param.matches("\\d+")){
    			 //클라이언트에게 잘못됐다는것을 에러메세지 
    			 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "펙토리얼 연산은 양수와 숫자만으로 처리");
    			 return;
    		 }
    		
    	}
    	
    	public long factorial(int number) {
    		if(number<0)
    			throw new IllegalArgumentException("음수에 대해서는 연산 불가");
    		if(number ==0){
    			return 1;
    		}else{
    					return number*factorial(number-1);
    		}
    		
    	}
    	
    }
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <%
    	String expression = (String)request.getAttribute("expression");
    
    %>
    <h4>연산 결과: <%=expression%></h4>
    </body>
    </html>


    <비동기 방식>

    화면이 전환되지 않으면서 바로 아래쪽에 출력되도록

    =>jQuery CDN 검색하고  

    여기 검색해서 다른이름으로 저장하고 가져오기

    스크립트 위에다가 쓸 경우

    인터프리팅 방식이므로 되도록 밑에다가 ...

     

    =>콘솔로 찍은 것은 같은 녀석 

    얘네들은 httpelement 타입일까 jQuery일까 

    맵핑하기 전 객체 

    $(this) -> http엘리먼트가 제이쿼리 객체화

     

    화면 전체에 락을 거느냐 안거느냐

    lock : window에 락 거는것 : 동기

    락을 걸지 않은것 : 비동기 => 검색결과 누가먼저 나올지 모르고 다른 화면은 가만 히 .. 

     

     

    <나중에 jQuery모르겠으면 검색해보기>

    자주쓰는것 템플릿 등록 (ajax부분 그런데 $$으로 해주기)

    window -> prefernces 

    url : "여기에 커서 "  insert Variable 하고 cursor넣기 

     

    <%@page import="java.util.Objects"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>04/factorial.jsp</title>
    <script type="text/javascript" src="<%=request.getContextPath()%>/resources/js/jquery-3.6.0.min.js"></script>
    
    </head>
    <body>
    <h4></h4>  
    <!-- 1.Model -> Model2 ->ajax -> XML/JSON(Marshalling) -->
    <!-- 2! ->2*1 =2, 3! ->3*2*1 =6 -->
    연산을 자바 스크립틀릿 기호만으로 반복 곱하기 연산 수행 <br>
    <!-- <form action="명령어_요청URL" method="파라미터 전송 방법 & 요청의 목적" enctype="요청 데이터의 표현 방식"></form> -->
    
    <form action="<%=request.getContextPath()%>/04/factorial.do" name="facForm">
     
     <input type="number" name="number" min="0" value="" />
     <input type="text" name="dummy" value="asas"/>
     <input type="submit" value="="/>
    </form>
    
    <div id ="resultArea">
    
    </div>
    
    <script>
    //발생한 이벤트는 파라미터로 들어오며, 이벤트에는 그 이벤트를 발생시킨 타켓이 들어가 있다.
    		let resultArea =$("#resultArea"); //변수로 받아놓는게 좋음
    		let facForm = $("form[name]").on("submit",function(event){
    			event.preventDefault();
    			//form 의 submit 이벤트의 기본 특성은 동기 요청.
    			console.log(event.target);
    			console.log(this);
    //			$(this) -> httpelement 에서 JQuery객체화
    //          XMLHttpRequest 객체를 활용한 비동기 요청
    			let action =this.action; //$(this).attr("action");
    			let method = this.method;
    			let data =$(this).serialize(); //Query String 생성
    			console.log(data); //ex)parm1=value&param2=value2
    			$.ajax({
    				url: action,
    				method:method,
    				data:data,
    				dataType:"html"  //text, html, json, xml, script->main type :text, 파일업로드 처리를 비동기로? (FormData)
    				,success:function(resp,status,jqXHR){ //resp : html소스 옴
    					$("#resultArea").html(resp);
    				},
    			    error :function(jqXHR, status, error){
    			    	console.log(jqXHR)
    			    	console.log(status)
    			    	console.log(error)
    			    }
    			});
    			return false;
    		});
    		console.log(facForm);
    		
    		
    </script>
    
    </body>
    </html>

    <만약에 jsp오류가 빈번할 경우>

     

    728x90
Designed by Tistory.