Luver Duck 2022. 9. 6. 10:30

<table></table> 태그

<table></table> 태그 : 표를 만드는 태그

- border : 테두리 표시 (border = "1"일 때 표시하며 border = "0"일 때 표시하지 않음)

- width : 테두리의 너비 설정

 

<table></table>의 구성 요소

<thead></thead> table의 머리글 영역
<tbody></tbody> table의 본문 영역
<tfooter></tfooter> table의 본문 요약 정보(평균, 합계 등)를 표시하는 영역

 

table의 행(row)과 관련된 태그 (<thead></thead>와 <tbody></tbody> 안에서 사용)

<tr></tr> 행 영역을 정의
<th></th> table의 머리글 영역에서 하나의 열을 정의 (자동 가운데 정렬)
<td></td>  

- rowspan : 숫자만큼 행을 늘린다 (↓)

- colspan : 숫자만큼 열을 늘린다  (→)

 

 

참고) 

 

EX) 복잡한 형태의 표 만들기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>테이블 예제</title>
	</head>
	<body>
		<table border = "1" width = "800">
			<thead>
				<tr>
					<th rowspan = "2">NO</th>
					<th rowspan = "2">부하의 종류</th>
					<th rowspan = "2">출력[kW]</th>
					<th colspan = "4">전부하 특성</th>
				</tr>
				<tr>
					<th>역률[%]</th>
					<th>효율[%]</th>
					<th>입력[kVA]</th>
					<th>입력[kW]</th>
				</tr>
			</thead>	
			<tbody>
				<tr>
					<td>NO.1</td>
					<td>유도전동기</td>
					<td>6대 X 37</td>
					<td>87.0</td>
					<td>80.5</td>
					<td>6대 X 53</td>
					<td>6대 X 46</td>
				</tr>
				<tr>
					<td>NO.2</td>
					<td>유도전동기</td>
					<td>1대 X 11</td>
					<td>84.0</td>
					<td>77.0</td>
					<td>17</td>
					<td>14.3</td>
				</tr>
				<tr>
					<td>NO.3</td>
					<td>전등 및 기타</td>
					<td>30</td>
					<td>100</td>
					<td>-</td>
					<td>30</td>
					<td>30</td>
				</tr>
			</tbody>
			<tfoot>
				<tr>
					<td colspan = "2">합계</td>
					<td>263</td>
					<td>88.0</td>
					<td>-</td>
					<td>365</td>
					<td>320.3</td>
				</tr>
			</tfoot>
		</table>
	</body>
</html>

 

Controller에서 View로 데이터를 보내는 방법

Model 인터페이스

addAttribute(String attributeName, Oject attributeValue) Model에 해당 이름과 값의 속성을 추가 (key-value 형태)

- Controller에서 Model을 Mapping 메소드 매개변수로 사용하면 view로 데이터를 보낼 수 있다

- Model은 Annotation이 필요없다

 

View에서 프로그래밍 언어를 사용하는 방법

- scriptlet

- EL (Expression Language)

- JSTL (JavaServer Pages Standard Tag Library)

 

EL (Expression Language)

- JSP에서 Java 언어를 사용하기 위한 프로그래밍 언어

- Controller에서 전송한 Model에 있는 Attribute의 데이터를 View(JSP)에서 사용할 수 있다

- Controller에서 전송된 Model에서 값을 꺼내는 방법

 

단일 변수 ${속성명} Model에 저장된 해당 이름의 값을 반환
DTO 형태 ${DTO명.getter메소드} Model에 저장된 해당 필드의 값을 getter메소드로 반환 (람다식으로 대체 가능)

 

JSTL (JavaServer Pages Standard Tag Library)

- JSP의 유용한 태그 모음

- 가장 중요한 점은 Java의 if문이나 확장 for문, switch ~ case와 기능이 비슷한 문법을 사용할 수 있다는 것이다

 

태그 라이브러리 선언문

<%@ taglib prefix="접두사" uri="URI" %>

- prefix : tag 이름 앞에 붙일 접두사

- uri : 어떤 태그를 사용할 것인지에 대한 식별자(uniform resource identifier)

 

<c></c> 태그 라이브러리 선언문

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

태그 - 부모 태그(자식 태그) 기능
if Java의 if문
choose(when, otherwise) Java의 If ~ else if ~ else문
forEach Java의 for문

 

JdbcTemplate 클래스를 이용한 CRUD 기능 구현

1. Model이 될 클래스 정의 (DTO 또는 VO)

1. Dao(Interface 형태)에서 추상 메소드 선언

2. DaoImpl(class 형태)에서 추상 메소드 구현

3. Controller에서 등록 페이지 Mapping 설정

 

준비 - Model이 될 클래스 정의 (DTO 또는 VO)

- MUSIC 테이블 컬럼명 확인

 

- DTO 클래스 생성 : 필드, 생성자, getter&setter 포함 (toString 오버라이딩은 선택 사항)

package com.kh.springhome.entity;

public class PocketMonsterDto {

	// 필드 - 컬럼의 자료형과 동일하게
	private int no;
	private String name;
	private String type;
	
	// 생성자
	public PocketMonsterDto() {
		super();
	}
	
	// getter & setter
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}

	// toString 오버리이딩 (선택사항)
	@Override
	public String toString() {
		return "PocketMonsterDto [no=" + no + ", name=" + name + ", type=" + type + "]";
	}
}

 

MUSIC 테이블 - 조회(SELECT)

1. Dao(Interface 형태)에서 추상 메소드 선언

- 조회(SELECT)는 명령 실행 후 조회 결과를 DTO의 형태로 LIST에 담아서 반환한다

- 조회(SELECT)는 전체 조회와 키워드를 이용한 검색 조회가 있다

- 키워드 검색 조회에서 type은 항목(이름 또는 타입)을, keyword는 검색어를 의미한다

package com.kh.springhome.repository;

import java.util.List;

import com.kh.springhome.entity.MusicDto;

public interface MusicDao {

	// 추상 메소드 - 전체 조회(selectList)
	List<MusicDto> selectList();

	// 추상 메소드 - 검색 조회(selectList)
	List<MusicDto> selectList(String type, String keyword);
}

 

2. DaoImpl(class 형태)에서 추상 메소드 구현

- SQL문을 실행하기 위해 가장 먼저 JdbcTemplate 클래스의 인스턴스를 스프링 IoC 컨테이너에 등록해야 한다

- 조회(SELECT) 결과를 반환하기 위한 RowMapper가 반드시 필요하다

 

- 전체 조회(selectList) 메소드 구현

1) SQL문 생성

2) SQL문에 바인드 변수가 없으므로 매개변수 배열은 없다

3) JdbcTemplate의 query(String sql, RowMapper<T> rowMapper) 메소드를 실행한다

 

- 검색 조회(selectList) 메소드 구현

1) SQL문 생성

    - SQL문의 #1에는 바인드 변수가 들어갈 수 없으므로 String 클래스의 replace() 메소드로 치환하는 방법을 사용

2) SQL문의 바인드 변수에 들어갈 매개변수 배열 생성

3) JdbcTemplate의 query(String sql, RowMapper<T> rowMapper, Object... args) 메소드 실행

package com.kh.springhome.repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.kh.springhome.entity.MusicDto;

@Repository
public class MusicDaoImpl implements MusicDao {

	// 의존성 주입
	@Autowired
	JdbcTemplate jdbcTemplate;
	
	// 조회(SELECT) 결과를 반환하기 위한 RowMapper
	private RowMapper<MusicDto> mapper = new RowMapper<>() {
		@Override
		public MusicDto mapRow(ResultSet rs, int rowNum) throws SQLException {
			MusicDto musicDto = new MusicDto();
			musicDto.setMusicNo(rs.getInt("music_no"));
			musicDto.setMusicTitle(rs.getString("music_title"));
			musicDto.setMusicArtist(rs.getString("music_artist"));
			musicDto.setMusicAlbum(rs.getString("music_album"));
			musicDto.setMusicPlay(rs.getInt("music_play"));
			musicDto.setReleaseTitle(rs.getDate("release_title"));
			return musicDto;
		}
	};
	
	// 추상 메소드 오버라이딩 - 전체 조회(selectList)
	@Override
	public List<MusicDto> selectList() {
		// 1) SQL문 생성
		// 2) SQL문에 바인드 변수가 없으므로 매개변수 배열은 없다
		String sql = "select * from music order by music_no asc";
		// 3) JdbcTemplate의 query(String sql, RowMapper<T> rowMapper) 메소드 실행
		return jdbcTemplate.query(sql, mapper);
	}
	
	// 추상 메소드 오버라이딩 - 검색 조회(selectList)
	@Override
	public List<MusicDto> selectList(String type, String keyword) {
		// 1) SQL문 생성
		String sql = "select * from music where instr(#1, ?) > 0 order by #1 asc";
		// - #1에는 바인드 변수를 쓸 수 없으므로 String 클래스의 replace() 메소드로 치환
		sql = sql.replace("#1", type);
		// 2) SQL문의 바인드 변수에 들어갈 매개변수 배열 생성
		Object[] param = new Object[] {keyword};
		// 3) JdbcTemplate의 query(String sql, RowMapper<T> rowMapper, Object... args) 메소드 실행
		return jdbcTemplate.query(sql, mapper, param);
	}
}

 

3. Controller에서 Mapping 설정

1) 조회 Mapping 설정

- localhost:포트번호/music/list 인 URL로 접속할 때

  /WEB-INF/views/music/list.jsp 경로에 있는 view를 띄우도록 주소를 Mapping한다

- type과 keyword가 모두 null이 아닌 경우 검색 조회로 판정한다 (isSearch의 값은 true)

- Model의 addAttribute 메소드를 사용하여 View로 전달할 Model에 포함될 속성의 이름과 값을 추가한다

package com.kh.springhome.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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.kh.springhome.entity.MusicDto;
import com.kh.springhome.repository.MusicDao;

@Controller
@RequestMapping("/music")
public class MusicController {

	// 의존성 주입
	@Autowired
	private MusicDao musicDao;

	// 조회(SELECT)
	// 조회 Mapping
	@GetMapping("/list")
	public String select(
				Model model, 
				@RequestParam(required = false) String type, 
				@RequestParam(required = false) String keyword) {
		// 조회 유형 판정 - isSearch가 true일 경우 검색어 조회. false일 경우 전체 조회
		boolean isSearch = type != null && keyword != null;
		// Model에 포함될 속성의 이름과 값(key-value) 설정
		if(isSearch) {	// Model에 검색 조회 결과의 List<MusicDto>를 포함
			model.addAttribute("list", musicDao.selectList(type, keyword));
		}
		else {	// Model에 전체 조회의 결과의 List<MusicDto>를 포함
			model.addAttribute("list", musicDao.selectList());
		}
		return "music/list";
	}
}

 

2) View에서 표시 형식 정의

- Controller로부터 전달받은 Model을 이용하여 View에 표시할 형식을 정한다

- Model에는 list라는 이름의 List<MusicDto>의 인스턴스가 포함되어 있다

- JSTL의 core 태그 라이브러리의 forEach를 사용하면 조회 결과인 List<MusicDto>를 쉽게 출력할 수 있다

<c:forEach var="musicDto" items="${list}">
	<tr height = "10" valign = "top">
		<td>${musicDto.getMusicNo()}</td>
		<td>${musicDto.getMusicTitle()}</td>
		<td>${musicDto.getMusicArtist()}</td>
		<td>${musicDto.getMusicAlbum()}</td>
		<td>${musicDto.getMusicPlay()}</td>
		<td>${musicDto.getReleaseTitle()}</td>
	</tr>
</c:forEach>

 

- core 태그 라이브러리의 if를 사용하면 특정 조건을 부여할 수 있다

<c:forEach var="musicDto" items="${list}">
	<tr height = "10" valign = "top">
		<td>${musicDto.getMusicNo()}</td>
		<td>${musicDto.getMusicTitle()}
			<!-- 조회수가 3 이상이면 hot.png 이미지가 붙도록 -->
			<c:if test="${musicDto.musicPlay >= 3}">
				<img src = "/image/hot.png" width="20" height="20"> 
			</c:if>
		</td>
		<td>${musicDto.getMusicArtist()}</td>
		<td>${musicDto.getMusicAlbum()}</td>
		<td>${musicDto.getMusicPlay()}</td>
		<td>${musicDto.getReleaseTitle()}</td>
	</tr>
</c:forEach>

 

- 완성된 JSP

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>음원 목록 조회</title>
</head>
<body>
<div align="center">
	<h1>음원 목록 조회</h1>
	<!-- 음원 검색창 (검색일 떄는 method를 get으로 한다) -->
	<form action = "list" method = "get">
		<!-- 항목 -->
		<select name = "type" required>
			<option value = "music_title">음원명</option>
			<option value = "music_artist">가수명</option>
			<option value = "music_album">앨범명</option>
		</select>
		<!-- 키워드 -->
		<input name = "keyword" placeholder = "검색어" required><br>
		<button>검색</button>
	</form>			
	<hr>	
	<!-- 목록 출력 -->
	<table border = "1" width = "600">
		<thead>
			<tr>
				<th>음원번호</th>
				<th>음원명</th>
				<th>가수명</th>
				<th>앨범명</th>
				<th>재생수</th>
				<th>발매일</th>
			</tr>
		</thead>
		<tbody>
			<!-- 반복문 -->
			<c:forEach var="musicDto" items="${list}">
				<tr height = "10" valign = "top">
					<td>${musicDto.getMusicNo()}</td>
					<td>${musicDto.getMusicTitle()}
						<c:if test="${musicDto.musicPlay >= 3}">
							<img src = "/image/hot.png" width="20" height="20"> 
						</c:if>
					</td>
					<td>${musicDto.getMusicArtist()}</td>
					<td>${musicDto.getMusicAlbum()}</td>
					<td>${musicDto.getMusicPlay()}</td>
					<td>${musicDto.getReleaseTitle()}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>
</div>
</body>
</html>

 

주소 입력(요청) -> Controler -> JSP -> 화면 출력(응답)