ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 22-09-19_jsp
    main 2022. 9. 19. 19:32

    일반적으로 mvc패턴과 model2를 혼용하는 경우가 있는데, 두개를 합친 개념으로 혼용해버림. 

     

    지난 주 한 내용 추가

     

    3가지 이동방식과, 각각의 방식에서 쓸 수 있는 scope 다 써 볼 것...

     

     

     

    ---

    --

    scope에 대해 복습하는 방향으로써

     

    오늘은 btsForm,jsp를 만들어서, bts 멤버들의 정보를 제공하는 폼을 만들어 보자요

     

    select의 option을 클릭하면 해당 멤버들의 개인 컨텐츠 페이지를 로드하도록 만들어 볼 거예요

     

     

    먼저 컨텐츠 페이지가 필요하니까여

    이렇게 검색해서, 우클릭(검사) -> 상단 버튼 클릭해서 원하는 소스 누르고 outerHTML copy 하면 소스 복사 됨

     

     

    이렇게 정보를 담은 jsp를 만들어 준다. (소스를 복사해서 붙여넣기 한 다음에, crt+shift+F 하면 자동 줄맞춤이 됨)

     

     

    이제 servlet을 만들어 줄 거임

     

    package kr.or.ddit.bts;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    
    public class BTSServlet extends HttpServlet{
    	
    	//딱 한번만 생성되는 메서드
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		super.init(config);
    		Map<String, String[]> btsDB = new LinkedHashMap<>();
    		btsDB.put("B001", new String[] {"RM","/WEB-INF/views/bts/rm.jsp"});
    		
    	}
    }

    하드코딩하지 않을 것

    .. 여기서부터 우리는 scope라는 개념을 사용 할 것

     

     

    ----

    init이 먼저 생성되어 있어야 함. ........

     

    이게 submit이 되면 member라는 parameter를
    여기서 받을 거고요

     

     

     

    ---

    <!-- 코드로 전송역할 만들기 정리  -->
             // 멤버 파라미터가 들어와야함 
             // 파라미터가 누락됐다면 상태코드 400
             // 존재하지 않은 파라미터 상태코드 
             // 이 모든걸 통과하면 검증
             //여기서 만든 map을 doget, form에서 사용
             // 어떤 scope을 사용해야할까 
             // web-inf로 갈수있는 이동방식 둘중에 하나를 정하기 

     

     

    --------------------------------------------------------------------------------------------------------------------

    --------------------------------------------------------------------------------------------------------------------

     

    중간에 지난번에 modal 안되던거 여쭤봄

    $msgArea.modal is not  function이라고 에러가 나면 3가지를 확인해야 함,

     

    먼저 msgArea가 잘 선언되어있는지. 만약에 선언되어있지 않다면 not defined 에러를 console에서 확인할 수있음. 그런데 해당 에러는 나지 않았음. 

     

    그러면 부트스트랩이 제대로 로딩되지 않았거나, 아니면 msgArea가 선언이 되긴 했는데 jquery가 아니거나임. 

     

    지금 나는 보면 

    여기bootstrap.js파일이 로딩이 안 되어 있었음. 

     

    그래서 페이지 소스 보기를 통해서 확인 해 보니까

     

    postScript.jsp 파일에 bootstrap script 소스가

    이렇게 오타가 하나 나 있었고,

     

    스크립트가 닫혀있지(</script>) 않았음... 제대로 닫히지 않으면 로딩이 안 된다고 하심. 

     

    해당 코드를 수정하니까

     

    너무 잘 나온다^0^......ㅜ

     

     

    그래서 이 경우는 postScript 소스에서 bootstrap script를 제대로 로딩하지 못해서 생겼던 문제였음을 알 수 있었음....

     

    --------------------------------------------------------------------------------------------------------------------

    --------------------------------------------------------------------------------------------------------------------

     

    btsForm과 BTSServlet이 동일한 Map을 공유해야 하니까..

    scope 이용해야 함.

     

    어떤 scope를 이용해야 하는가.

     

    안되는거먼저 탈락. 

    sessin 없어 탈락

    request 개념 없어 탈락

    page? 안돼 탈락

     

    이 페이지를 몇 명의 client에게 제공하든, 모두가 공유할 수 있는 데이터가 되어야 함 

    서버의 시작과 종료에 생명주기를 함께하는

    application scope 가 지금의 경우에 적절함.

     

     

    ---

    <%@page import="java.util.Map"%>
    <%@ 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>
    <script type="text/javascript" src="<%=request.getContextPath() %>/resources/js/jquery-3.6.1.min.js"></script>
    <script type="text/javascript">
    	$(function(){
    		$("#opMember").change(function(){
    			var member = $("#opMember").val();
    			alert("선택한 멤버"+member);
    			this.form.submit();
    		});		
    	});
    </script>
    </head>
    <body>
    <form action="<%=request.getContextPath() %>/bts/getContent">
    	<select name = "member" id="opMember" >
    		<%
    			//servlet에서 선언해서 application 사용할 수 있음
    			Map<String, String[]> btsDB = (Map)application.getAttribute("btsDB");
    			//반복문 필요
    			StringBuffer options = new StringBuffer();
    							// v 는 멤버 이름text 가짐
    			btsDB.forEach((k,v)->{
    				//format
    				options.append(
    					String.format("<option value ='%s'>%s</option>\n",k, v[0])		
    				);
    			});
    			//out을 이용해서 buffer의 option 기록할 수 있음. 
    			out.print(options);
    		%>
    
    	</select>
    </form>
    </body>
    </html>
    
    <!-- select에서 option 선택했을 때 자동으로 submit되게 하기 -->
    <!-- 코드로 전송역할 만들기  -->
    package kr.or.ddit.bts;
    
    import java.io.IOException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    										//application 전체를 통틀어 가장 먼저 실행되도록
    @WebServlet(value = "/bts/getContent", loadOnStartup = 1)
    public class BTSServlet extends HttpServlet{
    	private ServletContext application; 
    	
    	//딱 한번만 생성되는 메서드
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		//이 코드는 application 전체를 통틀어 가장 먼저 실행되어야 함 
    		super.init(config);
    		//전역변수 하나를 만들어 놓을 수 있져
    		application = getServletContext();
    		
    		Map<String, String[]> btsDB = new LinkedHashMap<>();
    		btsDB.put("B001", new String[] {"RM","/WEB-INF/views/bts/rm.jsp"});
    		btsDB.put("B002", new String[] {"진","/WEB-INF/views/bts/jin.jsp"});
    		btsDB.put("B003", new String[] {"슈가","/WEB-INF/views/bts/suga.jsp"});
    		btsDB.put("B004", new String[] {"제이홉","/WEB-INF/views/bts/jhop.jsp"});
    		btsDB.put("B005", new String[] {"지민","/WEB-INF/views/bts/jimin.jsp"});
    		btsDB.put("B006", new String[] {"뷔","/WEB-INF/views/bts/bui.jsp"});
    		btsDB.put("B007", new String[] {"정국","/WEB-INF/views/bts/jungkuk.jsp"});
    	
    		application.setAttribute("bteDB", btsDB);
    		
    	}
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//일단은 request scope를 써야 할 거 같거든요? 왜냐면 jsp에서 reuest를 보내면 그걸 받아서 처리하기만 하면 되니까...
    	}
    }

     

    음 코드는 문제가 없는데 

    500에러가 나져

     

    람다 함수 못쓴다고 에러 남, 소스레벨 1.8 이상에서만 된다고. 

    그런데 우리는 저것보다 높은 버전을 사용하고 있는데 왜 안될까요?

     

     

    jsp가지고 서블릿 못 만드는데, 우리가 사용하는 WAS인 tomcat이 jsp를 servlet으로 바꿔주고 컴파일까지 다 해줘서 사용할 수 있음. 그래서 tomcat의 설정에서 우리가 작성한 코드를 컴파일을 못 해주면 저런 서버측 에러가 발생할 수 있음. 

     

    그르면 톰캣의 설정을 확인하기 위해 web.xml을 보기로 하겠음. 

     

     

    톰캣이 가진 web.xml을 봅시다
    servlet 태그에서 default값을 설정하고 있는 요놈을 찾아보면
    요놈의 url pattern이 이렇게 되어 있져

     

     

    --

    client로부터 정적 요청/동적 요청 발생했을 때는 원래 별도의 처리과정을 거침

     

    근데 우리 웹서버 없이 WAS하나만 가지고 별도의 처리과정을 거치지 않고 한번에 다 처리했음

    그 이유가 default servlet 때문임. 쟤가 다 처리해주기 때문에 별도의 처리과정 없이 간단하게 처리가 가능함.

     

    우리가 저거를 아래처럼 지워버리면

    여기서 이제 image 동영상,java....etc 서비스가 불가능 함. (이용할 수 없음)

     

    나중에 spring 할 때 저거 일부러 무력화 시켜야 할 수 있음 기억해 둬야 함.

     

    이건뭐죠

    여태 jsp의 요청은 이 servlet이 받아줬던거임 얘가 다 처리해줬음. 

     

    이 servlet이 우리가 jsp로 요청 보냈을 때 servlet 만들어주고 컴파일 해주던 애임

     

    근데 위로 올라와 보면

    여기서 이 컴파일러 소스/타겟이 1.7로 되어 있어서 람다를 못썼던 거임

     

     

            <init-param>
            	<param-name>compilerSourceVM</param-name>
            	<param-value>1.8</param-value>
            </init-param>
            <init-param>
            	<param-name>compilerTargetVM</param-name>
            	<param-value>1.8</param-value>
            </init-param>

    이렇게 추가해주면

     

     

     

    ----

     

     

     

    -----

     

     

    이거 외부에서 접근할 수 없는 위치(WEB-INF)에 있어서 직접 실행하면 에러, 서버에서는 접근 가능

    redirect방식이 아닌 dispatch 방식 사용해야 함

    -->forward, include로 이동

    forward 사용해야 함

    지금 servlet에서는 만들어지는 정보가 없음. 그냥 controller 역할, 그래서 include 쓸 필요 없고 forward 쓰면 됨

     

    --

    <%@page import="java.util.Map"%>
    <%@ 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>
    <script type="text/javascript" src="<%=request.getContextPath() %>/resources/js/jquery-3.6.1.min.js"></script>
    
    </head>
    <body>
    <form action="<%=request.getContextPath() %>/bts/getContent">
    	<select name = "member" onchange="this.form.submit();">
    		<%
    			//servlet에서 선언해서 application 사용할 수 있음
    			Map<String, String[]> btsDB = (Map) application.getAttribute("btsDB");
    			//반복문 필요
    			StringBuffer options = new StringBuffer();
    			// v 는 멤버 이름text 가짐
    			btsDB.forEach((k,v)->{
    				//format
    				options.append(
    					String.format("<option value='%s'>%s</option>\n", k, v[0])		
    				);
    			});
    			//out을 이용해서 buffer의 option 기록할 수 있음. 
    			out.print(options);
    			
    			
    		%>
    
    	</select>
    </form>
    </body>
    </html>
    
    <!-- select에서 option 선택했을 때 자동으로 submit되게 하기 -->
    <!-- 코드로 전송역할 만들기  -->
    package kr.or.ddit.bts;
    
    import java.io.IOException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    										//application 전체를 통틀어 가장 먼저 실행되도록
    @WebServlet(value = "/bts/getContent", loadOnStartup = 1)
    public class BTSServlet extends HttpServlet{
    	private ServletContext application; 
    	
    	//딱 한번만 생성되는 메서드
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		//이 코드는 application 전체를 통틀어 가장 먼저 실행되어야 함 
    		super.init(config);
    		//전역변수 하나를 만들어 놓을 수 있져
    		application = getServletContext();
    		
    		Map<String, String[]> btsDB = new LinkedHashMap<>();
    		btsDB.put("B001", new String[] {"RM","/WEB-INF/views/bts/rm.jsp"});
    		btsDB.put("B002", new String[] {"진","/WEB-INF/views/bts/jin.jsp"});
    		btsDB.put("B003", new String[] {"슈가","/WEB-INF/views/bts/suga.jsp"});
    		btsDB.put("B004", new String[] {"제이홉","/WEB-INF/views/bts/jhop.jsp"});
    		btsDB.put("B005", new String[] {"지민","/WEB-INF/views/bts/jimin.jsp"});
    		btsDB.put("B006", new String[] {"뷔","/WEB-INF/views/bts/bui.jsp"});
    		btsDB.put("B007", new String[] {"정국","/WEB-INF/views/bts/jungkuk.jsp"});
    	
    		application.setAttribute("btsDB", btsDB);
    		//어디서든 이 DB를 공유하도록 하자는 의미에서 scope를 사용했었음. 
    		
    	}
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    		Map<String, String[]> btsDB = (Map)application.getAttribute("btsDB");
    		
    		req.setCharacterEncoding("UTF-8");
    		String member = req.getParameter("member");
    		
    		//------------------------------------------------
    		int status = 200;
    			//parameter가 안넘어온 && 비어있는
    		if(member==null && member.isEmpty()) {
    			//정상처리 불가, 원인은 client에게 있음
    			status = HttpServletResponse.SC_BAD_REQUEST;
    			
    		//넘어오긴 했다는 것, 가만 포함되지 않은 키(!B001~007)가 넘어온 경우
    		}else if(!btsDB.containsKey(member) ) {
    			status = HttpServletResponse.SC_NOT_FOUND;
    		}
    		
    		
    		//status에 따른 처리---------------------------------
    		if(status==200) {
    			String[] info = btsDB.get(member);
    			String contentURL = info[1];
    			//이제 이걸 가지고 이동. 이동에는 dispatch와 redirect 두가지가 있음
    			//모든 contetn 페이지는 WEB-INF 안에 있음
    			req.getRequestDispatcher(contentURL).forward(req, resp);
    		}else {
    			resp.sendError(status);
    		}
    		
    	}
    }

     

    이렇게 다 짜고.... 실행하면 ....

     

    이렇게 실행화면이 나오고...

     

    ???멤버의 컨텐츠들은 보호된 옵션이 된다....

    아마 URL에 보면 정해놓은 name으로 넘어가서인듯...

     

     

     

    ---

    추가미션, 체인지 했을 때 화면이 전환되지 않고 select, option이 있는 페이지 하단에서만 페이지가 변하도록 하기..

     

    --

     

    이런식으로 짜면.... 나중에 tracing????을 할때마다 비동기...?????? 에러....그래서 이렇게 하지말고요..

     

    그리고 data가 넘어가는걸 하드코딩으로 하나하나 써주고있음. 그러면 저 form, select의 name이 바뀌면 바꿔줘야 하는 것이 많음...

     

    동기를 비동기로 바꿔주기만 해야 함....

    또 action="<%=request.getContextPath() %>/bts/getContent"이거를 script에 넣어서 구조 자체를 바꿔버림...

     

    데이터가 넘어가는 방식이나 구조는 똑같아야 함...

     

    onchange="this.form.submit();"

     

    이 함수를 이용하면 submit 함수를 사용할 수 없겠지만, j query를 사용하면 사용가능....

     

     

    ---

    ㅜㅜ???????지난시간에 plugin.......하위구조....

     

    이놈의 정체는 다 함수......ajaxForm 저걸 이용하면 form tag를 비동기로 바꿀 수 이ㅏㅆ다고...

    --

     

    이 코드가 안된다가 아니라...

    <script type="text/javascript">
    	//submit하면 대상은 form tag가 됨
    	$(document).on("submit","form:first", function(event){
    		
    		//중단1 - 안전빵
    		event.preventDefault();
    		let form = this;// 여기서 this 는 Form
    		let url = this.action;
    		let method = this.method;
    		let data = $(this).serialize();
    		
    		//이렇게 하면 위에서 onchange 를 취소하지 않아도 되어요.....그렇다고 해요...
    		
    		$.ajax({
    			url : url.
    			method : method,
    			data : data,
    			dataType : "html",
    							//resp -- jsp source
    			success : function(resp) {
    				//이렇게 하면 form tag 하단에 집어넣는거 가능하겠져
    				$(form).after(resp);
    			},
    			error : function(errorResp) {
    				console.log(errorResp.status);
    			}
    		});
    		
    		//중단2 
    		return false;
    	});
    </script>

    이렇게 할 수도 있어요....

     

     

    BTS info 관련 코드 일단 최종

    ---

    [btsForm.jsp]

    <%@page import="java.util.Map"%>
    <%@ 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>
    <jsp:include page="/includee/preScript.jsp" />
    <body>
    <!-- choose the member who want to see information -->
    <form action="<%=request.getContextPath() %>/bts/getContent">
       <select name = "member" onchange="$(this.form).submit();">
          <%
             //servlet에서 선언해서 application 사용할 수 있음
             Map<String, String[]> btsDB = (Map) application.getAttribute("btsDB");
             //반복문 필요
             StringBuffer options = new StringBuffer();
             // v 는 멤버 이름text 가짐
             btsDB.forEach((k,v)->{
                //format
                options.append(
                   String.format("<option value='%s'>%s</option>\n", k, v[0])      
                );
             });
             //out을 이용해서 buffer의 option 기록할 수 있음. 
             out.print(options);
             
             
          %>
    
       </select>
    </form>
    
    
    <script type="text/javascript">
       //submit하면 대상은 form tag가 됨
       $(document).on("submit","form:first", function(){
          
          //중단1 - 안전빵
          event.preventDefault();
          let form = this;// 여기서 this 는 Form
          let url = this.action;
          let method = this.method;
          let data = $(this).serialize();
          
          //이렇게 하면 위에서 onchange 를 취소하지 않아도 되어요.....그렇다고 해요...
          
          $.ajax({
             url : url,
             method : method,
             data : data,
             dataType : "html",
                         //resp -- jsp source
             success : function(resp) {
                //이렇게 하면 form tag 하단에 집어넣는거 가능하겠져
                $(form).after(resp);
             },
             error : function(errorResp) {
                console.log(errorResp.status);
             }
          });
          
          //중단2 
          return false;
       });
    </script>
    </body>
    </html>
    
    <!-- select에서 option 선택했을 때 자동으로 submit되게 하기 -->
    <!-- 코드로 전송역할 만들기  -->

     

    [BTSServlet.java]

    package kr.or.ddit.bts;
    
    import java.io.IOException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
                                  //application 전체를 통틀어 가장 먼저 실행되도록
    @WebServlet(value = "/bts/getContent", loadOnStartup = 1)
    public class BTSServlet extends HttpServlet{
       private ServletContext application; 
       
       //딱 한번만 생성되는 메서드
       @Override
       public void init(ServletConfig config) throws ServletException {
          //이 코드는 application 전체를 통틀어 가장 먼저 실행되어야 함 
          super.init(config);
          //전역변수 하나를 만들어 놓을 수 있져
          application = getServletContext();
          
          Map<String, String[]> btsDB = new LinkedHashMap<>();
          btsDB.put("B001", new String[] {"RM","/WEB-INF/views/bts/rm.jsp"});
          btsDB.put("B002", new String[] {"진","/WEB-INF/views/bts/jin.jsp"});
          btsDB.put("B003", new String[] {"슈가","/WEB-INF/views/bts/suga.jsp"});
          btsDB.put("B004", new String[] {"제이홉","/WEB-INF/views/bts/jhop.jsp"});
          btsDB.put("B005", new String[] {"지민","/WEB-INF/views/bts/jimin.jsp"});
          btsDB.put("B006", new String[] {"뷔","/WEB-INF/views/bts/bui.jsp"});
          btsDB.put("B007", new String[] {"정국","/WEB-INF/views/bts/jungkuk.jsp"});
       
          application.setAttribute("btsDB", btsDB);
          //어디서든 이 DB를 공유하도록 하자는 의미에서 scope를 사용했었음. 
          
       }
       
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          
          Map<String, String[]> btsDB = (Map)application.getAttribute("btsDB");
          
          req.setCharacterEncoding("UTF-8");
          String member = req.getParameter("member");
          
          //------------------------------------------------
          int status = 200;
             //parameter가 안넘어온 && 비어있는
          if(member==null && member.isEmpty()) {
             //정상처리 불가, 원인은 client에게 있음
             status = HttpServletResponse.SC_BAD_REQUEST;
             
          //넘어오긴 했다는 것, 가만 포함되지 않은 키(!B001~007)가 넘어온 경우
          }else if(!btsDB.containsKey(member) ) {
             status = HttpServletResponse.SC_NOT_FOUND;
          }
          
          
          //status에 따른 처리---------------------------------
          if(status==200) {
             String[] info = btsDB.get(member);
             String contentURL = info[1];
             //이제 이걸 가지고 이동. 이동에는 dispatch와 redirect 두가지가 있음
             //모든 contetn 페이지는 WEB-INF 안에 있음
             req.getRequestDispatcher(contentURL).forward(req, resp);
          }else {
             resp.sendError(status);
          }
          
       }
    }

     

    ----

    이제 추가로 또 할거는요

     

    https://getbootstrap.com/docs/5.2/examples/dashboard/

     

    Dashboard Template · Bootstrap v5.2

    Dashboard

    getbootstrap.com

    이 ui를 적용하고 싶대요...

    왼쪽의 메뉴를 누르면 오른쪽 디스플레이 화면만 바뀌게...

     

    --

    수업은 심하게 빠른데

    에러 계속나서

    멘탈박살

    ---

    이게 바로 뜨게

     

    원래는 index.jsp로 되어 있어서 index.jsp파일이 열렸는데

    이렇게 수정을 하..면

    servlet파일에서 실행을 할 수 있어요. 

     

    이렇게 나온다는데

     

    하...

     

    위에 부트스트랩에서 긁어온 ui를 적용해서 하나의 jsp에서 7개의 jsp를 로딩할거예요 

    아래 코드를 활용해서요

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!doctype html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1">
    		<meta name="description" content="">
    		<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    		<meta name="generator" content="Hugo 0.88.1">
    		<meta name="theme-color" content="#7952b3">
    
    		<title>Dashboard Template · Bootstrap v5.1</title>
    		
    		<!-- prescript.jsp -->
    		PRESCRIPT
    		
    		<style>
    			.bd-placeholder-img {
    				font-size: 1.125rem;
    				text-anchor: middle;
    				-webkit-user-select: none;
    				-moz-user-select: none;
    				user-select: none;
    			}
    			
    			@media ( min-width : 768px) {
    				.bd-placeholder-img-lg {
    					font-size: 3.5rem;
    				}
    			}
    		</style>
    		
    		<!-- Custom styles for this template -->
    		<link href="<%=request.getContextPath()%>/resources/css/dashboard.css" rel="stylesheet">
    	</head>
    	<body class="d-flex flex-column vh-100">
    		<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
    		<!-- headermenu.jsp -->
    			HEADERMENU
    		</header>
    	
    		<div class="container-fluid">
    			<div class="row">
    				<jsp:include page="/includee/leftMenu.jsp" />
    				<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
    					<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
    					<!-- Main Content Area start -->
    						<div class="border border-primary">
    						<!-- 만들거예요, index.jsp가 들어와야 해요 -->
    							INDEX
    						</div>
    					<!-- Main Content Area end -->
    					</div>
    				</main>
    			</div>
    		</div>
    	
    		<footer class="footer mt-auto py-3 bg-dark col-md-9 ms-sm-auto col-lg-10">
    		
    		<!-- footer.jsp -->
    			FOOTER
    		</footer>
    		
    		<!-- postscript.jsp -->
    		POSTSCRIPT
    	</body>
    </html>

     

    주석으로 jsp가 표기된 곳에 jsp들을 로딩해보세요

     

    --

    에러난거 다잡고 놓친거 다 고치고 멘탈 쪼끔회복 하

    --

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!doctype html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1">
    		<meta name="description" content="">
    		<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    		<meta name="generator" content="Hugo 0.88.1">
    		<meta name="theme-color" content="#7952b3">
    
    		<title>Dashboard Template · Bootstrap v5.1</title>
    		
    		<jsp:include page="/includee/preScript.jsp" />
    		
    		<style>
    			.bd-placeholder-img {
    				font-size: 1.125rem;
    				text-anchor: middle;
    				-webkit-user-select: none;
    				-moz-user-select: none;
    				user-select: none;
    			}
    			
    			@media ( min-width : 768px) {
    				.bd-placeholder-img-lg {
    					font-size: 3.5rem;
    				}
    			}
    		</style>
    		
    		<!-- Custom styles for this template -->
    		<link href="<%=request.getContextPath()%>/resources/css/dashboard.css" rel="stylesheet">
    	</head>
    	<body class="d-flex flex-column vh-100">
    		<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
    			<jsp:include page="/includee/headerMenu.jsp" />
    		</header>
    	
    		<div class="container-fluid">
    			<div class="row">
    			
    				<jsp:include page="/includee/leftMenu.jsp" />
    				
    				<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
    					<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
    					<!-- Main Content Area start -->
    						<div class="border border-primary">
    							<jsp:include page="/WEB-INF/views/index.jsp" />
    						</div>
    					<!-- Main Content Area end -->
    					</div>
    				</main>
    			</div>
    		</div>
    	
    		<footer class="footer mt-auto py-3 bg-dark col-md-9 ms-sm-auto col-lg-10">
    			<jsp:include page="/includee/footer.jsp" />
    		</footer>
    		<jsp:include page="/includee/postScript.jsp" />
    	</body>
    </html>

    jsp 로딩 코드 넣어줌. include 태그 활용

     

     

    --

    css까지 적용하고 left menu에 우리가 로딩할 jsp의 이름을 적어줌.

    왼쪽 메뉴를 누르면 가운데 뜨게 할 것 

     

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
      <nav id="sidebarMenu" class="col-md-2 col-lg-2 d-md-block bg-light sidebar collapse">
          <div class="sidebar-sticky pt-3">
            <ul class="nav flex-column">      
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>/05/calendar.jsp">Calendar</a>
    			</li>
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>/02/factorial.jsp">Factorial</a>
    			</li>	
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>/02/calculateForm.jsp">Calculator</a>
    			</li>	
            </ul>
          </div>
        </nav>

    leftmenu.jsp

     

    이제 해당 링크를 누르면 페이지로 이동은하지만, ui를 벗어남.

     

    그러면 모든 요청이 welcome page로 넘어가야함???

     

    그러면? 를 이용하여 get 방식으로 parameter를 넘기는 방식으로 가능
    이제 넘어오는 parameter에 따라서 include되는 페이지를 동적으로 바꿔 주어야 함

     

     

    index Servlet으로 오는 경우는 네가지

    크게 두가지 command 라는 parameter가 있는 경우와 없는 경우

     

    여기서 잡시는데 Servlet(controller)에서 저 값이 처음 잡힘

     

     

    처리할 수 있는 command가 data화 되어 있어야 함. Map, enum, ...

     

    IndexServlet에서는 

    //welcome page와 특정 page를 식별해야 함

     

     

    init, lifeCycle callback, 단 한번 실행됨

     

     

    ---

     

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
      <nav id="sidebarMenu" class="col-md-2 col-lg-2 d-md-block bg-light sidebar collapse">
          <div class="sidebar-sticky pt-3">
            <ul class="nav flex-column">      
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=CALENDAR">Calendar</a>
    			</li>
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=FACTORIAL">Factorial</a>
    			</li>	
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=CALCULATOR">Calculator</a>
    			</li>	
            </ul>
          </div>
        </nav>

    이거 반복되니까 한번만 처리하자. 

     

    init으로 IndexServlet 에서 만든 db를 leftmenu에서도 사용할 수 있도록 

     

     

    ---

     

    --

     

     

    어디서 에러가 났을까여.,.

     

     

     

    ---------

     

    ----------

     

     

    이제 calendar.jsp는.... 혼자 작동 안하니까 html~body 지워요, 닫히는 body, html도 지워요

    jquery도 얘를 호출해주는 페이지에서 로딩해주니까 지워주세ㅐ요

    보이는 형태는 차이가 없지만 저걸 안 지우면 html 소스 안에 html 소스가 또 들어있는 이상한형상이 뜨거든여 그걸 없애줌

     

     

    --

    serverside page module화 작업을 하고 있어요 우리는.,..

    jquery를 쓸수 있냐 없냐도 calender.jsp 단계가 아니라, index 에서 결정되는거예요...

     

     

    ----

     

    ---

     

    이런거 다른 거 누르면 405 에러남. 저기 있는 애들 get메서드 사용.

     

     

    ---

    오늘의 최종 소스코드

     

    indexServlet.java

    package kr.or.ddit.commons.controller;
    
    import java.io.IOException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    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("/index.do")
    public class IndexServlet extends HttpServlet{
    	// 데이터 공유를 위한 application scope 사용
    	private ServletContext application;
    	
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		super.init(config);
    		application = getServletContext();
    		Map<String, String> commandDB = new LinkedHashMap<>();
    		commandDB.put("CALENDAR", "/05/calendar.jsp");
    		commandDB.put("FACTORIAL", "/02/factorial.jsp");
    		commandDB.put("CALCULATOR", "/02/calculateForm.jsp");
    		application.setAttribute("commandDB", commandDB);
    	}
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		Map<String, String> commandDB = (Map)application.getAttribute("commandDB");
    		
    		String command = req.getParameter("command");
    		//index에서 사용하는 commandPage를 여기서 선언 해 줘야 함
    		String commandPage = null;
    		int status = 200;
    		
    		if(command==null || command.isEmpty()) {
    			// 여기서는 commandPage가 index.jsp여야 하고 
    			commandPage = "/WEB-INF/views/index.jsp";
    		}else {
    			// 여기서는 경우에따라 commandPage가 바뀌어야 함
    			// 정해진 3개의 페이지, 상수의 집합인 enum 또는 Map을 사용할 수도 있음.
    			if(!commandDB.containsKey(command)) {
    				status = HttpServletResponse.SC_NOT_FOUND;
    			}else {
    				commandPage = commandDB.get(command);
    			}
    		}
    		if(status==200) {
    			//request, session, application scope 중 사용하면 되는데
    			//서버에 부하를 주지 않도록 최소한의 영역을 주는 request scope 사용
    			req.setAttribute("commandPage", commandPage);
    			
    			String viewName = "/WEB-INF/views/template.jsp";
    			req.getRequestDispatcher(viewName).forward(req, resp);
    		}else {
    			resp.sendError(status);
    		}
    				 		
    		
    		
    	}
    }

     

    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    welcome page
    <script>
    // 	$(function(){
    // 		$.fn.modal
    // 	})
    	window.addEventListener("DOMContentLoaded", function(event){
    		console.log($.fn.modal);
    	});
    </script>

     

     

    template.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!doctype html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1">
    		<meta name="description" content="">
    		<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    		<meta name="generator" content="Hugo 0.88.1">
    		<meta name="theme-color" content="#7952b3">
    
    		<title>Dashboard Template · Bootstrap v5.1</title>
    		
    		<jsp:include page="/includee/preScript.jsp" />
    		
    		<style>
    			.bd-placeholder-img {
    				font-size: 1.125rem;
    				text-anchor: middle;
    				-webkit-user-select: none;
    				-moz-user-select: none;
    				user-select: none;
    			}
    			
    			@media ( min-width : 768px) {
    				.bd-placeholder-img-lg {
    					font-size: 3.5rem;
    				}
    			}
    		</style>
    		
    		<!-- Custom styles for this template -->
    		<link href="<%=request.getContextPath()%>/resources/css/dashboard.css" rel="stylesheet">
    	</head>
    	<body class="d-flex flex-column vh-100">
    		<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
    			<jsp:include page="/includee/headerMenu.jsp" />
    		</header>
    	
    		<div class="container-fluid">
    			<div class="row">
    			
    				<jsp:include page="/includee/leftMenu.jsp" />
    				
    				<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
    					<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
    					<!-- Main Content Area start -->
    						<div class="border border-primary">
    												<!-- scope안에서꺼내는 형태로 나와야 함
    												쌍따옴표, 홀따옴표로 써 주기..그래야 에러 안 남 -->
    							<%
    							String cp = (String)request.getAttribute("commandPage");
    							%>
    							<jsp:include page='<%=cp %>' />
    						</div>
    					<!-- Main Content Area end -->
    					</div>
    				</main>
    			</div>
    		</div>
    	
    		<footer class="footer mt-auto py-3 bg-dark col-md-9 ms-sm-auto col-lg-10">
    			<jsp:include page="/includee/footer.jsp" />
    		</footer>
    		<jsp:include page="/includee/postScript.jsp" />
    	</body>
    </html>

     

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
      <display-name>WebStudy01</display-name>
      <welcome-file-list>
        <welcome-file>index.do</welcome-file>
      </welcome-file-list>
      <context-param>
      	<param-name>imageFolderPath</param-name>
      	<param-value>D:/contents/images</param-value>
      </context-param>
      
      
      <servlet>
      	<servlet-name>DescriptionServlet</servlet-name>
      	<servlet-class>kr.or.ddit.servlet01.DescriptionServlet</servlet-class>
      	<init-param>
      		<param-name>param1</param-name>
      		<param-value>value1</param-value>
      	</init-param>
      	<load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
      	<servlet-name>DescriptionServlet</servlet-name>
      	<url-pattern>/desc</url-pattern>
      </servlet-mapping>
      
      	<error-page>
      		<!-- 500이라는 에러페이지에서 사용할 수 있는 걸 결정 -->
      		<error-code>500</error-code>
    		<location>/errors/error500.jsp</location>
      	</error-page>
      
      <session-config>
      	<session-timeout>2</session-timeout>
      </session-config>
    
      
      <!-- 
        <servlet>
      	<servlet-name>ImageFormServlet</servlet-name>
      	<servlet-class>kr.or.ddit.servlet01.ImageFormServlet</servlet-class>
      	<init-param>
      		<param-name>imageFolderPath</param-name>
      		<param-value>D:/contents/images</param-value>
      	</init-param>
      	<load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
      	<servlet-name>ImageFormServlet</servlet-name>
      	<url-pattern>/imageForm</url-pattern>
      </servlet-mapping>
      
          <servlet>
      	<servlet-name>ImageServlet</servlet-name>
      	<servlet-class>kr.or.ddit.servlet01.ImageServlet</servlet-class>
      	<init-param>
      		<param-name>imageFolderPath</param-name>
      		<param-value>D:/contents/images</param-value>
      	</init-param>
      	<load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
      	<servlet-name>ImageFormServlet</servlet-name>
      	<url-pattern>/imageForm</url-pattern>
      </servlet-mapping>
      
       -->
      
    </web-app>

     

    postScript.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <script type="text/javascript" src="<%=	request.getContextPath() %>/resources/js/bootstrap-5.1.3-dist/js/bootstrap.bundle.min.js"></script>

     

    preScript.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <link rel="stylesheet" href="<%=request.getContextPath() %>/resources/js/bootstrap-5.1.3-dist/css/bootstrap.min.css">   
    <script type="text/javascript" src="<%=request.getContextPath() %>/resources/js/jquery-3.6.1.min.js"></script>

    leftmenu.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
      <nav id="sidebarMenu" class="col-md-2 col-lg-2 d-md-block bg-light sidebar collapse">
          <div class="sidebar-sticky pt-3">
            <ul class="nav flex-column">      
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=CALENDAR">Calendar</a>
    			</li>
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=FACTORIAL">Factorial</a>
    			</li>	
    			<li class="nav-item">
    				<a class="nav-link active" href="<%=request.getContextPath() %>?command=CALCULATOR">Calculator</a>
    			</li>	
            </ul>
          </div>
        </nav>

    headermenu.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap w-100 p-0 shadow">
      <a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">Company403</a>
      <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <ul class="nav px-3 col">
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="#">상단메뉴1</a>
        </li>
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="#">상단메뉴2</a>
        </li>
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="#">상단메뉴3</a>
        </li>
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="#">상단메뉴4</a>
        </li>
      </ul>
      <ul class="nav px-3 col-2">
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="<%=request.getContextPath() %>/login/loginForm.jsp">Sign in</a>
        </li>
        <li class="nav-item text-nowrap">
          <a class="nav-link" href="<%=request.getContextPath() %>/login/logout.do">Sign out</a>
        </li>
      </ul>
    </nav>

     

    footer.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
     <div class="container">
        <span class="text-muted">Place sticky footer content here.</span>
     </div>

     

     

     

    factorial.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <form id="factorialForm" action="<%=request.getContextPath() %>/factorial">
    	<input type="number" name="operand"  value="${number }"/>
    </form>
    <pre>
    1. 반복문 : scriptlet
    2. 재귀 호출 : declaration
    3. 피연산자 선택 UI
    4. Model1 -> Model2
    5. 비동기.
    <%-- ${number }! = ${result } --%>
    <span id="resultArea"></span>
    </pre>
    <script type="text/javascript">
    	var path = $("#resultArea");
    	const PATTERN = "%O! = %R";
    	$(":input[name]").on("change", function(){
    		$(this).parents("form:first").submit();
    	});
    	$(document).on("submit", "#factorialForm" ,function(event){
    		event.preventDefault();
    		let url = this.action;
    		let method = this.method;
    		let data = $(this).serialize(); // query string 
    		
    		$.ajax({
    			url : url,
    			method : method,
    			data : data,
    			dataType : "json",
    			success : function(resp) {
    				path
    						.html( 
    								PATTERN.replace("%O", resp.operand)
    										.replace("%R", resp.result)
    						);
    			},
    			error : function(errorResp) {
    				console.log(errorResp.status);
    			}
    		});
    		
    		return false;
    	})
    </script>

    factorialServlet.java

    package kr.or.ddit.servlet02;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    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("/factorial")
    public class FactorialServlet extends HttpServlet {
    	 
    	//4단계
    	private long factorial(int number){
    		if(number<=0){
    			throw new IllegalArgumentException("연산은 양수만 처리함..");
    		 }
    		   //10*9*8*7*6*5*....1
    		
    		if(number==1){
    			return 1;
    		}else{
    			return number*factorial(number-1);
    		      
    		}
    	}
    	
    	
    	//Java -> Json : marshalling
    	
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		String operand= request.getParameter("operand");
    		if(operand!=null && operand.matches("\\d{1,3}")){
    			int number =Integer.parseInt(operand);
    			long result = factorial(number);
    			request.setAttribute("number", number);
    			request.setAttribute("result", result);
    			
    			String json =String.format("{\"operand\" : %d, \"result\" : %d }",number,result);
    			
    			request.setAttribute("json", json);
    			
    		}else if(operand!=null && !operand.matches("\\d{1,3}")){
    			response.sendError(HttpServletResponse.SC_BAD_REQUEST);
    			return;
    		}
    		String accept =request.getHeader("Accept");
    		if(accept.contains("json")) {
    			response.setContentType("application/json,charset=UTF-8");
    			try(
    					PrintWriter out = response.getWriter();
    			){
    				out.print(request.getAttribute("json"));
    			}
    			
    		}else {
    			
    			String view="/02/factorial.jsp";
    			request.getRequestDispatcher(view).forward(request,response);
    		}
    				
    				
    		
    	}
    	
    	 
    }

     

    calculateForm.jsp

    <%@page import="kr.or.ddit.enumpkg.OperatorType"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!-- 이항 연산자로 4칙 연산 처리. -->
    Send Data Type
    <input type="radio" name="sendDataType" value="json" checked>JSON
    <input type="radio" name="sendDataType" value="parameter">Parameter
    <hr />
    Receive Data Type
    <input type="radio" name="receiveDataType" value="xml">XML
    <input type="radio" name="receiveDataType" value="json" checked>JSON
    
    <form action="<%=request.getContextPath()%>/calculate" method="post" name="calForm">
       <input type="number" name="leftOp" />
       <select name="operator">
          <%
             for(OperatorType single: OperatorType.values()){%>
                <option value = '<%=single.name()%>'><%=single.getSign()%></option>
             <%}
          %>
       </select>
       <input type="number" name="rightOp" />
       <input type="submit" value="=">
    </form>
    <div id="result"></div>
    
    <script>
    	let makeSendData = function(settings){
    		let inputs = calForm.find(":input[name]");
    		let data ={};
    		$.each(inputs, function(index, input){
    			let name = this.name;
    			let value = $(this).val();
    			let type = this.type;
    //			data.leftObj =23;
    //			data['leftObj']=23;
    			if(type=='number'){
    				data[name] = parseInt(value);
    			}else{
    				data[name] = value;
    			}
    		
    		});
    		console.log(data);
    			//여기까지는 data가 javascript nature data였는데
    		let sendDataType = $("[name=sendDataType]:checked").val();
    		if(sendDataType == 'json'){
    			settings.data = JSON.stringify(data);
    			//여기선 데이터가 JSON data가 됨
    			settings.contentType = "application/json;charset=UTF-8";
    		}else{
    			settings.data = data;
    		}
    	}
    
    	let makeReceiveDataType = function(settings){
    		let receiveDataType = $("[name=receiveDataType]:checked").val();
    		let dataType = receiveDataType;
    		settings.dataType = dataType;
    	}
    
       let calForm =$(document.calForm).on("submit", function(event){
          event.preventDefault();
          
          let url = this.action;
          let method = this.method;
          //let data = $(this).serialize(); //QueryString
          /*
          let leftOp = $("input[name=leftOp]",document.calForm).val
    	  let rightOp = $("input[name=rightOp]",document.calForm).val
    	  let operator = $("input[name=operator]",document.calForm).val
          
          let jsObj =   {
                leftOp,
                rightOp,
                operator
                };
    
          let json = JSON.stringify(jsObj);
    		*/      
          let settings ={
        		 url:url,
       	         method:method,
       	         success:function(resp){
       	        	console.log(resp);
       	            calForm.after(resp.expression);
       	         },
       	         error: function(errorResp){
    //   	        console.log(errorResp.status);
       	            alert(errorResp.status);
       	         }
          };
          
          makeSendData(settings);
          
          makeReceiveDataType(settings);
          
          
          $.ajax(settings);
          return false;
       });
    </script>

     

    calender.jsp

    <%@page import="java.util.TimeZone"%>
    <%@page import="java.util.Locale"%>
    <%@page import="java.text.DateFormatSymbols"%>
    <%@ page import="java.util.Calendar" %>
    <%@ page import="static java.util.Calendar.*" %>
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
       
    <%
    	Locale locale = request.getLocale(); //이제 locale 정보를 받아놓을거임...
    	TimeZone timeZone = TimeZone.getDefault();
    	String yearParam = request.getParameter("year");
    	String monthParam = request.getParameter("month");
    	String language = request.getParameter("language");
    	String timeZoneId = request.getParameter("timeZoneId");
    		
    	Calendar calendar = getInstance(timeZone, locale);
    	//데이터 검증할것, 데이터가 있어야 하며, 데이터가 4자리 숫자여야 한다
    	//("\\d{4}")) --> d는 문자 한개 + {4} 4번 반복 ==> 4자리 문자
    	if(yearParam!=null && yearParam.matches("\\d{4}")
    		&& monthParam!=null && monthParam.matches("^1[0-1]$|^[0-9]$")){
    			//^[0-9]$ 이건 한자리라서 1~10월만 볼 수 있고 11,12월을 못봄. 근데 이 둘의 공통은 문장의 시작이 1임
    			//^1$[0,1] : 문장의시작(^)이 1로 시작하고 끝남($)의 조건, 두가지 조건을 합침 (|)	
    		calendar.set(YEAR, Integer.parseInt(yearParam));
    		calendar.set(MONTH, Integer.parseInt(monthParam));
    	}
    	if(language!=null && !language.isEmpty()){
    		locale = Locale.forLanguageTag(language);
    	}
    	if(timeZoneId!=null && !timeZoneId.isEmpty()){
    		timeZone = TimeZone.getTimeZone(timeZoneId);
    	}
    	Calendar today = getInstance(timeZone, locale);
    	
    //	String title = String.format(locale, "%1$ty, %1$tB",  calendar); //%1$ty... 여기서 y를 소문자로 적으면 연도가 두자리 
    
    	String title = String.format(locale, "%1$tY, %1$tB", calendar);	// y를 대문자로 적으면 연도가 4자리로 나옴
    	String now = String.format(locale, "%tc", today);
    	
    	calendar.add(MONTH, -1);		//전 달로 가겠다
    	int beforeYear = calendar.get(YEAR);	//연도를뽑겠다
    	int beforeMonth = calendar.get(MONTH);	//달을 뽑겠다.
    	
    	calendar.add(MONTH, 2);			//다음 달로 가겠다
    	int nextYear = calendar.get(YEAR);
    	int nextMonth = calendar.get(MONTH);
    	
    	calendar.add(MONTH, -1);		//다시 이번 달로 오겠다.
    	int year = calendar.get(YEAR);
    	int month = calendar.get(MONTH);
    	
    	calendar.set(DAY_OF_MONTH,1);
    	int dayOfWeek1st = calendar.get(DAY_OF_WEEK);	//목요일이면 5요일이니까 5를 가짐
    	int offset = dayOfWeek1st -1;
    		calendar.add(DAY_OF_MONTH, -offset);
    	
    //	calendar.add(DAY_OF_MONTH, 1);	//내일의 날짜를 찾겠다.. 하루 뒤의 날짜로 바뀌는거임
    //	calendar.add(DAY_OF_MONTH, -1); //이렇게 하면 하루 전날로 바뀌는 거임
    	calendar.add(DAY_OF_MONTH, -offset); //이렇게 하면 달력의 시작이 며칠이 될 지 나옴
    	
    	
    	
    	DateFormatSymbols dfs = new DateFormatSymbols(locale); 
    %>
    
    <h4>
    <%-- ?year=<%=beforeYear %>&month=<%=beforeMonth %> --%>
    <a href="#" class="changeBtn" data-year="<%=beforeYear %>" data-month="<%=beforeMonth %>">&lt;&lt;&lt;</a>
    <%= title %>
    <!--  ?year=<%=nextYear %>&month=<%=nextMonth %>-->
    <a href="#" class="changeBtn" data-year="<%=nextYear %>" data-month="<%=nextMonth %>">&gt;&gt;&gt;</a>
    </h4>
    <h4>현재 시각 : <%=now %></h4>
    <form name="calForm" method="get">
    	<input type="hidden" name="command" value="CALENDAR" />
    	<input type="text" name="year" pattern="\d{4}" placeholder="2022" value="<%=year %>"/>
    	<select name="month">
    		<%
    			String[] months = dfs.getMonths();
    			for(int idx=JANUARY; idx<=DECEMBER; idx++){
    				out.println( String.format("<option value='%d'>%s</option>", idx, months[idx]));
    				
    			}
    		%>
    	</select>
    	<select name="language">
    		<%
    			Locale[] locales =Locale.getAvailableLocales();
    			for(Locale tmp : locales){
    				String display = tmp.getDisplayLanguage(tmp);
    				
    				if(display.isEmpty()) continue;
    				
    				out.println(
    						String.format("<option value ='%s'>%s</option>", tmp.toLanguageTag(), display)
    						);
    			}
    		%>
    		<!-- <option value="ko-KR">한국어</option>
    		<option>영어</option> -->
    	</select>
    	<select name ="timeZoneId">
    		<%
    			//내가 일단 하고 있음
    			/*
    //			TimeZone timeZones = TimeZone.getTimeZone("America/Los_Angeles");
    			//TimeZone[] timeZones = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, null, null);
    			String[] zoneIds = TimeZone.getAvailableIDs();
    			
    			
    			for(String tmz : timeZones){
    				TimeZone tz = TimeZone.getTimeZone(id);
    				out.println(
    						String.format("<option value ='%s'>%s</option>")
    						);
    			}*/
    			
    		%>
    		<option value="Asia/Seoul">아시아/서울</option>
    	</select>
    </form>
    <table>
    <thead>
    	<tr>
    		<%
    			String[] weekDays = dfs.getShortWeekdays();
    			for(int col=SUNDAY; col<=SATURDAY; col++){
    				out.println(String.format("<th>%s</th>", weekDays[col]));
    			}
    		%>
    		</tr>
    	</thead>
    	<tbody>
    	<%
    		
    		
    		for(int row=1; row<=6; row++){
    			out.println("<tr>");
    			for(int col=SUNDAY; col<=SATURDAY; col++){
    				out.println(String.format("<td>%te</td>", calendar));
    				calendar.add(DAY_OF_MONTH, 1);
    			}
    			out.println("</tr>");
    		}
    	%>
    	</tbody>
    </table>
    <script type="text/javascript">
    	let yearTag = $("[name=year]").val("<%=year %>");
    	let monthTag = $("[name=month]").val("<%=month %>");
    	let languageTag = $("[name=language]").val("<%=language %>");
    	
    	$(".changeBtn").on("click",function(event){
    		event.preventDefault();	//안전하게 한번 더 취소... 이제 a태그는 역할을 하지 않음
    		
    		//값을 세팅해 줘야 함... 연도와 월을 꺼내야 함....
    		let year = $(this).data("year");
    		let month = $(this).data("month");
    		
    		yearTag.val(year);
    		monthTag.val(month);
    		
    		calForm.submit();
    		return false;	//event의 기본행위 취소
    		
    	})
    	
    	let calForm = $(document.calForm).on("change",":input[name]",function(event){
    //		evetn.target == this // evetn.target은 this와 같은 의미를 가짐
    //		this.form.submit();		//		이건 submit 이벤트 발생 안 함
    				// this.form ,== document.calForm 이건 이거랑 같죠
    		this.form.requestSubmit();	//이건 submit 이벤트 발생함
    	})
    	
    
    </script>

     

     

    완성하면 위와 같이 페이지를 만들 수 있다.

     

     

     

     

     

     

     

    ㅎㅎ...그만해제발..

     

     

    application의 인증구조 완성,... 확장해서 DB이용...

     

    ???

     

     

    ---

    [누군가 질문]

    btsForm에서 <select name = "member" onchange="this.form.submit();">

    이렇게 해놓으면 submit 이벤트가 발생을 안해서

    <select name = "member" onchange="$(this.form).submit();">

    이렇게 해줘야 한다고 

     

    왜? 이게 뭔지

     

     

    https://developer.mozilla.org/ko/

     

    MDN Web Docs

    The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps.

    developer.mozilla.org

    이 페이지에서 front에서 쓸 수 있느 모든 내용이 있음.

    formelement 저기 들어가보자

     

     

    Methods에 submit 가서 보면

    No submit---- 발생 안된다고 나옴. 그런데 

     

    The HTMLFormElement.requestSubmit() method is identical to activating a form's submit <button> and does not have these differences.

     

    <button>: The Button element - HTML: HyperText Markup Language | MDN

    The <button> HTML element is an interactive element activated by a user with a mouse, keyboard, finger, voice command, or other assistive technology. Once activated, it then performs a programmable action, such as submitting a form or opening a dialog.

    developer.mozilla.org

    이건 뭐가 된대...

     

    그래서 jquery로 쓰되 안되면

    이런 식으로도 쓸 수 있음..

     

     

    그러니까 어쨋든 이걸 외우라는게 아니라 궁금한 게 있으면 정식 document 찾아보고.. 이런 문서들을 보는 경험도 필요하다는거... 여기서 파생되는 내용들이 많다고....

     

    document page.. 우리가 자주 쓰는 곳 3가지가 있음. 

     

    1. JAVA SE API -- 자바 8버전 document임

    https://docs.oracle.com/javase/8/docs/api/

     

    Java Platform SE 8

     

    docs.oracle.com

     

    2. JAVA EE API --

    https://docs.oracle.com/javaee/7/api/toc.htm

     

    Java(TM) EE 7 Specification APIs

     

    docs.oracle.com

     

    3. MOZILA SITE

    https://developer.mozilla.org/en-US/

     

    MDN Web Docs

    The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps.

    developer.mozilla.org

     

    4. J QUERY Document page

    https://api.jquery.com/

     

    jQuery API Documentation

    jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. If you're new t

    api.jquery.com

     

     

    최종 프로젝트 하려면 최소한 이 네군데는 자주 보고 찾아봐야 한다고....(3군데라면서요^^)

    -----

    'main' 카테고리의 다른 글

    22-09-20_jsp  (2) 2022.09.20
    22-09-20_python  (0) 2022.09.20
    22-09-19_python  (0) 2022.09.19
    22-09-16_jsp  (4) 2022.09.16
    22-09-15_jsp  (4) 2022.09.15
Designed by Tistory.