TIL/academy

국비 TIL(Today I Learned) 20220823 한줄 게시판(댓글) 만들기

토희 2022. 8. 23. 17:06
728x90

multipart: 파일을 포함한 데이터

여기에 밑에 내용이 있음

maxUploadSize 한번에 올릴수있는 사이즈

지금은 10메가가 좀 안될거임

 

multipartResolver : 올릴수 있는 파일에 대한 허용을 걸어둔거임

ajaxForm을 통해 submit으로 하게되면 스프링으로 넘어왔을때 multipartResolver작동,

0은 안 걸려짐, 최대크기가 지정가능

 

viewResolver도 있음? 찾아보기!!!!

https://galid1.tistory.com/527

 

SpringMVC - Spring MVC 동작원리 - 5 (ViewResolver, DispatcherServlet 기본전략 등록 과정)

DispatcherServlet의 initViewResolver SpringBoot나 이미 설정되어있는 Spring을 사용하신 분들은 위와같이 Controller의 handler들에서 간단히 view(문자열)이름만을 반환하면 사용자에게 해당 view가 보이게..

galid1.tistory.com

 

 

 

한줄 게시판! 댓글

 

테이블 생성먼저

 

 

controller 만듬

 

 

jsp

기본셋팅, 코어태그, 제이쿼리, css가져오기

 

cotroller에 action작성하고

 

OB_SQL.xml

 

 

 

슬림 스크롤

 

main.jsp 기존 로그인관련

 

오늘 새로 만든파일들

ob.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{ 
	width: 800px; 
	margin: 0 auto;
}
.mtb{
	margin: 5px;
}
.login{
	vertical-align: baseline;
}
.con{
	width: calc(100% - 22px); 
	height: 60px; 
	border: 1px solid #d7d7d7; 
	resize: none; 
	padding: 10px
}

.update{
	display: none;
}
.con_td{
	font-size: 0
}
.paging_area{
	display: block; 
	position: relative; 
	left: 0;
	margin-bottom: 10px;
}
.search_area{
	text-align: center;
}
body {
	overflow: auto;
}
</style>
<script type="text/javascript" 
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
src="resources/script/common/popup.js"></script>
<!-- Slimscroll -->
<!-- <script type="text/javascript" src="resources/script/jquery/jquery.slimscroll.js"></script> -->
<script type="text/javascript">
$(document).ready(function () {

	
	reloadList();
	
	$(".board_table #loginBtn").on("click", function () {
		location.href = "testALogin";
	})
	
	$("#insertBtn").on("click", function () {
	 		if($.trim($("#con").val()) == ""){
				makeAlert("알림","내용을 입력하세요." , function () {
					$("#con").focus();
				});
	 		}	else {
	 				action("insert");
			}
	
		})
		
	// 페이징 클릭시
	$(".paging_area").on("click", "span", function () {
		$("#page").val($(this).attr("page"));
		//기존 값 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchText").val($("#oldText").val());
		
		reloadList();
	})	
		
	// 검색 클릭시
	$("#searchBtn").on("click", function () {
		$("#page").val("1");
		//기존 값 새값으로 변경
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldText").val($("#searchText").val());
		
		reloadList();
	})
	
	// 목록의 삭제버튼 클릭시
	$("tbody").on("click", ".delete_btn", function () {
		var no = $(this).parent().parent().attr("no");
		
		  makePopup({
		         title : "알림",
		         contents : "삭제하시겠습니까?",
		         // draggable : true,
		         buttons : [{
		            name : "삭제",
		            func:function() {
		            	$("#no").val(no);
		            	action("delete");
		            	closePopup(); // 제일 위의 팝업 닫기
		            }
		         }, {
		            name : "취소"
		    }]
		})
	})
	
	// 목록 수정버튼 클릭시
	$("tbody").on("click", ".update_btn", function () {
		var no = $(this).parent().parent().attr("no");
		$("#no").val(no);

		
		//eq(인덱스번호) : 자식들 중 인덱스 몇번째 인지 찾아서 취득
		var con = $(this).parent().parent().children().eq(1).html();
		// 수정 내용 넣기 전 <> 변화
		con = con.replace(/&lt;/gi, "<");
		con = con.replace(/&gt;/gi, ">");
		
		
		$("#con").val(con);
		
		
		// 등록버튼 감추기 + 수정, 취소버튼 나타나기
		$(".insert").hide();
		$(".update").show();
		
		// 작성영역에 포커스
		$("#con").focus();
	})
	
	// 수정 영역의 취소버튼
	$("thead #cancelBtn").on("click", function () {
		// 입력내용 초기화
		$("#no").val("");
		$("#con").val("");
		// 등록버튼 나타나기 + 수정, 취소버튼 감추기
		$(".insert").show();
		$(".update").hide();
	})
	
	// 수정 영역의 수정버튼
	$("thead #updateBtn").on("click", function () {
		action("update");
	})
	
})


var msg ={
	"insert" : "등록",
	"update" : "수정",
	"delete" : "삭제",
}

function action(flag) {
	// con의 <를을 웹문자로 변환
	$("#con").val($("#con").val().replace(/</gi, "&lt;"));
	// con의 >를을 웹문자로 변환
	$("#con").val($("#con").val().replace(/>/gi, "&gt;"));
	
	
	// Javascript object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수있다. 
	// Java의 Map에서 get, put역활
	console.log(msg[flag]);
	
	var params = $("#actionForm").serialize();
	
	$.ajax({
		url : "AOBAction/" + flag,
		type : "POST", 
		dataType: "json", 
		data: params, 
		success : function(res) { 
			switch(res.msg){
			case "success" :
				// 내용 초기화
				$("#con").val("");
				$("#no").val("");

				// 목록 재조회
				switch(flag){
				case "insert" :
				case "delete" :
					// 조회 데이터 초기화
					$("#page").val("1");
					$("#searchGbn").val("0");
					$("#searchText").val("");
					$("#oldGbn").val("0");
					$("#oldText").val("");
					break;
				case "update" :
					// 기존값 유지
					$("#searchGbn").val($("#oldGbn").val());
					$("#searchText").val($("#oldText").val());

					// 입력내용 초기화
					$("#no").val("");
					$("#con").val("");
					// 등록버튼 나타나기 + 수정, 취소버튼 감추기
					$(".insert").show();
					$(".update").hide();
					break;
					
			
				}
				reloadList();
				break;
			case "fail" :
				makeAlert("알림" ,  msg[flag] + "에 실패하였습니다.");
				break;
			case "error" :
				makeAlert("알림" , msg[flag] + " 중 문제가 발생하였습니다.");
				break;
			}
		},
		error : function(request, status, error) { 
			console.log(request.responseText); 
		}
	}); //Ajax End
} // action Function End

function reloadList() {
	var params = $("#searchForm").serialize();
	$.ajax({
		url : "AOBList",
		type : "POST", 
		dataType: "json", 
		data: params, 
		success : function(res) { 
			drawList(res.list);
			drawPaging(res.pd);
		},
		error : function(request, status, error) { 
			console.log(request.responseText); 
		}
	}); //Ajax End
}

function drawList(list) {
	var html = "";
	
	for(var data of list){
		html +="<tr no=\"" + data.NO  + "\">";
		html +="<td>" + data.MEM_NM + "</td>";
		html +="<td>" + data.CON + "</td>";
		html +="<td>" + data.DT + "</td>";
		html +="<td>";
		if("${sMemNo}" == data.MEM_NO){ // 작성자이면
			html +="<div class=\"cmn_btn_ml mtb update_btn\">수정</div><br/>";
			html +="<div class=\"cmn_btn_ml mtb delete_btn\">삭제</div>";
		}
		html +="</td>";
		html +="</tr>";
	}
	
	$("tbody").html(html);
}



function drawPaging(pd) {
	var html = "";
	
	html += "<span class=\"page_btn page_first\" page=\"1\">처음</span>";
	// 이전
	if($("#page").val() == "1"){
		html += "<span class=\"page_btn page_prev\" page=\"1\">이전</span>";
	} else{
		// 문자열을 숫자로 바꾸기위해 *1
		html += "<span class=\"page_btn page_prev\" page=\"" + ($("#page").val() *1 - 1) + "\">이전</span>";
	}
	
	for(var i = pd.startP; i <= pd.endP; i++){
		if($("#page").val() * 1 == i){ // 현재 페이지
			html += "<span class=\"page_btn_on\" page=\"" + i + "\">" + i + "</span>";
		} else { // 다른 페이지
			html += "<span class=\"page_btn\" page=\"" + i + "\">" + i + "</span>";
		}
	}
	
	if($("#page").val() *1 == pd.endP){ // 현재페이지가 마지막 페이지라면
		html += "<span class=\"page_btn page_next\" page=\"" +pd.maxP+ "\">다음</span>";
	} else {
		html += "<span class=\"page_btn page_next\" page=\"" + ($("#page").val() *1 + 1) + "\">다음</span>";
	}
	
	html += "<span class=\"page_btn page_last\" page=\"" +pd.maxP+ "\">마지막</span>";
	
	$(".paging_area").html(html);
                                                                     
}

</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<hr/>
<div class="wrap">
	<div class="board_area">
		<!-- 작성 또는 로그인 -->
		
		<!-- 목록 -->
		<table class="board_table">
			<colgroup>
				<col width="100"> <!-- 작성자 -->
				<col width="500"> <!-- 내용 -->
				<col width="100"> <!-- 날짜 -->
				<col width="100"> <!-- 버튼 -->
			</colgroup>
			<thead>
				<c:choose>
					<%-- 이 주석 써야함--%>
					<c:when test="${empty sMemNo}"><!-- 비 로그인시 -->
						<tr>
							<th colspan="4">
								로그인이 필요한 서비스입니다.
								<div class="cmn_btn_ml login" id="loginBtn">로그인</div>
							</th>
						</tr>
					</c:when>
					<c:otherwise><!-- 로그인시 -->
						<tr>
							<th>${sMemNm}</th>
							<td colspan="2" class="con_td">
								<form action="#" id="actionForm">
									<input type="hidden" name="no" id="no">
									<input type="hidden" name="memNo" value="${sMemNo}">
									<textarea class="con" name="con" id="con">Hi</textarea>
								</form>
							</td>
							<td>
								<div class="insert">
									<div class="cmn_btn_ml" id="insertBtn">등록</div>
								</div> 
								<div class="update">
									<div class="cmn_btn_ml mtb" id="updateBtn">수정</div><br/>
									<div class="cmn_btn_ml mtb" id="cancelBtn">취소</div>
								</div>
							</td>
						</tr>
					</c:otherwise>
				</c:choose>
				<tr>
					<th>작성자</th>
					<th>내용</th>
					<th>작성자</th>
					<th>&nbsp;</th>
				</tr>
			</thead>
			<tbody>
				
			</tbody>
		</table>
		<!-- 페이징 -->
		<div class="paging_area"></div>
	</div>
	<div class="search_area">
		<!-- 검색어 유지용 -->
		<input type="hidden" id="oldGbn" value="0" />
		<input type="hidden" id="oldText" />
		<form action="#" id="searchForm">
			<input type="hidden" name="page" id="page" value="1" />
			<select name="searchGbn" id="searchGbn">
				<option value="0">작성자</option>
				<option value="1">내용</option>
			</select>
			<input type="text" name="searchText" id="searchText"/>
			<div class="cmn_btn_ml" id="searchBtn">검색</div>
		</form>
	</div>
</div>
</body>
</html>

 

AOBController.java

package com.spring.sample.web.testa.Controller;

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.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.sample.common.service.IPagingService;
import com.spring.sample.web.testa.dao.IACDao;

@Controller
public class AOBController {
	@Autowired
	public IACDao dao;

	@Autowired
	public IPagingService ips;

	// DB안 붙으니 예외처리 x
	@RequestMapping(value = "AOB")
	public ModelAndView aob(ModelAndView mav) {
		mav.setViewName("testa/AOB/ob");

		return mav;
	}

	@RequestMapping(value = "/AOBAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String AOBAction(@PathVariable String gbn, @RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		int cnt = 0;

		try {
			switch (gbn) {
			case "insert":
				cnt = dao.insert("ob.insertOb", params);
				break;
			case "update":
				cnt = dao.update("ob.updateOb", params);
				break;
			case "delete":
				cnt = dao.update("ob.deleteOb", params);
				break;
			}

			if (cnt > 0) {
				model.put("msg", "success");
			} else {
				model.put("msg", "fail");
			}
		} catch (Exception e) {
			e.printStackTrace();
			model.put("msg", "error");
		}

		return mapper.writeValueAsString(model);
	}

	@RequestMapping(value = "/AOBList", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String AOBList(@RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		// 페이지 받아오게 되어있음
		int cnt = dao.getInt("ob.getObCnt", params);

		HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")), cnt, 10, 5);

		params.put("start", Integer.toString(pd.get("start")));
		params.put("end", Integer.toString(pd.get("end")));

		List<HashMap<String, String>> list = dao.getList("ob.getObList", params);

		model.put("list", list);
		model.put("pd", pd);

		return mapper.writeValueAsString(model);
	}
}

 

OB_SQL.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="ob">
	<insert id="insertOb" parameterType="hashmap">
		INSERT INTO OB(NO, MEM_NO, CON) VALUES (OB_SEQ.NEXTVAL, #{memNo}, #{con})
	</insert>
	<update id="updateOb" parameterType="hashmap">
		UPDATE OB SET CON = #{con}
		WHERE NO = #{no}
	</update>
	<update id="deleteOb" parameterType="hashmap">
		UPDATE OB SET DEL = 0
		WHERE NO = #{no}
	</update>
	<select id="getObCnt" parameterType="hashmap" resultType="Integer">
		SELECT COUNT(*) AS CNT
			FROM OB O INNER JOIN MEM M ON O.MEM_NO = M.MEM_NO
			AND M.DEL=1
		WHERE O.DEL = 1
		<if test="searchText != null and searchText != ''">
			<choose>
			 	<when test="searchGbn eq 0">
			 	<!-- 작성자 검색 -->
			 			AND M.MEM_NM LIKE '%' || #{searchText} || '%'
			 	</when>
				<when test="searchGbn eq 1">
				<!-- 내용 검색 -->
			 			AND O.CON LIKE '%' || #{searchText} || '%'
			 	</when>
			</choose>
		</if>
	</select>
	<select id="getObList" parameterType="hashmap" resultType="hashmap">
		SELECT O.NO, O.MEM_NO, O.MEM_NM, O.CON, O.DT   
		FROM (SELECT O.NO, O.MEM_NO, M.MEM_NM, O.CON,
             CASE WHEN TO_CHAR(O.DT, 'YY.MM.DD') = TO_CHAR(SYSDATE, 'YY.MM.DD') 
                  THEN TO_CHAR(O.DT, 'HH24:MI')
                  ELSE TO_CHAR(O.DT, 'YY.MM.DD')
             END AS DT, 
               ROW_NUMBER() OVER(ORDER BY O.NO DESC) AS RNUM
	      FROM OB O INNER JOIN MEM M
	                  ON O.MEM_NO = M.MEM_NO
	                 AND M.DEL = 1
	      WHERE O.DEL = 1
	      <if test="searchText != null and searchText != ''">
				<choose>
				 	<when test="searchGbn eq 0">
				 	<!-- 작성자 검색 -->
				 			AND M.MEM_NM LIKE '%' || #{searchText} || '%'
				 	</when>
					<when test="searchGbn eq 1">
					<!-- 내용 검색 -->
				 			AND O.CON LIKE '%' || #{searchText} || '%'
				 	</when>
				</choose>
			</if>
	      ) O
		WHERE O.RNUM BETWEEN #{start} AND #{end}
	</select>
</mapper>

 

728x90