221107 SpringBoot layout

wonny·2022년 11월 7일
0

수업 복습

목록 보기
11/14

SpringBootMiniProject

테이블 생성:

create table bootshop (num smallint primary key auto_increment,
sangpum varchar(30),
price int,
photoname varchar(50),
ipgoday datetime);

pom.xml

<!-- tomcat-embed-jasper -->
		<dependency>
		    <groupId>org.apache.tomcat.embed</groupId>
		    <artifactId>tomcat-embed-jasper</artifactId>
		    <scope>provided</scope>
		</dependency>
	
		<!-- jstl -->
		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
		

application.yml

#tomcat port
server:
  port: 9001
  
#jsp
spring:
  #mvc:
    #view:
      #prefix: /WEB-INF/
      #suffix: .jsp
  devtools:
    livereload:
      enabled: true
      
#mysql
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/sist?serverTimezone=Asia/Seoul
    username: dragon
    password: 1234
  

BootShopDto


위처럼 필요한 컨트롤러, Dto, 인터페이스 등을 만들어준 후에 Dto를 만들어준다.

package mini.data.dto;

import java.sql.Timestamp;

import org.apache.ibatis.type.Alias;

import lombok.Data;

@Data
@Alias("bsdto")
public class BootShopDto {

	private String num;
	private String sangpum;
	private String photoname;
	private int price;
	private Timestamp ipgoday;
	
	
}

SpringBootMiniProjectApplication.java

@ComponentScan, @MapperScan 해주기

package com.example.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({"mini.data.*"})
@MapperScan("mini.data.*") //mini.data.mapper
public class SpringBootMiniProjectApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootMiniProjectApplication.class, args);
	}

}

BootShopSql.xml

위에서 mapper를 등록해줬으니 BootShopSql.xml에서 mapper의 namespace를 적어줄 수 있다.

<?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="mini.data.mapper.BootShopMapperInter">


</mapper>

등록, 조회

BootShopMapperInter.java


@Mapper
public interface BootShopMapperInter {

	public int getTotalCount();
	public void insertBootShop(BootShopDto dto);
	public List<BootShopDto> getAllList();
}

BootShopSql.xml

	<select id="getTotalCount" resultType="int">
		select count(*) from bootshop
	</select>
	
	<insert id="insertBootShop" parameterType="bsdto">
		insert into bootshop (sangpum, price, photoname, ipgoday) values(#{sangpum},#{price},#{photoname},now())
	</insert>
	
	<select id="getAllList" resultType="bsdto">
		select * from bootshop order by num desc
	</select>

HomeController.java

//처음 시작시 list
	@GetMapping("/")
	public String start() {
		//return "redirect:bootshop/list";
		return "/layout/main"; //tiles
	}

BoardShopController.java

@Controller
public class BootShopController {

	@Autowired
	BootShopMapperInter mapper;
	
	
	
	//list 이동+전체 출력
	@GetMapping("/bootshop/list")
	public ModelAndView list() {
		ModelAndView mview = new ModelAndView();
		
		int totalCount = mapper.getTotalCount();
		List<BootShopDto> list = mapper.getAllList();
		
		mview.addObject("totalCount", totalCount);
		mview.addObject("list", list);
		
		//mview.setViewName("bootshop/shoplist"); //jsp
		mview.setViewName("/bootshop/shoplist"); //tiles
		return mview;
	}
	
	//addform 이동
	@GetMapping("/bootshop/shopform")
	public String form() {
		return "/bootshop/addform";
	}
	
	//insert
	@PostMapping("/bootshop/insert")
	public String insert(@ModelAttribute BootShopDto dto,
			@RequestParam MultipartFile upload,
			HttpSession session) {
		
		String path = session.getServletContext().getRealPath("/photo");
		System.out.println(path);
		
		if(upload.getOriginalFilename().equals(""))
			dto.setPhotoname(null);
		else {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
			String photoname="f_"+sdf.format(new Date())+upload.getOriginalFilename();
			
			dto.setPhotoname(photoname);
			
			try {
				upload.transferTo(new File(path+"/"+photoname));
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		//insert
		mapper.insertBootShop(dto);
		
		return "redirect:list";
	}

bootshop/shoplist.jsp

<body>
<div class="alert alert-success" style="width: 800px;">
	<b>총 ${totalCount }개의 상품이 있습니다.</b>
</div>
 
<table class="table table-bordered" style="width: 600px; margin: 30px;">
 	<caption><span><button type="button" class="btn btn-default" onclick="location.href='shopform'">상품 추가</button></span></caption>
 	
 	<c:forEach var="dto" items="${list }" varStatus="i">
	 	<tr>
	 		<td width="230" rowspan="4">
	 			<c:if test="${dto.photoname!=null }">
		 			<img alt="" src="../photo/${dto.photoname}" style="width: 200px; height: 200px;">
	 			</c:if>
	 			<c:if test="${dto.photoname==null }">
		 			<img alt="" src="../image/noimage.png" style="width: 200px; height: 200px;">
	 			</c:if>
	 		</td>
			<td>
				<b>상품명: ${dto.sangpum}</b>
			</td>
	 	</tr>
	 	<tr>
	 		<td>
	 			<b>단가: <fmt:formatNumber value="${dto.price }" type="currency"/> </b>
	 		</td>
	 	</tr>
	 	<tr>
	 		<td>
	 			<b>입고일: <fmt:formatDate value="${dto.ipgoday}" pattern="yyyy-MM-dd"/> </b>
	 		</td>
	 	</tr>
	 	<tr>
	 		<td>
	 			<button type="button" class="btn btn-warning" onclick="location.href='updateform?num=${dto.num}'">수정</button>
	 			<button type="button" class="btn btn-danger" onclick="location.href='delete?num=${dto.num}'">삭제</button>
	 		</td>
	 	</tr>
 	
 	</c:forEach>
 </table>

</body>

bootshop/addform.jsp

<script type="text/javascript">
	function readURL(input) {
	    if (input.files && input.files[0]) {
	        var reader = new FileReader();
	        reader.onload = function (e) {
	            $('#uploadimg').attr('src', e.target.result);
	        }
	        reader.readAsDataURL(input.files[0]);
	    }
	}
</script>
</head>
<body>
<form action="insert" method="post" enctype="multipart/form-data">
<table class="table table-bordered" style="width: 1000px; margin: 50px 50px;">
	<caption><h3>상품 등록</h3></caption>
		<tr bgcolor="pink">
			<th style="width: 150px;">상품명</th>
			<th style="width: 100px;">단가</th>
			<th style="width: 250px;">이미지</th>
			<th style="width: 350px;">미리보기</th>
		</tr>
		<tr>
			<td>
				<input type="text" class="form-control" name="sangpum" required="required">
			</td>
			<td>
				<input type="text" class="form-control" name="price" required="required">
			</td>
			<td>
				<input type="file" class="form-control" name="upload" onchange="readURL(this);">
			</td>
			<td>
				<div style="margin: 20px 20px;">
				    <img id="uploadimg" src="" alt="상품 이미지를 등록해주세요"  style="width: 150px; height: 150px;" />
				</div>
			</td>
		</tr>
		<tr>
			<td colspan="5" align="center">
				<button type="submit" class="btn btn-primary">등록하기</button>
				<button type="button" class="btn btn-seconday" onclick="location.href='list'">목록으로</button>
			</td>
		</tr>
		


</table>
</form>

여기까진 지금까지 했던 것 반복.
이제부터는 layout으로 웹페이지를 구성한다.

layout 구성

layout/title.jsp

<c:set var="root" value="<%=request.getContextPath() %>"></c:set>

절대경로를 미리 root로 지정해주면 경로를 줄 때 편하다.

<a href="/"><img alt="" src="${root}/image/title.png"> 
<br>
	<b>SpringBoot+Mybatis+Tiles3</b>
</a>

layout/info.jsp

<div style="font-size: 12pt; line-height: 25px;">
	<span class="glyphicon glyphicon-user"></span>00교육센터<br>
	<span class="glyphicon glyphicon-phone-alt"></span>02-1111-2222<br>
	<span class="glyphicon glyphicon-map-marker"></span>서울시 강남구<br>
	<span class="glyphicon glyphicon-envelope">ssss@naver.com</span><br>
	<span class="glyphicon glyphicon-barcode"></span><br>
</div>

layout/menu.jsp

<c:set var="root" value="<%=request.getContextPath() %>"></c:set>
<body>
	<ul class="nav nav-tabs menu">
		<li class="nav-item">
			<a class="nav-link active" href="${root}/">Home</a>
		</li>
		<li class="nav-item dropdown">
			<a class="nav-link dropdown-toggle"	data-bs-toggle="dropdown" href="#">상품</a>
			<ul class="dropdown-menu">
				<li><a class="dropdown-item" href="${root}/bootshop/shopform">상품 등록</a></li>
				<li><a class="dropdown-item" href="${root}/bootshop/list">상품 목록</a></li>
			</ul>
		</li>
		<li class="nav-item dropdown">
			<a class="nav-link dropdown-toggle"	data-bs-toggle="dropdown" href="#">회원</a>
			<ul class="dropdown-menu">
				<li><a class="dropdown-item" href="${root}/member/form">회원 가입</a></li>
				<li><a class="dropdown-item" href="${root}/member/list">회원 목록</a></li>
			</ul>
		</li>
		<li class="nav-item">
		<a class="nav-link" href="${root}/board/list">게시판</a></li>
		</li>
		<li class="nav-item">
		<a class="nav-link" href="${root}/load/map">오시는 길</a></li>
		</li>
	</ul>

	
</body>

layout/main.jsp

<c:set var="root" value="<%=request.getContextPath() %>"></c:set>
<body>
<img alt="" src="${root }/image/toy04.png" width="300">

</body>

pom.xml

		<!-- tiles-jsp -->
		<dependency>
		    <groupId>org.apache.tiles</groupId>
		    <artifactId>tiles-jsp</artifactId>
		    <version>3.0.8</version>
		</dependency>

		<!-- tiles-el -->
		<dependency>
		    <groupId>org.apache.tiles</groupId>
		    <artifactId>tiles-el</artifactId>
		    <version>3.0.8</version>
		</dependency>

tiles 관련 dependency 추가(자동 완성 오류나는 경우 tiles api도 추가)

WEB-INF/tiles.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC  
        "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"  
        "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<!-- #layout1 -->
	<definition name="layout1" template="/WEB-INF/layout/layout1.jsp">
		<put-attribute name="title" value="/WEB-INF/layout/title.jsp"/>
		<put-attribute name="menu" value="/WEB-INF/layout/menu.jsp"/>
		<put-attribute name="main" value="/WEB-INF/layout/main.jsp"/>
		<put-attribute name="info" value="/WEB-INF/layout/info.jsp"/>
	</definition>
	<!-- wild card_#1 -->
	<definition name="/*/*" extends="layout1">
		<put-attribute name="main" value="/WEB-INF/{1}/{2}.jsp"/>
	</definition>
	

definition: layout을 어떻게 만들지 정의한다.
name을 다르게 설정해주면 layout을 각각 다르게 만들어서 보이게 할 수 있다.
template="/WEB-INF/layout/layout1.jsp": layout1이 어디인지 경로를 지정해준다.
put-attribute name="title" value="/WEB-INF/layout/title.jsp": layout에 title을 넣겠다는 뜻
wild card: 전에는 board/list, board/addform... 이런식으로 썼는데 이걸 다 쓰기엔 힘드니까 와일드 카드를 사용해준다.
put-attribute name="main" value="/WEB-INF/{1}/{2}.jsp": main에 내용을 출력할 것이기 때문에 name="main"으로 준다. value 값은 "/WEB-INF/{폴더명}/{파일명}.jsp"로 주었기 때문에 와일드 카드의 name을 //로 준다. (굳이 앞에 /를 주는 이유는 layout이 여러개이기 때문이다)

layout/layou1.jsp

위에 taglib을 꼭 추가해줘야 한다.

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<body>
<div class="layout">
	<div class="title">
		<tiles:insertAttribute name="title"/>
	</div>
	<div class="menu">
		<tiles:insertAttribute name="menu"/>
	</div>
	<div class="info">
		<tiles:insertAttribute name="info"/>
	</div>
	<div class="main">
		<tiles:insertAttribute name="main"/>
	</div>
	
</div>
</body>

메인패키지/tilesConfig.java

package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.tiles3.SimpleSpringPreparerFactory;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

@Configuration
public class TilesConfig {
	@Bean
	public TilesConfigurer tilesConfigurer() {
		System.out.println("tiles");
		TilesConfigurer tilesConfigurer = new TilesConfigurer();
		tilesConfigurer.setDefinitions(new String[] {"/WEB-INF/tiles.xml"});
		tilesConfigurer.setCheckRefresh(true);
		//ViewPreparer에서 Autowired가 가능하게 하는 설정
		tilesConfigurer.setPreparerFactoryClass(SimpleSpringPreparerFactory.class);
		return tilesConfigurer;
	}
	@Bean
	public TilesViewResolver tilesViewResolver() {
		TilesViewResolver viewResolver = new TilesViewResolver();
		viewResolver.setViewClass(TilesView.class);
		viewResolver.setOrder(1);
		return viewResolver;
	}
	@Bean
	public UrlBasedViewResolver viewResolver() {
		final UrlBasedViewResolver resolver = new UrlBasedViewResolver();
		resolver.setViewClass(TilesView.class);
		resolver.setOrder(1);
		return resolver;
	}
}

tilesConfig까지 넣어주고 실행하면 된다.
이제 다른 layout을 만들어보자.

layout/map.jsp

<body>
<h2 class="alert alert-info">00 교육센터 강남</h2>
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3165.366002049731!2d127.03101211537782!3d37.499284979810504!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x357ca1c32408f9b7%3A0x4e3761a4f356d1eb!2z7IyN7Jqp6rWQ7Jyh7IS87YSw!5e0!3m2!1sko!2skr!4v1667802146804!5m2!1sko!2skr" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
</body>

map.jsp를 출력하는 layout2를 만들어보자.

layout/layout2.jsp

taglib 추가!

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<body style="background-color: pink">
<div class="layout">
	<div class="menu">
		<tiles:insertAttribute name="menu"/>
	</div>
	<div class="main">
		<tiles:insertAttribute name="main"/>
	</div>
</div>
</body>

tiles.xml

<!-- #layout2 -->
	<definition name="layout2" template="/WEB-INF/layout/layout2.jsp">
		<put-attribute name="menu" value="/WEB-INF/layout/menu.jsp" />
		<put-attribute name="main" value="/WEB-INF/layout/map.jsp"/> 
	</definition>
	<!-- wild card#2 -->
	<definition name="/sub/*/*" extends="layout2">
		<put-attribute name="main" value="/WEB-INF/{1}/{2}.jsp"></put-attribute>
	</definition>

put-attribute name="main" value="/WEB-INF/layout/map.jsp": main 부분에 map.jsp를 출력하겠다는 뜻

HomeController.java

//map 나오게
		@GetMapping("/load/map")
		public String map() {
			return "/sub/layout/map";
		}
profile
하다 보면 되겠지요..!

0개의 댓글