반응형
01. REST API는 언제 사용?
- 하이브리드 앱 만들 때 많이 이용
- 내 폰 기기 말고 온라인 상(서버)에 저장된 데이타베이스의 저장된 값들을 가져올 때 REST API 많이 이용함
- 게임 캐릭터의 정보(게임 서버에 저장되어 있을 것임),
- 우리가 대화한 카카오톡 내용 정보(카카오 서버에 저장되어 있을 것임),
- 네이버 메일 내용의 정보(네이버 서버에 저장되어 있을 것임) .. 이러한 것들을 가져다 쓸 때 REST API 많이 이용함
- 백엔드 개발자 : 🧡REST API 만들기
- 프론트엔드 개발자 : 🧡REST 프로그램 만들기
- 백엔드 개발자 : 🧡REST API 테스트 하기 (HTML이나 JSP 문서 없을 경우에 테스트 반드시 필요!)
실제 회사에서 몇개의 프론트 컨트롤러(서블릿)를 사용할까??
- 웹사이트용 프론트 컨트롤러 : 클라이언트가 요청하면 JSP 형식으로 응답해줌
- REST API용 프론트 컨트롤러 : 클라이언트가 요청하면 JSON 형식으로 응답해줌 - 하이브리드앱 만들때 사용
- 전산용 프론트 컨트롤러 : 회사 내부적인 관리 시스템을 구현하기 위해 사용
- 등등...
웹서버 (정적문서제공 - HTML,CSS,JS,IMAGE파일 등) : 아파치
WAS (동적문서제공 - 서블릿 이용) : 톰캣 , 제우스
02. 테이블, DTO
🖤[테이블, DTO] RestBoard.java
package xyz.itwill10.dto;
import lombok.Data;
/*
create table restboard(num number primary key, writer varchar2(50), content varchar2(100), regdate date);
create sequence restboard_seq;
desc restboard;
이름 널? 유형
------- -------- -------------
NUM NOT NULL NUMBER
WRITER VARCHAR2(50)
CONTENT VARCHAR2(100)
REGDATE DATE
*/
@Data
public class RestBoard {
private int num;
private String writer;
private String content;
private String regdate;
}
03. Mapper바인딩
💛[Mapper] RestBoardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<mapper namespace="xyz.itwill10.mapper.RestBoardMapper">
<insert id="insertRestBoard">
<selectKey resultType="int" keyProperty="num" order="BEFORE">
select restboard_seq.nextval from dual
</selectKey>
insert into restboard values(#{num},#{writer},#{content},sysdate)
</insert>
<update id="updateRestBoard">
update restboard set writer=#{writer},content=#{content} where num=#{num}
</update>
<delete id="deleteRestBoard">
delete from restboard where num=#{num}
</delete>
<!-- RESTBOARD 테이블에 저장된 모든 게시글들의 갯수를 검색해서 int로 반환받음 -->
<select id="selectRestBoardCount" resultType="int">
select count(*) from restboard
</select>
<select id="selectRestBoard" resultType="RestBoard">
select * from restboard where num=#{num}
</select>
<!-- rownum을 이용해 인라인뷰 2번 사용해서 페이징 처리 : [시작행번호] ~ [종료행번호] 까지만 검색 -->
<select id="selectRestBoardList" resultType="RestBoard">
select * from (select rownum rn, board.* from (select * from restboard order by num desc) board)
where rn between #{startRow} and #{endRow}
</select>
<!-- 만약 동적 SQL을 이용한다면 ?? [${search} : 컬럼명] = [#{keyword} : 값] -->
<!--
<select id="selectRestBoardList" resultType="RestBoard">
select * from (select rownum rn, board.* from
<if test="keyword!=null">
where ${search}=#{keyword}
</if>
(select * from restboard order by num desc) board)
where rn between #{startRow} and #{endRow}
</select>
-->
</mapper>
💛[Mapper] RestBoardMapper.java
package xyz.itwill10.mapper;
import java.util.List;
import java.util.Map;
import xyz.itwill10.dto.RestBoard;
public interface RestBoardMapper {
int insertRestBoard(RestBoard board);
int updateRestBoard(RestBoard board);
int deleteRestBoard(int num);
int selectRestBoardCount();
RestBoard selectRestBoard(int num);
//전달받아야 할 값의 DTO 클래스가 없으므로 Map 객체로 받기
//=> ex) startRow , endRow, keyword ..
List<RestBoard> selectRestBoardList(Map<String, Object> map);
}
04. @Repository
🖤[DAO] RestBoardDAO.java
package xyz.itwill10.dao;
import java.util.List;
import java.util.Map;
import xyz.itwill10.dto.RestBoard;
public interface RestBoardDAO {
int insertRestBoard(RestBoard board);
int updateRestBoard(RestBoard board);
int deleteRestBoard(int num);
int selectRestBoardCount();
RestBoard selectRestBoard(int num);
//전달받아야 할 값의 DRTO 클래스가 없으므로 Map 객체로 받기
//=> ex) startRow , endRow, keyword ..
List<RestBoard> selectRestBoardList(Map<String, Object> map);
}
🖤[DAO] RestBoardDAOImpl.java
package xyz.itwill10.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.RestBoard;
import xyz.itwill10.mapper.RestBoardMapper;
@Repository
@RequiredArgsConstructor
public class RestBoardDAOImpl implements RestBoardDAO {
private final SqlSession sqlSession;
@Override
public int insertRestBoard(RestBoard restBoard) {
return sqlSession.getMapper(RestBoardMapper.class).insertRestBoard(restBoard);
}
@Override
public int updateRestBoard(RestBoard restBoard) {
return sqlSession.getMapper(RestBoardMapper.class).updateRestBoard(restBoard);
}
@Override
public int deleteRestBoard(int num) {
return sqlSession.getMapper(RestBoardMapper.class).deleteRestBoard(num);
}
@Override
public int selectRestBoardCount() {
return sqlSession.getMapper(RestBoardMapper.class).selectRestBoardCount();
}
@Override
public RestBoard selectRestBoard(int num) {
return sqlSession.getMapper(RestBoardMapper.class).selectRestBoard(num);
}
@Override
public List<RestBoard> selectRestBoardList(Map<String, Object> map) {
return sqlSession.getMapper(RestBoardMapper.class).selectRestBoardList(map);
}
}
05. @Service
🖤[Service] (부모) RestBoardService.java
package xyz.itwill10.service;
import java.util.List;
import java.util.Map;
import xyz.itwill10.dto.RestBoard;
public interface RestBoardService {
void addRestBoard(RestBoard restBoard);
void modifyRestBoard(RestBoard restBoard);
void removeRestBoard(int num);
int getRestBoardCount();
RestBoard getRestBoard(int num);
List<RestBoard> getRestBoardList (Map<String, Object> map);
}
🖤[Service] (자식) RestBoardServiceImpl.java
package xyz.itwill10.service;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dao.RestBoardDAO;
import xyz.itwill10.dto.RestBoard;
//실제 Service 클래스를 만들 때는 반드시 예외를 전달해서 만들기!!
//이 예제는 예외전달하지 않을 것임
@Service
@RequiredArgsConstructor
public class RestBoardServiceImpl implements RestBoardService{
private final RestBoardDAO restBoardDAO;
@Transactional
@Override
public void addRestBoard(RestBoard restBoard) {
restBoardDAO.insertRestBoard(restBoard);
}
@Transactional
@Override
public void modifyRestBoard(RestBoard restBoard) {
/*
if(restBoardDAO.selectRestBoard(restBoard.getNum())==null) {
throw new Exception("해당 게시글을 찾을 수 없습니다");
}
*/
restBoardDAO.updateRestBoard(restBoard);
}
@Transactional
@Override
public void removeRestBoard(int num) {
restBoardDAO.deleteRestBoard(num);
}
@Override
public int getRestBoardCount() {
return restBoardDAO.selectRestBoardCount();
}
@Override
public RestBoard getRestBoard(int num) {
return restBoardDAO.selectRestBoard(num);
}
@Override
public List<RestBoard> getRestBoardList(Map<String, Object> map) {
return restBoardDAO.selectRestBoardList(map);
}
}
06. @Controller
🖤[Controller] RestBoardController.java
package xyz.itwill10.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
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.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.RestBoard;
import xyz.itwill10.service.RestBoardService;
import xyz.itwill10.util.Pager;
//🌈REST API 테스트 하는 법
//REST 기능을 제공하는 페이지를 요청하여 요청 처리 메소드가 정상적으로 실행되는지 확인하기 위해 Advanced REST Client 크롬앱을 설치하여 사용
// => REST API 테스트 프로그램
// => JSP 문서 없이도 이 앱을 이용하면 값이 잘 전달되는지 확인 가능함
//REST 기능을 제공하는 요청 처리 메소드의 페이지 요청방식
//=> @RequestMapping 어노테이션의 method 속성값을 사용하여 구분
//=> @GetMapping, @PostMapping 등의 어노테이션 사용 가능
//=> 페이지 요청방식 : GET(검색), POST(삽입), PUT(전체 변경), PATCH(부분 변경), DELETE(삭제) 등
//=> 일반적으로 검색은 GET을 많이 사용하지만, 필요에 따라 POST로도 가능!
//=> [PUT], [PATCH], [DELETE] 등의 요청방식은 [POST] 요청방식에서 파생된 요청방식
//=> 리퀘스트 메세지의 몸체부(body)에 전달값 저장
@Controller
//@RestController : REST 기능을 제공하는 요청 처리 메소드로만 작성된 Controller 클래스를 Spring Bean으로 등록하기 위한 어노테이션
//=> REST 기능을 제공하는 요청 처리 메소드에 @ResponseBody 어노테이션을 사용하지 않아도 반환값을 텍스트 데이타로 응답 처리 가능
//=> 주의) 클라이언트에게 JSP 문서로 응답하는 요청 처리 메소드가 하나라도 있을 경우 @RestController 작성 불가능
@RequiredArgsConstructor
public class RestBoardController {
private final RestBoardService restBoardService;
💜 /board 요청
//클라이언트에게 JSP 문서로 응답 - 이 메소드가 있기 때문에 @RestController 사용 불가능
@RequestMapping("/board")
public String restBoard() {
return "rest/board"; // 클라이언트에게 [JSP 문서]로 응답
}
💜[GET]방식 : /board_list 요청
//클라이언트에게 [텍스트 데이타 - JSON]로 응답 - XML형식 말고 JSON 형식 이용할 것임
//=> 클라이언트는 AJAX 기능을 사용해 아래의 요청 URL 주소로 요청할 것임
//페이지 번호를 전달받아 RESTBOARD 테이블에 저장된 게시글 목록 중 해당 페이지 번호의 범위에 게시글 목록을 검색하여 JSON 형식의 데이타로 응답하는 요청 처리 메소드
// => 게시글 목록을 페이징 처리하여 출력하기 위해 요청 페이지 번호의 게시글 목록과 페이지 번호 출력 관련 값이 저장된 객체를 Map 객체의 엔트리로 저장하여 JSON 형식의 텍스트 데이타로 응답 처리되도록 반환
//=> 즉, 반환형(Map) -> {"게시글목록":"", "페이지번호":""}
@RequestMapping(value="/board_list", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> restBoard(@RequestParam(defaultValue = "1")int pageNum) {
//System.out.println("pageNum = " + pageNum); //board_list?pageNum=5 하면 -> pageNum = 5 출력됨
//RESTBOARD 테이블에 저장된 모든 게시글의 갯수를 반환하는 메소드 호출
int totalBoard=restBoardService.getRestBoardCount();
int pageSize=5; //하나의 페이지에 출력될 게시글의 갯수 저장
int blockSize=5; //하나의 블럭에 출력될 페이지 번호의 갯수 저장
//페이징 처리 관련 값이 필드에 저장된 Pager 객체 생성
Pager pager=new Pager(pageNum, totalBoard, pageSize, blockSize);
//RestBoardService 클래스의 getRestBoardList() 메소드를 호출하기 위해 Map 객체 생성
// => Map 객체에는 요청 페이지의 시작 행번호(startRow)와 종료 행번호(endRow)를 엔트리로 저장하여 SQL 명령에서 사용
Map<String, Object> pageMap = new HashMap<String, Object>();
pageMap.put("startRow", pager.getStartRow());
pageMap.put("endRow", pager.getEndRow());
//요청 페이지 번호에 대한 게시글 목록을 List 객체로 반환받아 저장
List<RestBoard> restBoardList = restBoardService.getRestBoardList(pageMap);
//처리 결과를 저장하기 위한 Map 객체 생성 - Map 객체를 반환하여 JSON 형식의 데이타로 응답
// => Map 객체에는 게시글 목록(List 객체)과 페이징 처리 관련 값이 저장된 객체(Pager 객체)를 엔트리로 저장
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("restBoardList",restBoardList);
resultMap.put("pager",pager);
return resultMap; //Map 객체로 반환하여 JSON형식의 텍스트 데이타로 응답
}
💜[POST]방식 : /board_add 요청
//게시글을 전달받아 RESTBOARD 테이블에 삽입하고 처리결과를 일반 텍스트로 응답하는 요청 처리 메소드
// => [application/json] 형식으로 전달된 값을 Java 객체로 제공받기 위해 매개변수에 @RequestBody 어노테이션 사용
@RequestMapping(value="/board_add", method = RequestMethod.POST)
@ResponseBody
public String restBoardAdd(@RequestBody RestBoard restBoard) {
//HtmlUtils.htmlEscape(String str) : 전달받은 문자열에서 HTML 태그 관련 문자를 회피
//문자(Escape Character)로 변환하여 반환하는 메소드 - XSS 공격에 대한 방어법
//=> (방어법 클래스를 직접 만들지 않아도 Spring 에서 다 제공해주니 HtmlUtils 클래스 다져다쓰기)
restBoard.setContent(HtmlUtils.htmlEscape(restBoard.getContent()));
restBoardService.addRestBoard(restBoard);
return "success";
}
💜[GET]방식 : /board_view 요청
//글번호를 전달받아 RESTBOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 JSON 형식의
//텍스트 데이타로 응답하는 요청 처리 메소드
@RequestMapping(value="/board_view", method = RequestMethod.GET)
@ResponseBody
public RestBoard restBoardView(@RequestParam int num) {
return restBoardService.getRestBoard(num);
}
💜[PUT]방식 , [PATCH]방식 : /board_modify 요청 - 부분변경과 전체변경
//게시글을 전달받아 RESTBOARD 테이블에 저장된 해당 게시글을 변경하고 처리결과를 일반 텍스트로 응답하기 위한 요청 처리 메소드
// => 페이지 요청 방식을 여러개로 설정할 경우 @RequestMapping 어노테이션의 method 속성값으로 배열 사용 가능
@RequestMapping(value="/board_modify", method = {RequestMethod.PUT, RequestMethod.PATCH})
@ResponseBody
public String restBoardModify(@RequestBody RestBoard restBoard) {
restBoardService.modifyRestBoard(restBoard);
return "success";
}
💜[DELETE]방식 : /board_remove{num} 요청
//요청 URL 주소의 글번호를 전달받아 RESTBOARD 테이블에 저장된 해당 글번호의 게시글을
//삭제하고 처리결과를 일반 텍스트로 응답하기 위한 요청 처리 메소드
// => 요청 URL 주소를 사용하여 전달된 값은 @RequestMapping 어노테이션의 value 속성값에서
//{이름} 형식으로 표현 가능 - @PathVariable 어노테이션을 사용하여 전달값을 매개변수에 저장
//@PathVariable : URL 주소로 제공된 값을 요청 처리 메소드의 매개변수에 저장하기 위한 어노테이션
// => 요청 URL 주소에서 표현된 이름과 매개변수의 이름이 반드시 같아야만 매개변수에 값 저장 가능
// => @PathVariable 어노테이션에 value 속성값을 사용하여 요청 URL 주소에서 표현된 이름으로
//제공된 값을 얻어와 매개변수에 저장 가능
@RequestMapping(value="/board_remove/{num}", method = RequestMethod.DELETE)
@ResponseBody
public String restBoardRemove(@PathVariable int num) {
restBoardService.removeRestBoard(num);
return "success";
}
}
07. VIEW
💚[JSP] board.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
<!-- 제이쿼리 라이브러리 사용하기 위해 cdn 처리 -->
<script src="<https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js>"></script>
<style type="text/css">
#btnDiv { margin: 10px;}
#restBoardTable { border: 1px solid black; border-collapse: collapse; }
#restBoardTable td, #restBoardTable th { border: 1px solid black; padding: 3px;}
/* display의 기본값을 none으로 설정 - [글쓰기] 버튼 클릭시 보여질 예정 */
/* [신규 게시글을 입력받기 위한 태그] & [변경 게시글을 입력받기 위한 태그] - 같은 디자인임 */
/* 실제 출력화면에서는 */
.inputDiv {
width: 240px; height: 80px; border: 2px solid black; background-color: gray;
position: absolute; top: 50%; left: 50%;
margin-top: -40px; margin-left: -120px; padding: 5px; z-index: 100;
display: none;
}
</style>
</head>
<body>
<h1>RestBoard</h1>
<hr>
<div id="btnDiv">
<button type="button" id="writeBtn">글쓰기</button>
</div>
<!-- 게시글 목록을 출력하는 태그 -->
<div id="restBoardListDiv"></div>
<!-- 페이지 번호를 출력하는 태그 -->
<div id="pageNumDiv"></div>
<!-- 신규 게시글을 입력받기 위한 태그 -->
<div id="insertDiv" class="inputDiv">
<table>
<tr>
<td>작성자</td>
<td><input type="text" id="insertWriter" class="insert"></td>
</tr>
<tr>
<td>내용</td>
<td><input type="text" id="insertContent" class="insert"></td>
</tr>
<tr>
<td colspan="2">
<button type="button" id="insertBtn">저장</button>
<button type="button" id="cancelInsertBtn">취소</button>
</td>
</tr>
</table>
</div>
<!-- 변경 게시글을 입력받기 위한 태그 -->
<div id="updateDiv" class="inputDiv">
<input type="hidden" id="updateNum">
<table>
<tr>
<td>작성자</td>
<td><input type="text" id="updateWriter" class="update"></td>
</tr>
<tr>
<td>내용</td>
<td><input type="text" id="updateContent" class="update"></td>
</tr>
<tr>
<td colspan="2">
<button type="button" id="updateBtn">변경</button>
<button type="button" id="cancelUpdateBtn">취소</button>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
//현재 요청 페이지의 번호를 저장하기 위한 전역변수
// => 모든 함수에서 사용 가능하며 프로그램 종료 전까지 값을 유지
var page=1;
//🧡특정 페이지의 게시글 목록을 출력하는 함수 호출
boardListDisplay(page);
🧡특정 페이지의 게시글 목록을 출력하는 함수
//RESTBOARD 테이블에 저장된 게시글 목록을 페이징 처리하여 검색하고 처리 결과를 JSON 형식의
//데이타로 응답하는 페이지를 AJAX 기능으로 요청
// => 응답받은 JSON 형식의 데이타로 게시글 목록 출력 태그를 변경
function boardListDisplay(pageNum) {
//1.
//현재 요청한 페이지를 전역변수에 저장 (프로그램 종료 전까지 값 유지)
page=pageNum;
//2.
//AJAX 이용해 RESTBOARD 테이블에 저장된 게시글 목록을 페이징 처리하여 검색하고
//처리 결과를 JSON 형식으로 받음
//[요청URL주소] - [/board_list?pageNum=2]
$.ajax({
//2-1. GET으로 요청할게
type: "get",
//2-2. board_list 주소로 요청하는데 pageNum값 전달할게
url : "${pageContext.request.contextPath}/board_list?pageNum="+pageNum,
//2-3. 처리결과는 JSON 형식으로 받을게
dataType : "json", //JSON 형식(자바스크립트 객체)
//2-4. 요청 성공하면 result객체(자바스크랍투 객체)에 담아서 사용할게~
//나는 전달받은 JSON 결과값(result)을 html로 변경해서 table로 출력할거야~
success : function(result) {
//alert(result); //[object Object] >> 자바스크립트 Object 객체
//매개변수로 제공받은 자바스크립트 객체를 HTML로 변경하여 게시글 목록 출력 태그 변경
if(result.restBoardList.length==0){ //검색된 게시글이 없는 경우
var html="<table id='restBoardTable'>";
html+="<tr>";
html+="<th width='800' colspan='6'>검색된 게시글이 없습니다</th>";
html+="</tr>";
html+="<table>";
$("#restBoardListDiv").html(html);
return;
}
var html="<table id='restBoardTable'>";
html+="<tr>";
html+="<th width='50'>번호</th>";
html+="<th width='100'>작성자</th>";
html+="<th width='350'>내용</th>";
html+="<th width='200'>작성일</th>";
html+="<th width='50'>변경</th>";
html+="<th width='50'>삭제</th>";
html+="</tr>";
$("#restBoardList").each(function() {//게시글 목록을 반복 처리
html+="<tr>";
html+="<td align='center'>"+this.num+"</td>";
html+="<td align='center'>"+this.writer+"</td>";
html+="<td>"+this.content+"</td>";
html+="<td align='center'>"+this.regdate+"</td>";
html+="<td align='center'><button type='button' onclick='modify("+this.num+")'>변경</button></td>";
html+="<td align='center'><button type='button' onclick='remove("+this.num+")'>삭제</button></td>";
html+="</tr>";
})
html+="<table>";
$("#restBoardListDiv").html(html);
//💛페이지 번호를 출력하는 함수 호출
//=> result(Object객체)가 가진 pager 를 매개변수로 전달하겠다는 뜻
pageNumDisplay(result.pager);
},
//2-5. 요청 실패하면 xhr 객체에 담아서 사용할게~
//나는 alert창에 상태코드 출력할거야~
error : function (xhr) {
alert("에러코드(게시글 목록 검색) : "+xhr.status)
}
});
}
💛페이지 번호를 출력하는 태그를 변경하는 함수
//페이지 번호를 출력하는 태그를 변경하는 함수 - 페이지 번호 출력
// => 매개변수로 pager라는 Object 객체를 전달받음
function pageNumDisplay(pager) {
var html="";
if(pager.startPage > pager.blockSize){
html+="<a href='javascript:boardListDisplay("+pager.prevPage+")'>이전</a>";
}
for(i=pager.startPage; i<=pager.endPage; i++){
if(pager.pageNum!=i){
html+="<a href='javascript:boardListDisplay("+i+")'>["+i+"]</a>";
} else {
html+="["+i+"]";
}
}
if(pager.endPage != pager.totalPage){
html+="<a href='javascript:boardListDisplay("+pager.nextPage+")'>다음</a>";
}
$("#pageNumDiv").html(html);
}
🖤[글쓰기] 태그를 클릭한 경우 이벤트함수 호출
//[글쓰기] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
$("#writeBtn").click(function() {
//변경 게시글을 입력받기 위한 태그 초기화
$(".update").val("");//입력태그 초기화
$("#updateDiv").hide();//태그 숨김
//신규 게시글을 입력받기 위한 태그 출력
$("#insertDiv").show();
});
🖤신규 게시글의 [저장] 태그를 클릭한 경우 이벤트함수 호출
//신규 게시글을 입력받기 위한 태그에서 [저장] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
// => 사용자 입력값을 얻어와 RESTBOARD 테이블에 삽입하는 페이지를 AJAX 기능으로 요청하여
//처리결과를 제공받아 응답 처리
$("#insertBtn").click(function() {
var writer=$("#insertWriter").val();
var content=$("#insertContent").val();
if(writer=="") {
alert("작성자를 입력해 주세요.");
return;
}
if(content=="") {
alert("내용 입력해 주세요.");
return;
}
//AJAX 요청
//[요청URL주소] - [/board_add]
$.ajax({
type: "post",
url: "${pageContext.request.contextPath}/board_add",
//headers : 요청정보가 저장된 리퀘스트 메세지의 머릿부(Header)를 변경하기 위한 속성
// => 리퀘스트 메세지의 머릿부에서 몸체부에 저장된 전달값에 대한 문서형식(MimeType)을 변경
//headers: {"contentType":"application/json"},
//contentType : 리퀘스트 몸체부에 저장된 전달값에 대한 문서형식을 변경하기 위한 속성
// => 리퀘스트 몸체부에 저장된 전달값을 JSON 형식의 텍스트 데이타로 전달
// => 요청 처리 메소드의 매개변수에서 @RequestBody 어노테이션을 사용하여 모든 전달값을
//Java 객체로 제공받아 사용 - 전달값은 Java 객체의 필드값으로 저장
contentType: "application/json",
//JSON.stringify(object) : JavaScript 객체를 전달받아 JSON 형식의 텍스트 데이타로 변환하는 메소드
data: JSON.stringify({"writer":writer,"content":content}),
dataType: "text",
success: function(result) {
if(result=="success") {
//신규 게시글을 입력받기 위한 태그 초기화
$(".insert").val("");//입력태그 초기화
$("#insertDiv").hide();//태그 숨김
//🧡특정 페이지 번호의 게시글 목록을 출력하는 함수 호출
boardListDisplay(page);
}
},
error: function(xhr) {
alert("에러코드(게시글 삽입) = "+xhr.status)
}
});
});
🖤신규 게시글의 [취소] 태그를 클릭한 경우 이벤트함수 호출
//신규 게시글을 입력받기 위한 태그에서 [취소] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
$("#cancelInsertBtn").click(function() {
//신규 게시글을 입력받기 위한 태그 초기화
$(".insert").val("");//입력태그 초기화
$("#insertDiv").hide();//태그 숨김
});
🖤게시글의 [변경] 태그를 클릭한 경우 이벤트함수 호출
//게시글의 [변경] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
// => 글번호를 전달받아 RESTBOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는
//페이지를 AJAX 기능으로 요청하여 처리결과를 JSON 형식의 데이타로 응답받아 변경 게시글을
//입력받기 위한 태그의 입력값으로 초기화 처리
function modify(num) {
//alert(num);
//신규 게시글을 입력받기 위한 태그 초기화
$(".insert").val("");//입력태그 초기화
$("#insertDiv").hide();//태그 숨김
//변경 게시글을 입력받기 위한 태그 출력
$("#updateDiv").show();
//AJAX 요청
//[요청URL주소] - [/board_view?num=2]
$.ajax({
type: "get",
//페이지 요청시 질의문자열(QueryString)을 사용하여 값 전달
// => 요청 처리 메소드의 매개변수에 @RequestParam 어노테이션을 사용하여 값을 제공받아 사용
url: "${pageContext.request.contextPath}/board_view?num="+num,
dataType: "json", //처리결과는 JSON으로 받음
success: function(result) {
//처리결과를 받아서 입력테그의 입력값으로 초기화함
$("#updateNum").val(result.num);
$("#updateWriter").val(result.writer);
$("#updateContent").val(result.content);
},
error: function(xhr) {
alert("에러코드(게시글 검색) = "+xhr.status)
}
});
}
🖤변경 게시글의 [변경] 태그를 클릭한 경우 이벤트함수 호출
//변경 게시글을 입력받기 위한 태그에서 [변경] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
// => 사용자 입력값을 얻어와 RESTBOARD 테이블에 저장된 게시글 변경하는 페이지를 AJAX
//기능으로 요청하여 처리결과를 제공받아 응답 처리
$("#updateBtn").click(function() {
var num=$("#updateNum").val();
var writer=$("#updateWriter").val();
var content=$("#updateContent").val();
if(writer=="") {
alert("작성자를 입력해 주세요.");
return;
}
if(content=="") {
alert("내용 입력해 주세요.");
return;
}
//AJAX 요청
//[요청URL주소] - [/board_modify]
$.ajax({
type: "put",
url: "${pageContext.request.contextPath}/board_modify",
contentType: "application/json",
data: JSON.stringify({"num":num,"writer":writer,"content":content}),
dataType: "text",
success: function(result) {
if(result=="success") {
//변경 게시글을 입력받기 위한 태그 초기화
$(".update").val("");//입력태그 초기화
$("#updateDiv").hide();//태그 숨김
//🧡특정 페이지 번호의 게시글 목록을 출력하는 함수 호출
boardListDisplay(page);
}
},
error: function(xhr) {
alert("에러코드(게시글 변경) = "+xhr.status)
}
});
});
🖤변경 게시글의 [취소] 태그를 클릭한 경우 이벤트함수 호출
//변경 게시글을 입력받기 위한 태그에서 [취소] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
$("#cancelUpdateBtn").click(function() {
//변경 게시글을 입력받기 위한 태그 초기화
$(".update").val("");//입력태그 초기화
$("#updateDiv").hide();//태그 숨김
});
🖤게시글의 [삭제] 태그를 클릭한 경우 이벤트함수 호출
//게시글의 [삭제] 태그를 클릭한 경우 호출되는 이벤트 처리 함수
// => 글번호를 전달받아 RESTBOARD 테이블에 저장된 해당 글번호의 게시글을 삭제하는 페이지를
//AJAX 기능으로 요청하여 처리결과를 일반 텍스트로 제공받아 응답 처리
function remove(num) {
//alert(num);
if(confirm("게시글을 삭제 하시겠습니까?")) {
//AJAX 요청
//[요청URL주소] - [/board_remove/3]
$.ajax({
type: "delete",
//페이지 요청시 요청 URL 주소를 사용하여 "값 전달"
// => 요청 처리 메소드의 매개변수에 @PathVariable 어노테이션을 사용하여 값을 제공받아 사용
url: "${pageContext.request.contextPath}/board_remove/"+num,
dataType: "text",
success: function(result) {
if(result=="success") {
//특정 페이지 번호의 게시글 목록을 출력하는 함수 호출
boardListDisplay(page);
}
},
error: function(xhr) {
alert("에러코드(게시글 삭제) = "+xhr.status)
}
});
}
</script>
</body>
</html>
반응형
'framework > spring mvc 웹사이트제작법' 카테고리의 다른 글
[springMVC웹] 16. exception패키지, util패키지 (0) | 2024.08.05 |
---|---|
[springMVC웹] 15. 파일 업로드 프로그램 (요청 처리 메소드에서 파일 업로드 처리) (0) | 2024.08.05 |
[springMVC웹] 13. 요청 처리 메소드에서 JSON으로 응답하는 법 (0) | 2024.08.05 |
[springMVC웹] 12. 암호화처리, 보안처리(권한처리), 예외처리하는 법 (0) | 2024.08.05 |
[springMVC웹]11. 트랜잭션 매니저 이용하는 법 @Transactional (0) | 2024.08.05 |