부트캠프55일차(검색기능구현,ajax , fetch , 예제)
1) 검색기능 구현(/board/list)
2)ajax사용
2-1)ajax 맛보기
2-2) ajax를 POST방식 or GET방식
2-3) JSON 사용
2-4) fetch ( jsp사용) (최신방법)
2-5) fetch( json 사용)
2-6) fetch (파라미터값 사용가능)
2-7) jquery를 사용한 ajax
3) AJAX문제
1) 검색기능 구현(board / list)
/webapp/view/board/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<!--
첨부파일이 존재하는 게시물의 제목앞에 @ 표시
-->
<head>
<meta charset="UTF-8">
<title>게시물목록</title>
</head>
<body>
<h2>${boardName}</h2>
<form action="list?boardid=${boardid}" method="post" name="sf">
<input type="hidden" name="pageNum" value="1">
<select class="w3-select" name="column">
<option value="">선택하시오</option>
<option value="writer">작성자</option>
<option value="title">제목</option>
<option value="content">내용</option>
<option value="title,writer">제목+작성자</option>
<option value="title,content">제목+내용</option>
<option value="writer,content">작성자+내용</option>
<option value="title,writer,content">제목+작성자+내용</option>
</select>
<script type="text/javascript">
document.sf.column.value='${param.column}'
</script>
<input class="form-control" type="text" placeholder="Search"
name="find" value="${param.find}">
<button class="btn btn-primary" type="submit">Search</button>
</form>
<table class="table">
<c:if test="${boardcount == 0}">
<tr><td colspan="5">등록된게시글이없어요</td></tr>
</c:if>
<c:if test="${boardcount > 0}">
<tr><td colspan="5" style="text-align:right">글 갯수:${boardcount}</td></tr>
<tr>
<th width="8%">번호</th><th width="45%">제목</th>
<th width="14%">작성자</th><th width="22%">등록일</th>
<th width="11%">조회수</th>
</tr>
<c:set var="num" value="${num}" /> <!-- (controller에서만듬)num속성을 c:set으로 지정 -->
<c:forEach var="b" items="${list}" >
<tr><td>${num}</td>
<c:set var="num" value="${num-1}" /> <!-- num을 -1해줌 -->
<td style="text-align: left">
<c:if test="${!empty b.file1}"><a href="../upload/board/${b.file1}">(FILE)</a></c:if>
<c:if test="${empty b.file1}"> </c:if>
<!-- 답글인 경우 grplevel만큼 공백을주자 -->
<c:if test="${b.grplevel>0}">
<c:forEach var="i" begin="1" end="${b.grplevel}">
 
</c:forEach>└
</c:if>
<a href="info?num=${b.num}">${b.title}</a></td>
<td>${b.writer}</td>
<%--
오늘등록된 게시물의 형식은 HH:mm:ss형식으로바꾸자
--%>
<td>
<fmt:formatDate value="${b.regdate}" type="date" var="rdate"/>
<fmt:formatDate value="${today}" type="date" var="tdate"/>
<c:if test="${rdate==tdate}">
<fmt:formatDate value="${b.regdate}" type="time"/>
</c:if>
<c:if test="${rdate!=tdate}">
<fmt:formatDate value="${b.regdate}" type="both"/>
</c:if>
</td>
<td>${b.readcnt}</td>
</c:forEach>
<tr><td colspan="5" align="center">
<c:if test="${pageNum <= 1}">[이전]</c:if>
<c:if test="${pageNum > 1}">
<a href="javascript:listsubmit(${pageNum-1})">[이전]</a>
</c:if>
<c:forEach var="a" begin="${startpage}" end="${endpage}">
<c:if test="${a == pageNum}"><a href="#">[${a}]</a></c:if><!-- 현재페이지를 누르면 아무일도일어나지않음 -->
<c:if test="${a != pageNum}"><!-- 다른페이지클릭시 해당 pageNum으로넘어감 -->
<a href="javascript:listsubmit(${a})">[${a}]</a>
</c:if>
</c:forEach>
<c:if test="${pageNum >= maxpage}">[다음]</c:if>
<c:if test="${pageNum < maxpage}">
<a href="javascript:listsubmit(${pageNum+1})">[다음]</a>
</c:if>
</td></tr>
</c:if>
<!--
1.공지사항 게시판인경우 관리자로그인한 경우만 글쓰기출력하기
2. write
-->
<c:if test="${boardid != 1 || sessionScope.login=='admin'}">
<tr><td colspan="5" style="text-align:right">
<p align="right"><a href="writeForm">[글쓰기]</a></p>
</td></tr>
</c:if>
</table>
<script type="text/javascript">
function listsubmit(page){
f = document.sf;
f.pageNum.value = page;
f.submit();
}/*페이지를 변경해도 find와 column이 초기화되지않음*/
</script>
</body>
</html>
/java/controller/BoardController.java의 변경 및 추가
String column = request.getParameter("column"); //선택한 값
String find = request.getParameter("find"); //입력한 값
if(column == null || column.equals("")||
find == null || find.equals("")) {
column = null;
find = null;
}
int limit = 10;//페이지당 출력되는 게시물의건수
int boardcount = dao.boardCount(boardid,column,find);//현재등록된 게시물건수
//pageNum에 해당하는 게시물목록을 최대10개 조회
List<Board> list = dao.list(boardid,pageNum,limit,column,find);
그에따른 BoardDao의 boardCount메서드 , list메서드 변경
public int boardCount(String boardid, String column, String find) {
SqlSession session = MyBatisConnection.getConnection();
try {
map.clear();
map.put("boardid", boardid);
map.put("column", column);
map.put("find", find);
if(column!=null) {
String[] cols = column.split(",");
switch(cols.length) {
case 3 : map.put("col3", cols[2].trim());
case 2 : map.put("col2", cols[1].trim());
case 1 : map.put("col1", cols[0].trim());
}//3개가있다면 3개 다 집어넣어야함( break문 안씀)
}
return session.getMapper(cls).boardCount(map);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
MyBatisConnection.close(session);
}
return 0;
}
public List<Board> list(String boardid, int pageNum, int limit, String column, String find) {
SqlSession session = MyBatisConnection.getConnection();
map.clear();
map.put("boardid", boardid);
map.put("start", (pageNum-1) * limit);
map.put("limit", limit);
map.put("column", column);
map.put("find", find);
if(column!=null) {
String[] cols = column.split(",");
switch(cols.length) {
case 3 : map.put("col3", cols[2].trim());
case 2 : map.put("col2", cols[1].trim());
case 1 : map.put("col1", cols[0].trim());
}//3개가있다면 3개 다 집어넣어야함( break문 안씀)
}
try {
return session.getMapper(cls).list(map);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
MyBatisConnection.close(session);
}
return null;
}
Mapper의변경 ( sqlcol의 이름을가진 쿼리문을 생성함)
column들과(1개가있다면 1개만 2개가있다면 2개모두) find를 비교하는 문장
만일 column이 null일 시 비교문장은 들어가지않을거임
String sqlcol =
"<if test='column != null'> "
+ "AND ("
+ "<if test='col1 != null'> ${col1} LIKE '%${find}%'</if>"
+"<if test='col2 != null'> OR ${col2} LIKE '%${find}%'</if>"
+"<if test='col3 != null'> OR ${col3} LIKE '%${find}%'</if>"
+ ")</if>";
@Select({
"<script>",
"SELECT COUNT(*) FROM board",
"WHERE boardid = #{boardid}",
sqlcol,"</script>"
})
int boardCount(Map<String, Object> map);
@Select({"<script>","select * from board where boardid=#{boardid}"+
sqlcol+" order by grp desc , grpstep asc limit #{start},#{limit}","</script>"})
//grp==num 을 내림차순으로함 (최신이 가장 위에뜨게)
//start번에서부터 limit개 조회해
List<Board> list(Map<String, Object> map);
3개의컬럼( 작성자+내용+제목)을 선택하고
'에'를 입력했다면
다음과같은 방식의 쿼리가 나갈거임
2) ajax사용
ajaxStudy의 이름으로 webProject생성
2-1) AJAX 맛보기
/webapp/ex01_basic.html생성
ajax객체( XMLHttpRequest() )
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XMLHttpRequest객체</title>
</head>
<body>
<h2>XMLHttpRequest객체</h2>
<button onclick="loadJson()">요청</button>
<div id="demo"></div>
<script type="text/javascript">
function loadJson(){
const xhttp = new XMLHttpRequest();//ajax객체 readyState:0
//서버에 요청할수있는 자바스크립트객체
xhttp.open("GET","ex01_basic.jsp",true);//open(method,url,비동기방식)
//readyState:1
xhttp.send();
//readyState:2
/*
onreadystatechange : xhttp객체의 상태 변경 시 자동호출되는 함수(콜백함수)
*/
xhttp.onreadystatechange = function(){
/*
readyState : ajax상태
0 : 객체생성
1 : open()실행
2 : send()실행(서버에요청만 한 상태 응답X)
3 : 서버에 응답 중
4 : 서버에서 응답 완료
status : 서버에서 응답결과(HTTP응답코드)
200 : 정상처리
404 : 서버페이지없음
500 : 서버페이지에서 오류발생
*/
if(this.readyState==4 && this.status ==200){ // 정상응답완료
//responseText : 서버에서 전달받은 응답메시지
alert(this.responseText);
document.querySelector("#demo").innerHTML = this.responseText;
}
}
}
</script>
</body>
</html>
ex01_basic.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<table>
<tr><td><font color="red">ex01_basic.jsp</font></td></tr>
<tr><td><font color="blue">ex01_basic.jsp</font></td></tr>
<tr><td><font color="yellow">ex01_basic.jsp</font></td></tr>
</table>
2-2) ajax를 POST방식 or GET방식
ex02_basic.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XMLHttpRequest객체를 통한 요청</title>
</head>
<body>
<form name="f">
<input type="text" name="name">
</form>
<button type="button" onclick="loadJspGet()">입력(get)</button>
<button type="button" onclick="loadJspPost()">입력(Post)</button>
<div id="demo"></div>
<script type="text/javascript" src="ex02_basic.js"></script>
</body>
</html>
ex02_basic.JS
function loadJspGet(){
const xhttp = new XMLHttpRequest(); //ajax객체
const params = "?name="+document.f.name.value;
xhttp.open("GET","ex02_basic.jsp"+params);
//ex02_basic.jsp?name="name.value" 형식으로넘어감
xhttp.send();
xhttp.onreadystatechange=callback;
}
function loadJspPost(){
const xhttp = new XMLHttpRequest();
const params = "name="+document.f.name.value;
xhttp.open("Post","ex02_basic.jsp");
//POST 데이터가 폼 형식이라는 걸 서버에 알려줌. + 인코딩지정
xhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8")
xhttp.send(params); //POST : send시 파라미터전달
xhttp.onreadystatechange=callback;
}
function callback(){
if(this.readyState==4 && this.status == 200){
alert(this.responseText);
document.querySelector("#demo").innerHTML = this.responseText;
}
}
ex02_basic.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<table>
<tr><td>${param.name}</td></tr>
<tr><td><font color="red">ex02_basic.jsp</font></td></tr>
<tr><td><font color="blue">ex02_basic.jsp</font></td></tr>
<tr><td><font color="yellow">ex02_basic.jsp</font></td></tr>
</table>
2-3) JSON 사용
/webapp/ex03_json.json
파일 생성
[
{"author" :{"book":"ajax","pubDate":"2025-04-21"}},
{"author" :{"book":"자바","pubDate":"2025-02-01"}},
{"author" :{"book":"WEB","pubDate":"2025-03-20"}}
]
ex03_json.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<input type="button" value="JSON읽기" onclick="load('ex03_json.json')">
<div id="area" style="color:red"></div>
<script type="text/javascript">
function load(url){
const xhttp = new XMLHttpRequest();
xhttp.open("GET",url);
xhttp.send();
xhttp.onreadystatechange = callBack
}
function callBack(){
if(this.readyState==4 && this.status ==200){
let area = document.querySelector("#area"); //div
let data = JSON.parse(this.responseText)
/*
this.responseText : JSON.parse
[] : 배열 , {} : 객체
[{"author" :{"book":"ajax","pubDate":"2025-04-21"}},
{"author" :{"book":"자바","pubDate":"2025-02-01"}},
{"author" :{"book":"WEB","pubDate":"2025-03-20"}}]
*/
//data : 배열 (json객체를 요소로 가지는 배열)
for(s of data){ // s : json객체 요소 한개
// {"author" :{"book":"ajax","pubDate":"2025-04-21"}}
// s.author.book : ajax
//s.author.pubDate : 2025-04-21
area.innerHTML += '<p>'+s.author.book+" : "+s.author.pubDate+'</p>'
//총 루프를 3번돌거임( 객체가3개임)
}
}
}
</script>
</body>
</html>
2-4) fetch ( jsp사용) (최신방법)
ex04_fetch.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fetch예제</title>
</head>
<body>
<h2>fetch함수를 이용한 요청</h2>
<button onclick="loadjsp()">요청</button>
<div id="demo"></div>
<script type="text/javascript" src="ex04_fetch.js">
</script>
</body>
</html>
ex04_fetch.js
ex01_basic.jsp는 위에 있음
function loadjsp(){
//ex01_basic.jsp 파일에 GET 요청을 보냄(비동기처리함수)
fetch("ex01_basic.jsp")
//JSP 파일의 응답 결과(HTML이든 문자열이든)를 문자열로 추출함
//response = jsp의response가 아님 (변수명)(서버에서온 응답)
.then((response)=>response.text())
//(추출한문자열)얻은 data를 id가 demo인 요소에 출력함
.then((data)=>document.querySelector('#demo').innerHTML = data)
}
2-5)fetch( json 사용)
(최신방법)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fetch예제2</title>
</head>
<body>
<button onclick="load1('ex03_json.json')">JSON읽기</button>
<button onclick="load2('ex03_json.json')">JSON읽기2</button>
<div id="area" style="color:red"></div>
<div id="area2" style="color:blue"></div>
<script type="text/javascript">
function load1(url){
fetch(url)
.then((r)=>r.text()) /*r.text() : 서버에서응답받은 문자열*/
.then((t)=>{ /* t : r.text() */
let data= JSON.parse(t); // t를 JSON객체형식으로 변경해(배열)
let area = document.querySelector("#area")
for(s of data){
area.innerHTML += '<p>'+s.author.book+" : "+s.author.pubDate+'</p>'
}
})
}
function load2(url){
fetch(url)
.then((r)=>r.json())/*r.json() : 서버에서 json객체로 받아냄(배열)*/
.then(data=>{ //data : r.json()배열
let area2 = document.querySelector("#area2")
for(s of data){
area2.innerHTML += '<p>'+s.author.book+
" : "+s.author.pubDate+'</p>'
}
})
}
</script>
</body>
</html>
2-6) fetch (파라미터값 사용가능)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>fetch함수 이용</h2>
<form name="f">
<input type="text" name="name"></form>
<button onclick="loadJspGet()">입력(get)</button>
<button onclick="loadJspPost()">입력(post)</button>
<div id="demo"></div>
<script type="text/javascript">
function loadJspGet(){
fetch("ex02_basic.jsp?name=" +document.f.name.value)
.then((r)=>r.text())
.then((data)=>document.querySelector("#demo").innerHTML = data)
}
function loadJspPost(){
fetch("ex02_basic.jsp",{
method:"POST",
headers :{
"Content-type":"application/x-www-form-urlencoded; charset=UTF-8"},
body:"name="+document.f.name.value
})
.then((r)=>r.text())
.then((data)=>{
document.querySelector("#demo").innerHTML = data
})
}
</script>
</body>
</html>
2-7) jquery를 사용한 ajax
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
꼭 head부분에 넣어줘야 jquery를 사용할수있음
/ajaxStudy/src/main/webapp/ex07_ajax1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery이용한 ajax</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<button id="btn1">ex07_ajax1.jsp 호출</button>
<button id="rmbtn1">ex07_ajax1.jsp 호출로 추가된요소 제거</button><br>
<button id="btn2">ex07_ajax2.jsp 호출</button>
<button id="rmbtn2">ex07_ajax2.jsp 호출로 추가된요소 제거</button>
<script type="text/javascript">
$("#rmbtn1").click(function(){
$("#one").last().remove(); /id가 one인태그 마지막을 지우기*/
/*$("h1").eq(-1).remove(); eq(-1) : 뒤에서첫번쨰*/
/*$("h1").get(-1).remove(); get(-1) : 뒤에서첫번쨰*/
})
$(function(){
$("#btn1").click(function(){
$.ajax("ex07_ajax1.jsp",{
success : function(data){
$("body").append(data)
},
error : function(e){
alert("서버오류 : "+e.status)
}
})
})
})
/*--------------------POST방식-----------------------------*/
$("#btn2").click(function(){
$.ajax({
url : "ex07_ajax2.jsp",
type:"POST",
/*data : "name=홍길동&age=20",밑에 방식과 같음*/
data : {name:"홍길동",age:30},
success : function(data){
$("body").append(data)
},
error : function(e){
alert("서버오류 : "+e.status)
}
})
})
$("#rmbtn2").click(function(){
$("#two").last().remove();
})
</script>
</body>
</html>
/ajaxStudy/src/main/webapp/ex07_ajax1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1 style="color:blue" id="one">Jqeury ajax 첫번쨰 연습</h1>
/ajaxStudy/src/main/webapp/ex07_ajax2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1 id="two" style="color:red">안녕하세요 ${param.name}입니다 나이는 ${param.age}입니다</h1>
문제1)
/webapp/test0421/test1.html
<!DOCTYPE html>
<!-- /webapp/test0421/test1.html
test1.html: ajax 객체를 통해 test1.jsp의 숫자 중 가장 큰값을 찾아 result 영역에 출력하기
test1.jsp : 0~99사이의 임의의 값을 10 개 생성하여 ,로 연결하여 전송하기
-->
<html>
<head>
<meta charset="UTF-8">
<title>ajax Test</title>
</head>
<body>
<div id="result"></div>
<script src="test01.js"></script>
</body></html>
/webapp/test0421/test1.jsp
<%@page import="java.util.Arrays"%>
<%@page import="java.util.Random"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
Random r2 = new Random();
/*String[] num2 = new String[10];
for(int i=0; i<10; i++){
num2[i] = String.valueOf(r2.nextInt(100));// 0~99
}
out.print(num2);*/
for(int i=0; i<10; i++){
int a = r2.nextInt(100);// 0~99
out.print(a);
if(i!=9){
out.print(",");
}
}
%>
/webapp/test0421/test1.js
const xhttp = new XMLHttpRequest();
xhttp.open("GET","test01.jsp");
xhttp.send();
xhttp.onreadystatechange = callBack
function callBack(){
if(this.readyState==4 && this.status == 200){
let data = this.responseText.split(",");
let max = data[0];
for(s of data){
if(max<s){
max = s;
}
}
document.querySelector("#result").innerHTML += `${data}<br>`
document.querySelector("#result").innerHTML += `가장큰수는 ${max}`;
}
}
문제2)
/webapp/test0421/test2.html
<!DOCTYPE html>
<!-- /webapp/test0421/test2.html
test2.html : fetch을 통해 현재 페이지에 전송받아 결과를 result 영역에 출력하기
test2.jsp 에서 num에서 입력 받은 숫자까지의 합계를 구하기
-->
<html>
<head>
<meta charset="UTF-8">
<title>fetch Test</title>
</head>
<body>
<input type="text" id="num">
<button onclick="fetchteset(0)">전체합계구하기</button>
<button onclick="fetchteset(1)">짝수합구하기</button>
<button onclick="fetchteset(2)">홀수합구하기</button>
<div id="result"></div>
<script>
function fetchteset(x){
fetch("test2.jsp?f="+x+"&num="+document.querySelector("#num").value)
.then((r)=>r.text())
.then((data)=>document.querySelector('#result').innerHTML = data)
}
</script>
</body></html>
/webapp/test0421/test2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
int a = Integer.parseInt(request.getParameter("f"));
int num = Integer.parseInt(request.getParameter("num"));
switch(a){
case 0 : {
int sum=0;
for(int i =1 ; i<=num ; i++){
sum+= i;
}
out.print(sum);}break;
case 1 : {
int sum=0;
for(int i =1 ; i<=num ; i++){
if(i%2==0){
sum+= i;
}
}
out.print(sum);}break;
case 2 : {
int sum=0;
for(int i =1 ; i<=num ; i++){
if(i%2==1){
sum+= i;
}
}
out.print(sum);}break;
}
%>
<td></td>
-> 과같은 (자바14이상 사용가능)
을 하려면
그냥 java파일을 따로만들어쓰고
JSP는 그냥 출력용으로만 사용해보자
hi/Test02.java
package hi;
public class Test02 {
public int sumVal(int x, int sum) {
int total=0;
switch (x) {
case 0 ->{
for (int i =1; i <= sum; i++) {
total+= i;
}
return total;
}
case 1->{
for (int i =1; i <= sum; i++) {
if(i%2==0) { //짝수
total+= i;
}
}
return total;
}
case 2->{
for (int i =1; i <= sum; i++) {
if(i%2==1) { //홀스
total+= i;
}
}
return total;
}
}
return total;
}
}
변경된 jsp코드 (간결해짐)
<%@page import="hi.Test02"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
int a = Integer.parseInt(request.getParameter("f"));
int num = Integer.parseInt(request.getParameter("num"));
Test02 t2 = new Test02();
out.print(t2.sumVal(a,num));
%>
<td></td>