Input Validation

Sign Up

Form_View

<div>
	<form action="insert" method="post" enctype="multipart/form-data" onsubmit="return check()">
		<table>
			<caption align="top"><b>회원가입</b></caption>
			<tr>
				<td rowspan="5" align="center">
					<input type="file" name="multi" id="myphoto" style="display: none">
					<button type="button" id="btnphoto">사진선택</button><br>
					<img id="showimg">
				</td>
				<td>
					<div>
						<input type="text" name="id" id="id" class="form-control">&nbsp;
						<button type="button" id="btnidcheck">중복체크</button>&nbsp;&nbsp;
						<span class="idsuccess"></span>
					</div>
				</td>
			</tr>
			<tr>
				<td>
					<div>
						<input type="password" class="form-control"	name="pass" id="pass" maxlength="4" required="required">&nbsp;
						<input type="password" class="form-control"	name="pass2" id="pass2" maxlength="4" required="required">&nbsp;&nbsp;
						<span class="passsuccess"></span>
					</div>
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<button type="submit">회원가입</button>
				</td>
			</tr>
		</table>
	</form>
</div>
  • 회원 가입 <form>의 기능 요구사항
    - 파일(이미지) 선택 시 <img>태그로 선택한 이미지 확인 (#showimg)
    - 중복 아이디 검증하여 검증 결과 출력 (.idsuccess)
    - 비밀번호 교차 검증하여 검증 결과 출력 (.passsuccess)
    - 결과 제출(action) 시 위의 3가지 검증 실행 및 통과하지 못하면 제출 거부 (onsubmit=”return check()”)

Validation_Image Preview

$("#btnphoto").click(function(){
	$("#myphoto").trigger("click");
});

//사진 미리보기
$("#myphoto").on("change", function(event) {

  var file = event.target.files[0];

  var reader = new FileReader();
  reader.onload = function(e) {
    $("#showimg").attr("src", e.target.result);
  }

  reader.readAsDataURL(file);
});
  • on 메서드의 (event).target 함수의 files[i] 객체로 변경(선택)한 파일 호출
  • FileReader() 객체의 onload 함수는 파일을 성공적으로 읽을 시 작동

Validation_ID Validation

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="boot.data.mapper.MemberMapperInter">
	<select id="validId" parameterType="String" resultType="int">
		select count(*) from bootmember where id=#{id}
	</select>
</mapper>
  • Sql문을 통해 해당 아이디가 이미 존재하는지 확인
@Service
public class MemberServie implements MemberServiceInter {

	@Autowired
	MemberMapperInter mapperInter;

	@Override
	public int validId(String id) {
		return mapperInter.validId(id);
	}
}
  • @Service에서 로직 처리 (처리 로직이 간단하거나 없으면 @Mapper로 직행 가능)
@Controller
public class MemberController {
	
	@Autowired
	MemberServie service;

	@GetMapping("/member/idcheck")
	public @ResponseBody Map<String, String> idcheck(@RequestParam String id) {
		
		Map<String, String> map=new HashMap<>();
		int check=service.validId(id);
		
		if(check==0)
			map.put("check", "사용가능한 아이디입니다");
		else
			map.put("check", "사용중인 아이디입니다");
		
		return map;
	}
}
  • Ajax 비동기 처리 방식을 사용하기 위해 반환 데이터를 Json 형식으로 전달하기 위해 @ResponseBody 선언
  • 입력 값에 따른 반환 데이터 구분
$("#btnidcheck").click(function(){
	
	var id=$("#id").val();
	var s="";
	
	$.ajax({
		data:{"id":id},
		dataType:"json",
		type:"get",
		url:"idcheck",
		success:function(res){
			s+="<b style='font-size:1em'>"+res.check+"</b>";
			
			$("span.idsuccess").html(s);
			if(res.check=="사용중인 아이디입니다"){
				$("#id").val("");
				$("span.idsuccess").attr("style","width: 200px;color: red");
			}
			else{
				$("span.idsuccess").attr("style","width: 200px;color: blue");
			}
		}
	});
});
  • Ajax의 반환 데이터를 이용해 View 출력

Validation_PW Cross Validation

$("#pass2").keyup(function(){
			
	var p1=$(this).val();
	var p2=$("#pass").val();
	
	if(p1==p2){
		$("span.passsuccess").text("비밀번호 확인");
	}
	else{
		$("span.passsuccess").text("비밀번호 일치시켜주세요");
	}
});
  • keyup 이벤트는 key가 입력될 때 작동하는 이벤트 정의
    • 입력 외의 별도의 작동 트리거는 없음

Confirm Validation

function check(){
	//사진
	if($("#myphoto").val()==""){
		alert("사진을 선택해주세요");
		return false;
	}
	//id
	if($("span.idsuccess").text()!="사용가능한 아이디입니다"){
		alert("아이디 중복체크를 해주세요");
		return false;
	}
	//비밀번호
	if($("span.passsuccess").text()!="비밀번호 확인"){
		alert("비밀번호가 서로 다릅니다");
		return false;
	}
}
  • View의 <form>태그의 onsubmit 조건에 해당 함수 return

Sign In (Log In)

Controller_Main

@Controller
public class LoginController {
	
	@Autowired
	MemberServie service;

	@GetMapping("/login/main") //root의 main과 무관,중간경로 있음
	public String loginform(HttpSession session,Model model) {
		
		String myid=(String)session.getAttribute("myid");
		String loginok=(String)session.getAttribute("loginok");
		
		if(loginok==null)
			return "/login/loginForm";
		else {
			String name=service.getName(myid);
			model.addAttribute("name", name);
			
			return "/sub/login/logoutForm";
		}
	}
}
  • 로그인 기능의 Main 매핑은 로그인 시 로그아웃 폼으로, 로그아웃 시 로그인 폼으로 이동해야 함
  • 로그인, 아웃 후 Main으로 매핑 시 자동으로 이동 페이지 지정

Sign In Form

<form action="loginprocess" method="post">
	<div>
		<input type="text" name="id" value="${sessionScope.saveok==null?'':sessionScope.myid}">
		<input type="password" name="pass">
	</div>
	<button type="submit">LogIn</button>
	<input type="checkbox" name="save" value="yes" ${sessionScope.saveok==null?'':'checked'}>아이디저장
</form>
  • 로그아웃 시 전달 받을 데이터(sessionScope)에 의한 태그 조작을 위한 삼항연산자
    • 초기에는 null 값이므로 이를 처리할 필요 있음

Controller_In Process

@Controller
public class LoginController {

	//autowired 생략
	@PostMapping("/login/loginprocess")
	public String loginproc(@RequestParam String id,String pass,
			@RequestParam(required = false) String save,
			HttpSession session) {
		
		HashMap<String, String> map=new HashMap<>();
		int check=service.loginPassCheck(id, pass);
		
		if(check==1) {
			session.setMaxInactiveInterval(60*60*8);
			
			session.setAttribute("myid", id);
			session.setAttribute("loginok", "yes");
			session.setAttribute("saveok", save);
			
			MemberDto mdto=service.getDataById(id);
			session.setAttribute("loginphoto", mdto.getPhoto());
			
			return "redirect:main";
		}
		else {
			return "/sub/member/passFail";
		}
	}
}
  • ‘아이디저장’ 버튼(save)은 초기 null이므로 반드시 required 조건을 false로 고정
  • Id와 Password의 유효성 검사 메서드 호출
  • `session` 설정
    • setMaxInactiveInterval() 객체로 비동작 session 유지 시간 설정
    • 아이디(myid), 로그인 여부 식별자(loginok), 아이디 저장 여부 식별자(saveok) session 지정
    • 이미지 사용 편의성을 위해 이미지 데이터(loginphoto) session에 등록

Sign Out

Controller_Out Process

@GetMapping("/login/logoutprocess")
public String logout(HttpSession session) {
	
	session.removeAttribute("loginok");
	
	return "redirect:main";
}
  • 로그아웃 폼은 간단하므로 생략
  • 로그아웃 시 로그인 여부 식별자는 제거

View_My Page

<c:forEach var="dto" items="${list }">
	<c:if test="${sessionScope.loginok!=null and sessionScope.myid==dto.id }">
		<table>
			<tr>
				<td rowspan="5" align="center">
					<img src="../membersave/${dto.photo }"><br><br>
					<button type="button" class="mod" num="${dto.num }">사진수정</button>
				</td>
				<th><b>이름</b></th>
				<td><b>${dto.name }</b></td>
				<td rowspan="5" align="center" valign="middle">
					<button type="button" class="mod" onclick="location.href='updatemember?num=${dto.num}'">수정</button>
					<button type="button" class="del" num="${dto.num}">삭제</button>
				</td>
			</tr>
			<!--기타정보 생략-->
		</table>
	</c:if>
</c:forEach>
<input type="file" style="display: none" id="newphoto" num="">
  • <c:if>조건문의 교집합 연산자는 &&, and 모두 유효
  • 아래에서 Ajax를 이용해 파일 처리 및 사진 수정할 것 : 아래의 JavaScript 코드는 이 HTML 코드와 연결

Ajax File Processing

  • Ajax 사용 시 파일 형식의 데이터를 처리하려면 단순 Object 데이터와 다른 방법 필요

FormData Object

  • 일반적으로 폼에 enctype을 별도로 지정하지 않을 경우 application/x-www-form-urlencoded 타입으로 전송
  • application/x-www-form-urlencoded란 데이터 형식이 key=value&key=value의 형태로 전달되는 HTML form의 기본 Content-Type이다.
  • 참고 : 자주 사용되는 application/json은 데이터 형식이 {key: value} 형태

Image Modify

$(".mod").click(function(){
		var num=$(this).attr("num");
			
		$("#newphoto").attr("num",num);
		$("#newphoto").trigger("click");
	});
		
$("#newphoto").change(function(){
	var num=$(this).attr("num");
		
	const form=new FormData();
	form.append("photo",$(this)[0].files[0]); //선택한 한개만 추가
			//MultipartFile객체의 참조변수명..반드시 db컬럼명과 일치
	form.append("num",num);
	
	$.ajax({
		data:form,
		dataType:"html",
		type:"post",
		url:"updatephoto",
		//enctype: 'multipart/form-data',
		processData: false, //이게 enctype
	  contentType: false,
		success:function(){
			location.reload();
		}
	});
});
  • Ajax url로 전달할 데이터는 ***FormData()*** 객체에 담아 보냄
    • append 함수 이용하여 데이터 추가
    • Ajax 사용 시 MultipartFile 객체의 참조변수명은 반드시 DB의 해당 컬럼명과 동일해야 함
  • processData: false, contentType: false설정

SQL_Mapper

<mapper namespace="boot.data.mapper.MemberMapperInter">
	<update id="updatePhoto" parameterType="Map">
		update bootmember set photo=#{photo} where num=#{num}
	</update>
</mapper>

Service

@Service
public class MemberServie implements MemberServiceInter {

	@Autowired
	MemberMapperInter mapperInter;

	@Override
	public int loginPassCheck(String id, String pass) {

		Map<String, String> map=new HashMap<>();
		map.put("id", id);
		map.put("pass", pass);
		
		return mapperInter.loginPassCheck(map);
	}
}

Controller

@Controller
public class MemberController {
	
	@Autowired
	MemberServie service;

	@PostMapping("/member/updatephoto")
	@ResponseBody
	public void modify(@RequestParam String num,
			MultipartFile photo, //MultipartFile객체 참조변수명 반드시 db의 컬럼명과 일치
			HttpSession session) {
		
		String path=session.getServletContext().getRealPath("/membersave");
		String oldphoto=service.getPhotoByNum(num);
		File file=new File(path+"\\"+oldphoto);
		file.delete();
		
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
		String newphoto=sdf.format(new Date())+"_"+photo.getOriginalFilename();

		try {
			photo.transferTo(new File(path+"\\"+newphoto));
			service.updatePhoto(num, newphoto);
			
			session.setAttribute("loginphoto", newphoto);
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • 반환 데이터가 없으므로 void 타입
  • 기타 update 방식은 기존과 동일

Multiple Optional Event

View_List

<input type="checkbox" id="allcheck">
<c:forEach var="dto" items="${list }">
	<table>
		<!--해당 테이블의 정보 생략-->
		<input type="checkbox" num="${dto.num }" class="del">
	</table>
</c:forEach>
<button type="button" id="btnmemberdel" num="">선택강퇴</button>
  • <c:forEach>에 따라 ${list}의 데이터가 반복되며 테이블 생성 (#del 포함)
  • 유일한 버튼
    • 전체 선택 버튼 (#allcheck)
    • 선택한 요소들에게 이벤트 부여하는 버튼 (#btnmemberdel)

Event

$("#allcheck").click(function(){
	var check=$(this).is(":checked");
	alert(check); //true or false
	
	$(".del").prop("checked",check);
});
  • .is(”:checked”) 메서드 중 (”:check”)는 선택 이벤트를 의미하며, is()는 해당 선택자가 해당 이벤트에 당했는지 여부에 따라 true, false 반환
  • .prop(”checked”,check)는 선택자에게 이벤트를 true, false 값에 따라 부여 혹은 제거할지 결정하는 메서드
    • .del에게 “checked” 이벤트를 부여(true), 제거(false)
$("#btnmemberdel").click(function(){
	
	var cnt=$(".del:checked").length;
	
	if(cnt==0){
		alert("먼저 선택해주세요");
		return false;
	}
	$(".del:checked").each(function(i,ele){
		var num=$(this).attr("num");
		
		$.ajax({
			data:{"num":num},
			dataType:"html",
			type:"get",
			url:"delete",
			success:function(){
				alert("삭제 완료");
				location.reload();
			}
		});
	});
});
  • .each() 반복문을 사용하여 :checked 이벤트를 부여한 선택자(.del)에게 모두 결과 함수 적용
  • 결과적으로 하나의 이벤트로 해당 선택자 전체 태그에 이벤트 부여
profile
초보개발자

0개의 댓글