<실습>
1. board_list.jsp 완료
- boardVO.java 생성, SecurityCode.java 생성, AdminController에 board_list 바인드매핑 생성
2. board_view.jsp 완료
- board_view.jsp 생성, AdminController에 board_view 바인드매핑 생성
- ReplyController 생성
3. board_write.jsp 완료
- board_write.jsp 생성, AdminController에 board_write 바인드매핑 생성
3개의 jsp파일 각각 board_list.html, board_view.html, board_write.html에서 복사해서 생성한다.
전체적으로 경로 확인, "/admin/board/board_list(or view or write)" 로 수정
1. board_list.jsp
- boardVO 생성 -> AdminController에서 model클래스를 이용해서 jsp로 board_list 데이터 세트를 보낼 때 필요한 클래스
package org.edu.vo;
import java.util.Date;
/**
* 게시판에서 사용되는 데이터 입출력 클래스
* @author 이시은
*
*/
public class BoardVO {
//멤버변수 선언
private Integer bno; //int는 입력값이 null일 때 에러나기 때문에, Integer로 변경
private String title;
private String content;
private String writer;
private Date regdate;
private Date update_date;
private Integer view_count;
private Integer reply_count;
@Override
public String toString() {
return "디버그 BoardVO [bno=" + bno + ", title=" + title + ", content=" + content + ", writer=" + writer + ", regdate="
+ regdate + ", update_date=" + update_date + ", view_count=" + view_count + ", reply_count="
+ reply_count + "]";
}
public Integer getBno() {
return bno;
}
public void setBno(Integer bno) {
this.bno = bno;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
public Date getUpdate_date() {
return update_date;
}
public void setUpdate_date(Date update_date) {
this.update_date = update_date;
}
public Integer getView_count() {
return view_count;
}
public void setView_count(Integer view_count) {
this.view_count = view_count;
}
public Integer getReply_count() {
return reply_count;
}
public void setReply_count(Integer reply_count) {
this.reply_count = reply_count;
}
}
- SecurityCode.java 생성
- 유해사이트로 이동하게 하는 등의 스크립트의 유입을 막기 위해 시큐어코딩을 해준다.
- servlet-context.xml 에 <context:component-scan base-package="org.edu.util" /> 추가
* servlet-context 안에 있는 component-scan이 지정한 package경로에 존재하는 @Controller, @Service, @Repository, @RestController(Rest-API) 어노테이션 클래스를 자동으로 읽어들여서 빈으로 등록. => 실행가능
- AdminController에 @Inject 방식으로 가져와서 쓴다.
package org.edu.util;
import org.springframework.stereotype.Controller;
//컨트롤러 클래스를 사용하는 이유는 스프링에서 사용 가능한 bean으로 만들기 위해서.
@Controller
public class SecurityCode {
/**
* XSS 방지 처리. Cross Site Script 약자 XSS
*
* @param data
* @return
*/
public String unscript(String data) {
if (data == null || data.trim().equals("")) {
return "";
}
String ret = data;
ret = ret.replaceAll("<(S|s)(C|c)(R|r)(I|i)(P|p)(T|t)", "<script");
ret = ret.replaceAll("</(S|s)(C|c)(R|r)(I|i)(P|p)(T|t)", "</script");
ret = ret.replaceAll("<(O|o)(B|b)(J|j)(E|e)(C|c)(T|t)", "<object");
ret = ret.replaceAll("</(O|o)(B|b)(J|j)(E|e)(C|c)(T|t)", "</object");
ret = ret.replaceAll("<(A|a)(P|p)(P|p)(L|l)(E|e)(T|t)", "<applet");
ret = ret.replaceAll("</(A|a)(P|p)(P|p)(L|l)(E|e)(T|t)", "</applet");
ret = ret.replaceAll("<(E|e)(M|m)(B|b)(E|e)(D|d)", "<embed");
ret = ret.replaceAll("</(E|e)(M|m)(B|b)(E|e)(D|d)", "<embed");
ret = ret.replaceAll("<(F|f)(O|o)(R|r)(M|m)", "<form");
ret = ret.replaceAll("</(F|f)(O|o)(R|r)(M|m)", "<form");
return ret;
}
}
- AdminController에 board_list 바인드 매핑 추가, 더미데이터 입력
@RequestMapping(value="/admin/board/board_list", method=RequestMethod.GET)
public String board_list(Model model) throws Exception {
//테스트용 더미 게시판 데이터 만들기
BoardVO board_input = new BoardVO();
board_input.setBno(1);
board_input.setTitle("첫번째 게시물입니다.");
board_input.setContent("첫번째 게시물 내용입니다.<br>줄바꿈했습니다.");
board_input.setWriter("admin");
Date regdate = new Date();
board_input.setRegdate(regdate);
board_input.setView_count(2);
board_input.setReply_count(0);
BoardVO[] board_array = new BoardVO[2];
board_array[0] = board_input;
// ----------------------------------------------
BoardVO board_input2 = new BoardVO();
board_input2.setBno(2);
board_input2.setTitle("두번째 게시물입니다.");
board_input2.setContent("두번째 게시물 내용입니다.<br>줄바꿈했습니다.");
board_input2.setWriter("user02");
board_input2.setRegdate(regdate);
board_input2.setView_count(2);
board_input2.setReply_count(0);
// board_input.setBno(2); // 게시물번호만 2로 변경, 나머지값들은 변경없이 board_array[1]에 저장
board_array[1] = board_input2;
List<BoardVO> board_list = Arrays.asList(board_array); //배열타입을 List타입으로 변경 절차.
model.addAttribute("board_list", board_list);
return "admin/board/board_list";
}
2. board_view.jsp
- AdminController에 board_view 바인드 매핑 추가, 더미데이터 입력
@RequestMapping(value="/admin/board/board_view", method=RequestMethod.GET)
public String board_view(@RequestParam("bno") Integer bno, Model model) throws Exception {
//jsp로 보낼 더미데이터 memberVO에 담아서 보낸다.
// 실제로는 아래처럼 더미데이터를 만드는 것이 아닌, 쿼리스트링(질의문자열)로 받아온 bno(게시물고유번호)를 이용해서
// DB에서 SELECT * FROM tbl_board WHERE bno=? 실행이 된 결과값을 BoardVO형으로 받아서 jsp로 보내줌
BoardVO boardVO = new BoardVO();
boardVO.setBno(1);
boardVO.setTitle("첫번째 게시물입니다.");
String xss_data="첫번째 내용입니다.<br>줄바꿈 자리입니다.<script>alert('메롱')</script>";
boardVO.setContent(securityCode.unscript(xss_data));
boardVO.setWriter("admin");
Date regdate = new Date();
boardVO.setRegdate(regdate);
boardVO.setView_count(2);
boardVO.setReply_count(0);
model.addAttribute("boardVO", boardVO);
return "admin/board/board_view";
}
- ReplyController 생성
- REST-API 기술 사용하기 때문에 따로 controller 만들어준다.
package org.edu.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* ReplyController.java 클래스
* 댓글 구현 Rest-API 전용 Controller
*
* @author 이시은
*
*/
@RestController
public class ReplyController {
//댓글입력 메소드(아래)
@RequestMapping(value="/reply/reply_write", method=RequestMethod.POST)
public ResponseEntity<String> reply_write(){
ResponseEntity<String> responseEntity = new ResponseEntity<String>("OK", HttpStatus.OK);
//ResponseEntity는 json 텍스트를 반환하는데, (전송내용:"SUCCESS", HttpSatus.OK(200))
//(전송내용-e.getMessage()실페메세지값, 전송상태-HttpStatus.BAD_REQUEST(400))
return responseEntity;
}
//기존 @Controller의 메소드 반환값인 파일위치 대신에
//@RestController의 메소드의 반환값인 ResponseEntity는 json텍스트(body,전송상태값)로, Ajax로 호출한 jsp에 리턴보내게 된다.
}
3. board_write.jsp
- AdminController에 board_write 바인드 매핑 추가
@RequestMapping(value="/admin/board/board_write", method=RequestMethod.GET) //url경로
public String board_write () throws Exception {
return "admin/board/board_write";//파일경로
}
@RequestMapping(value="/admin/board/board_write", method=RequestMethod.POST)
public String board_write(MultipartFile file, BoardVO boardVO) throws Exception {
//POST로 받은 boardVO내용을 DB서비스에 입력하면 된다.
//DB에 입력 후 새로고침 명령으로 게시물테러를 당하지 않으려면 redirect로 이동 처리한다.(아래)
return "redirect:/admin/board/board_list";
}
- 첨부 파일 설정 servlet-context.xml 추가
<!-- html폼에서 첨부파일 업로드 설정 10메가 제한 -->
<beans:bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="10485760"></beans:property>
</beans:bean>
<!-- 업로드한 파일이 저장되는 위치: 로컬PC용 -->
<beans:bean id="uploadPath" class="java.lang.String">
<beans:constructor-arg value="C:\\egov\\workspace\\upload" />
</beans:bean>
'JAVA 기반 웹&앱 콘텐츠 융합 디지털 컨버전스 개발자 과정' 카테고리의 다른 글
[27일차] Service클래스 생성 및 CRUD 테스트 (0) | 2020.12.15 |
---|---|
[26일차] (0) | 2020.12.14 |
[24일차] Ajax 이용한 REST API방식의 댓글 기능 구현 (0) | 2020.12.10 |
[22일차] (0) | 2020.12.08 |
[21일차] (0) | 2020.12.07 |