IT 프로젝트/블로그 만들기

[Spring Boot] 스프링 부트 프로젝트/블로그 만들기 - 관리자(admin) 카테고리(category) 페이지 만들기

happygram 2018. 11. 19. 21:00

관리자 페이지 기능 중 '카테고리' 관리하는 페이지를 작성합니다.


기능 목록


  • 카테고리 추가/변경/조회


소스

category.html


<th:block th:include="admin/category-js"></th:block>
<h3>카테고리 <small>카테고리를 관리합니다.</small></h3>
<div class="box box-primary">
    <div class="box-header with-border">
        <h3 class="box-title">입력</h3>
    </div>
    <!-- /.box-header -->
    <!-- form start -->
    <form role="form" th:action="@{/category}" method="post">
        <div class="box-body">
            <div class="form-group">
                <label for="nm">식별자</label>
                 <input type="text" class="form-control" id="nm" name="nm" placeholder="식별 가능한 이름입니다." required>
            </div>
            <div class="form-group">
                <label for="labelNm">이름</label>
                <input type="text" class="form-control" id="labelNm" name="labelNm" placeholder="실제 보이는 이름입니다." required>
            </div>
            <div class="form-group">
                <label for="orderNo">순서</label>
                <input type="number" min="1" max="10000" class="form-control" id="orderNo" name="orderNo" placeholder="순서를 입력하세요." required>
            </div>
            <input type="submit" class="btn btn-primary" value="저장"/>
        </div>
        <!-- /.box-body -->
    </form>
</div>
 
<div class="box box-primary">
    <div class="box-header with-border">
        <h3 class="box-title">목록</h3>
    </div>
    <div class="content">
        <table id="category_table" class="table table-striped table-bordered" style="width: 100%">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Label Name</th>
                    <th>Order No</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
    </div>
</div>
 
cs

'template/admin' 경로에 'category.html' 페이지를 추가합니다.


    <!-- form start -->
    <form role="form" th:action="@{/category}" method="post">
        <div class="box-body">
            <div class="form-group">
                <label for="nm">식별자</label>
                 <input type="text" class="form-control" id="nm" name="nm" placeholder="식별 가능한 이름입니다." required>
            </div>
            <div class="form-group">
                <label for="labelNm">이름</label>
                <input type="text" class="form-control" id="labelNm" name="labelNm" placeholder="실제 보이는 이름입니다." required>
            </div>
            <div class="form-group">
                <label for="orderNo">순서</label>
                <input type="number" min="1" max="10000" class="form-control" id="orderNo" name="orderNo" placeholder="순서를 입력하세요." required>
            </div>
            <input type="submit" class="btn btn-primary" value="저장"/>
        </div>
        <!-- /.box-body -->
    </form>
cs


식별자, 이름, 순서를 입력하고 '저장' 버튼을 누르면 'POST' 형식으로 서버에 요청하여 카테고리가 데이터베이스에 저장됩니다.


        <table id="category_table" class="table table-striped table-bordered" style="width: 100%">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Label Name</th>
                    <th>Order No</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>

카테고리를 조회하기 위한 테이블입니다.

스크립트에서 'DataTable' 라이브러리를 사용할 것 입니다.


category-js.html


<script th:inline="javascript">
$(function(){
    // Ajax call for category
    $.ajax({
        method : 'GET',
        url: BASE_CONTEXT_PATH + 'category',
    }).done(function(result){
        // Category tables
        $('#category_table').DataTable({
            data : result,
            columns: [
                { data: 'nm' },
                { data: 'labelNm' },
                { data: 'orderNo' }
            ]
        });
    }).fail(function(xhr, ajaxOptions, thrownError){
        alert(xhr);
    });
});
</script>
cs

'DataTable' 을 이용하여 조회를 합니다.

'DataTable' 은 Javascript 라이브러리로 테이블에 유용한 기능을 제공합니다.

(페이징 처리, 검색, 컬럼 정렬 등)


DataTable 참조 사이트


CategoryController.java
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.ResponseBody;
import org.springframework.web.servlet.view.RedirectView;

import project.blog.dto.CategoryDto;
import project.blog.service.CategoryService;

@Controller
@RequestMapping("/category")
public class CategoryController {

	@Autowired
	private CategoryService categoryService;

	@GetMapping
	public @ResponseBody List<CategoryDto> getCategories() {
		return categoryService.getCategories();
	}
	
	@PostMapping
	public RedirectView newCategories(@ModelAttribute CategoryDto categoryDto) {
		categoryService.newCategories(categoryDto);
		return new RedirectView("/admin/category");
	}
}

카테고리 서비스를 호출하여, '카테고리 목록', '카테고리 등록' 을 처리합니다.


소스 설명

	@GetMapping
	public @ResponseBody List<CategoryDto> getCategories() {
		return categoryService.getCategories();
	}

서비스를 이용하여 카테고리 목록을 가져옵니다.


	@PostMapping
	public RedirectView newCategories(@ModelAttribute CategoryDto categoryDto) {
		categoryService.newCategories(categoryDto);
		return new RedirectView("/admin/category");
	}

서비스를 이용하여 카테고리를 등록합니다.

등록 후 카테고리 메인 페이지로 이동합니다.


CategoryService.java
import java.util.List;
import java.util.stream.Collectors;

import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import project.blog.dto.CategoryDto;
import project.blog.repository.CategoryRepository;

@Service
public class CategoryService {
	
	@Autowired
	private CategoryRepository categoryRepository;
	
	@Autowired
	private ModelMapper modelMapper;
	
	public List<CategoryDto> getCategories(){
		return categoryRepository.findAll().stream().map(category -> modelMapper.map(category, CategoryDto.class)).collect(Collectors.toList());
	}
	
	public CategoryDto newCategories(CategoryDto categoryDto) {
		return modelMapper.map(categoryRepository.save(categoryDto.toEntity()), CategoryDto.class);
	}
	
	public String getCategoryLabelNm(String nm) {
		return categoryRepository.findByNm(nm).getLabelNm();
	}
}

카테고리에서 필요한 처리를 Repository 를 통해서 처리하고 있습니다.

실제 데이터 접근은 Repository 에서 합니다.


소스 설명

	public List<CategoryDto> getCategories(){
		return categoryRepository.findAll().stream().map(category -> modelMapper.map(category, CategoryDto.class)).collect(Collectors.toList());
	}

Repository 를 통해서 카테고리 목록을 가져오고, domain 을 DTO 로 변환하여 결과를 변환합니다.

lambda 식을 이용하여 간결하게 표현 하였습니다.


	public CategoryDto newCategories(CategoryDto categoryDto) {
		return modelMapper.map(categoryRepository.save(categoryDto.toEntity()), CategoryDto.class);
	}

Repository 에 domain 을 전달 해야 하므로, DTO 의 toEntity() 메소드를 호출하여 처리합니다.


	public String getCategoryLabelNm(String nm) {
		return categoryRepository.findByNm(nm).getLabelNm();
	}

Repository 에서 JPA 표준에 맞게 만들어둔 메소드를 처리합니다.


CategoryRepository.java
import org.springframework.data.jpa.repository.JpaRepository;

import project.blog.domain.Category;

public interface CategoryRepository extends JpaRepository<Category, String> {
	Category findByNm(String nm);
}

JpaRepository 를 상속 받아서 이용하고, 이름으로 카테고리를 조회 하기 위해서 JPA 표준에 맞게 메소드를 정의 하였습니다.


CategoryDto.java
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import project.blog.domain.Category;

@Getter
@Setter
@NoArgsConstructor
public class CategoryDto {
	private String nm;
	private String labelNm; 
	private int orderNo;
	
	public Category toEntity(){
        return Category.builder()
        		.nm(nm)
        		.labelNm(labelNm)
        		.orderNo(orderNo)
                .build();
    }
}

서비스에서 DTO 를 사용하여 Controller 와 통신합니다.


Category.java
import javax.persistence.Entity;
import javax.persistence.Id;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Category {
	@Id
    private String nm;
    private String labelNm;
    private int orderNo;
    
    @Builder
    public Category(String nm, String labelNm, int orderNo) {
    	this.nm = nm;
    	this.labelNm = labelNm;
    	this.orderNo = orderNo;
    }
}

테이블과 직접 매핑하는 domain 클래스를 생성 합니다.


결과




참조 라이브러리 사이트 목록 - 도움에 감사를 드립니다.

https://datatables.net/