📝Tiles
웹 페이지의 상단, 하단, 사이드바, ajax, 공통css 등과 같이 반복적으로 사용되는 부분에 정보를 모듈화해서 관리해줍니다.
즉 모듈관리 프로그램입니다.
JSP의 include같은 걸로 쓸수도 있지만 Tiles가 훨씬 우수합니다.
JSP Include 방식의 문제점은 매 JSP 페이지마다 모두 동일한 페이지들을 include 한다고 표시를 해야합니다.
만약 include 하는 페이지의 이름이 바뀌기라도 한다면 그에 해당하는 모든 페이지를 다 수정해야만 합니다.
<!-- spring 버전은 3.0.8 이상 필요 및 자바버전도 유의-->
<properties>
<java-version>11</java-version>
<org.springframework-version>5.2.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<!-- Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-extras</artifactId>
<version>3.0.8</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>3.0.8</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.8</version>
</dependency>
pom.xml
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
<beans:property name="order" value="2" />
</beans:bean>
<!-- load 순서 2번째 -->
<beans:bean
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<beans:property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView" />
<beans:property name="order" value="1" />
</beans:bean>
<!-- load 순서 1번째 (tiles 설정파일) -->
<beans:bean
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<beans:property name="definitions"
value="/WEB-INF/tiles.xml" />
</beans:bean>
<!-- load 순서 1번째에 쓰이는 tiles 설정파일 -->
servlet-context.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>
<definition name="*/*" template="/WEB-INF/views/include/layout.jsp">
<put-attribute name="title" value="{2} - OCR" />
<put-attribute name="header" value="/WEB-INF/views/include/top.jsp" />
<put-attribute name="body" value="/WEB-INF/views/{1}/{2}.jsp" />
<put-attribute name="static" value="/WEB-INF/views/include/static.jsp" />
<put-attribute name="aside" value="/WEB-INF/views/include/side.jsp" />
</definition>
<!-- definition name은 Controller의 */*형태의 return값을 받으면 해당 definition으로 분기시키겠다는 의미입니다.-->
<!-- 예를 들어 Controller에서 페이지 리턴하려면 login/login_page 이런 형식으로 return할 때 {1} 에는 login이 들어가고 {2}에는 login_page가 들어가게 됩니다.
<!-- 그리고 분기 페이지(template)는 layout.jsp 이라는 것입니다.-->
<!-- layout.jsp에서 각각 모듈로 된 걸 injection 하게 됩니다.-->
<!-- put-attribute 은 layout에 넣을 요소 -->
<!-- 위와 같은 방법으로 body는 동적으로 바뀌게 된다. -->
</tiles-definitions>
tiles.xml
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<!-- tiles.xml에서 선언한 name으로 각 모듈을 호출합니다. -->
<title><tiles:insertAttribute name="title" /></title>
<tiles:insertAttribute name="static" />
</head>
<body>
<!-- header -->
<tiles:insertAttribute name="header" />
<div class="row">
<!-- side -->
<div class="col-1" id="layoutSide">
<div id="layoutSidenav">
<tiles:insertAttribute name="aside" />
</div>
</div>
<!-- body -->
<div class="col-9 mt-5" style="position: relative; left: 100px;">
<tiles:insertAttribute name="body" />
</div>
</div>
</body>
</html>
layout.jsp (전체 구조)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<link href="<%=request.getContextPath()%>/resources/css/side_style.css"
rel="stylesheet"><tiles:insertAttribute name="aside" />
<div class="sidebody">
<div class="sidenavigation">
<ul>
<li class="sidelist active"><a href="test"> <span
class="icon ps-4"><ion-icon name="albums-outline"></ion-icon></span>
<span class="title ms-3">대시보드</span>
</a></li>
<li class="sidelist"><a href="listOcr"> <span
class="icon ps-4"><ion-icon name="person-outline"></ion-icon></span>
<span class="title ms-3">주민등록증</span>
</a></li>
<li class="sidelist"><a href="#"> <span class="icon ps-4"><ion-icon
name="car-outline"></ion-icon></span> <span class="title ms-3">운전면허증</span>
</a></li>
<li class="sidelist"><a href="#"> <span class="icon ps-4"><ion-icon
name="language-outline"></ion-icon></span> <span class="title ms-3">외국인등록증</span>
</a></li>
<li class="sidelist"><a href="#"> <span class="icon ps-4"><ion-icon
name="airplane-outline"></ion-icon></span> <span class="title ms-3">여권</span>
</a></li>
</ul>
</div>
</div>
<script type="module"
src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.esm.js"></script>
<script nomodule
src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.js"></script>
<script src="<%=request.getContextPath()%>/resources/js/script.js"></script>
side.jsp (사이드바)
<style>
@import
url('https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap')
;
</style>
<!-- CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous">
<link href="<%=request.getContextPath()%>/resources/css/styles.css"
rel="stylesheet">
<link href="<%=request.getContextPath()%>/resources/css/custom.css"
rel="stylesheet">
<link href="<%=request.getContextPath()%>/resources/css/common.css"
rel="stylesheet">
<link href="<%=request.getContextPath()%>/resources/css/bootstrap.css"
rel="stylesheet" />
<link
href="<%=request.getContextPath()%>/resources/css/search_result.css"
rel="stylesheet" />
<link rel="icon" type="image/x-icon"
href="<%=request.getContextPath()%>/resources/assets/img/favicon.png" />
<!-- JS -->
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
static.jsp (정적 소스)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<style>
background: linear-gradient(137deg, #fff6b7, #f77c99, #6578f2, #c2ffd8); background-size: 800% 800%; -webkit-animation: AnimationName 16s ease infinite; -moz-animation: AnimationName 16s ease infinite; -o-animation: AnimationName 16s ease infinite; animation: AnimationName 16s ease infinite; @-webkit-keyframes AnimationName { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} } @-moz-keyframes AnimationName { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} } @-o-keyframes AnimationName { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} } @keyframes AnimationName { 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} }
</style>
<nav
class="topnav navbar navbar-expand shadow justify-content-between justify-content-sm-start navbar-light m-0 p-0"
id="sidenavAccordion" style="height:70px">
<!-- Sidenav Toggle Button
<button class="btn btn-icon btn-transparent-dark" id="sidebarToggle">
<i data-feather="menu"></i>
</button> -->
<!-- Navbar Brand-->
<!-- * * Tip * * You can use text or an image for your navbar brand.-->
<!-- * * * * * * When using an image, we recommend the SVG format.-->
<!-- * * * * * * Dimensions: Maximum height: 32px, maximum width: 240px-->
<a href="test" class="ms-5 me-2"> <img
src="<%=request.getContextPath()%>/resources/image/logo.png"
; style="width: 113px;">
</a>
<a href="doLogout" style="right: 0; color: #FFFFFF;" onclick="if(confirm('로그아웃 하시겠습니까?') == false)return false;"> 로그아웃 </a>
</nav>
top.jsp (상단)
footer.jsp는 저는 안 써가지고 따로 만들진 않았습니다.
- 참고용(여러가지의 - tiles 활용 방식)
<?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>
<definition name="*/*" template="/WEB-INF/views/include/layout.jsp">
<put-attribute name="title" value="{2} - Search" />
<put-attribute name="header" value="/WEB-INF/views/include/top.jsp" />
<put-attribute name="body" value="/WEB-INF/views/{1}/{2}.jsp" />
<put-attribute name="static" value="/WEB-INF/views/include/static.jsp" />
<put-attribute name="aside" value="/WEB-INF/views/include/side.jsp" />
<put-attribute name="footer" value="/WEB-INF/views/include/footer.jsp" />
</definition>
<definition name="*/*/*" template="/WEB-INF/views/include/none_layout.jsp">
<put-attribute name="title" value="{3} - Search" />
<put-attribute name="body" value="/WEB-INF/views/{1}/{2}/{3}.jsp" />
<put-attribute name="static" value="/WEB-INF/views/include/static.jsp" />
<put-attribute name="footer" value="/WEB-INF/views/include/footer.jsp" />
</definition>
<definition name="login" template="/WEB-INF/views/include/login_layout.jsp">
<put-attribute name="title" value="login - Search" />
<put-attribute name="body" value="/WEB-INF/views/login/login.jsp" />
<put-attribute name="static" value="/WEB-INF/views/include/static.jsp" />
<put-attribute name="footer" value="/WEB-INF/views/include/footer.jsp" />
</definition>
</tiles-definitions>