자바 공부/[자바] 기본 공부

[SPRING] 게시판 만들기

햅2024 2024. 12. 23. 21:36

1. 리스트 화면 구현

  • mapper : getList.java, mapper.xml : SQL 구현
  • JUnit을 통한 mapper Test
  • BoardDAO : getList() 작성
  • JUnit을 통한 dao Test
  • BoardController : list 요청에 따른 list() 작성
  • list.html : th:each - th:object - th:text 를 이용하여 루프 구현

2. Board 게시판 구현

  • read.html : 글 상세보기 구현
  • read.html에서 수정하기 버튼 -> modify.html
  • modify 서비스에서 modify.html로 boardVO 를 전송
  • list에서 검색 기능 추가
    • getListWidthKey(String, String) 구현
    • mapper.xml 에서 criteria(공통 부분) 작성 후 include => where 1 = 1 또는 where bno > 0

MyBatis typeAliases 사용

typeAliases : 패키지에 대한 별명 설정

 

src/main/java -> com.koreait.boar.mybatis -> MyBatisConfig.java

package com.koreait.board.mybatis;

import java.io.IOException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import lombok.RequiredArgsConstructor;

@Configuration  // Config(설정) 관련 클래스
@RequiredArgsConstructor
@MapperScan("com.koreait.board.mapper")  // Mapper를 스캔할 패키지
public class MyBatisConfig {
   
   // 커넥션 풀 및 MyBatis에 필요한 요소들을 메모리에 할당하고 관리
   // XML과 java 연동에 필요한 경로 관리
   private final ApplicationContext applicationContext;
   
   // 1. Property 가져오기
   // @Bean
   // @Configuration 또는 @Component가 작성된 클래스의 메서드에 사용
   // 메서드의 리턴 객체를 Spring 컨테이너에 등록
   @Bean
   @ConfigurationProperties(prefix="spring.datasource")
   public HikariConfig hikariConfig() { return new HikariConfig(); }
   
   // 2. DataSource 설정
   @Bean
   public DataSource dataSource() {
      HikariDataSource hds = new HikariDataSource(hikariConfig());
      return hds;
   }
   
   // 3. SQL Session Factory
   @Bean
   public SqlSessionFactory sqlSessionFactory() throws IOException {

      SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
      sfb.setDataSource(dataSource());
      
      // SQL을 작성할 xml 경로 설정
      sfb.setMapperLocations(applicationContext.getResources("classpath*:/mapper/*.xml"));
      sfb.setConfigLocation(applicationContext.getResource("classpath:/config/config.xml"));
      
      try {
         SqlSessionFactory factory = sfb.getObject();
         // DB는 대소문자 구분이 없으므로 컬럼명을 _로 연결하여 만든다.
         // _로 연결된 변수를 CamelCase로 바꾸는 설정을 true로 입력
         // open_date(DB) -> openDate(Java)
         factory.getConfiguration().setMapUnderscoreToCamelCase(true);
         return factory;
      }
      catch(Exception e) { e.printStackTrace(); }
      
      return null;
   }
   
}

 

src/main/resources -> config 폴더 생성 -> config.xml 파일 생성

config.xml

<?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>
	<typeAliases>
		<typeAlias alias="boardVO" type="com.koreait.board.bean.BoardVO"></typeAlias>
	</typeAliases>
</configuration>

 

BoardMapper.xml

 

com.koreait.board.bean.BoardVO 를 boardVO 로 치환

<?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">
<!-- 연결할 인터페이스 정보를 namespace에 기술 -->
<mapper namespace="com.koreait.board.mapper.BoardMapper">
	<insert id="insert">
		INSERT INTO TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
		VALUES(NEXTVAL(SEQ_BOARD), #{title}, #{content}, #{writer})
	</insert>
	<insert id="insertSelectKey">
		<selectKey keyProperty="bno" order="BEFORE" resultType="long">
			SELECT NEXTVAL(SEQ_BOARD) FROM DUAL
		</selectKey>
		INSERT INTO TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
		VALUES(#{bno}, #{title}, #{content}, #{writer})
	</insert>
	<select id="getList" resultType="boardVO">
		<![CDATA[
		SELECT BNO, TITLE, CONTENT, WRITER, REGDATE, UPDATEDATE
		FROM TBL_BOARD
		WHERE BNO > 0
		]]>
	</select>
	<select id="get" resultType="boardVO">
		SELECT BNO, TITLE, CONTENT, WRITER, REGDATE, UPDATEDATE
		FROM TBL_BOARD
		WHERE BNO = #{bno}
	</select>

	<update id="update">
		UPDATE TBL_BOARD SET TITLE = #{title}, CONTENT = #{content}, WRITER = #{writer}  
		WHERE BNO = #{bno}
	</update>
</mapper>

 

 

----

BoardController.java

package com.koreait.board.controller;

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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.koreait.board.bean.BoardVO;
import com.koreait.board.dao.BoardDAO;

import lombok.extern.slf4j.Slf4j;

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

	@Autowired
	private BoardDAO dao;
	
	// List
	@GetMapping("list")
	public void list(Model model) {
		log.info("---------------------------------------------");
		log.info("Get List Called");
		model.addAttribute("list", dao.getList());
		log.info("---------------------------------------------");
	}
	
	// register(글쓰기) 화면 호출용
	@GetMapping("register")
	public void register() {

	}
	
	// register(글쓰기) 처리용
	@PostMapping("register")
	public void write(BoardVO board) {
		log.info("글 : "+ board);
		log.info(dao.register(board) + "건 등록 완료");
	}
}

bootstarp -> Download 

https://getbootstrap.com/docs/5.3/getting-started/download/

 

Download

Download Bootstrap to get the compiled CSS and JavaScript, source code, or include it with your favorite package managers like npm, RubyGems, and more.

getbootstrap.com

 

src/main/resource -> static 폴더에 압축 풀기

 


templates -> board -> list.html 생성

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Board</title>
<link rel="stylesheet" href="/css/bootstrap.css">
</head>
<body>
	<h1 class="text-center" style="margin: 20px auto;">
		Board List	<input type="button" id="write" value="글쓰기"></input>
		<span class="btn btn-success" id="write2">글쓰기2</span>
	</h1> 
	<hr>
	<div class="col-md-8 text-center" style="margin: 0 auto;">
	<table class="table table-striped">
		<thead>
			<tr>
				<td>번호</td>
				<td>제목</td>
				<td>작성자</td>
				<td>작성일</td>
				<td>수정일</td>
			</tr>
		</thead>
		<tbody>
		<th:block th:each="board:${list}">
			<tr th:object="${board}">
				<td th:text="*{bno}"></td>
				<td th:text="*{title}"></td>
				<td th:text="*{writer}"></td>
				<td th:text="*{regdate}"></td>
				<td th:text="*{updatedate}"></td>
			</tr>
		</th:block>
		</tbody>
	</table>
	</div>
</body>
<script>
	var btn = document.getElementById("write");
	btn.addEventListener("click", function(){
		//alert("버튼 클릭");
		location.href = "/board/register";
	});
	
	//var btn2 = document.getElementById("write2");
	//btn2.addEventListener("click", function(){
		//alert("버튼 클릭");
	//	location.href = "/board/register";
	//});
	
	var btn2 = document.querySelector("span");
	btn2.addEventListener("click", function(){
		//alert("버튼 클릭");
		location.href = "/board/register";
	});
	
	//querySelectorAll 일 때는 querySelectorAll("span")[0]; 이렇게 씀
	
</script>
</html>


반응형 UI 만들기

width 가 918px 이하일 경우 class=hide 인 항목들 숨기기

 

<head>
	<meta charset="UTF-8">
	<title>Board</title>
	<link rel="stylesheet" href="/css/bootstrap.css">
	<style>
		@media (max-width: 918px){
			.hide{
				display: none;
			}
		}
	</style>
</head>
<body>
	<h1 class="text-center" style="margin: 20px auto;">
		Board List	<input type="button" id="write" value="글쓰기"></input>
		<span class="btn btn-success" id="write2">글쓰기2</span>
	</h1> 
	<hr>
	<div class="col-md-8 text-center" style="margin: 0 auto;">
	<table class="table table-striped">
		<thead>
			<tr>
				<td>번호</td>
				<td>제목</td>
				<td>작성자</td>
				<td>작성일</td>
				<td>수정일</td>
			</tr>
		</thead>
		<tbody>
		<th:block th:each="board:${list}">
			<tr th:object="${board}">
				<td th:text="*{bno}" class="hide"></td>
				<td th:text="*{title}"></td>
				<td th:text="*{writer}"></td>
				<td th:text="*{regdate}"></td>
				<td th:text="*{updatedate}" class="hide"></td>
			</tr>
		</th:block>
		</tbody>
	</table>
	</div>
</body>

 

 

전체 소스코드

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>Board</title>
	<link rel="stylesheet" href="/css/bootstrap.css">
	<style>
		@media (max-width: 918px){
			.hide{
				display: none;
			}
		}
	</style>
</head>
<body>
	<h1 class="text-center" style="margin: 20px auto;">
		Board List	<input type="button" id="write" value="글쓰기"></input>
		<span class="btn btn-success" id="write2">글쓰기2</span>
	</h1> 
	<hr>
	<div class="col-md-8 text-center" style="margin: 0 auto;">
	<table class="table table-striped">
		<thead>
			<tr>
				<td class="hide">번호</td>
				<td>제목</td>
				<td>작성자</td>
				<td>작성일</td>
				<td class="hide">수정일</td>
			</tr>
		</thead>
		<tbody>
		<th:block th:each="board:${list}">
			<tr th:object="${board}">
				<td th:text="*{bno}" class="hide"></td>
				<td th:text="*{title}"></td>
				<td th:text="*{writer}"></td>
				<td th:text="*{regdate}"></td>
				<td th:text="*{updatedate}" class="hide"></td>
			</tr>
		</th:block>
		</tbody>
	</table>
	</div>
</body>
<script>
	var btn = document.getElementById("write");
	btn.addEventListener("click", function(){
		//alert("버튼 클릭");
		location.href = "/board/register";
	});
	
	//var btn2 = document.getElementById("write2");
	//btn2.addEventListener("click", function(){
		//alert("버튼 클릭");
	//	location.href = "/board/register";
	//});
	
	var btn2 = document.querySelector("span");
	btn2.addEventListener("click", function(){
		//alert("버튼 클릭");
		location.href = "/board/register";
	});
	
	//querySelectorAll 일 때는 querySelectorAll("span")[0]; 이렇게 씀
	
</script>
</html>

board (5).zip
2.98MB
board (6).zip
2.98MB
board (7).zip
2.98MB

 

'자바 공부 > [자바] 기본 공부' 카테고리의 다른 글

[SPRING] DB 등록  (1) 2024.12.19
[SPRING] 게시글 추가, 리스트 불러오기  (0) 2024.12.18
[SPRING] Mapper  (1) 2024.12.12
[SPRING] Lombok 라이브러리  (1) 2024.12.11
[SPRING] 스프링 프레임워크 기초  (4) 2024.12.10