Spring Boot(JSP,Mybatis)

상품 목록

작성자
vita
작성일
2023-11-19 23:12
조회
125

상품 목록

이제 본격적으로 기능을 구현하겠습니다.

먼저 상품목록 출력 기능입니다.

상품 목록의 전반적인 흐름은 아래와 같습니다.





 

주소창에 http://localhost 라고 입력하면 상품목록이 출력됩니다.

모든 요청은 항상 Controller를 경유하게 됩니다.

ProductController 는 ProductDAO 에게 자료를 요청합니다.

ProductDAO 는 mybatis mapper인 product.xml 에 있는 sql 명령어를 실행하여 결과를 Controller에 되돌려줍니다.

Controller는 그 자료를 저장하여 list.jsp 페이지에 보내 출력시킵니다.

 

 

1. ProductDAO.java

com.example.product 패키지에서 우클릭하고 New > Class를 클릭합니다.  클래스 이름은 ProductDAO 입니다.  





 

클래스를 만든 후 아래의 코드를 작성합니다.




package com.example.product;

 

@Repository

public class ProductDAO {

   @Autowired

   SqlSession sqlSession;

   public List<Map<String, Object>> list() {

       return sqlSession.selectList("product.list");

   }

}


 

[해설]

 


@Repository

public class ProductDAO



@Repository 어노테이션은 현재 클래스를 Spring Framework에서 관리하는 데이터 처리를 위한 bean으로 등록시키는 역할을 합니다.  

@Repository 어노테이션이 없다면 아래와 같이 ProductDAO 클래스의 객체를 만드는 작업을 직접 해야 합니다.




ProductDAO productDao=new ProductDAO();


 

@Repository 어노테이션이 있으므로 아래와 같이 @Autowired 어노테이션을 사용하여 간단히 사용할 수 있습니다.

 


@Autowired

ProductDAO productDao;





@Repository

public class ProductDAO


 

DAO는 Data Access Object의 약자입니다.  주로 데이터 처리를 하는 클래스에 DAO라는 이름을 붙입니다.

sql 명령어를 실행시킬 때 많이 사용하는 기술은 mybatis입니다.  

시작 클래스인 ProductApplication.java 클래스의 sqlSession() method를 다시 보겠습니다.




   @Bean

   public SqlSessionTemplate sqlSession(SqlSessionFactory factory) {

       return new SqlSessionTemplate(factory);

   }



@Bean 어노테이션은 Java 객체를 만드는 어노테이션입니다.  Spring Framework이 시작될 때 method 이름인 sqlSession bean이 만들어집니다.




 @Autowired

   SqlSession sqlSession;



@Autowired 어노테이션을 사용하여 서버가 시작될 때 이미 만들어진 sqlSession bean을 연결시킵니다.




public List<Map<String, Object>> list(String product_name) {

       return sqlSession.selectList("product.list", "%" + product_name + "%");

}


 

다음에 작성하게 될 product.xml의 쿼리를 호출하는 코드입니다.

상품이름을 전달하여 해당되는 상품의 리스트를 리턴합니다.  상품이름이 빈값일 경우 모든 상품들을 리턴하게 됩니다.

 

 

2. mybatipse 플러그인 설치

mybatis의 mapper는 xml 문서 형식으로 작성합니다.  작성을 좀더 편리하게 하기 위하여 mybatipse 플러그인을 설치하겠습니다.

STS의 Help > Eclipse Marketplace 메뉴의 검색란에 mybatipse 를 입력하여 조회합니다.

MyBatipse 1.2.5 를 설치합니다.  Install 버튼을 누릅니다.





 

I accept the terms of the license agreement 를 선택하고 [Finish] 버튼을 누릅니다.(버전에 따라서 이 화면이 나타나지 않을 수도 있습니다.)





 

위의 화면이 아닌 아래와 같은 화면이 표시될 수 있습니다.  Unsigned 체크박스에 체크한 후 Trust Selected 버튼을 누릅니다.





 

설치가 완료되면 [Restart Now] 버튼을 눌러서 STS를 재시작합니다.





 

 

3. product.xml

src/main/resources 하위의 mappers 패키지에 product.xml 파일을 생성합니다.





 

검색란에 mybatis를 입력하여 MyBatis XML Mapper를 선택하고 [Next] 버튼을 누릅니다.





 

File name에 product.xml 을 입력하고 [Finish] 버튼을 누릅니다.





 

아래의 코드를 입력합니다.

<mapper namespace=“mappers.product”> 부분을

<mapper namespace=“product”>로 수정합니다.




<?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="product">

   <select id="list" resultType="java.util.Map">

       select * from product

       order by product_name

   </select>

   

</mapper>


 

[해설]

 


<?xml version="1.0" encoding="UTF-8"?>


 

이 파일이 xml 문서임을 나타내는 구문입니다.

xml은 Extended Markup Language의 약자입니다.  html과 달리 xml은 태그를 자유롭게 만들고 사용할 수 있습니다.  xml은 주로 데이터를 주고 받을 때 표준 형식으로 사용합니다.  또는 프로그래밍의 환경설정, 화면 구성 등의 다양한 용도로 사용됩니다.




<mapper namespace="product">


 

현재 작성하고 있는 파일을 mapper 라고 합니다.  데이터베이스의 레코드와 Java 클래스를 매핑시켜 주는 역할을 하기 때문입니다.  

namespace는 SQL 명령어들을 구분하기 위해서 붙이는 식별자입니다.  

 

앞의 ProductDAO 에서 작성했던 코드를 다시 보겠습니다.




public List<Map<String, Object>> list() {

       return sqlSession.selectList("product.list");

}


 

여기서 product.list 는 namespace가 product 이고 id가 list 인 sql 명령어를 실행시키라는 뜻입니다.




<mapper namespace="product">

<select id="list" resultType="java.util.Map">


 

resultType="java.util.Map" 은 sql 명령어를 실행했을 때 1개의 레코드를 저장할 Java 자료형으로 Map을 지정한 것입니다.




   <select id="list" resultType="java.util.Map">

       select * from product

       order by product_name

   </select>





sql 명령어의 실행 결과가 Map에 저장되어 dao로 리턴되고 다시 Controller에 리턴됩니다.

 


   <select id="list" resultType="java.util.Map">

       select * from product

       order by product_name

   </select>


 


public List<Map<String, Object>> list() {

       return sqlSession.selectList("product.list");

 }


 

 

Controller의 list() method는 list.jsp 페이지에 자료를 넘기게 됩니다.

 


   @RequestMapping("/list")

   public ModelAndView list(ModelAndView mav) {

       mav.setViewName("list");

       mav.addObject("list", productDao.list(product_name));

       return mav;

   }



4. ProductController.java

com.example.product 패키지에서 우클릭하고 ProductController 클래스를 생성합니다.  아래의 코드를 입력합니다.




package com.example.product;

 

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;

 

@Controller

public class ProductController {

   @Autowired

   ProductDAO productDao;

   @RequestMapping("/")

   public String home() {

       return "redirect:/list";

   }

   @RequestMapping("/list")

   public ModelAndView list(ModelAndView mav) {

       mav.setViewName("list");

       mav.addObject("list", productDao.list());

       return mav;

   }

}


 

[해설]

 


@Controller

public class ProductController


 

@Controller 어노테이션이 붙은 클래스는 Spring Framework에서 관리하는 bean입니다.  bean은 Java 클래스의 객체를 의미합니다.  웹애플리케이션이 시작될 때 @Controller 어노테이션이 붙은 클래스가 자동으로 실행되고 메모리에 로딩됩니다.




@Autowired

ProductDAO productDao;


 

@Autowired 어노테이션은 ProductDAO 클래스의 객체를 productDao 참조변수에 연결시켜주는 역할을 합니다.  이것을 어려운 용어로 의존관계 주입이라고 합니다.

 

아래와 같은 코드는 참조변수만 있고 실제로 가리키는 내용이 없으므로 아무 일도 할 수 없는 변수입니다.

 


ProductDAO productDao;


 

우변에 ProductDAO 클래스의 객체가 생성되어 있어야 참조변수를 통해 method를 호출할 수 있습니다.

 


ProductDAO productDao=new ProductDAO();


 

ProductDAO 클래스에는 @Repository 라는 어노테이션이 붙어 있습니다.  서버가 시작될 때 ProductDAO도 자동으로 실행되고 메모리에 로딩이 된 상태입니다.

 


@Repository

public class ProductDAO





@RequestMapping("/")

   public String home() {

       return "redirect:/list";

   }


 

@RequestMapping 어노테이션은 url과 method를 연결시켜주는 역할을 합니다.  사용자가 http://localhost 라고 입력하면 위의 home() method가 호출됩니다.




   @RequestMapping("/")

   public String home() {

       return "redirect:/list";

   }


 

Controller의 return은 실제값을 리턴하는 것이 아니라 jsp 페이지 또는 다른 url로 이동하는 기능입니다.  

여기서의 redirect는 다른 주소로 이동을 시키는 명령어입니다.  

이 코드는 다시 Controller의 /list를 호출하게 됩니다.




@RequestMapping("/list")

public ModelAndView list(ModelAndView mav) {


 

ModelAndView는 Model + View의 기능을 가지는 클래스입니다.  Model에 자료를 저장한 후 지정된 View로 이동하는 기능을 제공합니다.




mav.setViewName("list");


 

이동할 View의 이름을 지정합니다.  list.jsp 페이지로 이동을 하게 됩니다.    




mav.addObject("list", productDao.list());


 

모델에 자료를 저장합니다.  addObject(key, value) 구조로 되어 있습니다.  변수명은 list, 값은 상품목록 리스트입니다.




return mav;


 

ModelAndView 객체를 리턴합니다.  지정된 list.jsp로 이동하여 상품목록이 출력됩니다.    

 

 

5. main.css

하이퍼링크의 스타일을 바꾸기 위해서 css 파일을 작성합니다.  src/main/webapp/resources/css 디렉토리에 생성하면 됩니다.




a:link { text-decoration: none; color: blue; }

a:hover { text-decoration: underline; color: red; }

a:visited { text-decoration: none; }

a:active { text-decoration: none; color: yellow; }


 

 

6. list.jsp

src/main/webapp/WEB-INF/views 디렉토리에서 마우스 우클릭을 하고 New > Other를 누릅니다.





 

검색란에 jsp를 입력하고 JSP File을 선택하고 [Next] 버튼을 누릅니다.





 

File name에 list.jsp 를 입력하고 [Finish] 버튼을 누릅니다.





 

아래의 코드를 입력합니다.

 


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

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

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

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

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

<link rel="stylesheet" href="/resources/css/main.css">

</head>

<body>

<h2>상품목록</h2>

등록된 상품개수: ${fn:length(list)}

<table width="100%">

   <tr>

   <c:forEach var="row" items="${list}" varStatus="vs">

       <td style="width:20%; word-break: break-word; vertical-align: bottom;">

           <c:choose>

               <c:when test="${row.filename != '-' }">

                   <img src="/resources/images/${row.filename}" width="100px" height="100px"><br>

               </c:when>

               <c:otherwise>

                   [상품 이미지 미등록]<br>

               </c:otherwise>

           </c:choose>

           상품명: ${row.product_name}<br>

           가격: <fmt:formatNumber value="${row.price}" pattern="#,###" />원

       </td>

       <c:if test="${vs.count mod 5 == 0}">

           </tr><tr>

       </c:if>

   </c:forEach>

   </tr>

</table>

</body>

</html>


 

[해설]

 


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


 

이 페이지의 언어는 Java 이고 내용은 html 이며 파일 인코딩 방식은 utf-8 이라는 내용입니다.




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

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

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


 

jsp에서 Java 코드를 대체할 수 있는 태그 라이브러리 선언문입니다.

taglib prefix=“접두사” uri=“식별자” 형식으로 되어 있습니다.

core 태그는 조건문, 반복문 등의 기능을 제공합니다.

format 태그는 숫자, 날짜의 출력 형식을 제공합니다.

functions 태그는 다양한 함수들을 제공합니다.




<link rel="stylesheet" href="/resources/css/main.css">


 

스타일시트를 지정하는 코드입니다.  href=“스타일시트파일” 이름을 작성합니다.




등록된 상품개수: ${fn:length(list)}


 

${변수} 코드는 EL(Expression Language) 문법이며 표현언어라고 합니다.  EL도 jsp 페이지에서 Java 코드를 대체하기 위한 구문을 제공합니다.

 

fn:length(list)는 functions 태그에 내장되어 있는 length 함수를 호출하여 list 변수의 자료 개수를 계산합니다.  list 라는 이름의 변수는 Controller에서 넘어온 변수입니다.  

 

Controller에서 list 라는 이름으로 값을 넘겼습니다.




mav.addObject("list", productDao.list(product_name));


 

jsp 페이지에서는 ${list} 로 받으면 됩니다.  보내는 쪽과 받는 쪽의 변수명이 같아야 읽을 수가 있습니다.

 

c:forEach 는 core 태그 중에서 forEach 문을 실행시키는 JSTL 태그입니다.

형식은 아래와 같습니다.

<c:forEach var=“개별변수” items=“리스트변수”>




   <c:forEach var="row" items="${list}" varStatus="vs">


 

${list}는 Controller에서 전달한 변수입니다.




   <c:forEach var="row" items="${list}" varStatus="vs">


 

리스트에 포함된 개별자료가 row라는 이름으로 반복하여 첫번째 자료부터 마지막 자료까지 반복 처리가 됩니다.




   <c:forEach var="row" items="${list}" varStatus="vs">


 

varStatus는 반복문의 상태를 확인할 수 있는 변수입니다..





           <c:choose>

               <c:when test="${row.filename != '-' }">

                   <img src="/resources/images/${row.filename}" width="100px" height="100px"><br>

               </c:when>

               <c:otherwise>

                   [상품 이미지 미등록]<br>

               </c:otherwise>

           </c:choose>


 

choose 태그는 2개 이상의 조건을 검사하여 분류하는 명령어입니다.

<c:choose>

               <c:when test="조건식">

                   조건식이 맞을 경우

               </c:when>

               <c:when test="조건식">

                   조건식이 맞을 경우

               </c:when>

               <c:otherwise>

                   그 외의 경우

               </c:otherwise>

</c:choose>

when test=“조건식”을 검사하여 맞는지의 여부에 따라 여러가지 경우 중 하나의 처리를 하게 됩니다.

${row.filename != ‘-’ }   첨부파일의 이름이 – 이 아니면 이미지를 화면에 표시합니다.  첨부파일의 이름이 – 이라면 첨부파일이 없으므로 [상품 이미지 미등록] 문구를 출력합니다.




           상품명: ${row.product_name}<br>


 

${row.필드명}  형식으로 출력이 되어 상품이름이 출력됩니다.




           가격: <fmt:formatNumber value="${row.price}" pattern="#,###" />원


 

formatNumber 태그의 값은 가격입니다.  pattern에 #,### 라고 지정하면 세자리마다 컴머를 출력할 수 있습니다.

 




       <c:if test="${vs.count mod 5 == 0}">

           </tr><tr>

       </c:if>


 

if문은 core 태그의 조건문입니다.  

varStatus 변수의 count 변수는 반복문의 카운트 횟수를 의미합니다.  10개의 상품이 있다면 1~10 까지 반복적으로 출력이 됩니다.  A mod B 라는 식은 A를 B로 나눈 나머지를 의미합니다.

즉 ${vs.count mod 5 == 0} 이라는 식은 count 값을 5로 나눈 나머지가 0이면 줄바꿈을 하라는 뜻입니다.  한 줄에 5개의 상품만 출력하겠다는 것입니다.

 

 

7. 상품 목록 실행 결과 확인

프로젝트에서 우클릭을 하고 Run As > spring boot app을 클릭하면 웹서버가 시작됩니다.

또는 com.example.product 패키지의 ProductApplication.java 클래스를 우클릭한 후 Run As > Spring Boot App 메뉴를 클릭합니다.





 

스프링 부트가 성공적으로 실행되었습니다.

Console에 에러가 없으면 정상적으로 실행된 것입니다.

Tomcat 서비스가 80번 포트에서 실행중임을 알 수 있습니다.





 

웹브라우저를 실행하신 후 주소창에 http://localhost를 입력하면 상품목록을 볼 수 있습니다.

아직은 아무 상품도 등록된 것이 없습니다.

상품 등록 기능까지 만든 후에 아래와 같은 화면을 볼 수 있습니다.




Scroll to Top