스프링 컨트롤러 이용하기 복습)
web.xml 에 정보 등록
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
</init-param>
</servlet>
위 코드를 통해 presentation-layer.xml 에 컨트롤러, 핸들러, 뷰리저버 정보를 저장한다고 정보를 등록한다.
프론트 컨트롤러 DAO 에 직접 접근이 아니라
비즈니스 계층을 통해 액션 컨트롤러로 접근하는 방식으로 수정
스프링컨테이너 안에 보더 서비스, 보더 컨테이너
보더 서비스를 보더 컨테이너 안에 주입.
프론트 컨트롤러의 요청에 의해서 보더컨테이너는 보더 서비스를 오토와이어
BoardController.java
package com.springbook.view.board;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음
// 자동의존주입 방식으로 정보 주입
@Autowired
// private BoardDAO boardDAO;
private BoardService boardService;
// @ModelAttribute 의 특징
// @RequestMapping 메소드가 실행 되기 전에 실행된다.
// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다.
// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다.
@ModelAttribute("conditionMap") // ("") <- View 페이지에서 사용할 이름
public Map<String, String> searchConditionMap() {
Map<String, String> conditionMap = new HashMap<>();
conditionMap.put("제목", "TITLE");
conditionMap.put("내용", "CONTENT");
return conditionMap;
}
// 글 등록
@RequestMapping(value = "/insertBoard.do")
public String insertBoard(BoardVO vo) {
//boardDAO.insertBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 수정
// @ModelAttribute("board")으로 정보를 가지고 온다
// @SessionAttributes("board")와 실제 같은 값
// 수정한 정보는 vo에 들어있다.
// 한번 들어온 객체들을 넣어두고
// 수정된 title, content는 나중에 처리
// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
@RequestMapping(value = "/updateBoard.do")
public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
System.out.println(vo.getSeq());
System.out.println(vo.getTitle());
System.out.println(vo.getWriter());
System.out.println(vo.getContent());
System.out.println(vo.getRegDate());
System.out.println(vo.getCnt());
//boardDAO.updateBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 삭제
@RequestMapping(value = "/deleteBoard.do")
public String deleteBoard(BoardVO vo) {
//boardDAO.deleteBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 상세조회
@RequestMapping(value = "/getBoard.do")
public String getBoard(BoardVO vo, Model model) {
model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
return "getBoard.jsp";
}
// 글 목록 검색
// 커멘드 객체인 경우
@RequestMapping(value = "/getBoardList.do")
public String getBoardList(BoardVO vo, Model model) {
model.addAttribute("boardList", boardService.getBoardList(vo));
return "getBoardList.jsp";
}
}
이렇게 하고 실행하면 실행되지 않음.
BoardController의 ‘private BoardService boardService;’ 가 생성되지 않았기 때문.
web.xml 에 추가해야 ‘private BoardService boardService;’ 를 읽어올 수 있다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
이렇게 하고 index.jsp를 실행하면 실행이 잘 된다.
‘springJDBC로 getBoardList() 기능 처리’ 라는 메세지도 출력된다.
메모리에 할당되는 시점 때문에 web.xml에 저렇게 세팅을 해두지 않으면 정상적으로 작동되지 않는다.
원래 컨트롤러에서는 직접 DAO를 커멘드 객체로 만들었다.
이걸 다 지우고 비즈니스 계층으로 만듦. 다형성을 이용하기 위한 것.
기존의 방식으로 하면 수정, 유지보수가 어렵다. DAO를 쓴 부분을 다 수정해야 하기 때문이다.
BoardComtroller.java
// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음
// 자동의존주입 방식으로 정보 주입
@Autowired
// private BoardDAO boardDAO;
private BoardService boardService;
이렇게 비즈니스 계층을 만듦으로서 유지 보수가 용이해진다.
수정된 전체 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<!-- 한글깨짐 방지 -->
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
검색기능 구현
내용이나 제목으로 검색하면 그에 맞는 목록이 검색되게 해야 한다.
BoardDAO.java
package com.springbook.biz.board.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.common.JDBCUtil;
@Repository("boardDAO")
public class BoardDAO {
private Connection conn = null;
private PreparedStatement stmt = null;
private ResultSet rs = null;
// SQL 명령어
// 상수형태로 만들어 두었다.
private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";
private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete board where seq=?";
private final String BOARD_GET = "select * from board where seq=?";
private final String BOARD_LIST = "select * from board order by seq desc";
// 검색기능
private final String BOARD_LIST_T = "select * from board where title like '%'||?||'%' order by seq desc";
private final String BOARD_LIST_C = "select * from board where content like '%'||?||'%' order by seq desc";
// 글 등록
public void insertBoard(BoardVO vo) {
System.out.println("===> JDBC로 insertBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_INSERT);
stmt.setString(1, vo.getTitle());
stmt.setString(2, vo.getWriter());
stmt.setString(3, vo.getContent());
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(stmt, conn);
}
}
// 글 수정
public void updateBoard(BoardVO vo) {
System.out.println("===> JDBC로 updateBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_UPDATE);
stmt.setString(1, vo.getTitle());
stmt.setString(2, vo.getContent());
stmt.setInt(3, vo.getSeq());
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(stmt, conn);
}
}
// 글 삭제
public void deleteBoard(BoardVO vo) {
System.out.println("===> JDBC로 deleteBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_DELETE);
stmt.setInt(1, vo.getSeq());
stmt.executeUpdate();
} catch (Exception e){
e.printStackTrace();
} finally {
JDBCUtil.close(stmt, conn);
}
}
// 글 상세 조회
public BoardVO getBoard(BoardVO vo) {
BoardVO board = new BoardVO();
System.out.println("===> JDBC로 getBoard() 상세 보기 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_GET);
stmt.setInt(1, vo.getSeq());
rs = stmt.executeQuery();
if (rs.next()) {
board.setSeq(rs.getInt("SEQ"));
board.setTitle(rs.getString("TITLE"));
board.setWriter(rs.getString("WRITER"));
board.setContent(rs.getString("CONTENT"));
board.setRegDate(rs.getDate("REGDATE"));
board.setCnt(rs.getInt("CNT"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(rs, stmt, conn);
}
return board;
}
// 글 목록 조회
public List<BoardVO> getBoardList(BoardVO vo) {
System.out.println("==> JDBC로 getBoardList() 기능 처리");
List<BoardVO> boardlist = new ArrayList<>();
try {
conn = JDBCUtil.getConnection();
// 검색 기능
if (vo.getSearchCondition().equals("TITLE")) {
stmt = conn.prepareStatement(BOARD_LIST_T);
} else if (vo.getSearchCondition().equals("CONTENT")) {
stmt = conn.prepareStatement(BOARD_LIST_C);
}
stmt.setString(1, vo.getSearchKeyword());
rs = stmt.executeQuery();
while (rs.next()) {
BoardVO board = new BoardVO();
board.setSeq(rs.getInt("SEQ"));
board.setTitle(rs.getString("TITLE"));
board.setWriter(rs.getString("WRITER"));
board.setContent(rs.getString("CONTENT"));
board.setRegDate(rs.getDate("REGDATE"));
board.setCnt(rs.getInt("CNT"));
boardlist.add(board);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(stmt, conn);
}
return boardlist;
}
}
BoardDAOSpring.java - 실질적으로 현재 연결된 DAO
package com.springbook.biz.board.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.springbook.biz.board.BoardVO;
// 비즈니스 계층에서 사용할 수 있도록 빈에 등록
@Repository
public class BoardDAOSpring {
@Autowired
private JdbcTemplate jdbcTemplate;
// 상수형태로 만들어 두었다.
private final String BOARD_INSERT = " insert into board(seq, title, writer, content) values "
+ " ((select nvl(max(seq),0) + 1 from board), ?, ?, ?)";
private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete board where seq=?";
private final String BOARD_GET = "select * from board where seq=?";
private final String BOARD_LIST = "select * from board order by seq desc";
// 검색기능
private final String BOARD_LIST_T = "select * from board where title like '%'||?||'%' order by seq desc";
private final String BOARD_LIST_C = "select * from board where content like '%'||?||'%' order by seq desc";
// ---------- update() 구문 사용 ----------
// 글 등록
public void insertBoard(BoardVO vo) {
System.out.println("===> springJDBC로 insertBoard() 기능 처리");
// insert를 springJDBC에서는 update가 처리, try catch문 사용 안해도 됨.
// 기존 jdbc 에서 사용한 '?' 대신 순서대로 객체를 가지고 와 적어준다.
// jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
}
// 글 수정
public void updateBoard(BoardVO vo) {
System.out.println("===> springJDBC로 updateBoard() 기능 처리");
jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
}
// 글 삭제
public void deleteBoard(BoardVO vo) {
System.out.println("===> springJDBC로 deleteBoard() 기능 처리");
jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
}
// ---------- queryForObject(), query() 구문 사용 ----------
// 글 상세 조회
public BoardVO getBoard(BoardVO vo) {
System.out.println("===> springJDBC로 getBoard() 상세 보기 처리");
// 배열로 값을 받기 때문에 배열에 넣어준다
Object[] args= {vo.getSeq()};
// return jdbcTemplate.queryForObject(sql, args, rowMapper);
return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
}
// 글 목록 조회
public List<BoardVO> getBoardList(BoardVO vo) {
System.out.println("==> springJDBC로 getBoardList() 기능 처리");
Object[] args = {vo.getSearchKeyword()};
if (vo.getSearchCondition().equals("TITLE")) {
return jdbcTemplate.query(BOARD_LIST_T, args, new BoardRowMapper());
} else if (vo.getSearchCondition().equals("CONTENT")) {
return jdbcTemplate.query(BOARD_LIST_C, args, new BoardRowMapper());
}
return null;
}
}
BoardController.java
package com.springbook.view.board;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음
// 자동의존주입 방식으로 정보 주입
@Autowired
private BoardService boardService;
// @ModelAttribute 의 특징
// @RequestMapping 메소드가 실행 되기 전에 실행된다.
// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다.
// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다.
@ModelAttribute("conditionMap") // ("") <- View 페이지에서 사용할 이름
public Map<String, String> searchConditionMap() {
Map<String, String> conditionMap = new HashMap<>();
conditionMap.put("제목", "TITLE");
conditionMap.put("내용", "CONTENT");
return conditionMap;
}
@RequestMapping(value = "/insertBoard.do")
public String insertBoard(BoardVO vo) {
//boardDAO.insertBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 수정
// @ModelAttribute("board")으로 정보를 가지고 온다
// @SessionAttributes("board")와 실제 같은 값
// 수정한 정보는 vo에 들어있다.
// 한번 들어온 객체들을 넣어두고
// 수정된 title, content는 나중에 처리
// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
@RequestMapping(value = "/updateBoard.do")
public String updateBoard(@ModelAttribute("board") BoardVO vo) {
System.out.println(vo.getSeq());
System.out.println(vo.getTitle());
System.out.println(vo.getWriter());
System.out.println(vo.getContent());
System.out.println(vo.getRegDate());
System.out.println(vo.getCnt());
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 삭제
@RequestMapping(value = "/deleteBoard.do")
public String deleteBoard(BoardVO vo) {
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 상세조회
@RequestMapping(value = "/getBoard.do")
public String getBoard(BoardVO vo, Model model) {
model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
return "getBoard.jsp";
}
// 글 목록 검색
// 커멘드 객체인 경우
@RequestMapping(value = "/getBoardList.do")
public String getBoardList(BoardVO vo, Model model) {
if(vo.getSearchCondition() == null) {
vo.setSearchCondition("TITLE");
}
if(vo.getSearchKeyword() == null) {
vo.setSearchKeyword("");
}
model.addAttribute("boardList", boardService.getBoardList(vo));
return "getBoardList.jsp";
}
}
getBoardList.jsp 에서 searchCondition 스펠링 수정, BoardVO에서도 수정해줬다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import="com.springbook.biz.board.*"%>
<%@page import="com.springbook.biz.board.impl.*"%>
<%@page import="java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<% %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<center>
<h1>글 목록</h1>
<h3>
${userName }님! 게시판에 오신 걸 환영합니다! <a href="logout.do">log-out</a>
</h3>
<form action="getBoardList.do" method="post">
<table border="1" cellpadding="0" cellspacing="0" width="700">
<tr>
<td align="right">
<select name="searchCondition">
<c:forEach items="${conditionMap }" var="option">
<option value="${option.value }">${option.key }
</c:forEach>
</select>
<input name="searchKeyword" type="text" />
<input type="submit" value="검색" /></td>
</tr>
</table>
</form>
<table border="1" cellpadding="0" cellspacing="0" width="700">
<tr>
<th bgcolor="orange" width="100">번호</th>
<th bgcolor="orange" width="200">제목</th>
<th bgcolor="orange" width="150">작성자</th>
<th bgcolor="orange" width="150">등록일</th>
<th bgcolor="orange" width="100">조회수</th>
</tr>
<c:forEach items="${boardList }" var="board">
<tr>
<td>${board.seq }</td>
<td><a href="getBoard.do?seq=${board.seq }"> ${board.title }</a>
</td>
<td>${board.writer }</td>
<td>${board.regDate }</td>
<td>${board.cnt}</td>
</tr>
</c:forEach>
</table>
<br> <a href="insertBoard.jsp">새글 등록</a>
</center>
</body>
</html>
BoardVO.java
package com.springbook.biz.board;
import java.util.Date;
public class BoardVO {
private int seq;
private String title;
private String writer;
private String content;
private Date regDate;
private int cnt;
private String searchCondition;
private String searchKeyword;
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getRegDate() {
return regDate;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public int getCnt() {
return cnt;
}
public void setCnt(int cnt) {
this.cnt = cnt;
}
public String getSearchCondition() {
return searchCondition;
}
public void setSearchCondition(String searchCondition) {
this.searchCondition = searchCondition;
}
public String getSearchKeyword() {
return searchKeyword;
}
public void setSearchKeyword(String searchKeyword) {
this.searchKeyword = searchKeyword;
}
@Override
public String toString() {
return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ", content=" + content + ", regDate="
+ regDate + ", cnt=" + cnt + "]";
}
}
파일 업로드, 다운로드
insertBoard에 파일을 업로드할 수 있는 부분을 추가
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<center>
<h1>글 등록</h1>
<a href="logout.do">Log-out</a>
<hr>
<form action="insertBoard.do" method="post" enctype="multipart/form-data">
<table border="1" callpadding="0" cellspacing="0">
<tr>
<td bgcolor="orange" width="70">제목</td>
<td align="left"><input type="text" name="title" /></td>
</tr>
<tr>
<td bgcolor="orange">작성자</td>
<td align="left"><input type="text" name="writer" size="10" /></td>
</tr>
<tr>
<td bgcolor="orange">내용</td>
<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
</tr>
<tr>
<td bgcolor="orange" width="70">업로드</td>
<td align="left">
<input type="file" name="uploadFile"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="새 글 등록" />
</td>
</tr>
</table>
</form>
<hr>
<a href="getBoardList.do">글 목록 가기</a>
</center>
</body>
</html>
파일 업로드 라이브러리 common fileupload 사용
BoardWeb/pom.xml에 추가
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
presentation-layer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 스캔태그를 사용해서 스캔처리, 모두 어노테이션으로 해결 -->
<context:component-scan base-package="com.springbook.view"></context:component-scan>
<!-- 파일업로드 빈 설정, 빈 등록 시 id는 스프링이 읽을 수 있는 방식으로 정해져 있다.-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000"></property>
</bean>
</beans>
BoardVO.java
getOriginalFilename(), transferTo(), isEmpyt() 메소드를 사용해 파일 업로드
package com.springbook.biz.board;
import java.util.Date;
import org.springframework.web.multipart.MultipartFile;
public class BoardVO {
private int seq;
private String title;
private String writer;
private String content;
private Date regDate;
private int cnt;
private String searchCondition;
private String searchKeyword;
// 파일 변수를 담는 멤버변수
// web.xml의 빈에서 값을 할당해준다
private MultipartFile uploadFile; // getOriginalFilename(), transferTo(), isEmpyt()
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getRegDate() {
return regDate;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public int getCnt() {
return cnt;
}
public void setCnt(int cnt) {
this.cnt = cnt;
}
public String getSearchCondition() {
return searchCondition;
}
public void setSearchCondition(String searchCondition) {
this.searchCondition = searchCondition;
}
public String getSearchKeyword() {
return searchKeyword;
}
public void setSearchKeyword(String searchKeyword) {
this.searchKeyword = searchKeyword;
}
public MultipartFile getUploadFile() {
return uploadFile;
}
public void setUploadFile(MultipartFile uploadFile) {
this.uploadFile = uploadFile;
}
@Override
public String toString() {
return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ", content=" + content + ", regDate="
+ regDate + ", cnt=" + cnt + "]";
}
}
BoardController.java
package com.springbook.view.board;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음
// 자동의존주입 방식으로 정보 주입
@Autowired
// private BoardDAO boardDAO;
private BoardService boardService;
// @ModelAttribute 의 특징
// @RequestMapping 메소드가 실행 되기 전에 실행된다.
// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다.
// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다.
@ModelAttribute("conditionMap") // ("") <- View 페이지에서 사용할 이름
public Map<String, String> searchConditionMap() {
Map<String, String> conditionMap = new HashMap<>();
conditionMap.put("제목", "TITLE");
conditionMap.put("내용", "CONTENT");
return conditionMap;
}
// 글 등록
@RequestMapping(value = "/insertBoard.do")
public String insertBoard(BoardVO vo) throws IllegalStateException, IOException { // BoardVO vo가 커멘드 객체
//boardDAO.insertBoard(vo);
// 파일 업로드
MultipartFile uploadFile = vo.getUploadFile();
if (!uploadFile.isEmpty()) {
String fileName = uploadFile.getOriginalFilename();
uploadFile.transferTo(new File("c://work//uploads//" + fileName)); // 파일 위치 경로
}
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 수정
// @ModelAttribute("board")으로 정보를 가지고 온다
// @SessionAttributes("board")와 실제 같은 값
// 수정한 정보는 vo에 들어있다.
// 한번 들어온 객체들을 넣어두고
// 수정된 title, content는 나중에 처리
// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
@RequestMapping(value = "/updateBoard.do")
public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
System.out.println(vo.getSeq());
System.out.println(vo.getTitle());
System.out.println(vo.getWriter());
System.out.println(vo.getContent());
System.out.println(vo.getRegDate());
System.out.println(vo.getCnt());
//boardDAO.updateBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 삭제
@RequestMapping(value = "/deleteBoard.do")
public String deleteBoard(BoardVO vo/* , BoardDAO boardDAO */) {
//boardDAO.deleteBoard(vo);
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 상세조회
@RequestMapping(value = "/getBoard.do")
public String getBoard(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
return "getBoard.jsp";
}
// 글 목록 검색
// 커멘드 객체인 경우
@RequestMapping(value = "/getBoardList.do")
public String getBoardList(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
if(vo.getSearchCondition() == null) {
vo.setSearchCondition("TITLE");
}
if(vo.getSearchKeyword() == null) {
vo.setSearchKeyword("");
}
model.addAttribute("boardList", boardService.getBoardList(vo));
return "getBoardList.jsp";
}
// 글 목록 검색
// 커멘드 객체가 아닌 경우
/*
* @RequestMapping(value = "/getBoardList.do") public String
* getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
* "TITLE",required = false) String condition,
*
* @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
* false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
*
* System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
* keyword);
*
* model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
* "getBoardList.jsp"; }
*/
}
파일이 업로드 된다. 추가적으로 업로드 된 파일 확인 등은 스스로 추가해볼 것.
이번 주까지 스프링 마무리하고 스프링 부트 나갈 것.
스프링 부트 : 스프링으로 애플리케이션을 만들 때 필요한 설정을 간편하게 처리해주는 별도의 프레임워크
다음 달 초, 조가 나온다. 디자인부터 시작.
데이터 변환
jackson 라이브러리를 사용해서 제이슨 형태로 데이터 받기
BoardWeb/pom.xml에 추가
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.7</version>
</dependency>
presentation-layer.xml 에서 Namespace에 들어가 mvc 체크하기
presentation-layer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 스캔태그를 사용해서 스캔처리, 모두 어노테이션으로 해결 -->
<context:component-scan base-package="com.springbook.view"></context:component-scan>
<!-- HttpMessageConverter를 구현한 모든 변환기가 생성된다 -->
<!-- 자바객체를 JSON응답 보디로 변환할 때는 MappingJackson2HttpMessageConverter를 사용한다 -->
<!-- 스프링 컨테이너가 어노테이션 처리를 해준다, 우리가 직접 MappingJackson2HttpMessageConverter을 사용하는 것이 아님.-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 파일업로드 빈 설정, 빈 등록 시 id는 스프링이 읽을 수 있는 방식으로 정해져 있다.-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000"></property>
</bean>
</beans>
제이슨 형식으로 글 목록을 변환 받은 것을 보기 위해 index.jsp에 a 태그를 추가했다.
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<center>
<h1>게시판 프로그램</h1>
<hr>
<a href="login.do">로그인</a>
<br>
<br>
<a href="getBoardList.do">글 목록 바로가기</a>
<br>
<br>
<a href="dataTransform.do">글 목록 변환</a>
<hr>
</center>
</body>
</html>
BoardController.java
package com.springbook.view.board;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
//import com.springbook.biz.board.impl.BoardDAO;
@Controller // web.xml에 있는 프론트컨트롤러를 읽어준다
@SessionAttributes("board") // 저장할 때 "board"라는 이름의 객체가 있으면 session 영역에 저장
public class BoardController {
// 통합 컨트롤러
// 변수 선언 - 변수만 선언해서는 아무 정보도 가지고 올 수 없음
// 자동의존주입 방식으로 정보 주입
@Autowired
// private BoardDAO boardDAO;
private BoardService boardService;
// 글 목록 JSON으로 변환
@RequestMapping(value = "/dataTransform.do")
// @ResponseBody 어노테이션을 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하며 클라이언트로 전송한다
@ResponseBody // 자바형식을 제이슨형식으로 바꿔달라고 요청
public List<BoardVO> dataTransform(BoardVO vo){
vo.setSearchCondition("TITLE");
vo.setSearchKeyword("");
List<BoardVO> boardList = boardService.getBoardList(vo);
return boardList;
}
// @ModelAttribute 의 특징
// @RequestMapping 메소드가 실행 되기 전에 실행된다.
// @ModelAttribute 메소드의 실행 결과로 리턴되어지는 객체는 자동으로 Model에 저장된다.
// @ModelAttribute 메소드의 실행을 View페이지에서 사용할 수 있다.
@ModelAttribute("conditionMap") // ("") <- View 페이지에서 사용할 이름
public Map<String, String> searchConditionMap() {
Map<String, String> conditionMap = new HashMap<>();
conditionMap.put("제목", "TITLE");
conditionMap.put("내용", "CONTENT");
return conditionMap;
}
// 글 등록
@RequestMapping(value = "/insertBoard.do")
public String insertBoard(BoardVO vo) throws IllegalStateException, IOException { // BoardVO vo가 커멘드 객체
//boardDAO.insertBoard(vo);
// 파일 업로드
MultipartFile uploadFile = vo.getUploadFile();
if (!uploadFile.isEmpty()) {
String fileName = uploadFile.getOriginalFilename();
uploadFile.transferTo(new File("c://work//uploads//" + fileName)); // 파일 위치 경로
}
boardService.insertBoard(vo);
return "redirect:getBoardList.do";
}
// 글 수정
// @ModelAttribute("board")으로 정보를 가지고 온다
// @SessionAttributes("board")와 실제 같은 값
// 수정한 정보는 vo에 들어있다.
// 한번 들어온 객체들을 넣어두고
// 수정된 title, content는 나중에 처리
// 전체 데이터를 null 데이터 없이 넘겨 처리하기 위해선 이렇게 사용해야 한다.
@RequestMapping(value = "/updateBoard.do")
public String updateBoard(@ModelAttribute("board") BoardVO vo/* , BoardDAO boardDAO */) {
System.out.println(vo.getSeq());
System.out.println(vo.getTitle());
System.out.println(vo.getWriter());
System.out.println(vo.getContent());
System.out.println(vo.getRegDate());
System.out.println(vo.getCnt());
//boardDAO.updateBoard(vo);
boardService.updateBoard(vo);
return "redirect:getBoardList.do";
}
// 글 삭제
@RequestMapping(value = "/deleteBoard.do")
public String deleteBoard(BoardVO vo/* , BoardDAO boardDAO */) {
//boardDAO.deleteBoard(vo);
boardService.deleteBoard(vo);
return "redirect:getBoardList.do";
}
// 글 상세조회
@RequestMapping(value = "/getBoard.do")
public String getBoard(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
model.addAttribute("board", boardService.getBoard(vo)); // model은 request 영역에 저장
return "getBoard.jsp";
}
// 글 목록 검색
// 커멘드 객체인 경우
@RequestMapping(value = "/getBoardList.do")
public String getBoardList(BoardVO vo/* , BoardDAO boardDAO */, Model model) {
if(vo.getSearchCondition() == null) {
vo.setSearchCondition("TITLE");
}
if(vo.getSearchKeyword() == null) {
vo.setSearchKeyword("");
}
model.addAttribute("boardList", boardService.getBoardList(vo));
return "getBoardList.jsp";
}
// 글 목록 검색
// 커멘드 객체가 아닌 경우
/*
* @RequestMapping(value = "/getBoardList.do") public String
* getBoardList(@RequestParam(value = "searchCondtion",defaultValue =
* "TITLE",required = false) String condition,
*
* @RequestParam(value = "searchKeyword",defaultValue = "CONTENT",required =
* false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) {
*
* System.out.println("검색 조건" + condition); System.out.println("검색 단어" +
* keyword);
*
* model.addAttribute("boardList", boardDAO.getBoardList(vo)); return
* "getBoardList.jsp"; }
*/
}
맥북에도 스프링을 깔고 기존에 쓴 코드들을 다 가지고 왔다.
실행해보니 글이 삭제되지 않아서 보니까 BoardController에 오타가 있어서 수정했다.
휴 다행.. 이제 파일 업로드를 할 경로를 설정하고 폴더도 만들어야 한다.
'2024_UIUX 국비 TIL' 카테고리의 다른 글
UIUX _국비과정 0726 [🍀MyBatis] (0) | 2024.08.22 |
---|---|
UIUX _국비과정 0725 [스프링 JSON형식변환, 페이징 추가, MyBatis] (0) | 2024.08.21 |
UIUX _국비과정 0723 [스프링 컨트롤러 사용하기] (0) | 2024.08.19 |
UIUX _국비과정 0722 [웹소켓 채팅, 스프링 컨트롤러 사용하기] (0) | 2024.07.31 |
UIUX _국비과정 0719 [스프링 model2방식 웹만들기] (0) | 2024.07.30 |