티스토리 뷰




테스트 환경

OS : Windows 10 64bit

Tool : STS spring-tool-suite-3.7.3.RELEASE

Was : apache-tomcat-8.0.36

Java : jdk1.8.0_91








깔끔한 웹 사이트 구축을 하고 싶지만 시간과 디자인 능력이 없다면 부트스트랩을 이용하자. 
Bootstrap은 반응형 웹으로 구현되어 있기 때문에 PC용과 모바일용으로 구분해서 만들 필요가 없다. 


1. 부트스트랩 다운로드 

기본소스만 받으려면 Bootstrap을, 예제 소스까지 받으려면 Source code를 다운로드 한다. 






2. 프로젝트에 부트스트랩 include


다운로드한 파일을 압축해제 한다.

아래와 같이 부트스트랩 폴더를 webapp폴더 아래에 복사한다. 

폴더명은 bootstrap으로 변경했다.







3. 예제 소스 적용하기


Getting started 페이지 아래에 보면 샘플 페이지들을 볼 수 있다. 

여기서 하나를 선택하여 메인화면으로 적용해 보자.

오리지널 소스코드만 다운로드 했기때문에 샘플 코드에 필요한 js파일이 없다. 

필요한 js 파일 몇개만 직접 생성하자. 


만약 이작업이 귀찮다면 Source code를 다운로드하여 필요한 js파일을 복사해서 붙여넣기 한다. 



bootstrap/css/carousel.css


/* GLOBAL STYLES

-------------------------------------------------- */

/* Padding below the footer and lighter body text */


body {

  padding-bottom: 40px;

  color: #5a5a5a;

}



/* CUSTOMIZE THE NAVBAR

-------------------------------------------------- */


/* Special class on .container surrounding .navbar, used for positioning it into place. */

.navbar-wrapper {

  position: absolute;

  top: 0;

  right: 0;

  left: 0;

  z-index: 20;

}


/* Flip around the padding for proper display in narrow viewports */

.navbar-wrapper > .container {

  padding-right: 0;

  padding-left: 0;

}

.navbar-wrapper .navbar {

  padding-right: 15px;

  padding-left: 15px;

}

.navbar-wrapper .navbar .container {

  width: auto;

}



/* CUSTOMIZE THE CAROUSEL

-------------------------------------------------- */


/* Carousel base class */

.carousel {

  height: 500px;

  margin-bottom: 60px;

}

/* Since positioning the image, we need to help out the caption */

.carousel-caption {

  z-index: 10;

}


/* Declare heights because of positioning of img element */

.carousel .item {

  height: 500px;

  background-color: #777;

}

.carousel-inner > .item > img {

  position: absolute;

  top: 0;

  left: 0;

  min-width: 100%;

  height: 500px;

}



/* MARKETING CONTENT

-------------------------------------------------- */


/* Center align the text within the three columns below the carousel */

.marketing .col-lg-4 {

  margin-bottom: 20px;

  text-align: center;

}

.marketing h2 {

  font-weight: normal;

}

.marketing .col-lg-4 p {

  margin-right: 10px;

  margin-left: 10px;

}



/* Featurettes

------------------------- */


.featurette-divider {

  margin: 80px 0; /* Space out the Bootstrap <hr> more */

}


/* Thin out the marketing headings */

.featurette-heading {

  font-weight: 300;

  line-height: 1;

  letter-spacing: -1px;

}



/* RESPONSIVE CSS

-------------------------------------------------- */


@media (min-width: 768px) {

  /* Navbar positioning foo */

  .navbar-wrapper {

    margin-top: 20px;

  }

  .navbar-wrapper .container {

    padding-right: 15px;

    padding-left: 15px;

  }

  .navbar-wrapper .navbar {

    padding-right: 0;

    padding-left: 0;

  }


  /* The navbar becomes detached from the top, so we round the corners */

  .navbar-wrapper .navbar {

    border-radius: 4px;

  }


  /* Bump up size of carousel content */

  .carousel-caption p {

    margin-bottom: 20px;

    font-size: 21px;

    line-height: 1.4;

  }


  .featurette-heading {

    font-size: 50px;

  }

}


@media (min-width: 992px) {

  .featurette-heading {

    margin-top: 120px;

  }

}






bootstrap/css/ie10-viewport-bug-workaround.css


@CHARSET "UTF-8";

/*!

 * IE10 viewport hack for Surface/desktop Windows 8 bug

 * Copyright 2014-2015 Twitter, Inc.

 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)

 */


/*

 * See the Getting Started docs for more information:

 * http://getbootstrap.com/getting-started/#support-ie10-width

 */

@-webkit-viewport { width: device-width; }

@-moz-viewport    { width: device-width; }

@-ms-viewport     { width: device-width; }

@-o-viewport      { width: device-width; }

@viewport         { width: device-width; }





bootstrap/js/ie-emulation-modes-warning.js


// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT

// IT'S JUST JUNK FOR OUR DOCS!

// ++++++++++++++++++++++++++++++++++++++++++

/*!

 * Copyright 2014-2015 Twitter, Inc.

 *

 * Licensed under the Creative Commons Attribution 3.0 Unported License. For

 * details, see https://creativecommons.org/licenses/by/3.0/.

 */

// Intended to prevent false-positive bug reports about Bootstrap not working properly in old versions of IE due to folks testing using IE's unreliable emulation modes.

(function () {

  'use strict';


  function emulatedIEMajorVersion() {

    var groups = /MSIE ([0-9.]+)/.exec(window.navigator.userAgent)

    if (groups === null) {

      return null

    }

    var ieVersionNum = parseInt(groups[1], 10)

    var ieMajorVersion = Math.floor(ieVersionNum)

    return ieMajorVersion

  }


  function actualNonEmulatedIEMajorVersion() {

    // Detects the actual version of IE in use, even if it's in an older-IE emulation mode.

    // IE JavaScript conditional compilation docs: https://msdn.microsoft.com/library/121hztk3%28v=vs.94%29.aspx

    // @cc_on docs: https://msdn.microsoft.com/library/8ka90k2e%28v=vs.94%29.aspx

    var jscriptVersion = new Function('/*@cc_on return @_jscript_version; @*/')() // jshint ignore:line

    if (jscriptVersion === undefined) {

      return 11 // IE11+ not in emulation mode

    }

    if (jscriptVersion < 9) {

      return 8 // IE8 (or lower; haven't tested on IE<8)

    }

    return jscriptVersion // IE9 or IE10 in any mode, or IE11 in non-IE11 mode

  }


  var ua = window.navigator.userAgent

  if (ua.indexOf('Opera') > -1 || ua.indexOf('Presto') > -1) {

    return // Opera, which might pretend to be IE

  }

  var emulated = emulatedIEMajorVersion()

  if (emulated === null) {

    return // Not IE

  }

  var nonEmulated = actualNonEmulatedIEMajorVersion()


  if (emulated !== nonEmulated) {

    window.alert('WARNING: You appear to be using IE' + nonEmulated + ' in IE' + emulated + ' emulation mode.\nIE emulation modes can behave significantly differently from ACTUAL older versions of IE.\nPLEASE DON\'T FILE BOOTSTRAP BUGS based on testing in IE emulation modes!')

  }

})();






bootstrap/js/ie8-responsive-file-warning.js


// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT

// IT'S JUST JUNK FOR OUR DOCS!

// ++++++++++++++++++++++++++++++++++++++++++

/*!

 * Copyright 2011-2015 Twitter, Inc.

 *

 * Licensed under the Creative Commons Attribution 3.0 Unported License. For

 * details, see https://creativecommons.org/licenses/by/3.0/.

 */

// Intended to prevent false-positive bug reports about responsive styling supposedly not working in IE8.

if (window.location.protocol == 'file:') {

  window.alert('ERROR: Bootstrap\'s responsive CSS is disabled!\nSee getbootstrap.com/getting-started/#respond-file-proto for details.')

}






views/main.jsp 파일을 생성한 뒤 아래 예제 소스를 복사해서 붙여 넣는다.


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html lang="ko">

  <head>

    <meta charset="utf-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->

    <meta name="description" content="">

    <meta name="author" content="">

    <!-- <link rel="icon" href="../../favicon.ico"> -->


    <title>Carousel Template for Bootstrap</title>


    <!-- Bootstrap core CSS -->

    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">


    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->

    <link href="bootstrap/css/ie10-viewport-bug-workaround.css" rel="stylesheet">


    <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->

    <!--[if lt IE 9]><script src="bootstrap/js/ie8-responsive-file-warning.js"></script><![endif]-->

    <script src="bootstrap/js/ie-emulation-modes-warning.js"></script>


    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->

    <!--[if lt IE 9]>

      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>

      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>

    <![endif]-->


    <!-- Custom styles for this template -->

    <link href="bootstrap/css/carousel.css" rel="stylesheet">

  </head>

<!-- NAVBAR

================================================== -->

  <body>

    <div class="navbar-wrapper">

      <div class="container">


        <nav class="navbar navbar-inverse navbar-static-top">

          <div class="container">

            <div class="navbar-header">

              <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">

                <span class="sr-only">Toggle navigation</span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

              </button>

              <a class="navbar-brand" href="#">Project name</a>

            </div>

            <div id="navbar" class="navbar-collapse collapse">

              <ul class="nav navbar-nav">

                <li class="active"><a href="#">Home</a></li>

                <li><a href="#about">About</a></li>

                <li><a href="#contact">Contact</a></li>

                <li class="dropdown">

                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>

                  <ul class="dropdown-menu">

                    <li><a href="#">Action</a></li>

                    <li><a href="#">Another action</a></li>

                    <li><a href="#">Something else here</a></li>

                    <li role="separator" class="divider"></li>

                    <li class="dropdown-header">Nav header</li>

                    <li><a href="#">Separated link</a></li>

                    <li><a href="#">One more separated link</a></li>

                  </ul>

                </li>

              </ul>

            </div>

          </div>

        </nav>


      </div>

    </div>



    <!-- Carousel

    ================================================== -->

    <div id="myCarousel" class="carousel slide" data-ride="carousel">

      <!-- Indicators -->

      <ol class="carousel-indicators">

        <li data-target="#myCarousel" data-slide-to="0" class="active"></li>

        <li data-target="#myCarousel" data-slide-to="1"></li>

        <li data-target="#myCarousel" data-slide-to="2"></li>

      </ol>

      <div class="carousel-inner" role="listbox">

        <div class="item active">

          <img class="first-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="First slide">

          <div class="container">

            <div class="carousel-caption">

              <h1>Example headline.</h1>

              <p>Note: If you're viewing this page via a <code>file://</code> URL, the "next" and "previous" Glyphicon buttons on the left and right might not load/display properly due to web browser security rules.</p>

              <p><a class="btn btn-lg btn-primary" href="#" role="button">Sign up today</a></p>

            </div>

          </div>

        </div>

        <div class="item">

          <img class="second-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Second slide">

          <div class="container">

            <div class="carousel-caption">

              <h1>Another example headline.</h1>

              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>

              <p><a class="btn btn-lg btn-primary" href="#" role="button">Learn more</a></p>

            </div>

          </div>

        </div>

        <div class="item">

          <img class="third-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Third slide">

          <div class="container">

            <div class="carousel-caption">

              <h1>One more for good measure.</h1>

              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>

              <p><a class="btn btn-lg btn-primary" href="#" role="button">Browse gallery</a></p>

            </div>

          </div>

        </div>

      </div>

      <a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">

        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>

        <span class="sr-only">Previous</span>

      </a>

      <a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">

        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>

        <span class="sr-only">Next</span>

      </a>

    </div><!-- /.carousel -->



    <!-- Marketing messaging and featurettes

    ================================================== -->

    <!-- Wrap the rest of the page in another container to center all the content. -->


    <div class="container marketing">


      <!-- Three columns of text below the carousel -->

      <div class="row">

        <div class="col-lg-4">

          <img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">

          <h2>Heading</h2>

          <p>Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.</p>

          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>

        </div><!-- /.col-lg-4 -->

        <div class="col-lg-4">

          <img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">

          <h2>Heading</h2>

          <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.</p>

          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>

        </div><!-- /.col-lg-4 -->

        <div class="col-lg-4">

          <img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">

          <h2>Heading</h2>

          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>

          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>

        </div><!-- /.col-lg-4 -->

      </div><!-- /.row -->



      <!-- START THE FEATURETTES -->


      <hr class="featurette-divider">


      <div class="row featurette">

        <div class="col-md-7">

          <h2 class="featurette-heading">First featurette heading. <span class="text-muted">It'll blow your mind.</span></h2>

          <p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>

        </div>

        <div class="col-md-5">

          <img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">

        </div>

      </div>


      <hr class="featurette-divider">


      <div class="row featurette">

        <div class="col-md-7 col-md-push-5">

          <h2 class="featurette-heading">Oh yeah, it's that good. <span class="text-muted">See for yourself.</span></h2>

          <p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>

        </div>

        <div class="col-md-5 col-md-pull-7">

          <img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">

        </div>

      </div>


      <hr class="featurette-divider">


      <div class="row featurette">

        <div class="col-md-7">

          <h2 class="featurette-heading">And lastly, this one. <span class="text-muted">Checkmate.</span></h2>

          <p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>

        </div>

        <div class="col-md-5">

          <img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">

        </div>

      </div>


      <hr class="featurette-divider">


      <!-- /END THE FEATURETTES -->



      <!-- FOOTER -->

      <footer>

        <p class="pull-right"><a href="#">Back to top</a></p>

        <p>&copy; 2015 Company, Inc. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>

      </footer>


    </div><!-- /.container -->

  </body>

</html>





마지막으로 클래스 파일을 생성하자.

패키지 경로는 me.jlblog.myapp.controller 이고, 클래스 명은 MainController.java 이다.

소스는 다음과 같다.


package me.jlblog.myapp.controller;


import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


@Controller

public class MainController {

private static final Logger logger = LoggerFactory.getLogger(MainController.class);

@RequestMapping(value = "/main", method = RequestMethod.GET)

public String main(Locale locale, Model model) {

logger.info("Welcome main! The client locale is {}.", locale);

return "main";

}

}




아.. 부트스트랩 매핑을 위해 하나만 더 추가하자. 


spring/appServlet/servlet-context.xml을 열어서 아래 내용을 추가한다. 


<resources mapping="/resources/**" location="/resources/" />

<resources mapping="/bootstrap/**" location="/bootstrap/" />




톰캣서버를 start 한후 localhost:8080/main으로 접속한다.

아래 이미지처럼 화면이 출력 된다면 성공한 것이다. 





자. 이제 다음은?



댓글