JSP 12강 - 유효성 검사2

자주 사용되는 정규식 패턴 정리

숫자만 : ^[0-9]*$
영문자만 : ^[a-zA-Z]*$
한글만 : ^[가-힣]*$
이메일 : /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i
휴대전화 : ^01(?:0|1|[6-9])-(?:\d{3}|\d{4})-\d{4}$
전화번호 : ^\d{2,3}-\d{3,4}-\d{4}$ 
주민번호 : ^\d{6]\-[1-4]\d{6}
IP주소 : ([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})
URL : ^(file|gopher|news|nntp|telnet|https?|ftps?|sftp):\/\/([a-z0-9-]+\.)+[a-z0-9]{2,4}.*\$
날짜 : ^\d{2,4}\/\d{1,2}\/\d{1,2}$

http://regexlib.com에 정규식 관련 정보 있으니 찾아보기

6. 데이터 형식 유효성 검사

  • 사용자가 폼 페이지의 입력 항목에 입력한 데이터 값이 특정 형태에 적합한지 검사하기 위해 정규 표현식을 사용하는 방법
  • 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어
  • 정규 표현식(regExp)에서 사용하는 기호를 메타 문자라고 함
  • 메타 문자는 정규 표현식 내부에서 특정한 의미를 가진 문자

validation05.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<!DOCTYPE html>
<html>
<head>
<title>Validation</title>
</head>
<body>
<script type="text/javascript">
	function checkMember() {
		//id 체크 정규식 : 숫자, 영문만 입력 가능 
		var regExpId = /^[0-9a-z]+$/;
		//비밀번호 : 숫자, 특수문자 각 1회 이상, 영문은 2개 이상 사용하여 8자리 이상 입력
		var regExpPasswd = /(?=.*\d{1,50})(?=.*[~`!@#$%\^&*()-+=]{1,50})(?=.*[a-zA-Z]{2,50}).{8,50}$/;
		//이름 : 한글 검사
		var regExpName = /^[가-힣]*$/;
		//전화번호 형식인지 검사
		var regExpPhone = /^\d{2,3}-\d{3,4}-\d{4}$/;
		//이메일 형식인지 검사
		var regExpEmail = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;

		
		var form = document.Member;
		
		var id = form.id.value;
		var passwd = form.passwd.value;
		var name = form.name.value;
		var phone = form.phone1.value + "-" + form.phone2.value + "-" + form.phone3.value;
		var email = form.email.value;
		
		//정규표현식.test(변수)
		if(!regExpId.test(id)){
			alert("아이디는 숫자, 영문만 입력 가능합니다.");
			form.id.select();
			return;
		}
		if(!regExpPasswd.test(passwd)){
			alert("숫자, 특수문자 각 1회 이상, 영문은 2개 이상 사용하여 8자리 이상 입력 가능합니다.");
			form.passwd.select();
			return;
		}
		if(!regExpName.test(name)){
			alert("이름은 한글만 입력해주세요");
			form.name.select();
			return;
		}
		if(!regExpPhone.test(phone)){
			alert("연락처 형식에 맞춰주세요");
			form.phone2.select();
			return;
		}
		if(!regExpEmail.test(email)){
			alert("이메일 형식에 맞춰주세요");
			form.email.select();
			return;
		}
		//모두 테스트 통과 시 submit 처리
		form.submit();
	}
</script>

<h3>회원 가입</h3>
<form name="Member" method="post" action="validation05_process.jsp">
	<p>아이디 : <input type="text" name="id"/></p>
	<p>비밀번호 : <input type="text" name="passwd"/></p>
	<p>이름: <input type="text" name="name"/></p>
	<p>연락처 :
		<select name="phone1">
			<option value="010">010</option>
			<option value="011">011</option>
			<option value="016">016</option>
			<option value="017">017</option>
			<option value="019">019</option>
		</select>
		<input type="text" maxlength="4" size="4" name="phone2" />
		<input type="text" maxlength="4" size="4" name="phone3" />
	</p>
	<p>이메일 : <input type="text" name="email"/></p>
	<p><input type="button" value="가입하기" onclick="checkMember()" />
</form>

</body>
</html>

jstl_fmt02.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 
<!DOCTYPE html>
<html>
<head>
<title>숫자 형식 맞춰 화면출력</title>
</head>
<body>
<p>숫자 : <fmt:formatNumber value="3200100" /></p>
<p>설정된 숫자를 숫자 형식으로 표현 : 
	<fmt:formatNumber value="3200100" type="number" />
</p>
<p>천 단위 구분 기호(,) 없이 표현 :
	<fmt:formatNumber value="3200100" type="number" groupingUsed="false"/>
</p>
	<!-- groupingUsed가 true여야만 통화 형식으로 표현된다  -->
<p>천 단위 구분 기호(,) 있고, 통화 형식으로 표현 :
	<fmt:formatNumber value="3200100" type="currency" groupingUsed="true"/>
</p>
<p>천 단위 구분 기호(,) 있고, 통화 형식으로 표현 :
	<fmt:formatNumber value="3200100" type="currency" currencySymbol="&"/>
</p>
<p>퍼센트 형식 :
	<fmt:formatNumber value="0.45" type="percent"/>
</p>
<p>소수점 자리 표현 (최대 10자리, 소수점 둘째 자리):
	<fmt:formatNumber value="3200100" minIntegerDigits="10" minFractionDigits="2"/>
</p>
<p>패턴 지정:
	<fmt:formatNumber value="3200100.45" pattern=".000"/>
</p>
<p>패턴 지정:
	<fmt:formatNumber value="3200100.45" pattern="#,#00.0#"/>
</p>
</body>
</html>

숙제
⦁ 다음 조건에 맞게 작업해보자

1) WebContent/js/ 폴더에 validationBook.js 파일 생성
2) 생성된 validationBook.js 파일에 유효성 검사를 위한 핸들러 함수 작성

  • 도서 아이디가 ISBN으로 시작되고 숫자를 포함하여 문자 길이가 5~12자 인지 검사
  • 도서명의 문자 길이가 4~12인지 검사
  • 가격의 문자 길이가 0인지 숫자인지 검사(길이가 0이면 안됨)
  • 가격이 음수인지 검사(음수이면 안됨)
  • 재고 수가 숫자인지 검사

validationBook.js

function CheckAddBook(){
	var bookCode = document.getElementById("bookCode");	
	var bookName = document.getElementById("bookName");	
	var price = document.getElementById("price");
	var stock = document.getElementById("stock");
	
	//도서 아이디가 ISBN으로 시작되고 숫자를 포함하여 문자 길이가 5~12자 인지 검사
	if(!check(/^[0-9]{5,12}$/,bookCode,
		"[상품 코드]\nISBN으로 시작되고 숫자를 포함하여 문자 길이를  5~12자까지 입력하세요.")){
		//submit 안함
		return false;
	}
	//도서명의 문자 길이가 4~12인지 검사
	if(bookName.value.length < 4 || bookName.value.length > 12){
		alert("[도서명]\n최소 4자에서 최대 12자까지 입력하세요");
		bookName.select();
		bookName.focus();
		return false;
	}
	//가격의 문자 길이가 0인지 숫자인지 검사(길이가 0이면 안됨)
	if(price.value.length == 0 || isNaN(price.value)){
		alert("[가격]\n숫자만 입력해주세요");
		price.select();
		price.focus();
		return false;
	}//가격이 음수인지 검사(음수이면 안됨)
	if(price.value < 0){
		alert("[가격]\n음수는 입력할 수 없습니다.");
		price.select();
		price.focus();
		return false;
	}
	//재고 수가 숫자인지 검사
	if(isNaN(stock.value)){
		alert("[재고 수]\n숫자만 입력해주세요");
		stock.select();
		stock.focus();
		return false;
	}
	
	//regExg : 정규표현식, e : 대상객체, msg : alert할 메시지
	//정규표현식에 맞으면 true, 다르면 false를 요청한 곳으로 return
	function check(regExp, e, msg){
		//정규식에 맞으면 바로 true를 return
		if(regExp.test(e.value)){
			return true;
		}
		//정규식에 맞지 않으면..
		alert(msg);
		e.select();
		e.focus();
		//form이 submit 되지 않음
		return false;
	}//end check()
	document.newBook.submit();
}

3) WebContent/ch08/ 폴더에 addBook.jsp 파일 작성

  • 폼 페이지에서 입력되는 도서 아이디, 도서명, 가격, 재고 수의 유효성 검사를 위해 핸들러 함수가 저장되어 있는 validationBook.js 파일을 연결하도록 작성
  • [등록] 버튼을 클릭하면 핸들러 함수가 실행되도록 onclick 속성을 작성

addBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/js/validationBook.js"></script>
<title>도서 등록</title>
</head>
<body>
	<jsp:include page="/ch03/top.jsp" />
	
	<div class="jumbotron">
		<div class="container">
			<h2 class="display-3">도서 등록</h2>
		</div>
	</div>
	<div class="container">	
	<form name="newBook" action="processAddBook.jsp" 
				method="post" class="form-horizontal" enctype="multipart/form-data">
				<div class="form-group row">
					<label class="col-sm-2">도서 코드</label>
					<div class="col-sm-3">
						<input type="text" name="bookCode" id="bookCode"
							class="form-control" />
					</div>
				</div>
			<div class="form-group row">
				<label class="col-sm-2">도서명</label>
				<div class="col-sm-3">
					<input type="text" name="bookName" id="bookName"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">가격</label>
				<div class="col-sm-3">
					<input type="text" name="price" id="price"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">저자</label>
				<div class="col-sm-3">
					<input type="text" name="writer"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">출판사</label>
				<div class="col-sm-3">
					<input type="text" name="publisher"
						class="form-control" />
				</div>
			</div>						
			<div class="form-group row">
				<label class="col-sm-2">출판일</label>
				<div class="col-sm-3">
					<input type="text" name="bookDate"
						class="form-control" />
				</div>
			</div>						
			<div class="form-group row">
				<label class="col-sm-2">총페이지 수</label>
				<div class="col-sm-3">
					<input type="text" name="bookPage"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상세정보</label>
				<div class="col-sm-5">
					<textarea name="bookInfo" rows="2" cols="50" class="form-control"></textarea>
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">분류</label>
				<div class="col-sm-3">
					<input type="text" name="category"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">재고 수</label>
				<div class="col-sm-3">
					<input type="text" name="stock" id="stock"
						class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상태</label>
				<div class="col-sm-5">
					<input type="radio" name="condition" id="condition1" value="new" />
						<label for="condition1">신규도서</label>
					<input type="radio" name="condition" id="condition2" value="Refurbished" />
						<label for="condition2">중고도서</label>
					<input type="radio" name="condition" id="condition3" value="ebook" />
						<label for="condition3">E-Book</label>
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">이미지</label>
				<div class="col-sm-5">
					<input type="file" name="filename" class="form-control" />
				</div>
			</div>
			<div class="form-group row">
				<div class="col-sm-offset-2 col-sm-10">
					<input type="submit" class="btn btn-primary" value="등록" onclick="CheckAddBook()"/>
				</div>
			
			</div>
		</form>	
	</div>
<!-- content 끝 -->
<script type="text/javascript">
CKEDITOR.replace("bookInfo");
</script>

<!-- bottom 인클루드 시작 -->
	<jsp:include page="/ch03/bottom.jsp" />
<!-- bottom 인클루드 끝 -->
</body>
</html>

4) Src.dto 패키지에 Book.java 작성

  • 위 그림에서 입력 받는 요소들을 담을 자바빈 클래스 작성
  • 멤버변수, getter/setter 메소드, toString 메소드 생성

Book.java

package dto;

public class Book {

	private String bookCode;
	private String bookName;
	private Integer price;
	private String writer;
	private String publisher;
	private String bookDate;
	private Integer bookPage;
	private String bookInfo;
	private String category;
	private long stock;
	private String condition;
	private String filename;
	

	public Book() {
		super();
	}
	
	//생성자 
	public Book(String bookCode, String bookName, Integer price) {
		super();
		this.bookCode = bookCode;
		this.bookName = bookName;
		this.price = price;
	}
	
	public String getBookCode() {
		return bookCode;
	}
	public void setBookCode(String bookCode) {
		this.bookCode = bookCode;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public Integer getPrice() {
		return price;
	}
	public void setPrice(Integer price) {
		this.price = price;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getPublisher() {
		return publisher;
	}
	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}
	public String getBookDate() {
		return bookDate;
	}
	public void setBookDate(String bookDate) {
		this.bookDate = bookDate;
	}
	public Integer getBookPage() {
		return bookPage;
	}
	public void setBookPage(Integer bookPage) {
		this.bookPage = bookPage;
	}
	public String getBookInfo() {
		return bookInfo;
	}
	public void setBookInfo(String bookInfo) {
		this.bookInfo = bookInfo;
	}
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
	public long getStock() {
		return stock;
	}
	public void setStock(long stock) {
		this.stock = stock;
	}
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	public String getFilename() {
		return filename;
	}
	public void setFilename(String filename) {
		this.filename = filename;
	}
	
	@Override
	public String toString() {
		return "Book [bookCode=" + bookCode + ", bookName=" + bookName + ", price=" + price + ", writer=" + writer
				+ ", publisher=" + publisher + ", bookDate=" + bookDate + ", bookPage=" + bookPage + ", bookInfo="
				+ bookInfo + ", category=" + category + ", stock=" + stock + ", condition=" + condition + ", filename="
				+ filename + "]";
	}
	
	
	
}

5) src.ch08.com.dao 패키지에 BookRepository.java 클래스 생성

  • src.ch04.com.dao.ProductRepository.java 클래스를 참고하여 적합하게 작성

BookRepository.java

package ch04.com.dao;

import java.util.ArrayList;
import java.util.List;

import dto.Book;

//자바빈즈로 사용할 상품 데이터 접근 클래스
public class BookRepository {
	private List<Book> listOfBooks = new ArrayList<Book>();
	
	//싱글톤 패턴
	private static BookRepository instance = new BookRepository();
	public static BookRepository getInstance() {
		return instance;
	}

	//생성자
	public BookRepository() {
		Book hbook = new Book("9788983928207", "해리 포터와 마법사의 돌 (미나리마 에디션)", 30000);
		hbook.setWriter("J.K. 롤링");
		hbook.setPublisher("문학수첩");
		hbook.setBookDate("2020-10-20");
		hbook.setBookPage(368);
		hbook.setBookInfo("해리 포터 미나리마 에디션 시리즈");
		hbook.setCategory("외국판타지/환상소설");
		hbook.setStock(100);
		hbook.setCondition("New");
		hbook.setFilename("B1234.jpg");
		
		Book dbook = new Book("9791165343729", "달러구트 꿈 백화점 2 ", 13800);
		dbook.setWriter("이미예");
		dbook.setPublisher("팩토리나인");
		dbook.setBookDate("2021-07-27");
		dbook.setBookPage(308);
		dbook.setBookInfo("달러구트 꿈 백화점 2 - 단골손님을 찾습니다");
		dbook.setCategory("한국판타지/환상소설");
		dbook.setStock(1000);
		dbook.setCondition("EBook");
		dbook.setFilename("B1235.jpg");
		
		Book sbook = new Book("9791157675982", "2022 수제비 정보처리기사 실기 FINAL 실전 모의고사 ", 25000);
		sbook.setWriter("NCS 정보처리기술사 연구회");
		sbook.setPublisher("건기원");
		sbook.setBookDate("2021-06-15");
		sbook.setBookPage(474);
		sbook.setBookInfo("수험생 입장에서 제대로 쓴 합격 비법서");
		sbook.setCategory("수험서/자격증");
		sbook.setStock(1000);
		sbook.setCondition("Refurbished");
		sbook.setFilename("B1236.jpg");
		
		listOfBooks.add(hbook);
		listOfBooks.add(dbook);
		listOfBooks.add(sbook);
	}
	//저장된 모든 상품 가져오기
	public List<Book> getAllBooks(){
		return listOfBooks;
	}
	
	//상품  상세정보 가져오기
	public Book getBookByCode(String bookCode) {
		Book BookByCode = null;
		
		for(int i=0; i<listOfBooks.size(); i++) {
			Book book = listOfBooks.get(i);
			
			if(book!=null&&book.getBookCode()!=null&&
					book.getBookCode().equals(bookCode)) {
				BookByCode = book;
				break;
			}
		}
		return BookByCode;
	}
	
	//상품 추가
	public void addBook(Book book) {
		listOfBooks.add(book);
	}
	
	
}

6) WebContent/ch08/ 폴더에 addBook_process.jsp 파일 작성

  • addBook.jsp 요청 시 담긴 폼 데이터를 받아 BookRepository 클래스를 통해 생성한 객체에 넣어줌

ProcessAddBook.jsp

<%@page import="dto.Book"%>
<%@page import="ch04.com.dao.BookRepository"%>
<%@page import="java.util.Enumeration"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ page import="com.oreilly.servlet.MultipartRequest"%>
<!DOCTYPE html>
<html>
<head>
<title>cos.jar 도서 업로드</title>
</head>
<body>

<%
	request.setCharacterEncoding("UTF-8");
	//웹 어플리케이션상의 절대 경로
	String realFolder = "C:\\JSPSpring\\workspace\\JSPBook\\WebContent\\upload";
	
	String filename="";

	//최대 업로드될 파일의 크기 5MB
	int maxSize = 5*1024*1024;
	
	//인코딩 유형
	String encType = "UTF-8";
	
	//cos.jar 라이브러리의 핵심 클래스
	MultipartRequest multi = new MultipartRequest(
			request, realFolder, maxSize, encType, new DefaultFileRenamePolicy()
			);
	//폼 데이터 처리
	String bookCode = multi.getParameter("bookCode");
	String bookName = multi.getParameter("bookName");
	String price = multi.getParameter("price");
	String writer = multi.getParameter("writer");
	String publisher = multi.getParameter("publisher");
	String bookDate = multi.getParameter("bookDate");
	String bookPage = multi.getParameter("bookPage");
	String bookInfo = multi.getParameter("bookInfo");
	String category = multi.getParameter("category");
	String stock = multi.getParameter("stock");
	String condition = multi.getParameter("condition");
	
	Integer bprice;
	if(price.isEmpty()){
		bprice = 0;
	}else{
		bprice = Integer.valueOf(price);
	}
	
	Integer bpage;
	if(bookPage.isEmpty()){
		bpage = 0;
	}else{
		bpage = Integer.valueOf(bookPage);
	}
	
	long bstock;
	if(stock.isEmpty()){
		bstock = 0;
	}else{
		bstock = Long.valueOf(stock);
	}
	
	//파일객체 처리
		//multi객체 안에는 request 객체가 들어있고, request객체 안에는 파일 객체가 있음
		Enumeration files = multi.getFileNames();
		//productImage2
		String fname = (String)files.nextElement();
		//폼 페이지에서 전송되어 서버에 업로드된 파일을 가져옴
		String fileName = multi.getFilesystemName(fname);
		
		out.print("fname : " + fname + ", fileName : " + fileName);
		
		//싱글톤패턴
		BookRepository dao =  BookRepository.getInstance();
		
		Book newBook = new Book();
		newBook.setBookCode(bookCode);
		newBook.setBookName(bookName);
		newBook.setPrice(bprice);
		newBook.setWriter(writer);
		newBook.setPublisher(publisher);
		newBook.setBookDate(bookDate);
		newBook.setBookPage(bpage);
		newBook.setBookInfo(bookInfo);
		newBook.setCategory(category);
		newBook.setStock(bstock);
		newBook.setCondition(condition);
		
		
		//파일 객체의 파일명(fileName : P1237.jpg)
		newBook.setFilename(fileName);
		//dao : data access object(여기서는 메모리 DB라고 생각)
		dao.addBook(newBook);
		//상품 목록으로 리다이렉트
		response.sendRedirect("books.jsp");
	%>

	</body>
	</html>

7) WebContent/ch08/products.jsp 생성

  • addBook.jsp와 addBook_process.jsp를 통해 추가된 book정보를 목록으로 출력
  • WebContent/ch04/products.jsp 참고

Books.jsp

<%@page import="dto.Book"%>
<%@page import="ch04.com.dao.BookRepository"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/css/bootstrap.min.css" />
<title>도서 목록</title>
</head>
<body>
<%
BookRepository bookDAO = BookRepository.getInstance();
%>
	<jsp:include page="/ch03/top.jsp" />
	<div class="jumbotron">
	<div class="container">
		<h1 class="display-3">도서 목록</h1>
	</div>
	</div>
<%
	List<Book> listOfBooks = bookDAO.getAllBooks();
%>	
	<div class="container">
		<div class="row" align="center">
		<%
			for(int i=0; i<listOfBooks.size(); i++){
				Book book = listOfBooks.get(i);
		%>
			<div class="col-md-4">
				<img src="/upload/<%=book.getFilename()%>" style="width: 350px; height: 370px"/>
				<h3><%=book.getBookName() %></h3>
				<p><%=book.getBookInfo() %></p>
				<p><%=book.getWriter()%>|<%=book.getPublisher()%>|<%=book.getPrice() %>원</p>
				<a href="book.jsp?id=<%=book.getBookCode() %>" class="btn btn-secondary" role="button">상세 정보&raquo;</a>
				
			</div>
		<%
			}
		%>
		
		</div>
	</div>		
	<jsp:include page="/ch03/bottom.jsp" />			
</body>
</html>

좋은 웹페이지 즐겨찾기