Git → 분산 버전 관리 시스템

  • 협업을 위해 사용
  • 파일의 양이 많아지고 같은 파일을 여러 번 수정하는 경우에는 관리가 어려워짐
  • 코드를 유지하며 유지보수에 도움을 주는 git

 

소스트리 툴 강사님 추천

깃을 사용하려면 우선 설치

 

git bash 명령어

 

git bash 들어가서 사용자 이름, 이메일 설정 :

$ git config --global user.email "이메일"

$ git config --global user.name "설정할 이름"

 

사용자 등록이 되었는지 확인 :

$ git config --list

 

현재 위치 보기 :

$ pwd

→ /c/Users/ITSC

 

현재 디렉토리에 들어있는 파일 정보 리스트 확인 :

$ ls

 

숨긴 파일 보기 :

$ ls -la

 

한 칸 상위 폴더로 이동 :

$ cd ..

→ /c/Users

 

하위 폴더로 이동 :

$ ls 해서 하위 폴더 확인 한 후 이동하고 싶은 폴더 $ cd (이동할 폴더) 치기

 

다시 홈 디렉토리로 이동 :

$ cd ~

 

디렉토리 만들기

$ mkdir (만들 디렉토리 이름)

 

디렉토리 삭제

$ rm -r test

 

메모장 파일 만들기

$ vim (파일명).txt

 

파일 수정

$ i

 

수정 후 나가기

$ esc 누르고 :wq 누르기

 

수정한 파일 내용 확인

$ cat (파일이름).txt

 

깃허브 :

깃을 이용해 온라인에서 여러 사람이 파일을 공유할 수 있게 해주는 저장소

 

버전관리는 내 pc에서, 그 후 공유할 때는 깃허브에 올리기

작업 트리 / 스테이지 / 저장소
          깃은 스테이지와 저장소를 관리

 

 

작업트리 → 스테이지 → 저장소 에 올려야 깃허브에 올라갈 수 있다.

작업트리에서 스테이지로 값 보내기 → add

스테이지에서 저장소로 값 보내기 → commit

 

강사님의 팁) 깃허브만 믿으면 안되고 본인이 본인 파일 3차 백업까지 해놓아야 한다.

usb, 로컬, 클라우드, 깃허브 관리

 

깃 저장소 만들기 명령어

$ git init

 

깃 저장소 상태 확인

$ git status

// 이렇게 뜬다

Untracked files: // 아직 깃에 올리지 않은 파일 (use "git add <file>..." to include in what will be committed) // 스테이지에 올려라 hello.txt

 

스테이지 영역으로 보내기

$ git add hello.txt (파일명)

스테이지까지 올리면 커밋하라는 메세지가 뜬다.

 

메세지를 달아 파일 올리기

$ git commit -m "message1" - ”(표시할 메세지)”

 

깃 저장소 버전 관리 ( 커밋이 얼마나 일어났는지 확인할 수 있다)

$ git log

커밋까지 된 후 다시 수정하면 스테이지에 올리거나 다시 원복하라는 메세지가 뜬다.

 

저장소 영역으로 보내기

$ git commit -m

 

스테이지 저장, 커밋까지 한번에 하기 ( 추적관리가 최소 1회 이상 되었을 때 사용가능)

$ git commit -am “message2” - ”(표시할 메세지)”

 

가장 최신 버전 확인은 뒤에 (head→ master)라고 적혀있다

 

변경 사항 확인

$ git diff

 

원상복구를 한 후 hello2.txt 새로운 파일 만들기

변경 이력 확인, 파일 정보까지 같이 확인하는 옵션

$ git log --stat ( - 두 개 띄어쓰기 없이 쓴 것)

 

메세지 실수가 있을 경우 처리하는 명령어 (가장 최근의 메세지 변동)

$ git commit --amend

 

작업트리에서 수정한 파일 되돌리기

$ git checkout

 

git restore --staged <file> 라는 메세지가 나올 때 스테이지에서 작업트리로 되돌리기

$ git reset HEAD <file>

 

최신 커밋의 저장소에서 작업트리로 되돌리기

$ git reset HEAD^ 

 

작업을 특정 위치로 되돌리고 싶을 때 (복원불가)

$ git reset 커밋 해시값

ex) git reset c665b8ee637814876ef797a71f6347f23d95ccb7

 

버전 정보 삭제 없이

$ git revert 커밋 해시값

 

git add는 되어있는 상태로 돌아간다

$ git reset --soft 커밋 해시값

 

git add 이전으로 돌아간다

$ git reset --mixed 커밋 해시값

 


이어서 브런치 만들기, 깃허브와 연결해서 원격저장소 관리 

 

UIUX _국비과정 0729 ~ 30 (Git) | Notion

Git → 분산 버전 관리 시스템

ringed-tartan-f02.notion.site

 

오후에 시험을 본다

 

MyBatis

  • 쿼리문을 별도 관리, 분리한다
  • 동적 쿼리를 작성할 수 있다.
  • 캐시 기능을 제공해 데이터베이스 연산 속도를 높일 수 있다.

 

동적쿼리란

실행 시점에 조건에 따라 SQL 쿼리를 동적으로 생성하는 것.

데이터 베이스의 검색 조건이나 결과값 등이 동적으로 변환할 때 유용하게 사용된다.

 

src/main/resources > mapping > board-mapping.xml 에서 쿼리문을 처리

BoardDAO에서는 board-mapping.xml에서 적은 쿼리문을 언제 사용할지 정의해준다고 생각하면 됨.

 

 

board-mapping.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="BoardDAO">

	<!-- 글 등록 -->
	<insert id="insertBoard">
		insert into board (seq,title,writer,content)
		values ((select nvl(max(seq),0) + 1 from board), #{title}, #{writer}, #{content})
	</insert>
	
	<!-- 글 수정 -->
	<update id="updateBoard">
		update board set title=#{title}, content=#{content}, where seq=#{seq}
	</update>
	
	<!-- 글 삭제 -->
	<delete id="deleteBoard">
		delete board where seq=#{seq}
	</delete>
	
	<!-- 글 상세 조회 -->
	<select id="getBoard" resultType="board">
		select * from board where seq=#{seq}
	</select>
	
	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board">
		select * from board where title like '%'||#{searchKeyword}||'%' 
		order by seq desc
	</select>
	
</mapper>

 

src/main/java > com.springbook.biz.board > BoardServiceClient

package com.springbook.biz.board;

import com.springbook.biz.board.impl.BoardDAO;

public class BoardServiceClient {

	public static void main(String[] args) {
		BoardDAO boardDAO = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setTitle("myBatis 제목");
		vo.setWriter("홍길동");
		vo.setContent("여름아 부탁해");
		boardDAO.insertBoard(vo);

	}

}

 

이렇게 하고 실행했는데 이런 경고 메세지가 생겨서 보니

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/C:/Users/USER/.m2/repository/org/mybatis/mybatis/3.3.1/mybatis-3.3.1.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

mybatis 버전 문제였다. 3.3.1 버전에서 → 3.5.2 버전으로 업그레이드 한 후 실행했더니 해결

 

pom.xml 수정

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis</artifactId>
	    <version>3.5.2</version>
	</dependency>

참고) https://sillutt.tistory.com/entry/Mybatis-WARNING-An-illegal-reflective-access-operation-has-occurred

 

[Mybatis] WARNING: An illegal reflective access operation has occurred

원인 테스트 중 다음과 같은 경고가 발생했다. WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/C:/Users/USER/.m2/repository/org/mybatis/mybatis/

sillutt.tistory.com

 

 

BoardServiceClient.java

package com.springbook.biz.board;

import java.util.List;

import com.springbook.biz.board.impl.BoardDAO;

public class BoardServiceClient {

	public static void main(String[] args) {
		BoardDAO boardDAO = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		// 글 등록
		vo.setTitle("myBatis 제목");
		vo.setWriter("홍길동");
		vo.setContent("여름아 부탁해");
		boardDAO.insertBoard(vo);
		
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		
		// 상세글 조회
		//vo.setSeq(19);
		//BoardVO getboard = boardDAO.getBoard(vo);
		//System.out.println("상세글 조회 결과: " + getboard);
		
		// 글 수정
		//vo.setTitle("오늘의 날씨");
		//vo.setContent("맑음");
		//vo.setSeq(17);
		//boardDAO.updateBoard(vo);
	
		// 글 삭제
		//vo.setSeq(29);
		//boardDAO.deleteBoard(vo);
		
		// 전체 글 조회
		List<BoardVO> boardList = boardDAO.getBoardList(vo); 
		
		for (BoardVO board : boardList) {
			System.out.println("==>" + board.toString());
		}

	}

}

 

조회, 수정, 삭제가 안된다..! 미해결과제

 

해결 )

 

스프링 pom.xml 세팅 시 aspectjweaver 태그 위치 설정 관계

0729)금요일에 mybatis 를 기존에 만들어 둔 게시판과 연동했는데 실행 오류가 났다.오늘 오전 다시 파일들을 찬찬히 살펴보며 코드를 수정했는데 pom.xml 에 세팅 오류가 있었다.' 오류 메세지 )Contex

100dumpling.tistory.com

 


 

추가로 알아 둘 것.

 

board-mapping.xml

		<selectkey keyProperty="seq" resultType="int" order="BEFORE">
			select board_seq.nextval as seq from duel
		</selectkey>
		
		insert into board (seq,title,writer,content)
		values (#{seq}, #{title}, #{writer}, #{content})
		
		<!-- 어떤 값을 따로 쓰고 싶을 때 -->
		<!-- order="AFTER" insert 처리가 된 후에 값을 가지고 와라 -->
		<selectkey keyProperty="writer" resultType="int" order="AFTER">
			select writer from board
		</selectkey>
		
	</insert>
	
	<insert id ="hobby">
	insert into hobby (writer) values(#{writer}) <!-- 다른 테이블의 writer를 끌어올 수 있다 -->
	</insert>

시퀀스 객체를 DB에 만들어 두고 시퀀스 객체를 이용할 수 있다.

 

board-mapping.xml

	<!-- 컬럼이름과 VO객체 멤버 이름 비교, 이름이 다르더라도 자동으로 매치가 된다 -->
	<resultMap id="boardResult" type="board">
		<id property="seq" column="SEQ"/>
		<result property="title" column="TITLE"/>
		<result property="writer" column="WRITER"/>
		<result property="content" column="CONTENT"/>
		<result property="regDate" column="REGDATE"/>
		<result property="cnt" column="CNT"/>
	</resultMap>

 

쿼리문을 쓸 때 부등호( <, > ) 인식을 못한다. 그럼으로 부등호를 써야할 때는

	<!-- 조건절에 비교연산자(<, >)을 식으로 인식하기 위해 -->
	<![CDATA[ 
		insert into board (seq,title,writer,content)
		values ((select nvl(max(seq),0) + 1 from board), #{title}, #{writer}, #{content})
	]]>

<![CDATA[ ]]> 안에 비교할 대상의 식이 쓰이게 사용해야 한다.

 

BoardDAO.java

package com.springbook.biz.board.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.util.SqlSessionFactoryBean;

public class BoardDAO {
	
	// 원형
//	public List seleList(String statement)
//	public List seleList(String statement, Object parmeter)
//	
//	public int insert(String statement, Object parmeter)
//	public int update(String statement, Object parmeter) throws SQLException
//	public int delete(String statement, Object parmeter) throws SQLException
	
	// SqlSession 타입 mybatis은 xml의 정보를 다 가지고 있다. 
	private SqlSession mybatis;
	
	public BoardDAO() {
		mybatis = SqlSessionFactoryBean.getSqlSessionInstance();
	}
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		mybatis.insert("BoardDAO.insertBoard", vo); 
		mybatis.commit();
	}
	
	// 글 수정
	public void  updateBoard(BoardVO vo) {
		mybatis.update("BoardDAO.updateBoard", vo);
		mybatis.commit();
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		mybatis.delete("BoardDAO.deleteBoard", vo);
		mybatis.commit();
	}
	
	// 글 상세조회
	public BoardVO getBoard(BoardVO vo) {
		
		return mybatis.selectOne("BoardDAO.getBoard", vo); // 하나만 조회할때 selectOne
	}
	
	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		
		return mybatis.selectList("BoardDAO.getBoardList", vo); // 여러 개 조회할때 selectList 
	}
}

 


Spring에 Mybatis 연결하기

 

어떤 프로그램을 사용하기 위해서는 접점이 필요하다

Spring에서도 Mybatis을 사용하기 위해서는 SDK → api 인터페이스가 필요.

SDK 을 통해 Mybatis에 접근한다.

 

자바에서 오라클DB를 쓰는 것과 똑같은 원리. - JDBC가 SDK

 

다이나믹 SQL = 동적 쿼리문

조건절 분기

 

BoardWep > board-mapping.xml

	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board" resultMap="boardResult">
		select * from board where title like '%'||#{searchKeyword}||'%' 
		order by seq desc
	</select>

위와 같은 구문 고정이 title인데 동적 처리를 하면

 

BoardWep > board-mapping.xml

	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board" resultMap="boardResult">
		select * from board 
		where 1=1
		
		<if test="searchCondition == 'TITLE'">
		and title like '%'||#{searchKeyword}||'%'
		</if>
		<if test="searchCondition == 'CONTENT'">
		and content like '%'||#{searchKeyword}||'%' 
		</if>
		order by seq desc
	</select>

이렇게 바꿀 수 있다.

where 절의 중복을 막기 위해 where 1=1 를 쓰고 where 절이 들어가는 곳마다 and 를 쓴다.

 

BoardWep > BoardDAOMybatis

package com.springbook.biz.board.impl;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

@Repository
public class BoardDAOMybatis {
	// SqlSessionTemplate이 mybatis 기능을 쓰는 라이브러리
	// SqlSessionTemplate 객체를 사용
	
	// 자동의존주입
	@Autowired
	private SqlSessionTemplate mybatis;
	
	public void insertBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 insertBoard() 기능 처리");
		mybatis.insert("BoardDAO.insertBoard", vo);
	}
	
	public void updateBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 updateBoard() 기능 처리");
		mybatis.update("BoardDAO.updateBoard", vo);
	}
	
	public void deleteBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 deleteBoard() 기능 처리");
		mybatis.delete("BoardDAO.deleteBoard", vo);
	}
	
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 getBoard() 기능 처리");
		return mybatis.selectOne("BoardDAO.getBoard", vo);
	}
	
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> Mybatis로 getBoardList() 기능 처리");
		return mybatis.selectList("BoardDAO.getBoardList", vo);
	}
}

 

applicationContext

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <!-- 패키지를 스캔해준다. 다 해주는 것은 아니고 표시되어진 클래스만 스캔해준다 -> 이것이 어노테이션 -->
	<!-- <context:component-scan base-package="polymorphism"></context:component-scan> -->
	<context:component-scan base-package="com.springbook.biz"></context:component-scan>
	
	<!-- database.properties 의 파일을 읽어올 수 있게 해준다 -->
	<context:property-placeholder location="classpath:config/database.properties"/>
	
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.driver}"></property>
	<property name="url" value="${jdbc.url}"></property>
	<property name="username" value="${jdbc.username}"></property>
	<property name="password" value="${jdbc.password}"></property>

	</bean>
	
	<!--JdbcTemplate 클래스를 통해 DB에 접근 (crud) -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		 <property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
		<tx:method name="get*" read-only="true"/> <!-- get메소드 제외하고 트랜잭션 처리를 해줘라 -->
		<tx:method name="*" />
		</tx:attributes>
	</tx:advice>
	
	<bean id="sqlsession" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="configLocation" value="classpth:sql-map-config.xml"/>
	</bean>
	
	<bean class="org.mybatis.spring.SqlSessionTemplate"> 
		<!-- 생성자 의존 주입 -->
		<constructor-arg ref="sqlSession"></constructor-arg>
	</bean>
	
	<aop:config>
		<aop:pointcut expression="execution(* com.springbook.biz..*(..))" id="txPointcut"/> <!-- biz 하위의 모든 메소드를 수정하겠다 -->
		
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
	</aop:config>
	
	
</beans>

 

 

 

JSON 형식으로 값 반환

 

presentation-layer.xml

	<!-- HttpMessageConverter를 구현한 모든 변환기가 생성된다 -->
	<!-- 자바객체를 JSON응답 보디로 변환할 때는 MappingJackson2HttpMessageConverter를 사용한다 -->
	<!-- 스프링 컨테이너가 어노테이션 처리를 해준다, 우리가 직접 MappingJackson2HttpMessageConverter을 사용하는 것이 아님.-->
	<mvc:annotation-driven></mvc:annotation-driven>

 

Boardcontroller.java

	// 글 목록 JSON으로 변환
	@RequestMapping(value = "/dataTransform.do")
	// @ResponseBody 어노테이션을 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하며 클라이언트로 전송한다
	@ResponseBody // 자바형식을 제이슨형식으로 바꿔달라고 요청
	public List<BoardVO> dataTransform(BoardVO vo){
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		List<BoardVO> boardList = boardService.getBoardList(vo);
		return boardList;
	}

 

JSON 형식으로 값을 받아오는 화면

getBoardListJson.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>
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
table {
	width: 100%;
	border-collapse: collapse;
}

th, td {
	border: 1px solid #dddddd;
	text-align: left;
	padding: 8px;
}

th {
	background-color: #f2f2f2;
}
</style>

<script>
	$(document).ready(function() {
		$.ajax({
			url : 'dataTransform.do',
			method : 'GET',
			dataType : 'json',
			success : function(data) {
				var tableBody = $('#boardTable tbody');
				data.forEach(function(item) {
					var row = $('<tr></tr>');
					row.append('<td>' + item.seq + '</td>');
					row.append('<td>' + item.title + '</td>');
					row.append('<td>' + item.writer + '</td>');
					row.append('<td>' + item.content + '</td>');
					row.append('<td>' + item.cnt + '</td>');
					tableBody.append(row);
				});
			},
			error : function(xhr, status, error) {
				console.error('Error fetching data:', error);
			}
		});
	});
</script>

</head>
<body>
	<table id="boardTable">
		<thead>
			<tr>
				<td>번호</td>
				<td>제목</td>
				<td>작성자</td>
				<td>내용</td>
				<td>조회수</td>
			</tr>
		</thead>
		<tbody>
			<!-- 값을 받아오는 곳 -->
		</tbody>
	</table>
</body>
</html>

 

 

페이징 기능 추가

페이징 기능 추가를 과제로 해봤는데 너무 어려웠다ㅠ 잘 동작하지 않았고 챗 GPT한테 물어보며 코드를 수정하는 바람에 더 복잡해졌다.

하다 너무 어려우면 했던 걸 다시 복습하는 게 나을 것 같다.

이걸 잘 못한 이유도 결국 전에 코드를 내가 다 짠 게 아니라 강사님 코드를 따라 치고 내 것으로 못 만들어서 그런거니..

각설하고 일단 잘못된 코드라도 기록해 놓는다. 또 수정하다 보면 어디서 뭐가 잘못됐는지 잊혀지니 여기에 써 놓기로.

 

∨ 페이징 기능 추가 전 BoardDAOSpring.java 코드

더보기
package com.springbook.biz.board.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

// 비즈니스 계층에서 사용할 수 있도록 빈에 등록
@Repository
public class BoardDAOSpring {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	// 상수형태로 만들어 두었다.
	private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
			+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";
	

	private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
	private final String BOARD_DELETE = "delete board where seq=?";
	private final String BOARD_GET = "select * from board where seq=?";
	private final String BOARD_LIST = "select * from board order by seq desc";
	
	// 검색기능
	private final String BOARD_LIST_T = "select * from board where title like '%'||?||'%' order by seq desc";
	private final String BOARD_LIST_C = "select * from board where content like '%'||?||'%' order by seq desc";
	
	// ---------- update() 구문 사용 ----------
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 insertBoard() 기능 처리");
		// insert를 springJDBC에서는 update가 처리, try catch문 사용 안해도 됨.
		// 기존 jdbc 에서 사용한 '?' 대신 순서대로 객체를 가지고 와 적어준다.
		// jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
		jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
	}
	
	// 글 수정
	public void updateBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 updateBoard() 기능 처리");
		jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 deleteBoard() 기능 처리");
		jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
	}
	
	// ---------- queryForObject(), query() 구문 사용 ----------
	
	// 글 상세 조회
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 getBoard() 상세 보기  처리");
		
		// 배열로 값을 받기 때문에 배열에 넣어준다
		Object[] args= {vo.getSeq()};
		
		// return jdbcTemplate.queryForObject(sql, args, rowMapper);
		return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
	}
	
	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> springJDBC로 getBoardList() 기능 처리");
		
		Object[] args = {vo.getSearchKeyword()};
		
		if (vo.getSearchCondition().equals("TITLE")) {
			return jdbcTemplate.query(BOARD_LIST_T, args, new BoardRowMapper());
		} else if (vo.getSearchCondition().equals("CONTENT")) {
			return jdbcTemplate.query(BOARD_LIST_C, args, new BoardRowMapper());
		}
		return null;
		
	}
	

}

 

 

동작 되지 않는 코드

 BoardController.java

더보기
package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
//import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
//import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.board.PageDTO;

//import oracle.net.aso.l;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	// private BoardDAO boardDAO;
	private BoardService boardService;
	
	// 글 목록 JSON으로 변환
	@RequestMapping(value = "/dataTransform.do")
	// @ResponseBody 어노테이션을 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하며 클라이언트로 전송한다
	@ResponseBody // 자바형식을 제이슨형식으로 바꿔달라고 요청
	public List<BoardVO> dataTransform(BoardVO vo){
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		List<BoardVO> boardList = boardService.getBoardList(vo);
		return boardList;
	}
	
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록	
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) throws IllegalStateException, IOException { // BoardVO vo가 커멘드 객체
		//boardDAO.insertBoard(vo);
		
		// 파일 업로드
		MultipartFile uploadFile = vo.getUploadFile();
		if (!uploadFile.isEmpty()) {
			String fileName = uploadFile.getOriginalFilename();
			uploadFile.transferTo(new File("c://work//uploads//" + fileName)); // 파일 위치 경로
		}
		
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// --------- 페이징 ---------
	 @GetMapping("/paging")
     public String paging(Model model, 
    		 @RequestParam(value = "page" , required = false , defaultValue = "1") int page){
         int pageSize = 5;
		 List<BoardVO> pagingList = boardService.pageList(page,pageSize);
         PageDTO pageDTO = boardService.pagingParam(page, pageSize);
         model.addAttribute("boardList", pagingList); // pagingList -> 한 페이지에 들어갈 게시글의 갯수를 지정
         model.addAttribute("paging" , pageDTO); // 한 번에 몇 개의 페이지를 보이게 할 것인지에 대한 설명

         return "paging";
     }
 
	
	
	
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		//boardDAO.updateBoard(vo);
		boardService.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo/* , BoardDAO boardDAO */) {
		//boardDAO.deleteBoard(vo);
		boardService.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
		
		model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
			
		if(vo.getSearchCondition() == null) {
			vo.setSearchCondition("TITLE");
		}
		if(vo.getSearchKeyword() == null) {
			vo.setSearchKeyword("");
		}
		
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체가 아닌 경우
	/*
	 * @RequestMapping(value = "/getBoardList.do") public String
	 * getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
	 * "TITLE",required = false) String condition,
	 * 
	 * @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
	 * false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
	 * 
	 * System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
	 * keyword);
	 * 
	 * model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
	 * "getBoardList.jsp"; }
	 */
	
}

 BoardService

더보기
package com.springbook.biz.board;

import java.util.List;

public interface BoardService {
	// crud

	// 글 등록
	void insertBoard(BoardVO vo);

	// 글 수정
	void updateBoard(BoardVO vo);

	// 글 삭제
	void deleteBoard(BoardVO vo);

	// 글 상세조회
	BoardVO getBoard(BoardVO vo);

	// 글 목록 조회
	List<BoardVO> getBoardList(BoardVO vo);

	// 페이징 메소드
	List<BoardVO> pageList(int page, int pageSize);

	PageDTO pagingParam(int page, int pageSize);

}

 BoardServiceImpl

더보기
package com.springbook.biz.board.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.PageDTO;
import com.springbook.biz.board.boardRepository;

import jdk.nashorn.internal.ir.BlockLexicalContext;


@Service("boardService")
public class BoardServiceImpl implements BoardService {

	// boardDAO를 의존 주입해야 한다.
	@Autowired
	private BoardDAOSpring boardDAO;
	
    @Autowired
    private BoardMapper boardMapper;
	
	public BoardServiceImpl() {
	}
	
	

	@Override
	public void insertBoard(BoardVO vo) {
		
		boardDAO.insertBoard(vo);

	}

	@Override
	public void updateBoard(BoardVO vo) {

		boardDAO.updateBoard(vo);
	}

	@Override
	public void deleteBoard(BoardVO vo) {

		boardDAO.deleteBoard(vo);
	}

	@Override
	public BoardVO getBoard(BoardVO vo) {

		return boardDAO.getBoard(vo);
	}

	@Override
	public List<BoardVO> getBoardList(BoardVO vo) {

		return boardDAO.getBoardList(vo);
	}

    @Override
    public List<BoardVO> pageList(int page, int pageSize) {
        int pageStart = (page - 1) * pageSize;
        return boardMapper.pageList(pageStart, pageSize);
    }

    @Override
    public PageDTO pagingParam(int page, int pageSize) {
        int boardCount = boardMapper.boardCount();
        int maxPage = (int) Math.ceil((double) boardCount / pageSize);
        int startPage = ((int) Math.ceil((double) page / blockLimit) - 1) *  blockLimit + 1;
        int endPage = startPage + blockLimit - 1;
        if (endPage > maxPage) {
            endPage = maxPage;
        }

        PageDTO pageDTO = new PageDTO();
        pageDTO.setPage(page);
        pageDTO.setStartPage(startPage);
        pageDTO.setMaxPage(maxPage);
        pageDTO.setEndPage(endPage);
        return pageDTO;
    }
    
}

BoardMapper

더보기
package com.springbook.biz.board;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface BoardMapper {

    @Select("SELECT * FROM board ORDER BY seq DESC LIMIT #{pageStart}, #{pageSize}")
    List<BoardVO> pageList(@Param("pageStart") int pageStart, @Param("pageSize") int pageSize);

    @Select("SELECT COUNT(*) FROM board")
    int boardCount();

    // 나머지 메서드들은 기존과 동일
}

 

정작 BoardDAOSpring은 수정하지 않았는데 접근 자체가 잘못된 것 같다.

다시 해보기 ㅠㅠ

 


MyBatis

  • 쿼리문을 별도 관리, 분리한다

 

파일 만들기

 

여기서 next 를 누르고 조금 기다리면

이런 화면이 나온다

이 파란 부분 선택,

이렇게 설정해 파일을 만든다.

그 후 새로 만든 파일 new → 소스 폴더 누르고 stc/main/java 파일 만들기 → ojdbc6 (맥은 11) 연결하고 톰캣 서버 연결도 해주기.

 

maven 에서 mybatis, ibatis-core 라이브러리 두 개를 pom.xml에 추가한다.

 

MyBatis 에서는 BoardDAO에서 쓴 쿼리문을 그대로 사용,

기존 BoardDAO에서 ? 처리된 것을 기존에는 VO를 받아 처리했다면 여기서는 자동으로 VO를 받아와 #{}로 표기한다. 여기서는 VO.getTitle이런 식으로 쓰지 않음.

#{title} 이렇게 표기함으로서 의미를 함축

 

board-mapping.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="BoardDAO">

	<!-- 글 등록 -->
	<insert id="insertBoard">
		insert into board (seq,title,writer,content)
		values ((select nvl(max(seq),0) + 1 from board), #{title}, #{writer}, #{content})
	</insert>
	
	<!-- 글 수정 -->
	<update id="updateBoard">
		update board set title=#{title}, content=#{content}, where seq=#{seq}
	</update>
	
	<!-- 글 삭제 -->
	<delete id="deleteBoard">
		delete board where seq=#{seq}
	</delete>
	
	<!-- 글 상세 조회 -->
	<select id="getBoard" resultType="board">
		select * from board where seq=#{seq}
	</select>
	
	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board">
		select * from board where title like '%'||#{searchKeyword}||'%' 
		order by seq desc
	</select>
	
</mapper>

 

태그 속성 자체에 기능의 이름이 붙으며 쿼리문 사용이 보다 직관적이다.

 

여러 개의 insert 구문을 만들 수 있는데 이를 구분하는 것이 id값

 

update, delete 등 다른 것도 마찬가지.
id값으로 구분하고, <mapper namespace="BoardDAO"> 의 namespace를통해 접근한다.

 

VO 객체를 통해 값을 가져오고, VO 객체를 통해 값을 돌려줘야 하는데 여기서는

resultType="” 이게 그 역할을 해준다.

데이터베이스 설정 정보도 만들어줘야 한다.

 

db.properties 파일 만들어서

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1522:orcl1
jdbc.username=scott
jdbc.password=tiger

 

sql-map-config 에서는 DB 정보를 사용하기 위해 DB 정보가 담겨있는 db.properties 파일 연결해주기.

<properties resource="db.properties" />

 

sql-map-config 전문

<?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 파일 설정 -->
	<properties resource="db.properties" />

	<!-- Alias 설정 -->
	<typeAliases>
		<typeAlias alias="board"
			type="com.springbook.biz.board.BoardVO" />
	</typeAliases>

	<!-- DataSource 설정, 트랜잭션 연결 -->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
			<property name="driver" value="${jdbc.dirver}"/>
			<property name="url" value="${jdbc.url}"/>
			<property name="username" value="${jdbc.username}"/>
			<property name="password" value="${jdbc.password}"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- Sql Mapper 설정 -->
	<mappers>
		<mapper resource="mappings/board-mapping.xml" />
	</mappers>

</configuration>

에서 <typeAlias alias="board" type="com.springbook.biz.board.boardVO"/>는 BoardVO를 가리킨다.

 

type="com.springbook.biz.board.boardVO" 을 지정해줌으로서

BoardVO를 board라고 명명하고

board-mapping.xml에서 BoardVO를 board라고 쓸 수 있게 해준다.

 

SQL 이랑 연결이 된다는 것이 직접적인 트렌잭션, 쿼리문 처리가 가능하다는 것.

 

SqlSessionFactoryBean.java

package com.springbook.biz.util;

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;

public class SqlSessionFactoryBean {
	// SQL에 연결
	// 싱글톤 패턴
	// IO 스트림 관련 작업은 다 예외 처리 필요
	private static SqlSessionFactory sessionFactory = null;
	
	static {
		try {
			if (sessionFactory == null) {
				Reader reader = Resources.getResourceAsReader("sql-map-config.xml");
				sessionFactory = new SqlSessionFactoryBuilder().build(reader);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	// SqlSession 정보를 리턴 받으면 sql 정보를 쓸 수 있다.
	public static SqlSession getSqlSessionInstance() {
		
		return sessionFactory.openSession();
	}
}

 

BoardDAO.java

package com.springbook.biz.board.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.util.SqlSessionFactoryBean;

public class BoardDAO {
	
	// SqlSession 타입 mybatis은 xml의 정보를 다 가지고 있다. 
	private SqlSession mybatis;
	
	public BoardDAO() {
		mybatis = SqlSessionFactoryBean.getSqlSessionInstance();
	}
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		mybatis.insert("BoardDAO.insertBoard", vo); 
		mybatis.commit();
	}
	
	// 글 수정
	public void  updateBoard(BoardVO vo) {
		mybatis.update("BoardDAO.updateBoard", vo);
		mybatis.commit();
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		
	}
	
	// 글 상세조회
	public BoardVO getBoard(BoardVO vo) {
		
		return null;
	}
	
	// 글 목록 조회
	public List<BoardDAO> getBoardList(BoardVO vo) {
		
		return null;
	}
}

 

전체적인 파일 구조

 


일단 맥북에서

복습하며 json 형식으로 값을 받아와 목록을 만들었다.

 

페이징부터.. 이것저것 너무 할게 많다!

스프링 컨트롤러 이용하기 복습)

web.xml 에 정보 등록

  <servlet>
       <servlet-name>action</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/config/presentation-layer.xml</param-value>
      </init-param>
  </servlet>

위 코드를 통해 presentation-layer.xml 에 컨트롤러, 핸들러, 뷰리저버 정보를 저장한다고 정보를 등록한다.

 


프론트 컨트롤러 DAO 에 직접 접근이 아니라

비즈니스 계층을 통해 액션 컨트롤러로 접근하는 방식으로 수정

 

스프링컨테이너 안에 보더 서비스, 보더 컨테이너

보더 서비스를 보더 컨테이너 안에 주입.

프론트 컨트롤러의 요청에 의해서 보더컨테이너는 보더 서비스를 오토와이어

 

BoardController.java

package com.springbook.view.board;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	// private BoardDAO boardDAO;
	private BoardService boardService;
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) {
		//boardDAO.insertBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		//boardDAO.updateBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo) {
		//boardDAO.deleteBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, Model model) {
		
		model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo, Model model) {
			
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
	
}

이렇게 하고 실행하면 실행되지 않음.

BoardController의 ‘private BoardService boardService;’ 가 생성되지 않았기 때문.

 

web.xml 에 추가해야 ‘private BoardService boardService;’ 를 읽어올 수 있다.

   <context-param> 
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
   </context-param>
   
   <listener>
   	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>

 

이렇게 하고 index.jsp를 실행하면 실행이 잘 된다.

‘springJDBC로 getBoardList() 기능 처리’ 라는 메세지도 출력된다.

메모리에 할당되는 시점 때문에 web.xml에 저렇게 세팅을 해두지 않으면 정상적으로 작동되지 않는다.

 

원래 컨트롤러에서는 직접 DAO를 커멘드 객체로 만들었다.

이걸 다 지우고 비즈니스 계층으로 만듦. 다형성을 이용하기 위한 것.

기존의 방식으로 하면 수정, 유지보수가 어렵다. DAO를 쓴 부분을 다 수정해야 하기 때문이다.

 

BoardComtroller.java

	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	// private BoardDAO boardDAO;
	private BoardService boardService;

이렇게 비즈니스 계층을 만듦으로서 유지 보수가 용이해진다.

 

수정된 전체 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  
  <!-- 한글깨짐 방지 -->
  <filter>
      <filter-name>characterEncoding</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <init-param>
         <param-name>encoding</param-name>
         <param-value>UTF-8</param-value>
      </init-param>
   </filter>

   <filter-mapping>
      <filter-name>characterEncoding</filter-name>
      <url-pattern>*.do</url-pattern>
   </filter-mapping>
   
   <context-param> 
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
   </context-param>
   
   <listener>
   	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
  
  <servlet>
       <servlet-name>action</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/config/presentation-layer.xml</param-value>
      </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

 


 

검색기능 구현

 

내용이나 제목으로 검색하면 그에 맞는 목록이 검색되게 해야 한다.

 

BoardDAO.java

package com.springbook.biz.board.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.common.JDBCUtil;

@Repository("boardDAO")
public class BoardDAO {
	private Connection conn = null;
	private PreparedStatement stmt = null;
	private ResultSet rs = null;

	// SQL 명령어

	// 상수형태로 만들어 두었다.
	private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
			+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";

	private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
	private final String BOARD_DELETE = "delete board where seq=?";
	private final String BOARD_GET = "select * from board where seq=?";
	private final String BOARD_LIST = "select * from board order by seq desc";
	// 검색기능
	private final String BOARD_LIST_T = "select * from board where title like '%'||?||'%' order by seq desc";
	private final String BOARD_LIST_C = "select * from board where content like '%'||?||'%' order by seq desc";

	// 글 등록
	public void insertBoard(BoardVO vo) {
		System.out.println("===> JDBC로 insertBoard() 기능 처리");
		try {

			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_INSERT);
			stmt.setString(1, vo.getTitle());
			stmt.setString(2, vo.getWriter());
			stmt.setString(3, vo.getContent());
			stmt.executeUpdate();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
	}

	// 글 수정
	public void updateBoard(BoardVO vo) {
		System.out.println("===> JDBC로 updateBoard() 기능 처리");
		
		try {
			
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_UPDATE);
			stmt.setString(1, vo.getTitle());
			stmt.setString(2, vo.getContent());
			stmt.setInt(3, vo.getSeq());
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
	}

	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> JDBC로 deleteBoard() 기능 처리");
		
		try {
			
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_DELETE);
			stmt.setInt(1, vo.getSeq());
			stmt.executeUpdate();
			
		} catch (Exception e){
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
		
	}

	// 글 상세 조회
	public BoardVO getBoard(BoardVO vo) {
		
		BoardVO board = new BoardVO();
		System.out.println("===> JDBC로 getBoard() 상세 보기  처리");
		
		try {

			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_GET);
			stmt.setInt(1, vo.getSeq());
			rs = stmt.executeQuery();
			
			if (rs.next()) {
				
				board.setSeq(rs.getInt("SEQ"));
				board.setTitle(rs.getString("TITLE"));
				board.setWriter(rs.getString("WRITER"));
				board.setContent(rs.getString("CONTENT"));
				board.setRegDate(rs.getDate("REGDATE"));
				board.setCnt(rs.getInt("CNT"));
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(rs, stmt, conn);
		}
		
		return board;
	}

	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> JDBC로 getBoardList() 기능 처리");

		List<BoardVO> boardlist = new ArrayList<>();

		try {

			conn = JDBCUtil.getConnection();
			
			// 검색 기능
			if (vo.getSearchCondition().equals("TITLE")) {
				stmt = conn.prepareStatement(BOARD_LIST_T);
			} else if (vo.getSearchCondition().equals("CONTENT")) {
				stmt = conn.prepareStatement(BOARD_LIST_C);
			}
			stmt.setString(1,  vo.getSearchKeyword());
			rs = stmt.executeQuery();

			while (rs.next()) {
				BoardVO board = new BoardVO();
				board.setSeq(rs.getInt("SEQ"));
				board.setTitle(rs.getString("TITLE"));
				board.setWriter(rs.getString("WRITER"));
				board.setContent(rs.getString("CONTENT"));
				board.setRegDate(rs.getDate("REGDATE"));
				board.setCnt(rs.getInt("CNT"));

				boardlist.add(board);
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}

		return boardlist;
	}

}

 

BoardDAOSpring.java - 실질적으로 현재 연결된 DAO

package com.springbook.biz.board.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

// 비즈니스 계층에서 사용할 수 있도록 빈에 등록
@Repository
public class BoardDAOSpring {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	// 상수형태로 만들어 두었다.
	private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
			+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";
	

	private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
	private final String BOARD_DELETE = "delete board where seq=?";
	private final String BOARD_GET = "select * from board where seq=?";
	private final String BOARD_LIST = "select * from board order by seq desc";
	
	// 검색기능
	private final String BOARD_LIST_T = "select * from board where title like '%'||?||'%' order by seq desc";
	private final String BOARD_LIST_C = "select * from board where content like '%'||?||'%' order by seq desc";
	
	// ---------- update() 구문 사용 ----------
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 insertBoard() 기능 처리");
		// insert를 springJDBC에서는 update가 처리, try catch문 사용 안해도 됨.
		// 기존 jdbc 에서 사용한 '?' 대신 순서대로 객체를 가지고 와 적어준다.
		// jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
		jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
	}
	
	// 글 수정
	public void updateBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 updateBoard() 기능 처리");
		jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 deleteBoard() 기능 처리");
		jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
	}
	
	// ---------- queryForObject(), query() 구문 사용 ----------
	
	// 글 상세 조회
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 getBoard() 상세 보기  처리");
		
		// 배열로 값을 받기 때문에 배열에 넣어준다
		Object[] args= {vo.getSeq()};
		
		// return jdbcTemplate.queryForObject(sql, args, rowMapper);
		return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
	}
	
	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> springJDBC로 getBoardList() 기능 처리");
		
		Object[] args = {vo.getSearchKeyword()};
		
		if (vo.getSearchCondition().equals("TITLE")) {
			return jdbcTemplate.query(BOARD_LIST_T, args, new BoardRowMapper());
		} else if (vo.getSearchCondition().equals("CONTENT")) {
			return jdbcTemplate.query(BOARD_LIST_C, args, new BoardRowMapper());
		}
		return null;
		
	}
	

}

 

BoardController.java

package com.springbook.view.board;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	private BoardService boardService;
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}
	
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) {
		//boardDAO.insertBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo) {
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, Model model) {
		
		model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo, Model model) {
			
		if(vo.getSearchCondition() == null) {
			vo.setSearchCondition("TITLE");
		}
		if(vo.getSearchKeyword() == null) {
			vo.setSearchKeyword("");
		}
		
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
}

 

getBoardList.jsp 에서 searchCondition 스펠링 수정, BoardVO에서도 수정해줬다.

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

<% %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 목록</h1>
		<h3>
			${userName }님! 게시판에 오신 걸 환영합니다! <a href="logout.do">log-out</a>
		</h3>

		<form action="getBoardList.do" method="post">
			<table border="1" cellpadding="0" cellspacing="0" width="700">
				<tr>
					<td align="right">
					<select name="searchCondition">
							
							<c:forEach items="${conditionMap }" var="option">
								<option value="${option.value }">${option.key }
							</c:forEach>
							
					</select> 
					<input name="searchKeyword" type="text" /> 
					<input type="submit" value="검색" /></td>
				</tr>
			</table>
		</form>

		<table border="1" cellpadding="0" cellspacing="0" width="700">
			<tr>
				<th bgcolor="orange" width="100">번호</th>
				<th bgcolor="orange" width="200">제목</th>
				<th bgcolor="orange" width="150">작성자</th>
				<th bgcolor="orange" width="150">등록일</th>
				<th bgcolor="orange" width="100">조회수</th>
			</tr>

			<c:forEach items="${boardList }" var="board">

				<tr>
					<td>${board.seq }</td>
					<td><a href="getBoard.do?seq=${board.seq }"> ${board.title }</a>
					</td>
					<td>${board.writer }</td>
					<td>${board.regDate }</td>
					<td>${board.cnt}</td>
				</tr>
			</c:forEach>
		</table>

		<br> <a href="insertBoard.jsp">새글 등록</a>
	</center>
</body>
</html>

 

BoardVO.java

package com.springbook.biz.board;

import java.util.Date;

public class BoardVO {
	private int seq;
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;
	private String searchCondition;
	private String searchKeyword;
	

	public int getSeq() {
		return seq;
	}
	public void setSeq(int seq) {
		this.seq = seq;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	public String getSearchKeyword() {
		return searchKeyword;
	}
	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}
	
	@Override
	public String toString() {
		return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ", content=" + content + ", regDate="
				+ regDate + ", cnt=" + cnt + "]";
	}
}

 


 

파일 업로드, 다운로드

 

insertBoard에 파일을 업로드할 수 있는 부분을 추가

<%@ 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>
	<center>
		<h1>글 등록</h1>
		<a href="logout.do">Log-out</a>
		<hr>
		<form action="insertBoard.do" method="post" enctype="multipart/form-data">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name="title" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left"><input type="text" name="writer" size="10" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">업로드</td>
					<td align="left">
					<input type="file" name="uploadFile"/></td>
				</tr>
				
				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="새 글 등록" />
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="getBoardList.do">글 목록 가기</a>
	</center>
</body>
</html>

 

파일 업로드 라이브러리 common fileupload 사용

 

BoardWeb/pom.xml에 추가

	<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
	<dependency>
	    <groupId>commons-fileupload</groupId>
	    <artifactId>commons-fileupload</artifactId>
	    <version>1.3.1</version>
	</dependency>

 

presentation-layer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 스캔태그를 사용해서 스캔처리, 모두 어노테이션으로 해결 -->
	<context:component-scan base-package="com.springbook.view"></context:component-scan>
	
	<!-- 파일업로드 빈 설정, 빈 등록 시 id는 스프링이 읽을 수 있는 방식으로 정해져 있다.-->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="maxUploadSize" value="100000"></property>
	</bean>

</beans>

 

BoardVO.java

getOriginalFilename(), transferTo(), isEmpyt() 메소드를 사용해 파일 업로드

package com.springbook.biz.board;

import java.util.Date;

import org.springframework.web.multipart.MultipartFile;

public class BoardVO {
	private int seq;
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;
	private String searchCondition;
	private String searchKeyword;
	// 파일 변수를 담는 멤버변수
	// web.xml의 빈에서 값을 할당해준다 
	private MultipartFile uploadFile; // getOriginalFilename(), transferTo(), isEmpyt()
	

	public int getSeq() {
		return seq;
	}
	public void setSeq(int seq) {
		this.seq = seq;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	public String getSearchKeyword() {
		return searchKeyword;
	}
	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}
	
	public MultipartFile getUploadFile() {
		return uploadFile;
	}
	public void setUploadFile(MultipartFile uploadFile) {
		this.uploadFile = uploadFile;
	}
	
	@Override
	public String toString() {
		return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ", content=" + content + ", regDate="
				+ regDate + ", cnt=" + cnt + "]";
	}
}

 

BoardController.java

package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	// private BoardDAO boardDAO;
	private BoardService boardService;
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록	
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) throws IllegalStateException, IOException { // BoardVO vo가 커멘드 객체
		//boardDAO.insertBoard(vo);
		
		// 파일 업로드
		MultipartFile uploadFile = vo.getUploadFile();
		if (!uploadFile.isEmpty()) {
			String fileName = uploadFile.getOriginalFilename();
			uploadFile.transferTo(new File("c://work//uploads//" + fileName)); // 파일 위치 경로
		}
		
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		//boardDAO.updateBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo/* , BoardDAO boardDAO */) {
		//boardDAO.deleteBoard(vo);
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
		
		model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
			
		if(vo.getSearchCondition() == null) {
			vo.setSearchCondition("TITLE");
		}
		if(vo.getSearchKeyword() == null) {
			vo.setSearchKeyword("");
		}
		
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체가 아닌 경우
	/*
	 * @RequestMapping(value = "/getBoardList.do") public String
	 * getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
	 * "TITLE",required = false) String condition,
	 * 
	 * @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
	 * false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
	 * 
	 * System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
	 * keyword);
	 * 
	 * model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
	 * "getBoardList.jsp"; }
	 */
	
}

파일이 업로드 된다. 추가적으로 업로드 된 파일 확인 등은 스스로 추가해볼 것.

 


이번 주까지 스프링 마무리하고 스프링 부트 나갈 것.

스프링 부트 : 스프링으로 애플리케이션을 만들 때 필요한 설정을 간편하게 처리해주는 별도의 프레임워크

 

다음 달 초, 조가 나온다. 디자인부터 시작.


 

데이터 변환

jackson 라이브러리를 사용해서 제이슨 형태로 데이터 받기

 

 

BoardWeb/pom.xml에 추가

	<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
	<dependency>
	    <groupId>com.fasterxml.jackson.core</groupId>
	    <artifactId>jackson-databind</artifactId>
	    <version>2.9.7</version>
	</dependency>

 

presentation-layer.xml 에서 Namespace에 들어가 mvc 체크하기

 

presentation-layer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
		
	<!-- 스캔태그를 사용해서 스캔처리, 모두 어노테이션으로 해결 -->
	<context:component-scan base-package="com.springbook.view"></context:component-scan>
	
	<!-- HttpMessageConverter를 구현한 모든 변환기가 생성된다 -->
	<!-- 자바객체를 JSON응답 보디로 변환할 때는 MappingJackson2HttpMessageConverter를 사용한다 -->
	<!-- 스프링 컨테이너가 어노테이션 처리를 해준다, 우리가 직접 MappingJackson2HttpMessageConverter을 사용하는 것이 아님.-->
	<mvc:annotation-driven></mvc:annotation-driven>
	
	<!-- 파일업로드 빈 설정, 빈 등록 시 id는 스프링이 읽을 수 있는 방식으로 정해져 있다.-->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="maxUploadSize" value="100000"></property>
	</bean>

</beans>

 

제이슨 형식으로 글 목록을 변환 받은 것을 보기 위해 index.jsp에 a 태그를 추가했다.

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>
	<center>
		<h1>게시판 프로그램</h1>
		<hr>
		<a href="login.do">로그인</a>
		<br> 
		<br> 
		<a href="getBoardList.do">글 목록 바로가기</a>
		<br> 
		<br> 
		<a href="dataTransform.do">글 목록 변환</a>
		<hr>
	</center>
</body>
</html>

 

BoardController.java

package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
//import com.springbook.biz.board.impl.BoardDAO;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음 
	// 자동의존주입 방식으로 정보 주입
	@Autowired 
	// private BoardDAO boardDAO;
	private BoardService boardService;
	
	// 글 목록 JSON으로 변환
	@RequestMapping(value = "/dataTransform.do")
	// @ResponseBody 어노테이션을 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하며 클라이언트로 전송한다
	@ResponseBody // 자바형식을 제이슨형식으로 바꿔달라고 요청
	public List<BoardVO> dataTransform(BoardVO vo){
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		List<BoardVO> boardList = boardService.getBoardList(vo);
		return boardList;
	}
	
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록	
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) throws IllegalStateException, IOException { // BoardVO vo가 커멘드 객체
		//boardDAO.insertBoard(vo);
		
		// 파일 업로드
		MultipartFile uploadFile = vo.getUploadFile();
		if (!uploadFile.isEmpty()) {
			String fileName = uploadFile.getOriginalFilename();
			uploadFile.transferTo(new File("c://work//uploads//" + fileName)); // 파일 위치 경로
		}
		
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		//boardDAO.updateBoard(vo);
		boardService.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo/* , BoardDAO boardDAO */) {
		//boardDAO.deleteBoard(vo);
		boardService.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
		
		model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
			
		if(vo.getSearchCondition() == null) {
			vo.setSearchCondition("TITLE");
		}
		if(vo.getSearchKeyword() == null) {
			vo.setSearchKeyword("");
		}
		
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체가 아닌 경우
	/*
	 * @RequestMapping(value = "/getBoardList.do") public String
	 * getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
	 * "TITLE",required = false) String condition,
	 * 
	 * @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
	 * false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
	 * 
	 * System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
	 * keyword);
	 * 
	 * model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
	 * "getBoardList.jsp"; }
	 */
	
}

 

 

 

 


 

맥북에도 스프링을 깔고 기존에 쓴 코드들을 다 가지고 왔다.

실행해보니 글이 삭제되지 않아서 보니까 BoardController에 오타가 있어서 수정했다.

휴 다행.. 이제 파일 업로드를 할 경로를 설정하고 폴더도 만들어야 한다.

 

 

최종적인 파일 구조

 

com.springbook.view.controller 의 컨트롤러는 이제 사용하지 않는다.

각 컨트롤러에 이젠 스프링에서 제공하는 컨트롤러와 ModelAndView 서블릿을 임포트해서 사용한다.

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

 

 

전체 코드

GetBoardController

package com.springbook.view.user;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;


public class GetBoardController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		System.out.println("글 상세 조회 처리");
		
		String seq = request.getParameter("seq");

		BoardVO vo = new BoardVO();
		BoardDAO dao = new BoardDAO();
		
		vo.setSeq(Integer.parseInt(seq));
		
		BoardVO board = dao.getBoard(vo);
		
		// 데이터를 session에 담아 최종적으로 "getBoard.jsp"로 페이지 이동
		//HttpSession session = request.getSession();
		//session.setAttribute("board", board);
		
		//return "getBoard";
		
		ModelAndView mav = new ModelAndView();
		
		mav.addObject("board", board); // request 영역에 저장된다
		mav.setViewName("getBoard");

		return mav;
	}

}

 

GetBoardListController

package com.springbook.view.user;

import java.util.List;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;


public class GetBoardListController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("글 목록 검색 처리");
		
		BoardVO vo = new BoardVO();
		BoardDAO dao = new BoardDAO();
		
		List<BoardVO> boardList = dao.getBoardList(vo);
		
		// 목록을 session에 담아 최종적으로 "getBoardList.jsp"로 페이지 이동
		// HttpSession session = request.getSession();
		// session.setAttribute("boardList", boardList);
		
		// return "getBoardList";
		
		ModelAndView mav = new ModelAndView();
		
		mav.addObject("boardList", boardList); // request 영역에 저장된다
		//mav.setViewName("getBoardList.jsp"); // WEB-INF/board/getBoardList.jsp.jsp
		mav.setViewName("getBoardList"); // WEB-INF/board/getBoardList.jsp
		
		return mav;
	}

}

 

InsertBoardController

package com.springbook.view.user;

import java.io.UnsupportedEncodingException;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;


public class InsertBoardController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		System.out.println("글등록 처리");
		
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		String title = request.getParameter("title");
		String writer = request.getParameter("writer");
		String content = request.getParameter("content");

		BoardDAO dao = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setTitle(title);
		vo.setWriter(writer);
		vo.setContent(content);
		
		dao.insertBoard(vo);
		
		
		ModelAndView mav = new ModelAndView();
		
		// mav.setViewName("getBoardList.do");
		mav.setViewName("redirect:getBoardList.do");
		
		return mav;
		
		// return "getBoardList.do";
	}

}

 

LoginController

package com.springbook.view.user;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;

public class LoginController implements Controller {

	// 표준화
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println("로그인 처리");

		String id = request.getParameter("id");
		String password = request.getParameter("password");

		UserVO vo = new UserVO();
		vo.setId(id);
		vo.setPassword(password);

		UserDAO dao = new UserDAO();
		UserVO user = dao.getUser(vo);

		// 기존에는 세션에 필요한 데이터를 담았다.
		// 뷰 정보는 리턴 값에 담음.
		// 스프링 컨트롤러는 ModelAndView로 위 두 가지 일을 한번에 처리한다.
		ModelAndView mav = new ModelAndView();

		if (user != null) {
			mav.setViewName("redirect:getBoardList.do"); // WEB-INF/board/getBoardList.do.jsp 
			// redirect:는 viewResolver를 무시한다. 컨트롤러에 설정된 do로 가야하기 때문에 사용
		} else {
			mav.setViewName("redirect:login.jsp"); // WEB-INF/board/login.jsp.jsp
		}

		return mav;

//		   if(user != null) {
//			  HttpSession session = request.getSession();
//			  session.setAttribute("id", vo.getId());
//		      return "getBoardList.do"; 
//		   }else{
//		     return "login"; // 실패하면 이동할 대상, 여기서는 문자열로만 받았다
//		   }

	}

}

 

LogoutController

package com.springbook.view.user;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;


public class LogoutController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("로그아웃 처리");
		
		//HttpSession session = request.getSession();
		//session.invalidate();
		
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("redirect:login.jsp");
		
		return mav;

	}

}

 

UpdateBoardController

package com.springbook.view.user;

import java.io.UnsupportedEncodingException;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

public class UpdateBoardController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("글수정 처리");
		
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		String seq = request.getParameter("seq");
		String title = request.getParameter("title");
		String content = request.getParameter("content");
		
		BoardDAO dao = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setSeq(Integer.parseInt(seq));
		vo.setTitle(title);
		vo.setContent(content);
		
		dao.updateBoard(vo); 
		
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("redirect:getBoardList.do");
		
		return mav;
		
		// return "getBoardList.do";
	}

}

 

DeleteBoardController

package com.springbook.view.user;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;


public class DeleteBoardController implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		System.out.println("글삭제 처리");
		
		String seq = request.getParameter("seq");

		BoardDAO dao = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setSeq(Integer.parseInt(seq));
		
		dao.deleteBoard(vo);
		
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("redirect:getBoardList.do");
		
		return mav;
	}

}

 

main> wedapp> WEB-INF> config> presentation-layer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean
		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/login.do">login</prop>
				<prop key="/getBoardList.do">getBoardList</prop>
				<prop key="/getBoard.do">getBoard</prop>
				<prop key="/insertBoard.do">insertBoard</prop>
				<prop key="/updateBoard.do">updateBoard</prop>
				<prop key="/deleteBoard.do">deleteBoard</prop>
				<prop key="/logout.do">logout</prop>
			</props>
		</property>
	</bean>

	<bean id="login" class="com.springbook.view.user.LoginController"></bean>
	<bean id="getBoardList" class="com.springbook.view.user.GetBoardListController"></bean>
	<bean id="getBoard" class="com.springbook.view.user.GetBoardController"></bean>
	<bean id="insertBoard" class="com.springbook.view.user.InsertBoardController"></bean>
	<bean id="updateBoard" class="com.springbook.view.user.UpdateBoardController"></bean>
	<bean id="deleteBoard" class="com.springbook.view.user.DeleteBoardController"></bean>
	<bean id="logout" class="com.springbook.view.user.LogoutController"></bean>
	
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/board/"></property>
	<property name="suffix" value=".jsp"></property>
	</bean>
</beans>

 


 

어노테이션을 사용한 스프링 MVC 사용

어노테이션 컨트롤러 사용하기

 

어노테이션 방식의 bean 등록을 해야 한다.

main> wedapp> WEB-INF> config> presentation-layer.xml 에서

Namespace에 들어가 context 체크

getBoard.jsp와 getBoardList을 다시 webapp으로 옮기기

viewResolver를 통해서 WEB-INF 안의 파일을 사용할 수 있었지만 이젠 주석 처리를 해 사용할 수 없으므로 파일을 옮겨야 한다.

 

수정된 presentation-layer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 스캔태그를 사용해서 스캔처리, 모두 어노테이션으로 해결 -->
	<context:component-scan base-package="com.springbook.view"></context:component-scan>

</beans>

 

 

InsertBoardController 만 스프링 컨트롤러를 어노테이션으로 수정했을 때 동작이 잘 되는지 확인해보았다. 값이 잘 들어가는 모습이다.

 

 

수정된 InsertBoardController

package com.springbook.view.user;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class InsertBoardController {

	// bean, mapping 객체의 역할을 아래 어노테이션이 해결
	@RequestMapping(value = "/insertBoard.do")
	public void insertBoard(HttpServletRequest request) {
		
		System.out.println("글등록 처리");

// 필터부분도 사용할 필요가 없다		
//		try {
//			request.setCharacterEncoding("UTF-8");
//		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		String title = request.getParameter("title");
		String writer = request.getParameter("writer");
		String content = request.getParameter("content");

		BoardDAO dao = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setTitle(title);
		vo.setWriter(writer);
		vo.setContent(content);
		
		dao.insertBoard(vo);
		
		
		
		
// ---------------------------------------------------
// 어노테이션을 사용하지 않고 스프링 컨트롤러를 사용했을 때 ModelAndView를 사용
		
//		ModelAndView mav = new ModelAndView();
//		mav.setViewName("redirect:getBoardList.do");
//		return mav;
		
	}

}

 

스프링 어노테이션을 사용해 더 간편하게 수정된 InsertBoardController

package com.springbook.view.user;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class InsertBoardController {

	// bean, mapping 객체의 역할을 아래 어노테이션이 해결
	@RequestMapping(value = "/insertBoard.do")
//	public void insertBoard(HttpServletRequest request) {
	public String insertBoard(BoardVO vo, BoardDAO dao) { // BoardVO vo -> command 객체 (spring container가 관리)
		// spring container는 BoardVO의 setter 메소드에 설정된 이름을 이용해 insertBoard.jsp의 id로 파라매터를 받아 처리해준다
		// setter 메소드와 id값 파라메터의 이름이 일치해야 한다는 것을 전제로 한다. 
		
		System.out.println("글 등록 처리");
		
		dao.insertBoard(vo);
		return "redirect:getBoardList.do";
		
	}

}

 

return "redirect:getBoardList.do"; 

// 기존에는 forward한 방식으로 되어 있어 새로고침하면 계속 새 글이 등록됨.
// 때문에 redirect: 를 이용해 새로운 페이지를 요청해 새로고침해도 새 글이 등록 되지 않게 처리

 

 

 

스프링 어노테이션을 사용해 더 간편하게 수정된 GetBoardListController.java

package com.springbook.view.user;

import java.util.List;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;


import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class GetBoardListController  {

	@RequestMapping(value = "/getBoardList.do")
	public ModelAndView getBoardList(BoardVO vo, BoardDAO dao, ModelAndView mav) {
		System.out.println("글 목록 검색 처리");
		
		mav.addObject("boardList", dao.getBoardList(vo));
		mav.setViewName("getBoardList.jsp"); 
		return mav;
	}

}

이렇게 수정 후 insertBoard.jsp 를 실행해 글을 올리면 목록에 잘 등록이 되는 것을 볼 수 있다.

 

스프링 어노테이션을 사용해 더 간편하게 수정된 GetBoardController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class GetBoardController{

	@RequestMapping(value = "/getBoard.do")
	public ModelAndView getBoard(BoardVO vo, BoardDAO dao, ModelAndView mav) {
		
		System.out.println("글 상세 조회 처리");
		
		mav.addObject("board", dao.getBoard(vo)); // request 영역에 저장된다
		mav.setViewName("getBoard.jsp");
		return mav;
		
	}

}

 

스프링 어노테이션을 사용해 더 간편하게 수정된 updateBoardController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class UpdateBoardController {

	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(BoardVO vo, BoardDAO dao) {
		System.out.println("글수정 처리");
		
		dao.updateBoard(vo); 
		
		return "redirect:getBoardList.do";
	}

}

 

스프링 어노테이션을 사용해 더 간편하게 수정된 DeleteBoardController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class DeleteBoardController {

	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO dao) {
		
		System.out.println("글삭제 처리");
		
		dao.deleteBoard(vo);
		
		return "redirect:getBoardList.do";
	}

}

 

스프링 어노테이션을 사용해 더 간편하게 수정된 LoginController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;

@Controller
public class LoginController {

	// 표준화
	@RequestMapping(value = "/login.do")
	public String login(UserVO vo, UserDAO userDAO) {

		System.out.println("로그인 처리");
		
		if(userDAO.getUser(vo) != null) {
			return "redirect:getBoardList.do";
		} else {
			return "login.jsp";
		}


	}

}

 

스프링 어노테이션을 사용해 더 간편하게 수정된 LogoutController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;


@Controller
public class LogoutController {

	@RequestMapping(value = "/logout.do")
	public String logout(HttpSession session) {
		
		System.out.println("로그아웃 처리");
		session.invalidate();
		
		return "login.jsp";

	}

}

로그아웃은 session에 있는 아이디 정보를 지워야 함으로 HttpSession session 을 사용해야 한다.

invalidate : 무효화 하다

 


forward 방식과 redirect 방식의 차이

 

forward 방식은 URL에 변화가 생기지 않는다.

서버 내부적으로 Controller가 View에게 작업을 넘기고 View가 jsp 파일을 렌더링하여 결과 페이지를 클라이언트에게 넘긴다. 이를 클라이언트는 알지 못하고 따라서 URL 요청이 바뀌지 않음.

redirect 방식은 URL에 변화가 생긴다.

새로운 경로로 요청을 보내 새로운 request, response가 생긴다.

DB에 변화를 주는 작업 (회원가입, 게시판 글쓰기 등) redirect

시스템 변화 X (단순 조회, 검색) forward

 

출처) 

 

[Servlet & JSP] Redirect vs forward 방식 비교

[Servlet & JSP] Redirect vs forward 방식 비교 현재 JSP & Servlet을 활용한 WEB 개발에 대해서 전체적으로 학습을 진행하고 있습니다. 그중에서 Redirect와 foward 개념에 대해서 정리해보고자 합니다. 또한 간단

kbj96.tistory.com


 

통합 컨트롤러

 

BoardController.java

package com.springbook.view.board;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class BoardController {
// 통합 컨트롤러

	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public ModelAndView getBoard(BoardVO vo, BoardDAO boardDAO, ModelAndView mav) {
		mav.addObject("board", boardDAO.getBoard(vo)); // Model 정보 저장
		mav.setViewName("getBoard.jsp"); // View 정보 저장
		return mav;
	}
	
	// 글 목록 검색
	@RequestMapping(value = "/getBoardList.do")
	public ModelAndView getBoardList(BoardVO vo, BoardDAO boardDAO, ModelAndView mav) {
		mav.addObject("boardList", boardDAO.getBoardList(vo)); // Model 정보 저장
		mav.setViewName("getBoardList.jsp"); // View 정보 저장
		return mav;
	}
	
}

기존 컨트롤러 다 주석 처리 후

이 컨트롤러로 동작 시켜 보면 잘 되는 것을 확인할 수 있다.

 


doget 방식과 dopost 방식

get 방식은 화면을 띄워주고 post 방식은 데이터를 처리

 

커맨드 객체 (Command Object)

  • HttpServletRequest를 통해 들어온 요청 값을 setter 메서드를 통해 객체에 정의되어있는 속성에 바인딩이 되는 객체
  • DTO, VO 클래스, setter 메서드를 가지고 있어야 한다.

= 클라이언트가 전달해주는 피라미터 데이터를 주입 받기 위해 사용

HttpServletRequest 나 RequestParam 을 사용하는 것보다 훨씬 간단하다.


 

요청을 통해 로그인 페이지 실행

 

loginController.java

package com.springbook.view.user;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;

@Controller
public class LoginController {

	// 표준화
	@RequestMapping(value = "/login.do", method = RequestMethod.GET)
	// @ModelAttribute("이름") 로 이름을 지정해줄 수도 있다. 
	public String loginView(@ModelAttribute("userVO") UserVO vo) { // UserVO vo 로 생성된 커맨드 객체는 request 영역에 저장, 객체 저장명 -> userVO
		System.out.println("로그인 화면으로 이동...");
		vo.setId("test");
		vo.setPassword("test1234");
		return "login.jsp";  // login.jsp가 실행될 때  setId, setPassword 값을 쓸 수있다 
	}
	
	
	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String login(UserVO vo, UserDAO userDAO, HttpSession session) {
		System.out.println("로그인 인증 처리...");
		if (userDAO.getUser(vo) != null) {
			// 로그인 유무 체크하기
			session.setAttribute("id", userDAO.getUser(vo).getId());
			session.setAttribute("userName", userDAO.getUser(vo).getName());
			return "getBoardList.do";
		}else {
			return "login.jsp";
		}
	}
	
	
	
	
//	public String login(UserVO vo, UserDAO userDAO) {
//
//		System.out.println("로그인 처리");
		
//		if(userDAO.getUser(vo) != null) {
//			return "redirect:getBoardList.do";
//		} else {
//			return "login.jsp";
//		}

}

 

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>
	<center>
		<h1>게시판 프로그램</h1>
		<hr>
		<a href="login.do">로그인</a>
		<br> <br> <br>
		<a href="getBoardList.do">글 목록 바로가기</a>
		<hr>
	</center>
</body>
</html>

 

 

 

효율성을 높이기 위해 ModelAndView 사용 대신 Model 을 사용한 컨트롤러

BoardController.java

package com.springbook.view.board;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class BoardController {
// 통합 컨트롤러

	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, BoardDAO boardDAO, Model model) {
		
		model.addAttribute("board", boardDAO.getBoard(vo));
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo, BoardDAO boardDAO, Model model) {
		
		model.addAttribute("boardList", boardDAO.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
}

 

login.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>
	<center>
		<form action="login.do" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange">아이디</td>
					<td>
						<input type="text" name="id" value="${userVO.id }">
					</td>
				</tr>
				<tr>
					<td bgcolor="orange">비밀번호</td>
					<td>
						<input type="password" name="password" value="${userVO.password }">
					</td>
				</tr>
				<tr>
					<td colspan="2" align="center">
						<input type="submit" value="로그인"></td>
				</tr>
			</table>
		</form>
	</center>
</body>
</html>

 

 

커멘드 객체가 아닌 경우, 검색 처리

 

BoardController에서)

	// 글 목록 검색
	// 커멘드 객체가 아닌 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(@RequestParam(value = "searchCondtion",defaultValue = "TITLE",required = false) String condition,
			@RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required = false) String keyword,
			BoardVO vo, BoardDAO boardDAO, Model model) {
		
		System.out.println("검색 조건" + condition);
		System.out.println("검색 단어" + keyword);
		
		model.addAttribute("boardList", boardDAO.getBoardList(vo));
		return "getBoardList.jsp";
	}

 


@ModelAttribute 의 특징을 사용해 검색 기능 옵션 선택 부분 수정

 

BoardController.java

package com.springbook.view.board;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller
public class BoardController {
// 통합 컨트롤러
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, BoardDAO boardDAO, Model model) {
		
		model.addAttribute("board", boardDAO.getBoard(vo));
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo, BoardDAO boardDAO, Model model) {
			
		model.addAttribute("boardList", boardDAO.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체가 아닌 경우
	/*
	 * @RequestMapping(value = "/getBoardList.do") public String
	 * getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
	 * "TITLE",required = false) String condition,
	 * 
	 * @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
	 * false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
	 * 
	 * System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
	 * keyword);
	 * 
	 * model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
	 * "getBoardList.jsp"; }
	 */
	
}

 

getBoardList.jsp

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

<% %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 목록</h1>
		<h3>
			${userName }님! 게시판에 오신 걸 환영합니다! <a href="logout.do">log-out</a>
		</h3>

		<form action="getBoardList.do" method="post">
			<table border="1" cellpadding="0" cellspacing="0" width="700">
				<tr>
					<td align="right">
					<select name="searchCondtion">
							
							<c:forEach items="${conditionMap }" var="option">
								<option value="${option.value }">${option.key }
							</c:forEach>
							
					</select> 
					<input name="searchKeyword" type="text" /> 
					<input type="submit" value="검색" /></td>
				</tr>
			</table>
		</form>

		<table border="1" cellpadding="0" cellspacing="0" width="700">
			<tr>
				<th bgcolor="orange" width="100">번호</th>
				<th bgcolor="orange" width="200">제목</th>
				<th bgcolor="orange" width="150">작성자</th>
				<th bgcolor="orange" width="150">등록일</th>
				<th bgcolor="orange" width="100">조회수</th>
			</tr>

			<c:forEach items="${boardList }" var="board">

				<tr>
					<td>${board.seq }</td>
					<td><a href="getBoard.do?seq=${board.seq }"> ${board.title }</a>
					</td>
					<td>${board.writer }</td>
					<td>${board.regDate }</td>
					<td>${board.cnt}</td>
				</tr>
			</c:forEach>
		</table>

		<br> <a href="insertBoard.jsp">새글 등록</a>
	</center>
</body>
</html>

 

BoardController.java

package com.springbook.view.board;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;

@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
	
	// @ModelAttribute 의 특징
	// @RequestMapping 메소드가 실행 되기 전에 실행된다.
	// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다. 
	// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다. 
	@ModelAttribute("conditionMap")  // ("") <- View 페이지에서 사용할 이름
	public Map<String, String> searchConditionMap() {
		
		Map<String, String> conditionMap = new HashMap<>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 수정
	// @ModelAttribute("board")으로 정보를 가지고 온다 
	// @SessionAttributes("board")와 실제 같은 값
	// 수정한 정보는 vo에 들어있다.
	// 한번 들어온 객체들을 넣어두고 
	// 수정된 title, content는 나중에 처리
	// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board")BoardVO vo, BoardDAO boardDAO) {
		
		System.out.println(vo.getSeq());
		System.out.println(vo.getTitle());
		System.out.println(vo.getWriter());
		System.out.println(vo.getContent());
		System.out.println(vo.getRegDate());
		System.out.println(vo.getCnt());
		
		boardDAO.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, BoardDAO boardDAO, Model model) {
		
		model.addAttribute("board", boardDAO.getBoard(vo)); // model은 request 영역에 저장
		return "getBoard.jsp";
	}
	
	// 글 목록 검색
	// 커멘드 객체인 경우
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(BoardVO vo, BoardDAO boardDAO, Model model) {
			
		model.addAttribute("boardList", boardDAO.getBoardList(vo));
		return "getBoardList.jsp";
	}
	
}

 

18
비오는
33
날에는 일찍 집가자
2024-07-23
0

이렇게 값을 잘 받아온다.

 

🌀 스프링 소켓이란?

Spring Socket는 Spring Framework에서 제공하는 WebSocket 프로토콜을 지원하는 기능이다. 실시간 양방향 통신을 위한 프로토콜로, 서버와 클라이언트 간에 지속적인 연결을 유지하고 데이터를 실시간으로 주고받을 수 있게 해준다.

 


 

스프링에서 소켓을 다루기 전 JSP 에서 소켓을 만들어본다.

JSP 에서 작업함.

 

지난 시간 서버 측 작성

 

ChatServer.java - 서버

package websocket;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/ChatingServer") // 서버명
public class ChatServer {
	
	private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());

	@OnOpen   // 클라이언트 접속 시 실행
	public void onOpen(Session session) {
		clients.add(session);
		System.out.println("웹소켓 연결 :" + session.getId());
	}
	
	@OnMessage // 메세지를 받으면 실행
	public void onOMessgae(String message,Session session) throws IOException {
		System.out.println("메시지 전송 : " + session.getId() + ":" + message);
		synchronized(clients) {  
			for(Session client : clients) {  //모든 클라이언트에게 메세지 전달
				if(!clients.equals(session)) {
					client.getBasicRemote().sendText(message);				}
			}
		}
	}
	
	@OnClose // 클라이언트와 연결의 끊기면 실행
	public void onClose(Session session) {
		clients.remove(session);
		System.out.println("웹소켓 종료 :" + session.getId());
	}
	
	@OnError // 에레 발생 시 실행
	public void onError(Throwable e) {
		System.out.println("에러 발생");
		e.printStackTrace();
	}
	
}

 

web.xml 에서 

<!-- 웹소켓 채팅 서버 -->
  <context-param>
    <param-name>CHAT_ADDR</param-name>
    <param-value>http://localhost:9999/WebSocketProject</param-value>
  </context-param>

위 정보를 추가해줘야 한다.

 

추가된 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>FristJsp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>
  
  <context-param>
    <param-name>INIT_PARAM</param-name>
    <param-value>web.xl에 저장한 초기화 매개 변수</param-value>
  </context-param>
  
<!-- 오라클 설정 정보 -->
<!-- 지금 우리는 드라이버 정보를 초기화 시켜놓았다. 코드에 노출 시키지 않았으며, 앞으로도 이 방법을 쓸 것이다. -->
  <context-param>
    <param-name>OracleDriver</param-name>
    <param-value>oracle.jdbc.driver.OracleDriver</param-value>
  </context-param>
  
    <context-param>
    <param-name>OracleURL</param-name>
    <param-value>jdbc:oracle:thin:@localhost:1522:orcl1</param-value>
  </context-param>
  
    <context-param>
    <param-name>OracleId</param-name>
    <param-value>musthave</param-value>
  </context-param>
  
    <context-param>
    <param-name>OraclePwd</param-name>
    <param-value>1234</param-value>
  </context-param>
  
  
  <!-- 머스트 해브 -->

<!--     <context-param>
    <param-name>OracleId2</param-name>
    <param-value>musthave</param-value>
  </context-param> -->
  
  <!-- 페이징 정보 -->
    <context-param>
    <param-name>POSTS_PER_PAGE</param-name>
    <param-value>10</param-value>
  </context-param>
  <!-- 한 페이지에 출력할 갯수 -->
  
    <context-param>
    <param-name>PAGES_PER_BLOCK</param-name>
    <param-value>5</param-value>
  </context-param>
  <!-- 페이지 목록의 수 -->
  
<!-- 첨부 파일 최대 용량 설정(예제 14-8) -->
  <context-param>
    <param-name>maxPostSize</param-name>
    <param-value>1024000</param-value>
  </context-param>
  
<!-- 웹소켓 채팅 서버 -->
  <context-param>
    <param-name>CHAT_ADDR</param-name>
    <param-value>http://localhost:9999/WebSocketProject</param-value>
  </context-param>
  
  
  
  <filter>
    <filter-name>SetCharEncoding</filter-name>
    <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
      </init-param>
  </filter>
  <filter-mapping>
    <filter-name>SetCharEncoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  
  
</web-app>

 

 

 

 

웹소켓으로 채팅 구현 시 사용하는 5가지 어노테이션

 

@ServerEndpoint

@OnOpen

@OnMessage

@OnClose

@OnError

 

 💡 웹소켓 주소 구성 : ws://호스트명:포드번호/컨텍스트(프로젝트명)/서버명 ws://http://localhost:9999/WebSocketProject/WEB-INF/classes/websocket/ChatServer.java

 

MutiChatMain.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>

<script>
	function chatWinOpen() {
		let id = document.getElementById("chatId");
		if (id.value == "") {
			alert("대화명을 입력 후 채팅창을 열어주세요");
			id.focus();
			return;
		}

		window.open("ChatWindow.jsp?chatId=" + id.value, "",
				"width=350, height=400");
		id.value = "";
	}
</script>
</head>
<body>
	<h2>웹소켓 채팅 - 대화명 적용해서 채팅창 띄워주기</h2>
	대화명 :
	<input type="text" id="chatId" />
	<button onclick="chatWinOpen();">채팅 참여</button>
</body>
</html>

 

ChatWindow.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>
<script>
// 서버에 접속
let webSocket = new WebSocket("<%=application.getInitParameter("CHAT_ADDR")%>/ChatingServer");

	// 필요한 값 가지고 오기
	window.onload = function() {
		chatWindow = document.getElementById("chatWindow");
		chatMessage = document.getElementById("chatMessage");
		chatId = document.getElementById("chatId").value;
	}
	
	// 소켓 끊기
	function disconnect(){
		webSocket.close();
	}
	
	//메세지 전송
	function sendMessage() {
		chatWindow.innerHTML += "<div class='myMsg'>" + chatMessage.value + "</div>";
		webSocket.send(chatId + '|' + chatMessage.value);
		chatMessage.value = "";
		// 메세지가 많아지면 스크롤처리
		chatWindow.scrollTop = chatWindow.scrollHeight;
	}
	
	function enterKey() {
		if (window.event.keyCode == 13){
			sendMessage();
		}
	}

	// 소켓이 서버로 가서 동작하는 메소드
	// 웹소켓이 서버에 연결되면 실행, 이 속성의 함수는 자동으로 실행
	webSocket.onopen = function(event) {
		chatWindow.innerHTML += "웹소켓 서버에 연결되었습니다.<br/>";
	}
	
	webSocket.onclose = function(event){
		 chatWindow.innerHTML += "웹소켓 서버가 종료되었습니다.<br/>";
	}

	webSocket.onmessage = function(event){
		// message를 배열 형식으로 받는다
		let message = event.data.split("|");
		let sender = message[0];
		let content = message[1];
		
		if (content != null) {
			chatWindow.innerHTML += "<div>" + sender + ":" + content + "</div>";
		}
		// 메세지가 많아지면 스크롤처리
		chatWindow.scrollTop = chatWindow.scrollHeight;
	}
	
</script>

<style type="text/css">
#chatWindow {
	border: 1px solid black;
	width: 270px;
	height: 310px;
	overflow: scroll;
	padding: 5px;
}

#chatMessage {
	width: 236px;
	height: 30px;
}

#sendBtn {
	height: 30px;
	position: relative;
	top: 2px;
	left: -2px;
}

#closeBtn {
	margin-bottom: 3px;
	position: relative;
	top: 2px;
	left: -2px;
}

#chatId {
	width: 158px;
	height: 24px;
	border: 1px solid #AAAAAA;
	background-color: #EEEEEE;
}

.myMsg {
	text-align: right;
}
</style>
</head>
<body>
	<!-- 나의 아이디를 묶어 보내야 한다 chatId,chatWindow,chatMessage 사용 -->
	대화명 :
	<input type="text" id="chatId" value="${param.chatId }" readonly>
	<button id="closeBtn" onclick="disconnect();">채팅 종료</button>

	<!-- 채팅이 표시되는 공간 -->
	<div id="chatWindow"></div>
	<div>
		<input type="text" id="chatMessage" onkeyup="enterKey();" />
		<button id="sendBtn" onclick="sendMessage()">전송</button>
	</div>
</body>
</html>

창을 여러 개 띄워 메세지를 주고 받을 수 있다.

 

윈도우는 터미널에서 ipconfig를 치면 본인의 ip 주소를 확인할 수 있다.

서버는 ip주소를 뿌리고 클라이언트는 서버의 ip 주소를 받으면 클라이언트끼리 채팅이 가능하다.

 

 

추가로 실험해본 채팅창의 색을 바꾸기(색 전송하기) 반 성공..

 

ChatWindow.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>
<script>
// 서버에 접속
let webSocket = new WebSocket("<%=application.getInitParameter("CHAT_ADDR")%>/ChatingServer");

	// 필요한 값 가지고 오기
	window.onload = function() {
		chatWindow = document.getElementById("chatWindow");
		chatMessage = document.getElementById("chatMessage");
		chatId = document.getElementById("chatId").value;
	}
	
	// 소켓 끊기
	function disconnect(){
		webSocket.close();
	}
	
	//메세지 전송
	function sendMessage() {
		chatWindow.innerHTML += "<div class='myMsg'>" + chatMessage.value + "</div>";
		webSocket.send(chatcolor + chatId + '|' + chatMessage.value);
		chatMessage.value = "";
		// 메세지가 많아지면 스크롤처리
		chatWindow.scrollTop = chatWindow.scrollHeight;
	}
	
	function enterKey() {
		if (window.event.keyCode == 13){
			sendMessage();
		}
	}
	
	function changeColor() {
		let color = "tomato";
		webSocket.send("colorChange|" + color);
	}

	// 소켓이 서버로 가서 동작하는 메소드
	// 웹소켓이 서버에 연결되면 실행, 이 속성의 함수는 자동으로 실행
	webSocket.onopen = function(event) {
		chatWindow.innerHTML += "웹소켓 서버에 연결되었습니다.<br/>";
	}
	
	webSocket.onclose = function(event){
		 chatWindow.innerHTML += "웹소켓 서버가 종료되었습니다.<br/>";
	}

	webSocket.onmessage = function(event){
		// message를 배열 형식으로 받는다
		let message = event.data.split("|");
		let sender = message[0];
		let content = message[1];
		
		if (messageType === "colorChange") {
			chatWindow.style.backgroundColor = content;
		} else if (content != null) {
			chatWindow.innerHTML += "<div>" + sender + ":" + content + "</div>";
		}
		// 메세지가 많아지면 스크롤처리
		chatWindow.scrollTop = chatWindow.scrollHeight;
	}
	
	
</script>

<style type="text/css">
#chatWindow {
	border: 1px solid black;
	width: 270px;
	height: 310px;
	overflow: scroll;
	padding: 5px;
}

#chatMessage {
	width: 236px;
	height: 30px;
}

#sendBtn {
	height: 30px;
	position: relative;
	top: 2px;
	left: -2px;
}

#closeBtn {
	margin-bottom: 3px;
	position: relative;
	top: 2px;
	left: -2px;
}

#chatId {
	width: 158px;
	height: 24px;
	border: 1px solid #AAAAAA;
	background-color: #EEEEEE;
}

.myMsg {
	text-align: right;
}
</style>
</head>
<body>
	<!-- 나의 아이디를 묶어 보내야 한다 chatId,chatWindow,chatMessage 사용 -->
	대화명 :
	<input type="text" id="chatId" value="${param.chatId }" readonly>
	<button id="closeBtn" onclick="disconnect();">채팅 종료</button>

	<!-- 채팅이 표시되는 공간 -->
	<div id="chatWindow"></div>
	<div>
		<input type="text" id="chatMessage" onkeyup="enterKey();" />
		<button id="sendBtn" onclick="sendMessage()">전송</button>
		<button id="colorBtn" onclick="changeColor();">토마토</button>
	</div>
</body>
</html>

문제는 내 채팅창에 색은 바뀌지 않는다..

 

 


 

다시 스프링으로 넘어온다.

본격적으로 스프링 프레임 워크 사용해보기

 

 

스프링에서 오류가 났을 때 이런 메세지를 볼 수 있는데

💡 java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/action-servlet.xml]

이건 action-servlet.xml 이라는 파일을 찾는다는 뜻이다.

 

action-servlet.xml는 핸들러, 컨트롤러, 뷰리저버 정보를 가지고 있는 파일이다.

 

 

property ⇒ 맵 구조

(모든 객체의 구조 알아보기)

 

최종적인 파일 구조

 

 

UIUX _국비과정 0718 [스프링 model1방식 웹만들기]

스프링 JDBC update()→ insert, update, deletequeryForInt()queryForObject() : 실행결과를 자바 객체(VO)로 매핑하여 리턴query() : 검색된 데이터의 row(레코드) 수 만큼 RowMapper객체의 MapRow()메소드가 실행된다. 그

100dumpling.tistory.com

 

지난 시간,

프론트 컨트롤러 (jsp)

DispatcherServlet를 만들었다.

 

▼ DispatcherServlet

더보기
package com.springbook.view.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// @WebServlet("*.do") 라고 쓰는 매핑정보가  web.xml에 들어 있다.
// 프론트 컨트롤러의 역할
public class DispatcherServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	private void process(HttpServletRequest request, HttpServletResponse response) {
		// request, response를 받아서 필요한 작업 처리
		// getRequestURI() 포트번호를 제외하고 뒤의 값을 반환
		String uri = request.getRequestURI();
		String path = uri.substring(uri.lastIndexOf("/")); // /login.do <- 이렇게 '/' 뒤의 주소를 가지고 온다

		System.out.println(path);

    // .do 뒤에 뭐가 오냐에 따라 판단
		if (path.equals("/login.do")) {
			System.out.println("로그인 처리");
		} else if (path.equals("/logout.do")) {
			System.out.println("로그아웃 처리");
		} else if (path.equals("/insertBoard.do")) {
			System.out.println("글 등록 처리");
		} else if (path.equals("/updataBoard.do")) {
			System.out.println("글 수정 처리");
		} else if (path.equals("/deleteBoard.do")) {
			System.out.println("글 삭제 처리");
		} else if (path.equals("/getBoard.do")) {
			System.out.println("글 상세 조회 처리");
		} else if (path.equals("/getBoardList.do")) {
			System.out.println("글 목록 검색 처리");
		}

	}
}

요청하는 주소값을 잘 처리하고 있다. 이걸 시작으로 model2방식의 게시판을 만들 수 있다.

 


 

 

로그인 처리가 된 주소를

http://localhost:9999/BoardWeb/login.do 이렇게 바꿔줘야 한다.

 

login.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>
	<center>
		<form action="login.do" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange">아이디</td>
					<td>
						<input type="text" name="id">
					</td>
				</tr>
				<tr>
					<td bgcolor="orange">비밀번호</td>
					<td>
						<input type="password" name="password">
					</td>
				</tr>
				<tr>
					<td colspan="2" align="center">
						<input type="submit" value="로그인"></td>
				</tr>
			</table>
		</form>
	</center>
</body>
</html>

 

<form action="login.do" method="post"> 를 DispatcherServlet에 써 놓은 주소로 바꿔준다.

DispatcherServlet 에는 login.do로 페이지를 이동하면 어느 화면을 보여줄지 판단하기 위해 모델1방식에서 작성했던 login_proc 의 코드를 옮겨 넣어준다.

모델 1방식에서는 프론트컨트롤러 없이 login_proc가 바로 화면 이동을 할 수 있게 해줬다.

 

→ 글 목록 보기

http://localhost:9999/BoardWeb/getBoardList.jsp 이 주소로 직접 실행하면 안되고

http://localhost:9999/BoardWeb/getBoardList.do 로 직접 접근해야한다.

이렇게 접근해도 주소는 .jsp로 바뀌는데 리다이렉트 방식이기 때문

 

 

DispatcherServlet

package com.springbook.view.controller;

import java.io.IOException;
import java.util.List;

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

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;

// @WebServlet("*.do") 라고 쓰는 매핑정보가  web.xml에 들어 있다.
// 프론트 컨트롤러의 역할
public class DispatcherServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		process(request, response);
	}

	private void process(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		// request, response를 받아서 필요한 작업 처리
		// getRequestURI() 포트번호를 제외하고 뒤의 값을 반환
		String uri = request.getRequestURI();
		String path = uri.substring(uri.lastIndexOf("/")); // /login.do <- 이렇게 '/' 뒤의 주소를 가지고 온다

		System.out.println(path);
		
		// .do 뒤에 뭐가 오냐에 따라 판단
		if (path.equals("/login.do")) {
			
			   System.out.println("로그인 처리");
			
			   // login_proc 의 코드. 모델 2에서는 프론트컨트롤러가 proc의 역할을 수행한다.
			   String id = request.getParameter("id");
			   String password = request.getParameter("password");
			   
			   UserVO vo = new UserVO();
			   vo.setId(id);
			   vo.setPassword(password);
			   
			   UserDAO dao = new UserDAO();
			   UserVO user = dao.getUser(vo);
			   
			   if(user != null) {
				  HttpSession session = request.getSession();
				  session.setAttribute("id", vo.getId());
			      response.sendRedirect("getBoardList.do");
			      
			   }else{
			      response.sendRedirect("login.jsp");
			   }
			
			   
		} else if (path.equals("/logout.do")) {
			
			System.out.println("로그아웃 처리");
			
			HttpSession session = request.getSession();
			session.invalidate();
			
			response.sendRedirect("login.jsp");
			
			
		} else if (path.equals("/insertBoard.do")) {
			
			System.out.println("글 등록 처리");
			
			request.setCharacterEncoding("UTF-8");
			
			String title = request.getParameter("title");
			String writer = request.getParameter("writer");
			String content = request.getParameter("content");
			
			BoardVO vo = new BoardVO();
			BoardDAO dao = new BoardDAO();
			
			vo.setTitle(title);
			vo.setWriter(writer);
			vo.setContent(content);
			
			dao.insertBoard(vo);
			
			response.sendRedirect("getBoardList.do");
			
			
		} else if (path.equals("/updataBoard.do")) {
			
			System.out.println("글 수정 처리");
			
			request.setCharacterEncoding("UTF-8");

			String seq = request.getParameter("seq");
			String title = request.getParameter("title");
			String content = request.getParameter("content");

			BoardVO vo = new BoardVO();
			BoardDAO dao = new BoardDAO();

			vo.setSeq(Integer.parseInt(seq));
			vo.setTitle(title);
			vo.setContent(content);

			dao.updateBoard(vo);

			response.sendRedirect("getBoardList.do");
			
			
		} else if (path.equals("/deleteBoard.do")) {
			
			System.out.println("글 삭제 처리");
			
			request.setCharacterEncoding("UTF-8");

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

			BoardVO vo = new BoardVO();
			BoardDAO dao = new BoardDAO();

			vo.setSeq(Integer.parseInt(seq));

			dao.deleteBoard(vo);

			response.sendRedirect("getBoardList.do");
			
			
		} else if (path.equals("/getBoard.do")) {
			
			System.out.println("글 상세 조회 처리");
			
			String seq = request.getParameter("seq");

			BoardVO vo = new BoardVO();
			BoardDAO dao = new BoardDAO();
			
			vo.setSeq(Integer.parseInt(seq));
			
			BoardVO board = dao.getBoard(vo);
			
			// 데이터를 session에 담아 최종적으로 "getBoard.jsp"로 페이지 이동
			HttpSession session = request.getSession();
			session.setAttribute("board", board);
			response.sendRedirect("getBoard.jsp");
			
			
		} else if (path.equals("/getBoardList.do")) {
			
			System.out.println("글 목록 검색 처리");
			
			BoardVO vo = new BoardVO();
			BoardDAO dao = new BoardDAO();
			
			List<BoardVO> boardList = dao.getBoardList(vo);
			
			// 목록을 session에 담아 최종적으로 "getBoardList.jsp"로 페이지 이동
			HttpSession session = request.getSession();
			session.setAttribute("boardList", boardList);
			// 실제 화면에 뿌려줄때는 jsp로 가야한다.
			response.sendRedirect("getBoardList.jsp");
			
		}

	}
}

 

하지만 이렇게 프론트컨트롤러에 모든 정보를 담아두는 것은 좋은 방법이 아니다.

핸들러의 역할만 하는 것이 적절.

 

getBoard

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%
	//String seq = request.getParameter("seq");

	//BoardVO vo = new BoardVO();
	//BoardDAO dao = new BoardDAO();
	
	//vo.setSeq(Integer.parseInt(seq));
	
	//BoardVO board = dao.getBoard(vo);
	// 모델 2방식에서는 위 코드 사용 X 
	
	BoardVO board = (BoardVO)session.getAttribute("board");
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 상세</h1>
		<a href="logout.do">Log-out</a>
		<hr>
		<form action="updateBoard.do" method="post">
		
		<input name="seq" type="hidden" value="<%=board.getSeq() %>">
		
			<table border="1" cellpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left">
					<input name="title" type="text" value="<%=board.getTitle() %> ">
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">작성자</td>
					<td align="left">
					<%=board.getWriter() %>
					</td>
				</tr>
				
			    <tr>
					<td bgcolor="orange" width="70">내용</td>
					<td align="left">
					<textarea name="content" cols="40" rows="10" ><%=board.getContent() %></textarea>
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">등록일</td>
					<td align="left">
					<%=board.getRegDate() %>
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">조회수</td>
					<td align="left">
					<%=board.getCnt() %>
					</td>
				</tr>
				
				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="글 수정"/> 
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="insertBoard.jsp">글 등록</a> <!-- 글 등록은 .jsp -->
		<a href="deleteBoard.do?seq=<%=board.getSeq() %>">글 삭제</a>
		<a href="getBoardList.do">글 목록</a>
		
	</center>
</body>
</html>

 

getBoardList

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%@page import="java.util.*"%>
<%
  
	//BoardVO vo = new BoardVO();
	//BoardDAO dao = new BoardDAO();
	
	//List<BoardVO> boardList = dao.getBoardList(vo);
	// 모델 2방식에서는 위 코드를 사용하지 않는다.
	
	// DispatcherServlet에서 만들어 둔 session에서 데이터를 가지고 온다
	List<BoardVO> boardList = (List<BoardVO>)session.getAttribute("boardList");
    
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 목록</h1>
		<h3>
			테스트님! 게시판에 오신 걸 환영합니다! <a href="logout.do">log-out</a>
		</h3>

		<form action="getBoardList.jsp" method="post">
			<table border="1" cellpadding="0" cellspacing="0" width="700">
				<tr>
					<td align="right">
					<select name="searchCondition">
							<option value="TITLE">제목</option>
							<option value="CONTENT">내용</option>
					</select>
					<input name="searchKeyword" type="text" /> 
					<input type="submit" value="검색" /> 
					</td>
				</tr>
			</table>
		</form>

		<table border="1" cellpadding="0" cellspacing="0" width="700">
			<tr>
				<th bgcolor="orange" width="100">번호</th>
				<th bgcolor="orange" width="200">제목</th>
				<th bgcolor="orange" width="150">작성자</th>
				<th bgcolor="orange" width="150">등록일</th>
				<th bgcolor="orange" width="100">조회수</th>
			</tr>

			<% 
				for (BoardVO board : boardList) {
					
				%>

			<tr>
				<td>
					<%=board.getSeq() %>
				</td>
				<td>
				<a href="getBoard.do?seq=<%=board.getSeq() %>">
					<%=board.getTitle() %></a>
				</td>
				<td>
					<%=board.getWriter() %>
				</td>
				<td>
					<%=board.getRegDate() %>
				</td>
				<td>
					<%=board.getCnt() %>
				</td>
			</tr>

			<%
				}
				%>
		</table>

		<br> <a href="insertBoard.jsp">새글 등록</a>
	</center>
</body>
</html>

 

insertBoard

<%@ 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>
	<center>
		<h1>글 등록</h1>
		<a href="logout.do">Log-out</a>
		<hr>
		<form action="insertBoard.do" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name="title" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left"><input type="text" name="writer" size="10" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
				</tr>

				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="새 글 등록" />
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="getBoardList.do">글 목록 가기</a>
	</center>
</body>
</html>

글이 잘 들어오는 것을 확인할 수 있다.

 

 


 

MVC 구조의 프로그래밍

 

 

  • DispatcherServlet(f.c)

 

  • HandlerMapping

: 매핑정보를 관리해주는 핸들러

 

  • Controller(a.c)

: 인터페이스 상속하는 구조로 작성, 역할은 다르지만 하나의 표준화된 메소드를 가지고 실행

(비즈니스 계층과 비슷하다)

 

  • ViewResolver(jsp)

스프링 JDBC

 

  • update()

→ insert, update, delete

  • queryForInt()
  • queryForObject() : 실행결과를 자바 객체(VO)로 매핑하여 리턴
  • query() : 검색된 데이터의 row(레코드) 수 만큼 RowMapper객체의 MapRow()메소드가 실행된다. 그리고 매핑된 VO객체 여러개를 List컬렉션에 저장하여 리턴한다.

-> select

 

▼ applicationContext.xml

더보기
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!-- 패키지를 스캔해준다. 다 해주는 것은 아니고 표시되어진 클래스만 스캔해준다 -> 이것이 어노테이션 -->
	<!-- <context:component-scan base-package="polymorphism"></context:component-scan> -->
	<context:component-scan base-package="com.springbook.biz"></context:component-scan>
	
	<!-- database.properties 의 파일을 읽어올 수 있게 해준다 -->
	<context:property-placeholder location="classpath:config/database.properties"/>
	
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.driver}"></property>
	<property name="url" value="${jdbc.url}"></property>
	<property name="username" value="${jdbc.username}"></property>
	<property name="password" value="${jdbc.password}"></property>

	</bean>
	
	<!--JdbcTemplate 클래스를 통해 DB에 접근 (crud) -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	

</beans>

 

BoardDAOSpring

package com.springbook.biz.board.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

// 비즈니스 계층에서 사용할 수 있도록 빈에 등록
@Repository
public class BoardDAOSpring {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	// 상수형태로 만들어 두었다.
	private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
			+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";

	private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
	private final String BOARD_DELETE = "delete board where seq=?";
	private final String BOARD_GET = "select * from board where seq=?";
	private final String BOARD_LIST = "select * from board order by seq desc";
	
	// ---------- update() 구문 사용 ----------
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 insertBoard() 기능 처리");
		// insert를 springJDBC에서는 update가 처리, try catch문 사용 안해도 됨.
		// 기존 jdbc 에서 사용한 '?' 대신 순서대로 객체를 가지고 와 적어준다.
		jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
	}
	
	// 글 수정
	public void updateBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 updateBoard() 기능 처리");
		jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 deleteBoard() 기능 처리");
		jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
	}
	
	// ---------- queryForObject(), query() 구문 사용 ----------
	
	// 글 상세 조회
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> springJDBC로 getBoard() 상세 보기  처리");
		
		// 배열로 값을 받기 때문에 배열에 넣어준다
		Object[] args= {vo.getSeq()};
		
		// return jdbcTemplate.queryForObject(sql, args, rowMapper);
		return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
	}
	
	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> springJDBC로 getBoardList() 기능 처리");
		// '?' 가 없다. 글 목록 전체 조회이기 때문에 모든 글들을 다 불러오면 된다.
		return jdbcTemplate.query(BOARD_LIST, new BoardRowMapper());
		
	}
	

}

 

BoardRowMapper

package com.springbook.biz.board.impl;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import com.springbook.biz.board.BoardVO;

public class BoardRowMapper implements RowMapper<BoardVO> {
// BoardDAO 의 resultSet의 역할을 수행한다.
	
	@Override
	public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		
		BoardVO board = new BoardVO();
		
		board.setSeq(rs.getInt("SEQ"));
		board.setTitle(rs.getString("TITLE"));
		board.setWriter(rs.getString("WRITER"));
		board.setContent(rs.getString("CONTENT"));
		board.setRegDate(rs.getDate("REGDATE"));
		board.setCnt(rs.getInt("CNT"));
		
		return board;
	}
	
	
	
}

 

BoardServiceImpl 에서 BoardDAOSpring 의존 주입

private BoardDAOSpring boardDAO;

 

 

▼ BoardServiceImpl

더보기
package com.springbook.biz.board.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.common.Log4jAdvice;
import com.springbook.biz.common.LogAdvice;


@Service("boardService")
public class BoardServiceImpl implements BoardService {

	// boardDAO를 의존 주입해야 한다.
	@Autowired
	private BoardDAOSpring boardDAO;
	
	
	public BoardServiceImpl() {
	}

	@Override
	public void insertBoard(BoardVO vo) {
		// @Autowired를 했기 때문에 사용가능, @Autowired로 객체를 생성한거다.
		boardDAO.insertBoard(vo);

	}

	@Override
	public void updateBoard(BoardVO vo) {
		boardDAO.updateBoard(vo);
	}

	@Override
	public void deleteBoard(BoardVO vo) {
		boardDAO.deleteBoard(vo);
	}

	@Override
	public BoardVO getBoard(BoardVO vo) {
		return boardDAO.getBoard(vo);
	}

	@Override
	public List<BoardVO> getBoardList(BoardVO vo) {
		return boardDAO.getBoardList(vo);
	}

}

 

BoardServiceClient에서 실행하면 ‘===> springJDBC로 insertBoard() 기능 처리’ 라고 뜨며 springJDBC가 실행되는 것을 볼 수 있다.

 

 

 

Spring 트랜잭션

데이터 수정 삭제, 등 일련의 작업들이 연결되어 있다.

실제 데이터 베이스에 반영하는 것. 잘 처리가 되면 커밋, 롤백 등 작업처리.

어떤 메소드의 동작에 의해서 그 메소드가 실행하는 동작 처리에 트랜잭션이 일어나야 한다. 이 트랜잭션은 공통관심사 (AOP) → DAO

 

트랜잭션을 위한 라이브러리 사용

tx 선택하기

 


트랜잭션(Transaction) : 더 이상 쪼갤 수 없는 최소 작업 단위

 

트랜잭션 마무리 작업

  • 커밋 : 작업이 마무리 됨
  • 롤백 : 작업을 취소하고 이전의 상태로 되돌림

 

스프링에서 제공하는 트랜잭션 기술

  1. 트랜잭션 동기화
  2. 트랜잭션 추상화
  3. AOP를 이용한 트랜잭션 분리 ← 우리가 사용해본 것.

 

 

스프링으로 웹 만들기 model1 방식

 

login.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>
	<center>
		<form action="login_proc.jsp" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange">아이디</td>
					<td>
						<input type="text" name="id">
					</td>
				</tr>
				<tr>
					<td bgcolor="orange">비밀번호</td>
					<td>
						<input type="password" name="password">
					</td>
				</tr>
				<tr>
					<td colspan="2" align="center">
						<input type="submit" value="로그인"></td>
				</tr>
			</table>
		</form>
	</center>
</body>
</html>

실행해보면 이렇게 나온다.

 

주소를 의미있게 설정하기 위해 server.xml 파일의 Context부분을 수정해준다.

그 후 톰캣 서버를 다시 리스타트해 실행하면

 

주소가 이렇게 바뀐 것을 확인할 수 있다.

 

 

 

login_proc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.user.*" %>
<%@page import="com.springbook.biz.user.impl.*" %>
<%
   String id = request.getParameter("id");
   String password = request.getParameter("password");
   
   UserVO vo = new UserVO();
   vo.setId(id);
   vo.setPassword(password);
   
   UserDAO dao = new UserDAO();
   UserVO user = dao.getUser(vo);
   
   if(user != null) {
      response.sendRedirect("getBoardList.jsp");
      
   }else{
      response.sendRedirect("login.jsp");
   }
   
%>

 

아이디와 비밀번호가 일치하면 사이트 이동이 일어나게 만들어준다.

 

getBoardList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%@page import="java.util.*"%>
<%
  
	BoardVO vo = new BoardVO();
	BoardDAO dao = new BoardDAO();
	
	List<BoardVO> boardList = dao.getBoardList(vo);
    
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 목록</h1>
		<h3>
			테스트님! 게시판에 오신 걸 환영합니다! <a href="logout_proc.jsp">log-out</a>
		</h3>

		<form action="getBoardList.jsp" method="post">
			<table border="1" callpadding="0" cellspacing="0" width="700">
				<tr>
					<td align="right">
					<select name="searchCondition">
							<option value="TITLE">제목</option>
							<option value="CONTENT">내용</option>
					</select>
					<input name="searchKeyword" type="text" /> 
					<input type="submit" value="검색" /> 
					</td>
				</tr>
			</table>
		</form>

		<table border="1" callpadding="0" cellspacing="0" width="700">
			<tr>
				<th bgcolor="orange" width="100">번호</th>
				<th bgcolor="orange" width="200">제목</th>
				<th bgcolor="orange" width="150">작성자</th>
				<th bgcolor="orange" width="150">등록일</th>
				<th bgcolor="orange" width="100">조회수</th>
			</tr>

			<% 
				for (BoardVO board : boardList) {
					
				%>

			<tr>
				<td>
					<%=board.getSeq() %>
				</td>
				<td>
				<a href="getBoard.jsp?seq=<%=board.getSeq() %>">
					<%=board.getTitle() %>
				</a>
				</td>
				<td>
					<%=board.getWriter() %>
				</td>
				<td>
					<%=board.getRegDate() %>
				</td>
				<td>
					<%=board.getCnt() %>
				</td>
			</tr>

			<%
				}
				%>
		</table>

		<br> <a href="insertBoard.jsp">새글 등록</a>
	</center>
</body>
</html>

 

상세보기 - getBoard.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%
	String seq = request.getParameter("seq");

	BoardVO vo = new BoardVO();
	BoardDAO dao = new BoardDAO();
	
	vo.setSeq(Integer.parseInt(seq));
	
	BoardVO board = dao.getBoard(vo);
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<center>
		<h1>글 상세</h1>
		<a href="logout_proc.jsp">Log-out</a>
		<hr>
		<form action="">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left">
					<input name="title" type="text" value="<%=board.getTitle() %> ">
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">작성자</td>
					<td align="left">
					<%=board.getWriter() %>
					</td>
				</tr>
				
			    <tr>
					<td bgcolor="orange" width="70">내용</td>
					<td align="left">
					<textarea name="content" cols="40" rows="10" ><%=board.getContent() %></textarea>
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">등록일</td>
					<td align="left">
					<%=board.getRegDate() %>
					</td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">조회수</td>
					<td align="left">
					<%=board.getCnt() %>
					</td>
				</tr>
				
				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="글 수정"/> 
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="insertBoard.jsp">글 등록</a>
		<a href="deleteBoard.jsp">글 삭제</a>
		<a href="getBoardList.jsp">글 목록</a>
		
	</center>
</body>
</html>

 

글 등록 - insertBoard.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>
	<center>
		<h1>글 등록</h1>
		<a href="logout_proc.jsp">Log-out</a>
		<hr>
		<form action="insertBoard_proc.jsp" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name="title" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left"><input type="text" name="writer" size="10" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
				</tr>

				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="새 글 등록" />
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="getBoardList.jsp">글 목록 가기</a>
	</center>
</body>
</html>

 

insertBoard_proc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%
	request.setCharacterEncoding("UTF-8");
	
	String title = request.getParameter("title");
	String writer = request.getParameter("writer");
	String content = request.getParameter("content");
	
	BoardVO vo = new BoardVO();
	BoardDAO dao = new BoardDAO();
	
	vo.setTitle(title);
	vo.setWriter(writer);
	vo.setContent(content);
	
	dao.insertBoard(vo);
	
	response.sendRedirect("getBoardList.jsp");
%>

글이 잘 올라가는 것을 확인 할 수 있다. 

 

글 등록 - insertBoard.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>
	<center>
		<h1>글 등록</h1>
		<a href="logout_proc.jsp">Log-out</a>
		<hr>
		<form action="insertBoard_proc.jsp" method="post">
			<table border="1" callpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name="title" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left"><input type="text" name="writer" size="10" /></td>
				</tr>

				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
				</tr>

				<tr>
					<td colspan="2" align="center">
					<input type="submit" value="새 글 등록" />
					</td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="getBoardList.jsp">글 목록 가기</a>
	</center>
</body>
</html>

 

insertBoard_proc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%
	request.setCharacterEncoding("UTF-8");
	
	String title = request.getParameter("title");
	String writer = request.getParameter("writer");
	String content = request.getParameter("content");
	
	BoardVO vo = new BoardVO();
	BoardDAO dao = new BoardDAO();
	
	vo.setTitle(title);
	vo.setWriter(writer);
	vo.setContent(content);
	
	dao.insertBoard(vo);
	
	response.sendRedirect("getBoardList.jsp");
%>

 

 

따로 수정하는 페이지가 있는것이 아니라 글 상세보기 안에서 바로 수정하기 가능

updateBoard_proc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%

request.setCharacterEncoding("UTF-8");

String seq = request.getParameter("seq");
String title = request.getParameter("title");
String content = request.getParameter("content");

BoardVO vo = new BoardVO();
BoardDAO dao = new BoardDAO();

vo.setSeq(Integer.parseInt(seq));
vo.setTitle(title);
vo.setContent(content);

dao.updateBoard(vo);

response.sendRedirect("getBoardList.jsp");

%>

 

로그아웃 - logout_proc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	session.invalidate();

	response.sendRedirect("login.jsp");
	
%>

 

 

 

스프링으로 웹 만들기 model2 방식

중간에 경비역할의 컨트롤러

 

프론트 컨트롤러 (jsp)

DispatcherServlet

package com.springbook.view.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// @WebServlet("*.do") 라고 쓰는 매핑정보가  web.xml에 들어 있다.
public class DispatcherServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	private void process(HttpServletRequest request, HttpServletResponse response) {
		// request, response를 받아서 필요한 작업 처리
		// getRequestURI() 포트번호를 제외하고 뒤의 값을 반환
		String uri = request.getRequestURI();
		String path = uri.substring(uri.lastIndexOf("/")); // /login.do <- 이렇게 '/' 뒤의 주소를 가지고 온다

		System.out.println(path);

		if (path.equals("/login.do")) {
			System.out.println("로그인 처리");
		} else if (path.equals("/logout.do")) {
			System.out.println("로그아웃 처리");
		} else if (path.equals("/insertBoard.do")) {
			System.out.println("글 등록 처리");
		} else if (path.equals("/updataBoard.do")) {
			System.out.println("글 수정 처리");
		} else if (path.equals("/deleteBoard.do")) {
			System.out.println("글 삭제 처리");
		} else if (path.equals("/getBoard.do")) {
			System.out.println("글 상세 조회 처리");
		} else if (path.equals("/getBoardList.do")) {
			System.out.println("글 목록 검색 처리");
		}

	}
}

+ Recent posts