1) SpringBoot
1-1) Server, JPA, DB 예제
1-1-1) 테스트 저장
1-1-2) 방명록 쓰기
1) SpringBoot
1-1) Server, JPA, DB 예제
[web4] 안에 web4.txt 파일 생성 후 내용 아래와 같이 작성 : 이를 통해 프로젝트 한 번에 파악 및 내용 공유 가능
[web4 예제]
로그인하지 않고 글을 쓰는 게시판
비밀번호를 맞게 입력하면 삭제 가능
* 테이블 구조
create table guestbook(
num integer auto_increment primary key, -- 번호. 자동생성. 기본키
name varchar(100) not null, -- 이름. 필수입력. 문자열. 100byte
password varchar(100) not null, -- 비밀번호. 필수입력. 문자열. 100byte
message text not null, -- 본문내용. 필수입력. 긴 문자열
inputdate timestamp default current_timestamp -- 작성시간. 자동입력. 현재시간
);
[web4] 안에 build.gradle 파일 내용 아래와 같이 작성
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'net.datasa'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
[src/main/resources] 안에 application.properties 파일 내용 아래와 같이 작성
spring.application.name=web4
#접속 포트번호
server.port=8888
#Context Path
server.servlet.context-path=/
#Logback 사용. 전체를 대상으로 로깅 레벨 지정
#error>warn>info>debug>trace
logging.level.root=info
#특정 패키지를 대상으로 로깅 레벨 지정
logging.level.net.datasa.web3=debug
#세션의 유지 시간 (기본값은 30분 = 1800초)
#단위 : s (seconds), m (minutes), h (hours), d (days)
server.servlet.session.timeout=60m
# MySQL 데이터베이스 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Seoul&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
# JPA 설정
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace
spring.jackson.time-zone=Asia/Seoul
[src/main/java] - [net.datasa.web4] 안에 HomeController.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping({"", "/"})
public String home() {
return "home";
}
}
[src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>web4</title>
</head>
<body>
<h1>[ web4 ]</h1>
<p>
<a href="test">저장 테스트</a>
</p>
<p>
<a href="write">방명록 글쓰기</a>
</p>
</body>
</html>
1-1-1) 테스트 저장
(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;
@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
private final GuestBookService guestbookService;
/*
* public class GuestBookController {
* GuestBookController(GuestBookService guestbookService) {
* this.guestbookService = guestbookService;
* }
* }
*/
// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
// 실행 후 메인화면으로 다시 redirect
@GetMapping("test")
public String test() {
guestbookService.test();
return "redirect:/";
}
}
(2) [src/main/java] - [net.datasa.web4] 안에 Web4Application.java 파일 생성 후 아래와 같이 "@EnableJpaAuditing" Annotation 추가
package net.datasa.web4;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@EnableJpaAuditing
@SpringBootApplication
public class Web4Application {
public static void main(String[] args) {
SpringApplication.run(Web4Application.class, args);
}
}
(3) [src/main/java] - [net.datasa.web4.domain.entity] 안에 GuestBookEntity.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.domain.entity;
import java.time.LocalDateTime;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="guestbook")
@EntityListeners(AuditingEntityListener.class)
public class GuestBookEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="num")
Integer num;
@Column(name="name", nullable = false, length = 100)
String name;
@Column(name="password", nullable = false, length = 100)
String password;
@Column(name="message", nullable = false, columnDefinition = "text")
String message;
@CreatedDate
@Column(name="inputdate")
LocalDateTime inputdate;
}
(4) [src/main/java] - [net.datasa.web4.repository] 안에 GuestBookRepository.java 파일 생성 후 아래와 같이 작성
(주의 : Class가 아닌 Interface로 파일 생성한다!)
package net.datasa.web4.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.datasa.web4.domain.entity.GuestBookEntity;
@Repository
public interface GuestBookRepository extends JpaRepository<GuestBookEntity, Integer> {
}
(5) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.service;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;
@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
private final GuestBookRepository guestbookRepository;
// 저장 테스트
public void test() {
// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
GuestBookEntity entity = GuestBookEntity.builder()
.name("aaa")
.password("111")
.message("글 내용1")
.build();
guestbookRepository.save(entity);
}
}
(6) 결과 화면
첫 접속 화면
"저장 테스트" 문구 클릭 시 DB에 새로운 데이터 저장됨
실행 전 화면
실행 후 화면
1-1-2) 방명록 쓰기
(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;
@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
private final GuestBookService guestbookService;
/*
* public class GuestBookController {
* GuestBookController(GuestBookService guestbookService) {
* this.guestbookService = guestbookService;
* }
* }
*/
// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
// 실행 후 메인화면으로 다시 redirect
@GetMapping("test")
public String test() {
guestbookService.test();
return "redirect:/";
}
// home 화면에서 "글쓰기"를 클릭하면 입력 form으로 이동
@GetMapping("write")
public String write() {
return "writeForm";
}
// 입력 form에서 글쓰고 "저장" 버튼 누르면 받아서 글 저장
@PostMapping("write")
public String write(@ModelAttribute GuestBookDTO dto) {
log.debug("전달된 값 : {}", dto);
guestbookService.writeSave(dto);
return "redirect:/";
}
}
(2) [src/main/java] - [net.datasa.web4.domain.dto] 안에 GuestBookDTO.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.domain.dto;
import java.time.LocalDateTime;
import lombok.Data;
@Data
public class GuestBookDTO {
int num;
String name;
String password;
String message;
LocalDateTime inputdate;
}
(3) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성
package net.datasa.web4.service;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;
@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
private final GuestBookRepository guestbookRepository;
// 저장 테스트
public void test() {
// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
GuestBookEntity entity = GuestBookEntity.builder()
.name("aaa")
.password("111")
.message("글 내용1")
.build();
guestbookRepository.save(entity);
}
public void writeSave(GuestBookDTO dto) {
GuestBookEntity entity = GuestBookEntity.builder()
.name(dto.getName())
.password(dto.getPassword())
.message(dto.getMessage())
.build();
guestbookRepository.save(entity);
}
}
(4) [src/main/resources] - [templates] 안에 writeForm.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록 글쓰기</title>
<style>
.index {
display: inline-block;
margin-right: 20px;
}
textarea {
height: 80px;
}
</style>
<script>
window.onload = function() {
let nameInput = document.querySelector("#name");
let pwInput = document.querySelector("#password");
let messageInput = document.querySelector("#message");
let saveBtn = document.querySelector("#saveBtn");
saveBtn.addEventListener("click", function check(event) {
if (
nameInput.value.length == 0
|| pwInput.value.length == 0
|| messageInput.value.length == 0
) {
alert("이름, 비밀번호, 내용을 모두 입력하세요");
event.preventDefault();
return false;
}
if (!isNaN(nameInput.value)) {
alert("이름은 문자로 입력하세요");
nameInput.focus();
nameInput.value = null;
event.preventDefault();
return false;
}
if (!isNaN(pwInput.value)) {
alert("비밀번호는 문자로 입력하세요");
pwInput.focus();
pwInput.value = null;
event.preventDefault();
return false;
}
if (!isNaN(messageInput.value)) {
alert("내용은 문자로 입력하세요");
messageInput.focus();
messageInput.value = null;
event.preventDefault();
return false;
}
return true;
});
}
</script>
</head>
<body>
<h1>[ 방명록 글쓰기 ]</h1>
<br>
<form action="write" method="post" onsubmit="return check();">
<table>
<tr>
<td class="index">이름</td>
<td>
<input type="text" name="name" id="name">
</td>
</tr>
<tr>
<td class="index">비밀번호</td>
<td>
<input type="text" name="password" id="password">
</td>
</tr>
<tr>
<td class="index">내용</td>
<td>
<textarea name="message" id="message"></textarea>
</td>
</tr>
</table>
<input type="submit" value="저장" id="saveBtn">
</form>
</body>
</html>
(5) 결과 화면
첫 접속 화면
"방명록 글쓰기" 문구 클릭 시 화면
"저장" 버튼 클릭 시 결과
- 이름, 비밀번호, 내용 모두 입력했는지 체크하는 JavaScript 함수 구현
- 이름, 비밀번호, 내용 각각 입력값이 문자열로 입력되었는지 체크하는 JavaScript 함수 구현