728x90

지난 포스팅 [프로젝트 셋팅]에 이어 게시글 생성에 대한 구현 방법을 정리합니다.

게시글 생성을 위해 생성할 파일들은 다음과 같습니다.

BoardDTO - BoardController - BoardService (interface) - BoardServiceImpl (구현체) - BoardMapper - View (+ JS)

* 코드는 https://github.com/wmdwjddyd6/Board-Spring-MVC 에서 확인 가능합니다.

 

GitHub - wmdwjddyd6/Board-Spring-MVC

Contribute to wmdwjddyd6/Board-Spring-MVC development by creating an account on GitHub.

github.com

 


 

0.A 게시판 테이블 생성

CREATE TABLE `shoppingmall`.`tb_board` (
  `id` int AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `delete_yn` varchar(1) DEFAULT 'N',
  `create_date` datetime DEFAULT NULL,
  `views` int DEFAULT '0',
  `type` varchar(20) DEFAULT 'board',
  PRIMARY KEY (`id`)
)
  • id (게시글 번호) : 게시글 고유 번호 (PK)
  • delete_yn : 게시글 삭제 여부 (N: 삭제 안 된 상태, Y: 삭제 된 상태)
  • create_date : 게시글 생성 날짜
  • views : 조회수
  • type : 게시글 타입 (후에 기능의 확장을 위해 넣음. 자유게시판, 비밀게시판, 공지사항 등 분리 수단)

 

0.B servlet-context.xml 설정

	<context:component-scan base-package="com.spring.shoppingmall.controller" />
	<context:component-scan base-package="com.spring.shoppingmall.service" />
  • 다음 코드를 추가하여 @Component 어노테이션이 붙은 코드를 읽을 수 있도록 합니다. (@Service, @Controller 등 @Component에 포함)

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
		<beans:property name="contentType" value="text/html; charset=UTF-8"/>
	</beans:bean>
	
	<context:component-scan base-package="com.spring.shoppingmall.controller" />
	<context:component-scan base-package="com.spring.shoppingmall.service" />
	
</beans:beans>
  • servlet-context.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:aop="http://www.springframework.org/schema/aop"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/beans https://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
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- Root Context: defines shared resources visible to all other web components -->

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName"
			value="com.mysql.cj.jdbc.Driver"></property>
		<property name="url"
			value="jdbc:mysql://localhost:3306/shoppingmall?serverTimezone=Asia/Seoul">
		</property>
		<property name="username" value="root"></property>
		<property name="password" value="asdf1234"></property>
	</bean>

	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
	</bean>

	<mybatis-spring:scan base-package="com.spring.shoppingmall.mapper"/>
	
</beans>
  • root-context.xml 전체 코드
  • 현재는 DataBase를 위한 설정 코드가 대부분 (전 포스팅에서 설정했습니다.)

 

0.C View (write.jsp)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
	language="java"%>
<%@ page session="false"%>
<html>
<head>
<title>글쓰기</title>
</head>
<body>
	<h1>글쓰기 화면</h1>

	<form>
		제목 <br />
		<input size="120" type="text" id="title" name="title" /> <br /> <br />
		내용 <br />
		<textarea cols="100" rows="13" id="content" name="content"></textarea>
		<button type="button" id="write_btn">작성</button>
	</form>

	<a href="/">메인으로 돌아가기</a>

	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
	<script src="/resources/js/write.js"></script>
	
</body>
</html>
  • 제목과 내용을 담을 input 태그를 작성해줍니다.
  • button에 이벤트를 추가하기 위해 id를 지정해줍니다.
  • ajax사용을 위해 아래의 스크립트 코드를 삽입합니다.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

 

1. BoardDTO ( +DataBase)

@Data
@Getter
@Setter
public class BoardDTO {
	private Long id;
	private String title;
	private String content;
	private String deleteYn;
	private Timestamp createDate;
	private Long views;
	private String type;
}
  • Board테이블에 생성한 컬럼들을 변수로 선언해줍니다.

 

2.. BoardController

@Controller
public class BoardController {

	private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
	
	@Autowired
	private BoardService boardService;
	
	/*
	 * 게시글 작성 화면 이동
	 * */
	@RequestMapping(method = RequestMethod.GET, value = "/board/write")
	public String writeForm(Model model) {
		return "board/write";
	}
	
	/*
	 * 게시글 작성
	 */
	@ResponseBody
	@RequestMapping(method = RequestMethod.POST, value = "/board")
	public int write(Model model, @RequestBody BoardDTO boardDTO) {
		logger.debug("게시글 작성 호출");

		int result = 0;
		result = boardService.write(boardDTO);
		logger.debug("result is {}", result);

		return result;
	}
}
  • GET 요청은 게시글 작성 화면으로 이동하고, POST 요청은 게시글 등록 로직을 수행합니다.
  • boardService.write()를 통해 로직을 수행합니다.
  • @RequestBody로 JSON 데이터를 받아 BoardDTO객체를 생성 및 초기화합니다. (@RequestParam은 url을 통해 값을 받아오기 때문에 해당 작업에 사용하지 않음)

 

3. BoardService

public interface BoardService {
	
	// 게시글 작성
	int write(BoardDTO boardDTO);
}
@Service
public class BoardServiceImpl implements BoardService {

	@Autowired
	private BoardMapper boardMapper;
	
	@Override
	public int write(BoardDTO boardDTO) {
		boardDTO.setCreateDate(Timestamp.valueOf(LocalDateTime.now()));
		boardDTO.setType("board");
        
		return boardMapper.insertBoard(boardDTO);
	}
}
  • Controller에서 받은 boardDTO에 나머지 설정할 값을 setter를 통해 설정합니다.
  • MyBatis를 이용하여 Mysql에 데이터를 추가하기 위해 boardMapper.insertBoard()를 호출합니다.

 

4. Mapper

public interface BoardMapper {
	public int insertBoard(BoardDTO boardDTO);
}
  • 게시글 관련 Mapper를 생성하고, 게시글 생성 쿼리를 작성할 메서드를 정의합니다.

 

<?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.spring.shoppingmall.mapper.BoardMapper">

	<sql id="boardColumns">
		id
		,title
		,content
		,delete_yn
		,create_date
		,views
		,type
	</sql>


	<!--게시글 작성 -->
	<insert id="insertBoard" parameterType="com.spring.shoppingmall.model.BoardDTO">
		
		INSERT INTO
			tb_board (title, content, create_date, type)
		VALUES
			(#{title}, #{content}, #{createDate}, #{type})
			
	</insert>
</mapper>
  • 이전 포스팅에서 생성했던 BoardMapper.xml을 수정해서 사용합니다.
  • namespace랑 parameterType 등 패키지 명에 주의!
  • 해당 구문이 정상 실행되면 결과값으로 1이 나오고, 실패 시 0이 나옵니다.

 

5. js 코드 (ajax 요청)

var writeBtn = document.getElementById("write_btn").addEventListener("click", write);

function write() {
    var title = document.getElementById("title").value;
    var content = document.getElementById("content").value;
    var data = { "title": title, "content": content };

    $.ajax({
        contentType: 'application/json',
        type: "POST",
        url: "/board",
        data: JSON.stringify(data),
        success: function (response) {
            console.log("성공 : " + response);
            // location.href="list"; (성공 시 /board/list.jsp로 이동)
        },
        error: function (response) {
            console.log("실패 : " + response);
            console.log(response);
        }
    })
}
  • 작성 버튼 클릭 시 이벤트를 추가하기 위해 addEventListener를 사용합니다.
  • title과 content 값을 가져오고 ajax를 통해 /board/write url로 POST 요청을 보냅니다.
  • 서버와 통신에 성공(요청에 대한 응답이 제대로 왔을 때)하면 success, 실패하면 error의 response로 응답 값이 들어옵니다.
  • 서버의 Controller와 통신 성공 시 응답 받은 값은 1 또는 0일테니 이를 이용해서 수행할 동작을 정의 가능
  • location.href를 통해 게시글 등록 성공 시 이동 할 페이지를 지정 가능합니다.
  • JSON타입으로 데이터를 주고받기 위해 contentType은 json으로 맞춰주고, JSON.stringify를 사용하여 JSON 문자열로 변환하여 서버에 데이터를 전달합니다.

 

 


 

구현 중 겪은 에러 참고 ^-'

https://black-mint.tistory.com/74

 

[Spring] org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class

ajax를 이용하여 게시글 등록 구현 중 에러가 발생했습니다. 게시글 등록 요청 시 database에 입력은 잘 되지만 ajax요청의 응답으로 success구문이 실행돼야 하는데 아래의 error 부분 구문이 실행되던

black-mint.tistory.com

 

+ Recent posts