[SpringMVC + MyBatis + Ajax] 게시판 댓글 추가/삭제/List (Ajax 이용)

결과

  • 기존 게시판 만드는 방법이 아닌 JSON을 사용하였다.
  • 기존에 만든 게시글 밑에 댓글 작성창 만들었다.
  • 댓글 작성창 아래 댓글 List가 보이도록 하였다.
  • 댓글 작성/삭제 시 바로 댓글 List에 반영되도록 하였고 Ajax를 사용하여 비동기 처리를 하였다.

 

 

 

 

 

 

 

 

 

Project Explorer

 

 

 

 

 

 

 

 

설정들

▶pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.spring</groupId>
	<artifactId>boardApp</artifactId>
	<name>boardProject</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>11</java-version>
		<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
		<org.aspectj-version>1.9.0</org.aspectj-version>
		<org.slf4j-version>1.7.25</org.slf4j-version>
		<jackson.version>2.9.5</jackson.version>

		<!-- add dependencies version DB start -->
		<org.springframework.jdbc-version>4.3.14.RELEASE</org.springframework.jdbc-version>
		<org.mybatis-version>3.4.6</org.mybatis-version>
		<org.mybatis.spring-version>1.3.2</org.mybatis.spring-version>
		<org.mysql.connector-version>8.0.27</org.mysql.connector-version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- JDBC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework.jdbc-version}</version>
		</dependency>

		<!-- myBatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${org.mybatis-version}</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>${org.mybatis.spring-version}</version>
		</dependency>

		<!-- MySql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${org.mysql.connector-version}</version>
		</dependency>

		<!-- MyBatis log -->
		<dependency>
			<groupId>org.lazyluke</groupId>
			<artifactId>log4jdbc-remix</artifactId>
			<version>0.2.7</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Resource 어노테이션 Java11부터 지원 X 따라서 따로 의존 추가 -->
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>

		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>${jackson.version}</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.version}</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>${jackson.version}</version>
		</dependency>


		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>
		
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>
		

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<additionalProjectnatures>
						<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
					</additionalProjectnatures>
					<additionalBuildcommands>
						<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
					</additionalBuildcommands>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2.1</version>
				<configuration>
					<mainClass>org.test.int1.Main</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

 

 

 

▶web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>


	<!-- request에 대한 한글처리 -->
	<filter>
		<filter-name>EncodingFilter</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>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

 

 

 

 

▶root-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:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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-3.1.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 -->

	  
	<context:property-placeholder location="classpath:/properties/database.properties" />
	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
		<property name="driverClass" value="${db.driver}" />
		<property name="url" value="${db.url}" />
		<property name="username" value="${db.username}" />
		<property name="password" value="${db.password}" />
	</bean>


	<!-- MyBatis 맵퍼의 SQL 문장에 대한 파라미터 및 리턴 타입을 담을 클래스를 검색 할 패키지 지정 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:mybatis-config.xml" />
		<property name="mapperLocations" value="classpath:mybatisMappers/*.xml" />
	</bean>

	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSessionFactory"></constructor-arg>
	</bean>
   
	
</beans>

 

 

 

 

▶database.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/{db name}
db.username={username}
db.password={password}

 

 

 

▶mybatis-config.xml

<?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:bean>
	
	<context:component-scan base-package="com.spring.boardapp" />
	
	
	
</beans:beans>

 

 

 

 

serlvet-context.xml

<?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:bean>
	
	<context:component-scan base-package="com.spring.boardapp" />
	
	
	
</beans:beans>

 

 

 

 

 

 

 

 

 

 

 

JSON 설정


https://yeo-computerclass.tistory.com/299 JSON 설정에 관한 자세한 내용을 보려면 이를 참고

 

위에 설정 코드에서 JSON 설정 부분만 설명하는 것이므로 넘겨도 된다.

 

pom.xml 추가

<properties> 태그에 추가

<jackson.version>2.9.5</jackson.version>

 

<dependency> 태그에 추가

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jackson.version}</version>
</dependency>    
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>    
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version}</version>
</dependency>

 

 

 

 

 

 

 

 

 

테이블 생성


▶board_reply (댓글)

CREATE TABLE board_reply(
reply_id BIGINT PRIMARY KEY AUTO_INCREMENT,
board_id BIGINT,
reply_content text NOT NULL,
reply_writer VARCHAR(30) NOT NULL,
reply_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
reply_updatetime DATETIME
);

ALTER TABLE board_reply ADD FOREIGN KEY(board_id) REFERENCES board(id);

 

 

 

 

 

 

 

 

DTO 생성

package com.spring.boardapp.domain;

public class Reply {
	private String reply_id;
    private String board_id;
    private String reply_content;
    private String reply_writer;
    private String reply_datetime;
    private String reply_updatetime;
    
    
	public String getReply_id() {
		return reply_id;
	}
	public void setReply_id(String reply_id) {
		this.reply_id = reply_id;
	}
	public String getBoard_id() {
		return board_id;
	}
	public void setBoard_id(String board_id) {
		this.board_id = board_id;
	}
	public String getReply_content() {
		return reply_content;
	}
	public void setReply_content(String reply_content) {
		this.reply_content = reply_content;
	}
	public String getReply_writer() {
		return reply_writer;
	}
	public void setReply_writer(String reply_writer) {
		this.reply_writer = reply_writer;
	}
	public String getReply_datetime() {
		return reply_datetime;
	}
	public void setReply_datetime(String reply_datetime) {
		this.reply_datetime = reply_datetime;
	}
	public String getReply_updatetime() {
		return reply_updatetime;
	}
	public void setReply_updatetime(String reply_updatetime) {
		this.reply_updatetime = reply_updatetime;
	}
}

 

 

 

 

Controller

package com.spring.boardapp.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.spring.boardapp.domain.Reply;
import com.spring.boardapp.service.ReplyService;

@RestController
@RequestMapping("/reply")
public class ReplyController {
	
	@Resource(name = "ReplyService")
	private ReplyService replyService;
	
	@PostMapping(value = "/new",
				consumes = "application/json",            //클라가 서버에 보내는 데이터 형식
				produces = {MediaType.TEXT_PLAIN_VALUE})  //서버가 클라에 보내는 데이터 형식
	public ResponseEntity<String> create(@RequestBody Reply reply){  //ResponseEntity: 응답 형태 보낼 수 있음
																	 //@RequestBody: 요청을 해당 타입으로 변환 여기선 (JSON->Reply)
		
		int insertResult = replyService.insertReply(reply);
		System.out.println("등록호출됨");
		
		return insertResult==1 ? new ResponseEntity<String>("success",HttpStatus.OK) :
							new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	@GetMapping(value = "/{board_id}",
				produces = {MediaType.APPLICATION_XML_VALUE,
							MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<List<Reply>> getReplyList(@PathVariable String board_id){
		return new ResponseEntity<List<Reply>>(replyService.getReplyList(board_id), HttpStatus.OK);
	}
	
	@RequestMapping(method = {RequestMethod.PUT, RequestMethod.PATCH},
					value="/{reply_id}",
					consumes = "application/json",
					produces = {MediaType.TEXT_PLAIN_VALUE})
	public ResponseEntity<String> modify(@RequestBody Reply reply, @PathVariable String reply_id){
		
		reply.setReply_id(reply_id); //요청 데이터 댓글 번호 처리
		System.out.println("수정 호출됨");
		
		return replyService.updateReply(reply) ? new ResponseEntity<String>("success",HttpStatus.OK) :
												new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	@DeleteMapping(value = "/{reply_id}",
					produces = {MediaType.TEXT_PLAIN_VALUE})
	public ResponseEntity<String> delete(@PathVariable String reply_id){
		
		return replyService.deleteReply(reply_id) ? new ResponseEntity<String>("success", HttpStatus.OK):
													new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	
}

 

 

 

 

DAO

▶인터페이스

package com.spring.boardapp.dao;

import java.util.List;
import java.util.Map;

import com.spring.boardapp.domain.Reply;

public interface ReplyDao {
	// 댓글 달기
	int insertReply(Reply reply);

	// 댓글 목록 출력
	List<Reply> getReplyList(String board_id);

	// 댓글 삭제
	int deleteReply(String reply_id);
}

 

 

▶Impl

package com.spring.boardapp.dao;

...

@Repository("ReplyDao")
public class ReplyDaoImpl implements ReplyDao {
	
	@Autowired
	SqlSession sqlSession;
	
	// 댓글
	@Override
	public int insertReply(Reply reply) {
		// TODO Auto-generated method stub
		return sqlSession.insert("insertReply", reply);
	}

	@Override
	public List<Reply> getReplyList(String board_id) {
		// TODO Auto-generated method stub
		return sqlSession.selectList("selectReply", board_id);
	}

	@Override
	public int deleteReply(String reply_id) {
		// TODO Auto-generated method stub
		return sqlSession.delete("deleteReply", reply_id);
	}
}

 

 

 

 

 

Service

▶인터페이스

package com.spring.boardapp.service;

import java.util.List;
import java.util.Map;

import com.spring.boardapp.domain.Reply;

public interface ReplyService {
	// 댓글 달기
	int insertReply(Reply reply);

	// 댓글 목록 출력
	List<Reply> getReplyList(String board_id);

	// 댓글 삭제
	boolean deleteReply(String reply_id);
}

 

 

▶impl

package com.spring.boardapp.service;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.spring.boardapp.dao.ReplyDao;
import com.spring.boardapp.domain.Reply;

@Service("ReplyService")
public class ReplyServiceImpl implements ReplyService {

	@Resource(name = "ReplyDao")
	private ReplyDao replyDao;

	@Override
	public int insertReply(Reply reply) {
		// TODO Auto-generated method stub
		return replyDao.insertReply(reply);
	}

	@Override
	public List<Reply> getReplyList(String board_id) {
		// TODO Auto-generated method stub
		return replyDao.getReplyList(board_id);
	}

	@Override
	public boolean deleteReply(String reply_id) {
		// TODO Auto-generated method stub
		if (replyDao.deleteReply(reply_id) == 1)
			return true;
		else
			return false;
	}
}

 

 

 

 

 

Ajax 처리 따로

view 페이지에서 직접 처리해도 되지만 코드가 번접해지기 때문에 따로 빼놓자!

 

▶reply.js

update : 댓글 수정을 원할 경우 추가
displayTime : 24시간 이내 시간으로만 표시 이후 날짜로 표시할 경우
현재 코드에서는 위 두 코드는 사용하지 않았다.
/**
 * 
 */
 console.log("Reply Module....");
 
 var replyService=(function(){
 	
 	function add(reply, callback, error){
 		console.log("Add Reply.........");
 		
 		$.ajax({
 			type : 'post',
 			url : '/reply/new',
 			data : JSON.stringify(reply),
 			contentType : "application/json; charset=utf-8",
 			success : function(result, status, xhr){
 				if(callback){
 					callback(result);
 				}
 			},
 			error : function(xhr, status, er){
 				if(error){
 					error(er);
 				}
 			}
 		})
 	}
 	
 	
 	function getList(param, callback, error){
 		var boardId = param.board_id;
 		
 		$.getJSON("/reply/" + boardId + ".json",
 			function(data){
 				if(callback){
 					callback(data);
 				}
 			}).fail(function(xhr, status, err){
 			if(error){
 				error();
 			}
 		});
 	}
 	
 	function update(reply, callback, error){
 	
 		console.log('reply_id: ' + reply.reply_id);
 		
 		$.ajax({
 			type : 'put',
 			url : '/reply/' + reply.reply_id,
 			data : JSON.stringify(reply),
 			contentType : "application/json; charset=utf-8",
 			success : function(result, status, xhr){
 				if(callback){
 					callback(result);
 				}
 			},
 			error : function(xhr, status, er){
 				if(error){
 					error(er);
 				}
 			}
 		});
 	}
 	
 	function remove(reply_id, callback, error){
 		$.ajax({
 			type : 'delete',
 			url : '/reply/' + reply_id,
 			success : function(deleteResult, status, xhr){
 				if(callback){
 					callback(deleteResult);
 				}
 			},
 			error : function(xhr, status, er){
 				if(error){
 					error(er);
 				}
 			}
 		});
 	}
 	
 	function displayTime(timeValue) {

		var today = new Date();

		var gap = today.getTime() - timeValue;

		var dateObj = new Date(timeValue);
		var str = "";

		if (gap < (1000 * 60 * 60 * 24)) {

			var hh = dateObj.getHours();
			var mi = dateObj.getMinutes();
			var ss = dateObj.getSeconds();

			return [ (hh > 9 ? '' : '0') + hh, ':', (mi > 9 ? '' : '0') + mi,
					':', (ss > 9 ? '' : '0') + ss ].join('');

		} else {
			var yy = dateObj.getFullYear();
			var mm = dateObj.getMonth() + 1; // getMonth() is zero-based
			var dd = dateObj.getDate();

			return [ yy, '/', (mm > 9 ? '' : '0') + mm, '/',
					(dd > 9 ? '' : '0') + dd ].join('');
		}
	};
 	
 	
 	
 	return {
 		add : add,
 		getList : getList,
 		update : update,
 		remove : remove,
 		displayTime : displayTime
 	};
 	
 })();

 

 

▶reply.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.spring.boardapp.dao.ReplyDao">
	<insert id="insertReply" parameterType="com.spring.boardapp.domain.Reply">
		INSERT INTO board_reply(
		board_id,
		reply_content,
		reply_writer
		)VALUES(
		#{board_id},
		#{reply_content},
		#{reply_writer}
		)
	</insert>
	<select id="selectReply" parameterType="String" resultType="Reply">
		SELECT *
		FROM board_reply
		WHERE board_id = #{board_id}
	</select>
	<delete id="deleteReply" parameterType="String">
		DELETE FROM board_reply
		WHERE reply_id = #{reply_id}
	</delete>
</mapper>

 

 

 

 

 

View

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- jquery -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
h1, h2 {
	text-align: center;
}

table {
	margin: auto;
}
</style>
<title>게시글(${board.id })</title>
</head>
<body>
	<h1>게시글(${board.id })</h1>
	
    	...

	<div style="width: 930px; margin: auto;">
		<br>
		
		<div style="border-radius: 7px; border: 2px solid; border-color: silver;  ">
			<div style="text-align: center;"><strong> Writer Reply </strong></div><br>
			<div>
				<label style="padding:15px">작성자</label><br>
				<input type="text" style="border-color: silver; border-radius: 15px;width:98%; height:40px; margin:10px; padding:10px" id="reply_writer" name="reply_writer" value="">
			</div>
			<br>
			<br>
			<div>
				<label style="padding:15px">내용</label><br>
				<textarea rows="" cols="" style="border-color: silver; border-radius: 15px; width:98%; height:80px; margin:10px; padding:10px" id="reply_content" name="reply_content" value=""></textarea>
<!-- 				<input type="text"style="border-color: silver; border-radius: 15px; width:98%; height:80px; margin:10px;" id="reply_content" name="reply_content" value="">	 -->
			</div>
				<br>
				<br>
			<div style="float:right; padding:10px;">
			<button id="registReplyBtn" style ="height:25px; border-radius: 20px;"">
				Register
			</button>
			</div>
				<br>
				<br>
		</div>
		<br>
		<br>
		<div>
			<ul class="chat" style="padding-left: 0px;">
			</ul>
		</div>
	</div>

	<button data-delete="hi"></button>

	<!-- 댓글 -->
	<script type="text/javascript" src="/resources/js/reply.js"></script>
	
	
	
	<script>
		$(document).ready(function() {

			var boardId = '<c:out value="${board.id}"/>';
			var replyUL = $(".chat"); //class 걸어놓는것
			
			showReplyList();

			function showReplyList() {

			replyService.getList(
				{
					board_id : boardId
				},
				function(list) {

					var str = "";
					
					if (list == null || list.length == 0) {
						replyUL.html("");
						return;
					}
					
					for (var i = 0, len = list.length || 0; i < len; i++) {
						str += "<li style='list-style:none; border-color: red; border: 1px solid;border-radius: 4px;'>";
					    str += "<div style='padding:10px'><strong>"+ list[i].reply_writer + "</strong><small style='float: right'>";
						str += list[i].reply_datetime + "</small></div><p style='padding:10px'>" + list[i].reply_content +"</p>";
						str += "<div><input type=button class='replyDeleteBtn'  data-delete='"+ list[i].reply_id + "' value='삭제'style='float:right; width:60px; height:30px; border-radius: 20px;'><br><br></div></li><br>";
					}
					

					replyUL.html(str);
					$("input:button.replyDeleteBtn").on('click',replyDeleteBtn)

				 });//end function
			}//end showList
			
			$('#registReplyBtn').click(function(){
				var registReplyWriter = document.getElementById('reply_writer').value.trim();
				var registReplyContent = document.getElementById('reply_content').value.trim();
				
				if(registReplyWriter == "" || registReplyContent == ""){
					alert("항목을 채워주세요");
					
				}
				else{
					var reply = {
							board_id : boardId,
							reply_writer : registReplyWriter,
							reply_content : registReplyContent
					};
					
					replyService.add(
							reply,
							function(result){
								alert(result);
								showReplyList();
								$('input[name=reply_writer]').attr('value',"");
							}
					);
					
				}
			})
			
			
			function replyDeleteBtn(){
				
				var replyId = $(this).attr("data-delete");
				
				replyService.remove(
					replyId, 
					function(result) {
						if(result==="success"){
							alert("REMOVED");
							showReplyList();
						}
					}, 
					function(err){
					alert('ERROR...');
				});
			}
			
		});
		
	</script>


</body>
</html>