SpringBoot
출처
본 내용인 스프링부트 시작하기-김인우 지음 참고하였습니다.
스프링 부트 기초부터 시작하기 좋은 책이니 참고하면 좋을 것 같습니다.
개발 환경 설정
- 이클립스 설치
- STS 플러그인 설치
- Spring Tools4
- 그레이들 설치
- buildship
- 그레이들 에디터 설치
- Minimalist Gradle Editor
- 그레이들 파일에 연결
- Windows>Preferences>General>Editor>File Associations>*.gradle 찾아서 Editor default 설정
- 글자 색상 추가, 자동 완성 기능 제공
- 이클립스 메뉴 및 Perspective 변경
- Perspective>Customize Perspective>Shortcut탭>Java>Class,Interface,Package,Annotation,JavaProject,Source Folder 선택
- Web>CSS File, HTML, JSP
- 패키지 보여 주기 변경
- Project Explorer 옆 아래 화살표 버튼> Package Presentations > Hierarchical
- 이클립스 뷰(View) 설정
- 소스코드 외 필요한 정보 제공
- Show View>Others>Console, Search, Problems, Progress, Package Explorer 추가
- 프로젝트 인코딩 설정
- Windows>Preferences>General>Workspace>Text file encoding>UTF-8로 변경
스프링 프로젝트 만들어보기
스프링의 장점
- 프로젝트에 자주 사용되는 라이브러리들이 미리 조합되어 있음
- 복잡한 설정을 자동으로 처리
- 내장 서버를 포함하여 톰캣과 같은 서버를 추가하지 않아도 바로 개발 가능
- JAR 파일로 웹 애플리케이션 배포 가능
스프링 부트로 프로젝트 생성하기
- File>New>Spring Starter Project
- Example
- Group: com.example
- Artifact: Sample
- Package: sample
- Type: Gradle
- 의존성 설정
- Web - Web
- Core - DevTools -> 개발 생산성 향상에 도움
- 스프링 부트 시동 확인
- 프로젝트 우클릭>Run As>Spring Boot App
Hello World 만나보기
- sample 패키지 밑에 controller 패키지 생성
- sample 패키지 우클릭 > New>Package
- name: sample.controller 입력
- controller 패키지 밑에 HelloController 클래스 생성(자동 패키지 import 단축키: cmd+ shift+o)
- RestController: 해당 클래스가 Rest 컨트롤러 기능 수행
- RequestMapping: 해당 메소드를 실행할 수 있는 주소 설정
package sample.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/") public String hello() { return "Hello World"; } }
SampleApplication 클래스
스프링 부트 애플리케이션의 구성과 실행을 담당하는 주용한 클래스
@SpringBootApplication
- 스프링 부트의 핵심 어노테이션
@SpringBootApplication
- 스프링 부트의 핵심 어노테이션
- 3가지의 어노테이션으로 구성
@EnableAutoConfiguration
- 스프링의 다양한 설정이 자동 구성됨
@ComponentScan
- 컴포넌트 검색 기능을 활성화해서 자동으로 여러 가지 컴포넌트 클래스를 검색
- 검색된 컴포넌트 및 빈 클래스를 스프링 애플리케이션 컨텍스트에 등록
@Configureation
- 자바 기반 설정 파일을 의미
build.gradle
- Gradle로 생성된 프로젝트의 빌드를 관리
- dependencies에 의존성 추가
스프링 프레임워크 이해하기
스프링 프레임워크란?
자바 기반의 애플리케이션 개발에 기반이 되는 프레임워크이다. 프레임워크를 사용하면 개발자들은 비지니스 로직 개발에 더 집중할 수 있다.
MVC 패턴
MVC는 Model-View-Controller 구조로 해당 패턴을 하용하면 사용자 인터페이스와 비지니스 로직을 분리하여 개발할 수 있다. 구조간에 영향도를 최소로하여 개발 및 변경이 쉬운 애플리케이션을 만들 수 있다.
게시판 개발을 위한 프로젝트 새로 생성
스프링 스타터 프로젝트 생성
- 이름을 Board로 설정
- 의존성 설정 - 초기환경 설정을 쉽게할 수 있도록 도와줌
- Core: DevTools, Lombok, Configuration Processor, Aspects
- SQL: JPA, MySQL, MyBatis
- Template Engines: Thymelear
- Web: WEb
- 데이터베이스 연결하기
- 데이터 소스 설정
- application.properties
- @Bean 어노테이션을 이용하여 데이터 소스 설정
- application.properties
- src/main/resources
- useUnicode - 주소에 유니코드 설정
spring.datasource.hikari.driver-class=com.mysql.ci.jdbc.Driver spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/insight? useUnicode=true&characterEncoding=utf-8 spring.datasource.hikari.username= spring.datasource.hikari.password= spring.datasource.hikari.connection-test-query=SELECT 1
- src/main/resources
- 데이터 소스 설정
- DatabaseConfiguration 클래스 만들기
- src/main/java/board 패키지 밑에 configuration 패키지 생성 > DatabaseConfiguration 클래스 생성
- @PropertySource: application.properties를 사용할 수 있도록 설정 파일 위치 지정
- @ConfigurationProperties prefix로 지정한 properties를 Config 파일로 만듦
- 앞에서 만든 Config 설정 파일을 이용하여 데이터베이스와 연결하는 데이터 소스 생성
package board.configuration; import javax.sql.DataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @Configuration @PropertySource("classpath:/application.properties") public class DatabaseConfiguration { @Bean @ConfigurationProperties(prefix="spring.datasource.hikari") public HikariConfig hikariConfig() { return new HikariConfig(); } @Bean public DataSource dataSource() throws Exception{ DataSource dataSource = new HikariDataSource(hikariConfig()); System.out.println(dataSource.toString()); return dataSource; } }
- src/main/java/board 패키지 밑에 configuration 패키지 생성 > DatabaseConfiguration 클래스 생성
마이바티스 연동하기
SQL 매퍼(Mapper) 기반 프레임워크이다. JDBC를 사용할 경우 쿼리와 비지니스 로직을 분리하기가 어렵다. 마이바티스 같은 프레임워크를 사용하면 비지니스 로직과 쿼리를 분리하기가 쉬워진다.
마이바티스 설정하기
package board.configuration;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.context.annotation.PropertySource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
@PropertySource("classpath:/application.properties")
public class DatabaseConfiguration {
@Autowired
private ApplicationContext applicationContext;
@Bean
@ConfigurationProperties(prefix="spring.datasource.hikari")
public HikariConfig hikariConfig() {
return new HikariConfig();
}
@Bean
public DataSource dataSource() throws Exception{
DataSource dataSource = new HikariDataSource(hikariConfig());
System.out.println(dataSource.toString());
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResource("classpath:/mapper/**/sql-*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
- 스프링 마이바티스에서는 SqlSessionFactory를 생성하기 위해 SqlSessionFactoryBean을 사용
매퍼 폴더 생성하기
매퍼 폴더에는 애플리케이션에서 사용할 쿼리를 담고 있는 XML 파일 저장
- src/main/resource 폴더 밑에 mapper 폴더 생성
- 매퍼 파일의 위치 -
classpath:/mapper/**/sql-*.xml
- classpath: resources 폴더를 의미
/mapper/**/
: mapper 폴더 밑의 모든 폴더를 의미/sql-*.xml
: 이름이 sql-로 시작하고, 확장자가 xml인 모든 파일
마이바티스 연결 확인
package board;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class BoardApplicationTests {
@Autowired
private SqlSessionTemplate sqlSession;;
@Test
public void contextLoads() {
}
@Test
public void testSqlSession() throws Exception{
System.out.println(sqlSession.toString());
}
}
- BoardApplicationTests.java 테스트 코드 작성
- SqlSessionTemplate 출력 확인
간단한 게시판 구현하기
게시판을 만들기 위한 기본 설정
데이터베이스 구성
- 게시판 테이블 구성
CREATE TABLE t_board ( board_idx INT(11) NOT NULL AUTO_INCREMENT COMMENT '글 번호', title VARCHAR(300) NOT NULL COMMENT '제목', contents TEXT NOT NULL COMMENT '내용', hit_cnt SMALLINT(10) NOT NULL DEFAULT '0' COMMENT '조회수', created_datetime DATETIME NOT NULL COMMENT '작성시간', creator_id VARCHAR(50) NOT NULL COMMENT '작성자', updated_datetime DATETIME DEFAULT NULL COMMENT '수정시간', updater_id VARCHAR(50) DEFAULT NULL COMMENT '수정자', deleted_yn CHAR(1) NOT NULL DEFAULT 'N' COMMENT '삭제여부', PRIMARY KEY (board_idx) );
스타일 시트 추가하기
- src/main/resources 폴더 밑의 static 폴더에 css 폴더 생성 > style.css 생성
@CHARSET "UTF-8"; @import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css); @import url(http://cdn.jsdelivr.net/font-nanum/1.0/nanumbarungothic/nanumbarungothic.css); html{overflow:scorll;} html, body, div, h1, h2, a, form, table, caption, thead, tbody, tr, th, td, submit { margin:0; outline:0; border:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; } body { font-size:0.875em; line-height:1.5; color:#666; -webkit-text-size-adjust:none; min-width:320px; font-family:'NanumGothic','나눔고딕',dotum, "Helvetica Neue", Helvetica, Verdana, Arial, Sans-Serief; } h1, h2, h3 {font-size: 1.5em;} p{margin:0; padding:0;} ul{margin:0;} a:link, a:visited {text-decoration:none; color: #656565;} input{vertical-align:middle;} input:focus {outline:0;} caption {display:none; width:0; height:0; margin-top:-1px; overflow:hidden; visibility:hidden; font-size:0; line-height:0;} .container {max-width:1024px; margin:30px auto;} .board_list {width:100%; border-top:2px solid #252525; border-bottom:1px solid #ccc; margin:15px 0; border-collapse: collapse;} .board_list thead th:first-child {background-image:none;} .board_list thead th {border-bottom:1px solid #ccc; padding:13px 0; color:#3b3a3a; text-align: center; vertical-align:middle;} .board_list tbody td {border-top:1px solid #ccc; padding:13px 0; text-align:center; vertical-align:middle;} .board_list tbody tr:first-child td {border:none;} .board_list tbody tr:hover{background:#ffff99;} .board_list tbody td.title {text-align:left; padding-left:20px;} .board_list tbody td a {display:inline-block} .board_detail {width:100%; border-top:2px solid #252525; border-bottom:1px solid #ccc; border-collapse:collapse;} .board_detail tbody input {width:100%;} .board_detail tbody th {text-align:left; background:#f7f7f7; color:#3b3a3a; vertical-align:middle; text-align: center;} .board_detail tbody th, .board_detail tbody td {padding:10px 15px; border-bottom:1px solid #ccc;} .board_detail tbody textarea {width:100%; min-height:170px} .btn {margin:5px; padding:5px 11px; color:#fff !important; display:inline-block; background-color:#7D7F82; vertical-align:middle; border-radius:0 !important; cursor:pointer; border:none;} .btn:hover {background: #6b9ab8;} .file_list a {display:inherit !important;}
롬복 추가하기
자바 클래스를 만들 때 자주 만드른 코드들을 어노테이션을 이용하여 자동으로 만들어주는 라이브러리로 getter, setter, toString, equals, hashCode 자동 생성 해준다.
- 롬복 설치 - https://projectlombok.org/
- lombok.jar 더블클릭하여 롬복 인스톨러 실행
- eclipse ide 폴더 선택
게시글 목록 만들기
DTO 만들기
DTO(Data Transfer Object)는 애플리케이션 내 각 계층 간 데이터를 주고받는 데 사용되는 객체.
- board 패키지 밑에 board.dto 폴더 성성
- BoardDto 클래스 생성
- @Data: 롬복의 어노테이션으로 모든 필드의 getter, setter, toString, hashCode, equals 생성
- 데이터베이스는 _(underscore)를 사용하는 스네이크 표기법을 사용
package board.dto; import lombok.Data; @Data public class BoardDto { private int boardIdx; private String title; private String contents; private int hitCnt; private String creatorId; private String createdDateTime; private String updaterId; private String updatedDateTime; }
마이바티스 설정하기
자바의 카멜 케이스 표기법과 데이터베이스의 스네이크 표기법을 맞춰줌
- application.properties에 설정 추가
mybatis.configuration.map-underscore-to-camel-case=true
빈 등록하기
- DatabaseConfiguration 클래스 코드 수정
@Bean @ConfigurationProperties(prefix="mybatis.configuration") public org.apache.ibatis.session.Configuration mybatisConfig(){ return new org.apache.ibatis.session.Configuration(); }
- sqlSessionFactory 메서드에 설정 파일 추가
sqlSessionFactoryBean.setConfiguration(mybatisConfig());
컨트롤러 영역
컨트롤러는 클라이언트로 부터 요청을 받아서 해당 요청을 수행하는 데 필요한 비지니스 로직을 호출하고 그 결과를 응답해 주는 디스패처 역할을 함
- 컨트롤러 클래스에 @Controller 어노테이션 적용
- @RequestMapping 어노테이션을 이용하여 요청에 대한 주소 지정
- 요청에 필요한 비즈니스 로직 호출
- 실행된 비즈니스 로직 결과를 뷰로 리턴
패키지 생성
- board 패키지 밑에 board.controller 패키지 생성
- controller 패키지 안에 BoardController 클래스 생성
package board.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import board.dto.BoardDto; @Controller public class BoardController { @Autowired private BoardService boardService; @RequestMapping("/board/openBoardList.do") public ModelAndView openBoardList() throws Exception{ ModelAndView mv = new ModelAndView("/board/boardList"); List<BoardDto> list = boardService.selectBoardList(); mv.addObject("list", list); return mv; } }
서비스 영역
서비스 영역은 일반적으로 Service 인터페이스와 ServiceImpl 클래스로 구성. 이렇게 나누어서 구성하는 경우 여러 가지 장점이 있다.
- 느슨한 결합을 유지하여 의존관계 최소화
- 의존관계 최소화로 인해 기능 변화에도 최소한의 수정
- 모듈화를 통해 어디서든 사용할 수 있도록 재사용성 높임
- 스프링의 IoC/DI 기능을 이용한 빈 관리 기능 사용 가능
board 서비스 인터페이스 생성
비지니스 로직을 수행하기 위한 메서드 정의
package board.board.service;
import java.util.List;
import board.board.dto.BoardDto;
public interface BoardService {
List<BoardDto> selectBoardList() throws Exception;
}
board 서비스 구현
package board.board.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import board.board.dto.BoardDto;
@Service
public class BoardServiceImpl implements BoardService{
@Autowired
private BoardMapper boardMapper;
@Override
public List<BoardDto> selectBoardList() throws Exception{
return boardMapper.selectBoardList();
}
}
- @Service: 비즈니스 로직을 처리하는 서비스 클래스를 나타냄ㄷ
private BoardMapper boardMapper
: 데이터베이스에 접근하는 DAO빈 선언
매퍼 영역
마이바티스는 데이터 접근 객체인 DAO를 만드는 것보다 SqlSessionDaoSupport, SqlSessionTemplate를 사용하기를 권장합니다. 이를 이용하여 마이바티스 스프링 연동 모듈은 다른 빈에 직접 주입할 수 있는 매퍼를 생성할 수 있다.
- board/board 패키지 밑에 mapper 패키지 생성
- mapper 패키지에 BoardMapper 인터페이스 생성
- 메서드의 이름과 쿼리의 이름을 동일하게 해야 함
package board.board.mapper; import java.util.List; import org.apache.ibatis.annotations.Mapper; import board.board.dto.BoardDto; @Mapper public interface BoardMapper { List<BoardDto> selectBoardList() throws Exception; }
SQL 작성
쿼리를 XML에 작성하고 아이디를 이용하여 매핑한다. XML의 경우 src/main/resources에 위치 한다.
- src/main/resources 밑에 mapper.board 폴더 생성 > sql-board.xml 파일 생성
- 매퍼의 네임 스페이스 지정
- 매퍼와 XML 쿼리를 매칭해서 사용하려면 매퍼 인터페이스의 경로와 메소드의 이름과 쿼리의 이름이 같아야 함
- parameterType, resultType을 지정할 때는 패키지 경로를 포함한 전체 경로를 명시해야 함
- 매퍼의 네임 스페이스 지정
<?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="board.board.mapper.BoardMapper"> <select id="selectBoardList" resultType="board.board.dto.BoardDto"> <![CDATA[ SELECT board_idx, title, hit_cnt, DATE_FORMAT(created_datetime, '%Y.%m.%d %H:%i:%s') AS created_datetime FROM t_board WHERE deleted_yn = 'N' ORDER BY board_idx DESC ]]> </select> </mapper>
뷰 작성하기
사용자에게 보여 줄 화면을 작성
- src/main/resources/templates 폴더 밑에 board 폴더 생성
- board 폴더 안에 boardList.html 파일 생성
<!DOCTYPE html> <html lang="ko" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>board</title> <link rel="stylesheet" th:href="@{/css/style.css}"/> </head> <body> <div class="container"> <h2>게시글 목록</h2> <table class="board_list"> <colgroup> <col width="15%"/> <col width="*"/> <col width="15%"/> <col width="20%"/> </colgroup> <thead> <tr> <th scope="col">글번호</th> <th scope="col">제목</th> <th scope="col">조회수</th> <th scope="col">작성일</th> </tr> </thead> <tbody> <tr th:if="${#lists.size(list)} > 0" th:each="list : ${list}"> <td th:text="${list.boardIdx}"></td> <td class="title"><a href="/board/openBoardDetail.do?boardIdx=" th:attrappend="href=${list.boardIdx}" th:text="${list.title}"></a></td> <td th:text="${list.hitCnt}"></td> <td th:text="${list.createdDatetime}"></td> </tr> <tr th:unless="${#lists.size(list)} > 0"> <td colspan="4">조회된 결과가 없습니다.</td> </tr> </tbody> </table> <a href="/board/openBoardWrite.do" class="btn">글 쓰기</a> </div> </body> </html>
실행 결과 확인하기
게시물 등록 쿼리
INSERT INTO t_board
(
title,
contents,
creator_id,
created_datetime
)
VALUES
(
'first title',
'first contents',
'admin',
NOW()
)
게시물 등록 기능
게시글 등록 화면 만들기
- templates/board 폴더 안에 boardWrite.html 생성
<!DOCTYPE html> <html lang="ko" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>board</title> <link rel="stylesheet" th:href="@{/css/style.css}"/> </head> <body> <div class="container"> <h2>게시글 등록</h2> <form id="frm" name="frm" method="post" action="/board/insertBoard.do"> <table class="board_detail"> <tr> <td>제목</td> <td><input type="text" id="title" name="title"/></td> </tr> <tr> <td colspan="2"> <textarea id="contents" name="contents"></textarea> </td> </tr> </table> <input type="submit" id="submit" value="저장" class="btn"> </form> </div> </body> </html>
컨트롤러 영역
컨트롤러 영역에 두개의 메서드가 추가 된다.
- 게시글 등록 화면 호출
@RequestMapping("/board/openBoardWrite.do") public String openBoardWrite() throws Exception{ return "/board/boardWrite"; }
- 게시글 등록 기능
@RequestMapping("/board/insertBoard.do") public String insertBoard(BoardDto board) throws Exception{ boardService.insertBoard(board); return "redirect:/board/openBoardList.do"; }
서비스 및 매퍼 영역
BoardService 인터페이스에 내용 추가
void insertBoard(BoardDto board) throws Exception;
BoardServiceImpl 클래스에 다음 메서드 추가
@Override
public void insertBoard(BoardDto board) throws Exception{
boardMapper.insertBoard(board);
}
BoardMapper 인터페이스에 코드 추가
void insertBoard(BoardDto board) throws Exception;
SQL 작성
sql-board.xml 안에 다음 쿼리 추가
<insert id="insertBoard" parameterType="board.board.dto.BoardDto" useGeneratedKeys="true" keyProperty="boardIdx">
<![CDATA[
INSERT INTO t_board
(
title,
contents,
created_datetime,
creator_id
)
VALUES
(
#{title},
#{contents},
NOW(),
'admin'
)
]]>
</insert>
- 롬복이 제대로 설치되어 있지 않으면 title을 찾을 수 없다고 나온다.
게시글 상세화면 만들기
게시글 조회와 조회수 증가 작업 수행
목록 화면 수정하기
boardList.html 파일에 목록에서 글 부분을 링크로 연결
<td class="title">
<a href="/board/openBoardDetail.do?boardIdx=" th:attrappend="href=${list.boardIdx}" th:text="${list.title}"></a>
</td>
컨트롤러 영역
상세화면 호출 주소를 추가하고 글 상세 내역을 조회하는 로직 호출
@RequestMapping("/board/openBoardDetail.do")
public ModelAndView openBoardDetail(@RequestParam int boardIdx) throws Exception{
ModelAndView mv = new ModelAndView("/board/boardDetail");
BoardDto board = boardService.selectBoardDetail(boardIdx);
mv.addObject("board", board);
return mv;
}
서비스 및 매퍼 영역
BoardService 인터페이스에 내용 추가
BoardDto selectBoardDetail(int boardIdx) throws Exception;
BoardServiceImpl에 내용 추가
@Override
public BoardDto selectBoardDetail(int boardIdx) throws Exception{
BoardDto board = boardMapper.selectBoardDetail(boardIdx);
boardMapper.updateHitCount(boardIdx);
return board;
}
- 선택된 글의 조회수 증가
- 선택된 게시글의 내용 조회
Mapper 코드 추가
BoardDto selectBoardDetail(int boardIdx) throws Exception;
void updateHitCount(int boardIdx) throws Exception;
SQL 작성
조회수 증가와 게시글 상세 내용 조회 쿼리 작성
<select id="selectBoardDetail" parameterType="int" resultType="board.board.dto.BoardDto">
<![CDATA[
SELECT
board_idx,
title,
contents,
hit_cnt,
DATE_FORMAT(created_datetime, '%Y.%m.%d %H:%i:%s') AS created_datetime,
creator_id
FROM
t_board
WHERE
board_idx = #{boardIdx}
AND deleted_yn = 'N'
]]>
</select>
<update id="updateHitCount" parameterType="int">
<![CDATA[
UPDATE
t_board
SET
hit_cnt = hit_cnt + 1
WHERE
board_idx = #{boardIdx}
]]>
</update>
뷰 작성
boardDetail.html 파일 만들고 내용 작성
- 업데이트가 필요한 항목은 input 태그에 넣음
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>게시글 상세 화면</title>
<link rel="stylesheet" th:href="@{/css/style.css}"/>
</head>
<body>
<div class="container">
<h2>게시글 상세 화면</h2>
<form id="frm" method="post">
<table class="board_detail">
<colgroup>
<col width="15%"/>
<col width="35%"/>
<col width="15%"/>
<col width="35%"/>
</colgroup>
<caption>게시글 상세내용</caption>
<tbody>
<tr>
<th scope="row">글 번호</th>
<td th:text="${board.boardIdx }"></td>
<th scope="row">조회수</th>
<td th:text="${board.hitCnt }"></td>
</tr>
<tr>
<th scope="row">작성자</th>
<td th:text="${board.creatorId }"></td>
<th scope="row">작성일</th>
<td th:text="${board.createdDatetime }"></td>
</tr>
<tr>
<th scope="row">제목</th>
<td colspan="3"><input type="text" id="title" name="title" th:value="${board.title }"/></td>
</tr>
<tr>
<td colspan="4" class="view_text">
<textarea title="내용" id="contents" name="contents" th:text="${board.contents }"></textarea>
</td>
</tr>
</tbody>
</table>
<input type="hidden" id="boardIdx" name="boardIdx" th:value="${board.boardIdx }">
</form>
<a href="#this" id="list" class="btn">목록으로</a>
<a href="#this" id="edit" class="btn">수정하기</a>
<a href="#this" id="delete" class="btn">삭제하기</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#list").on("click", function(){
location.href = "/board/openBoardList.do";
});
$("#edit").on("click", function(){
var frm = $("#frm")[0];
frm.action = "/board/updateBoard.do";
frm.submit();
});
$("#delete").on("click", function(){
var frm = $("#frm")[0];
frm.action = "/board/deleteBoard.do";
frm.submit();
});
});
</script>
</body>
</html>
게시글 수정 및 삭제 기능 만들기
뷰 변경하기
- 데이터 전송을 위한 form 태그 추가
- 글번호는 hidden 속성으로 전달
컨트롤러 영역
게시글의 수정 및 삭제 코드를 추가
@RequestMapping("/board/updateBoard.do")
public String updateBoard(BoardDto board) throws Exception{
boardService.updateBoard(board);
return "redirect:/board/openBoardList.do";
}
@RequestMapping("/board/deleteBoard.do")
public String deleteBoard(int boardIdx) throws Exception{
boardService.deleteBoard(boardIdx);
return "redirect:/board/openBoardList.do";
}
- 글이 수정 및 삭제되면 게시글 목록 화면으로 이동
서비스 및 매퍼 영역
Board 인터페이스에 다음 코드를 추가
void updateBoard(BoardDto board) throws Exception;
void deleteBoard(int boardIdx) throws Exception;
BoardServiceImpl에 다음 코드 추가
@Override
public void updateBoard(BoardDto board) throws Exception {
boardMapper.updateBoard(board);
}
@Override
public void deleteBoard(int boardIdx) throws Exception {
boardMapper.deleteBoard(boardIdx);
}
Mapper 인터페이스에 코드 추가
void updateBoard(BoardDto board) throws Exception;
void deleteBoard(int boardIdx) throws Exception;
SQL 작성
<update id="updateBoard" parameterType="board.board.dto.BoardDto">
<![CDATA[
UPDATE t_board SET
title = #{title},
contents = #{contents},
updated_datetime = Now(),
updater_id = 'admin'
WHERE
board_idx = #{boardIdx}
]]>
</update>
<update id="deleteBoard" parameterType="int">
<![CDATA[
UPDATE t_board SET
deleted_yn = 'Y',
updated_datetime = Now(),
updater_id = 'admin'
WHERE
board_idx = #{boardIdx}
]]>
</update>
[부록A-1] Mysql 설치
docker-compose.yaml 생성
version: '3.1'
services:
db:
image: mysql:5.7
container_name: mysql5.7
ports:
- "3306:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=user
- MYSQL_PASSWORD=user
- MYSQL_DATABASE=insight
docker-compos backgroud 모드로 실행
$ docker-compose up -d
MySQL용 GUI 도구 sequelpro 설치하기
[부록B] eclipse mac 단축키
자동완성 등록
- 환경설정>Generals>Keys>Assist 검색>alt+space로 변경
'Backend' 카테고리의 다른 글
[OOP] 좋은 객체 지향 설계 원칙 (0) | 2021.07.20 |
---|---|
[JPA] 요구사항 분석과 기본 매핑 & 연관관계 매핑 기초 (0) | 2020.04.13 |
[JPA] 영속성 컨텍스트 (0) | 2020.04.08 |
Vert.x (0) | 2020.02.18 |
[Spring] Spring IoC (0) | 2020.02.17 |
댓글