빅데이터 Java 개발자 교육 [Spring - 3 (물품)]

Jun_Gyu·2023년 5월 2일
0
post-thumbnail

오늘은 저번시간에 이어 전체적인 복습 겸, Item(물품)에 관련한 기능들을 추가해보겠다.

복습하기

추가할 사항들은 DTO, Controller, Service, ServiceImpl, Mapper, Mapper.xml, html이다.
엄청많다;;

차례대로 추가해보자.

item dto

package com.example.dto;
import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Item {

	private long no;
	private String name;
	private String content;
	private long quantity;
	private long price;
	private Date regdate;
	
	private long imageNo; // 대표 이미지번호를 저장할 임시변수

}

itemImage dto

package com.example.dto;

import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString (exclude = {"filedata"})
@NoArgsConstructor
@AllArgsConstructor
public class ItemImage {
	private long no;

	private String filename;
	private long filesize;
	private byte[] filedata; //BLOB
	private String filetype;
    
	private long itemno;
	private Date regdate;

}

ItemMapper

package com.example.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.dto.Item;
import com.example.dto.ItemImage;

@Mapper
public interface ItemMapper {

    // 물품전체조회
    public List<Item> selectItemList();
    
    // 이미지 물품 등록
    public int insertItemImage( ItemImage obj );

    // 이미지 번호가 전송되면 1개의 이미지 정보 반환 (개별이미지 1개)
    public ItemImage selectItemImageOne( long no );

    // 물품번호를 전송하면 해당하는 이미지번호를 반환
    public List<Long> selectItemImageNo( long itemno );

}

우선적으로 물품의 전체 조회가 가능한 기능부터 추가해보았다.

ItemMapper.xml

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

<!-- 기존의 interface ItemMapper명과 일치해야 함-->
<mapper namespace="com.example.mapper.ItemMapper"> 
    
    <!-- 물품 전체조회 -->
    <select id="selectItemList" resultType="com.example.dto.Item">
    <!-- resultType에는 반환하고자 하는 형태가 들어가야 함. -->
        SELECT * FROM item ORDER BY no DESC
    </select>

    <!-- 물품이미지 등록 (1) -->
    <insert id="insertItemImage" parameterType="com.example.dto.ItemImage">
        INSERT INTO itemimage(filename, filesize, filedata, filetype, itemno)
        VALUES(#{filename}, #{filesize}, #{filedata}, #{filetype},#{itemno})
    </insert>
    
    <!-- 이미지 한개의 주소 설정 -->
    <select id="selectItemImageOne" parameterType="long" resultType="com.example.dto.ItemImage">
        SELECT * FROM itemimage WHERE no = #{no}
    </select>

    <!-- 물품당 이미지no 조회 -->
    <select id="selectItemImageNo" parameterType="long" resultType="long">
        SELECT i.no FROM itemimage i WHERE itemno = #{itemno}
    </select>
</mapper>

ItemService

package com.example.service;
import java.util.List;

import org.springframework.stereotype.Service;

import com.example.dto.Item;
import com.example.dto.ItemImage;

// 컨트롤러에서 실행하는 클래스
@Service
public interface ItemService {
    
    // 물품 전체조회
    public List<Item> selectItemList();

    // 이미지 물품 등록
    public int insertItemImage(ItemImage obj);
}

ItemServiceImpl

package com.example.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.example.dto.Item;
import com.example.dto.ItemImage;
import com.example.mapper.ItemMapper;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor 
public class ItemServiceImpl implements ItemService{

    final ItemMapper iMapper; // 매퍼 객체 생성 @Autowired Itemmapper iMapper;

    @Override
    public List<Item> selectItemList() {
        try {
            return iMapper.selectItemList();
        }
        catch (Exception e) {
            e.printStackTrace(); // 오류발생시 터미널에 표시
            return null; // 오류발생시 null 반환
        }
    }

    @Override
    public int insertItemImage(ItemImage obj) {
        try {
            return iMapper.insertItemImage(obj);
        }
        catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
       
    }
    
}

Service의 경우에는 개인 실습때는 생략하기로 했다!


ItemController

package com.example.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.example.dto.Item;
import com.example.dto.ItemImage;
import com.example.mapper.ItemMapper;
import com.example.service.ItemService;

@Controller
@RequestMapping(value = "/item")
public class ItemController {

    @Autowired ItemService iService; // 서비스 객체 생성
    @Autowired ItemMapper iMapper; // 서비스 사용하지 않고 바로 매퍼 호출.(나중에는 서비스를 통해서 할것!)
    @Autowired ResourceLoader resourceLoader; // resources 폴더의 파일 불러오기

    @Value("${default.image}") String defaultImage; // 기본이미지

    /* ------------------------------------------------------------------------------------------------- */
                                                 // image //

    // <img src="@{/item/image(no=1)}">
    // String = html 파일을 표시
    // ResponseEntity<byte[]>  =>  이미지나 동영상등을 표시
    // 127.0.0.1:9090/ROOT/item/image?no=1
    @GetMapping(value = "/image")
    public ResponseEntity<byte[]> image( @RequestParam(name = "no", defaultValue = "0" ) long no ) throws IOException {
        ItemImage obj = iMapper.selectItemImageOne(no);


        HttpHeaders headers = new HttpHeaders();
        if( obj != null ){ // 이미지가 존재하는 경우
            if( obj.getFilesize() > 0 ){
                headers.setContentType( MediaType.parseMediaType( obj.getFiletype() ) );
                ResponseEntity<byte[]> response = new ResponseEntity<>( obj.getFiledata(), headers, HttpStatus.OK );
                return response;
            }
        }
        
        InputStream is = resourceLoader.getResource("classpath:/static/images/default.png").getInputStream(); // exception 발생됨.
        headers.setContentType(MediaType.IMAGE_PNG);
        return new ResponseEntity<>( is.readAllBytes(), headers, HttpStatus.OK );
    }
    /* ------------------------------------------------------------------------------------------------- */
                                                // insertImage //

    // /item/insertimage.do?no=7 => name값은 no이고, value값은 숫자 7이 전달됨.
    // <input type="text" name="no" value="7" />
    @GetMapping(value = "/insertimage.do")
    public String insertimageGet(@RequestParam(name = "no", defaultValue = "0", required = false) long no,
            Model model) {
        if (no == 0) {
            return "redirect:selectlist.do"; // 상대경로로 이동, 가장 마지막 주소만 변경해서 이동
        }

        model.addAttribute("itemno", no);
        return "/item/insertimage"; // resources/ templates/item폴더/insertimage.html
    }

    @PostMapping(value = "/insertimage.do")
    public String insertImagePOST( @ModelAttribute ItemImage obj, 
            @RequestParam(name = "file1") MultipartFile file1) throws IOException {
        obj.setFilename( file1.getOriginalFilename() );        
        obj.setFilesize( file1.getSize() );
        obj.setFiletype( file1.getContentType() );
        obj.setFiledata( file1.getBytes() ); //exception발생됨.
        System.out.println(obj.toString()); //확인용

        int ret = iService.insertItemImage(obj);
        if( ret == 1) {
            return "redirect:insertimage.do?no=" + obj.getItemno(); 
        }
        return "redirect:insertimage.do?no=" + obj.getItemno(); 
    }
    /* ------------------------------------------------------------------------------------------------- */
                                                // selectlist //
    // 127.0.0.1:9090/ROOT/item/selectList.do
    @GetMapping(value = "/selectlist.do")
    public String selectListGet(Model model) {
        // 1. 서비스를 호출하여 물품목록 받기
        List<Item> list = iService.selectItemList();

        // 2. model을 활용하여 view로 받은목록 전달하기
        model.addAttribute("list", list);

        // 3. view를 화면에 표시하기
        return "/item/selectlist"; // resources/templates (/item폴더를 생성, selectlist.html을 생성)
    }
    /* ------------------------------------------------------------------------------------------------- */
}


HTML

selectlist.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <title>물품 전체조회</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
</head>
<body>
    <header>
        <br>
        <h1 class="text-center">Jungyu's ItemSelecter</h1>
    </header>
    <table class="table table-hover table-striped text-center" style="border: 1px solid;">
        <thead>
            <tr style="background-color: rgb(255, 237, 237);">
                <th>물품번호</th>
                <th>물품명</th>
                <th>물품내용</th>
                <th>물품가격</th>
                <th>물품수량</th>
                <th>등록일</th>
                <th>이미지 등록하기</th>
            </tr>
        </thead>
        <tbody>
            <!-- 'ItemController'로부터 전달받은 "list" -->
            <tr th:each="obj : ${list}">
                <td th:text="${obj.no}"></td>
                <td th:text="${obj.name}"></td>
                <td th:text="${obj.content}"></td>
                <td th:text="${obj.price}"></td>
                <td th:text="${obj.quantity}"></td>
                <td th:text="${obj.regdate}"></td>
                <!-- 물품 번호를 받아와서 이미지를 등록하는 방식. -->
                <td><a th:href="@{/item/insertimage.do(no=${obj.no})}" class="btn btn-outline-danger">이미지 등록</a></td>
            </tr>
        </tbody>
    </table>
</body>
</html>

insertimage.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <title>물품 이미지 등록</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
</head>
<body>
    <form th:action="@{/item/insertimage.do}" method="post" enctype="multipart/form-data">
        외래키(물품번호) : <input type="text" name="itemno" th:value="${itemno}" readonly/><br />
        첨부 이미지 : <input type="file" name="file1" accept="image/*"/><br />
        <input type="submit" value="업로드" />
    </form>
    <a th:href="@{/item/selectlist.do}">뒤로가기</a>
</body>
</html>

위와같이 기본적으로 물품과 관련된 기본적인 페이지들을 구성해주었다.




resource 폴더의 파일 불러오기

이번에는 이미지가 없을 시 나오는 기본이미지의 경로 설정방법이다.

@Autowired ResourceLoader resourceLoader; // resources 폴더의 파일 불러오기

먼저 controller에 리소스파일을 불러오는 ResourceLoader 기능을 추가한다.

이후 기본 이미지 파일이 있는 경로를 위와 같이 지정해준다.

추가로 @Value 어노테이션을 사용하여 항상 경로를 반복적으로 입력해야 하는 수고를 줄이는 방법도 있다.

위의 방법을 이용한다면 아래와 같이 다른 상황에서도 사용이 가능하다.

Mapper.xml의 resultType 경로 간략하게 표시하기

위에서 본 Value 어노테이션과 같은 느낌으로, mapper의 결과값을 내보낼 형태를 일일이 경로를 지정해주지 않아도 된다.

profile
시작은 미약하지만, 그 끝은 창대하리라

0개의 댓글