웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.06.29

shine94 2020. 6. 29. 09:05

1. 기존 배운 것에 추가, request parameter를 받는 방법
   @PathVariable : request parameter를 GET 방식의 query string이 아닌 URL 경로에 담아서 전달할 수 있다.

 

 

2. JSP MVC 모델 2의 경우 컨트롤러에서 수행하는 것을 Command 객체라 불렀으나
   스프링에서는 그와 같은 역할을 하는 객체를 Service라고 부른다(두 용어 혼용 가능)

 

 

3. 스프링에서 커맨드 객체는 parameter 받기 위한  bean객체이다.

 

 

4. STS11_RequestParameter

** [src/main/java] com.lec.beans.WriteDTO > HomeController 서블릿

package com.lec.sts11_param;

import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.lec.beans.WriteDTO;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
	// parameter 추출
	// handler 메소드에서도 서블릿에서 보앗던 HttpServletRequest, HttpServletResponse 매개변수 가능.!!!
	
	@RequestMapping(value = "/member/delete", method = RequestMethod.GET)   // -> /member/delete?id=34
	//public String delMember(Model model, HttpServletRequest request) {
	public String delMember(HttpServletRequest request, Model model) {		// 순서 바뀌어도 동작
		String id = request.getParameter("id");
		model.addAttribute("mbId", id);
		return "member/delete";
	}
	
	@RequestMapping(value="/member/regOk", method = RequestMethod.POST)
	public String regOKMember() {
		System.out.println("/member/regOk : POST");
		return "member/regOk";
	}
	
	@RequestMapping(value="/member/regOk", method = RequestMethod.GET)
	public String regOKMember(Model model) {
		System.out.println("/member/regOk : GET");
		return "member/regOk";
	}
	
	@RequestMapping(value = "/member/regist")
	public String registMember() {
		return "member/regist";
	}
	
	// GET/POST 둘다 받는 handler
	@RequestMapping(value = "/member/regOk2", 
			method = {RequestMethod.GET, RequestMethod.POST})
	public String regOkMember2() {
		return "member/regOk";
	}
	
	// handler 에
	// request parameter 의 name 값과 '같은 이름의 매개변수' 가 있으면
	// 바로 그 매개변수가 request parameter 값을 받아온다.
	
//	@RequestMapping("/member/find")
	//public String findMember(String id, String name, Model model) {
	//public String findMember(Model model, String name, String id) {	// 순서 무관
	
	// 숫자타입으로 하면 바로 parsing 하여 받는다.
	//public String findMember(Model model, String name, double id) {
	
	// 동일한 name의 request parameter 들.
//	public String findMember(Model model, String [] name, int [] id) {	
//		model.addAttribute("id", Arrays.toString(id));
//		model.addAttribute("name", Arrays.deepToString(name));
//	
//		return "member/find";
//	}
	
	// @RequestParam 사용
	@RequestMapping("/member/find")
	public String findMember(Model model,
			@RequestParam("id") String userid,   // name "id" parameter 값을 받아온다.
			@RequestParam("name") String username) {
		
		model.addAttribute("id", userid);
		model.addAttribute("name", username);
		
		return "member/find";		
	}
	
	// ------------------------------------------------------------
	// 커맨드 객체(Command Object)
	@RequestMapping("/board/write")
	public String writeBoard() {
		return "board/write";
	}
	
	// 기존 방식으로 구현하려면
	// 매 parameter 들을 매겨변수화 해야하기 때문에 힘들다.
//	@RequestMapping(value = "/board/writeOk", method= RequestMethod.POST)
//	public String writeOkBoard(
//		Model model, 
//		@RequestParam("name") String name,
//		@RequestParam("subject") String subject,
//		@RequestParam("content") String content
//		) {
//		WriteDTO dto = new WriteDTO();
//		dto.setName(name);
//		dto.setSubject(subject);
//		dto.setContent(content);
//		
//		model.addAttribute("dto", dto);
//		
//		return "board/writeOk";
//		
//	}
	
	// 커맨드 객체 사용
//	@RequestMapping(value = "/board/writeOk", method= RequestMethod.POST)
//	public String writeOkBoard(WriteDTO dto){
//		System.out.println(dto);
//		return "board/writeOk";		
//	}
		
	// 커맨드 객체에 attribute id 변경
	@RequestMapping(value = "/board/writeOk", method= RequestMethod.POST)
	public String writeOkBoard(
			@ModelAttribute("DTO") WriteDTO dto){
		System.out.println(dto);
		return "board/writeOk";		
	}
	
	// @PathVariable 방식
	@RequestMapping("/board/writePath/{name}/{subject}/{content}")
	public String writePathBorad(Model model,
			@PathVariable String name,
			@PathVariable String subject,
			@PathVariable String content) {
		model.addAttribute("name", name);
		model.addAttribute("subject", subject);
		model.addAttribute("content", content);
		return "board/writepath";
	}
	
	@RequestMapping("/member/ageCheck")
	public String chkAge(int age,
			RedirectAttributes redirectAttr) {
		redirectAttr.addAttribute("age", age);
		
		if(age < 19) {
			return "redirect:/member/underAge";
		} else {
			return "redirect:/member/adult";
		}
	}
	
	@RequestMapping("/member/underAge")
	public String pageUnderAge(
			@RequestParam("age") int age, Model model) {
		model.addAttribute("age", age);
		return "member/ageUnder";
	}
	
	@RequestMapping("/member/adult")
	public String pageAdult(
			@RequestParam("age") int age, Model model) {
		model.addAttribute("age", age);
		return "member/ageAdult";
	}
	
	@RequestMapping(value = "/common")	//  /common 으로 요청이 오면
	public String cccmmm() {        	// cccmmm() 핸들러가 수행되고.
		return "comn";     				// -->  /WEB-INF/views/comn.jsp   를 리턴하여 response 되게 한다.
	}
	
}

 

** src > main > webapp > WEB-INF > views > board > writeOk.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 
작성자: ${dto.name }<br>
글제목: ${dto.subject }<br>
내용: ${dto.content }<br>
-->
<!-- 
작성자: ${writeDTO.name }<br>
글제목: ${writeDTO.subject }<br>
내용: ${writeDTO.content }<br>
uid: ${writeDTO.uid }<br>
조회수: ${writeDTO.viewCnt }<br>
등록일: ${writeDTO.regDate }<br>
-->
작성자: ${DTO.name }<br>
글제목: ${DTO.subject }<br>
내용: ${DTO.content }<br>
uid: ${DTO.uid }<br>
조회수: ${DTO.viewCnt }<br>
등록일: ${DTO.regDate }<br>

 

** src > main > webapp > WEB-INF > views > board > write.jsp

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

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>글작성</title>
</head>
<script>
function chkSubmit(){  // 폼 검증
	frm = document.forms["frm"];
	
	var name = frm["name"].value.trim();
	var subject = frm["subject"].value.trim();
	
	if(name == ""){
		alert("작성자 란은 반드시 입력해야 합니다");
		frm["name"].focus();
		return false;
	}
	if(subject == ""){
		alert("제목은 반드시 작성해야 합니다");
		frm["subject"].focus();
		return false;
	}
	return true;
}

</script>
<body>
<h2>글작성</h2>
<%-- 글 내용이 많을수 있기 때문에 POST 방식 사용 --%>
<form name="frm" action="writeOk" method="post" onsubmit="return chkSubmit()">

<%-- int 매개변수 받는 setter도 동작할까? --%>
<%-- 동작한다, 자동적으로 spring에서 파싱해줌, 
	  대신, int를 제외한 타입을 입력 받으면 java.lang.NumberFormatException 에러 발생 --%>
uid: 
<input type="text" name="uid" value="123"/><br>

작성자:
<input type="text" name="name" value="장윤성"/><br>
제목:
<input type="text" name="subject" value="와 점심이다"/><br>
내용:<br>
<textarea name="content">맛있어용~.</textarea>
<br><br>
<input type="submit" value="등록"/>
</form>
<br>
<button type="button" onclick="location.href='list.jsp'">목록으로</button>


</body>
</html>

 

** src > main > webapp > WEB-INF > views > board > writepath.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
작성자: ${name }<br>
글제목: ${subject }<br>
내용: ${content }<br>

 

** src > main > webapp > WEB-INF > views > member > ageUnder.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
미성년자입니다<br>
나이: ${age }살<br>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > member > ageAdult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
성인입니다<br>
나이: ${age }살<br>
<jsp:include page="/common"/>

 

** src > main > webapp > WEB-INF > views > comn.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String servlet_request_uri = (String)request.getAttribute("javax.servlet.forward.request_uri");
	String conPath = request.getContextPath();
	
	//System.out.println(servlet_request_uri);
	//System.out.println(conPath);
	
	String servlet_reqpath = servlet_request_uri.substring(conPath.length());
	
	String uri = request.getRequestURI();
	String reqPath = uri.substring(conPath.length());
	String url = request.getRequestURL().toString();
	
	// jsp 파일명
	String jspFile = uri.substring(uri.lastIndexOf("/") + 1, uri.length());
	String jspName = uri.substring(uri.lastIndexOf("/") + 1, uri.length() - 4);
	
	request.setAttribute("jspName", jspName);
%>    
    
    
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= jspName %></title>
<link rel="stylesheet" type="text/css" 
	href="${pageContext.request.contextPath }/CSS/sts_common.css">
</head>
<body>
<hr>
<div class="sts">
<b>Servlet</b><br>
request URI : <span><%= servlet_request_uri %></span><br>
context path : <span><%= conPath %></span><br>
request path : <span><%= servlet_reqpath %></span><br>
VIEW file : <span><%= jspFile %></span><br>
<hr>
<b>VIEW(JSP)</b><br>
url : <span><%= url %></span><br>
VIEW Path : <span><%= reqPath %></span><br>
uri : <span><%= uri %></span><br>
</div>


</body>
</html>

 

 

5. 폼 데이터 검증(Parameter Validation)
 : 신뢰성 있는 웹 어플리케이션 작성을 위해 폼데이터 검증 필수,
   기본적으로 폼데이터는 2단계 걸쳐 검증 필요

 

[1단계] 클라이언트에서 submit하기 전에 검증 : JavaScript 사용


[2단계] 서버에서 검증 : Spring, JSP 등 사용

 

 

6. STS12_Validation

1) uid 값은 반드시 숫자 입력 : 비어 있으면 안됨 

2) name은 반드시 입력 : 비어 있으면 안됨

 

** src > main > webapp > WEB-INF > web.xml -> filter 추가

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- 스프링 컨테이너 인코딩 설정 -->
	<filter>
		<filter-name>encodingFilter</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>
		<init-param>
			<param-name>forceEncoding</param-name>  
			<param-value>true</param-value>
		</init-param>
	</filter>    

	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>                 
	</filter-mapping>

</web-app>

 

** [src/main/java] com.lec.beans > WriteDTO.java

package com.lec.beans;

// DTO : Data Trasfer Object
//    데이터를 담아 나르기 위한 객체

// 게시글DTO, 회원DTO, ... 필요한 데이터 객체들 만큼 정의
// Bean 객체

public class WriteDTO {
	private int uid;     // wr_uid
	private String subject;   //wr_subject
	private String content;   //wr_content
	private String name;  // wr_name
	private int viewCnt;   // wr_viewcnt
	private String regDate;   // wr_regdate
	
	// 개발시..
	// 다음 3가지 네이밍은 일치시켜주는 것이 좋다 .
	// 클래스 필드명 = DB 필드명  = form 의 name명
	
	// 기본생성자, 매개변수 생성자
	public WriteDTO() {
		super();
		System.out.println("WriteDTO() 객체 생성");
	}
	public WriteDTO(int uid, String subject, String content, String name, int viewCnt) {
		super();
		this.uid = uid;
		this.subject = subject;
		this.content = content;
		this.name = name;
		this.viewCnt = viewCnt;
		System.out.println("WriteDTO(uid, subject, content, name, viewCnt) 객체 생성");
	}
	
	// getter / setter
	public int getUid() {
		System.out.println("getUid() 호출");
		return uid;
	}
	public void setUid(int uid) {
		System.out.println("setUid(" + uid + ") 호출");
		this.uid = uid;
	}
	public String getSubject() {
		System.out.println("getSubject() 호출");
		return subject;
	}
	public void setSubject(String subject) {
		System.out.println("setSubject(" + subject + ") 호출");
		this.subject = subject;
	}
	public String getContent() {
		System.out.println("getContent() 호출");
		return content;
	}
	public void setContent(String content) {
		System.out.println("setContent(" + content + ") 호출");
		this.content = content;
	}
	public String getName() {
		System.out.println("getName() 호출");
		return name;
	}
	public void setName(String name) {
		System.out.println("setName(" + name + ") 호출");
		this.name = name;
	}
	public int getViewCnt() {
		System.out.println("getViewCnt() 호출");
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		System.out.println("setViewCnt(" + viewCnt + ") 호출");
		this.viewCnt = viewCnt;
	}
	public String getRegDate() {
		System.out.println("getRegDate() 호출");
		return regDate;
	}
	public void setRegDate(String regDate) {
		System.out.println("setRegDate(" + regDate + ") 호출");
		this.regDate = regDate;
	}
	
	// 테스트, 개발용으로 toString() 오버라이딩 하면 좋다.
	@Override
	public String toString() {
		return "WriteDTO] " + uid + " : " + subject + " : " 
			+ content + " : " + name + " : " + viewCnt + " : " + regDate;
	}
	
} // end DTO

 

** [src/main/java] com.lec.sts12_validation > BoardController.java 

package com.lec.sts12_validation;

import java.util.List;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lec.beans.WriteDTO;

@Controller
@RequestMapping("/board")
public class BoardController {

	@RequestMapping("write.do")
	public String write() {
		return "board/write";
	}
	
	@RequestMapping("writeOk.do")
	//public String writeOk(@ModelAttribute("w") WriteDTO dto,
	public String writeOk(@ModelAttribute("w") @Valid WriteDTO dto,
			BindingResult result) {	// ← validator 가 유효성 검사를 한 결과가 담긴 객체
		System.out.println("writeOk(): " + dto.getUid() + ":" + dto.getName());
		//System.out.println("에러 개수 : " + result.getErrorCount());	// 바인딩 과정에서 발생한 에러 개수
		//System.out.print("validate전 " ); showErrors(result);
		
		String page = "board/writeOk";
		
		// validator 객체 생성
		//BoardValidator validator = new BoardValidator();
		//validator.validate(dto, result);
		System.out.print("validate후 " ); showErrors(result);
		
		if(result.hasErrors()) {	// 에러 있으면
			page = "board/write";	// 원래 폼으로 돌아가기!
		}
		
		return page;
	}
	
	// error에 담겨 있는 에러 들을 다 출력하기
	public void showErrors(Errors errors) {
		if(errors.hasErrors()) {
			System.out.println("에러 개수 : " + errors.getErrorCount());
			System.out.println("\t[field]\t|[code]");
			List<FieldError> errList = errors.getFieldErrors();
			
			for(FieldError err : errList) {
				System.out.println("\t" + err.getField() + "\t|" + err.getCode());
			}
			
		} else {
			System.out.println("에러 없음");
		}
		
	}
	
	// 이 컨트롤러 클래스의 handler 에서 폼 데이터를 바인딩 할때 검증하는 개체 지정
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setValidator(new BoardValidator());
	}
	
}


** src > main > webapp > WEB-INF > views > board > write.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>글 작성</title>
<style>
span { color: red;}
</style>
</head>
<body>
<form action="writeOk.do">
uid(<span>숫자</span>): 
	<input type="text" name="uid" value="${w.uid }"><br>
작성자(<span>*</span>): 
	<input type="text" name="name" value="${w.name }"><br>
제목(<span>*</span>):
	<input type="text" name="subject" value="${w.subject }"/><br>
<input type="submit" value="등록"></br>
</form>
</body>
</html>


** src > main > webapp > WEB-INF > views > board > writeOk.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
uid : ${w.uid}<br>
작성자 : ${w.name}<br>
제목 : ${w.subject }<br>
<button onclick="history.back()">돌아가기</button>


** [src/main/java] com.lec.sts12_validation > BoardValidator.java

package com.lec.sts12_validation;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.lec.beans.WriteDTO;

public class BoardValidator implements Validator {

	// 이 Validator 가 제공하는 Class의 인스턴스(clazz)를 유효성 검사할 수 있는가?
	@Override
	public boolean supports(Class<?> clazz) {
		// ↓ 검증할 객체의 클래스 타입인지 확인 : WriteDTO = clazz; 가능 여부
		return WriteDTO.class.isAssignableFrom(clazz);
	}

	// 주어진 객체(target)에 대한 유효성 검사를 하고
	// 유효성 검사에 오류가 있는 경우, 주어진 객체에 이 오류들을 errors 에 등록한다.
	@Override
	public void validate(Object target, Errors errors) {
		System.out.println("validate()");
		WriteDTO dto = (WriteDTO)target;
		
		// 수행할 parameter 검증들.
		int uid = dto.getUid();
		if(uid == 0) {
			System.out.println("uid 오류");
			// 에러 등록 rejectValue(field, errorCode)
			errors.rejectValue("uid", "invalidUid");
		}
		
		String name = dto.getName();
		if(name == null || name.trim().isEmpty()) {
			System.out.println("name 오류 : 반드시 한글자 입력 필요합니다");
			errors.rejectValue("name", "empthName");
		}
		
		// ValidationUtils 사용
		// 단순히 빈 폼 데이터를 처리할때는 아래와 같이 사용 가능.
		// 두번째 매개변수 "subject" 는 반드시 target 클래스 필드명이어야 함.
		// 이는 Errors 에 등록될때에도 동일한 field 명으로 등록된다.
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "subject", "emptySubject");
		
	}

}


** validate()를 스프링 프레임워크에서 호출 : pom.xml에 <dependency> 추가

[참고] Validator 인터페이스를 구현한 클래스를 만들고, validate() 메소드를 직접 호출하여 사용 가능

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.lec</groupId>
	<artifactId>sts12_validation</artifactId>
	<name>STS12_Validation</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>5.2.1.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
		
		
		<dependency>
		    <groupId>org.hibernate.validator</groupId>
		    <artifactId>hibernate-validator</artifactId>
		    <version>6.1.5.Final</version>
		</dependency>
		        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

[추가] https://mvnrepository.com을 이용하여 추가, hibernate validator 검색

[추가] pom.xml에 <dependency> 추가 후 Update Maven Project 필수 : 단축키 Alt + F5

 

 

7. spring-jdbc를 활용한 JDBC 프로그래밍
 : 스프링에서 제공하는 spring-jdbc를 사용하면 반복되고 번거로운 작업들이 단순화 될 수 있다.

 

 

8. DBMS 라이브러리 세팅
 : Maven 빌드 사용시, 주요 DBMS의 라이브러리를 가져올 수 있다.

 

[Spring에서 오라클 라이브러리 추가] pom.xml에서 추가, 설정하기

<!--dependencies 위에 설정 -->
<repositories>
  <repository>
    <id>oracle</id>
    <name>ORACLE JDBC Repository</name>

    <url>https://code.lds.org/nexus/content/groups/main-repo</url>

  </repository>
</repositories>

 

<!-- dependencies 안쪽 에 설정 -->
<!-- ojdbc6 -->
<dependency>

  <groupId>com.oracle</groupId>

  <artifactId>ojdbc6</artifactId>
  <version>11.2.0.3</version>
</dependency>

 

<!-- spring jdbc 사용 -->  
<dependency>  
  <groupId>org.springframework</groupId>  
  <artifactId>spring-jdbc</artifactId>  
  <version>${org.springframework-version}</version>  
</dependency>

 

[정상적으로 다운되면 Maven Dependencies에서 spring-jdbc와 spring-tx 파일이 확인 가능]

 

 

9. STS13_JDBC, 과거 JSP MVC 모델 2 방식의 게시판을 스프링으로 옮기기

** src > main > webapp > WEB-INF > web.xml에 filter 장착

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- 스프링 컨테이너 인코딩 설정 -->
	<filter>
		<filter-name>encodingFilter</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>
		<init-param>
			<param-name>forceEncoding</param-name>  
			<param-value>true</param-value>
		</init-param>
	</filter>    

	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>                 
	</filter-mapping>

</web-app>

 

** 메이븐 세팅파일 pom.xml에 오라클 라이브러리, spring jdbc 추가

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.lec</groupId>
	<artifactId>sts13_jdbc</artifactId>
	<name>STS13_JDBC</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	
	
	<!-- Maven 빌드를 사용하는 Spring 에서 오라클 라이브러리 추가하기 -->
	<!--dependencies 위에 설정 -->
	<repositories>
        <repository>
         <id>oracle</id>
         <name>ORACLE JDBC Repository</name>
         <url>https://code.lds.org/nexus/content/groups/main-repo</url>
        </repository>
	</repositories>
	
	
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>  
		
		
		<!-- dependencies 안쪽 에 설정 -->
		<!-- ojdbc6 -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>
            

	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

** [src/main/java] old > D.java

package old;

/*
 * DB 접속 정보, 쿼리문, 테이블명, 컬럼명 등은
 * 별도로 관리하든지
 * XML, 초기화 파라미터 등에서 관리하는 것이 좋다.
 */
public class D {
	public static final String DRIVER = "oracle.jdbc.driver.OracleDriver";  // JDBC 드라이버 클래스
	public static final String URL = "jdbc:oracle:thin:@localhost:1521:XE";  // DB 접속 URL
	public static final String USERID = "scott0316";  // DB 접속 계정 정보
	public static final String USERPW = "tiger0316";
	
	public static final String SQL_WRITE_SELECT = 
			"SELECT * FROM test_write ORDER BY wr_uid DESC"; 

	public static final String SQL_WRITE_INSERT = "INSERT INTO test_write " +
		"(wr_uid, wr_subject, wr_content, wr_name) " +
		"VALUES(test_write_seq.nextval, ?, ?, ?)";

	public static final String SQL_WRITE_INC_VIEWCNT =  // 조회수 증가
			"UPDATE test_write SET wr_viewcnt = wr_viewcnt + 1 WHERE wr_uid = ?";

	public static final String SQL_WRITE_SELECT_BY_UID =  // 글 읽어 오기
			"SELECT * FROM test_write WHERE wr_uid = ?";

	public static final String SQL_WRITE_UPDATE = 
			"UPDATE test_write SET wr_subject = ?, wr_content = ? WHERE wr_uid = ?";

	public static final String SQL_WRITE_DELETE_BY_UID = 
			"DELETE FROM test_write WHERE wr_uid = ?";

}

 

** [src/main/java] old > WriteDTO.java 

package old;

// DTO : Data Transfer Object
//    데이터를 담아 나르기 위한 객체

// 게시글DTO, 회원DTO, ... 필요한 데이터 객체들 만큼 정의
// Bean 객체

public class WriteDTO {
	private int uid;     // wr_uid
	private String subject;   //wr_subject
	private String content;   //wr_content
	private String name;  // wr_name
	private int viewCnt;   // wr_viewcnt
	private String regDate;   // wr_regdate
	
	// 개발시..
	// 다음 3가지 네이밍은 일치시켜주는 것이 좋다 .
	// 클래스 필드명 = DB 필드명  = form 의 name명
	
	// 기본생성자, 매개변수 생성자
	public WriteDTO() {
		super();
		System.out.println("WriteDTO() 객체 생성");
	}
	public WriteDTO(int uid, String subject, String content, String name, int viewCnt) {
		super();
		this.uid = uid;
		this.subject = subject;
		this.content = content;
		this.name = name;
		this.viewCnt = viewCnt;
		System.out.println("WriteDTO(uid, subject, content, name, viewCnt) 객체 생성");
	}
	
	// getter / setter
	public int getUid() {
		System.out.println("getUid() 호출");
		return uid;
	}
	public void setUid(int uid) {
		System.out.println("setUid(" + uid + ") 호출");
		this.uid = uid;
	}
	public String getSubject() {
		System.out.println("getSubject() 호출");
		return subject;
	}
	public void setSubject(String subject) {
		System.out.println("setSubject(" + subject + ") 호출");
		this.subject = subject;
	}
	public String getContent() {
		System.out.println("getContent() 호출");
		return content;
	}
	public void setContent(String content) {
		System.out.println("setContent(" + content + ") 호출");
		this.content = content;
	}
	public String getName() {
		System.out.println("getName() 호출");
		return name;
	}
	public void setName(String name) {
		System.out.println("setName(" + name + ") 호출");
		this.name = name;
	}
	public int getViewCnt() {
		System.out.println("getViewCnt() 호출");
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		System.out.println("setViewCnt(" + viewCnt + ") 호출");
		this.viewCnt = viewCnt;
	}
	public String getRegDate() {
		System.out.println("getRegDate() 호출");
		return regDate;
	}
	public void setRegDate(String regDate) {
		System.out.println("setRegDate(" + regDate + ") 호출");
		this.regDate = regDate;
	}
	
	// 테스트, 개발용으로 toString() 오버라이딩 하면 좋다.
	@Override
	public String toString() {
		return "WriteDTO] " + uid + " : " + subject + " : " 
			+ content + " : " + name + " : " + viewCnt + " : " + regDate;
	}
	
} // end DTO

 

** [src/main/java] old > WriteDAO.java 

package old;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;


// DAO : Data Access Object
//   DB 에 접속하여 트랜잭션을 수행하는 객체

// 다루는 데이터 소스의 종류에 따라 DAO는 여러개 정의 사용 가능

public class WriteDAO {
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;   // SELECT 결과, executeQuery()
	
	// DAO 객체가 생성될때 Connection 도 생성된다.
	public WriteDAO() {
		
		try {
			Class.forName(D.DRIVER);
			conn = DriverManager.getConnection(D.URL, D.USERID, D.USERPW);
			System.out.println("WriteDAO 생성, 데이터 베이스 연결!");
		} catch(Exception e) {
			e.printStackTrace();
			// throw e;
		}		
		
	} // 생성자

	// DB 자원 반납 메소드,
	public void close() throws SQLException {
		if(rs != null) rs.close();
		if(pstmt != null) pstmt.close();
		if(stmt != null) stmt.close();
		if(conn != null) conn.close();
	} // end close()
	
	// 새글 작성 <-- DTO
	public int insert(WriteDTO dto) throws SQLException {
		String subject = dto.getSubject();
		String content = dto.getContent();
		String name = dto.getName();
		
		int cnt = this.insert(subject, content, name);
		return cnt;
	}
	
	// 새글 작성 <-- 제목, 내용, 작성자 
	public int insert(String subject, String content, String name) throws SQLException {
		int cnt = 0;
		
		try {			
			pstmt = conn.prepareStatement(D.SQL_WRITE_INSERT);
			pstmt.setString(1, subject);
			pstmt.setString(2, content);
			pstmt.setString(3, name);
			
			cnt = pstmt.executeUpdate();
		} finally {
			close();			
		}

		return cnt;
	}
	
	// ResultSet --> DTO 배열로 리턴
	public WriteDTO [] createArray(ResultSet rs) throws SQLException {
		WriteDTO [] arr = null;  // DTO 배열
		
		ArrayList<WriteDTO> list = new ArrayList<WriteDTO>();
		
		while(rs.next()) {
			int uid = rs.getInt("wr_uid");
			String subject = rs.getString("wr_subject");
			String name = rs.getString("wr_name");
			String content = rs.getString("wr_content");
			int viewCnt = rs.getInt("wr_viewcnt");
			Date d = rs.getDate("wr_regdate");
			Time t = rs.getTime("wr_regdate");
			
			String regDate = "";
			if(d != null){
				regDate = new SimpleDateFormat("yyyy-MM-dd").format(d) + " "
						+ new SimpleDateFormat("hh:mm:ss").format(t);
			}
			
			WriteDTO dto = new WriteDTO(uid, subject, content, name, viewCnt);
			dto.setRegDate(regDate);
			list.add(dto);
			
		} // end while
		
		int size = list.size();
		
		if(size == 0) return null;
		
		arr = new WriteDTO[size];
		list.toArray(arr);  // List -> 배열		
		return arr;
	}
	
	// 전체 SELECT
	public WriteDTO [] select() throws SQLException {
		WriteDTO [] arr = null;
		
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT);
			rs = pstmt.executeQuery();
			arr = createArray(rs);
		} finally {
			close();
		}		
		
		return arr;
	} // end select()
	
	// 특정 uid 의 글 내용 읽기, 조회수 증가
	// viewCnt 도 1 증가 해야 하고, 글 읽어와야 한다 --> 트랜잭션 처리
	public WriteDTO [] readByUid(int uid) throws SQLException{
		int cnt = 0;
		WriteDTO [] arr = null;
		
		try {
			// 트랜잭션 처리
			// Auto-commit 비활성화
			conn.setAutoCommit(false);
			
			// 쿼리들 수행
			pstmt = conn.prepareStatement(D.SQL_WRITE_INC_VIEWCNT);
			pstmt.setInt(1, uid);
			cnt = pstmt.executeUpdate();
			
			pstmt.close();
			
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT_BY_UID);
			pstmt.setInt(1, uid);
			rs = pstmt.executeQuery();
			
			arr = createArray(rs);
			conn.commit();
			
		} catch(SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			close();
		}
		
		return arr;
	} // end readByUid()
	
	
	// 특정 uid 의 글 만 SELECT (조회수 증가 없슴!)
	public WriteDTO [] selectByUid(int uid) throws SQLException {
		WriteDTO [] arr = null;
		
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT_BY_UID);
			pstmt.setInt(1, uid);
			rs = pstmt.executeQuery();
			arr = createArray(rs);
		} finally {
			close();
		}
		return arr;
	}
	
	
	// 특정 uid 의 글 수정 (제목, 내용)
	public int update(int uid, String subject, String content) throws SQLException {
		int cnt = 0;
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_UPDATE);
			pstmt.setString(1, subject);
			pstmt.setString(2, content);
			pstmt.setInt(3, uid);
			
			cnt = pstmt.executeUpdate();
		} finally {
			close();
		}		
		
		return cnt;
	} // end update()
	
	// 특정 uid 글 삭제하기
	public int deleteByUid(int uid) throws SQLException {
		int cnt = 0;
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_DELETE_BY_UID);
			pstmt.setInt(1, uid);
			cnt = pstmt.executeUpdate();
		} finally {
			close();
		}		
		return cnt;
	} // end deleteByUid()
	
} // end DAO

 

** [src/main/java] old > Command 인터페이스

package old;

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

public interface Command {
	void execute(HttpServletRequest request, HttpServletResponse response);
}

 

** [src/main/java] old > ListCommand.java 

package old;

import java.sql.SQLException;

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

public class ListCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		
		WriteDAO dao = new WriteDAO();  // DAO 객체 생성
		WriteDTO [] arr = null;  
		
		try {
			// 트랜잭션 수행
			arr = dao.select();
			
			// "list" 란 name 으로 request 에 arr 값 전달
			// 즉 request 에 담아서 컨트롤러에 전달되는 셈.
			request.setAttribute("list", arr);
			
		} catch(SQLException e) {
			// 만약 CP 사용한다면
			// NamingException 도 처리 해야 함.
			
			e.printStackTrace();
		}
	}
}

 

** [src/main/java] old > WriteCommand.java 

package old;

import java.sql.SQLException;

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


public class WriteCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		
		int cnt = 0;
		WriteDAO dao = new WriteDAO();
		
		// 매개변수 받아오기
		String name = request.getParameter("name");
		String subject = request.getParameter("subject");
		String content = request.getParameter("content");
		
		if(name != null && subject != null &&
				name.trim().length() > 0 && subject.trim().length() > 0) {
			
			try {
				cnt = dao.insert(subject, content, name);
			} catch(SQLException e) {
				e.printStackTrace();
			}
			
		} // end if
			
		request.setAttribute("result", cnt);

	} // end execute()

} // end Command

 

** [src/main/java] old > ViewCommand.java

package old;

import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ViewCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		WriteDAO dao = new WriteDAO();
		WriteDTO [] arr = null;
		int uid = Integer.parseInt(request.getParameter("uid"));  // 매개변수 검증 필요

		try {
			arr = dao.readByUid(uid);  // 읽기 + 조회수 증가
			request.setAttribute("list", arr);
		} catch (SQLException e) { // 만약 ConnectionPool 을 사용한다면 여기서 NamingException 도 catch 해야 한다  
			e.printStackTrace();
		}

	}

}

 

** [src/main/java] old > SelectCommand.java 

package old;
import java.sql.SQLException;

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

public class SelectCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		WriteDAO dao = new WriteDAO();
		WriteDTO [] arr = null;
		int uid = Integer.parseInt(request.getParameter("uid"));  // 매개변수 검증 필요

		try {
			arr = dao.selectByUid(uid);  // 읽기 only
			request.setAttribute("list", arr);
		} catch (SQLException e) { // 만약 ConnectionPool 을 사용한다면 여기서 NamingException 도 catch 해야 한다  
			e.printStackTrace();
		}
	}

}

 

** [src/main/java] old > UpdateCommand.java 

package old;

import java.sql.SQLException;

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

public class UpdateCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		int cnt = 0;

		WriteDAO dao = new WriteDAO();

		//입력한 값을 받아오기
		int uid = Integer.parseInt(request.getParameter("uid"));
		String subject = request.getParameter("subject");
		String content = request.getParameter("content");

		// 유효성 체크  null 이거나, 빈문자열이면 이전화면으로 돌아가기
		if(subject != null && subject.trim().length() > 0){			
			try {			
				cnt = dao.update(uid, subject, content);
			} catch (SQLException e) {
				e.printStackTrace();
			}

		} // end if

		request.setAttribute("result", cnt);

	}

}

 

** [src/main/java] old > DeleteCommand.java 

package old;

import java.sql.SQLException;

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


public class DeleteCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		int cnt = 0;

		WriteDAO dao = new WriteDAO();

		//입력한 값을 받아오기
		int uid = Integer.parseInt(request.getParameter("uid"));

		try {			
			cnt = dao.deleteByUid(uid);
		} catch (SQLException e) {
			e.printStackTrace();
		}

		request.setAttribute("result", cnt);
	}

}

 

** [src/main/java] com.lec.sts13_jdbc.old > OldController.java 

package com.lec.sts13_jdbc.old;

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

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

import old.*;

@Controller
@RequestMapping("/old")
public class OldController {
	
	@RequestMapping("/list.do")
	public String list(HttpServletRequest request, HttpServletResponse response) {
		new ListCommand().execute(request, response);
		return "old/list";
	}
	
	@RequestMapping("/write.do")
	public String write(HttpServletRequest request, HttpServletResponse response) {
		return "old/write";
	}
	
	@RequestMapping("/writeOk.do")
	public String writeOk(HttpServletRequest request, HttpServletResponse response) {
		new WriteCommand().execute(request, response);
		return "old/writeOk";
	}
	
	@RequestMapping("/view.do")
	public String view(HttpServletRequest request, HttpServletResponse response) {
		new ViewCommand().execute(request, response);
		return "old/view";
	}
	
	@RequestMapping("/update.do")
	public String update(HttpServletRequest request, HttpServletResponse response) {
		new SelectCommand().execute(request, response);
		return "old/update";
	}
	
	@RequestMapping("/updateOk.do")
	public String updateOk(HttpServletRequest request, HttpServletResponse response) {
		new UpdateCommand().execute(request, response);
		return "old/updateOk";
	}
	
	@RequestMapping("/deleteOk.do")
	public String deleteOk(HttpServletRequest request, HttpServletResponse response) {
		new DeleteCommand().execute(request, response);
		return "old/deleteOk";
	}
	
}

 


9. 기존 JSP, DAO+DTO 버전의 JDBC 프로그래밍 반복적인 작업이 많았다
 : 아래의 4단계를 트랜잭션 페이지마다 반복함 


① 드라이버 로드 : DriverManager > ② 데이터베이스 연결 : Connection
> ③ SQL문 실행 : Statement, PreparedStatement, ResultSet > ④ 해제 : close()

 

 

10. 스프링 JdbcTemplate 객체
 : 기존 JSP에서 반복되고 번거로운 작업을 spring-jdbc 라이브러리의 JdbcTemplate 객체를 이용하여 통합관리한다.

 

 

11. 빈(bean)으로 관리

 : 코드 간결화의 효과,

   JdbcTemplate 객체는 스프링 컨테이너 안에 빈(bean)으로 생성되어 Java에서 필요할때마다 가져다 사용(주입받음) 

** DispatcherServlet이 생성될 때, Spring Container도 생성(즉 Container 안의 JdbcTemplate 빈(bean) 객체도 생성)

 

 

12.  STS13_JDBC, spring-jdbc 버전 게시판

** [src/main/java] com.lec.sts13_jdbc.board > C.java

package com.lec.sts13_jdbc.board;

import org.springframework.jdbc.core.JdbcTemplate;

public class C {
	// 스프링 컨테이너에 생성된 JdbcTemplate을 받아와서
	// 언제든지 원할때마다 가져다 쓸 수 있도록 public static 으로 설정
	public static JdbcTemplate template;
	
	// 게시글 관련 쿼리문
	public static final String SQL_WRITE_SELECT = 
			"SELECT wr_uid \"uid\", wr_subject subject, "
			+ "wr_content content, wr_name name, wr_viewcnt viewcnt, "
			+ "wr_regdate regdate FROM test_write ORDER BY wr_uid DESC";

	public static final String SQL_WRITE_SELECT_BY_UID = // 글 읽어 오기
			"SELECT wr_uid \"uid\", wr_subject subject, "
			+ "wr_content content, wr_name name, wr_viewcnt viewcnt, "
			+ "wr_regdate regdate FROM test_write WHERE wr_uid=?";

	public static final String SQL_WRITE_INSERT = "INSERT INTO test_write " +
		"(wr_uid, wr_subject, wr_content, wr_name) " +
		"VALUES(test_write_seq.nextval, ?, ?, ?)";

	public static final String SQL_WRITE_INC_VIEWCNT =  // 조회수 증가
			"UPDATE test_write SET wr_viewcnt = wr_viewcnt + 1 WHERE wr_uid = ?";


	public static final String SQL_WRITE_UPDATE = 
			"UPDATE test_write SET wr_subject = ?, wr_content = ? WHERE wr_uid = ?";

	public static final String SQL_WRITE_DELETE_BY_UID = 
			"DELETE FROM test_write WHERE wr_uid = ?";

}

 

** [src/main/java] com.lec.sts13_jdbc.board.beans > BWriteDTO.java

package com.lec.sts13_jdbc.board.beans;

import java.sql.Timestamp;

public class BWriteDTO {
	private int uid;     	// wr_uid
	private String subject;	//wr_subject
	private String content;	//wr_content
	private String name;	// wr_name
	private int viewCnt;	// wr_viewcnt
	private Timestamp regDate;	// wr_regdate
	
	public BWriteDTO() {
		super();
	}
	public BWriteDTO(int uid, String subject, String content, String name, int viewCnt, Timestamp regDate) {
		super();
		this.uid = uid;
		this.subject = subject;
		this.content = content;
		this.name = name;
		this.viewCnt = viewCnt;
		this.regDate = regDate;
	}
	
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getViewCnt() {
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		this.viewCnt = viewCnt;
	}
	public Timestamp getRegDate() {
		return regDate;
	}
	public void setRegDate(Timestamp regDate) {
		this.regDate = regDate;
	}

}

 

** [src/main/java] com.lec.sts13_jdbc.board.beans > BWriteDAO.java

package com.lec.sts13_jdbc.board.beans;

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

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;

import com.lec.sts13_jdbc.board.C;

public class BWriteDAO {
	JdbcTemplate template;
	
	public BWriteDAO() {
		this.template = C.template;
	}
	
	// 전체 SELECT
	public List<BWriteDTO> select() {
		// 이렇게 간단해진다!
		return template.query(C.SQL_WRITE_SELECT,
				new BeanPropertyRowMapper<BWriteDTO>(BWriteDTO.class));
	}
	
	public int insert(final BWriteDTO dto) {
		
		
		// 1. update() + PreparedStatementSetter() 
//		return
//		template.update(C.SQL_WRITE_INSERT, new PreparedStatementSetter() {
//			@Override
//			public void setValues(PreparedStatement ps) throws SQLException {
//				ps.setString(1, dto.getSubject());
//				ps.setString(2, dto.getContent());
//				ps.setString(3, dto.getName());				
//			}
//		} );
		
		
		// 2. update() + PreparedStatementCreator()
		return
		template.update(new PreparedStatementCreator() {
			
			@Override
			public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
				
				PreparedStatement ps = con.prepareStatement(C.SQL_WRITE_INSERT);
				ps.setString(1, dto.getSubject());
				ps.setString(2, dto.getContent());
				ps.setString(3, dto.getName());
	
				return ps;
			}
		});
		
	}

}

 

** [src/main/java] com.lec.sts13_jdbc.board.command > BCommand 인터페이스

package com.lec.sts13_jdbc.board.command;

import org.springframework.ui.Model;

public interface BCommand {
	void execute(Model model);
}

 

** [src/main/java] com.lec.sts13_jdbc.board.command > BListCommand.java

package com.lec.sts13_jdbc.board.command;

import java.util.List;

import org.springframework.ui.Model;

import com.lec.sts13_jdbc.board.beans.*;

public class BListCommand implements BCommand {

	@Override
	public void execute(Model model) {
		BWriteDAO dao = new BWriteDAO();
		List<BWriteDTO> list = dao.select();
		model.addAttribute("list", list);
	}

}

 

** [src/main/java] com.lec.sts13_jdbc.board.command > BWriteCommand.java

package com.lec.sts13_jdbc.board.command;

import java.util.Map;

import org.springframework.ui.Model;

import com.lec.sts13_jdbc.board.beans.BWriteDAO;
import com.lec.sts13_jdbc.board.beans.BWriteDTO;

public class BWriteCommand implements BCommand {

	@Override
	public void execute(Model model) {
		
		// Model 안에 있는 값(attribute) 꺼내기
		Map<String, Object> map= model.asMap();
		BWriteDTO dto = (BWriteDTO)map.get("dto");
		BWriteDAO dao = new BWriteDAO();
		int result = dao.insert(dto);
		model.addAttribute("result", result);
	}

}

 

** [src/main/java] com.lec.sts13_jdbc.board.controller > BoardController.java

package com.lec.sts13_jdbc.board.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.lec.sts13_jdbc.board.C;
import com.lec.sts13_jdbc.board.beans.BWriteDTO;
import com.lec.sts13_jdbc.board.command.BCommand;
import com.lec.sts13_jdbc.board.command.BListCommand;
import com.lec.sts13_jdbc.board.command.BWriteCommand;

@Controller
@RequestMapping("/board")
public class BoardController {

	private BCommand command;
	private JdbcTemplate template;
	
	public BoardController() {
		super();
		System.out.println("BoardController() 생성");
	}
	
	@Autowired
	public void setTemplate(JdbcTemplate template) {
		System.out.println("setTemplate() 호출");
		this.template = template;
		C.template = template;
	}
	
	@RequestMapping("/list.do")
	public String list(Model model) {
		command = new BListCommand();
		command.execute(model);
		return "board/list";
	}
	
	@RequestMapping("/write.do")
	public String write(Model model) {
		return "board/write";
	}
	
	@RequestMapping(value = "/writeOk.do", method = RequestMethod.POST)
	public String writeOk(BWriteDTO dto, Model model) {
		model.addAttribute("dto", dto);
		new BWriteCommand().execute(model);
		return "board/writeOk";
	}
	
}

 

 

[STS13_JDBC의 View, Update, Delete는 다음 시간에 계속할 예정]

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.07.01  (0) 2020.07.01
2020.06.30  (0) 2020.06.30
2020.06.23  (0) 2020.06.23
2020.06.22  (0) 2020.06.22
2020.06.19  (0) 2020.06.19