WEB/✿JSP

[JSP] 🔗모델1 구조(3) 실습

W_W_Woody 2022. 1. 18. 00:57

m1_board Dynamic Web Project>

모델1 구조(2) 실습에서 추가되는 것은

페이징 처리 (작성된 유틸리티 클래스 이용)

rownum : 호출할 때 레코드에 번호를 매겨준다.

rownum을 사용할 때는 서브쿼리 형태로 명시한다.

rownum값 뿐만 아니라 원하는 데이터도 다 나와야한다.

뒤에있는 서브쿼리가 테이블역할을 한다. (SELECT * FROM SBOARD ORDER BY NUM DESC)

 

컬럼이 많아져서 SQL문장코드가 길어지면 일일이 명시하기 불편하므로 전체를 다 읽어오게 하려고 한다.

(rownum은 우리가 만든게 아니라 호출하면 oracle이 정보를 준다(의사열))

* 컬럼은 모든컬럼을 의미하기 때문에 rownum을 썼기 때문에 모든컬럼을 의미하지 못해서 에러가난다.

*만 쓰거나  rownum만쓰거나 해야 에러안난다.

 

서브쿼리를 지정을 한다. AS쓰는 방법이 가장 쉬운방법이다.

서브쿼리가 테이블 역할을 했고 그 뒤에 AS쓰면 테이블AS가 된다.

에러가 나지 않게 하기위해서 *이 AS를 가르키게 한다. /표기법은 AS명.* /뜻은 AS명 태그가 가지고있는 모든 컬럼을 의미

a태그(즉, 서브쿼리 SELECT * FROM SBOARD ORDER BY NUM DESC )가 가지고 있는 모든 컬럼

 

페이지 구역 나누기를 하기위해 WHERE을 이용해보자

첫번째 페이지가 된다.

 

두번째 페이지를 설정해본다면

똑같은 방법으로 했는데 아무것도 나오지않는다.

 

그 이유는

rownum이 우리가 만든 컬럼이 아니라 오라클에서 제공하는 컬럼인데

주 메인 쿼리에서 호출 시 두번째 호출이 안됀다. 결국 한번만 호출이 된다는 소리이다.

 

우리가 만든 퀄럼으로 정착을 시키려면 서브쿼리로 만들어 버리면 된다.

이 때 AS를 부여한다.

①서브쿼리가 먼저동작하고 ②rownum(AS rnum)을 통해서 번호를 쭉 매기고 ③where절로 구간을 지정한 것이다.

 

DAO의 ◎글 목록 메서드에서 이용이 된다.

 

 

src/main/java/kr.util(패키지)/PagingUtil.java

특별한 기능을 수행하는 유틸리티 클래스를 이용한다.

PagingUtil.java
0.00MB

이 유틸리티 클래스를 복사해쓴다.

 

생성자에 정보를 넘겨서 연산을 하게 만드는데

페이지 번호 부여하는 것을 만들어줘서 수작업 할 필요가 없다. 

페이지 번호

생성자에게 정보를 넘겨주는 것들은 다음과 같다.

 

보고싶은 페이지카운트 번호pageNum을 Key번호를  Value로 get방식으로 (list.jps에) 넘긴다.

list.jsp?pageNum=2

 


 

모델1

DTO/VO : 데이터 교환을 위한 객체

DAO : DB 접근을 위한 객체(db연동)

JSP : UI작업

 

다이나믹 웹 프로젝트를 새로 생성하고

JavaSE 버전을 맞춰준다.

ojdbc8.jar 파일을 WEB-INF/lib경로에 넣어준다. (데이터베이스 연동을 하려면 ojdbc8.jar가 꼭 필요!)

 * SQL문과 DB사이에 매개가 되는게 JDBC이다. 드라이버는 Java문법이 적용되서 만들어진 프로그램인데 ORACLE에서 배포하며 .jar 확장자로 압축된 형태이다. 그래서 jdbc드라이버가 꼭 있어야한다.

META-INF경로에 context.xml파일을 넣어준다.

CSS폴더도 공유하기위해 복사한다.

파일을 정리해서 생성하자.

 

src/main/webapp/sql/table.sql 

백업용 sql파일을 만들고, SQL Developer 에서 TABLE과 SEQUENCE를 생성한다.

CREATE TABLE SBOARD(
num number primary key,
title varchar2(150) not null,
name varchar2(30) not null,
passwd varchar2(12) not null,
content clob not null, --clob : 4기가까지 저장가능
ip varchar2(30) not null,
reg_date date not null
);

CREATE SEQUENCE SBOARD_SEQ;

- PRIMARY KEY  : UNIQUE제약조건, NOT NULL제약조건이 같이 들어간다.

- clob : 4기가까지 저장 가능하다.


src/main/java/kr.board.vo(패키지)/BoardVO.java

컬럼명과 일치하는 VO(자바빈)를 만든다.

 

VO역할을 하는 클래스이므로  (컬럼명과 일치시켜서) private한 프로퍼티(≒멤버변수) 를 만들고.

 

이 때 private Date reg_date; 변수는 데이터베이스에 연동하기 때문에

import java.util.Date; 를 사용하는 것이 아니라, import java.sql.Date; 를 사용한다.

 

gertters, settters를 만들어준다.

생성된 get메서드/set메서드 와 프로퍼티 사이에 필요한 메서드를 생성할 수 있다. 

 

로그인을 할 것이기 때문에 비밀번호를 체크하는 메서드를 만들어보자

//비밀번호 체크
public boolean isCheckedPassword(String userPasswd) {
    if(passwd.equals(userPasswd)) { //비밀번호 일치
        return true;
    }
    return false; //비밀번호 불일치
}

private String passwd;

 

if(passwd.equals(userPasswd))

DB에 있는 비밀번호

사용자가 입력한 비밀번호

--- m1_member와 동일한 방법 ---

▼ code

더보기
더보기
package kr.board.vo;

import java.sql.Date;

public class BoardVO {
	private int num; //글번호
	private String title; //제목
	private String name; //작성자
	private String passwd; //비밀번호
	private String email; //이메일
	private String content; //내용
	private String ip; //작성자 ip
	private Date reg_date; //작성일
	
	//비밀번호 일치여부를 체크
	public boolean isCheckedPassword(String userPasswd) {
		if(passwd.equals(userPasswd)) {
			return true;
		}
		return false;
	}
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getIp() {
		return ip;
	}
	public void setIp(String ip) {
		this.ip = ip;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}
	
}


목록이 대문페이지이지만

데이터가있어야 작업을 수행하므로 글쓰는 작업을 먼저하고 목록이 있는 부분에 링크만 건 후 데이터를 넣고 작업을 수행한다.

insert하려면 DAO가 있어야하므로 DAO에는 기본적인 것만 명시해보자.


src/main/java/kr.board.dao(패키지)/BoardDAO.java

전 실습 내용을 참고하자.   [JSP] 🔗모델1 구조(2) 실습

싱글톤 패턴을 만든다.

싱글톤패턴

외부에서 생성자를 호출할 수 없도록 막고  →  DAO 내부적으로만 객체가 생성되도록 만들고 → 외부에서도 사용 할 수있게 static한 메서드를 만든다.

//1. DAO객체를 생성하고

private static BoardDAO instance = new BoardDAO(); 

//3. 외부에서도 사용 할 수있게 static한 메서드를 만든다.

public static BoardDAO getInstance() { 

            return instance;     } 

//2. DAO 내부적으로만 객체가 생성되도록 만들고

private BoardDAO() {}; 

 

우리가 호출할 수 있는건 BoardDAO getInstance() 이다.

 

context.xml에서 설정 정보를 읽어들여 커넥션풀로부터 커넥션을 할당받는 메서드를 만든다.

이것 또한 외부에서 호출못하게private,  Context객체가 가지고있는 lookup메서드를 이용해서 찾는다.

private Connection getConnection() throws Exception{

            Context initCtx = new InitialContext();

            DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/xe");

            return ds.getConnection();

      }

 

자원정리 까지 해준다.

private void executeClose(ResultSet rs, PreparedStatement pstmt, Connection conn) {

            if(rs!=null)try {rs.close();}catch (SQLException e) {}

            if(pstmt!=null)try {pstmt.close();}catch (SQLException e) {}

            if(conn!=null)try {conn.close();}catch (SQLException e) {}

      }

 

데이터베이스에 연동할 메서드들을 생성하자.

◎글 저장,

글의 총 갯수/레코드 수 (페이지 번호를 넣기위해 총 레코드 수를  구한다),

글 목록,

글 상세,수정

글 수정,

글 삭제

 

◎ 글 저장

데이터는 전부 boardVO에 담아서 온다.

public void insert(BoardVO boardVO)throws Exception{

//글 저장
	public void insert(BoardVO boardVO)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		try {
			conn = getConnection(); //커넥션 풀로부터 커넥션을 할당
			//SQL문작성
			sql = "INSERT INTO sboard (num,title,name,passwd,content,ip,"
					+ "reg_date) VALUES(sboard_seq.nextval,?,?,?,?,?,SYSDATE)";
			pstmt = conn.prepareStatement(sql); //PreparedStatement객체 생성
			pstmt.setString(1, boardVO.getTitle()); //?에 데이터 바인딩
			pstmt.setString(2, boardVO.getName());
			pstmt.setString(3, boardVO.getPasswd());
			pstmt.setString(4, boardVO.getContent());
			pstmt.setString(5, boardVO.getIp());
			pstmt.executeUpdate(); //SQL문 실행
		} catch (Exception e) {
			throw new Exception(e);
		}finally { //자원정리
			executeClose(null, pstmt, conn);
		}
	}

◎ 글 목록

JSP에서는 roop를 돌면서 UI생성작업이 가능

클래스인 DAO는 roop를 돌면서  UI생성작업이 불가능 (데이터 처리만 한다)
→ 데이터만 담아서 UI에 보낸 후 UI쪽에서 roop를 돌아야 한다.

하나의 레코드를 자바빈에담고 그 자바빈을 ArrayList에 담아서 반환해야한다.

 

일반적인 패턴으로는,

같은 클래스 내에서  ArrayList를 사용한다면 자료형을  ArrayList로 사용하고, 다른 클래스로 보낼때는 List타입으로 보낸다.

(ArrayList가 List인터페이스에 임플리먼트되어있어서 ????리스트가 더 큰 범위)

반환타입을 List로 한다. (ArrayList를 생성하는건데 List인터페이스에 임플리먼트되어있어서 list타입을 쓸 수 있다.???)

public List<BoardVO> getList(int startRow, int endRow)throws Exception{

변수를 선언해주고

Connection conn = null;

PreparedStatement pstmt = null;

ResultSet rs = null;

List<BoardVO> list = null;

String sql = null;

return할 때는 list를 반환하므로 return list; 해주고  중간에 try-catch 작업을 넣어주자.

 

커넥션 풀로부터 커넥션을 할당받고

rownum을 이용한  sql문을 작성해주자.(상단을 참고)

sql = "SELECT * FROM (SELECT a.*, rownum rnum FROM (SELECT * FROM sboard ORDER BY num DESC)a) WHERE rnum >= ? AND rnum <= ?";

PreparedSatement객체를 생성해주고 ?에 시작하는 rownum 번호와  끝나는 rownum 번호를 지정해준다.

그리고 SQL문을 테이블에 반영하고 결과행들을 ResultSet에 담아준다.

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, startRow);

pstmt.setInt(2, endRow);

rs=pstmt.executeQuery();

 

SQL문을 테이블에 반영하고 결과행들을 ResultSet에 담은(rs=pstmt.executeQuery();) 후에

ArrayList 객체 생성 (DAO라서 UI를 못만든다. 위에 설명함)

list = new ArrayList<BoardVO>();

  import java.util.ArrayList;

 

roop를 돌며 하나의 레코드는 자바빈에 담고, 그 자바빈을 ArrayList에 담는다

while(rs.next()) { 

하나의 레코드 정보를 담기위해서 BoardVO객체(자바빈) 생성

BoardVO boardVO = new BoardVO();

자바빈에 데이터를 담을 때는 표시할 것만 담아도 되고, 전부를 다담고 나중에 화면에서 표시할 때 선택해서 꺼내도 상관없다. 속도차이 같은건 없기 때문에 원하는대로 작업을 한다.

boardVO.setNum(rs.getInt("num"));

boardVO.setTitle(rs.getString("title"));

boardVO.setName(rs.getString("name"));

boardVO.setReg_date(rs.getDate("reg_date"));

                       

자바빈(vo)을 ArrayList에 반드시 등록한다. 등록을 안하면 ArrayList가 비어있어서 데이터처리를 못한다.

list.add(boardVO);  } 

list를 반환한다.

return list;

 

이 페이지 연산을 하려면 총 레코드 수가 있어야한다. 별도의 메서드를 만들어준 글의 총 갯수(레코드 수 ) 메서드를 작성한다.

→ COUNT함수를 이용한 이 메서드가 있어야 페이징 처리가 가능함

//글 목록
	public List<BoardVO> getList(int startRow, int endRow)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		List<BoardVO> list = null;
		String sql = null;
		try {
			conn = getConnection(); //커넥션풀로부터 커넥션을 할당
			sql = "SELECT * FROM (SELECT a.*, rownum rnum FROM (SELECT * FROM sboard ORDER BY num DESC)a) "
					+ "WHERE rnum >= ? AND rnum <= ?"; //시작rnum번호, 끝rnum번호
			pstmt = conn.prepareStatement(sql); //PreparedStatement객체를 생성
			pstmt.setInt(1, startRow);
			pstmt.setInt(2, endRow);
			rs=pstmt.executeQuery(); //SQL문을 테이블에 반영하고 결과 행들을 ResultSet에 담음
			list = new ArrayList<BoardVO>(); //ArrayList개체 생성
			while(rs.next()) {
				BoardVO boardVO = new BoardVO(); //하나의 레코드 정보를 담기위해서 BoardVO객체 생성
				boardVO.setNum(rs.getInt("num"));
				boardVO.setTitle(rs.getString("title"));
				boardVO.setName(rs.getString("name"));
				boardVO.setReg_date(rs.getDate("reg_date"));
				list.add(boardVO); //반드시 자바빈(vo)을 ArrayList에 등록
			}
		} catch (Exception e) {
			throw new Exception(e);
		}finally {
			executeClose(rs, pstmt, conn);
		}
		return list; //리스트를 반환 list.jsp
	}

글의 총 갯수(레코드 수 )

페이징 연산을 하려면 총 레코드 수가 있어야한다. 

 

총 레코드 수를 읽어와야 하므로 

ResultSet rs = null

총 레코드 수를 담아야 하므로

int count = 0; 

sql 작성 시 COUNT함수를 이용한다.

sql = "SELECT COUNT(*) FROM sboard"

행이 하나밖에 없는 단독행이기 때문에 

if(rs.next()) { 

읽어온 총 count를 넣어주는데 "COUNT(*)"를 사용할 수 있지만 일반적으로 컬럼이 하나면 컬럼 인덱스를 쓰는 게 좋다.

count = rs.getInt(1);  } 

//글의 총 레코드수(개수) 
	public int getCount()throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = null;
		int count = 0;
		
		try {
			conn = getConnection(); //커넥션 풀로부터 커넥션을 할당
			sql = "SELECT COUNT(*) FROM sboard";
			
			pstmt = conn.prepareStatement(sql); //PreparedStatement객체 생성
			rs = pstmt.executeQuery(); //sql문을 테이블에 반영하고 결과행을 ResultSet에 담음
			if(rs.next()) { //행이 하나 이므로 if
				count = rs.getInt(1); //컬럼이 하나이므로 컬럼 인덱스를 넣는게 편함
			}
		}catch (Exception e) {
			throw new Exception(e);
		}finally {
			executeClose(rs, pstmt, conn);
		}
		return count;
	}

 

글 상세,수정Form

//글 상세, 수정폼
	public BoardVO getBoard(int num)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		BoardVO board = null;
		String sql = null;
		try {
			conn = getConnection(); //커넥션 풀로부터 커넥션을 할당
			sql = "SELECT * FROM sboard WHERE num =?";
			pstmt = conn.prepareStatement(sql); //PreparedStatement객체 생성
			pstmt.setInt(1, num); //?에 데이터 바인딩
			rs = pstmt.executeQuery(); //SQL문을 테이블에 반영하고 결과'행'을 ResultSet에 담음
			if(rs.next()) {
				board = new BoardVO();
				board.setNum(rs.getInt("num"));
				board.setTitle(rs.getString("title"));
				board.setName(rs.getString("name"));
				board.setPasswd(rs.getString("passwd"));
				board.setContent(rs.getNString("content"));
				board.setIp(rs.getString("ip"));
				board.setReg_date(rs.getDate("reg_date"));
			}
		} catch (Exception e) {
			throw new Exception(e);
		}finally { //자원정리
			executeClose(rs, pstmt, conn);
		}
		return board; //detale.jsp
	}

◎ 글 수정

//글 수정
	public void update(BoardVO boardVO)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		try {
			conn = getConnection(); //커넥션풀로부터 커넥션을 할당
			sql = "UPDATE sboard SET title=?,name=?,content=?,"
					+ "ip=?,reg_date=SYSDATE WHERE num=?";
			pstmt = conn.prepareStatement(sql); //PreparedStatement객체 생성
			pstmt.setString(1, boardVO.getTitle());
			pstmt.setString(2, boardVO.getName());
			pstmt.setString(3, boardVO.getContent());
			pstmt.setString(4, boardVO.getIp());
			pstmt.setInt(5, boardVO.getNum());
			pstmt.executeUpdate(); //SQL문을 반영
		} catch (Exception e) {
			throw new Exception(e);
		}finally {
			executeClose(null, pstmt, conn);
		}
	}

◎ 글 삭제

//글 삭제
	public void delete(int num)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		try {
			conn = getConnection();
			sql  = "DELETE FROM sboard WHERE num=?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, num);
			pstmt.executeUpdate();
		} catch (Exception e) {
			throw new Exception(e);
		}finally {
			executeClose(null, pstmt, conn);
		}
	}

src/main/webapp/css/layout.css

복사해온 스타일에 table스타일도 추가해준다.

▼ code

더보기
더보기
/* 목록 */
table{
	width:800px;
	border:1px solid #000;
	border-collapse:collapse;
	margin-top:5px;
}
table td, table th{
	border:1px solid #000;
	padding:5px;
}

src/main/webapp/views/list.jsp : MAIN 

stylesheet를 링크넣어주고 UI작업만 일단 해준다. 호출되는 글쓰기 페이지(writeForm.jsp)로 가자

DAO, VO를 import해주고

ArrayList를 리스트타입으로 사용하기 때문에 import

<%@ page import="java.util.List" %>

UI작업을 할 때 

확장  for 문을 사용해서 인덱스0번 부터 boardVO를 꺼낸다. 가지고있는 get메서드를 활용해서 데이터를 표시한다.

<% for(BoardVO boardVO : list){ %>

         <tr>

                <td><%= boardVO.getNum() %></td>

회원번호가 세션에 있는게 아니라 get방식으로 전달

                <td><a href="detail.jsp?num=<%= boardVO.getNum() %>"><%= boardVO.getTitle() %></a></td>

                <td><%= boardVO.getName() %></td>

                <td><%= boardVO.getReg_date() %></td>

         </tr>

<% } %>

 

보고싶은 페이지카운트 번호를 pageNum을 Key로 번호를  Value로 get방식으로 (list.jps에) 넘긴다.

list.jsp?pageNum=2   이런식으로 페이지 처리를 하기 위해서 pageNum을 받아야한다.

(* 이 때 request에 저장된 'pageNum'이란 명칭은 PagingUtil에서 만들어진 것이라 우리가 따로 신경쓰지 않는 부분이다.)

처음진입할 때는  list.jsp ?pageNum=2 으로 ?pagenum이 없으므로, pagenum이 없을 때는 1페이지로 간주하기 위해서

우선,

선택한 페이지번호를 읽어오는데 getParameter는 무조건 String 으로 반환하므로

String pageNum = request.getParameter("pageNum");

pageNum이 없으면 1페이지로 간주한다. 즉 처음에는 무조건 1페이지로 간주하겠다.

      if(pageNum == null){

            pageNum ="1";  }

 

이제 연산할수 있게끔 정보를 변수에 담아둔다

 

현재 선택했던 페이지(pageNum) 문자열로 되어있기 때문에 연산하기 위해서 String을 int로 바꾼다.

int currentPage = Integer.parseInt(pageNum);

이제 데이터가 준비가 되었으니 count값을 구해서 PagingUtil을 생성해서 연산을 하게끔 만든다.

int count = dao.getCount();

여기까지가 PagingUtil이 원하는 데이터를 다 표시한 상태이다.(rowCount, pageCount, CurrentPage, count)

 

PagingUtil객체를 생성하여 관련 정보를 넘긴다. 그 전에 import 도 해준다.

PagingUtil pagingUtil = new PagingUtil(currentPage,count,rowCount,pageCount,"list.jsp");

타입        변수                                     인자 순서 중요                                마지막은 호출url(jsp)

 

ui목록 출력 시작 전에   조건 체크를 해준다. count ==0 인 경우는 글이 없다는 소리이므로 표시를 해준다.

<% if(count==0){ %>

<div class="result-display">저장된 글이 없습니다!</div>

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<%@ page import="kr.board.dao.BoardDAO" %>
<%@ page import="kr.board.vo.BoardVO" %>
<%@ page import="kr.util.PagingUtil" %>
<%@ page import="java.util.List" %>
<%
	String pageNum = request.getParameter("pageNum");
	if(pageNum == null){
		pageNum ="1"; //처음엔 무조건 null
	}
	int rowCount = 10; //한 화면에 몇 개의 글(행, 레코드)을 보여줄 지 지정한다.
	int pageCount = 10; //한 화면에 몇 개의 페이지 수를 보여줄 지 지정한다.
	int currentPage = Integer.parseInt(pageNum); //클릭할 때마다 매번 바뀜

	BoardDAO dao = BoardDAO.getInstance();
	//총 레코드 수
	int count = dao.getCount();
	//pagingUtil객체 생성
	PagingUtil pagingUtil = new PagingUtil(currentPage,count,rowCount,pageCount,"list.jsp");
	
	List<BoardVO> list = null;
	if(count>0){
						//시작 rownum번호, 끝 rownum번호
		list = dao.getList(pagingUtil.getStartCount(), pagingUtil.getEndCount()); 
	}
%>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 목록 MAIN</title>
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/layout.css">
</head>
	<body>
		<div class="page-main">
			<h1>게시판 목록</h1>
			<div class="align-right">
				<input type="button" value="글쓰기" onclick="location.href='writeForm.jsp'">
			</div>
<%
			if(count==0){
%>
			<div class="result-display">저장된 글이 없습니다!</div>
<%	
			}else{ //count가 있을 때
%>
			<!-- 목록 출력 시작 -->
			<table>
				<tr>
					<th>글번호</th>
					<th>제목</th>
					<th>작성자</th>
					<th>작성일</th>
				</tr>
<%
	for(BoardVO boardVO : list){
	/* 회원번호가 세션에 있는게아니라 get방식으로 전달 */
%>
		<tr>
			<td><%= boardVO.getNum() %></td>
			<td><a href="detail.jsp?num=<%= boardVO.getNum() %>"><%= boardVO.getTitle() %></a></td>
			<td><%= boardVO.getName() %></td>
			<td><%= boardVO.getReg_date() %></td>
		</tr>
<%
	}
%>
			</table>
			<!-- 목록 출력 끝 -->
			<div class="align-center">
				<%= pagingUtil.getPagingHtml() %> <%-- 페이지번호가있는문자열 반환 --%>
			</div>
<%
			}//end of else 
%>	
		</div>
	</body>
</html>


src/main/webapp/views/writeForm.jsp : 글쓰기Form

UI작업을 해주고 유효성 체크를 해준다.(여기서는 자바스크립트 이용했음)

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<link rel="stylesheet" href="<%= request.getContextPath()%>/css/layout.css">
<script type="text/javascript">
	window.onload=function(){
		var form = document.getElementById('write_form');
		//이벤트연결
		form.onsubmit=function(){
			var title = document.getElementById('title');
			if(title.value.trim()==''){
				alert('제목을 입력하세요!');
				title.focus();
				title.value='';
				return false;//submit안돼게 기본이벤트 초기화 하려고
			}
			var name = document.getElementById('name');
			if(name.value.trim()==''){
				alert('이름을 입력하세요!');
				name.focus();
				name.value='';
				return false;
			}
			var passwd = document.getElementById('passwd');
			if(passwd.value.trim()==''){
				alert('비밀번호를 입력하세요!');
				passwd.focus();
				passwd.value='';
				return false;
			}
			var content = document.getElementById('content');
			if(content.value.trim()==''){
				alert('내용을 입력하세요!');
				content.focus();
				content.value='';
				return false;
			}
		};
	};
</script>
</head>
<body>
<div class="page-main">
	<h1>글쓰기</h1>
	<form action="write.jsp" id="write_form" method="post">
		<ul>
			<li>
				<label for="title">제목</label>
				<input type="text" name="title" id="title" size="30" maxlength="50">
			</li>
			<li>
				<label for="name">작성자</label>
				<input type="text" name="name" id="name" size="10" maxlength="10">
			</li>
			<li>
				<label for="passwd">비밀번호</label>
				<input type="password" name="passwd" id="passwd" size="10" maxlength="12">
			</li>
			<li>
				<label for="content">내용</label>
				<textarea rows="5" cols="40" name="content" id="content"></textarea>
			</li>
		</ul>
		<div class="align-center">
			<input type="submit" value="글쓰기">
			<input type="button" value="목록" onclick="location.href='list.jsp'">
		</div>
	</form>
</div>
</body>
</html>


src/main/webapp/views/write.jsp : 글쓰기 완료

자원을 사용하려고 하므로 임포트 해준다.

<%@ page import="kr.member.dao.MemberDAO" %> 

Form에서 전송을 하면 request에 담기고 담긴걸 자바빈에 넣어줘야하는데 액션태그 사용한다. 

<%@ page import="kr.member.vo.MemberVO" %> 

 

id가 post방법으로 전송될 것이므로 전송된 데이터 인코딩 처리와 데이터 반환 처리를 해준다.

<% request.setCharacterEncoding("utf-8"); %> 

 

setproperty 를 이용해서 request에 담겨있는 정보를 자바빈으로 넘겨주는 작업을 한다.

JSP에서 자바빈 객체를 생성할 때 사용하는 <jsp:useBean>액션 태그를 사용한다.

<jsp:useBean id="board" class="kr.member.vo.BoardVO"/> 

- id : jsp 페이지에서 자바빈 객체에 접근할 때 사용할 이름을 명시함

- class : 패키지 이름을 포함한 자바빈 클래스의 완전한 이름을 입력함

 

자바빈 객체의 프로퍼티 값을 설정 하는<jsp:setProperty>액션 태그를 사용한다.

<jsp:setProperty name="board" property="*" /> 

- name : 프로퍼티의 값을 변경할 자바빈 객체의 이름. <jsp:useBean> 액션 태그의 id 속성에서 지정한 값을 사용

- property : 값을 지정할 프로퍼티의 이름

식별자(name="member" )를 이용해서 자바빈에 접근해서 모든 프로퍼티(property="*" )에 대해 검색을 하고 class(class="kr.member.vo.BoardVO"/)에 넣어준다.

 

이 때 셋팅을 안한 데이터가 있다. 직접 입력하지않은 데이터 = IP주소

ip주소는 입력한 값이아니라서 request로부터 뽑아서 request.getRemoteAddr() 을 이용하여 IP주소를 구해서 자바빈에 저장한다. 

<% board.setIp(request.getRemoteAddr());

자바빈이 만들어졌으니 DAO에 전달을 해준다

BoardDAO dao = BoardDAO.getInstance();

ip주소를 board라고 insert에 전달을 한다

dao.insert(board); %>

예외가 발생하지 않으면 정상적으로 처리가 되는데 글쓰기 작업이 완료되는 것이다.

태그에 css.stylesheet를 link걸고 완료가 되었다는 화면을 만들어준다.

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="kr.board.dao.BoardDAO"%>
<%@ page import="kr.board.vo.BoardVO"%>
<%
request.setCharacterEncoding("utf-8"); //전송된 데이터 인코딩 처리
%>
<jsp:useBean id="board" class="kr.board.vo.BoardVO" />
<jsp:setProperty property="*" name="board" />
<!-- ip주소는 입력한 값이 아니라서 request로부터 뽑아서 셋팅을 따로 해준다 -->
<%
//클라이언트의 ip주소 저장
//ip주소는 입력한 값이아니라서 request로부터 뽑아서 셋팅을 따로 해준다
board.setIp(request.getRemoteAddr());

BoardDAO dao = BoardDAO.getInstance();
dao.insert(board); //ip주소를 board라고 insert에 전달을 한다
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기 완료</title>
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/layout.css">
</head>
<body>
	<div class="page-main">
		<h1>글쓰기 완료</h1>
		<div class="result-display">
			<div class="align-center">
				게시판에 글을 등록했습니다. <br> <input type="button" value="목록" onclick="location.href='list.jsp'">
			</div>
		</div>
	</div>
</body>
</html>


src/main/webapp/views/detail.jsp : 글 상세

글상세 메서드를 먼저 작성

 

<input type="button" value="수정" onclick="location.href='updateForm.jsp?num=<%=boardVO.getNum()%>'">
<input type="button" value="삭제" onclick="location.href='deleteForm.jsp?num=<%=boardVO.getNum()%>'">
<input type="button" value="목록" onclick="location.href='list.jsp">

경로가 같으므로 파일명만 명시했음

▼ code

더보기
더보기
<%@page import="java.awt.image.DataBufferDouble"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ page import ="kr.board.dao.BoardDAO" %>
<%@ page import ="kr.board.vo.BoardVO" %>
<%
	int num = Integer.parseInt(request.getParameter("num")); //get방식으로 num값을 넘긴걸 표시
	BoardDAO dao = BoardDAO.getInstance();
	BoardVO boardVO = dao.getBoard(num); //getBoard()메서드
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 글 상세</title>
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/layout.css">
</head>
<body>
<div class="page-main">
	<h1>게시판 글상세</h1>
	<ul>
		<li>글번호 : <%=boardVO.getNum() %></li>
		<li>제목 : <%=boardVO.getTitle() %></li>
		<li>작성자 : <%=boardVO.getName() %></li>
	</ul>
	<hr size="1" width="100%" noshade="noshade">
	<p>
		<%= boardVO.getContent() %>
	</p>
	<div class="align-right">
		작성일 : <%=boardVO.getReg_date() %>
		<input type="button" value="수정" onclick="location.href='updateForm.jsp?num=<%=boardVO.getNum()%>'">
		<input type="button" value="삭제" onclick="location.href='deleteForm.jsp?num=<%=boardVO.getNum()%>'">
		<input type="button" value="목록" onclick="location.href='list.jsp">
	</div>
</div>
</body>
</html>

src/main/webapp/views/updateForm.jsp : 글 수정Form

세션을 이용하여 글번호를 처리하는게 아닌 get방식으로 처리하므로 hidden처리를 해줘야한다.

<input type="hidden" name="num" value="<%=num %>">

비밀번호는 바꾸는게 아니라 기존 비밀번호를 인증하는란이다.

바꾸려면 항목을 따로 만들어야한다.

 

데이터는 update.jsp로 가고 DAO에서 수정되는 메서드를 만들어보자.

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ page import="kr.board.dao.BoardDAO" %>
<%@ page import="kr.board.vo.BoardVO" %>
<%
   int num = Integer.parseInt(request.getParameter("num"));
   BoardDAO dao = BoardDAO.getInstance();
   BoardVO board = dao.getBoard(num);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 수정</title>
<link rel="stylesheet" href="<%=request.getContextPath() %>/css/layout.css">
<script type="text/javascript">
   window.onload=function(){
      var form=document.getElementById('update_form');
      form.onsubmit =function(){
         var title = document.getElementById('title');
         if(title.value.trim()==''){
            alert('제목을 입력하세요.');
            title.focus();
            title.value='';
            return false; //submit하지 못하게
         }
         var name= document.getElementById('name');
         if(name.value.trim()==''){
            alert('이름을 입력하세요.');
            name.focus();
            name.value='';
            return false;
         }
         var passwd = document.getElementById('passwd');
         if(passwd.value.trim()==''){
            alert('비밀번호를 입력하세요.');
            passwd.focus();
            passwd.value='';
            return false;
         }
         var content = document.getElementById('content');
         if(content.value.trim()==''){
            alert('내용을 입력하세요.');
            content.focus();
            content.value='';
            return false;
         }
      }
   }
</script>
</head>
<body>
<div class="page-main">
   <h1>글수정</h1>
   <form id="update_form" action="update.jsp" method="post">
      <input type="hidden" name="num" value="<%=num %>">
      <ul>
         <li>
            <label for="title">제목</label>
            <input type="text" name="title" id="title" size="30" value="<%=board.getTitle() %>" maxlength="50">
         </li>
         <li>
            <label for="name">이름</label>
            <input type="text" name="name" id="name" size="10"
            value="<%=board.getName() %>" maxlength="12">
         </li>
         <li>
            <label for="passwd">비밀번호</label> <!-- 기존 비밀번호 인증하는 것 -->
            <input type="password" name="passwd" id="passwd" size="10" maxlength="12">
            * 등록시 입력한 비밀번호
         </li>
         <li>
            <label for="content">내용</label>
            <textarea rows="5" cols="40" name="content" id="content"><%=board.getContent() %></textarea>
         </li>
      </ul>
      <div class="align-center">
         <input type="submit" value="글수정">
         <input type="button" value="목록" onclick="location.href='list.jsp'">
      </div>
   </form>
</div>
</body>
</html>


src/main/webapp/views/update.jsp : 글 수정 결과

<%@ page import="kr.board.dao.BoardDAO"%>

자바빈과 별개로 데이터 받는 부분이 있어서 VO도 import

<%@ page import="kr.board.vo.BoardVO"%>

 

글 번호와 비밀번호로 인증을 먼저 해야한다.

글 번호를 통해 한건의 레코드에 접근할 수 있고 DB에 저장된 비밀번호를 알아낼 수 있다

사용자가 입력한 비밀번호와 비교해서 일치하면 UPDATE처리 될 수 있도록

 

BoardDAO.getInstance(); 의 객체를 얻어온다음

<% BoardDAO dao = BoardDAO.getInstance();

비밀번호 인증을 위해서 글번호를 전달하고 한건의 레코드 정보를 BoardVO에 담아서 반환받아 정보를 읽어온다

BoardVO db_board = dao.getBoard(boardVO.getNum());

 

조건체크를 위해 boolean 타입의 변수를 하나 만든다

boolean check = false;

Form에서 바로 넘어오면 null이 아님

if(db_board!=null){

비밀번호 인증한다 (사용자가 입력한 비밀번호)

check=db_board.isCheckedPassword(boardVO.getPasswd()); }

인증 성공 시

if(check){

ip주소를 넣어주고

boardVO.setIp(request.getRemoteAddr());

boardVO를 넘겨준다

dao.update(boardVO); %>

 

결과를 자바스크립트로 처리한다.

 

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="kr.board.dao.BoardDAO"%>
<%@ page import="kr.board.vo.BoardVO"%>
<%
	request.setCharacterEncoding("utf-8"); //전송된 데이터 인코딩 처리
%>
<jsp:useBean id="boardVO" class="kr.board.vo.BoardVO"/>
<jsp:setProperty property="*" name="boardVO"/>
<%
 	BoardDAO dao = BoardDAO.getInstance();
	BoardVO db_board = dao.getBoard(boardVO.getNum());
	boolean check = false;
	if(db_board!=null){
						//사용자가 입력한 비밀번호
		check=db_board.isCheckedPassword(boardVO.getPasswd());
	}
	if(check){ //인증 성공 시
		boardVO.setIp(request.getRemoteAddr());
		dao.update(boardVO);
%>
<script type="text/javascript">
	alert('글수정을 완료했습니다');
	location.href='list.jsp';
</script>
<%
	}else{
%>
<script type="text/javascript">
	alert('비밀번호 불일치');
	history.go(-1);
</script>
<%
	}
%>


src/main/webapp/views/deleteForm.jsp : 글 삭제Form

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 정보삭제 Form</title>
<link rel="stylesheet" href="<%=request.getContextPath() %>/css/layout.css">
</head>
<body>
<%
	int num = Integer.parseInt(request.getParameter("num"));
%>
<div class="page-main">
	<h2>상품 정보 삭제</h2>
	<p class="align-center">
		<span>정말 삭제하시겠습니까?</span>
	</p>
	<form action="delete.jsp" method="post">
		<input type="hidden" name="num" value="<%=num%>">
		<div class="align-center">
			<input type="submit" value="삭제">
			<input type="button" value="목록" onclick="location.href='list.jsp'">
		</div>
	</form>	
</div> 
</body>
</html>


src/main/webapp/views/delete.jsp : 글 삭제

▼ code

더보기
더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="kr.product.dao.ProductDAO"  %>
<%@ page import="kr.product.vo.ProductVO" %>
<%
	request.setCharacterEncoding("utf-8"); //전송된 데이터 인코딩 처리
	int num = Integer.parseInt(request.getParameter("num")); //전송된 데이터 반환
	ProductDAO dao  = ProductDAO.getInstance();
		dao.delete(num);
%>
<script type="text/javascript">
	alert('상품정보를 삭제했습니다!');
	location.href='list.jsp';
</script>

 

 

 

 

모바일에서는 ajax로 전부 구현해도 상관이 없지만 한 페이지에서 ajax로 전부 구현하는 것은 데스크탑일 경우엔 필요한 경우에만 사용한다

Serialize () 를 이용해서 개별적으로 작업한느게 아니라 한번에

getAttribute는 무조건 오브젝트형태로 반환한다.