스프링

 

사용버전 

스프링부트 버전 :  2.7.0  - mybatis 

 

A 방법

 

1. Board 테이블 

CREATE TABLE t_board(
    `board_seq` int auto_increment primary key COMMENT 't_board 테이블 pk', 
    `board_type` varchar(255) COMMENT '게시판 종류', 
    `title` varchar(255) COMMENT '제목', 
    `contents` text  COMMENT '내용',
    `reg_date` timestamp NOT null default current_timestamp() COMMENT '등록일'
)ENGINE=InnoDB  DEFAULT CHARSET=utf8;

 

boardType.code  아니라  boardType  의 값으로 설정한다.

 

  <insert id="save" parameterType="kr.so.songjava.mvc.domain.dto.BoardDTO" useGeneratedKeys="true"  keyProperty="boardSeq">
  INSERT INTO T_BOARD  (BOARD_TYPE, TITLE, CONTENTS, REG_DATE )
  
  VALUES(#{boardType}, #{title}, #{contents}, NOW())
  </insert>


  <update id="update" parameterType="kr.so.songjava.mvc.domain.dto.BoardDTO">
  	UPDATE T_BOARD
  		SET
  			BOARD_TYPE=#{boardType},
  			TITLE=#{title},
  			CONTENTS =#{contents}
  	WHERE BOARD_SEQ =#{boardSeq}		
  </update>
  

 

 

2. BaseCodeLabelEnum, BoardType enum class 생성

 

BaseCodeLabelEnum

/**
 * 	기본 CodeLabelEnum 
 */
public interface BaseCodeLabelEnum {

	/** 코드를 리턴 */
	String code();

	/** 라베를  리턴 */
	String label();
	
	
}

 

BoardType

import lombok.AllArgsConstructor;
import lombok.Getter;

/**게시판 종류*/
public enum BoardType implements BaseCodeLabelEnum{

	NOTICE("공지사항"),
	FAQ("자주묻는질문"),
	INQUIRY("1:1문의"),
	;
	
	private String code;
	private String label;
	
	BoardType(String label) {
		this.code=name();
		this.label=label;
	}
	
	
	@Override
	public String code() {
		return code;
	}

	@Override
	public String label() {
		return label;
	}

	
	
}

 

 

3. BoardDTO boardType 변수 추가

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class BoardDTO {
	
	private int boardSeq;
	private BoardType boardType;
	private String title;
	private String contents;
		
}

 

 

4. Board boardType 변수 추가

import java.util.Date;

import kr.so.songjava.mvc.domain.enums.BoardType;
import lombok.Data;

@Data
public class Board {
	
	private int boardSeq;
	private BoardType boardType;
	private String title;
	private String contents;
	private Date regDate;
}

  

 

 

5. BaseCodeLabelEnumJsonSerializer 클래스 추가

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.http.MediaType;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;

import kr.so.songjava.mvc.domain.enums.BaseCodeLabelEnum;

/**
 *JSON 변환시 BaseCodeLabelEnum 클래스에 대한 변환을 동일하게 처리
 */
public class BaseCodeLabelEnumJsonSerializer  extends JsonSerializer<BaseCodeLabelEnum>{

	
	@Override
	public void serialize(BaseCodeLabelEnum value, JsonGenerator jsonGenerator, SerializerProvider serializers)
			throws IOException , JsonProcessingException {
		Map<String, Object> map=new HashMap<>();
		map.put("code", value.code());
		map.put("label", value.label());
		jsonGenerator.writeObject(map);
	}

	
	
}

 


6. WebMvcConfig ObjectMapper, MappingJackson2JsonView Bean 등록

	@Bean
	public ObjectMapper objectMapper() {
		ObjectMapper objectMapper =new ObjectMapper();
		SimpleModule simpleModule =new SimpleModule();
		simpleModule.addSerializer(BaseCodeLabelEnum.class, new BaseCodeLabelEnumJsonSerializer());
		objectMapper.registerModule(simpleModule);
		return objectMapper;
	}
	
	
	
	@Bean
	public MappingJackson2JsonView mappingJackson2JsonView() {
		MappingJackson2JsonView jsonView=new MappingJackson2JsonView();
		jsonView.setContentType(MediaType.APPLICATION_JSON_VALUE);
		jsonView.setObjectMapper(objectMapper());
		return jsonView;		
	}
	

 

 

출력값 :

{
  "code": "SUCCESS",
  "message": null,
  "data": [
    {
      "boardSeq": 1,
      "boardType": {
        "code": "NOTICE",
        "label": "공지사항"
      },
      "title": "spring",
      "contents": null,
      "regDate": "2022-06-25T17:53:52.000+00:00"
    }
  ]
}

 

 

 

====================================>====================================>====================================>=======

B 방법

BaseCodeLabelEnum 인터페이스 사용없이, 그리고

5~6번의 BaseCodeLabelEnumJsonSerializer 과 WebMvcConfig 에 빈 등록없이도 간단하게 

다음과  같이 어노테이션 추가로  json  형식으로 목록을 불러 올수 있다.

그러나 등록/ 수정시 파라미터 객체 와 불러오기 시 객체를 다르게 설정해야 한다.

 

 Enum 객체 전체 리턴

@JsonFormat(shape = Shape.OBJECT)

@AllArgsConstructor

@Getter

 

1.  유형  - 등록 및 수정시   BoardTypeInsert  , BoardInsertDTO    를 사용

 

BaseCodeLabelEnum

 

a) BoardTypeInsert

/**게시판 등록/수정시 파라미터 enum*/
public enum BoardTypeInsert {
 
    NOTICE("공지사항"),
    FAQ("자주묻는질문"),
    INQUIRY("1:1문의"),
    ;
     
    private String code;
    private String label;
     
    BoardTypeInsert(String label) {
        this.code=name();
        this.label=label;
    }
     
         
}

 

b) BoardInsertDTO

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/** 등록/수정시 파라미터 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class BoardInsertDTO {
	
	private int boardSeq;
	private BoardTypeInsert boardType;
	private String title;	
	private String contents;
	private String keyword;
		
}

 

swagger

 

 

 

 

2. 유형 - 목록 불러올시  JSON 객체 포맷  (BoardType, BoardDTO, BoardSearchParameter)

BoardType

 

/**게시판 종류*/
@JsonFormat(shape = Shape.OBJECT) // 추가
@AllArgsConstructor
@Getter
public enum BoardType {
 
    NOTICE("NOTICE", "공지사항"),
    FAQ("FAQ" ,"자주묻는질문"),
    INQUIRY("INQUIRY" ,"1:1문의")
    ;
         
    //@JsonValue // 한개의 데이터만 가져올경우 @JsonFormat 제거후 해당 변수에 @JsonValue 어노테이션 추가
    private String code;
    private String label;
         
}

 

BoardDTO

/** 데이터를 가져올시 파라미터 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class BoardDTO {
	
	private int boardSeq;
	private BoardType boardType;
	private String title;	
	private String contents;
	private String keyword;
		
}

 

==============================================================================================================================

3. 사용예

검색 처리 파라미터

파라미터 입력이 필요한 경우 1번 유형  BoardTypeInsert  를 사용하고,  반환 처리는 JSON 형식의 전환이 필요하므로 2번 유형을 사용한다.

 

BoardSearchParameter

@Data
public class BoardSearchParameter {	
	private String keyword;
	private List<BoardTypeInsert> boardTypes;  //배열로 다중 검색 처리를 위해 , NOTICE, FAQ,INQUIRY	
}

 

컨트롤 사용 예

 

BoardApiController
    

	/** 1.게시판 검색처리목록리턴 페이징 처리 x */
	@GetMapping({"","/"})
	@ApiOperation(value="목록조회", notes="1.게시판 검색처리목록리턴 페이징 처리 x")
	public BaseResponse<List<BoardDTO>> getList(@ApiParam BoardSearchParameter boardSearchParameter) throws Exception{
		return new BaseResponse<List<BoardDTO>>(boardService.getList(boardSearchParameter));
	}
	
	
	/**2.게시판 페이징 검색처리 목록리턴  - 페이징 검색처리 첫번째 방법 (WebMvcConfig 에 페이지 리졸버 등록 방식) */
	@GetMapping({"/pageSearchList"})
	@ApiOperation(value="목록조회 - WebMvcConfig 에 페이지 리졸버 등록 방식", notes="2.게시판 페이징 검색처리 목록리턴 ")
	public BaseResponse<List<BoardDTO>> paginationSearchList(
			@ApiParam  MySQLPageRequest pageRequest,
			@ApiParam  BoardSearchParameter parameter
			) throws Exception{
		log.info("1.pageRequest :" , pageRequest);
		PageRequestParameter<BoardSearchParameter> pageRequestParameter=new PageRequestParameter<BoardSearchParameter>(pageRequest, parameter);
		log.info("2.pageRequestParameter :" , pageRequestParameter);
		return new BaseResponse<List<BoardDTO>>(boardService.paginationSearchList(pageRequestParameter));
	}

	
	
	/** 3. 게시판 페이징 검색처리 목록리턴 - 페이징 검색처리 두번째방법 (전체 갯수 구함) */
	@GetMapping({"/pageSearchList2"})
	@ApiOperation(value="목록조회 - MysqlPageMaker 사용 ", notes="3.게시판 페이징 검색처리 목록리턴 ")
	public BaseResponse<List<BoardDTO>> paginationSearchList2(
			@ApiParam  MysqlPageMaker pageMaker
			) throws Exception{
		
		int totalCount =boardService.getTotalCount(pageMaker);
		pageMaker.setTotalCount(totalCount);
		
		log.info("1.pageMaker :  {} " , pageMaker);
		log.info("2.totalCount :  {}" , totalCount);		
		return new BaseResponse<List<BoardDTO>>(boardService.paginationSearchList2(pageMaker), pageMaker);
	}
	


 

 

mybatis  에서 boardTypes 으로 사용  

 <select id="getList" 	resultType="kr.so.songjava.mvc.domain.entity.Board">
    SELECT
    	 B.BOARD_SEQ,
    	 B.BOARD_TYPE,
    	 B.TITLE,
    	 B.REG_DATE    	 
   FROM T_BOARD B 
   <where>
   	 <if test="@org.apache.commons.lang3.StringUtils@isNotEmpty(keyword)">
   	 	AND B.TITLE LIKE CONCAT('%',  #{keyword}, '%')
   	 </if>
   	 
   	 <if test="@org.apache.commons.lang3.ObjectUtils@isNotEmpty(boardTypes)">
   	 	AND B.BOARD_TYPE IN (
   	 		<foreach collection="boardTypes" item="value" separator=",">
   	 			#{value}
   	 		</foreach>
   	 	)
   	 </if>   	 
   </where>   
   ORDER BY B.REG_DATE DESC     	
  </select>

 

 

 

검색 참조 :

스프링부트 검색 조건 추가 Mybatis Commons-Lang3 라이브러리 IsNotEmpty 사용으로 검색 

 

 

 

 

=>출력 형식 예

{
  "code": "SUCCESS",
  "message": null,
  "data": [
    {
      "boardSeq": 1,
      "boardType": {
        "code": "NOTICE",
        "label": "공지사항"
      },
      "title": "spring",
      "contents": null,
      "regDate": "2022-06-25T17:53:52.000+00:00"
    }
  ]
}

페이징 처리 파라미터 추가

{
  "code": "SUCCESS",
  "message": null,
  "pageMaker": {
    "page": 1,
    "perPageNum": 10,
    "pageStart": 0,
    "totalCount": 1001,
    "startPage": 1,
    "endPage": 6,
    "prev": false,
    "next": true,
    "displayPageNum": 6,
    "tempEndPage": 101,
    "searchType": null,
    "keyword": null
  },
  "displayPageNum": 0,
  "data": [
    {
      "boardSeq": 256,
      "boardType": {
        "code": "FAQ",
        "label": "자주묻는질문"
      },
      "title": "wJmTCEydrm",
      "contents": null,
      "regDate": "2022-06-26T03:38:59.000+00:00"
    },
    {
      "boardSeq": 512,
      "boardType": {
        "code": "FAQ",
        "label": "자주묻는질문"
      },
      "title": "JQvHGGREkU",
      "contents": null,
      "regDate": "2022-06-26T03:38:59.000+00:00"
    },
    {
      "boardSeq": 768,
      "boardType": {
        "code": "FAQ",
        "label": "자주묻는질문"
      },
      "title": "fPwypLLrpP",
      "contents": null,
      "regDate": "2022-06-26T03:38:59.000+00:00"
    }
  ]
}

 

 

 

* @JsonValue  사용할 경우 경우

 

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonValue;

import lombok.AllArgsConstructor;
import lombok.Getter;


/**게시판 종류*/
//@JsonFormat(shape = Shape.OBJECT) // 추가
@AllArgsConstructor
@Getter
public enum BoardType {

    NOTICE("NOTICE", "공지사항"),
    FAQ("FAQ" ,"자주묻는질문"),
    INQUIRY("INQUIRY" ,"1:1문의")
    ;
        
    @JsonValue // 추가
    private String code;
    private String label;
        
}

 

=>출력 형식  예

{
  "code": "SUCCESS",
  "message": null,
  "pageMaker": {
    "page": 1,
    "perPageNum": 10,
    "pageStart": 0,
    "totalCount": 1001,
    "startPage": 1,
    "endPage": 6,
    "prev": false,
    "next": true,
    "displayPageNum": 6,
    "tempEndPage": 101,
    "searchType": null,
    "keyword": null
  },
  "displayPageNum": 0,
  "data": [
    {
      "boardSeq": 256,
      "boardType": "FAQ",
      "title": "wJmTCEydrm",
      "contents": null,
      "regDate": "2022-06-26T03:38:59.000+00:00"
    },
    {
      "boardSeq": 512,
      "boardType": "FAQ",
      "title": "JQvHGGREkU",
      "contents": null,
      "regDate": "2022-06-26T03:38:59.000+00:00"
    }

  ]
}

 

 

 

 

 

 

 

 

 

 

 

C 방법

1. ResponseEntity  사용

2. Map<String, Object>   LinkedHashMap 사용 


3. ObjectMapper 객체를 담은 후 반환

 

코드양이  늘어는 것 같아 보이지만, 다른 클래스에 추가 설정도 없고,

 반환처리 DTO 및 입력 처리 등 기타 특별한 클래스를들을 만들어 줄 필요도 없고,

json 반화처리에서  제외할 멤버 변수 에 @JsonIgnore 어노테이션만 붙여주면 된다.

	@JsonIgnore
	@ApiModelProperty(hidden=true)
    private int pageStart;
     
    /** 하단 페이징  << 1 2 3 4 5 6 7 8 9 10 >>  */
	@JsonIgnore
	@ApiModelProperty(hidden=true)
    private int totalCount; //전체 개수

 

또한 필요한 객체를  map 으로 넣고 빼기가  쉽다.  

개발자들마다 처리방식들이 다양해서 A , B, C  등 다른 여러 방법들이 많이  있는 것 같은데, 

개인적인 생각으로는   쉽게 접근할 수 있는  방법 같아서 나는 C 방법을 사용한다. 

 

 

 

/** 1-2 . ObjectMapper 와 @ResponseBody 를 통한 게시판 검색처리목록리턴 페이징 처리 x */
	@GetMapping("/om/list1")
	@ApiOperation(value="ObjectMapper 목록조회 1", notes="2.게시판 검색처리목록리턴 페이징 처리 x")
	@ResponseBody
	public String getObjectMaperJsonList1(@ApiParam BoardSearchParameter boardSearchParameter) throws Exception{
		List<BoardDTO>  boardList =boardService.getList(boardSearchParameter);	
		ObjectMapper objectMapper=new ObjectMapper();
		String json=objectMapper.writeValueAsString(boardList);
		return json;
	}
	
	/** 1-3 . ObjectMapper 와 @ResponseBody 를 통한 게시판 검색처리목록리턴 페이징 처리 x */
	@GetMapping("/om/list2")
	@ApiOperation(value="ObjectMapper 목록조회 1", notes="3.게시판 검색처리목록리턴 페이징 처리 x")
	@ResponseBody
	public ResponseEntity<?> getObjectMaperJsonList2(@ApiParam BoardSearchParameter boardSearchParameter) throws Exception{
		
		List<BoardDTO>  boardList =boardService.getList(boardSearchParameter);	
		ObjectMapper objectMapper=new ObjectMapper();
		String json=objectMapper.writeValueAsString(boardList);
		
		return ResponseEntity.status(HttpStatus.OK).body(json);		
	}
	
	
	/** 
	 * ★★★★★★ 
	 * 1. ResponseEntity<?> 사용
	 * 2. Map<String, Object> 사용
	 * 3. ObjectMapper 객체를 담은 후 반환
	 * 
	 *
	 * 1-3 . ObjectMapper 와 @ResponseBody 를 통한 게시판 검색처리목록리턴 페이징 처리 x */
	@GetMapping("/om/list3")
	@ApiOperation(value="ObjectMapper 목록조회 3", notes="4.게시판 검색처리목록리턴 페이징 처리 x")
	@ResponseBody
	public ResponseEntity<?> getObjectMaperJsonList3(@ApiParam BoardSearchParameter boardSearchParameter) throws Exception{
		//1.map 객체 생성  - LinkedHashMap 입력순으로 출력 
		Map<String, Object> map=new LinkedHashMap<>();
	
		//2.json 반환 처리할 데이터 가져오기
		List<BoardDTO>  boardList =boardService.getList(boardSearchParameter);	
		
		//3. map 에 넣게
		map.put("code", BaseResponseCode.SUCCESS);
		map.put("boardList", boardList);		
		
		//4. objectMapper 로 json 전환처리
		ObjectMapper objectMapper=new ObjectMapper();
		String json=objectMapper.writeValueAsString(map);
		
		
		//5. ResponseEntity 로 json 반환
		return ResponseEntity.status(HttpStatus.OK).body(json);		
	}	


	/** 3-1
	 * 
	 * . 게시판 페이징 검색처리 목록리턴 - 페이징 검색처리 두번째방법 (전체 갯수 구함)
	 *   * ★★★★★★ 
	 * 1. ResponseEntity<?> 사용
	 * 2. Map<String, Object> 사용
	 * 3. ObjectMapper 객체를 담은 후 반환
	 * 
		http://localhost:8080/api/board/pageSearchList2?page=2&searchType=INQUIRY
	 */
	@GetMapping("/om/list/pagination")
	@ApiOperation(value="목록조회 - MysqlPageMaker 사용 ObjectMapper ", notes=""
			+ "1. ResponseEntity<?> 사용"
			+ "2. Map<String, Object> 사용"
			+ "3. ObjectMapper 객체를 담은 후 반환")
	public ResponseEntity<?> omPagination(
			@ApiParam MysqlPageMaker pageMaker
			) throws Exception{
		//1.map 객체 생성  - LinkedHashMap 입력순으로 출력 
		Map<String, Object> map=new LinkedHashMap<>();
				
		//2.json 반환 처리할 데이터 가져오기
		int totalCount =boardService.getTotalCount(pageMaker);
		pageMaker.setTotalCount(totalCount);		
		List<BoardDTO> boardList=boardService.paginationSearchList2(pageMaker);		
		
		//3. map 에 넣게
		map.put("code", BaseResponseCode.SUCCESS);
		map.put("pageMaker", pageMaker);
		map.put("data", boardList);			
		
		//4. objectMapper 로 json 전환처리
		ObjectMapper objectMapper=new ObjectMapper();
		String json=objectMapper.writeValueAsString(map);
		
		//5. ResponseEntity 로 json 반환
		return ResponseEntity.status(HttpStatus.OK).body(json);
	}

	





    /** 3-2 코드 간소화
     * 
     * . 게시판 페이징 검색처리 목록리턴 - 페이징 검색처리 두번째방법 (전체 갯수 구함)
     *   * ★★★★★★ 
     * 1. ResponseEntity<?> 사용
     * 2. Map<String, Object> 사용
     * 3. ObjectMapper 객체를 담은 후 반환
     * 
        http://localhost:8080/api/board/om/list/pagination?page=2&searchType=INQUIRY
     */
    @GetMapping("/om/list/pagination2")
    @ApiOperation(value="코드 간소화 목록조회 - MysqlPageMaker 사용 ObjectMapper ", notes=""
            + "1. ResponseEntity<?> 사용"
            + "2. Map<String, Object> 사용"
            + "3. ObjectMapper 객체를 담은 후 반환")
    public ResponseEntity<?> omPagination2(@ApiParam MysqlPageMaker pageMaker) throws Exception{

        //1.map 객체 생성  - LinkedHashMap 입력순으로 출력 
        Map<String, Object> map=new LinkedHashMap<>();
                
        //2.전체 갯수 구하기
        pageMaker.setTotalCount(boardService.getTotalCount(pageMaker));        
        
        //3. map 에 넣게
        map.put("code", BaseResponseCode.SUCCESS);
        map.put("pageMaker", pageMaker);
        map.put("data", boardService.paginationSearchList2(pageMaker));            
        
        //4. objectMapper 로 json 전환처리 후 ResponseEntity 로 json 반환    
        return ResponseEntity.status(HttpStatus.OK).body(new ObjectMapper().writeValueAsString(map));
    }








	

 

 

추가적으로  프론트에서 페이징 처리는 다음과 같은 css, 자바스트립트 참초

css

ul#pagingul {
	text-align: center;
	display: inline-block;
	border: 1px solid #ccc;
	border-right: 0;
	padding-left: 0rem;
}

ul#pagingul li {
	text-align: center;
	float: left;
	list-style: none;
	 outline: none;	
}

ul#pagingul li a {
	display: block;
	font-size: 14px;
	padding: 9px 12px;
	border-right: solid 1px #ccc;
	box-sizing: border-box;
	color: #000;
	text-decoration: none;
	 outline: none;	
}

ul#pagingul li.on {
	background: #000;
}

ul#pagingul li.on a {
	color: #fff;
	 outline: none;	
}

 

js

  // 페이징 표시 함수 
     //function(totalData, dataPerPage, pageCount, currentPage)
    paging: function(){
       // console.log("currentPage : " + currentPage);
 
        totalPage = Math.ceil(totalData / dataPerPage); //총 페이지 수
 
        if (totalPage < pageCount) {
            pageCount = totalPage;
        }
 
        let pageGroup = Math.ceil(currentPage / pageCount); // 페이지 그룹
        let last = pageGroup * pageCount; //화면에 보여질 마지막 페이지 번호
 
        if (last > totalPage) {
            last = totalPage;
        }
 
        let first = last - (pageCount - 1); //화면에 보여질 첫번째 페이지 번호
        let next = last + 1;
        let prev = first - 1;
 
        let pageHtml = "";
 
        if (prev > 0) {
            pageHtml += "<li><a href='#' id='prev'> « </a></li>";
        }
 
        //페이징 번호 표시 
        for (var i = first; i <= last; i++) {
 
            if (currentPage == i) {
                pageHtml +=
                    "<li class='on'><a href='#' id='" + i + "'>" + i + "</a></li>";
            } else {
                pageHtml += "<li><a href='#' id='" + i + "'>" + i + "</a></li>";
            }
        }
 
 
        if (last < totalPage) {
            pageHtml += "<li><a href='#' id='next'> » </a></li>";
        }
 
 		
	
        document.querySelector("#pagingul").innerHTML = pageHtml;
 
       // let displayCount = "";
       // displayCount = "현재 1 - " + totalPage + " (" + currentPage + "페이지) / " + totalData + "건";
       // document.querySelector("#displayCount").innerText = displayCount;
 
 
        //페이징 번호 클릭 이벤트 
        const paginationClass = document.querySelectorAll("#pagingul li a");
        for (let i = 0; i < paginationClass.length; i++) {
            paginationClass[i].addEventListener("click", function(e) {
                e.preventDefault();
 
                let $id = this.getAttribute("id")
                selectedPage = this.innerText;
 
                console.log("선택한 페이지 ", selectedPage);
                if ($id == "next") selectedPage = next;
                if ($id == "prev") selectedPage = prev;
                comment.list(selectedPage);
            });
        }
 
    },

 

 

 

전체 샘플 코드 예

let totalData; //총 데이터 수
let dataPerPage; //한 페이지에 나타낼 글 수
let pageCount; //페이징 개수
let currentPage; //현재 페이지
let comment = {
     
    init: function() {  
        //this.list();  

		$("#commentAdd").on("click", function(e){
				comment.commentAdd();			
		});
	
	
		$(".comment-delete").on("click", function(e){
			comment.commentDelete(e.target);			
		});
		
		$("#flexSwitchCheckChecked").on("click", function(e){
			$("#comment-add-list").toggle();
			$("#pagingul").toggle();
			
		});
		  
    },
 
    list: function(page) {
        if (page == undefined || page == "") {
            page = 1;
        }
 		const data= {
			'nttId':$("#nttId").val(),
			'page': ""+page,
			'subPageIndex':page
		}
 		//console.log(data);
	
	
		$.ajax({
			url:'/portal/comment/selectArticleCommentList.do',
			type:'post',
			contentType:'application/json;charset=UTF-8',
			data:JSON.stringify(data),
			dataType:"json",
			success:function(res){
				 console.log(res);
	            totalData = res.resultCnt;
	            dataPerPage = res.paginationInfo.recordCountPerPage;
	            pageCount = res.paginationInfo.totalPageCount;
	            currentPage = res.paginationInfo.currentPageNo;
	 				
				//{item.wrterId}
				//console.log(totalData);
				//console.log(dataPerPage);
				//console.log(pageCount);
				//console.log(currentPage);
				const LoginUniqId=$("#LoginUniqId").val();
				
					$("#totalData").text('댓글('+totalData+")");	
			
		            if (res.resState=="success") {
		                let html = "";
		                res.resultList.forEach(function(item) {
			
		 html +=`
						<div class="col-md-12 mb-2" >
                    <div class="card p-3 ">
                        <div class="d-flex justify-content-between align-items-left">
                      <div class="user d-flex flex-row align-items-left">
                        <span><small class="font-weight-bold  comment-user"><b style="color:#000">${item.frstRegisterNm}</b></small> 
                            <small class="font-weight-bold comment-text" id="comment-text-${item.commentNo}" >${item.commentCn}</small>	
                        </span>                          
                      </div>

                      <small>${item.frstRegisterPnttm}</small>
                      </div>


					<div id="update-comment-textarea-${item.commentNo}" class="mt-3" style="display:none;">
						<textarea class="form-control update-comment-textarea" data-id="updateComment-${item.commentNo}"  onkeyup="fn_checkByte(this)" >${item.commentCn}</textarea>
						 <sup class="supComment-left" id="sup-updateComment-${item.commentNo}"></sup>
					</div>
		`;
		
		
		var  html2 =`
		
                      <div class="action mt-2 " style="text-align:right" >                                              
						  <div class="reply px-4" style="display:inherit">	                  
                      
						 <div class="icons align-items-center comment-btn" 
					 id="commentUpdateFormBtn-${item.commentNo}"   data-id='${item.commentNo}'   onclick="comment.commentUpdateForm(this)">
                            <i class="fa fa-trash text-default"></i>
                            수정                    
                        </div> 
 
                       <div class="icons align-items-center  comment-btn"  style="display:none;" id="commentUpdateBtn-${item.commentNo}"  data-id='${item.commentNo}' onclick="comment.commentUpdate(this)">
                            <i class="fa fa-trash text-default success"></i>
                            수정 하기                  
                        </div> 
  
                       <div class="icons align-items-center comment-btn comment-delete" style=" margin-left: 10px;"	
						 data-id='${item.commentNo}'   onclick="comment.commentDelete(this)">
                            <i class="fa fa-trash text-default"></i>
                            삭제                    
                        </div>  
					</div>
			`	;	
           
	
				if(item.wrterId==LoginUniqId){
						html +=html2;
				}
	
			html +=`             
                      </div>
                    </div> 	
				</div>
					`;	



		                });
		 
		 
		               $("#comment-add-list").html(html);
		            }
		 
		            //페이징 표시 호출
		            comment.paging();
		             
		            //삭제 이벤트 추가
		   /*         let fileDeletes=document.querySelectorAll(".fileDeleteBtn");            
		            for(let i=0; i<fileDeletes.length; i++){
		                fileDeletes[i].addEventListener("click", function(e){
		                        fileList.fileDelete(e.target.getAttribute("data-id"));  
		                });
		            }
		             */
             				
				
			},
			error:function(res){
				console.log("error");
				console.log(res);	
			}
					
		});
			


 
    },
 

	commentAdd:function(){
			const commentContent =$("#commentContent").val();
					const nttId=$("#nttId").val();
					
					if(commentContent==""){
						tWarning("댓글을 입력해 주세요.");
						$("#commentContent").focus();
						return;
					}
					
					const param={
						"commentCn":commentContent,
						"nttId":nttId
					}
					
					
					$.ajax({
						url:'/portal/comment/insertArticleComment.do',
						type:'post',
						contentType:'application/json;charset=UTF-8',
						data:JSON.stringify(param),
						success:function(res){
							if(res=="success"){
								$("#commentContent").val("");
								$("#sup-commentContent").html("[0자 / 150]");
								comment.list();	
							}
							
						},
						error:function(res){
							console.log("error");
							console.log(res);	
						}
								
					});
						
	},


	commentDelete:function(e){
		
		if(confirm("정말 삭제 하시겠습니까?")){
				 const commentNo =$(e).attr("data-id");
				 console.log(commentNo);				
				  const param={
						"commentNo":commentNo
				   }
								
				$.ajax({
					url:'/portal/comment/deleteArticleComment.do',
					type:'post',
					contentType:'application/json;charset=UTF-8',
					data:JSON.stringify(param),
					success:function(res){
						if(res=="success"){							
							comment.list();	
							tInfo("삭제 처리 되었습니다.");
						}
						
					},
					error:function(res){
						console.log("error");
						console.log(res);	
					}
							
				});						
		}		
		
	},


	commentUpdateForm:function(e){
			 const commentNo =$(e).attr("data-id");
			// console.log(commentNo);
			 $("#comment-text-"+commentNo).css("display","none");
			 $("#update-comment-textarea-"+commentNo).show();	
		
		 	 $("#commentUpdateFormBtn-"+commentNo).css("display","none");
			 $("#commentUpdateBtn-"+commentNo).show();
			 $("#update-comment-textarea-"+commentNo +" textarea").focus();	
						
	} ,


		//업데이트 처리
	commentUpdate:function(e){
		    const commentNo =$(e).attr("data-id");
			const commentCn=$("#update-comment-textarea-"+commentNo +" textarea").val();
			const nttId=$("#nttId").val();
			if(commentCn==""){
				 tWarning("내용을 입력해 주세요.");	
				 $("#update-comment-textarea-"+commentNo +" textarea").focus();		
				return;
			}
			
			
			const param={
						"commentCn":commentCn,
						"commentNo":commentNo,
						"nttId":nttId
			}
			
		   $.ajax({
					url:'/portal/comment/updateArticleComment.do',
					type:'post',
					contentType:'application/json;charset=UTF-8',
					data:JSON.stringify(param),
					success:function(res){
						if(res=="success"){							
							 $("#comment-text-"+commentNo).css("display","block");
							 $("#update-comment-textarea-"+commentNo).hide();	
						
						 	 $("#commentUpdateFormBtn-"+commentNo).css("display","inline");
							 $("#commentUpdateBtn-"+commentNo).hide();
						   	 $("#comment-text-"+commentNo).text(commentCn);
							 tInfo("업데이트 처리 되었습니다.")
						}						
					},
					error:function(res){
						console.log("error");
						console.log(res);	
					}
							
				});				
			
		
;		
			 				
	} ,



	flexSwitchCheckChecked:function(){
		
	},



    // 페이징 표시 함수 
     //function(totalData, dataPerPage, pageCount, currentPage)
    paging: function(){
       // console.log("currentPage : " + currentPage);
 
        totalPage = Math.ceil(totalData / dataPerPage); //총 페이지 수
 
        if (totalPage < pageCount) {
            pageCount = totalPage;
        }
 
        let pageGroup = Math.ceil(currentPage / pageCount); // 페이지 그룹
        let last = pageGroup * pageCount; //화면에 보여질 마지막 페이지 번호
 
        if (last > totalPage) {
            last = totalPage;
        }
 
        let first = last - (pageCount - 1); //화면에 보여질 첫번째 페이지 번호
        let next = last + 1;
        let prev = first - 1;
 
        let pageHtml = "";
 
        if (prev > 0) {
            pageHtml += "<li><a href='#' id='prev'> « </a></li>";
        }
 
        //페이징 번호 표시 
        for (var i = first; i <= last; i++) {
 
            if (currentPage == i) {
                pageHtml +=
                    "<li class='on'><a href='#' id='" + i + "'>" + i + "</a></li>";
            } else {
                pageHtml += "<li><a href='#' id='" + i + "'>" + i + "</a></li>";
            }
        }
 
 
        if (last < totalPage) {
            pageHtml += "<li><a href='#' id='next'> » </a></li>";
        }
 
 		
	
        document.querySelector("#pagingul").innerHTML = pageHtml;
 
       // let displayCount = "";
       // displayCount = "현재 1 - " + totalPage + " (" + currentPage + "페이지) / " + totalData + "건";
       // document.querySelector("#displayCount").innerText = displayCount;
 
 
        //페이징 번호 클릭 이벤트 
        const paginationClass = document.querySelectorAll("#pagingul li a");
        for (let i = 0; i < paginationClass.length; i++) {
            paginationClass[i].addEventListener("click", function(e) {
                e.preventDefault();
 
                let $id = this.getAttribute("id")
                selectedPage = this.innerText;
 
                console.log("선택한 페이지 ", selectedPage);
                if ($id == "next") selectedPage = next;
                if ($id == "prev") selectedPage = prev;
                comment.list(selectedPage);
            });
        }
 
    },




 
}
 
 

//textarea 바이트 수 체크하는 함수
function fn_checkByte(obj){   
	var id=$(obj).attr("data-id");
	var strValue = obj.value;
	var strLen = strValue.length;
	var str = "";
	str += '[' + strLen + '자 / 150]';
	if(strLen > 149){
		alert("제한 글자를 초과하였습니다.");
		$(obj).val(strValue.substring(0, 148));
	}
	
	$("#sup-"+id).html(str);
   
}

 
comment.init();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

소스 :

 

https://github.com/braverokmc79/sprig_boot_2.7.0_mybatis_board_project/commit/9a15e66cb6cec807e7d2381a8bb8f37fbafcc394

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

총총들이 반병이라 , [병에 무엇을 부을 때 급하게 하면 반 병 밖에 붓지 못한다는 뜻으로] 무슨 일이나 급히 서둘러 하지 말고 오래 천천히 해야 된다는 말.

댓글 ( 5)

댓글 남기기

작성