22.09.30 - Spring Boot(SPA, REACT)
Spring-Boot(SPA : 한페이지에 다 있는 거), REACT활용
Controller
BoardController
package com.academy.bootspa.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.ModelAndView; import com.academy.bootspa.model.domain.Board; @Controller public class BoardController { @GetMapping("/board/main") public ModelAndView getMain() { System.out.println("메인 요청"); return new ModelAndView("main"); } //등록요청 처리 @PostMapping("/board/regist") public ModelAndView regist(Board board) { System.out.println("동기방식의 등록 요청을 받음"+board); return null; } }
Exception
BoardException
package com.academy.bootspa.exception; public class BoardException extends RuntimeException{ public BoardException(String msg) { // TODO Auto-generated constructor stub super(msg); } public BoardException(Throwable e) { // TODO Auto-generated constructor stub super(e); } public BoardException(String msg, Throwable e) { // TODO Auto-generated constructor stub super(msg,e); } }
Model
board
BoardDAO
package com.academy.bootspa.model.board; import java.util.List; import com.academy.bootspa.model.domain.Board; public interface BoardDAO { public List selectAll(); public Board select(int board_id); public void insert(Board board); public void update(Board board); public void delete(Board board); }BoardService
package com.academy.bootspa.model.board; import java.util.List; import com.academy.bootspa.model.domain.Board; public interface BoardService { public List selectAll(); public Board select(int board_id); public void insert(Board board); public void update(Board board); public void delete(Board board); }BoardServiceImpl
package com.academy.bootspa.model.board; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import com.academy.bootspa.exception.BoardException; import com.academy.bootspa.model.domain.Board; @Service public class BoardServiceImpl implements BoardService{ @Autowired @Qualifier("hibernateBoardDAO") private BoardDAO boardDAO; @Override public List selectAll() { // TODO Auto-generated method stub return boardDAO.selectAll(); } @Override public Board select(int board_id) { // TODO Auto-generated method stub return boardDAO.select(board_id); } @Override public void insert(Board board)throws BoardException{ // TODO Auto-generated method stub boardDAO.insert(board); } @Override public void update(Board board) throws BoardException{ // TODO Auto-generated method stub boardDAO.update(board); } @Override public void delete(Board board) throws BoardException { // TODO Auto-generated method stub boardDAO.delete(board); } }HibernateBoardDAO
package com.academy.bootspa.model.board; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.academy.bootspa.exception.BoardException; import com.academy.bootspa.model.domain.Board; @Repository public class HibernateBoardDAO implements BoardDAO { @Autowired //이걸로 쿼리문을 제어할 수 있음 private HibernateBoardRepository boardRepository; @Override public List selectAll() { // TODO Auto-generated method stub return boardRepository.findAll(); } @Override public Board select(int board_id) { return boardRepository.findById(board_id).get(); } @Override public void insert(Board board) throws BoardException{ // TODO Auto-generated method stub Board result =boardRepository.save(board);//자기가 알아서 board와 연결된 table insert까지 함 if(result==null) { throw new BoardException("Hibernate로 등록실패"); } } @Override public void update(Board board) throws BoardException{ // TODO Auto-generated method stub Board result =boardRepository.save(board); if(result==null) { throw new BoardException("Hibernate로 수정실패"); } } @Override public void delete(Board board) throws BoardException{ // TODO Auto-generated method stub try { boardRepository.delete(board); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); throw new BoardException("Hibernate로 삭제실패",e); } } }HibernateBoardRepository
package com.academy.bootspa.model.board; import org.springframework.data.jpa.repository.JpaRepository; import com.academy.bootspa.model.domain.Board; //Hibernate가 지원하는 JpaRepository 로 정의 DTO primary-key public interface HibernateBoardRepository extends JpaRepository<Board, Integer> { }MybatisBoardDAO
package com.academy.bootspa.model.board; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.academy.bootspa.exception.BoardException; import com.academy.bootspa.model.domain.Board; @Repository public class MybatisBoardDAO implements BoardDAO{ @Autowired private MybatisBoardMapper boardMapper; @Override public List selectAll() { // TODO Auto-generated method stub return boardMapper.selectAll(); } @Override public Board select(int board_id) { // TODO Auto-generated method stub return boardMapper.select(board_id); } @Override public void insert(Board board)throws BoardException { // TODO Auto-generated method stub int result = boardMapper.insert(board); if(result==0) { throw new BoardException("Mybaits에 의한 등록실패"); } } @Override public void update(Board board) throws BoardException{ // TODO Auto-generated method stub int result = boardMapper.update(board); if(result==0) { throw new BoardException("Mybatis에 의한 수정 실패"); } } @Override public void delete(Board board) throws BoardException{ // TODO Auto-generated method stub int result = boardMapper.delete(board); if(result==0) { throw new BoardException("Mybatis에 의한 수정 실패"); } } }MybatisBoardMapper
package com.academy.bootspa.model.board; import java.util.List; import org.apache.ibatis.annotations.Mapper; import com.academy.bootspa.model.domain.Board; //SqlSessionTemplate을 사용하지 않고 개발가능 @Mapper public interface MybatisBoardMapper { public List selectAll(); public Board select(int board_id); public int insert(Board board); public int update(Board board); public int delete(Board board); }
domain
Board
package com.academy.bootspa.model.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import lombok.Data; @Data @Entity public class Board { //프라이머리 키에 대하여 아래 2줄은 적어야함 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int board_id; private String title; private String writer; private String content; private String regdate; private int hit; }
mybatis
BoardMapper.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"> <mapper namespace="com.academy.bootspa.model.board.MybatisBoardMapper"> <select id="selectAll" resultType="Board"> select * from board </select> <select id="select" parameterType="int" resultType="Board"> select * from board where board_id=#{board_id} </select> <insert id="insert"> insert into board(title,writer,content) values(#{title},#{writer},#{content}) </insert> <update id="update" parameterType="Board"> update board set title=#{title}, writer=#{writer},content=#{content} where board_id=#{board_id} </update> <delete id="delete" parameterType="Board"> delete from board where board_id =#{board_id} </delete> </mapper>config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias type="com.academy.bootspa.model.domain.Board" alias="Board"/> </typeAliases> <mappers> <mapper resource="com/academy/bootspa/mybatis/BoardMapper.xml"/> </mappers> </configuration>
RestController
RestBoardController
package com.academy.bootspa.restcontroller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.academy.bootspa.exception.BoardException; import com.academy.bootspa.model.board.BoardService; import com.academy.bootspa.model.domain.Board; import com.academy.bootspa.util.Message; @RestController @RequestMapping("/rest") public class RestBoardController { @Autowired private BoardService boardService; //기존 폼을 시리얼화하여 전송 파라미터로 만든 후 전송된 요청받음 @PostMapping("/serial/board") public ResponseEntity<Message> registByParam(Board board){ System.out.println("registBySerial 등록 요청 받음"+board); boardService.insert(board); Message message = new Message(1,"registByParam 등록성공"); ResponseEntity<Message> entity = new ResponseEntity<Message>(message,HttpStatus.OK); return entity; } //기존 폼을 시리얼화하여 전송 json문자열로 변환한 후 전송된 요청받기 @PostMapping("/json/board") public ResponseEntity<Message> registByJson(@RequestBody Board board){ System.out.println("registByJson 등록 요청 받음"+board); boardService.insert(board); Message message = new Message(1,"registByJson 등록성공"); ResponseEntity<Message> entity = new ResponseEntity<Message>(message,HttpStatus.OK); return entity; } @GetMapping("/board") public List<Board> getList(){ List boardList = boardService.selectAll();
return boardList;
}
@GetMapping("/board/{board_id}")
public Board getDetail(@PathVariable("board_id") int board_id ) {
Board board = boardService.select(board_id);
System.out.println(board);
return board;
}
//한건 수정 요청
@PutMapping("/board")
public ResponseEntity<Message> update(Board board){
System.out.println("수정 요청으로 받은 파라미터"+board);
boardService.update(board);
Message message = new Message(1,"수정 성공");
ResponseEntity<Message> entity = new ResponseEntity<Message>(message,HttpStatus.OK);
return entity ;
}
@DeleteMapping("/board")
public ResponseEntity<Message> del(Board board){
boardService.delete(board);
Message message = new Message(1,"삭제 성공");
ResponseEntity<Message> entity = new ResponseEntity<Message>(message,HttpStatus.OK);
return entity ;
}
@ExceptionHandler(BoardException.class)
public ResponseEntity<Message> handle(BoardException e){
Message message = new Message(0,e.getMessage());
ResponseEntity<Message> entity = new ResponseEntity<Message>(message,HttpStatus.INTERNAL_SERVER_ERROR);
return entity;
}
}
```util
Message
package com.academy.bootspa.util; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class Message { private int code; private String msg; }
resources
application.properties
#서버포트 변경 server.port=7777 #뷰 매핑 spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp #DB연결 spring.datasource.url=jdbc:mysql://localhost:3306/javastudy?characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=1234 spring.datasource.driver-class-name=com.mysql.jdbc.Driver #connection pool(dbcp) spring.datasource.hikari.connection-timeout=10000 spring.datasource.hikari.maximum-pool-size=20 #mybatis config 설정파일 등록 mybatis.config-location=classpath:com/academy/bootspa/mybatis/config.xml #hibernate에 숨겨진 쿼리 출력 spring.jpa.show-sql=true
View
main.jsp
<%@ page contentType="text/html;charset=UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <style type="text/css"> body{margin:0px;} #wrapper{ width:100%; height:700px; overflow: hidden; } #input-area{ width: 20%; height:100%; float: left; background-color:yellow; } #list-area{ width: 60%; height:100%; float: left; background-color:skyblue; overflow: scroll; } #detail-area{ width: 20%; height:100%; float: left; background-color:pink; } #input-area input,#detail-area input{ width: 95%; } </style> <script type="text/babel"> /*-------------------------------------------------------------------- *동기방식의 폼 전송 ---------------------------------------------------------------------*/ function regist(){ $("#input-form").attr({ action:"/board/regist", method:"post" }); $("#input-form").submit(); } /*-------------------------------------------------------------------- *비동기 방식의 기존폼을 이용한 Parameter 문자열 전송 serialize : queryString의 형식으로 넘어감 serializeArray : key : value로 나옴 contentType은 : post방식에서의 네트워크 header부분에 application/x-www-form-urlencoded 이 나와있다. ---------------------------------------------------------------------*/ function registBySerial(){ var params = $("#input-form").serialize(); console.log(params); //이미 전송할 파라미터화가 완료되었으므로, Json으로 변환하지 말고 그냥 보내보자 $.ajax({ url:"/rest/serial/board", type:"post", data:params, contentType:"application/x-www-form-urlencoded;charset=utf-8", success:function(result,status,xhr){ getList(); }, error:function(xhr,status,error){ alert(error.msg); } }); } /*-------------------------------------------------------------------- *비동기 방식의 기존폼을 이용한 json 문자열 전송 ---------------------------------------------------------------------*/ function registByJson(){ var formArray = $("#input-form").serializeArray(); console.log(formArray); //원하는 형태의 json으로 가공 var json = {}; for(var i =0; i<formArray.length;i++){ json[formArray[i].name]=formArray[i].value; } console.log(json); //json 전송시 주의 : json 객체 자체는 전송 불가 즉 json문자열로 반환 $.ajax({ url:"/rest/json/board", type:"post", data:JSON.stringify(json), contentType:"application/json;charset=utf-8", success:function(result,status,xhr){ getList(); }, error:function(xhr,status,error){ alert(error.msg); } }); } /*-------------------------------------------------------------------- *비동기 방식으로 목록 가져오기 ---------------------------------------------------------------------*/ function getList(){ $.ajax({ url:"/rest/board", type:"get", success:function(result, status, xhr){ console.log("서버로부터 받은 json 목록",result); printList(result);//json 배열을 넘겨주자 }, error:function(xhr,status,error){ console.log(error); } }); } //비동기 방식으로 한건의 데이터 가져오기 function getDetail(board_id){ console.log("넘겨받은 board_id " +board_id); $.ajax({ url:"/rest/board/"+board_id, type:"get", success:function(result,status,xhr){ console.log(result); printBoard(result); }, error:function(xhr, status, error){ console.log(error); } }); } //우측 영역에 한건 출력 function printBoard(board){ $("#detail-form input[name='board_id']").val(board.board_id); $("#detail-form input[name='title']").val(board.title); $("#detail-form input[name='writer']").val(board.writer); $("#detail-form textarea[name='content']").val(board.content); } /*-------------------------------------------------------------------- *React를 이용한 UI처리 ---------------------------------------------------------------------*/ function Row(props){ var link = "javascript:getDetail("+props.board_id+")"; return( <tr align="center"> <td>{props.board_id}</td> <td><a href={link}>{props.title}</a></td> <td>{props.writer}</td> <td>{props.regdate}</td> <td>{props.hit}</td> </tr> ); } function BoardTable(props){ var list = props.boardList; //tr을 반복한 컨테츠를 구성 var tag =[];//여기에 tr을 모아둘것임 for(var i=0; i<list.length; i++){ var obj = list[i];//게시물 한건 꺼내기 tag.push(<Row board_id={obj.board_id} title={obj.title} writer={obj.writer} regdate={obj.regdate} hit={obj.regdate} />); //arrayList.add()와 동일 } return( <table width="100%" border="1px"> <thead> <tr> <th>No</th> <th>제목</th> <th>작성자</th> <th>등록일</th> <th>조회수</th> </tr> </thead> <tbody> {tag} </tbody> </table> ); } //화면에 테이블 출력함수 function printList(jsonArray){ var root = ReactDOM.createRoot(document.getElementById("list-area")); root.render(<BoardTable boardList={jsonArray} />); } //수정 요청 function edit(){ //비동기 요청시 기존 폼을 이용하는 법(파라미터,json) var params = $("#detail-form").serialize();
if(confirm("수정하시겠어요")){
$.ajax({
url:"/rest/board",
type:"PUT",
data:params,
contentType:"application/x-www-form-urlencoded;charset=utf-8",
success:function(result,status,xhr){
console.log(result.msg);
getList();
}
});
}
}
//삭제요청
function del(){
if(confirm("삭제하시겠어요")){
$.ajax({
url:"/rest/board?board_id="+$("#detail-form input[name='board_id']").val(),
type:"delete",
success:function(result,status, xhr){
console.log(result);
getList();
},
error:function(xhr,status,error){
alert(error);
}
});
}
}
$(function(){
$($("#input-area button")[0]).click(function(){
regist();
});
$($("#input-area button")[1]).click(function(){
registBySerial();
});
$($("#input-area button")[2]).click(function(){
registByJson();
});
//상세보기 폼의 버튼 이벤트 처리
$($("#detail-area button")[0]).click(function(){
edit();
});
$($("#detail-area button")[1]).click(function(){
del();
});
getList();
});
</script>
</head>
<body>
<div id="wrapper">
<div id="input-area">
<form id="input-form">
<input type="text" name="title" placeholder="제목">
<input type="text" name="writer" placeholder="작성자">
<textarea style="width: 95%;height:150px; " placeholder="내용" name="content"></textarea>
<button type="button">그냥등록</button>
<button type="button">폼시리얼 등록</button>
<button type="button">json 등록</button>
</form>
</div>
<div id="list-area">
<form id="list-form">
</form>
</div>
<div id="detail-area">
<form id="detail-form">
<input type="hidden" name="board_id">
<input type="text" name="title" placeholder="제목">
<input type="text" name="writer" placeholder="작성자">
<textarea style="width: 95%;height:150px;" placeholder="내용" name="content"></textarea>
<button type="button">수정</button>
<button type="button">삭제</button>
</form>
</div>
</div>
</body>
</html>
```'Program > Spring' 카테고리의 다른 글
| VO/DTO, @ToString, 생성자/빌더, 단위 테스트, 생성자주입VS필드 주입, Controller VS Service, Log4j2, JSP 분리 (0) | 2022.12.30 |
|---|---|
| 객체 지향 설계 원칙(SOLID 원칙) ,OCP, MVC (0) | 2022.12.27 |
| 쇼핑몰_Project - 9(관리자 페이지 제품수정(비동기+파일 업로드), Spring Boot Basic 프로젝트 (1) | 2022.12.27 |
| 쇼핑몰_Project - 8(관리자 페이지 주문 목록, 제품 목록) (0) | 2022.12.27 |
| 쇼핑몰_Project - 7(결제-2, 이메일 보내기) (0) | 2022.12.27 |