spring 2022/03/02(Sequence, item)

무간·2022년 3월 2일

spring 구동 순서

  1. 라이브러리 : pom.xml

  2. 환경설정 : resources/application.properties

  3. 컨트롤러, 서비스등의 컴포넌트 등록 : Boot20220228Application.java

  4. controller, service, view 구현


파일명 Sequence.java

package com.example.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

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

@Getter
@Setter
@NoArgsConstructor
@ToString

@Document(collection = "sequence")
public class Sequence {

    @Id // 필드이름 _id
    // @Field(name = "_id")
    private String seqName = null;

    @Field(name = "seq")
    private long seq = 0L;
    
}

파일명 SequenceService.java

package com.example.service;

import com.example.entity.Sequence;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

// 컨트롤러에서 사용 X
// 다른 service에서 시퀀스가 필요할때 사용할 용도
@Service
public class SequenceService {

    @Autowired
    private MongoTemplate mongoDB;

    public long generatedSequence(String seqName){

        // 조건은  _id가 seqName으로 전달되는 것을 찾음
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(seqName));

        // seq를 1증가 시킴
        Update update = new Update();
        update.inc("seq",1);

        // 옵션 반환과 1증가를 동시에 수행
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        options.upsert(true); // 없으면 insert, 있으면 update => upsert

        Sequence counter = mongoDB.findAndModify(query, update, options, Sequence.class);

        if(counter != null){
            return counter.getSeq();
        }
        return 1;        
    }   
}

파일명 Item.java

package com.example.entity;



import java.util.Date;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

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

@Getter
@Setter
@ToString
@NoArgsConstructor

@Document(collection = "item4")
public class Item {
    
    @Id
    private long code = 0L;

    // @Field(name = "itemname")
    private String name = null;

    // @Field(name = "itemprice")
    private long price = 0L;
    
    private long quantity = 0L;

    // import java.util    
    private Date regdate  = null;

    // byte 배열
    private byte[] filedata = null;
    private String filetype = null;
    private String filename = null;
    private long filesize = 0L;
    
}

파일명 insert.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>물품등록</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">

        <h3>item insert</h3>
        <hr />

        <form th:action="@{/item/insert}" method="post" enctype="multipart/form-data">            
            ** 물품코드, 등록일은 자동생성<br />
            <label style="width:95px; height: 30px; display:inline-block;">물품명 : </label>
            <input type="text" placeholder="물품명" name="name"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">가격 : </label>
            <input type="text" placeholder="가격" name="price"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">수량 : </label>
            <input type="text" placeholder="수량" name="quantity"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">대표 이미지 : </label>
            <input type="file" name="image" /><br />

            <label style="width:95px; height: 30px; display:inline-block;"></label>        
            <input type="submit" class="btn btn-primary" value="등록하기" />
        </form>
        
    </div>    
</body>
</html>

파일명 select.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>물품목록</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">
        <h3>item list</h3>
        <hr />

        <a th:href="@{/item/insert}">등록</a>
        <table class="table table-striped">
            <tr>
                <th>번호</th>
                <th>물품번호</th>
                <th>물품이름</th>
                <th>물품가격</th>
                <th>물품수량</th>
                <th>이미지</th>
                <th>버튼</th>
            </tr>

            <tr th:each="tmp, idx : ${list}">
                <td th:text="${idx.count}"></td>
                <td th:text="${tmp.code}"></td>
                <td th:text="${tmp.name}"></td>
                <td th:text="${tmp.price}"></td>
                <td th:text="${tmp.quantity}"></td>
                <td><img th:src="@{/item/image(code = ${tmp.code})}" style="width: 50px; height: 50px;" /></td>
                <td>
                    <a th:href="@{/item/update(code=${tmp.code})}" class="btn btn-primary" >수정</a>
                    <a th:href="@{/item/delete(code=${tmp.code})}" class="btn btn-primary" >삭제</a>
                </td>
            </tr>
        </table>

        <th:block th:each="i : ${#numbers.sequence(1, pages)}">
            <a th:href="@{/item/selectlist(page=${i})}" th:text="${i}"></a>
        </th:block>      

    </div>    
</body>
</html>

파일명 update.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>물품수정</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">
        

        <h3>item update</h3>
        <hr />

        <form th:action="@{/item/update}" method="post" enctype="multipart/form-data">

            <label style="width:95px; height: 30px; display:inline-block;">물품코드 : </label>
            <input type="text" th:value="${item.code}" name="code" readonly /></br>           
            
            <label style="width:95px; height: 30px; display:inline-block;">물품명 : </label>
            <input type="text" th:value="${item.name}" name="name"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">가격 : </label>
            <input type="text" th:value="${item.price}" name="price"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">수량 : </label>
            <input type="text" th:value="${item.quantity}" name="quantity"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">대표 이미지 : </label>
            <img th:src="@{/item/image(code = ${item.code})}" style="width: 50px; height: 50px;" />
            <input type="file" name="image" /><br />

            <label style="width:95px; height: 30px; display:inline-block;"></label>        
            <input type="submit" class="btn btn-primary" value="수정하기" />
            <a th:href="@{/item/selectlist}" class="btn btn-primary">목록으로</a>

        </form>
        
    </div>    
</body>
</html>

파일명 ItemController.java

package com.example.controller;

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

import com.example.entity.Item;
import com.example.service.ItemDB;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

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

    @Autowired
    public ItemDB itemDB;

    // resources/하위폴더의 파일을 읽기위한 객체생성
    // private ResourceLoader = new ResourceLoader();
    @Autowired
    private ResourceLoader resource;

    @PostMapping(value = "/update")
    public String updatePOST(
            @ModelAttribute Item item,
            @RequestParam(name="image")MultipartFile file) 
            throws IOException{
        if( !file.isEmpty() ) { // 첨부됨
            item.setFilename(file.getOriginalFilename());
            item.setFilesize(file.getSize());
            item.setFiletype(file.getContentType());
            item.setFiledata(file.getBytes());
        }

        int ret = itemDB.updateItemOne(item);
        if(ret == 1){
            return "redirect:/item/selectlist";
        }
        return "redirect:/item/update?code=" + item.getCode();
    }

    // 127.0.0.1:8080/item/update?code=2
    @GetMapping(value = "/update")
    public String updateGET(
            Model model,
            @RequestParam(name = "code")long code){
        // DB에서 1개의 정보 읽음
        Item item = itemDB.selectOneItem(code);
        // jsp로 전달
        model.addAttribute("item", item);
        // update.jsp 표시
        return "item/update";
    }

    // 127.0.0.1:8080/item/delete?code=2
    @GetMapping(value = {"delete"})
    public String deleteGET(@RequestParam(name="code") long code){
        int ret = itemDB.deleteItem(code);
        if(ret == 1 ){
            return "redirect:/item/selectlist";
        }
        return "redirect:/item/selectlist";
    }

    // 127.0.0.1:8080/item/image?code=2
    @GetMapping(value = "/image")
    public ResponseEntity<byte[]> imageGET(
        @RequestParam(name="code") long code){
        try {
            System.out.println(code);
            Item item = itemDB.selectOneItemImage(code);
            System.out.println(item.getFilesize());

            if(item.getFilesize() > 0 ){ //이미지가 있음
                HttpHeaders headers = new HttpHeaders();
                if(item.getFiletype().equals("image/jpeg")){
                    headers.setContentType(MediaType.IMAGE_JPEG);
                }
                else if(item.getFiletype().equals("image/png")){
                    headers.setContentType(MediaType.IMAGE_PNG);
                }
                else if(item.getFiletype().equals("image/gif")){
                    headers.setContentType(MediaType.IMAGE_GIF);
                }

                // 생성자(실재데잉터, headers, 200)
                ResponseEntity<byte[]> response = 
                    new ResponseEntity<byte[]>( item.getFiledata(), headers, HttpStatus.OK );

                return response;
            }
            else{// 이미지가 없는 경우
                InputStream stream = 
                    resource.getResource("classpath:/static/img/default.jpg").getInputStream();                

                HttpHeaders headers = new HttpHeaders();                
                headers.setContentType(MediaType.IMAGE_JPEG);
                
                ResponseEntity<byte[]> response = 
                    new ResponseEntity<byte[]>( stream.readAllBytes() , headers, HttpStatus.OK );

                return response;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }
    

    // 127.0.0.1:8080/item/selectlist
    // 127.0.0.1:8080/item/selectlist?page=1
    @RequestMapping(value = "/selectlist", method = RequestMethod.GET)
    // @GetMapping(value = {"/selectlist"})
    public String selectlistGET(Model model,
        @RequestParam(name = "page", defaultValue = "0") int page){

        if(page == 0 ){ // ?page=1을 추가하는 부분
            return "redirect:/item/selectlist?page=1";
        }

        // 1 페이지 => 0
        // 2 페이지 => 1
        // 1. 목록
        Pageable pageable = PageRequest.of(page-1, 10);
        List<Item> list = itemDB.selectListItem(pageable);

        // 2. 페이지네이션 개수
        long pages = itemDB.selectItemCount();
        
        // 목록
        model.addAttribute("list", list);
        // 10 => 1
        // 11 => 2
        // 21 => 3
        model.addAttribute("pages", (pages-1)/10+1);

        // item폴더의 select.jsp를 표시
        return "item/select";
    }

    // 127.0.0.1:8080/item/insert 
    @GetMapping(value = "/insert")
    public String insertGET(){

        // item폴더의 insert.jsp를 표시
        return "item/insert";
    }

    // 127.0.0.1:8080/item/insert
    @PostMapping(value = "/insert")
    public String insertPOST(
            @ModelAttribute Item item,
            @RequestParam(name = "image") MultipartFile file) 
            throws IOException {

        if(file.isEmpty() == false){ // 첨부됨
            item.setFilename(file.getOriginalFilename());
            item.setFilesize(file.getSize());
            item.setFiletype(file.getContentType());
            item.setFiledata(file.getBytes());
        }
        System.out.println(item.toString());
        int ret = itemDB.insertItem(item);
        if(ret == 1 ){
            return "redirect:/item/selectlist";
        }
        // GET으로 변경 127.0.0.1:8080/item/insert 
        return "redirect:/item/insert";
    }    
}

파일명 ItemDB.java

package com.example.service;

import java.util.List;

import com.example.entity.Item;

import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
public interface ItemDB {

    // 물품등록(추가할 물품정보가 처리 후에 int(-1, 0, 1)로 반환)
    public int insertItem (Item item);

    // 물품목록(페이지 정보 1, 2, 3...)
    public List<Item> selectListItem(Pageable page);
    
    // 이미지 정보 1개 조회
    public Item selectOneItemImage(long code);
    
    // 물품 1개 조회(이미지 제외)
    public Item selectOneItem(long code);

    // 물품 전체 개수 구하기 (페이지네이션의 페이지 표시용)
    public long selectItemCount();

    // 물품삭제
    public int deleteItem(long code);

    // 물품 수정
    public int updateItemOne(Item item);
}


파일명 ItemDBImpl.java

package com.example.service;

import java.util.Date;
import java.util.List;

import com.example.entity.Item;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

@Service
public class ItemDBImpl implements ItemDB{

    // DB연결객체
    @Autowired
    private MongoTemplate mongoDB;

    // 직접 만든 시퀀스용 서비스    
    // SequenceService sequence = new SequenceService //만들때 Autowired를 사용해서 사용 불가
    @Autowired
    private SequenceService sequence;
    

    @Override
    public int insertItem(Item item) {
        try {
            long seq = sequence.generatedSequence("SEQ_ITEM4_CODE");
            item.setCode(seq);
    
            // import java.util.Date
            Date date = new Date(); //현재시간 만들기
            item.setRegdate( date );
    
            Item item1 = mongoDB.insert(item);
            if(item1.getCode() == seq ){
                return 1;
            }
            return 0;
            
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }        
    }


    @Override
    public List<Item> selectListItem(Pageable pageable) {
        try {
            Query query = new Query();
            query.with(pageable); // skip().limit()
            query.fields().exclude("filedata", "filetype", "filesize", "filename"); //projection

            Sort sort = Sort.by(Direction.DESC,"_id");
            query.with(sort); // sort()
            
            return mongoDB.find(query, Item.class);
            
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }        
    }

    @Override
    public Item selectOneItemImage(long code) {
        try {
            // 조건 물품번호가 일치하는 것 1개 가져오기
            Query query = new Query();
            Criteria criteria = Criteria.where("_id").is(code);
            query.addCriteria(criteria);

            // projection
            query.fields().include("filedata", "filetype", "filesize");

            return mongoDB.findOne(query, Item.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Item selectOneItem(long code) {
        try {
            Query query = new Query();            
            query.addCriteria(Criteria.where("_id").is(code));
            return mongoDB.findOne(query, Item.class);
            
        } catch (Exception e) {
            e.printStackTrace();
            return null;            
        }
    }    

    @Override
    public long selectItemCount() {
        try {
            Query query = new Query();            
            return mongoDB.count(query, Item.class);
            
        } catch (Exception e) {
            e.printStackTrace();
            return -1;            
        }
    }

    @Override
    public int deleteItem(long code) {
        try {
            Query query = new Query();            
            query.addCriteria(Criteria.where("_id").is(code));
                        
            DeleteResult result = mongoDB.remove(query, Item.class);
            if(result.getDeletedCount() == 1L){
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;            
        }        
    }


    @Override
    public int updateItemOne(Item item) {
        try {
            Query query = new Query(); 
            query.addCriteria(Criteria.where("_id").is(item.getCode()));

            Update update = new Update();
            update.set("name",item.getName());
            update.set("price",item.getPrice());
            update.set("quantity",item.getQuantity());
            if(item.getFilesize() > 0){
                update.set("Filedata", item.getFiledata());
                update.set("Filesize", item.getFilesize());
                update.set("Filetype", item.getFiletype());
                update.set("Filename", item.getFilename());
            }

            UpdateResult result  = mongoDB.updateFirst(query, update, Item.class);
            if(result.getModifiedCount() == 1L){
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }   
}

profile
당신을 한 줄로 소개해보세요

0개의 댓글