- 기존 MVC 2 방식의 회원가입 폼 실습에서 spring으로 변환한 방식입니다. - spring, java1.8, tomcat 9.0, eclips - 사용 API (Maven 등록) : cglib, annotation, lombok
- 강의에서 배운 내용중 Controller에서 Model과 ModelAndView, RequestParam, {}, Get 등 기초적인 부분을 배웠지만 기초실습 부분중 회원가입에 어울릴 한가지 방식만을 소개해드리겠습니다. - 나머지 기초부분은 스프링 기초 실습 예제글로 따로 포스팅하겠습니다.
Bean을 매개변수로 사용하는 방식
- 디렉토리 구조 - 회원가입 유효성검사 js는 resource 폴더에 따로 위치시켰습니다. - bootstrap 적용을 위해 기존의 파일과 소스들을 가져왔습니다.
porm.xml
- 라이브러리 적용을 위해 프로젝트에 쓸것들을 미리 등록해 둡니다. (cglib, annotation, lombok)
- web.xml, root-context, servlet-context.xml은 기본으로 생성된 코드들로 사용합니다. (추가, 변경사항 없습니다.)
- jsp 부분입니다. - joinmain(초기화면) - joinform(회원가입 폼 화면) - joinview(회원가입 완료 후 이동 페이지)
- 부트스트랩 폴더는 기존에 직접 다운을 받아 사용했던것이 남아있어 그냥 끌고온겁니다. url 형식으로 사용하셔도 상관없습니다. - js/script.js는 회원가입의 유효성 검사를 위한 스크립트 파일입니다. - 다음 주소 API를 사용했습니다. 주소록 API 함수는 오픈된 예제를 사용했으며 joinform에 스크립트 등록을 또 해주어야 합니다. (위에 joinform.jsp 코드에 포함되어 있습니다.)
script.js
var re = /^[a-zA-Z0-9]{4,12}$/; // 아이디와 패스워드가 적합한지 검사할 정규식
var re2 = /^[0-9a-zA-Z]{1,}@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; // 이메일 조건 정규 표현식
function allCheck(){
return (idCheck()&&pwCheck()&&checkMail()&&nameCheck()&&checkAddr()&&ymdCheck()&&checkInterest()&&introCheck());
}
// 아이디
function idCheck(){
var id = document.getElementById("_id");
// ^ 이 규칙으로 문장을 시작한다.
// [문자 규칙을 입력]
// {} = [] 안에 포함되는 문자가 최소 4개부터 12개까지
if(id.value == ""){
window.alert("ID를 입력하세요");
id.focus();
id.value = "";
return false;
}
else if(!re.test(id.value)){
window.alert("아이디는 4~12자와 영어 숫자로만 입력");
id.focus();
id.value = "";
return false;
}
else return true;
}
// 주소 유효성 판별 체크 (상세주소)
function checkAddr(){
var sangaddr = document.getElementById("tbox3").value;
var numaddr = document.getElementById("tbox1").value;
if(numaddr == ""){
alert("주소를 입력해 주세요.");
document.getElementById("tbox1").focus;
return false;
}
if(sangaddr == ""){ //상세주소 없으면 안받아줌
alert("상세주소를 입력해 주세요.");
document.getElementById("tbox3").focus();
return false;
}
else return true;
}
// 비밀번호체크
function pwCheck(){
var pw1 = document.getElementById("_pw");
var pw2 = document.getElementById("_pw2");
// 아이디랑 비번이랑 같을 경우
if (pw1.value == document.getElementById("_id").value)
{
alert("아이디랑 비밀번호가 같으면 안됩니다.")
pw1.focus;
pw1.value = "";
pw2.value = "";
return false;
}
// 비번 길이와 영어소대문자 입력값이 올바른지
// 정규표현식을 true false로 반환할거면 test
else if (!re.test(pw1.value))
{
alert("비밀번호는 4~12자 또는 영문 대소문자만 입력하세요.");
pw1.focus;
pw1.value = "";
pw2.value = "";
return false;
}
// 비번 확인이 잘 안된 경우
else if (pw1.value != pw2.value)
{
alert("비밀번호를 확인해주세요")
pw1.focus;
pw1.value = "";
pw2.value = "";
return false;
}
else return true;
}
// 메일주소
function checkMail(){
var mail = document.getElementById("_mail");
if(mail.value == ""){
alert("이메일 내용을 입력해주세요.");
mail.focus;
mail.value = "";
return false;
}
else if(!re2.test(mail.value)){
alert("이메일 형식을 확인바랍니다.");
mail.focus;
mail.value = "";
return false;
}
else return true;
}
//이름
function nameCheck(){
var name = document.getElementById("_name");
var reKor = /^[가-힣]{1,}$/;
if (name.value == null){
alert("이름을 입력해주세요");
name.focus;
name.value = "";
return false;
}
else if(!reKor.test(name.value)){
alert("한글을 입력해 주세요.")
name.focus;
name.value = "";
return false;
}
else return true;
}
// 주소팝업
function addrFind() {
new daum.Postcode({
oncomplete: function(data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 각 주소의 노출 규칙에 따라 주소를 조합한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
var addr = ''; // 주소 변수
var extraAddr = ''; // 참고항목 변수
//사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
addr = data.roadAddress;
} else { // 사용자가 지번 주소를 선택했을 경우(J)
addr = data.jibunAddress;
}
// 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
if(data.userSelectedType === 'R'){
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
extraAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if(data.buildingName !== '' && data.apartment === 'Y'){
extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if(extraAddr !== ''){
extraAddr = ' (' + extraAddr + ')';
}
// 조합된 참고항목을 해당 필드에 넣는다.
document.getElementById("tbox4").value = extraAddr;
} else {
document.getElementById("tbox4").value = '';
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('tbox1').value = data.zonecode;
document.getElementById("tbox2").value = addr;
// 커서를 상세주소 필드로 이동한다.
document.getElementById("tbox3").focus();
}
}).open();
}
// 주민번호 , 생일
function ymdCheck(){
var today = new Date();
var yearcheck = today.getFullYear()
var ssn = document.getElementById("_ju").value;
var birth = ssn.substr(0,6);
var reymd = /^[0-9]{1,}$/; // 숫자만 판별하고 1개이상들어가야함.
// 몇년생인지 구분
if(!reymd.test(ssn)){
alert("숫자만 입력하세요.");
document.getElementById("_ju").focus;
document.getElementById("_ju").value = "";
return false;
}else{
if(parseInt("20"+birth.substr(0,2)) > yearcheck){
document.getElementById("birth").value = "19"+ birth.substr(0,2);
}
else {
document.getElementById("birth").value = "20"+ birth.substr(0,2);
}
// 월 체크
month[parseInt(birth.substr(2,2))-1].selected = true;
day[parseInt(birth.substr(4,2))-1].selected = true;
if(parseInt(ssn[6]) > 4)
{
alert("너는 성별이 어떻게 되냐?");
}
else if(
ssn[12] != (11-((2*parseInt(ssn[0])+ 3*parseInt(ssn[1])+ 4*parseInt(ssn[2])+
5*parseInt(ssn[3])+ 6*parseInt(ssn[4])+ 7*parseInt(ssn[5])+
8*parseInt(ssn[6])+ 9*parseInt(ssn[7])+ 2*parseInt(ssn[8])+
3*parseInt(ssn[9])+ 4*parseInt(ssn[10])+5*parseInt(ssn[11]))%11)))
{
alert("주민번호가 매우 수상해~");
}
return true;
}
}
//관심분야
function checkInterest(){
var interest = document.getElementsByName("hobby")
var cnt = 0;
for(var i =0; i<interest.length; i ++){
if(interest[i].checked){cnt++};
}
if (cnt == 0)
{
alert("관심분야를 체크해 주세요.")
return false;
}
else return true;
}
// 자기소개
function introCheck(){
var intro = document.getElementById("my_intro");
if(intro.value == ""){
alert("자기소개란에 내용을 입력해주세요.");
intro.focus;
return false;
}
else return true;
}
컨트롤러와 빈 클래스 부분입니다. - HomeController (디스패처가 정보를 전송해주기 위한 컨트롤러) - Member (빈즈 클래스)
HomeController
package com.study.sl;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.study.member.Member;
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
//메인
@RequestMapping("/main")
public String main() {
return "main/joinmain";
}
//회원가입
@RequestMapping("/joinform")
public String joinform() {
return "main/joinform";
}
//회원가입 완료 데이터 표시 페이지
@RequestMapping("/joinview")
public String joinview(HttpServletRequest request, Member member) {
HttpSession session = request.getSession();
session.setAttribute("id", member.getId());
return "main/joinview";
}
}
- joinview 함수에서는 매개변수로 Member라는 개체를 받고 있습니다. member 클래스에 값들이 필드에 맞게 자동으로 전송되어 리턴하게 됩니다. - session은 제가 다른것을 테스트하기 위해 써놓은겁니다 저 부분은 제외하셔도 상관없습니다.
- 해당 Member Class 에 대한 소스 내용입니다. 참으로 허전하죠 ? 클래스 선언 위에 부분을 보시면 @Getter @Setter 어노테이션이 있습니다. 네 말그대로 Getter와 Setter를 담당합니다. 또 @AllArgsConstructor는 생성자를 나타냅니다.
- Maven 에서 lombok api을 등록후 다른 설정이 하나 더 필요한데 이것은 다음에 따로 포스팅 하겠습니다. - 해당 클래스에 대한 구조입니다. - 어노테이션으로 한줄한줄 입력했을뿐인데 해당 객체에대한 게터세터 생성자가 등록되어있습니다. ** 생성자 @AllArgsConstructor를 사용시 객체 생성할떄 직접 값을 넣어주던지 해야합니다. 그렇지 않고 게터세터로만 이용할거면 이 어노테이션은 삭제하시기 바랍니다.
HomeController
- 또한 컨트롤러 부분의 게터를 사용할때도 아무런 문제가 없습니다.
joinform.jsp
- joinform.jsp 내에서도 동작이 잘됩니다. (개쩐당) - 주소하고 취미부분은 따로 설정을 해줘야하는데 귀찮아서 우선 뻈습니다. 다음에 할게요 ..
댓글