D+45::스프링부트 Board

Am.Vinch·2022년 8월 29일
0

20220829_Mon

참고)
학원 로드맵
웹개발 하기위해서
선수학습-java 1달
자바기반 웹개발- servlet,jsp -> 개념이 부족하면 다음에 배울것들이 모두 흐트러진다.
스프링부트 / jsp / react..
=>수료하면 그때부터 다시 공부해야한다..


  • 프로젝트 만들때 모든 패키지명은 여기 보이는 이 창 패키지에 기본값으로 저장이된다.

  • IOC: 제어의역전(코드제어의 주체가 바뀐다)
    -> 사용해야하는 객체를 만들어서 코드 개발(개발자의 역할) ex)new boardDTO()..
    -> 스프링에서는 객체를 스프링 컨테이너가 만들어준다.
    -> 클래스간의 결합도를 낮추기위해서 new로 객체생성시 결합도가 너무 높기 때문에.

그럼 어떻게 스프링이 알아서 객체를 자동으로 만드냐??

  • DI(Dependancy Injection) : 의존성 주입
  • 스프링은 자동으로 객체를 만드는게 아니라 만들어진 객체 중 적절한 객체를 찾아 바인딩(연결)시켜준다!-> "의존성 주입"
  • 의존성 주입을 하기 위해서는!
    1. 먼저 객체를 생성
    • 방법 4가지(클래스명 바깥에 사용)
      • (1) @Component:객체하나 생성(클래스명 맨 첫글자 소문자로 자동생성)
      • (2) @Respository:객체하나 생성
      • (3) @Service:객체하나 생성
      • (4) @Controller: Component에서 파생/객체하나 생성
    1. 만들어진 객체를 의존성 주입시킨다.
    • 방법 2가지 (어노테이션 사용)
      - 1) @Autowired
      - 2) @Resource: name값과 동일한 값의 객체를 가져오겠다
      단, 의존성 주입은 디폴트 패키지를 기본으로 되어 있어야한다.

-스프링에서는 패키지명을 절대 수정할 수 없다. 안그럼 다시 만들어 사용해야한다!

  • 설명) 컨트롤러 Controller는 프로젝트 내에서 여러개가 존재한다.

예를 들어...
자바의 jsp 경우
:컨트롤러 실행시 jsp에서 .뒤에 끝나는 것과 같은 컨트롤러를 따라 실행한다. (스프링도 마찬가지)
Member컨트롤러(
.me)
Item컨트롤러(.it)
Admin컨트롤러(
.ad)
스프링의 경우
: 각 컨트롤러의 괄호 안의 내용을 기본경로 뒤에 넣으면 그 컨트롤러를 들어가겠다는 의미
Member컨트롤러(/member) -> http://localhost:8081/member/login
Item컨트롤러(/item) -> http://localhost:8081/item
Admin컨트롤러(/admin) -> http://localhost:8081/admin


  • Board 프로젝트_testContrller_thymeleafController 파일 생성
    1. 기본경로에서 컨트롤러로 페이지 이동
      : test_text.html 파일 화면 출력
  • thymeleafController.java 파일

package kh.study.board.testController;

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

@Controller
@RequestMapping("/test") //-> 이렇게 밖으로 빼면 안에 썻을때보다 중복되는 "/test" 부분을 제거할 수 있다.
public class thymeleafController {
	//참고) return "aa";//template(기본) 폴더 안의 aa.html 파일을 실행하겠다
    
    //경로이동: http://localhost:8081/test/ex1 
	@GetMapping("/ex1")// get 메소드를 사용( form태그 제외 나머지 모두 get)
	public String textTest() {
		//스프링에서 return: 이동할 페이지명 정하는 것
		return "test/text_test";//template 기준으로 test 폴더안의 text_test.html 파일 실행
	}
}
  • test_text.html 파일 생성
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"><!-- jsp에서 foreach문 사용할때 lib태그 사용하는 것과 같다.앞으로 html 만들때는 사용해야한다. 원래 html만들때 next누르고 별도로 생성한 htnl_thymeleaf를 선택하면 자동생성된다-->
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
hello
</body>
</html>

(초창기버전)

(현재버전)

  • @GetMapping("/ex1") 어노테이션 사용하고 대신 @RequestMapping("/test")를 밖으로 빼서 중복을 줄이고 get메소드를 사용한다.

컨트롤러에서 보낸 데이터 board 값을 받아 사용할 때

: 컨트롤러에서 보낸 데이터값을(board) 받아서 가져와 사용하려는데 자바와 자바스크립트와 어떻게 다른가?
:

  • BoardVO
  • 컨트롤러에서 보낸 데이터 board 값을 받아 사용할 때
    -방법 1: 타임리프 속성 사용
    <span th:text="${board.title}"></span><br>
    -방법 2: 바로 사용
    [[${board.title}]]
  • 결과

스프링에서 반복문 forEach는 어떻게 사용하는가?

  • for_test.html 파일 생성

  • testController

package kh.study.board.testController;

import java.util.ArrayList;
import java.util.List;

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

import kh.study.board.vo.BoardVO;

@Controller
@RequestMapping("/test") //-> 이렇게 밖으로 빼면 안에 썻을때보다 중복되는 "/test" 부분을 제거할 수 있다.
public class thymeleafController {
	//참고) return "aa";//template(기본) 폴더 안의 aa.html 파일을 실행하겠다
	
	@GetMapping("/ex1")// get 메소드를 사용( form태그 제외 나머지 모두 get)
	public String textTest(Model model) {//model 인터페이스 객채생성 
		//BoardVO에서 getter,setter 어너테이션 만들고
		BoardVO vo = new BoardVO();
		vo.setTitle("제목입니다");
		vo.setWriter("작성자입니다");
		
		model.addAttribute("board", vo);//
		
		//스프링에서 return: 이동할 페이지명 정하는 것
		return "test/text_test";//template 기준으로 test 폴더안의 text_test.html 파일 실행
	
	}
	
	@GetMapping("/for")
	public String forTest(Model model) {
		
		List<BoardVO> boardList = new ArrayList<>();
		
		for(int i = 0 ; i<10; i++) {
			BoardVO vo = new BoardVO();
			vo.setTitle("제목" + (i +1));
			vo.setWriter("admin");
			
			boardList.add(vo);
		}
		
		model.addAttribute("list",boardList);
		
		return "test/for_test";
		
	}
}
  • for_test.html
<!DOCTYPE html>
<html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
	<tr>
		<td>제목</td>
		<td>작성자</td>
	</tr>
	<tr th:each="board : ${list}"> <!-- list에서 for문 돌려서 board라는 이름으로 데이터를 빼오겠다. -->
		<td th:text="${board.title}"></td>
		<td th:text="${board.writer}"></td>
	</tr>
</table>
<br>
<table border="1">
	<tr>
		<td>제목</td>
		<td>작성자</td>
		<td>현재 반복중인 인덱스 번호(0부터)</td>
		<td>현재 반복중인 인덱스 번호(1부터)</td>
		<td>총 갯수</td>
		<td>현재 반복중인 객체정보</td>
		<td>짝수행 여부</td>
		<td>홀수행 여부</td>
		<td>첫번째행 여부</td>
		<td>마지막행 여부</td>
	</tr>
	<!--  status 변수 사용할 때-->
	<tr th:each="board, status : ${list}"> <!-- list에서 for문 돌려서 board라는 이름으로 데이터를 빼오겠다. -->
		<td th:text="${board.title}"></td>
		<td th:text="${board.writer}"></td>
		<td th:text="${status.index}"></td>
		<td th:text="${status.count}"></td>
		<td th:text="${status.size}"></td>
		<td th:text="${status.current}"></td>
		<td th:text="${status.even}"></td>
		<td th:text="${status.odd}"></td>
		<td th:text="${status.first}"></td>
		<td th:text="${status.last}"></td>
	</tr>
</table>
<br>
<table border="1">
	<tr>
		<td>제목</td>
		<td>작성자</td>
		<td>현재 반복중인 인덱스 번호(0부터)</td>
		<td>현재 반복중인 인덱스 번호(1부터)</td>
		<td>총 갯수</td>
		<td>현재 반복중인 객체정보</td>
		<td>짝수행 여부</td>
		<td>홀수행 여부</td>
		<td>첫번째행 여부</td>
		<td>마지막행 여부</td>
	</tr>
	<!-- status 사용 안할 때-> boardStat 대체 -->
	<tr th:each="board : ${list}"> <!-- list에서 for문 돌려서 board라는 이름으로 데이터를 빼오겠다. -->
		<td th:text="${board.title}"></td>
		<td th:text="${board.writer}"></td>
		<td th:text="${boardStat.index}"></td>
		<td th:text="${boardStat.count}"></td>
		<td th:text="${boardStat.size}"></td>
		<td th:text="${boardStat.current}"></td>
		<td th:text="${boardStat.even}"></td>
		<td th:text="${boardStat.odd}"></td>
		<td th:text="${boardStat.first}"></td>
		<td th:text="${boardStat.last}"></td>
	</tr>
</table>
</body>
</html>
  • 주소창 입력 결과:
    http://localhost:8081/test/for

  • controller
@GetMapping("/if")
	public String ifTest(Model model) {
		BoardVO vo = new BoardVO();
		vo.setTitle("제목1");
		model.addAttribute("board",vo);
	
		return "test/if_test";
	}
  • if_test.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span th:if="${board.title == '제목1'}" th:text="제목1입니다."></span>
<span th:unless="${board.title == '제목1'}" th:text="제목1아닙니다."></span>

</body>
</html>
  • 여기서 이제, 컨트롤러에서 '제목1'에서 다른 값으로 변경시 새로고침하면? uless 태그가 사용된다.(elseIf가 따로 없기때문)
@GetMapping("/if")
	public String ifTest(Model model) {
		BoardVO vo = new BoardVO();
		vo.setTitle("제목11145");
		model.addAttribute("board",vo);
	
		return "test/if_test";
	}


  • 스프리이 & DB연동
  • BoardService
package kh.study.board.service;

import java.util.List;

import kh.study.board.vo.BoardVO;

public interface BoardService {
	//게시글 목록조회
	List<BoardVO> selectBoardList();
}
  • BoardServceImpl
package kh.study.board.service;

import java.util.List;

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

import kh.study.board.vo.BoardVO;

public class BoardServiceImpl implements BoardService {
		   //쿼리 실행하는 객체
//		   SqlSessionFactory sqlSessionFactory = SqlSessionManager.getSqlSession();
//		   SqlSession sqlSession;//생성이 아닌 선언만
	
	//@Autowired어노테이션은 미리 생성한 객체를 의존성 주입 시킬 때 사용한다.
	//아래코드가 진행이 된다는 것은, 프로젝트 실행 시
	// 스프링이 내부적으로 sqlSessionTemplate 자료형으로 객체를 미리 만들어 놓기 때문에 사용가능하다.
	//@Autowired는 그래서 동일한 자료형으로 객체가 미리 2개 이상 생성되어있다면,
	//프로젝트 실행과 동시에 오류 발생
	//-> DB로 이동
	@Autowired//자동연결   
	SqlSessionTemplate sqlSession;

	@Override
	public List<BoardVO> selectBoardList() {
		//원래 이클립스에서 하는 방식
//		List<BoardVO>  list = sqlSession.selectList("boardMapper.selectBoardList");
//		return list;
//		sqlSession.commit();(스프링은 자동 커밋)
		
		//->(스프링) 그래서 이제 부터 한 줄로 작성 가능해짐
		return sqlSession.selectList("boardMapper.selectBoardList");
	}
		
//		   @Override
//		   public List<CategoryDTO> selectCategoryList() {
//		      List<CategoryDTO> list = sqlSession.selectList("itemMapper.selectCategoryList");
//		      sqlSession.commit();
//		      return list;
//		   }
	

}
  • board-mapper
<?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="boardMapper">
	<resultMap type="kh.study.board.vo.BoardVO" id="board">
		<id column="BOARD_NUM" property="boardNum"/>
		<result column="TITLE" property="title"/>
		<result column="WRITER" property="writer"/>
		<result column="CONTENT" property="content"/>
		<result column="CREATE_DATE" property="createDate"/>
	</resultMap>

	<select id="selectBoardList" resultMap="board">
		SELECT BOARD_NUM 
		, TITLE
		, WRITER
		, CREATE_DATE
		FROM SPRING_BOARD
		ORDER BY BOARD_NUM DESC
	</select>
</mapper>
  • boardVO.java
package kh.study.board.vo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

//@Data
@Getter
@Setter
@ToString
public class BoardVO {
	//lombok 어노테이션(위에) 을 이용해 getter,setter를 편하게 만들수있다
	private int boardNum;
	private String title;
	private String content;
	private String writer;
	private String createDate;

}

@Resource - @autoWired 차이점 주의

  • BoardController
    : 이후, boardController 에서 리턴값의 페이지대로 html 파일 생성한다.
@Controller
@RequestMapping("/board")// "/board"로 시작하면 무조건 컨트롤러 실행하겠다
public class Boardcontroller {
	//boardService 라는 이름으로 만들어진 개체를 로드해서 
	//"의존성 주입"을 실행한다
	//@Resource는 @autoWired와 비슷하지만 자료형이 같은 객체가 아니라 
	//name값이 같은 변수명을 가져와서 데이터를 넣어준다

	@Resource(name = "boardService")
	private BoardService boardService;//스프링에서는 선언만!
	
	//게시글 목록 페이지 
	@GetMapping("/list")
	public String selectBoardList() {
		//게시글 목록 조회
		boardService.selectBoardList();
		
		return "board/board_list";
	}
}
  • board_list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
게시글목록페이지
</body>
</html>
  • 프로젝트 실행 후, 콘솔창 결과 확인
20220829 17:55:31.537 [http-nio-8081-exec-4] DEBUG j.sqltiming -  com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
1. SELECT BOARD_NUM 
		, TITLE
		, WRITER
		, CREATE_DATE
		FROM SPRING_BOARD
		ORDER BY BOARD_NUM DESC
 {executed in 123 msec} 
20220829 17:55:31.561 [http-nio-8081-exec-4] INFO j.resultsettable - 
|----------|------|-------|------------|
|board_num |title |writer |create_date |
|----------|------|-------|------------|
|----------|------|-------|------------|
profile
Dev.Vinch

0개의 댓글