온 코딩

[Spring](간단한게시판) DB 연결, 컨트롤러 등록 본문

복습 ARCHIVE/모델별 프로젝트

[Spring](간단한게시판) DB 연결, 컨트롤러 등록

SummerON 2021. 6. 10. 18:18

1. DB연결 

Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<Resource name="jdbc/orcl"
			auth="container"
			type="javax.sql.DataSource"
			username="계정명"
			password="비밀번호"
			driverClassName="oracle.jdbc.driver.OracleDriver"
			factory="org.apache.commons.dbcp.BasicDataSourceFactory"
			url="jdbc:oracle:thin:@127.0.0.1:1521:XE"
			maxActive="20"
			maxIdle="10">
	</Resource>
</Context>

BoardDAO 

-실제 DB연결을 시도하고 DB관련 메서드 저장되어 있음

package board.dao;

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

import javax.naming.InitialContext; //InitailContext implement Context
//클래스 등은 외부의 xml 문서를 통해 접근하기 때문에 예외처리 필수 
import javax.sql.DataSource;

import board.command.BoardCommand;
import board.dto.BoardDTO;

/**JNDI 방식의 Connection을 사용할 경우 : Context.xml **/
public class BoardDAO {
//DataSource 객체는 getConnection()과 동일한 역할을 담당
	DataSource ds;
	
	public BoardDAO() {
		//1. Context객체 얻기 : Context.xml문서에서 name="jdbc/orcl"속성값을 추출
		//방법 : InitialContext 객체를 이용 
		//     해당 객체가 가지고 있는 lookUP()을 통해 name 속성 값을 추출 할 수 있다.
		//     단, jdbc/orcl을 찾기 위해서는 java:comp/env/jdbc/orcl 이라고 적어야한다.
		
		try {
			InitialContext ctv = new InitialContext();
			
			//lookUP 메서드는 반환타입이 Object 이기 때문에 반드시 형변환!
			ds = (DataSource)ctv.lookup("java:comp/env/jdbc/orcl");
			
		} catch (Exception e) {
			System.out.println("DataSourceContext Load ERR : "+ e.getMessage());
		}
		
	}// 생성자 끝

	/** 글 목록 조회 **/
	public ArrayList<BoardDTO> list(){
		ArrayList<BoardDTO> list = new ArrayList<BoardDTO>();
		
		try {
			String sql = "select * from springboard order by num desc";
			Connection conn = ds.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet rs = pstmt.executeQuery();
			
			while(rs.next()) {
				BoardDTO data = new BoardDTO();
				data.setNum(rs.getInt("num"));
				data.setAuthor(rs.getString("author"));
				data.setContent(rs.getString("content"));
				data.setTitle(rs.getString("title"));
				data.setDate(rs.getString("writeday"));
				data.setReadcnt(rs.getInt("readcnt"));
				
				list.add(data);
			}
			
		}catch(Exception e) {
			System.out.println("list() ERR : "+ e.getMessage());
		}
		//finally 할 필요 없음 - 스프링에서 자동 관리 
		return list;
	}//list() end
	
	/** 새 글에 대한 글 번호를 위한 메서드 **/
	public int getNewNum() {
		int newNum = 1;
		
		try {
			String sql="select max(num) from springboard";
			Connection conn = ds.getConnection();
			PreparedStatement stmt = conn.prepareStatement(sql);
			ResultSet rs = stmt.executeQuery();
			
			if(rs.next()) {
				newNum = rs.getInt(1)+1;
				//max(num)은 실제 필드명이 아니기 때문에 index를 사용
				//현재 num 필드의 가장 큰 값 +1 => 새로운 글번호 
			}
			
		}catch(Exception e) {
			System.out.println("getNewNum() ERR : "+ e.getMessage());
		}
		
		return newNum;
	}
	
	/** 글 저장 메서드 **/
	public void write(BoardCommand data) {
		try {
			int newNum = getNewNum(); //새로운 글의 번호
			String sql="insert into springboard(num, author, title, content) values (?,?,?,?)";
			Connection conn = ds.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, newNum);
			pstmt.setString(2, data.getAuthor());
			pstmt.setString(2, data.getAuthor());
			pstmt.setString(3, data.getTitle());
			pstmt.setString(4, data.getContent());
			
			int n = pstmt.executeUpdate();
			System.out.println("insert result : "+n);
			
		}catch(Exception e) {
			System.out.println("write() ERR : "+ e.getMessage());
		}
	}
	
}//클래스 끝

2. 컨트롤러 사용

board-servlet.xml의 요청 처리 과정 

 

웹브라우저로부터 http://~~~/list.do 라는 요청이 들어오면 

=> name="./list.do"

 

ListActionController 객체를 생성하고 

=>class="board.controller.ListActionController"

 

생성된 객체 내의 맴버 변수인 dao에게 <property name="dao">

 

미리 등록해 놓은 boardDAO 객체를 전달

<ref bean="boardDAO">

(DB연결 -> 처리)

 

=>handlerRequest 호출 

 

board-servlet.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 id="defaultHandlerMapping"  class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
	
	<!-- DB 접속 : JNDI 방식 -->
	<bean id="boardDAO" class="board.dao.BoardDAO"></bean>
	
	<!-- 글 목록 보기 컨트롤러 등록 : private dao => setDao(boardDAO)-->
	<bean name="/list.do" class="board.controller.ListActionController">
		<property name="dao">
			<ref bean="boardDAO" />
		</property>
	</bean>
	
	<!-- 글쓰기 화면 처리 컨트롤러 등록 : 스프링이 제공-->
	<bean name="/writeui.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
		<property name="viewName" value="write"></property>
		<!-- ModelAndView.setViewName("write") return mav 객체-->
	</bean>
	
	<!-- 글 저장 처리 컨트롤러 등록 -->
	<bean name="/write.do" class="board.controller.WrtieActionController">
		<property name="dao">
			<ref bean="boardDAO" />
		</property>
		<property name="commandClass" value="board.command.BoardCommand"></property>
		<!-- BoardCommand객체는 handle()세번째 매개변수에 자동 전달 -->
	</bean>
	
	<!-- viewResolver(위치, 이동할 페이지 지정) : "list" -->
	<bean id="viewResolover"  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <property name="viewClass"   value="org.springframework.web.servlet.view.InternalResourceView"/>
	    <property name="prefix" value="/"/> <!-- "/list" -->
	    <property name="suffix" value=".jsp"/><!-- "/list.jsp" -->
	</bean>
	

</beans>

오늘 만든 기능 

리스트 출력 관련 (메인화면)

list.do

ListActionController

list.jsp

DAO - list()

1. ListActionController

- Controller를 구현함 - 따로 입력값이 없어서 AbstractCommandController를 상속받을 필요 없음!

package board.controller;

import java.util.ArrayList;

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

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

import board.dao.BoardDAO;
import board.dto.BoardDTO;

public class ListActionController implements Controller {

	private BoardDAO dao;
	
	public ListActionController() {
		
	}//생성자 
	
	public void setDao(BoardDAO dao) {
		this.dao = dao;
		System.out.println("setDAO 호출 됨 ==> "+ dao);
	}

	/**요청사항이 전달 되면 자동 호출되는 메서드**/
	@Override
	public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
		System.out.println("ListActionController의 handleRequest() 자동 호출 됨 ");
		
		ArrayList<BoardDTO> list = dao.list();
		ModelAndView mav = new ModelAndView();
		mav.setViewName("list"); // list.jsp를 의미
		mav.addObject("list",list); 
		//requet.setAttribute("list",list);개념과 동일
		
		
		return mav;
	}

}

2. list.jsp

- View!

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList, board.dto.BoardDTO" %>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>list.jsp</title>
</head>
<body>
	<table border="1">
		<tr>
	 		<td colspan="5">게시판 목록 &nbsp;&nbsp;&nbsp;
	 			<a href="writeui.do">글쓰기</a>
	 		</td>
		</tr>
		
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		
		<!-- DispatcherServlet은 Controller로 부터 ModelAndView 객체를 반고 
		그 중 Model에 해당하는 객체를 list.jsp의 request에게 전달
		따라서 list.jsp는 request의 attribute 영역에서 해당 객체를 추출하여 사용가능 -->
		
		<%
			ArrayList<BoardDTO> list = (ArrayList)request.getAttribute("list");
			
			if(list != null){
		  		for(BoardDTO dto :list){
		  			int num = dto.getNum();
		  			String title = dto.getTitle();
		  			String author = dto.getAuthor();
		  			String writeday = dto.getDate();
		  			int readcnt = dto.getReadcnt();
		%>
					<tr>
						<td><%=num %></td>
						<td><a href="retrieve.do?num=<%=num %>"><%=title %></a></td>
						<td><%=author %></td>
						<td><%=writeday.substring(0,10) %></td>
						<td><%=readcnt %></td>
					</tr>
		<%
		  		}//for end
		  } //if end
		%>
	</table>
</body>
</html>

 

글쓰기 관련

write.do

WriteActionController

(BoardCommand)

write.jsp

DAO - newNum() / write()

 

1. WriteActionController

- AbstractCommandController를 상속 - 입력값이 있기 때문에!!

package board.controller;

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

import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;

import board.command.BoardCommand;
import board.dao.BoardDAO;

/* AbstractCommandController를 상속 받은 이유 
 * 사용자가 입력한 값을 외부로부터 자동으로 전달받기 위해 
 * 요청시 자동 호출 되는 handle()의 매개변수의 역할 
 * HttpServletRequest : reqeust객체 (요청객체)
 * HttpServletResponse : response 객체(응답객체)
 * Object : 입력 받은 값을 저장하는 객체 
 * BindException : 전달받을 값에 대한 오류를 예외처리
 * 
 * 따라서 이 컨트롤러 등록 시, 입력받은 값들을 저장할 수 있는 객체(BoardCommand)가 필요하고
 * 객체는 commanClass 변수를 통해 자동 전달한다.
 */
//입력된 값을 데이터 베이스에 저장하는 컨트롤러
public class WriteActionController extends AbstractCommandController {
	private BoardDAO dao;
	
	public WriteActionController() {
	}

	public void setDao(BoardDAO dao) {
		this.dao = dao;
		System.out.println("WriteActionController setDao() 호출   "+dao);
	}



	public WriteActionController(Class commandClass) {
		super(commandClass);
	}

	public WriteActionController(Class commandClass, String commandName) {
		super(commandClass, commandName);
	}

	@Override
	protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException error)
			throws Exception {
		BoardCommand data = (BoardCommand) command;
		
		//BoardDAO의 write메서드에게 data 객체를 전달 
		dao.write(data);
		
		//Spring방식 : ModelAndView
//		ModelAndView mav = new ModelAndView();
//		mav.setViewName("redirect:/list.do");
		
		return new ModelAndView("redirect:/list.do");
	}

}

2. write.jsp

- BoardCommand의 변수와 wirte.jsp의 파라미터 값(name)이 같아서 자동으로 연결됨

- board-servlet / write.do쪽으로 전달 된 후 여기서 WriteActionController로 연결됨 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>write.jsp</title>
</head>
<body>
	<form action="write.do">
		<tr>
			<td>제목</td>
			<td>
				<input type="text" name="title" />
			</td>
		</tr>
		<tr>
			<td>작성자</td>
			<td>
				<input type="text" name="author" />
			</td>
		</tr>
		<tr>
			<td>내용</td>
			<td>
				<textarea row="5" cols="30" name="content"></textarea>
			</td>
		</tr>
		<tr>
		 	<td><input type="submit" value="저장"/></td>
		</tr>
	</form>

</body>
</html>

3.BoardCommand.java

package board.command;

public class BoardCommand {

	//write.jsp의 파라미터 명과 같아야 자동맵칭 됨 
	private String content;
	private String author;
	private String title;
	
	public BoardCommand() {
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	
}

 

Comments