카테고리 없음

자바 풀 스택 1/21 오전 기록 042-1

파티피플지선 2025. 1. 21. 13:19

9:25 경 도착

 

 

<9:30 1교시>

$().action() 대신 $.ajax()를 사용할 수 있다.

 

 

 

인풋요소에 메시지를 입력하면 이 메시지가 이클립스의 콘솔창에 나타나고, send.jsp에서 작성한 내용이 response에 담겨서 웹브라우저의 콘솔 창에 출력된다.

 

 

 

 

url: friends.jsp

이라고 상대경로로 써도 되고

/Step06ETC/jquery/freinds.jsp

라고 절대경로로 써도 되는데

$cpath를 사용할 수 없는 이유는 $ 이 경로가 쓰인 부분이 해석되는게 js에 의해서 해석되기 때문.

$cpath는 jsp에서 해석되는 문자열이다.

 

 

자바스크립트에서 우리가 전달하는 함수가 언제 호출되는지를 알아야 함수를 전달할 수 있다.

fetch 함수 : 서버가 응답을 하면 호출됨.

 

 

 

배열에서 사용할 수 있는 함수 기능 중에서  concat, filter, foreach, map, reduce   에 대해서 익히게 될 것.

 

 

배열.foreach()

for 문 대신에 사용할 수 있는 foreach 함수 : 매개변수로 함수가 전달하는 즉시 배열에 저장된 아이템의 개수 만큼 여러번 호출되며 아이템을 전달해줌 -> for 문 대신 사용 가능

 

 

insertAdjacentHtml 은 html로 해석하고 싶으면 사용

insertAdjacentText는 text로 해석하고 싶으면 사용

 

 

 

매개변수로 index도 전달 가능

 

 

 

배열.map()

map 함수 안에 전달한 함수에서 리턴한 값으로 새로운 배열을 만들어서 리턴하는 함수.

-> 기존에 있던 배열을 전달하고, 각각의 값을 변경해 리턴한 새로운 배열을 얻어냄.

 

 

 

 

<10:30 2교시>

깃허브와 이클립스 작업을 하다 보면 pull이 제대로 안 되는 문제가 생겨서 선생님이 window11의 onedrive가 바탕화면의 폴더들을 백업하면서 문제가 생기는 것 같다고 하심.

그래서 아예 C 드라이브에다가 우리 작업 폴더를 옮기려는데, 그러면 기존에 있던 이클립스 워크스페이스 환경을 그대로 구현하려면 다시 환경을 설정해야하는 번거로움이 있는걸 얌체같이 바꾸는 방법

 

 

새로운 폴더에 깃허브에 업로드해놨던 web work 내용을 클론해온다.

그러면 git은 깨끗한게 만들어 져 있음.

원래 있던 폴더에서 metadata와 나머지 내용을 복사해서 덮어 쓰기 하면 됨.

 

저번에 비밀번호 유효성 검증 vue로 작성하는거

나는 멍청하게 label에다가 클래스를 부여해서.... 안됐던거 같음... 

함수 코딩은 일단 맞았음

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/user/signup_form5.jsp</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
</head>
<body>
	<div class="container" id="app">
		<h1>회원가입 폼 입니다 (vuejs 이용)</h1>
		<form action="signup.jsp" method="post" id="signupForm" novalidate>
			<div class="mb-2">
				<label class="form-label" for="id">아이디</label>
				
				<input :class="{'is-valid':isIdValid ,'is-invalid':!isIdValid && isIdTyped}"
					@input="onIdInput" class="form-control" type="text" name="id" id="id"/>
				<small class="form-text">영문자 소문자로 시작하고 5~10 글자 이네로 입력하세요</small>
				<div class="valid-feedback">사용 가능한 아이디 입니다</div>
				<div class="invalid-feedback">사용할수 없는 아이디 입니다</div>
			</div>
			<div class="mb-2">
				<label class="form-label" for="pwd">비밀번호</label>
				<input @input="onPwdInput" 
						:class="{'is-valid':isPwdValid, 'is-invalid':!isPwdValid&&isPwdTyped}" 
						v-model="pwd" 
						class="form-control" type="password" name="pwd" id="pwd"/>
				<small class="form-text">특수 문자를 하나 이상 조합하세요.</small>
				<div class="invalid-feedback">비밀 번호를 확인 하세요</div>
			</div>
			<div class="mb-2">
				<label  class="form-label" for="pwd2">비밀번호 확인</label>
				<input @input="onPwdMatch" 
						:class="{'is-valid':isPwdValid,'is-invalid':!isPwdValid&&isPwdTyped}"
						v-model="pwd2" class="form-control" type="password"  id="pwd2"/>
			</div>		
			<div class="mb-2">
				<label class="form-label" for="email">이메일</label>
				<input @input="onEmailInput" :class="{'is-valid':isEmailValid ,'is-invalid':!isEmailValid && isEmailTyped}"
					class="form-control" type="email" name="email" id="email"/>
				<div class="invalid-feedback">이메일 형식에 맞게 입력하세요.</div>
			</div>				
			<button class="btn btn-success" type="submit" v-bind:disabled="!isIdValid || !isPwdValid || !isEmailValid">가입</button>
		</form>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<script>
		new Vue({
			el:"#app",
			data:{
				isIdValid:false,
				isIdTyped:false,
				isPwdValid:false,
				isPwdTyped:false,
				isEmailValid:false,
				isEmailTyped:false,
				pwd:"",
				pwd2:""
			},
			methods:{
				onIdInput(e){
						this.isIdTyped=true;
						const reg_id=/^[a-z].{4,9}$/;
						let inputId=e.target.value;
						if(!reg_id.test(inputId)){
							this.isIdValid=false;
							return;
						}
						fetch("${pageContext.request.contextPath }/user/checkid.jsp?id="+inputId)
						.then(res=>res.json())
						.then(data=>{		
							if(data.canUse){
								this.isIdValid=true;
							}else{
								this.isIdValid=false;
							}
						});
				},
				onEmailInput(e){
						this.isEmailTyped=true;
						const reg_email=/@/;
						const email=e.target.value;
						if(reg_email.test(email)){
							this.isEmailValid=true;
							return;
						}else{//제대로 입력하지 않았다면
							this.isEmailValid=false;
						}
				},
				onPwdInput(e){
						
						this.isPwdTyped=true;
						const reg_pwd=/[\W]/;	
						//정규표현식을 만족하는지 확인해서 만족하지 않으면 여기서 함수를 종료.
						//만일 첫번째 비밀번호가 정규표현식을 통과하지 못하거나 두번째 비밀번호가 정규표현식을 통과하지 못한다면~
						if(!reg_pwd.test(this.pwd)||!reg_pwd.test(this.pwd2)){
								this.isPwdValid=false;
								return;
						}
						//위를 통과했다면 여기서는 비밀번호가 같은지 여부를 알아내서 유효성 여부에 반영
						if(this.pwd == this.pwd2){
							//비밀번호가 유효하다
							this.isPwdValid=true;
						}else{
							//비밀번호가 유효하지 않다
							this.isPwdValid=false;
						}
				}		
			}
		});
		
	</script>
</body>
</html>

 

위에건 내거 아래건 샘꺼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/user/signup_form5.jsp</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
</head>
<body>
	<div class="container" id="app">
		<h1>회원가입 폼 입니다 (vuejs 이용)</h1>
		<form action="signup.jsp" method="post" id="signupForm" novalidate>
			<div class="mb-2">
				<label class="form-label" for="id">아이디</label>
				
				<input :class="{'is-valid':isIdValid ,'is-invalid':!isIdValid && isIdDirty}"
					@input="onIdInput"
					class="form-control" type="text" name="id" id="id"/>
					
				<small class="form-text">영문자 소문자로 시작하고 5~10 글자 이네로 입력하세요</small>
				<div class="valid-feedback">사용 가능한 아이디 입니다</div>
				<div class="invalid-feedback">사용할수 없는 아이디 입니다</div>
			</div>
			<div class="mb-2">
				<label class="form-label" for="pwd">비밀번호</label>
				<input v-model="pwd"
					@input="onPwdInput"
					:class="{'is-valid':isPwdValid,'is-invalid':!isPwdValid && isPwdDirty}" 
					class="form-control" type="password" name="pwd" id="pwd"/>
				<small class="form-text">특수 문자를 하나 이상 조합하세요.</small>
				<div class="invalid-feedback">비밀 번호를 확인 하세요</div>
			</div>
			<div class="mb-2">
				<label class="form-label" for="pwd2">비밀번호 확인</label>
				<input v-model="pwd2"
					@input="onPwdInput" 
					class="form-control" type="password"  id="pwd2"/>
			</div>		
			<div class="mb-2">
				<label class="form-label" for="email">이메일</label>
				<input @input="onEmailInput"
					:class="{'is-valid':isEmailValid, 'is-invalid': !isEmailValid && isEmailDirty}"
					class="form-control" type="email" name="email" id="email"/>
				<div class="invalid-feedback">이메일 형식에 맞게 입력하세요.</div>
			</div>				
			<button class="btn btn-success" type="submit" v-bind:disabled="!isIdValid || !isPwdValid || !isEmailValid">가입</button>
		</form>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<script>
		new Vue({
			el:"#app",
			data:{
				isIdValid:false,
				isIdDirty:false,
				isPwdValid:false,
				isPwdDirty:false,
				isEmailValid:false,
				isEmailDirty:false,
				pwd:"", 
				pwd2:""
			},
			methods:{
				onPwdInput(){
					this.isPwdDirty=true;
					//비밀 번호를 검증할 정규 표현식(특수문자 포함여부)
					const reg_pwd=/[\W]/;
					//일단 정규표현식을 만족하는지 확인해서 만족하지 않으면 함수를 여기서 종료
					//만일 첫번째 비밀번호가 정규표현식을 통과하지 못하거나 또는 두번째 비밀번호가 정규표현식을 통과하지 못한다면
					if( !reg_pwd.test(this.pwd) || !reg_pwd.test(this.pwd2) ){
						this.isPwdValid=false;
						return;
					}
					//위를 통과 했다면 여기서는 비밀번호가 같은지 여부를 알아내서 유효성 여부에 반영한다.
					if(this.pwd == this.pwd2){
						//비밀번호가 유효 하다는 의미에서 true 를 넣어준다.
						this.isPwdValid=true;
					}else{
						//비밀번호가 유효 하지 않다는 의미에서 false 를 넣어준다.
						this.isPwdValid=false;
					}
				},
				onEmailInput(e){
					//이메일을 검증할 정규표현식 
					const reg_email=/@/;
					this.isEmailDirty=true;
					//입력한 문자열 읽어오기 
					const email=e.target.value;
					//만일 email 을 제대로 입력 했다면 
					if(reg_email.test(email)){
						this.isEmailValid=true;		
					}else{//제대로 입력하지 않았다면
						this.isEmailValid=false;
					}
				},
				onIdInput(e){
					this.isIdDirty=true;
					//아이디를 검증할 정규 표현식 
					const reg_id=/^[a-z].{4,9}$/;
					//e.target 은 id input 요소의 참조값 
					
					//현재까지 입력한 아이디를 읽어온다.
					let inputId=e.target.value;
					//만일 정규표현식을 통과하지 못했다면 
					if(!reg_id.test(inputId)){
						//아이디의 상태값 변경
						this.isIdValid=false;
						return;
					}
					//fetch() 함수를 이용해서 get 방식으로 입력한 아이디를 보내고 사용가능 여부를 json 으로 응답받는다.
					fetch("${pageContext.request.contextPath }/user/checkid.jsp?id="+inputId)
					.then(res=>res.json())
					.then(data=>{		
						//만일 사용할수 있는 아이디라면
						if(data.canUse){
							//사용할수 있는 아이디라는 의미에서 true 를 넣어준다.
							this.isIdValid=true;
						}else{
							//사용할수 없는 아이디라는 의미에서 false 를 넣어준다.
							this.isIdValid=false;
						}
					});
				}
			}
		});
		
		/*	
		//아이디 유효성 여부를 관리할 변수를 만들고 초기값 부여 
		let isIdValid=false;
		//비밀번호 유효성 여부를 관리할 변수를 만들고 초기값 부여
		let isPwdValid=false;
		//이메일 유효성 여부를 관리할 변수를 만들고 초기값 부여
		let isEmailValid=false;
		
		const checkForm = ()=>{
			//폼 전체의 유효성 여부에 따라 분기한다 (지금은 id 유효성 여부만)
			if(isIdValid && isPwdValid && isEmailValid){
				// type 속성이 submit 인 요소를 찾아서 disabled 속성을 제거한다.
				document.querySelector("[type=submit]").removeAttribute("disabled");
			}else{
				// type 속성이 submit 인 요소를 찾아서 disabled="disabled" 속성을 추가한다.
				document.querySelector("[type=submit]").setAttribute("disabled", "disabled");
			}
		};
		
		//아이디를 검증할 정규 표현식 
		const reg_id=/^[a-z].{4,9}$/;
		
		// id 를 입력할때마다 실행할 함수 등록 
		document.querySelector("#id").addEventListener("input", (event)=>{
			//일단 is-valid, is-invalid 클래스를 모두 지우고 
			event.target.classList.remove("is-valid", "is-invalid");
			
			//현재까지 입력한 아이디를 읽어온다.
			let inputId=event.target.value;
			//만일 정규표현식을 통과하지 못했다면 
			if(!reg_id.test(inputId)){
				
				//어떤 요소에 클래스를 추가하는 방법
				//.classList.add("클래스명")
				
				event.target.classList.add("is-invalid");
				//아이디의 상태값 변경
				isIdValid=false;
				//아이디 상태값 변경이 버튼의 disabled 속성에 변화를 주도록 checkForm() 함수 호출
				checkForm();
				return;
			}
			//fetch() 함수를 이용해서 get 방식으로 입력한 아이디를 보내고 사용가능 여부를 json 으로 응답받는다.
			fetch("${pageContext.request.contextPath }/user/checkid.jsp?id="+inputId)
			.then(res=>res.json())
			.then(data=>{
				//일단 클래스를 제거한 후에 
				event.target.classList.remove("is-valid", "is-invalid");
				//만일 사용할수 있는 아이디라면
				if(data.canUse){
					event.target.classList.add("is-valid");
					//사용할수 있는 아이디라는 의미에서 true 를 넣어준다.
					isIdValid=true;
				}else{
					event.target.classList.add("is-invalid");
					//사용할수 없는 아이디라는 의미에서 false 를 넣어준다.
					isIdValid=false;
				}
				checkForm();
			});
		});
		
		//비밀번호를 검증할 정규표현식 객체
		const reg_pwd=/[\W]/;
		
		//함수를 미리 만들어서
		const checkPwd = ()=>{
			//양쪽에 입력한 비밀번호를 읽어와서 (2줄 코딩)
			let pwd=document.querySelector("#pwd").value;
			let pwd2=document.querySelector("#pwd2").value;
			
			//일단 is-valid 와 is-invalid 클래스를 제거를 먼저하고 (1줄 코딩)
			document.querySelector("#pwd").classList.remove("is-valid", "is-invalid");
			
			//일단 정규표현식을 만족하는지 확인해서 만족하지 않으면 함수를 여기서 종료(return) 해야 한다.
			//만일 첫번째 비밀번호가 정규표현식을 통과하지 못하거나 또는 
			//두번째 비밀번호가 정규표현식을 통과하지 못한다면 isPwdValid 를 false 로 변경하고 checkForm() 호출
			if(!reg_pwd.test(pwd) || !reg_pwd.test(pwd2)){
				document.querySelector("#pwd").classList.add("is-invalid");
				isPwdValid=false;
				checkForm();
				return;
			}
			
			//양쪽에 입력한 비밀번호가 같은지 확인해서 같으면 isPwdValid 를 true 
			// 다르면 isPwdValid 를 false 로 변경하고 checkForm() 호출 
			if(pwd == pwd2){
				document.querySelector("#pwd").classList.add("is-valid");
				//비밀번호가 유효 하다는 의미에서 true 를 넣어준다.
				isPwdValid=true;
			}else{
				document.querySelector("#pwd").classList.add("is-invalid");
				//비밀번호가 유효 하지 않다는 의미에서 false 를 넣어준다.
				isPwdValid=false;
			}
			checkForm();
		};
		
		document.querySelector("#pwd").addEventListener("input", checkPwd);
		document.querySelector("#pwd2").addEventListener("input", checkPwd);
			
		const reg_email=/^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
		
		document.querySelector("#email").addEventListener("input", (event)=>{
			//입력한 문자열 읽어오기 
			const email=event.target.value;
			//일단 is-valid 와 is-invalid 클래스를 제거를 먼저하고 
			document.querySelector("#email").classList.remove("is-valid", "is-invalid");
			//만일 email 을 제대로 입력 했다면 
			if(reg_email.test(email)){
				isEmailValid=true;
				event.target.classList.add("is-valid");
			}else{//제대로 입력하지 않았다면
				isEmailValid=false;
				event.target.classList.add("is-invalid");
			}
			checkForm();
		});
		*/
	</script>
</body>
</html>

 

 

 

 

<11:30 3교시>

EL : Expression Language

자주 쓰던 비교 연산자 대신 gt, ge, lt, le, eq, ne 등을 사용함.

empty, not empty나 3항 연산자도 자주 사용함.

 

 

EL은 자신이 얻은 값을 단순히 출력하는 기능만 있는게 아니라 jstl에서 사용할 수 있는 값을 만들어주기도 한다.

 

 

EL은 Request 영역이나 Session 영역에 저장된 값을 추출할 수 있음.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String myName="김구라";
	/*
		page scope 에  "myName" 이라는 키값으로 myName 담기
		해당 jsp 페이지 에서만 사용할수 있다.
	*/
	pageContext.setAttribute("myName", myName);
	
	String yourName="해골";
	/*
		request scope 에 "yourName" 이라는 키값으로 yourName 담기
		request scope 에 담은 값은 응답하기 전까지 사용할수 있다.
		(다른 페이지로 forward 이동해도 사용할수 있다)
		(다른 페이지로 redirect 이동하면 사용할수 없다)
	*/
	request.setAttribute("yourName", yourName);
	
	String ourName="원숭이";
	/*
		session scope 에  "ourName" 이라는 키값으로 ourName 담기
		session scope 에 담은 값은 세션이 유지 되는 동안 사용할수 있다.
		(다른 페이지로 forward, redirect 이동 해도 사용할수 있다)
		(웹브라우저를 닫거나 세션을 초기화 하기 전까지 사용할수 있다)
	*/
	session.setAttribute("ourName", ourName);
	
	String companyName="에이콘";
	/*
		application scope 에 "companyName" 이라는 키값으로 companyName 담기
		application scope 에 담은 내용은 서버를 끄기 전까지 사용할수 있다.
		(웹브라우저를 닫아도 지워지지 않는다)
	*/
	application.setAttribute("companyName", companyName);
	
%>     
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_el/test02.jsp</title>
</head>
<body>
	<div class="container">
		<h1> EL 로 page scope 에 저장된 값 추출</h1>
		<p>내이름은 <strong>${pageScope.myName }</strong></p>
		<p>내이름은 <strong>${myName }</strong></p>

		<h1>EL 로 request scope 에 저장된 값 추출</h1>
		<p>너의 이름은 <strong>${requestScope.yourName }</strong></p>
		<p>너의 이름은 <strong>${yourName }</strong></p>		
		<%-- 위의 EL 은 아래의 코드를 대신할수 있다. --%>
		<%
			String result = (String)request.getAttribute("yourName");
		%>
		<p>너의 이름은 <strong><%=result %></strong></p>

		<h1>EL 로 session scope 에 저장된 값 추출</h1>
		<p>우리 이름은 <strong>${sessionScope.ourName }</strong></p>
		<p>우리 이름은 <strong>${ourName }</strong></p>
		<%-- 위의 EL 은 아래의 코드를 대신할수 있다. --%>
		<%
			String result2 = (String)session.getAttribute("ourName");
		%>
		<p>우리 이름은 <strong><%=result2 %></strong></p>	

		<h1>EL 로 application scope 에 저장된 값 추출</h1>
		<p>학원 이름은 <strong>${applicationScope.companyName }</strong></p>
		<p>학원 이름은 <strong>${companyName }</strong></p>					
	</div>
</body>
</html>

 

 

클라이언트가 전송한 파라미터를 클라이언트의 웹브라우저에 출력해줘야 할 때 사용하기도 함.

 

 

c:choose 와 c:when, c:otherwise

근데 이 이미지에서 주석 쓴 부분을 쓰니까 에러남 그래서 삭제해주니까 제대로 됨

 

 

 

 

프로젝트 위해서 회원가입&로그인 페이지 만들기 하던거 이어서 함.

 

UserDto도 만듦

package test.user.dto;

public class UserDto {
	private long num;
	private String userName;
	private String password;
	private String email;
	private String role;
	private String profileImage;
	private String createdAt;
	private String updatedAt;
	
	public long getNum() {
		return num;
	}
	public void setNum(long num) {
		this.num = num;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public String getProfileImage() {
		return profileImage;
	}
	public void setProfileImage(String profileImage) {
		this.profileImage = profileImage;
	}
	public String getCreatedAt() {
		return createdAt;
	}
	public void setCreatedAt(String createdAt) {
		this.createdAt = createdAt;
	}
	public String getUpdatedAt() {
		return updatedAt;
	}
	public void setUpdatedAt(String updatedAt) {
		this.updatedAt = updatedAt;
	}
	
}

 

 

이전에 한거에서 필드/변수 이름들 바꿔줌.

signup-form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
<head>
<meta charset="UTF-8">
<title>/user/signup-form.jsp</title>
</head>
<body>
	<div class="container" id="app">
		<h1>회원가입 폼 입니다 (vuejs 이용)</h1>
		<form action="signup.jsp" method="post" id="signupForm" novalidate>
			<div class="mb-2">
				<label class="form-label" for="userName">아이디</label>
				
				<input :class="{'is-valid':isIdValid ,'is-invalid':!isIdValid && isIdTyped}"
					@input="onIdInput" class="form-control" type="text" name="userName" id="userName"/>
				<small class="form-text">영문자 소문자로 시작하고 5~10 글자 이네로 입력하세요</small>
				<div class="valid-feedback">사용 가능한 아이디 입니다</div>
				<div class="invalid-feedback">사용할수 없는 아이디 입니다</div>
			</div>
			<div class="mb-2">
				<label class="form-label" for="password">비밀번호</label>
				<input @input="onPwdInput" 
						:class="{'is-valid':isPwdValid, 'is-invalid':!isPwdValid&&isPwdTyped}" 
						v-model="password" 
						class="form-control" type="password" name="password" id="password"/>
				<small class="form-text">특수 문자를 하나 이상 조합하세요.</small>
				<div class="invalid-feedback">비밀 번호를 확인 하세요</div>
			</div>
			<div class="mb-2">
				<label  class="form-label" for="password2">비밀번호 확인</label>
				<input @input="onPwdMatch" 
						:class="{'is-valid':isPwdValid,'is-invalid':!isPwdValid&&isPwdTyped}"
						v-model="password2" class="form-control" type="password"  id="password2"/>
			</div>		
			<div class="mb-2">
				<label class="form-label" for="email">이메일</label>
				<input @input="onEmailInput" :class="{'is-valid':isEmailValid ,'is-invalid':!isEmailValid && isEmailTyped}"
					class="form-control" type="email" name="email" id="email"/>
				<div class="invalid-feedback">이메일 형식에 맞게 입력하세요.</div>
			</div>				
			<button class="btn btn-success" type="submit" v-bind:disabled="!isIdValid || !isPwdValid || !isEmailValid">가입</button>
		</form>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<script>
		new Vue({
			el:"#app",
			data:{
				isIdValid:false,
				isIdTyped:false,
				isPwdValid:false,
				isPwdTyped:false,
				isEmailValid:false,
				isEmailTyped:false,
				password:"",
				password2:""
			},
			methods:{
				onIdInput(e){
						this.isIdTyped=true;
						const reg_id=/^[a-z].{4,9}$/;
						let inputId=e.target.value;
						if(!reg_id.test(inputId)){
							this.isIdValid=false;
							return;
						}
						fetch("${pageContext.request.contextPath }/user/checkid.jsp?id="+inputId)
						.then(res=>res.json())
						.then(data=>{		
							if(data.canUse){
								this.isIdValid=true;
							}else{
								this.isIdValid=false;
							}
						});
				},
				onEmailInput(e){
						this.isEmailTyped=true;
						const reg_email=/@/;
						const email=e.target.value;
						if(reg_email.test(email)){
							this.isEmailValid=true;
							return;
						}else{//제대로 입력하지 않았다면
							this.isEmailValid=false;
						}
				},
				onPwdInput(e){
						
						this.isPwdTyped=true;
						const reg_pwd=/[\W]/;	
						//정규표현식을 만족하는지 확인해서 만족하지 않으면 여기서 함수를 종료.
						//만일 첫번째 비밀번호가 정규표현식을 통과하지 못하거나 두번째 비밀번호가 정규표현식을 통과하지 못한다면~
						if(!reg_pwd.test(this.password)||!reg_pwd.test(this.password2)){
								this.isPwdValid=false;
								return;
						}
						//위를 통과했다면 여기서는 비밀번호가 같은지 여부를 알아내서 유효성 여부에 반영
						if(this.password == this.password2){
							//비밀번호가 유효하다
							this.isPwdValid=true;
						}else{
							//비밀번호가 유효하지 않다
							this.isPwdValid=false;
						}
				}	
			}
		});
		
	</script>
</body>
</html>

 

 

<12:30 4교시>

UserDao.java(샘이 해준거 걍 복붙했음.. 다시 의미 살펴보기)

package test.user.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import test.user.dto.UserDto;
import test.util.DbcpBean;

public class UserDao {
	//자신의 참조값을 저장할 static 필드
	private static UserDao dao;
	//static 초기화 블럭 (이클래스가 최초로 사용될때 오직 한번만 수행된다)
	static {
		//객체를 생성해서 static 필드에 담는다.
		dao=new  UserDao();
	}
	//외부에서 객체 생성하지 못하도록 생성자의 접근 지정자를 private 로 설정
	private  UserDao() {}
		
	//static 필드에 저장된 GuestDao 의 참조값을 리턴해주는 static 메소드
	public static  UserDao getInstance() {
		return dao;
	}
	
	public UserDto getData(String userName) {
		UserDto dto=null;
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			//Connection Pool 로 부터 Connection 객체 하나 가져오기 
			conn = new DbcpBean().getConn();
			//실행할 sql 문 작성
			String sql = """
				SELECT num, password, email, role, profileImage, createdAt, updatedAt
				FROM users
				WHERE userName=?
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값 바인딩할게 있으면 여기서 하기
			pstmt.setString(1, userName);
			//sql 문 실행하고 결과를 ResultSet 객체로 리턴받기
			rs = pstmt.executeQuery();
			if (rs.next()) {
				dto=new UserDto();
				dto.setNum(rs.getLong("num"));
				dto.setUserName(userName);
				dto.setPassword(rs.getString("password"));
				dto.setEmail(rs.getString("email"));
				dto.setRole(rs.getString("role"));
				dto.setProfileImage(rs.getString("profileImage"));
				dto.setCreatedAt(rs.getString("createdAt"));
				dto.setUpdatedAt(rs.getString("updatedAt"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e) {
			}
		}
		return dto;
	}
	
	public UserDto getData(long num) {
		UserDto dto=null;
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			//Connection Pool 로 부터 Connection 객체 하나 가져오기 
			conn = new DbcpBean().getConn();
			//실행할 sql 문 작성
			String sql = """
				SELECT userName, password, email, role, profileImage, createdAt, updatedAt
				FROM users
				WHERE num=?
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값 바인딩할게 있으면 여기서 하기
			pstmt.setLong(1, num);
			//sql 문 실행하고 결과를 ResultSet 객체로 리턴받기
			rs = pstmt.executeQuery();
			if (rs.next()) {
				dto=new UserDto();
				dto.setNum(num);
				dto.setUserName(rs.getString("userName"));
				dto.setPassword(rs.getString("password"));
				dto.setEmail(rs.getString("email"));
				dto.setRole(rs.getString("role"));
				dto.setProfileImage(rs.getString("profileImage"));
				dto.setCreatedAt(rs.getString("createdAt"));
				dto.setUpdatedAt(rs.getString("updatedAt"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e) {
			}
		}
		return dto;
	}
	
	public boolean insert(UserDto dto) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			// 실행할 SQL 문 작성
	        String sql = """
	            INSERT INTO users 
	            (num, userName, password, email)
	            VALUES (users_seq.NEXTVAL, ?, ?, ?)
	        """;
	        pstmt = conn.prepareStatement(sql);
	        // ? 에 값을 여기서 바인딩한다.
	        pstmt.setString(1, dto.getUserName());
	        pstmt.setString(2, dto.getPassword());
	        pstmt.setString(3, dto.getEmail());
			// sql 문 실행하고 변화된 row 의 갯수 리턴받기
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null)
					conn.close();
				if (pstmt != null)
					pstmt.close();
			} catch (Exception e) {
			}
		}
		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}
	}
	
	public boolean update(UserDto dto) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 미완성의 sql 문
			String sql = """
				UPDATE users
				SET email=?, profileImage=?, updatedAt=SYSDATE
				WHERE num=?		
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값을 여기서 바인딩한다.
			pstmt.setString(1, dto.getEmail());
			pstmt.setString(2, dto.getProfileImage());
			pstmt.setLong(3, dto.getNum());
			// sql 문 실행하고 변화된 row 의 갯수 리턴받기
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null)
					conn.close();
				if (pstmt != null)
					pstmt.close();
			} catch (Exception e) {
			}
		}
		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}
	}
	
	public boolean updatePassword(UserDto dto) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 미완성의 sql 문
			String sql = """
				UPDATE users
				SET password=?, updatedAt=SYSDATE
				WHERE num=?
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값을 여기서 바인딩한다.
			pstmt.setString(1, dto.getPassword());
			pstmt.setLong(2, dto.getNum());
			// sql 문 실행하고 변화된 row 의 갯수 리턴받기
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null)
					conn.close();
				if (pstmt != null)
					pstmt.close();
			} catch (Exception e) {
			}
		}
		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}
	}
	public boolean updateRole(UserDto dto) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 미완성의 sql 문
			String sql = """
				UPDATE users
				SET role=?, updatedAt=SYSDATE
				WHERE num=?
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값을 여기서 바인딩한다.
			pstmt.setString(1, dto.getRole());
			pstmt.setLong(2, dto.getNum());
			// sql 문 실행하고 변화된 row 의 갯수 리턴받기
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null)
					conn.close();
				if (pstmt != null)
					pstmt.close();
			} catch (Exception e) {
			}
		}
		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}
	}
	
	public boolean delete(long num) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int rowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 미완성의 sql 문
			String sql = """
				DELETE FROM users
				WHERE num=?
			""";
			pstmt = conn.prepareStatement(sql);
			// ? 에 값을 여기서 바인딩한다.
			pstmt.setLong(1, num);
			// sql 문 실행하고 변화된 row 의 갯수 리턴받기
			rowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null)
					conn.close();
				if (pstmt != null)
					pstmt.close();
			} catch (Exception e) {
			}
		}
		if (rowCount > 0) {
			return true;
		} else {
			return false;
		}
	}
}

 

 

 

signup-form.jsp 완성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
<head>
<meta charset="UTF-8">
<title>/user/signup-form.jsp</title>
</head>
<body>
	<div class="container" id="app">
		<h1>회원가입 폼 입니다 (vuejs 이용)</h1>
		<form action="signup.jsp" method="post" id="signupForm" novalidate>
			<div class="mb-2">
				<label class="form-label" for="userName">아이디</label>
				<input :class="{'is-valid':isIdValid ,'is-invalid':!isIdValid && isIdTyped}"
					@input="onIdInput" class="form-control" type="text" name="userName" id="userName"/>
				<small class="form-text">영문자 소문자로 시작하고 5~10 글자 이네로 입력하세요</small>
				<div class="valid-feedback">사용 가능한 아이디 입니다</div>
				<div class="invalid-feedback">사용할수 없는 아이디 입니다</div>
			</div>
			<div class="mb-2">
				<label class="form-label" for="password">비밀번호</label>
				<input @input="onPwdInput" 
						:class="{'is-valid':isPwdValid, 'is-invalid':!isPwdValid&&isPwdTyped}" 
						v-model="password" 
						class="form-control" type="password" name="password" id="password"/>
				<small class="form-text">특수 문자를 하나 이상 조합하세요.</small>
				<div class="invalid-feedback">비밀 번호를 확인 하세요</div>
			</div>
			<div class="mb-2">
				<label  class="form-label" for="password2">비밀번호 확인</label>
				<input @input="onPwdInput" 
						:class="{'is-valid':isPwdValid,'is-invalid':!isPwdValid&&isPwdTyped}"
						v-model="password2" class="form-control" type="password"  id="password2"/>
			</div>		
			<div class="mb-2">
				<label class="form-label" for="email">이메일</label>
				<input @input="onEmailInput" :class="{'is-valid':isEmailValid ,'is-invalid':!isEmailValid && isEmailTyped}"
					class="form-control" type="email" name="email" id="email"/>
				<div class="invalid-feedback">이메일 형식에 맞게 입력하세요.</div>
			</div>				
			<button class="btn btn-success" type="submit" v-bind:disabled="!isIdValid || !isPwdValid || !isEmailValid">가입</button>
		</form>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<script>
		new Vue({
			el:"#app",
			data:{
				isIdValid:false,
				isIdTyped:false,
				isPwdValid:false,
				isPwdTyped:false,
				isEmailValid:false,
				isEmailTyped:false,
				password:"",
				password2:""
			},
			methods:{
				onIdInput(e){
						this.isIdTyped=true;
						const reg_id=/^[a-z].{4,9}$/;
						let inputUserName=e.target.value;
						if(!reg_id.test(inputUserName)){
							this.isIdValid=false;
							return;
						}
						fetch("${pageContext.request.contextPath }/user/checkid.jsp?userName="+inputUserName)
						.then(res=>res.json())
						.then(data=>{		
							if(data.canUse){
								this.isIdValid=true;
							}else{
								this.isIdValid=false;
							}
						});
				},
				onEmailInput(e){
						this.isEmailTyped=true;
						const reg_email=/@/;
						const email=e.target.value;
						if(reg_email.test(email)){
							this.isEmailValid=true;
							return;
						}else{//제대로 입력하지 않았다면
							this.isEmailValid=false;
						}
				},
				onPwdInput(e){
						
						this.isPwdTyped=true;
						const reg_pwd=/[\W]/;	
						//정규표현식을 만족하는지 확인해서 만족하지 않으면 여기서 함수를 종료.
						//만일 첫번째 비밀번호가 정규표현식을 통과하지 못하거나 두번째 비밀번호가 정규표현식을 통과하지 못한다면~
						if(!reg_pwd.test(this.password)||!reg_pwd.test(this.password2)){
								this.isPwdValid=false;
								return;
						}
						//위를 통과했다면 여기서는 비밀번호가 같은지 여부를 알아내서 유효성 여부에 반영
						if(this.password == this.password2){
							//비밀번호가 유효하다
							this.isPwdValid=true;
						}else{
							//비밀번호가 유효하지 않다
							this.isPwdValid=false;
						}
				}	
			}
		});
		
	</script>
</body>
</html>

 

 

 

checkid.jsp

<%@page import="test.user.dao.UserDao"%>
<%@page import="test.user.dto.UserDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//1. GET 방식 파라미터로 전달되는 입력한 id 값을 읽어온다.
	String userName=request.getParameter("userName");
	//2. DB에서 해당 회원 정보가 있는지 확인해서 사용가능여부를 알아낸다.
	UserDto dto=UserDao.getInstance().getData(userName);
	boolean canUse= dto == null? true:false;
%>
{"canUse":<%=canUse %>} <%-- 응답되는 json 문자열은 {"canUse":true} or {"canUse":false} --%>

 

 

 

signup.jsp

<%@page import="test.user.dao.UserDao"%>
<%@page import="test.user.dto.UserDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//1. 폼 전송되는 가입 회원 정보를 읽어와서
	String userName=request.getParameter("userName");
	String password=request.getParameter("password");
	String email=request.getParameter("email");
	//2. UserDto 객체에 담아서 
	UserDto dto=new UserDto();
	dto.setUserName(userName);
	dto.setPassword(password);
	dto.setEmail(email);
	//3. UserDao 객체를 이용해서 DB 에 저장한다.
	boolean isSuccess=UserDao.getInstance().insert(dto);
	//4. 응답하기 
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/user/signup.jsp</title>
</head>
<body>
	<div class="container">
		<h1>알림</h1>
		<%if(isSuccess){ %>
			<p>
				<strong><%=userName %></strong>님 가입 되었습니다.
				<a href="login-form.jsp">로그인 하러 가기</a>
			</p>
		<%}else{ %>
			<p>
				가입이 실패 했습니다.
				<a href="signup-form.jsp">다시 가입하러 가기</a>
			</p>
		<%} %>
	</div>
</body>
</html>

 

 

 

 

 

 

Select sequence_name from user_sequences;로 하면 지금까지 만든 squence들을 볼 수 있다.(view 에서 select 한다)

 

 

어제 만든 테이블 오타내서 칼럼 이름을 바꿈

 

SQL> alter table users rename column profileImagae to profileImage;

Table altered.

SQL> desc seq
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SEQUENCE_NAME                             NOT NULL VARCHAR2(30)
 MIN_VALUE                                          NUMBER
 MAX_VALUE                                          NUMBER
 INCREMENT_BY                              NOT NULL NUMBER
 CYCLE_FLAG                                         VARCHAR2(1)
 ORDER_FLAG                                         VARCHAR2(1)
 CACHE_SIZE                                NOT NULL NUMBER
 LAST_NUMBER                               NOT NULL NUMBER