복습

Maven

- pom.xml 에 의존 라이브러리 추가시 원격 저장소에서 로컬 저장소로 다운받음

- Spring Project 에서도 로컬 저장소(레포지토리) 는 똑같은 폴더를 쓴다

 

+ Spring

- Spring Project 도 이와 비슷한 폴더 구조로 만들어진다

- Spring Project 에서는 생성 시 부터 pom.xml 에 기본적인 라이브러리들이 들어있다

 

MyBatis 환경설정 파일

- 마켓플레이스에서 플러그인 다운받으면 생성할 수 있었지만 현재는 불가능

- 한개의 파일만 있으면 된다

- 들어가는 내용

1) Alias 설정

2) DB 연동

3) Mapper 파일 불러오기

 

Mapper 파일

- DAO 클래스 안의 SQL문이 들어있는 파일

- 마켓플레이스에서 플러그인 다운받으면 생성 가능

- 검색되는 컬럼명과 DTO 필드명이 다를때는 resultMap 태그로 매핑을 직접 잡아준다

 


JSP Model 2 - MyBatis 연동 : 회원가입 프로그램

Model 2 과 MyBatis 연동

- 클라우드에서 Model 2 과 MyBatis 가 이미 연동이 완료된 회원가입 프로그램 mybatismember 프로젝트 import

- zip 파일을 압축 풀어서 import

- import 하는 프로젝트는 Maven 프로젝트이다

- Maven 프로젝트이므로 구조는 다음과 같다

- src/main/java 안에 확장자가 java 인 파일들이 저장되어있다 (Controller, Service, DAO, DTO)

+ Model 2 이므로 src/main/java 안에서도 DTO, DAO, Service, Controller 가 서로 다른 패키지 안에 들어가있음

- src/main/resources 안에 DB 연동에 필요한 MyBatis 환경설정 파일 등이 들어가 있다

- src/main/webapp 안에 View 파일 등이 들어간다

 

- import한 mybatismember 프로젝트의 pom.xml 파일을 보자

- pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.myhome</groupId>
	<artifactId>mybatismember</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>mybatismember Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<!-- 복사 시작 -->
	<repositories>
		<repository>
			<id>codelds</id>
			<url>https://code.lds.org/nexus/content/groups/main-repo</url>
		</repository>
	</repositories>

	<dependencies>

		<!-- 오라클 JDBC Library -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>

		<!-- iBatis -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.3</version>
		</dependency>		

		<!-- jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-impl</artifactId>
			<version>1.2.5</version>
		</dependency>

		<!-- cos -->
		<dependency>
			<groupId>servlets.com</groupId>
			<artifactId>cos</artifactId>
			<version>05Nov2002</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>mybatismember</finalName>
	</build>
</project>

- 프로젝트 시작 시 가장 먼저 라이브러리를 구하는 작업을 해야한다

- dependencies 태그 안에 의존 라이브러리를 dependency 태그로 추가

- 오라클 JDBC, MySQL JDBC, iBatis, MyBatis 3.5.3 ver, JSTL, cos 라이브러리가 추가되었다

- 오라클 공식 저장소에서 다운받는 건 오류 많이 발생

- 오라클은 비공식 저장소 repository 를 원격 저장소 위치로 등록하고 거기서 오라클 JDBC 라이브러리를 불러오기

- MyBatis 연동시에는 반드시 MyBatis 라이브러리가 추가되어 있어야함

 

 

Model 2 에 MyBatis 연동시 구조

- Model 2 에서 MyBatis 를 연동

- Controller -> Service -> DAO -> MyBatis 와 연동해서 DB 연동

 

- db.properties

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=totoro
jdbc.password=totoro123

- 여기 db.properties 에 적힌 이 계정으로 접근해서 테이블을 생성해야한다

 

- MyBatis 환경설정 파일인 mybatis-config.xml 파일을 보자

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="model.MemberDTO" alias="member"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="member.xml" />
	</mappers>
</configuration>

 

- Mapper 파일 member.xml 을 보자

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mymember">

	<!-- 회원가입 -->
	<insert id="insert" parameterType="member">
	  insert into member0609 values(#{id},#{passwd},#{name},#{jumin1},#{jumin2},
	  #{mailid},#{domain},#{tel1},#{tel2},#{tel3},#{phone1},#{phone2},#{phone3},
	  #{post},#{address},#{gender},#{hobby},#{intro},sysdate)
	</insert>
	
	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>
	
	<!-- 회원정보 수정 -->
	<update id="update" parameterType="member">
	  update member0609 set name=#{name}, jumin1=#{jumin1}, jumin2=#{jumin2}, 
	  mailid=#{mailid}, domain=#{domain}, tel1=#{tel1}, tel2=#{tel2}, tel3=#{tel3},
	  phone1=#{phone1}, phone2=#{phone2}, phone3=#{phone3}, post=#{post}, address=#{address},
	  gender=#{gender}, hobby=#{hobby}, intro=#{intro} where id = #{id}
	</update>

	<!-- 회원 삭제 -->
	<delete id="delete" parameterType="String">
	  delete from member0609 where id = #{id}
	</delete> 

</mapper>

 

 


 

- db.properties 파일에서 totoro 계정으로 설정되어있으므로 totoro 계정에서 테이블을 생성해야함

+ import 시에 테이블이 생성되지는 않음

- sql 폴더의 model2member.sql 에서 totoro 계정으로 연결한 후 member0609 테이블을 생성하자

- 커넥션 프로파일 설정

- model2member.sql

-- 회원관리
select * from tab;
select * from member0609;

create table member0609(
	id varchar2(20) primary key,
	passwd  varchar2(20) not null,
	name varchar2(20) not null,
	jumin1 varchar2(6) not null,
	jumin2 varchar2(7) not null,
	mailid varchar2(30), 
	domain varchar2(30), 
	tel1 varchar2(5),
	tel2 varchar2(5),
	tel3 varchar2(5),
	phone1 varchar2(5),
	phone2 varchar2(5),
	phone3 varchar2(5),
	post varchar2(10),
	address varchar2(200),
	gender varchar2(20),
	hobby varchar2(50),
	intro varchar2(2000),
	register timestamp );

- 테이블 member0609 를 생성하자

- 테이블의 필드명과 DTO 클래스의 멤버변수(필드, 프로퍼티) 명을 같은 이름으로 설정해야 매핑이 자동으로 일어난다


JSP Model 2 - MyBatis 회원관리 프로그램 : 기본 파일들

- index.jsp

<%@ 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>
<body>

<!-- 모델2 회원관리 -->

<script>
	location.href="./LoginForm.do";
</script>

</body>
</html>

- index.jsp 실행이나 현재 프로젝트 Run As - Run on Server 로 실행시키자

- 로그인 폼이 나타난다

- '회원가입' 을 눌러 회원가입 폼으로 가서 가입을 시키자

- 이제 로그인 페이지로 넘어간다, 아이디, 비번이 일치하면 로그인 성공한다

- 정보수정을 해보자

- 비번이 일치할때 수정된다!

 

Model 2 흐름

Model 2 요청할때 흐름

- View 에서 Controller 로 찾아갈때 WebServlet 어노테이션의 패턴을 맞춰서 찾아간다

- Controller 에서 해당 Service 클래스로 넘긴다, Service 클래스에서 DAO 의 메소드를 불러서 DB와 연동

 

Model 2 돌아올때 흐름

- DAO 클래스에서 검색한 결과를 Service 로 넘기면 Service 에서 결과를 공유설정한다

- 다시 Controller 클래스로 돌아와서 View 페이지로 포워딩됨

 

- src/main/java 에서 model 패키지의 DTO 클래스인 MemberDTO.java 를 보자

// DTO(Data Transfer Object)

package model;

import java.sql.Timestamp;

public class MemberDTO {
	private String id;
	private String passwd;
	private String name;
	private String jumin1;
	private String jumin2;
	private String mailid;
	private String domain;
	private String tel1;
	private String tel2;
	private String tel3;
	private String phone1;
	private String phone2;
	private String phone3;
	private String post;
	private String address;
	private String gender;
	private String hobby;
	private String intro;
	private Timestamp register;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJumin1() {
		return jumin1;
	}
	public void setJumin1(String jumin1) {
		this.jumin1 = jumin1;
	}
	public String getJumin2() {
		return jumin2;
	}
	public void setJumin2(String jumin2) {
		this.jumin2 = jumin2;
	}
	public String getMailid() {
		return mailid;
	}
	public void setMailid(String mailid) {
		this.mailid = mailid;
	}
	public String getDomain() {
		return domain;
	}
	public void setDomain(String domain) {
		this.domain = domain;
	}
	public String getTel1() {
		return tel1;
	}
	public void setTel1(String tel1) {
		this.tel1 = tel1;
	}
	public String getTel2() {
		return tel2;
	}
	public void setTel2(String tel2) {
		this.tel2 = tel2;
	}
	public String getTel3() {
		return tel3;
	}
	public void setTel3(String tel3) {
		this.tel3 = tel3;
	}
	public String getPhone1() {
		return phone1;
	}
	public void setPhone1(String phone1) {
		this.phone1 = phone1;
	}
	public String getPhone2() {
		return phone2;
	}
	public void setPhone2(String phone2) {
		this.phone2 = phone2;
	}
	public String getPhone3() {
		return phone3;
	}
	public void setPhone3(String phone3) {
		this.phone3 = phone3;
	}
	public String getPost() {
		return post;
	}
	public void setPost(String post) {
		this.post = post;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public String getIntro() {
		return intro;
	}
	public void setIntro(String intro) {
		this.intro = intro;
	}
	public Timestamp getRegister() {
		return register;
	}
	public void setRegister(Timestamp register) {
		this.register = register;
	}

}

- 테이블의 필드명과 DTO 클래스의 멤버변수(필드, 프로퍼티) 명을 같은 이름으로 설정해야 매핑이 자동으로 일어난다

- 프로퍼티명이 컬럼명과 동일하게 되어있다, 쉽게 매핑 가능해짐


- Controller 클래스 MemberController.java 를 보자

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.Action;
import service.ActionForward;
import service.Delete;
import service.Idcheck;
import service.Login;
import service.MemberInsert;
import service.Update;
import service.UpdateMember;

/**
 * Servlet implementation class MemberController
 */
@WebServlet("*.do")
public class MemberController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();               
		String command = requestURI.substring(contextPath.length());  
		
		System.out.println("requestURI:"+requestURI);    // requestURI: /model2member/MemberInsert.do
		System.out.println("contextPath:"+contextPath);  // contextPath: /model2member
		System.out.println("command:"+command);          // command: /MemberInsert.do
		
		Action action = null;
		ActionForward forward = null;
		
		// 회원 가입
		if(command.equals("/MemberInsert.do")) {
			try {
				action = new MemberInsert();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 회원가입 폼	
		}else if(command.equals("/MemberForm.do")) {
			forward = new ActionForward();
			forward.setRedirect(true);
			forward.setPath("./member/memberform.jsp");
			
		// ID중복 검사(ajax)	
		}else if(command.equals("/Idcheck.do")) {
			try {
				action = new Idcheck();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 로그인(회원인증)	
		}else if(command.equals("/Login.do")) {
			try {
				action = new Login();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 로그인 폼	
		}else if(command.equals("/LoginForm.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/member/loginform.jsp");	
			
		// 로그 아웃	
		}else if(command.equals("/Logout.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/member/logout.jsp");
			
		// 회원정보 수정폼	
		}else if(command.equals("/UpdateMember.do")) {
			try {
				action = new UpdateMember();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 회원정보 수정	
		}else if(command.equals("/Update.do")) {
			try {
				action = new Update();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		
		// 회원탈퇴 폼	
		}else if(command.equals("/DeleteMember.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/member/deleteform.jsp");
			
		// 회원탈퇴	
		}else if(command.equals("/Delete.do")) {
			try {
				action = new Delete();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
		// 포워딩 처리
		if(forward != null) {
			if(forward.isRedirect()) {		// redirect 방식으로 포워딩
				response.sendRedirect(forward.getPath());
			}else {							// dispatcher 방식으로 포워딩
				RequestDispatcher dispatcher = 
						request.getRequestDispatcher(forward.getPath());
				dispatcher.forward(request, response);
			}
		}		
		
	}// doProcess() end	
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("get");
	
		doProcess(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("post");
		
		doProcess(request, response);		
	}

}

- 사용자가 get 방식 요청시 doGet() 이 자동실행되고, post 방식 요청시 doPost() 가 자동 실행됨

- 공통적인 작업을 하기 위한 doProcess() 메소드

 

Controller 클래스로 찾아가는 2가지 방법

1. WebServlet 어노테이션 패턴을 지정하고, 맞는 패턴으로 찾아가는 방법

- 현재 Model 2

2. Spring 에서는 web.xml 파일 안에서 Controller 클래스 이름, 위치가 등록되고, 매핑을 통해 찾아감

- Model 2 도 예전에 이방법을 사용했었다

 


- 다음은 DAO 클래스 MemberDAO.java 를 보자

// DAO(Data Access Object)

package dao;

import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import model.MemberDTO;

public class MemberDAO {
	
	private static MemberDAO instance = new MemberDAO();
	
	public static MemberDAO getInstance() {
		return instance;
	}
	
	public SqlSession getSession() {
		SqlSession session=null;
		Reader reader=null;			
		try {
			reader = Resources.getResourceAsReader("mybatis-config.xml");
			SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(reader);
			session = sf.openSession(true);	 // auto commit	
		}catch(Exception e) {
			e.printStackTrace();
		}		
		return session;
	}
		
		
	// 회원가입
	public int insert(MemberDTO member) throws Exception{
		int result=0;
		SqlSession session = getSession();
		result = session.insert("insert", member);		
		System.out.println("result:"+result);
		
		return result;
	}
	
	// ID중복검사
	public int idcheck(String id) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		if(member != null) {	// 중복 ID	
			result = 1;			
		}else {					// 사용가능한 ID
			result = -1;
		}
		
		return result;
	}
	
	// 로그인(회원인증)
	public int memberAuth(String id, String passwd) throws Exception {
		int result = 0;
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		if(member != null) {		// 중복 ID	
			if(member.getPasswd().equals(passwd)) {
				result = 1;			// 회원인증 성공
			}else {
				result = -1;		// 회원인증 실패
			}
		}

		return result;
	}

	
	// 회원 1명 정보 구하기 : 수정폼, 수정, 삭제
	public MemberDTO getMember(String id) throws Exception{
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		
		return member;
	}
	
	
	// 회원정보 수정
	public int update(MemberDTO member) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		result = session.update("update", member);

		return result;
	}

	// 회원 탈퇴
	public int delete(String id) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		result = session.delete("delete", id);		
		
		return result;
	}	

}

- MyBatis 와 연동하면 DAO 이후부터가 달라지는 내용이다

- SQL문이 Mapper xml 파일로 빠지고, 그 중간에 MyBatis 환경설정 파일이 있음

 

SqlSession 객체를 구해주는 메소드 (MemberDAO.java 부분)

 

	public SqlSession getSession() {
		SqlSession session=null;
		Reader reader=null;			
		try {
			reader = Resources.getResourceAsReader("mybatis-config.xml");
			SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(reader);
			session = sf.openSession(true);	 // auto commit	
		}catch(Exception e) {
			e.printStackTrace();
		}		
		return session;
	}

- MyBatis 환경설정 파일을 읽어와서 Reader 객체를 구하고, SqlSessionFactory 객체를 구하고, 세션을 openSession 으로 열어서 그 세션을 반환

- SqlSession 객체가 만들어지면, SqlSession 가 제공하는 메소드 5개를 사용할 수 있다

- Maven 에 추가했던 MyBatis 라이브러리의 클래스와 인터페이스들을 DAO 에서 import 해야한다


- MyBatis 환경설정 파일인 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="model.MemberDTO" alias="member"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="member.xml" />
	</mappers>
</configuration>

- property 태그 : 멤버변수를 property 라고 한다, 이 변수 "driver", "url" 등이 모두 프로퍼티 명임, Spring 의 DI 개념

- "driver" 변수에는 오라클과 연동하므로 오라클용 JDBC 드라이버 위치가 저장된 변수값을 사용

 

- ${jdbc.driverClassName} 등은 db.properties 파일에 있는 변수임

+ db.properties

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=totoro
jdbc.password=totoro123

 

- mappers 태그 안에서 Mapper 파일을 불러온다

- 같은 폴더 내에 있으므로 이름인 member.xml 만으로 불러온다

- 테이블이 늘어나면 Mapper 파일이 늘어나고, 이 mappers 태그 안의 코드도 늘어남

- 이 과정을 통해 MyBatis 환경 설정파일은 Mapper 파일을 불러오고, DAO 는 MyBatis 환경 설정 파일을 불러오므로 DAO 에서 Mapper 파일의 id 를 사용 가능하다


- 다음은 Mapper 파일인 member.xml 을 보자

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mymember">

	<!-- 회원가입 -->
	<insert id="insert" parameterType="member">
	  insert into member0609 values(#{id},#{passwd},#{name},#{jumin1},#{jumin2},
	  #{mailid},#{domain},#{tel1},#{tel2},#{tel3},#{phone1},#{phone2},#{phone3},
	  #{post},#{address},#{gender},#{hobby},#{intro},sysdate)
	</insert>
	
	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>
	
	<!-- 회원정보 수정 -->
	<update id="update" parameterType="member">
	  update member0609 set name=#{name}, jumin1=#{jumin1}, jumin2=#{jumin2}, 
	  mailid=#{mailid}, domain=#{domain}, tel1=#{tel1}, tel2=#{tel2}, tel3=#{tel3},
	  phone1=#{phone1}, phone2=#{phone2}, phone3=#{phone3}, post=#{post}, address=#{address},
	  gender=#{gender}, hobby=#{hobby}, intro=#{intro} where id = #{id}
	</update>

	<!-- 회원 삭제 -->
	<delete id="delete" parameterType="String">
	  delete from member0609 where id = #{id}
	</delete> 

</mapper>

- MyBatis 환경설정 파일에서 이 Mapper 파일을 불러올때 "mapper" 태그 안에서 불러왔으므로 이 Mapper 파일의 루트 엘리먼트도 "mapper" 이어야함

- namespace 값을 써서 다른 Mapper 파일 내에 id 중복 문제를 피한다

- 넘어오는 값의 자료형을 parameterType 에 쓰고, 돌려주는 값의 자료형을 returnType 에 쓴다


JSP Model 2 - MyBatis 연동 구조



JSP Model 2 - MyBatis 회원관리 프로그램 : 회원가입 기능

흐름 설명

1. index.jsp 에서 "/LoginForm.do" 로 요청

2. 어노테이션 패턴에 맞으므로 Controller 클래스로 찾아감, doGet() -> doProcess() 실행됨

- index.jsp 에서 location.href 로 Controller 로 찾아왔다, 폼이 아니므로 Get 방식 전송

3. command 변수에 저장된 내용을 통해 ActionForward 객체 forward 생성 후 포워딩 페이지, 방식 설정 후 밑에서 포워딩

- loginForm.jsp 로 포워딩 됨

- DB 연동안하므로 Service 클래스가 아닌 폼으로 감

4. 로그인 폼인 loginForm.jsp 로 넘어와서 '회원가입' 버튼을 누르면 "/MemberForm.do" 로 요청, 즉 회원가입 폼으로 간다

5.어노테이션 패턴에 맞으므로 Controller 클래스로 찾아감, doGet() -> doProcess() 실행됨

- loginForm.jsp 에서 location.href 로 Controller 찾아왔다, 폼이 아니므로 Get 방식 전송

6. command 변수에 저장된 내용을 통해 ActionForward 객체 forward 생성 후 포워딩 페이지, 방식 설정 후 밑에서 포워딩

- memberForm.jsp 로 포워딩 됨

7. 회원가입 폼인 memberForm.jsp 로 넘어와서 정보 입력 후 '회원가입' 버튼을 누르면 "/MemberInsert.do" 로 요청

- form에서 post 방식으로 전송

8. 어노테이션 패턴에 맞으므로 Controller 클래스로 찾아감. doPost() -> doProcess() 실행됨

9. command 변수에 저장된 내용을 통해 회원가입을 처리해주는 Service 클래스인 MemberInsert.java 로 보내줌

10.MemberInsert.java 에서 DTO 객체생성 후 회원가입 폼에서 입력된 값들을 모두 DTO 객체에 저장

- Spring 에서는 직접 DTO 객체 생성하고,Setter 메소드로 일일히 저장하는 작업 하지 않는다, 어노테이션으로 처리함

11. DAO 객체를 생성 후 DAO 의 insert() 메소드 호출하고, 매개변수로는 값을 설정한 DTO 객체를 전달

12. DAO 의 insert() 메소드안에서 SqlSession 객체를 받고, session.insert("insert',member) 로 id 가 insert 인 Mapper 파일의 SQL문 호출

- 삽입할 데이터를 전달해줘야 하므로, 전달할 값인 DTO 객체 member 를 두번째 매개변수에 써서 전달

13. Mapper 파일 member.xml 에서 id 가 insert 인 태그 안 SQL문 실행 후 삽입된 데이터 개수 1개를 돌려줌

14. DAO 에서 result 로 그 삽입된 데이터 개수 1개를 받아서 Service 클래스로 리턴함

15. Service 에서 - Service 클래스 하단에서 포워딩 방식, 포워딩할 페이지 지정

- Dispatcher 방식, loginform.jsp 페이지로 포워딩할 것

16. Service 클래스를 호출한 Controller 클래스로 돌아간다

17. Controller 클래스에서 forward != null 이므로 설정된 곳으로 포워딩함

- Dispatcher 방식, loginform.jsp 페이지로 포워딩 한다

 

코드 및 설명

- Controller 클래스에서 "/MemberForm.do" 부분만

		// 회원가입 폼	
		}else if(command.equals("/MemberForm.do")) {
			forward = new ActionForward();
			forward.setRedirect(true);
			forward.setPath("./member/memberform.jsp");
		}

- 회원가입 폼 memberform.jsp 는 길어서 코드 붙이지 않았다 * 나중에 ID중복검사 기능 부분 설명때 붙일 것

- Controller 클래스에서 "/MemberInsert.do" 부분만

		// 회원 가입
		if(command.equals("/MemberInsert.do")) {
			try {
				action = new MemberInsert();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}

 

- 회원가입 Service 클래스인 MemberInsert.java

package service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.MemberDAO;
import model.MemberDTO;

public class MemberInsert implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("MemberInsert");
		
		request.setCharacterEncoding("utf-8");
		
		MemberDTO member = new MemberDTO();
		member.setId(request.getParameter("id"));
		member.setPasswd(request.getParameter("passwd"));
		member.setName(request.getParameter("name"));
		member.setJumin1(request.getParameter("jumin1"));
		member.setJumin2(request.getParameter("jumin2"));
		member.setMailid(request.getParameter("mailid"));
		member.setDomain(request.getParameter("domain"));
		member.setTel1(request.getParameter("tel1"));
		member.setTel2(request.getParameter("tel2"));
		member.setTel3(request.getParameter("tel3"));
		member.setPhone1(request.getParameter("phone1"));
		member.setPhone2(request.getParameter("phone2"));
		member.setPhone3(request.getParameter("phone3"));
		member.setPost(request.getParameter("post"));
		member.setAddress(request.getParameter("address"));
		member.setGender(request.getParameter("gender"));
		
		String h = "";
		String[] h1 = request.getParameterValues("hobby");
		for(String h2 : h1) {
			h += h2+"-";			// 공부-게임-
		}
		member.setHobby(h);
		
		member.setIntro(request.getParameter("intro"));
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.insert(member);
		if(result == 1) {
			System.out.println("회원가입 성공");
		}
		
		ActionForward forward = new ActionForward();
		forward.setRedirect(false);
		forward.setPath("/member/loginform.jsp");
		
		return forward;
	}

}

 

- MemberDAO.java 에서 insert() 메소드 부분만

	// 회원가입
	public int insert(MemberDTO member) throws Exception{
		int result=0;
		SqlSession session = getSession();
		result = session.insert("insert", member);		
		System.out.println("result:"+result);
		
		return result;
	}

- Maven 에 추가했던 MyBatis 라이브러리의 클래스와 인터페이스들을 DAO 에서 import 해야한다

- session.insert("아이디", 전달할 값) 로 Mapper 파일의 SQL문을 불러오고 있다

- session.insert() 실행 후 자동으로 삽입 성공 데이터 개수 (1) 를 돌려준다, 그걸 result 변수에 받아서 리턴하고 있음

- DB 연동을 수행하므로 예외처리를 해야한다

- try - catch 로 직접 예외처리를 해도 되고, 메소드를 호출한 곳에 throws 로 예외를 던져도 된다

 

- member.xml 에서 회원 가입을 처리하는 SQL문 부분 (id 가 insert)

	<!-- 회원가입 -->
	<insert id="insert" parameterType="member">
	  insert into member0609 values(#{id},#{passwd},#{name},#{jumin1},#{jumin2},
	  #{mailid},#{domain},#{tel1},#{tel2},#{tel3},#{phone1},#{phone2},#{phone3},
	  #{post},#{address},#{gender},#{hobby},#{intro},sysdate)
	</insert>

- parameterType 속성값인 "member"는 MyBatis 환경설정 파일에서 Alias 값으로 지정한 별칭이다

- #{mailid} 의 의미는 member.getMailid()

 

+ member.xml 의 namespace

- Mapper 파일은 테이블 수에 비례해서 늘어나므로 namespace 가 있어야 서로 다른 파일에서 id 중복이 되더라도 충돌이 일어나지 않음

 

- 회원가입 시도시 콘솔창

- 회원가입이 성공적으로 되었음


JSP Model 2 - MyBatis 회원관리 프로그램 : 아이디 중복검사 기능

코드와 흐름 같이 설명

- ajax 로 처리

- 회원가입 폼인 memberform.jsp 파일을 보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
//				document.getElementById('join_zip2').value = data.postcode2;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>


<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="<%=request.getContextPath() %>/member/member.js"></script>

</head>
<body>

<form method="post" action="<%=request.getContextPath() %>/MemberInsert.do"> 
<table border=1 width=500 align=center>
	<caption>회원 가입</caption>
	<tr><td>ID</td>
		<td><input type=text autofocus="autofocus" id="id" name="id">
			<input type=button value="ID중복검사" id="idcheck">
			<div id="myid"></div>
		</td>
	</tr>
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd"></td>
	</tr>
	<tr><td>성명</td>
		<td><input type=text id="name" name="name"></td>
	</tr>
	<tr><td>주민번호</td>
		<td><input type=text size=6 maxlength=6 id="jumin1" name="jumin1">-
			<input type=text size=7 maxlength=7 id="jumin2" name="jumin2">
		</td>
	</tr>
	<tr><td>E-Mail</td>
		<td><input type=text size=10 id="mailid" name="mailid">@
		    <input type=text size=10 id="domain" name="domain">
		    <select id="email">
		    	<option value="">직접입력</option>
		    	<option value="naver.com">네이버</option>
		    	<option value="daum.net">다음</option>
		    	<option value="nate.com">네이트</option>
		    	<option value="gmail.com">gmail</option>
		    </select>		    
		 </td>
	</tr>
	<tr><td>전화번호</td>
		<td><input type=text size=4 id="tel1" name="tel1" maxlength=4>-
			<input type=text size=4 id="tel2" name="tel2" maxlength=4>-
			<input type=text size=4 id="tel3" name="tel3" maxlength=4>
		</td>
	</tr>
	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010">010</option>
				<option value="011">011</option>
				<option value="016">016</option>
				<option value="018">018</option>
				<option value="019">019</option>
			</select>-
			<input type=text size=4 id="phone2" name="phone2" maxlength=4>-
			<input type=text size=4 id="phone3" name="phone3" maxlength=4>
		</td>
	</tr>
	<tr><td>우편번호</td>
		<td><input type=text size=5 id="post" name="post">
			<input type=button value="우편번호검색" 
			       onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><td>주소</td>
		<td><input type=text size=45 id="address" name="address"></td>
	</tr>
	<tr><td>성별</td>
		<td>
			<input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</td>
	</tr>
	<tr><td>취미</td>
		<td>
			<input type="checkbox" id="h1" name="hobby" value="공부" checked>공부
			<input type="checkbox" id="h2" name="hobby" value="게임">게임
			<input type="checkbox" id="h3" name="hobby" value="등산">등산
			<input type="checkbox" id="h4" name="hobby" value="낚시">낚시
			<input type="checkbox" id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>	
	<tr><td>자기소개</td>
		<td>
			<textarea id="intro" name="intro" rows="5" cols="50" placeholder="자기소개를 100자 이내로 입력하세요"></textarea>
		</td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원가입">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>


</body>
</html>

- ID 중복검사 부분의 버튼의 id 는 "idcheck", 메세지를 출력할 div 태그의 id 값은 "myid", ID 입력양식의 id 는 "id"

- member.jsp 파일을 외부 자바 스크립트 파일로 불러온다

 

- member.jsp 파일에서 ID중복검사 부분을 보자

$(document).ready(function(){	
	
	// ID 중복검사
	$("#idcheck").click(function(){
		if($("#id").val()==""){
			alert("ID를 입력하세요");
			$("#id").focus();
			return false;
		}else{
			
			var id = $("#id").val();	
			
			$.ajax({
				type:"post",
				url:"/mybatismember/Idcheck.do",
				data:{"id":id},
				datatype:"text",
				success:function(data){
//					alert(data);
					
					if(data==1){	// 중복 ID
						$("#myid").text("중복ID");
						$("#id").val("").focus();
					}else{			// 사용 가능한 ID
						$("#myid").text("사용 가능한 ID");
						$("#passwd").focus();
					}					
				}
			});			
		}		
	});
})

- jQuery 로 버튼을 가장 먼저 구해오고, click 함수처리 + click 대신 keyup 이벤트로 처리해도 된다

- 입력양식에 값이 입력되지 않아씅면 경고창 띄우기

- 값이 입력되었을때 그 값을 가져와서 변수 id 에 저장

- $.ajax() 를 통해 "Idcheck.do" 로 요청

- 패키지가 다르므로 패키지명도 앞에 써준다

- 값을 가져갈때는 json 형태로 값을 가져간다 "id" 속성명에 id 값을 가져감

- 콜백함수로 데이터를 돌려받음, 돌려받은 뒤 1이 리턴되면 중복 ID 로 처리함, 리턴되는 값이 1 이 아니면 사용가능한 ID로 처리

 

- Controller 클래스로 간다

- Controller 클래스에서 "/Idcheck.do" 부분만

		// ID중복 검사(ajax)	
		}else if(command.equals("/Idcheck.do")) {
			try {
				action = new Idcheck();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}

 

- 여기서 Service 클래스인 Idcheck.java 파일로 보내준다

- Idcheck.java

package service;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.MemberDAO;

public class Idcheck implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Idcheck");
		
		request.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		
		String id = request.getParameter("id");
		System.out.println("id:"+ id);
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.idcheck(id);
		System.out.println("result:"+ result);	// 1 :  중복ID, -1 : 사용가능한 ID
		out.println(result);	// 브라우저에 출력되는 값이 callback함수로 리턴된다.
		
		return null;
	}

}

- member.js 에서 ajax 로 전달한 사용자가 입력한 id 값을 속성명 "id" 를 사용해서 request.getParameter("id") 로 받음

- DB와 연동하여 중복 ID 인지 아닌지 확인해야하므로 DAO 객체 생성 후 DAO의 idcheck() 메소드 호출

- idcheck() 메소드 호출 시 매개변수로 사용자가 입력한 id 값을 전달함

- idcheck() 에서 리턴된 값을 result 로 받음, 이때 중복 ID는 1, 사용가능한 ID는 -1 로 전달해주기로 함

- 콜백함수로 리턴되는 값은 브라우저에 출력되는 값이므로 out 객체로 result 값을 출력

+ System.out.println() 은 콘솔에 출력되는 값, out.println() 은 브라우저에 출력되는 값

 

- MemberDAO.java 에서 idcheck() 메소드 부분만

	// ID중복검사
	public int idcheck(String id) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		if(member != null) {	// 중복 ID	
			result = 1;			
		}else {					// 사용가능한 ID
			result = -1;
		}
		
		return result;
	}

- 매개변수로 사용자가 입력한 id 값을 전달받음

- SqlSession 객체를 변수 session 으로 받아오고 session.selectOne() 메소드를 호출하면서 Mapper 파일에서 id 가 "idcheck" 인 태그의 SQL문 호출

- 그 SQL문을 호출하면서 사용자가 입력한 id 를 넘김

- 사용자가 입력한 id 에 해당하는 검색되는 결과가 1개이므로 selectOne() 메소드로 검색해야함

- selectOne() 을 호출 후 DTO 객체 member 를 반환함, 그 객체가 있으면 DB에 이미 같은 id 인 데이터가 있다는 의미이므로 1 리턴

- 받아온 객체가 null 이면 같은 id 인 데이터가 없다는 의미이므로 사용가능한 id 라는 의미로 -1 리턴

 

  - member.xml 에서 ID중복검사를 처리하는 SQL문 부분 (id 가 idcheck)

	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>

- 전달되는 값은 id 이므로, 전달되는 값의 자료형인 String 을 parameterType 으로 쓴다

+ parameterType 속성값인 "member"는 MyBatis 환경설정 파일에서 Alias 값으로 지정한 별칭이다

- 돌려주는 데이터 타입은 DTO 이므로, resultType 에 member 를 쓴다

- SQL문에서 #{id} 는 전달되는 값의 변수명인 id 를 써준다

 

- 중복 아닌 ID 입력 후 'ID중복검사' 눌렀을때 콘솔 창

- 중복 ID 입력 후 'ID중복검사' 눌렀을때 콘솔 창


JSP Model 2 - MyBatis 회원관리 프로그램 : 로그인 기능

흐름 설명

1. index.jsp 에서 "/LoginForm.do" 로 요청

2. 어노테이션 패턴에 맞으므로 Controller 클래스로 찾아감, doGet() -> doProcess() 실행됨

- index.jsp 에서 location.href 로 Controller 로 찾아왔다, 폼이 아니므로 Get 방식 전송

3. command 변수에 저장된 내용을 통해 ActionForward 객체 forward 생성 후 포워딩 페이지, 방식 설정 후 밑에서 포워딩

- loginForm.jsp 로 포워딩 됨

- DB 연동안하므로 Service 클래스가 아닌 폼으로 감

4. 로그인 폼인 loginForm.jsp 로 넘어와서 아이디, 비번 입력 후 '로그인' 클릭시 form 태그에서 "/Login.do" 로 요청

- 사용자가 입력한 아이디, 비번 값도 전달함

- post 방식으로 요청했다

5. 어노테이션 패턴에 맞으므로 Controller 클래스로 찾아감, doPost() -> doProcess() 실행됨

- loginForm.jsp 에서 form 에서 post 방식으로 Controller 로 찾아왔다

+ 이땐 ActionForward 객체 forward 가 null 이므로 포워딩 코드에 접근하지 않음

6. command 변수에 저장된 내용을 통해 로그인(회원 인증)을 처리해주는 Service 클래스인 Login.java 로 보내줌

7. Login.java 에서 로그인 성공시 필요한 session 객체와 out 객체를 구한다

8. Login.java 에서 사용자가 로그인 폼에 입력한 아이디, 비밀번호를 받아서 저장

9. 회원 인증을 처리하기 위해 DB와 연동해야하고, DAO 객체를 생성하고 DAO의 memberAuth(id, passwd) 메소드 호출

- 매개변수로 사용자가 전달한 id, passwd 를 전달

10. DAO 클래스에서 memberAuth() 에서 SqlSession 객체 session 을 구하고 session.selectOne("idcheck",id) 호출하며 Mapper 파일에서 id 가 "idcheck" 인 태그의 SQL문 호출

- 1명에 대한 데이터를 가져오므로 selectOne() 사용

- 전달하는 값은 사용자가 입력한 id 이다

11. Mapper 파일 member.xml 에서 id 가 idcheck인 태그 안 SQL문 실행 후 id 에 해당하는 1명에 대한 상세정보를 DTO 객체로 리턴함

12. DAO 클래스에서 selectOne() 실행 후 돌려받은 값을 DTO 객체 member 에 저장한다

13. 그 객체 member 가 null 이 아니면 그 id 로 검색한 데이터가 DB에 존재한다는 뜻이므로 id가 일치한다는 의미

14. 다음엔 사용자가 입력한 비번과 member 에서 가져온 DB의 비번이 각각 일치시 회원 인증 성공으로 보고 1을 리턴

- 일치하지 않으면 회원 인증 실패로 보고 -1 리턴

15. Service 클래스로 돌아와서 memberAuth() 가 1을 리턴하면 성공으로 보고, 세션으로 id 값을 공유설정하고 포워딩 방식과 포워딩 페이지 설정 

- 여기서부터 SESSION 영역 시작

- 포워딩 할 페이지는 main.jsp 로 설정

+ session 공유시엔 상관없고, Service 클래스에서 request 방식 공유를 했을땐 Dispatcher 방식으로 포워딩 설정해야만 공유된 값 사용 가능

- 로그인 실패시 메세지를 뿌리고 이전 페이지로 돌아감

16. Service 클래스를 호출한 Controller 클래스로 돌아가서, 생성되고 값이 설정된 forward 객체를 리턴함

17. Controller 클래스에서 forward != null 이므로 Controller 클래스 하단에서 포워딩할 페이지, 방식을 가져와서 main.jsp 로 Dispatcher 방식 포워딩함

- Service 하단에서 설정했던 포워딩 페이지, 방식을 여기서 구해와서 실제 포워딩하는 것

18. main.jsp 에서 세션을 구해옴, 이때 세션이 있을때와 없을때 다른 화면을 보여줌

 

- MemberDAO.java 에서 memberAuth() 메소드 부분만

	// 로그인(회원인증)
	public int memberAuth(String id, String passwd) throws Exception {
		int result = 0;
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		if(member != null) {		// 중복 ID	
			if(member.getPasswd().equals(passwd)) {
				result = 1;			// 회원인증 성공
			}else {
				result = -1;		// 회원인증 실패
			}
		}

		return result;
	}

 

 

- member.xml 에서 로그인(회원 인증) 처리하는 SQL문 부분 (id 가 idcheck)

	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>

+ ID 중복검사 할때와 같은 SQL문 사용

 

- 맞는 아이디, 비밀번호 입력 후 로그인 시

 

- 마지막으로 로그인 성공 후 포워딩되는 메인 페이지인 main.jsp 를 보자

- main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> --%> <!-- 안됨 -->


<!--  세션이 있으면 -->
<%-- <c:if test="${not empty sessionScope.id}"> --%>	<!-- 2개 모두 잘됨 -->
<c:if test="${sessionScope.id != null }">
	${sessionScope.id} 님 환영 합니다. <br><br>
	
	<a href="<%=request.getContextPath() %>/UpdateMember.do">회원정보 수정</a>  <br><br>
	
	<a href="<%=request.getContextPath() %>/Logout.do">로그아웃</a>  <br><br>
	
	<a href="<%=request.getContextPath() %>/DeleteMember.do">회원탈퇴</a> <br><br>
</c:if>

<!-- 세션이 없으면 -->
<%-- <c:if test="${empty sessionScope.id}"> --%>
<c:if test="${sessionScope.id == null}">
	<a href="<%=request.getContextPath() %>/MemberForm.do">회원가입</a> <br><br>
	<a href="<%=request.getContextPath() %>/LoginForm.do">로그인</a> <br><br>
</c:if>

- 가장 먼저 EL 의 ${sessionScope.id != null} 로 네임 "id" 로 세션에 설정된 id 값이 있는지 확인한다

+ 또는 ${not empty sessioNScope.id} 를 if 조건으로 써도 된다

- 세션 공유값이 있으면 ~님 환영합니다 화면이 드고, 세션 공유값이 없으면 회원가입, 로그인 메뉴만 띄움 

 

링크 설정, 요청 네임값

- '회원정보 수정' : "/UpdateMember.do"

- '로그아웃' : "/Logout.do"

- '회원탈퇴' : "/DeleteMember.do"

- '회원가입' : "/MemberForm.do"

- '로그인' : "/LoginForm.do"

 

- main.jsp 를 그냥 실행하면 세션값이 없기때문에 아래 화면이 나타남

- 로그인 후에 main.jsp 로 넘어오면 세션값이 있으므로 아래 화면이 나타남


JSP Model 2 - MyBatis 회원관리 프로그램 : 로그아웃 기능

코드와 흐름 같이 설명

- 메인 페이지 main.jsp 에서 '로그아웃'  클릭시 "/Logout.do" 로 요청함

- Controller 클래스로 찾아간다

 

- Controller 클래스에서 "/Logout.do" 부분만

		// 로그 아웃	
		}else if(command.equals("/Logout.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/member/logout.jsp");
		}

- DB연동이 필요없으므로 Service 클래스로 가지 않음

- 바로 여기서 ActionForward 객체 foward 생성 후 포워딩 방식, 포워딩 페이지를 설정함

- logout.jsp 로 Dispatcher 방식으로 포워딩

 

- logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%	// 세션 삭제
	session.invalidate();
%>

<script>
	alert("로그아웃");
	location.href="./LoginForm.do";
</script>

logout.jsp 에서 해야할 일

1. 세션 삭제

2. 로그아웃 메세지 출력 후 다시 로그인 폼으로 돌아가기

- 로그인 폼으로 돌아가기 위한 요청인 "/LoginForm.do" 로 요청

 

- 그럼 다시 Controller 클래스에서 로그인 폼으로 포워딩 한다

 

로그아웃 시에는

- Controller 로 갔다가 Service 로 가지 않고 View로 바로 포워딩해서 세션을 끊고 다시 로그인 폼으로 가면 됨

 

- 로그아웃 시도

- '로그아웃' 눌렀을때 콘솔창

 


JSP Model 2 - MyBatis 회원관리 프로그램 : 수정폼 기능

코드와 흐름 같이 설명

+ 수정폼은 DB와 연동해서 상세정보를 구해와서 수정폼에 뿌려줘야함

- 메인 페이지 main.jsp 에서 '회원정보 수정'  클릭시 "/UpdateMember.do" 로 요청함

	<a href="<%=request.getContextPath() %>/UpdateMember.do">회원정보 수정</a>  <br><br>

- 이때 아무 값도 전달하지 않음, id 값은 로그인 성공 시 부터 공유설정되어있는 상태이다

- Controller 클래스로 찾아간다

 

- Controller 클래스에서 "/UpdateMember.do" 부분만

		// 회원정보 수정폼	
		}else if(command.equals("/UpdateMember.do")) {
			try {
				action = new UpdateMember();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}

- Controller 클래스에서 해당 Service 클래스로 보내줌

 

- Controller 클래스 포워딩 처리 부분

		// 포워딩 처리
		if(forward != null) {
			if(forward.isRedirect()) {		// redirect 방식으로 포워딩
				response.sendRedirect(forward.getPath());
			}else {							// dispatcher 방식으로 포워딩
				RequestDispatcher dispatcher = 
						request.getRequestDispatcher(forward.getPath());
				dispatcher.forward(request, response);
			}
		}

- Service 에서 돌아온 뒤 여기서 포워딩 처리됨

 

- 수정폼 Service 클래스인 UpdateMember.java 로 이동

package service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import dao.MemberDAO;
import model.MemberDTO;

public class UpdateMember implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("UpdateMember");
		
		HttpSession session = request.getSession();
		String id = (String)session.getAttribute("id");
		System.out.println("id:"+id);
		
		MemberDAO dao = MemberDAO.getInstance();
		MemberDTO member = dao.getMember(id);
		System.out.println("member:"+member);
		
		String hobby = member.getHobby();	// "공부-게임-등산-"
		String[] h = hobby.split("-");
		
		request.setAttribute("member", member);				
		request.setAttribute("h", h);				
		
		ActionForward forward = new ActionForward();	
		forward.setRedirect(false);        // dispatcher 방식으로 포워딩
		forward.setPath("/member/updateform.jsp");
		
		return forward;
	}

}

<DAO 갔다오기 전>

- session 객체를 생성 후 세션값인 id 를 가장 먼저 구해온다

- getAttribuate() 로 세션값을 구해올때는 Object 형으로 리턴하므로 "id" 네임값에 들어있는 값의 자료형인 String 형으로 다운캐스팅

- DAO 객체를 생성하고 DAO의 getMember() 메소드를 호출해서 1명에 대한 상세정보를 구해온다

- getMember() 의 매개변수로는 세션으로 구해온 id 값을 전달한다

<DAO 갔다온 후>

- DAO의 getMemger(id) 로 구해온 상세정보를 DTO 객체 member 가 받는다

- 그 객체 member 의 주솟값을 찍어봄 * 아래에 캡처

- 받아온 객체 member 를 request 객체로 공유설정해야 View 페이지에서 공유값을 받아서 뿌릴 수 있다

- 문자열들을 잘라서 String 배열 h 에 저장하고 따로 공유 설정

- DTO 객체 member 는 ${member.필드명} 형태로 View 에서 출력, 배열 h 는 forEach 태그의 items 로 들어가서 View 에서 출력

- 메소드 execute() 에서도 DAO 로부터 넘어온 예외를 다시 던짐, 메소드를 호출한 Controller 클래스에서 예외를 처리한다

- ActionForward 객체 forward 생성 후 updateform.jsp 로 Dispatcher 방식으로 포워딩 할 것임을 설정

 

- MemberDAO.java 에서 getMember() 메소드 부분만

	// 회원 1명 정보 구하기 : 수정폼, 수정, 삭제
	public MemberDTO getMember(String id) throws Exception{
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		
		return member;
	}

- 수정폼뿐 아니라 수정, 삭제시에 비번을 꺼낼때도 사용됨

- 검색되는 데이터가 1개이므로 selectOne() 메소드를 사용하고 id 가 "idcheck" 인 태그의 SQL문 호출, 사용자의 id 를 전달

- 예외를 던지므로서 메소드를 호출한 곳(Service 클래스쪽) 에 양도함

+ Service 클래스의 메소드에서도 예외를 던짐, 메소드를 호출한 Controller 클래스에서 예외를 처리한다

 

- member.xml 에서 로그인(회원 인증) 처리하는 SQL문 부분 (id 가 idcheck)

	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>

- 전달되는 값은 id 이므로 parameterType 을 String 으로 하고, 검색한 결과를 돌려줄때는 DTO 객체로 돌려주므로 resultType 은 member 로 한다

+ parameterType 속성값인 "member"는 MyBatis 환경설정 파일에서 Alias 값으로 지정한 별칭이다

- #{id} : selectOne() 을 호출할떄 두번째 매개변수로 넘어온 값으로 변수 id 가 넘어왔으므로 #{id} 로 그 값을 가져옴

- 검색결과를 setter 메소드로 DTO 객체에 저장시킬필요 없이 자동으로 매핑되어 DTO 객체에 저장되서 리턴된다

 

- 다음은 View 부분인 updateform.jsp 를 보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 수정 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
//				document.getElementById('join_zip2').value = data.postcode2;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>


<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="<%=request.getContextPath() %>/member/member.js"></script>

</head>
<body>

<form method="post" action="<%=request.getContextPath() %>/Update.do"> 
<input type="hidden" name="id" value="${member.id}">
<table border=1 width=500 align=center>
	<caption>회원 수정</caption>
	<tr><td>ID</td>
		<td>${member.id}</td>
	</tr>
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd"></td>
	</tr>
	<tr><td>성명</td>
		<td><input type=text id="name" name="name" value="${member.name}"></td>
	</tr>
	<tr><td>주민번호</td>
		<td><input type=text size=6 maxlength=6 id="jumin1" name="jumin1" value="${member.jumin1}">-
			<input type=text size=7 maxlength=7 id="jumin2" name="jumin2" value="${member.jumin2}">
		</td>
	</tr>
	<tr><td>E-Mail</td>
		<td><input type=text size=10 id="mailid" name="mailid" value="${member.mailid}">@
		    <input type=text size=10 id="domain" name="domain" value="${member.domain}">
		    <select id="email">
		    	<option value="">직접입력</option>
		    	<option value="naver.com">네이버</option>
		    	<option value="daum.net">다음</option>
		    	<option value="nate.com">네이트</option>
		    	<option value="gmail.com">gmail</option>
		    </select>		    
		 </td>
	</tr>
	<tr><td>전화번호</td>
		<td><input type=text size=4 id="tel1" name="tel1" maxlength=4 value="${member.tel1 }">-
			<input type=text size=4 id="tel2" name="tel2" maxlength=4 value="${member.tel2 }">-
			<input type=text size=4 id="tel3" name="tel3" maxlength=4 value="${member.tel3 }">
		</td>
	</tr>
	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010" <c:if test="${member.phone1 == '010' }">${'selected'}</c:if> >010</option>
				<option value="011" <c:if test="${member.phone1 == '011' }">${'selected'}</c:if> >011</option>
				<option value="016" <c:if test="${member.phone1 == '016' }">${'selected'}</c:if> >016</option>
				<option value="018" <c:if test="${member.phone1 == '018' }">${'selected'}</c:if> >018</option>
				<option value="019" <c:if test="${member.phone1 == '019' }">${'selected'}</c:if> >019</option>
			</select>-
			<input type=text size=4 id="phone2" name="phone2" maxlength=4 value="${member.phone2 }">-
			<input type=text size=4 id="phone3" name="phone3" maxlength=4 value="${member.phone3 }">
		</td>
	</tr>
	<tr><td>우편번호</td>
		<td><input type=text size=5 id="post" name="post" value="${member.post }">
			<input type=button value="우편번호검색" 
			       onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><td>주소</td>
		<td><input type=text size=45 id="address" name="address" value="${member.address }"></td>
	</tr>
	<tr><td>성별</td>
		<td>
		
		<c:if test="${member.gender == '남자' }">
			<input type=radio id="male" name="gender" value="남자" checked="checked">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</c:if>
		<c:if test="${member.gender == '여자' }">
			<input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자" checked="checked">여자
		</c:if>			
			
		</td>
	</tr>
	<tr><td>취미</td>
		<td>
			<input type="checkbox" id="h1" name="hobby" value="공부"
		<c:forEach var="i" items="${h}">
			<c:if test="${i=='공부'}">${'checked'}</c:if>
		</c:forEach> >공부
		
			<input type="checkbox" id="h2" name="hobby" value="게임"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='게임'}">${'checked'}</c:if>
		</c:forEach> >게임
			
			<input type="checkbox" id="h3" name="hobby" value="등산"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='등산'}">${'checked'}</c:if>
		</c:forEach> >등산
			
			<input type="checkbox" id="h4" name="hobby" value="낚시"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='낚시'}">${'checked'}</c:if>
		</c:forEach> >낚시
			
			<input type="checkbox" id="h5" name="hobby" value="쇼핑"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='쇼핑'}">${'checked'}</c:if>
		</c:forEach> >쇼핑
			
		</td>
	</tr>	
	<tr><td>자기소개</td>
		<td>
			<textarea id="intro" name="intro" rows="5" cols="50" placeholder="자기소개를 100자 이내로 입력하세요">${member.intro }</textarea>
		</td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원수정">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>


</body>
</html>

- 공유설정된 값을 받아서 수정폼에 뿌려준다

- 공유된 객체 member 안의 필드값들은 ${member.필드명} 으로 가져온다 (updateform.jsp 부분)

	<tr><td>성명</td>
		<td><input type=text id="name" name="name" value="${member.name}"></td>
	</tr>

- 공유된 배열 h 는 forEach 태그의 items 안에 "${h}" 가 들어감 (updateform.jsp 부분)

			<input type="checkbox" id="h1" name="hobby" value="공부"
		<c:forEach var="i" items="${h}">
			<c:if test="${i=='공부'}">${'checked'}</c:if>
		</c:forEach> >공부

- id 값은 수정폼에서 입력양식이 아닌 출력만 하고 있으므로 따로 hidden 객체로 id 값을 넘겨줌 

+ 세션이 있지만 바로 전달하는게 좋다

- 수정폼에서 입력 후 '회원수정' 을 누르면 action 값으로 지정된 "/Update.do" 로 요청

 

- 메인 페이지 main.jsp 에서 '회원정보 수정' 을 눌러 수정폼 으로 들어가보자

- 상세정보를 구해와서 값들을 수정폼에 잘 뿌리고 있다

 

- '회원정보 수정' 을 눌렀을때 콘솔창

- DAO 에서 검색해서 돌려받은 객체 member 가 출력됨 (데이터가 저장된 곳의 주소)


수정폼에서 처리하기 힘든 부분 (updateform.jsp 부분)

- jQuery 를 쓰지 않으면 처리하기 힘든 부분들이다

- 수정폼에서 처기하기 힘든 부분들을 jQuery 를 쓰지 않고 어떻게 처리했는지 보자

 

1. 핸드폰 첫번째 자리

	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010" <c:if test="${member.phone1 == '010' }">${'selected'}</c:if> >010</option>
				<option value="011" <c:if test="${member.phone1 == '011' }">${'selected'}</c:if> >011</option>
				<option value="016" <c:if test="${member.phone1 == '016' }">${'selected'}</c:if> >016</option>
				<option value="018" <c:if test="${member.phone1 == '018' }">${'selected'}</c:if> >018</option>
				<option value="019" <c:if test="${member.phone1 == '019' }">${'selected'}</c:if> >019</option>
			</select>-
			<input type=text size=4 id="phone2" name="phone2" maxlength=4 value="${member.phone2 }">-
			<input type=text size=4 id="phone3" name="phone3" maxlength=4 value="${member.phone3 }">
		</td>
	</tr>

- option 태그 안에 JSTL if 태그를 넣어서 특정 숫자일때 ${'selected'} 를 출력해서 선택되게 만듬

 

2. 성별 라디오 버튼

	<tr><td>성별</td>
		<td>
		
		<c:if test="${member.gender == '남자' }">
			<input type=radio id="male" name="gender" value="남자" checked="checked">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</c:if>
		<c:if test="${member.gender == '여자' }">
			<input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자" checked="checked">여자
		</c:if>			
			
		</td>
	</tr>

- JSTL if 태그를 넣어서 member.gender 값이 '남자' 일때 남자 라디오버튼에 checked 를 만들어서 선택되게 함

- if 태그 안에 라디오 버튼 을 넣어서 조건문을 만족할때만 나타남

 

3. 취미 체크박스

	<tr><td>취미</td>
		<td>
			<input type="checkbox" id="h1" name="hobby" value="공부"
		<c:forEach var="i" items="${h}">
			<c:if test="${i=='공부'}">${'checked'}</c:if>
		</c:forEach> >공부
		
			<input type="checkbox" id="h2" name="hobby" value="게임"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='게임'}">${'checked'}</c:if>
		</c:forEach> >게임
			
			<input type="checkbox" id="h3" name="hobby" value="등산"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='등산'}">${'checked'}</c:if>
		</c:forEach> >등산
			
			<input type="checkbox" id="h4" name="hobby" value="낚시"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='낚시'}">${'checked'}</c:if>
		</c:forEach> >낚시
			
			<input type="checkbox" id="h5" name="hobby" value="쇼핑"
		<c:forEach var="i" items="${h}">	
			<c:if test="${i=='쇼핑'}">${'checked'}</c:if>
		</c:forEach> >쇼핑
			
		</td>
	</tr>

- input 태그 안에 JSTL forEach 태그를 넣어서 배열 h 에서 값을 하나씩 가져와서 차레로 변수 i 에 저장

- 변수 i 가 '공부' 이면 공부 체크박스에 ${'checked'} 로 체크가 되게 함 

ex) h[0] = "공부", h[1] = "게임"

- 모든 체크박스마다 forEach 태그를 써서 일일히 찾아야한다

 

- jQuery 를 쓰지 않고 핸드폰 첫번째자리, 성별 라디오버튼, 취미 체크박스에 값을 뿌렸다



JSP Model 2 - MyBatis 회원관리 프로그램 : 회원 정보 수정 기능

코드와 흐름 같이 설명

- updateform.jsp 에서 '회원수정' 버튼을 누르면 "/Update.do" 로 요청함

- Controller 클래스로 찾아간다

 

- Controller 클래스에서 "/Update.do" 부분만

		// 회원정보 수정	
		}else if(command.equals("/Update.do")) {
			try {
				action = new Update();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}

 

- 정보 수정 Service 클래스인 Update.java 로 이동

package service;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.MemberDAO;
import model.MemberDTO;

public class Update implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Update");
		
		response.setContentType("text/html; charset=utf-8");
		request.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		
		MemberDTO member = new MemberDTO();
		member.setId(request.getParameter("id"));
		member.setPasswd(request.getParameter("passwd"));
		member.setName(request.getParameter("name"));
		member.setJumin1(request.getParameter("jumin1"));
		member.setJumin2(request.getParameter("jumin2"));
		member.setMailid(request.getParameter("mailid"));
		member.setDomain(request.getParameter("domain"));
		member.setTel1(request.getParameter("tel1"));
		member.setTel2(request.getParameter("tel2"));
		member.setTel3(request.getParameter("tel3"));
		member.setPhone1(request.getParameter("phone1"));
		member.setPhone2(request.getParameter("phone2"));
		member.setPhone3(request.getParameter("phone3"));
		member.setPost(request.getParameter("post"));
		member.setAddress(request.getParameter("address"));
		member.setGender(request.getParameter("gender"));
		
		String h="";
		String[] h1 = request.getParameterValues("hobby");
		for(String h2 : h1) {
			h += h2+"-";			// h = "공부-게임-등산-"
		}
		member.setHobby(h);
		member.setIntro(request.getParameter("intro"));
		
		MemberDAO dao = MemberDAO.getInstance();
		MemberDTO old = dao.getMember(member.getId());
		
		// 비번 비교
		if(old.getPasswd().equals(member.getPasswd())) { //비번 일치시
			int result = dao.update(member);
			if(result==1) System.out.println("회원수정 성공");
			
		}else {											 //비번 불일치시
			out.println("<script>");
			out.println("alert('비번이 일치하지 않습니다.');");
			out.println("history.go(-1);");
			out.println("</script>");
			out.close();
			
			return null;
		}	
		
		ActionForward forward = new ActionForward();
		forward.setRedirect(false);
		forward.setPath("/member/main.jsp");
		
		return forward;
	}

}

- 수정폼에서 입력값들이 넘어오므로 한글 인코딩

- id 도 hidden 객체로 넘어왔고, 사용자가 입력한 비번도 넘어왔다

- DTO 객체 member 를 생성해서 setter 메소드로 id 와 사용자가 수정폼에 입력한 값들을 member 에 저장

- DAO 의 메소드를 2번 호출해야함, 비번 확인을 위해 상세정보 가져올때 1번, 수정할때 1번

- DAO 객체 생성 후 DB에 저장된 비번을 가져오기 위해 DAO 의 getMember() 메소드를 호출하면서 수정폼에서 넘겨준 id 를 매개변수로 넘겨준다

<DAO getMember() 에서 돌아온 후>

- old.getPasswd() 는 DB에 저장된 비번, member.getPasswd() 는 사용자가 입력한 비번

- 두 비번이 일치시 수정 하는 메소드인 DAO의 update() 메소드 호출, 수정할 데이터를 저장한 DTO 객체 member 를 넘김

<DAO update() 에서 돌아온 후>

- 수정 성공시 1을 돌려주기로 했으므로, 1을 리턴받으면 "회원수정 성공" 메세지를 콘솔에 출력

- 비번 일치가 되면 수정 후 if-else 문 아래 문장인 ActionForward 객체 foward 생성 후, main.jsp 로 Dispatcher 방식 으로 포워딩 페이지, 방식 지정

- 성공시 Controller 클래스로 가서 main.jsp 로 포워딩하면 아직 세션이 남아있으므로 세션이 있을때의 화면이 뜬다

- 비번이 일치하지 않으면 메세지를 출력한 후 다시 이전페이지인 수정폼으로 돌아간다

 

- MemberDAO.java 에서 getMember() 메소드 부분만

	// 회원 1명 정보 구하기 : 수정폼, 수정, 삭제
	public MemberDTO getMember(String id) throws Exception{
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		
		return member;
	}

- 1명에 대한 상세정보를 구하므로 selectOne() 메소드, id 값이 "idcheck" 인 Mapper 파일의 SQL문 호출

- 사용자가 입력한 id 값을 매개변수로 넘겨준다

- 돌려받은 객체 member 를 Service 클래스로 리턴

 

- member.xml 에서 수정 처리하는 SQL문 부분 (id 가 idcheck)

	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>

- DTO 객체에 상세정보가 자동으로 저장(매핑) 되어 돌려준다

 

- MemberDAO.java 에서 update() 메소드 부분만

	// 회원정보 수정
	public int update(MemberDTO member) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		result = session.update("update", member);

		return result;
	}

- SqlSession 객체를 변수 session 으로 받아오고 update SQL문을 부를 것이므로 session.update() 메소드를 호출

- Mapper 파일에서 id 가 "update" 인 태그의 SQL문 호출, 호출하며 수정할 데이터를 저장한 객체 member 를 넘김

- session.update() 가 잘 실행되면 1 을 리턴하고, 그걸 result 변수로 받아서 다시 Service 클래스로 돌려줌

 

- member.xml 에서 수정 처리하는 SQL문 부분 (id 가 update)

	<!-- 회원정보 수정 -->
	<update id="update" parameterType="member">
	  update member0609 set name=#{name}, jumin1=#{jumin1}, jumin2=#{jumin2}, 
	  mailid=#{mailid}, domain=#{domain}, tel1=#{tel1}, tel2=#{tel2}, tel3=#{tel3},
	  phone1=#{phone1}, phone2=#{phone2}, phone3=#{phone3}, post=#{post}, address=#{address},
	  gender=#{gender}, hobby=#{hobby}, intro=#{intro} where id = #{id}
	</update>

- DTO 객체 member 가 넘어왔으므로 parameterType 은 전달되는 값의 자료형인 DTO alias 값 member 를 작성

- DTO 객체가 전달될때 DTO 객체 안의 내용을 가져오는 방법 : #{} 안에 DTO 객체의 필드명을 쓴다

ex) #{name} 은 member.getName() 과 같은 의미, #{jumin1} 은 member.getJumin1() 과 같은 의미

- 수정된 데이터 개수를 자동으로 돌려준다, 성공시 1 반환


JSP Model 2 - MyBatis 회원관리 프로그램 : 회원 탈퇴 기능

코드와 흐름 같이 설명

- 탈퇴 폼 + 탈퇴 기능 한번에 설명

- DB 연동이 필요하지 않으므로 main.jsp 에서 '회원탈퇴' 클릭시 Controller 클래스로 가서 바로 View 탈퇴 폼으로 가기

	<a href="<%=request.getContextPath() %>/DeleteMember.do">회원탈퇴</a> <br><br>

- 회원 탈퇴 폼으로 가기 위해 "/DeleteMember.do" 로 요청함

- Controller 클래스로 넘어감

 

- Controller 클래스에서 "/DeleteMember.do" 부분만

		// 회원탈퇴 폼	
		}else if(command.equals("/DeleteMember.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/member/deleteform.jsp");
		}

- DB연동이 필요하지 않으므로 Service 클래스가 아닌 View 페이지로 바로 이동

- 여기서 ActionForward 객체 forward 생성 후 포워딩 페이지, 방식 지정

- 탈퇴 폼 View 페이지인 deleteform.jsp 로 간다

 

- deleteform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 탈퇴</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="<%=request.getContextPath() %>/member/member.js"></script>

</head>
<body>

<form method="post" action="<%=request.getContextPath() %>/Delete.do"> 
<input type="hidden" name="id" value="${sessionScope.id}">
<table border=1 width=500 align=center>
	<caption>회원 탈퇴</caption>	
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd"></td>
	</tr>	
	<tr><td colspan=2 align=center>
			<input type=submit value="회원탈퇴">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>


</body>
</html>

- 아직 SESSION 영역이므로 공유설정된 세션값인 id 가 남아있다, 

- 세션 값을 ${sessionScope.id} 로 가져와서 hidden 객체를 통해 "id" 변수에 저장해서 세션 값을 "/Delete.do" 로 넘긴다

+ hidden 으로 id 값을 "/Delete.do" 로 넘기지 않아도 Delete.java 에서 공유된 세션에서 id 값을 가져와도 된다

+ 하지만 session 객체도 만들어아하고 번거로우므로 그냥 hidden 으로 비밀번호와 함께 form 으로 같이 넘기는 것

- 탈퇴를 위해선 탈퇴폼에 사용자가 비밀번호를 입력해야함

- 해당하는 회원 1명의 정보를 구하기 위해 id 값을 꼭 넘겨야함

- hidden 으로 넘어가는 id 와 입력양식으로 넘어가는 비밀번호 passwd 가 "/Delete.do" 로 요청하며 post 방식으로 넘어감

 

- Controller 클래스에서 "/Delete.do" 부분만

		// 회원탈퇴	
		}else if(command.equals("/Delete.do")) {
			try {
				action = new Delete();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}

 

- 회원 탈퇴 Service 클래스인 Delete.java 로 이동

package service;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import dao.MemberDAO;
import model.MemberDTO;

public class Delete implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Delete");
		
		response.setContentType("text/html; charset=utf-8");
		request.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		
		MemberDAO dao = MemberDAO.getInstance();
		MemberDTO old = dao.getMember(id);
		
		// 비번 비교
		if(old.getPasswd().equals(passwd)) {	// 비번 일치시
			int result = dao.delete(id);
			if(result == 1) System.out.println("회원삭제 성공");
			
			session.invalidate();               // 세션 삭제
			
		}else {									// 비번 불일치시
			out.println("<script>");	
			out.println("alert('비번이 일치하지 않습니다.');");	
			out.println("history.go(-1);");	
			out.println("</script>");	
			out.close();
			
			return null;			
		}
		
		ActionForward forward = new ActionForward();
		forward.setRedirect(false);
		forward.setPath("/LoginForm.do");
		
		return forward;
	}

}

- 회원 삭제(탈퇴) 성공시에 필요한 session 객체, out 객체 생성

- hidden 으로 넘어온 id 값과, 입력양식에서 넘어온 비번 passwd 를 getParameter() 로 받아서 변수 id, passwd 에 저장

- 비번 비교를 위해 DAO의 getMember() 메소드를 호출해서 해당 id 의 회원에 대한 상세정보를 가져온다

- DAO 에서 메소드 호출을 2번 해야한다, 비번을 가져오기 위해 상세정보 가져올때 1번, 회원 삭제할때 1번

<DAO getMember() 에서 돌아온 후>

- old.getPasswd() 는 DB의 비번, passwd 는 사용자가 탈퇴폼에 입력한 비번, 두 비번 일치시 DAO 의 delete() 메소드 호출

- delete() 를 호출하며 id 값을 매개변수로 전달

<DAO update() 에서 돌아온 후>

- 1 을 리턴받으면 성공이라 여기고, "회원삭제 성공" 메세지 출력하고 세션을 삭제한다, SESSION 영역 끝

- 삭제에 성공하면 if-else 문 아래에서 forward 객체를 생성하고 "/LoginForm.do" 로 포워딩 페이지 설정, Dispatcher 방식으로 포워딩 방식 설정

-  삭제에 실패하면 메세지를 출력하고 이전 페이지인 삭제폼으로 이동, return null; 을 추가해서 execute() 를 빠져나가며 아래의 코드를 forward 설정 코드를 실행하지 않도록 함

- 이전 페이지인 삭제폼으로 이동하는데 아래의 forward 설정 코드를 실행하면 오류가 난다. 한번에 두 곳으로 갈 수 없으므로


- MemberDAO.java 에서 getMember() 메소드 부분만

	// 회원 1명 정보 구하기 : 수정폼, 수정, 삭제
	public MemberDTO getMember(String id) throws Exception{
		SqlSession session = getSession();
		MemberDTO member = session.selectOne("idcheck", id);
		
		return member;
	}

- member.xml 에서 수정 처리하는 SQL문 부분 (id 가 idcheck)

	<!-- ID중복검사, 회원인증 -->
	<select id="idcheck" parameterType="String" resultType="member">
	 select * from member0609 where id = #{id}
	</select>

- MemberDAO.java 에서 delete() 메소드 부분만

	// 회원 탈퇴
	public int delete(String id) throws Exception{
		int result = 0;
		SqlSession session = getSession();
		result = session.delete("delete", id);		
		
		return result;
	}

- delete SQL문을 사용하므로 SqlSession 객체의 메소드 delete() 를 사용해야한다

- Mapper 파일에서 id 가 "delete' 인 SQL문을 호출, 매개변수로는 삭제하고자 하는 회원의 id 값을 넘김

- session.delete() 에서 삭제 성공시 리턴하는 1을 result 변수에 저장 후 다시 Service 클래스로 1 리턴

 

- member.xml 에서 수정 처리하는 SQL문 부분 (id 가 delete)

	<!-- 회원 삭제 -->
	<delete id="delete" parameterType="String">
	  delete from member0609 where id = #{id}
	</delete>

- 삭제하고자 하는 회원의 id 값이 넘어오므로 parameterType 은 String 이어야한다

- #{id} : session.delete() 에서 두번째 매개변수로 넘어온 변수 id 의 값을 ${id} 로 가져옴

- 자동으로 삭제된 데이터 개수를 리턴해줌 (성공시 1 리턴)

 

- main.jsp 에서 '회원탈퇴' 클릭시 콘솔창 (탈퇴 폼)

 

- 탈퇴 폼에서 맞는 비밀번호를 입력하고 '회원탈퇴' 클릭시

- 탈퇴에 성공하고 로그인 폼으로 포워딩됨

- 탈퇴 폼에서 '회원탈퇴' 클릭해서 회원탈퇴에 성공 했을때 콘솔 창


JSP Model 2 - MyBatis 연동 구조



JSP Model 2 - MyBatis 연동 : 게시판 프로그램

Model 2 과 MyBatis 연동

- 클라우드에서 Model 2 과 MyBatis 가 이미 연동이 완료된 게시판 로그램 mybatisboard 프로젝트 import

- zip 파일을 압축 풀어서 import

- import 하는 프로젝트는 maven 프로젝트이다

- Maven 프로젝트이므로 구조는 다음과 같다

- src/main/java 안에 확장자가 java 인 파일들이 저장되어있다 (Controller, Service, DAO, DTO)

+ Model 2 이므로 src/main/java 안에서도 DTO, DAO, Service, Controller 가 서로 다른 패키지 안에 들어가있음

- src/main/resources 안에 DB 연동에 필요한 MyBatis 환경설정 파일 등이 들어가 있다 (주로 xml 파일들)

- src/main/webapp 안에 View 파일 등이 들어간다

- Maven 프로젝트는 WEB-INF 폴더 안에 lib 폴더가 생성되지 않는다, 대신 pom.xml 에서 라이브러리 추가함

- boardupload 는 첨부파일이 저장될 폴더이다

 

- import한 mybatismember 프로젝트의 pom.xml 파일을 보자

- pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.myhome</groupId>
	<artifactId>mybatisboard</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>ibatisboard Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<!-- 복사 시작 -->
	<repositories>
		<repository>
			<id>codelds</id>
			<url>https://code.lds.org/nexus/content/groups/main-repo</url>
		</repository>
	</repositories>

	<dependencies>

		<!-- 오라클 JDBC Library -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>

		<!-- iBatis -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.3</version>
		</dependency>

		<!-- jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- cos -->
		<dependency>
			<groupId>servlets.com</groupId>
			<artifactId>cos</artifactId>
			<version>05Nov2002</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>mybatisboard</finalName>
	</build>
</project>

- 프로젝트 시작 시 가장 먼저 라이브러리를 구하는 작업을 해야한다

- dependencies 태그 안에 의존 라이브러리를 dependency 태그로 추가

- 오라클 JDBC, MySQL JDBC, iBatis, MyBatis 3.5.3 ver, JSTL, cos 라이브러리가 추가되었다

- 오라클 공식 저장소에서 다운받는 건 오류 많이 발생

- 오라클은 비공식 저장소 repository 를 원격 저장소 위치로 등록하고 거기서 오라클 JDBC 라이브러리를 불러오기

- MyBatis 연동시에는 반드시 MyBatis 라이브러리가 추가되어 있어야함

 

- db.properties

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=totoro
jdbc.password=totoro123

- DB 접속에 대한 내용들이 들어가 있다

- 테이블을 생성할때 totoro 계정에서 생성해야 한다


- 테이블을 만들자

- db.properties 파일에서 totoro 계정으로 설정되어있으므로 totoro 계정에서 테이블을 생성해야함

+ import 시에 테이블이 생성되지는 않음

- sql 폴더의 model2.sql 에서 totoro 계정으로 연결한 후 model22테이블을 생성하자

- 커넥션 프로파일 설정

- model2.sql

-- 모델2 게시판
select * from tab;
select * from seq;
select * from model22;

create table model22(
	board_num number,
	board_name varchar2(20),
	board_pass varchar2(15),
	board_subject varchar2(50),
	board_content varchar2(2000),
	board_file varchar2(50),
	board_re_ref number,
	board_re_lev number,
	board_re_seq number,
	board_readcount number,
	board_date timestamp,
	primary key(board_num)
);

create sequence model22_seq
start with 1
increment by 1
nocache;

- 테이블 model22 와 시퀀스 model22_seq 를 생성

- board_num 이 primary key 가 되고, board_num 에는 시퀀스 model22_seq 값이 들어갈 것

 

컬럼 설명

- board_re_ref : 원문은 시퀀스, 댓글은 부모의 ref 값과 동일값

- board_re_lev : 원문은 0, 1단계 댓글은 1, 2단계 댓글은 2

- board_re_seq : 원문은 0, 댓글, 대댓글의 board_re_seq 는 계속 바뀌는 값


JSP Model 2 - MyBatis 게시판 프로그램 : 기본 파일들

 

흐름 보기

- index.jsp

<%@ 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>
<body>

 모델2 게시판
 
<%
	response.sendRedirect("./BoardListAction.do");
%> 

<script>
//	location.href="./BoardListAction.do";
</script>

</body>
</html>

- index.jsp 실행이나 현재 프로젝트 Run As - Run on Server 로 실행시키자

- 목록을 요청하는 "/BoardListAction.do" 로 요청하고 있다, 목록을 요청하고 목록을 출력하는 페이지까지 온다

- 그래서 목록 페이지가 보인다

 

- '글쓰기' 를 눌러서 글 작성 폼으로 가서 게시판에 글을 작성해보자

- 글을 '등록' 하면 아래처럼 목록을 다시 가져와서 목록 페이지로 돌아간다

- 글 작성 성공시 콘솔창

path:C:\Users\admin\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\mybatisboard\boardupload

- 첨부파일도 성공적으로 서버에 업로드 되었음을 확인 가능

 

- 글을 클릭하면 상세 페이지로 넘어가면서 조회수를 1 증가시킴

- 댓글을 달아보자

- 글 삭제하기


- DTO 인 BoardBean.java 파일을 보자

- MyBatis 로 자동 매핑이 가능하도록 테이블의 컬럼명과 DTO 의 프로퍼티명을 일치시켰다

package model;

import java.sql.Timestamp;

public class BoardBean {
	private int board_num;
	private String board_name;
	private String board_pass;
	private String board_subject;
	private String board_content;
	private String board_file;
	private int board_re_ref;
	private int board_re_lev;
	private int board_re_seq;
	private int board_readcount;
	private Timestamp board_date;	
	
	public int getBoard_num() {
		return board_num;
	}
	public void setBoard_num(int board_num) {
		this.board_num = board_num;
	}
	public String getBoard_name() {
		return board_name;
	}
	public void setBoard_name(String board_name) {
		this.board_name = board_name;
	}
	public String getBoard_pass() {
		return board_pass;
	}
	public void setBoard_pass(String board_pass) {
		this.board_pass = board_pass;
	}
	public String getBoard_subject() {
		return board_subject;
	}
	public void setBoard_subject(String board_subject) {
		this.board_subject = board_subject;
	}
	public String getBoard_content() {
		return board_content;
	}
	public void setBoard_content(String board_content) {
		this.board_content = board_content;
	}
	public String getBoard_file() {
		return board_file;
	}
	public void setBoard_file(String board_file) {
		this.board_file = board_file;
	}
	public int getBoard_re_ref() {
		return board_re_ref;
	}
	public void setBoard_re_ref(int board_re_ref) {
		this.board_re_ref = board_re_ref;
	}
	public int getBoard_re_lev() {
		return board_re_lev;
	}
	public void setBoard_re_lev(int board_re_lev) {
		this.board_re_lev = board_re_lev;
	}
	public int getBoard_re_seq() {
		return board_re_seq;
	}
	public void setBoard_re_seq(int board_re_seq) {
		this.board_re_seq = board_re_seq;
	}
	public int getBoard_readcount() {
		return board_readcount;
	}
	public void setBoard_readcount(int board_readcount) {
		this.board_readcount = board_readcount;
	}
	public Timestamp getBoard_date() {
		return board_date;
	}
	public void setBoard_date(Timestamp board_date) {
		this.board_date = board_date;
	}
}

- 테이블의 컬럼명과 DTO 의 프로퍼티명을 일치시켜야 자동 매핑이 가능하다


- Controller 클래스 BoardFrontController.java 를 보자

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.Action;
import service.ActionForward;
import service.BoardAddAction;
import service.BoardDelete;
import service.BoardDetailAction;
import service.BoardListAction;
import service.BoardModify;
import service.BoardModifyAction;
import service.BoardReply;

/**
 * Servlet implementation class BoardFrontController
 */
@WebServlet("*.do")
public class BoardFrontController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI:"+requestURI);
		System.out.println("contextPath:"+contextPath);
		System.out.println("command:"+command);
		
		Action action = null;
		ActionForward forward = null;
		
		// 글작성
		if(command.equals("/BoardAddAction.do")) {
			try {
				action = new BoardAddAction();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		
		// 글작성 폼	
		}else if(command.equals("/BoardForm.do")) {	
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/board/qna_board_write.jsp");
			
		// 글목록	
		}else if(command.equals("/BoardListAction.do")) {
			try {
				action = new BoardListAction();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 상세 페이지	
		}else if(command.equals("/BoardDetailAction.do")) {
			try {
				action = new BoardDetailAction();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 댓글 폼	
		}else if(command.equals("/BoardReplyAction.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/board/qna_board_reply.jsp");
			
		// 댓글	
		}else if(command.equals("/BoardReply.do")) {
			try {
				action = new BoardReply();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 수정 폼	
		}else if(command.equals("/BoardModifyAction.do")) {
			try {
				action = new BoardModifyAction();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 수정	
		}else if(command.equals("/BoardModify.do")) {
			try {
				action = new BoardModify();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		// 삭제 폼	
		}else if(command.equals("/BoardDeleteAction.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("/board/qna_board_delete.jsp");
			
		// 삭제	
		}else if(command.equals("/BoardDelete.do")) {
			try {
				action = new BoardDelete();
				forward = action.execute(request, response);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
		
		if(forward != null) {
			if(forward.isRedirect()) {	 // redirect 방식으로 포워딩
				response.sendRedirect(forward.getPath());
				
			}else {						// dispatcher 방식으로 포워딩
				RequestDispatcher dispatcher = 
						request.getRequestDispatcher(forward.getPath());
				dispatcher.forward(request, response);
			}			
		}		
		
	} // doProcess() end
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		response.getWriter().append("Served at: ").append(request.getContextPath());
		System.out.println("get");		
	
		doProcess(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		doGet(request, response);
		System.out.println("post");
		
		doProcess(request, response);
	}

}

- command 변수에 저장된 값에 따라 다른 Service 클래스로 이동 또는 View로 포워딩

 

+ 인터페이스 Action.java

- Service 클래스들이 인터페이스를 상속함으로서 안의 추상메소드를 반드시 메소드 오버라이딩 해야함 

- 구현클래스가 여러개 있을때 이 구현 클래스들을 통일성있게 설계하기 위해 인터페이스 상속

 

+ 클래스 ActionForward.java

- 어느 페이지로 포워딩할지, 어떤 방식으로 포워딩할지 설정하는 클래스

 

- DAO 클래스인 BoardDAO.java 를 보자

- BoardDAO.java

package dao;

import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import model.BoardBean;

public class BoardDAO {

	private static BoardDAO instance = new BoardDAO();

	public static BoardDAO getInstance() {
		return instance;
	}
		
	public SqlSession getSession() {
		SqlSession session=null;
		Reader reader=null;			
		try {
			reader = Resources.getResourceAsReader("mybatis-config.xml");
			SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(reader);
			session = sf.openSession(true);	 // auto commit	
		}catch(Exception e) {
			e.printStackTrace();
		}		
		return session;
	}
	
	
	//글작성(원문작성)
	public int insert(BoardBean board) throws Exception {
		int result=0;
		SqlSession session = getSession();
		result = session.insert("board_insert", board);		
		System.out.println("result:"+result);
		
		return result;
	}
	
	
	// 총데이터 갯수 구하기
	public int getCount() throws Exception{
		int result=0;
		SqlSession session=getSession();
		result = (Integer)session.selectOne("board_count");
		
		return result;
	}
	
	
	// 데이터 목록
	public List getList(int page) throws Exception {
//	public List getList(Map map) throws Exception {
		List list = new ArrayList();
		SqlSession session=getSession();
		list = session.selectList("board_list", page); 
		
		return list;
	}
	
	
	// 조회수 증가
	public void updateCount(int board_num) throws Exception{
		SqlSession session = getSession();
		session.update("board_updatecount", board_num);
	}
		
	
	// 댓글 출력 순서 (board_re_seq값 증가)
	public void updateSeq(BoardBean board) {
		SqlSession session = getSession();
		session.update("board_updateseq", board);
	}
		

	// 댓글작성
	public void boardReply(BoardBean board) {
		SqlSession session = getSession();
		session.insert("board_reply", board);
	}
	
	
	// 상세 페이지, 수정 폼
	public BoardBean getContent(int board_num) throws Exception {
		BoardBean board = new BoardBean();

		SqlSession session=getSession();
		board  = (BoardBean)session.selectOne("board_content", board_num);
		
		return board;
	}
	
	
	// 글수정
	public void update(BoardBean board) throws Exception {
		SqlSession session=getSession();
		session.update("board_update", board);
	}

	
	// 글삭제
	public void delete(int board_num) {
		SqlSession session=getSession();
		session.delete("board_delete", board_num);
	}

}

- DB와 연동하기 위한 여러 메소드들만으로 구성되어있다

- getSession() 메소드는 SqlSession 객체를 구해오는 메소드이고, 이 객체가 있어야 지원되는 5개 메소드 사용 가능

 

- MyBatis 환경설정 파일

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="model.BoardBean" alias="board"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="board.xml" />
	</mappers>
</configuration>

1) DTO 인 BoardBean 클래스의 alias (별칭)를 "board" 로 설정함

2) db.properties 파일의 변수들을 불러와서 DB 와 관련된 내용들을 작성함

- property 태그의 name 은 정해져있다, "driver", "url", "username", "password" 는 바뀌지 않음

3) Mapper 파일 board.xml 을 mapper 태그로 불러오고 있다

- Mapper 파일은 테이블 개수에 비례한다

- board.xml 에 따로 패키지가 없다, 즉 같은 폴더 하위에 있으므로 패키지명을 써주지 않고 board.xml 만 쓴다

 

- Mapper 파일 board.xml 을 보자

- board.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="myboard">

	<!-- 글작성(원문) -->
	<insert id="board_insert" parameterType="board">
	 insert into model22 values(model22_seq.nextval,#{board_name},
	 #{board_pass},#{board_subject},#{board_content},
	 #{board_file,jdbcType=VARCHAR},model22_seq.nextval,0,0,0,sysdate)
	</insert>
	
	<!-- 글갯수 -->
	<select id="board_count" resultType="int">
	 select count(*) from model22
	</select>
	
	<!-- 글목록 -->
	<!-- page 전달-->
	<select id="board_list" parameterType="int" resultType="board">
	 select * from (select rownum rnum, board.* from (
	  select * from model22 order by board_re_ref desc,board_re_seq asc) board )
	  where rnum &gt;= (#{page}-1) * 10 + 1   and rnum &lt;= #{page}*10
	</select> 
	
	<!-- Map 전달 -->
	<!-- <select id="board_list" parameterType="Map" resultType="board">
	 select * from (select rownum rnum, board.* from (
	  select * from model22 order by board_re_ref desc,board_re_seq asc) board )
	  where rnum &gt;= #{start} and rnum &lt;= #{end}
	</select> -->
	
	<!-- 조회수 증가 -->
	<update id="board_updatecount" parameterType="int">
     update model22 set board_readcount=board_readcount+1 where board_num = #{board_num}	
	</update>
	
	<!-- 상세페이지, 수정폼 -->
	<select id="board_content" parameterType="int" resultType="board">
	 select * from model22 where board_num = #{board_num}
	</select>
	
	<!-- 댓글 출력순서 -->
	<update id="board_updateseq" parameterType="board">
	 update model22 set board_re_seq=board_re_seq+1 
	  where board_re_ref = #{board_re_ref} and board_re_seq &gt; #{board_re_seq}
	</update>
	
	<!-- 댓글 작성 -->
	<insert id="board_reply" parameterType="board">
	 insert into model22 values(model22_seq.nextval,#{board_name},
	 #{board_pass},#{board_subject},#{board_content},
	 #{board_file,jdbcType=VARCHAR},#{board_re_ref},#{board_re_lev},#{board_re_seq},0,sysdate)
	</insert>

	<!-- 글수정 -->
	<update id="board_update" parameterType="board">
	 update model22 set board_name=#{board_name}, board_subject=#{board_subject},
	 board_content=#{board_content} where board_num=#{board_num}
	</update>

	<!-- 글삭제 -->
	<delete id="board_delete" parameterType="int">
	 delete from model22 where board_num=#{board_num}
	</delete>



	<!-- <select id="getSomething" parameterType="int" resultType="#package.#modelname">
		SELECT
		columnname1,
		columnname2,
		columnname3
		FROM tablename1
		WHERE columnname1 = #{value}
	</select>

	<resultMap type="#modelname" id="YourResultSet">
		<id property="param1" column="columnname1" />
		<result property="param2" column="columnname2" />
		<result property="param3" column="columnname3" />
	</resultMap>

	<select id="getAll" resultMap="YourResultSet">
		SELECT * FROM tablename1
	</select>

	<insert id="insertSomething" parameterType="#modelname">
		INSERT INTO tablename1 (columnname1, columnname2, columnname3)
		VALUES(#{value1},#{value2},#{value3})
	</insert>

	<update id="updateSomething" parameterType="#modelname">
		UPDATE tablename1
		SET
		columnname1=#{param1}
		WHERE
		columnname2 = #{param2}
	</update>

	<delete id="deleteSomething" parameterType="int">
		DELETE FROM tablename1 WHERE
		columnname1 = #{param1}
	</delete> -->

</mapper>

- MyBatis 환경설정 파일에서 이 Mapper 파일 board.xml 을 mapper 태그로 불러왔으므로 이 파일 board.xml 의 루트 엘리먼트는 mapper

 

글 목록 가져오기 주의 (board.xml 부분)

	<!-- 글목록 -->
	<!-- page 전달-->
	<select id="board_list" parameterType="int" resultType="board">
	 select * from (select rownum rnum, board.* from (
	  select * from model22 order by board_re_ref desc,board_re_seq asc) board )
	  where rnum &gt;= (#{page}-1) * 10 + 1   and rnum &lt;= #{page}*10
	</select>

- MyBatis 는 값이든 주소값이든 전달할 값을 단 1개만 전달 가능하므로 페이지번호 page 를 넘긴다

- 페이지번호 page 만 있으면 startRow 와 endRow 를 여기서 계산 할 수 있기 때문이다

 


JSP Model 2 - MyBatis 게시판 프로그램 : 글 작성 기능 

- 내일

+ Recent posts