ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 0915. 여행 페이지를 만들자
    Spring 2023. 9. 15. 18:22

    사전 준비

    테이블 준비

    int이기만 한 no를 실제 pk로 설정하기.
     alter 사용

    select * from travel;
    
    -- 기존 컬럼 no에 pk, auto_increment 배정
    alter table travel
    modify no int auto_increment primary key;

    제대로 변경됨

    테이블 준비 끝
     


    **여행 페이지 만들기 시작 순서**

    0) DB에서 테이블 정의

    1) VO 객체 정의 (테이블에 대응하는) => TravelVO
    2) Mapper 인터페이스 정의
    3) Mapper xml 정의
    -> 테스트
    4)Service 인터페이스 정의 + 구현
    -> 구현한 걸로 테스트
    5) Controller 정의
    6) jsp (화면 정의)

    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     

    • [domain] 패키지에 TravelVO 클래스 만들기

    @Data 주고 만들기

    DDL 에서 봤던 순서대로 정의하기

    package org.galapagos.domain;
    
    import lombok.Data;
    
    @Data
    public class TravelVO {
    	private Long no;
    	private String region;
    	private String title;
    	private String description;
    	private String address;
    	private String phone;
    
    }

    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     
    [Mapper] 패키지에서 인터페이스 추가

    • TravelMapper

    *<TravelVO> : TimeMapper🐲

    package org.galapagos.mapper;
    
    import java.util.List;
    
    import org.galapagos.domain.Criteria;
    import org.galapagos.domain.TravelVO;
    
    public interface TravelMapper {
    
    	public int getTotalCount(Criteria cri); // 갖다쓸 수 있음. int로 바꿔주기
    
    	// 페이지 목록 추출 (bno 수정필요)
    	public List<TravelVO> getList(Criteria cri);
    
    	// pk 추출 포함
    	public void insert(TravelVO travel); // insertselectkey 만들 필요 x 한 벌로 운영
    
    	public TravelVO read(Long no);
    	
    	public int delete(Long no);
    
    	public int update(TravelVO travel);
    }

    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     
    Mapper xml을 만들 때 주의점
    Mapper 인터페이스와 같은 패키지 경로에 맞춰서 해야 한다.

    ❗작업 전에 mybatis-config.xml에서 같은 패키지에 TravelVO가 속해있는지 확인해야 한다.🐲

    TravelMapper.xml 로 복사해오는 요소들

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 이 xml은 mapper 정의이다. -->
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!-- 나랑 짝이 되는 인터페이스가 누구냐 -->
    <mapper namespace="org.galapagos.mapper.TravelMapper">
    </mapper>

     
    검색 기능 >  검색 조건 조정

    • 검색조건 가져와서 수정하기

    BoardMapper.xml => TravelMapper.xml 로 복사하기(앞으로 계속 나올 일)
     title(T), description(D), region(R) 을 검색필터로 할 것임

    조정할 부분
    이 사이에 넣어서 고쳐줄 것이다.

    	<sql id="criteria">
    		<trim prefixOverrides="OR">
    			<foreach item="type" collection="typeArr">
    				<trim prefix="OR">
    					<choose>
    						<when test="type == 'T'.toString()">
    							title like CONCAT('%', #{keyword}, '%')
    						</when>
    						<when test="type == 'D'.toString()">
    							description like CONCAT('%', #{keyword}, '%')
    						</when>
    						<when test="type == 'R'.toString()">
    							region like CONCAT('%', #{keyword}, '%')
    						</when>
    					</choose>
    				</trim>
    			</foreach>
    		</trim>
    	</sql>
    • <sql> 태그 밑에 총 건수 보여주는 <select> 태그 추가
    	<select id="getTotalCount" resultType="int">
    		select count(*) from travel //tbl_ 빼야함
    	</select>

    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     

    • TravelMapperTest (JUnit Test Case) 만들기

    메서드 전체 체크

     
    가져올 어노테이션 추가하고 @Autowired

    좌 TravelMapperTest / 우 BoardMapperTest

    Criteria 추가

    • getTotalCount 총 검색 건수

    *현재 검색어 따로 없는 상황

    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import lombok.extern.log4j.Log4j;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = { RootConfig.class })
    @Log4j
    public class TravelMapperTest {
    	
    	@Autowired
    	private TravelMapper mapper;
    
    	@Test
    	public void testGetTotalCount() {
    		Criteria cri = new Criteria(); //검색어 없는 상황
    	}
        
      }

    테스트 실행하면 잘 된다.
    xml 에도 criteria 추가

    	@Test
    	public void testGetTotalCount() {
    		Criteria cri = new Criteria(); //검색어 없는 상황
    		
    		int total = mapper.getTotalCount(cri);
    		log.info("total: " + total);
    		
    		cri.setType("RTD");
    		cri.setKeyword("해수욕장");
    		total = mapper.getTotalCount(cri);
    		log.info("total: " + total);
    	}

     
    testgetList()
    첫 페이지 10개를 리턴하는 테스트

    	<select id="getList" resultType="TravelVO">
    		select * from travel
    		<where>
    			<include refid="criteria"></include>
    		</where>
    		order by region, title
    		limit #{offset} , #{amount}
    	</select>
    	@Test
    	public void testGetList() {
    		Criteria cri = new Criteria();
    		
    		List<TravelVO> list = mapper.getList(cri); //리턴:첫페이지 10개
    	}

     

     
     
    TravelMapper.xml read 가져오기... 이후 계속 반복
    * 첫 번째 박스 : xml, 두 번째 박스 : TravelMapperTest 코드 

    • read 
    	<select id="read" resultType="TravelVO">
    		select * from travel
    		where no = #{no}
    	</select>
    	@Test
    	public void testRead() {
    		TravelVO travel = mapper.read(10L); //long 타입 L
    		log.info(travel);
    	}

     

    • insert
    	<insert id="insert"> <!-- id는 인터페이스 메서드명과 동일 -->
    		insert into travel (region, title, description, address, phone)
    		values (#{region}, #{title}, #{description}, #{address}, #{phone})
    		<!-- #은 preparedStatement:?에서 물음표 역할 -->
    		
    		<selectKey resultType="Long" keyProperty="no"
    			keyColumn="no" order="AFTER">
    			SELECT LAST_INSERT_ID()
    		</selectKey>
    	</insert>
    	@Test
    	public void testInsert() { //insert이므로 no는 지정할 필요 없음
    		TravelVO travel = new TravelVO();
    		travel.setRegion("수도권");
    		travel.setTitle("강남 에코파크");
    		travel.setDescription("강남에 위치한 에너지 파크");
    		travel.setAddress("서울시 강남구");
    		travel.setPhone("1111-2222-3333");
    		
    		mapper.insert(travel);
    		log.info(travel);
    	}
    INFO : org.galapagos.mapper.TravelMapperTest - TravelVO(no=113, region=수도권, title=강남 에코파크, description=강남에 위치한 에너지 파크, address=서울시 강남구, phone=1111-2222-3333)

     
     

    • update

    권역빼고 title, description, address, phone 부분 바꾸기

    		<update id="update">
    		update travel set
    			title = #{title},
    			description = #{description},
    			address = #{address},
    			phone = #{phone}
    		where no = #{no}
    <!-- 		update_date = now() -->
    	</update>

    no=113 이었던 거 기억하고 수정해야 한다!

    	@Test
    	public void testUpdate() {
    		TravelVO travel = mapper.read(113L);
    		travel.setTitle("강남 에너지 파크");
    		travel.setDescription("강남의 떠오르는 명소");
    		travel.setAddress("서울시 강남구 1");
    		travel.setPhone("010-1234-5678");
    		mapper.update(travel);
    	}

     

     

    • delete

     

    	<delete id="delete">
    		DELETE FROM travel where no = #{no}
    	</delete>
    	@Test
    	public void testDelete() {
    		mapper.delete(113L); //강남 어쩌구 지우기
    	}

    사라짐

     


    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     
    [service 패키지]

    • 인터페이스 TravelService 만들기

     

    package org.galapagos.service;
    
    import java.util.List;
    
    import org.galapagos.domain.Criteria;
    import org.galapagos.domain.TravelVO;
    
    public interface TravelService {
    	
    	// CRUD 기본골격, 리턴타입 true, false
    	
    	public int getTotal(Criteria cri);
    
    	public List<TravelVO> getList(Criteria cri);
    	
    	public TravelVO get(Long no);
    	
    	public void register(TravelVO travel);
    
    	public boolean modify(TravelVO travel);
    
    	public boolean remove(Long no);
    
    }

     

    • TravelServiceImpl 만들어서 implement로 TravleService 사용하기 

    @Service 추가 꼭 하기 (애매하면 @Component)

     

    package org.galapagos.service;
    
    import java.util.List;
    
    import org.galapagos.domain.Criteria;
    import org.galapagos.domain.TravelVO;
    import org.galapagos.mapper.TravelMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import lombok.AllArgsConstructor;
    import lombok.extern.log4j.Log4j;
    
    @Log4j
    @Service // bean 등록
    //@AllArgsConstructor // auto wired 대신 생성자 매개변수로 주입해서 쓸 수 있는 방법 -> 가독성 상승
    
    public class TravelServiceImpl implements TravelService {
    
    	@Autowired
    	private TravelMapper mapper;
    	
    	@Override
    	public int getTotal(Criteria cri) {
    		return mapper.getTotalCount(cri);
    	}
    
    	@Override
    	public List<TravelVO> getList(Criteria cri) {
    		return mapper.getList(cri);
    	}
    
    	@Override
    	public TravelVO get(Long no) {
    		//조회수 처리
    		return mapper.read(no);
    	}
    
    	@Override
    	public void register(TravelVO travel) {
    		mapper.insert(travel);
    		//첨부파일 업로드
    
    	}
    
    	@Override
    	public boolean modify(TravelVO travel) {
    		//영향받은 행의 개수 리턴, 1이면 성공한 것
    		return mapper.update(travel) == 1;
    	}
    
    	@Override
    	public boolean remove(Long no) {
    		return mapper.delete(no) == 1;
    	}
    
    }

     

    ❤️
    +)조회수 처리
    조회수 증가시키려면 get 호출에서 해야 한다.

    +) 첨부파일 업로드
    Foreign Key 잡아서 register에서 한다.

     
     


    🖤 스토리 보드

     
    공통 /travel
     
    /travel ---/list --- ▶ 목록  ◀---/get--- ▶ 상세 ◀---/modify ---▶ 수정
                                    ↥                            ↥
                                /register    ↖         /remove
                                    ↧                            ↧ 
                               글쓰기                     삭제 (하면 목록으로)
     
     
     
     


    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     
    잘 된다.
    과정 어디 감
    잘 될 거임.
     


    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)
     
    TravelController
    @Controller 로 역할 주고 @Autowired, 그외 필요한 어노테이션 몽땅 넣기
    list 부터 건들 것이다. @GetMapping("/list") 가져오기!

    package org.galapagos.controller;
    
    
    import org.galapagos.domain.Criteria;
    import org.galapagos.domain.PageDTO;
    import org.galapagos.service.TravelService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import lombok.AllArgsConstructor;
    import lombok.extern.log4j.Log4j;
    
    @Controller
    @Log4j
    @RequestMapping("/travel")
    @AllArgsConstructor
    public class TravelController {
    	
    	@Autowired
    	private TravelService service;
    	
    	
    	@GetMapping("/list")
    	public void list(@ModelAttribute("cri") Criteria cri,
    			Model model) {
    	
    		int total = service.getTotal(cri);
    
    		model.addAttribute("list", service.getList(cri));
    		model.addAttribute("pageMaker", new PageDTO(cri, total));	
    
    	}
    
    }

     
     
    *HomeController 조정

    board -&amp;amp;amp;gt; travel

     
     


    VO 객체 정의 ➡️ Mapper 인터페이스 정의 ▶ Mapper xml 정의 ▶ 테스트 ➡️Service 인터페이스 정의 + 구현
    ➡️구현한 걸로 테스트 ➡️Controller 정의 ➡️jsp (화면 정의)


    📍목록보기

    list.jsp

     
     
    views 에서 travel 폴더 생성
    list.jsp 생성
    (앞으로 이렇게 복사해서 travel에 맞게 고치는 걸 반복할 예정)

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>100대 관광지</title>
    
    <script>
    	$(document).ready(function() {
    
    		let searchForm = $('#searchForm');
    		
    		$('#searchForm button').on('click', function(e) { 
    			let type =searchForm.find('option:selected');
    			if (!type.val()) {
    				alert('검색종류를 선택하세요');
    				return false;
    			}
    
    			let keyword = searchForm.find('input[name="keyword"]');
    			if (!keyword.val()) { //필수요소 체크
    				keyword.focus();
    				alert('키워드를 입력하세요');
    				return false;
    			}
    
    			searchForm.find('input[name="pageNum"]').val('1');
    			e.preventDefault();
    			searchForm.submit();
    		});
    
    	});
    </script>

    <script>태그 검색 기능이 중복되므로 정리하기
     
    1. resources에서 js폴더에 javascript 파일 생성
    이름 : search.js

     
    2. <script> 태그 안에 부분만 복사해서 search.js 로 옮긴 후 <script>태그 안에 경로로 처리해 주기
     

    ⬇️search.js 더보기 클릭

    더보기
     	$(document).ready(function() {
    
    		let searchForm = $('#searchForm');
    		
    		$('#searchForm button').on('click', function(e) { 
    			let type =searchForm.find('option:selected');
    			if (!type.val()) {
    				alert('검색종류를 선택하세요');
    				return false;
    			}
    
    			let keyword = searchForm.find('input[name="keyword"]');
    			if (!keyword.val()) { //필수요소 체크
    				keyword.focus();
    				alert('키워드를 입력하세요');
    				return false;
    			}
    
    			searchForm.find('input[name="pageNum"]').val('1');
    			e.preventDefault();
    			searchForm.submit();
    		});
    
    	});

    list.jsp 깔끔해짐

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    <%@include file="../layouts/header.jsp"%>
    
    <script src="/resources/js/search.js">
    </script>
    
    <title>100대 관광지</title>

     
    +) 예전 프로젝트 list.jsp도 수정 가능

    쫄보라 주석처리함

     
    list.jsp
    pagination이랑 추가(원래 글쓰기) 기능 xml

    <%@include file="../common/pagination.jsp"%>
    
    <div class="text-right">
    	<a href="register" class="btn btn-primary"> <i class="far fa-edit"></i>
    		추가
    	</a>
    </div>

     
    list.jsp
    a href #으로 처리했던 것 criteria 사용하기 위해 primary key인 no 정보 함께 주기

    <a href="${cri.getLink('get')}&no=${travel.no}">${travel.title}</a>

    이제 검색 잘 됨


    📍상세보기

    get.jsp

     
    Controller부터 시작 
     
    /get, /modify 
     

    	@GetMapping({ "/get", "/modify" })
    	public void get(
    			@RequestParam("no") Long no, 
    			@ModelAttribute("cri") Criteria cri, 
    			Model model) {
    		
    		model.addAttribute("travel", service.get(no));
    	}

    jsp 구조 유사할 거니까 board에 있던 jsp를 travel 폴더로 복사해 오기

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
    <%@ include file="../layouts/header.jsp"%>
    
    <script>
    	$(document).ready(function() {
    		$('.remove').click(function() {
    			// 클릭 이벤트 핸들러 함수
    			if (!confirm('정말 삭제하시겠습니까?'))
    				return;
    			document.forms.removeForm.submit();
    		});
    	});
    </script>
    
    <c:if test="${result=='success'}">
    	<script>
    		alert("수정이 완료되었습니다!");
    	</script>
    </c:if>
    
    <h1 class="page-header">
    	<i class="far fa-file-alt"></i> ${travel.title}
    </h1>
    <div class="d-flex justify-content-between">
    	<div>
    	${travel.region}
    	</div>
    	<div>
    		${travel.phone}"
    	</div>
    </div>
    	<div>주소 : ${travel.address}</div>
    <hr>
    	<div>제목 : ${travel.description}</div>
    
    <div class="mt-4">
    	<a href="${cri.getLink('list')}" class="btn btn-primary list">
    	<i class="fas fa-list"></i>목록</a>
    	<a href="${cri.getLink('modify')}&no=${travel.no}" class="btn btn-primary modify">
    	<i class="far fa-edit"></i>수정</a> 
    	<a href="#" class="btn btn-danger remove">
    	<i class="fas fa-trash-alt"></i>삭제</a>
    </div>
    
    <form action="remove" method="post" name="removeForm">
    	<input type="hidden" name="no" value="${travel.no}" />
    	<input type="hidden" name="pageNum" value="${cri.pageNum}" />
    	<input type="hidden" name="amount" value="${cri.amount}" />
    	<input type="hidden" name="type" value="${cri.type}" />
    	<input type="hidden" name="keyword" value="${cri.keyword}" />
    </form>
    
    <%@ include file="../layouts/footer.jsp"%>

     
     


    ✨description 내용 줄바꿈 넣어주기

    <br> 태그 사용해서 디비버에서 직접하기

    -- 원본 업데이트 하기 replace/ . 부분을 .<br>로 바꾸기. 안에 내용 다 바꿀 거니 where 절 필요 X
    update travel
    set
    	description = replace(description, ".", ".<br>");

    바꾸기 전
    〈br〉태그 후 근데 상태가 영;

    -- br 태그 지우고 다시
    update travel
    set
    	description = replace(description, "<br>", "");

    점(.) 뒤에 띄어쓰기로 한 칸 넣어줘야한다. 안 그러면 소수점으로 인식

    -- .뒤에 띄어쓰기 있는 버전
    update travel
    set
    	description = replace(description, ". ", ".<br>");

    편-안


    ✨지도 넣기

     
    get.jsp
    지도 놓을 위치 잡기
    *height 낮게 잡으면 잘 안 보이니까 300px 주기

    <hr>
    	<div class="mt-4">제목 : ${travel.description}</div>
    <hr>
    	<div class="mt-4">주소 : ${travel.address}</div>
    <div id="map" style="width:100%; height:300px; background:gray">
    </div>

     

    회색 박스 위치(60px 주면 이만큼 나온다)

    카카오맵으로 넣기

    절차

    🖤개발자 등록
    https://developers.kakao.com/

    1. 카카오 아이디 있어서 그걸로 로그인하면 된다.

    좌측 이미지의 제품소개 버튼을 눌러서 내리면 우측 이미지와 같은 API 안내가 뜬다.


    2.  내 어플리케이션 - 어플리케이션 추가하기 

    3. 앱 이름과 사업자명 입력 후 저장 

    4. 이제 내 어플리케이션에서 뜨면 클릭

    5. 삼단바 눌러서 [플랫폼] - [Web플랫폼 등록]

    서버주소포트번호, 본인 실제 ip 주소 3가지 등록 후 저장
    *실제 프로젝트 시, 클라우드 서버 주소를 ip주소 위치에 넣어줘야 한다.
    ip: 172.30.1.39

    6. [요약정보] - JavaScript키를 복사해 두자. ⭐⭐⭐

    Kakao 지도 API
    https://apis.map.kakao.com/

    스크립트 작업
    get.jsp 젤 하단 부분에서 작업

     

    <script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=<APP KEY>">
    </script>
    <script>
      let mapContainer = document.getElementById('map');
      //  지도 제어 코딩
    </script>

    여기서 APP KEY 부분에 아까 발급받은 JavaScript 키를 넣어야 한다.
    꺽쇠 <> 없애줘야한다❗

    javascript 키 삽입

    순수 자바스크립트로 DOM 처리할 것이다.

    let mapContainer = document.getElementById('map');

    만들어둔 id가 map인 해당 div 태그에 대한 참조를 달라는 뜻 
     
    앞에 type이랑 app key 뒤에 &libraries=services(=>Geocoder인식용) 추가해서 최종 코드
    type은 굳이 안 넣어도 동작하는 것 같다.

    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=48ccf7434c3170f3a6d7c80234a050c8&libraries=services">
    </script>

    • 지도 객체 만들기 🌱

    Map 생성자, 첫 번째 인자:getElementByID / 두 번째 인자 : 지도를 어떻게 만들지 옵션
    속성명 : center(중심좌표), level(확대레벨)
    *LatLng : 위도, 경도를 나타내는 객체

    지도 객체 Map (오타 *LanLng이다.)
    LatLng 객체

     

    travel에 있던 곳 하나 주소 구글맵에 검색해서 [여기를 출발지로 설정]
    주소창에 나오는 위도, 경도

    위에서 잡았던 위도와 경도를 코드 안에 함께 넣어서 옵션 지정

    <script>
    //  지도 제어 코딩
      let mapContainer = document.getElementById('map');
      let mapOption = { 
    		  center: new kakao.maps.LatLng(37.8103437,128.8815612), // 중심좌표
    		  level: 3 // 지도의 확대 레벨
    		  };
    let map = new kakao.maps.Map(mapContainer, mapOption); 
    </script>

    • 마커 넣기📍

     

    Marker 클래스 사용법

    <script> 태그 안에 중심좌표랑 같이 넣어주기. (아까 위도, 경도 똑같이)
    ⭐원래는 DB에 해당 중심좌표 위치를 같이 넣어주는 게 좋다.

    // 마커가 표시될 위치
    	var markerPosition = new kakao.maps.LatLng(37.8103437, 128.8815612); 
    	// 마커 생성
    	var marker = new kakao.maps.Marker({
    	position: markerPosition
    	});
    	// 마커가 지도 위에 표시되도록 설정
    	marker.setMap(map);

     

    보통 전처리를 통해서 DB에 중심좌표를 넣어두지만 우리는 안 그랬으니 GeoCode를 사용해 보자

    더보기
    GeoCode

    디폴트 생성자로 생성을 시켜서 addressSearch(주소문자열, 콜백함수) 메서드를 쓰는 것
    콜백함수 매개변수 : result, status(찾기 성공 여부 - 처리결과상 성공하면 result에 위도, 경도 객체가 리턴)
    ⭐result는 배열에 담겨서 리턴되기 때문에 배열처리가 필요하다!!(한 개의 주소가 여러 군데에 있을 수 있다.)
     
    지도 <script> 안에서 앞부분에 넣기
    ❤️${travel.address} : 주소로 직접 쳐야할 부분을 대신한 el

    <script>
    //Geocode
     let geocoder = new kakao.maps.services.Geocoder();
     let address ='${travel.address}'; //주소 직접 치지말고 el로 가져오기

     
     
    ❗주의사항
    자바스크립트의 모든 함수는 비동기 함수이다.
    동기:함수실행이 끝날 때까지 기다려줌
    비동기는 기다려주지 않아 ! => 콜백 함수가 항상 등록된다.
    addressSearch 하고 바로 리턴된다는 뜻
     
    첫 번째 좌표로 위도, 경도를 만들고 그 마커를 맵의 중심에 위치시킬 것.

    //Geocode
     let geocoder = new kakao.maps.services.Geocoder();
     let address ='${travel.address}'; //주소 직접 치지말고 el로 가져오기 
     //콜백함수 매개변수:result, status
     geocoder.addressSearch(address, function(result, status) {
    	 if (status === kakao.maps.services.Status.OK) {
    	 // 배열의 첫번째 위치로 이동
    	 var coords = new kakao.maps.LatLng(result[0].y, result[0].x);
    	 var marker = new kakao.maps.Marker({
    	 map: map,
    	 position: coords //*coords : 이미지 맵에서 영역의 좌표를 지정하는 속성
    	 });
    	 // 지도의 중심을 결과값으로 받은 위치로 이동시킵니다
    	 map.setCenter(coords);
    	 }
     });

    🧙 중복코드 및 하드코딩 고치기

     

    1. 마커 중복코드 주석처리

    2. 중심좌표 이동 중복코드 지우고 하드코딩 부분 coords 로 바꾸기

    위에서 let으로 coords가 설정됨

    3. else 처리

    Status가 OK가 아닌 경우도 있을 수 있으므로 해야 한다.
    (잘못된 주소, 서버 이상 등)

    파란 블록 부분

     


    +) 지도에서 마커 누르면 뜨는 information 창 만들기🌱
    https://apis.map.kakao.com/

    나중에 해 보기


    📍수정하기

    modify.jsp

     
    Controller로 가서 post 요청 찾기
     

    	@PostMapping("/modify")
    	public String modify(
    			TravelVO travel,
    			@ModelAttribute("cri") Criteria cri, 
    			RedirectAttributes rttr) {
    		
    	  service.modify(travel);
    	  
    	  return "redirect:" + cri.getLink("/travel/get") +
    			  "&no=" + travel.getNo();
    
    	  
    	 }

    modify.jsp 복사해서 수정하기

     

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
    
    <%@ include file="../layouts/header.jsp"%>
    <%-- 개별 페이지 --%>
    <link rel="stylesheet"
    	href="/resources/css/summernote/summernote-lite.min.css">
    <script src="/resources/js/summernote/summernote-lite.min.js"></script>
    <script src="/resources/js/summernote/lang/summernote-ko-KR.min.js"></script>
    
    <script>
    	$(document).ready(function() {
    		$('#content').summernote({ //jQuery Plugin < 해당 기능 확장
    			height : 300, // 에디터 높이
    			focus : true, // 에디터 로딩후 포커스를 맞출지 여부
    			lang : "ko-KR", // 한글 설정
    		});
    	});
    	// 기본 글꼴 설정
    	$('#summernote').summernote('fontName', 'Arial');
    </script>
    
    
    <h1 class="page-header">
    	<i class="far fa-edit"></i>여행지 정보 수정
    </h1>
    <div class="panel panel-default">
    	<div class="panel-body">
    		<form role="form" method="post">
    			<input type="hidden" name="pageNum" value="${cri.pageNum}" />
    			<input type="hidden" name="amount" value="${cri.amount}" />
    			<input type="hidden" name="no" value="${travel.no}">
    			<div class="form-group">
    				<label>권역</label> <input name="region" class="form-control"
    					value="${travel.region}" required>
    			</div>
    			<div class="form-group">
    				<label>제목</label> <input name="title" class="form-control"
    					value="${travel.title}" required>
    			</div>
    			<div class="form-group">
    				<label>주소</label> <input name="address" class="form-control"
    					value="${travel.address}" required>
    			</div>
    			<div class="form-group">
    				<label>전화번호</label> <input name="phone" class="form-control"
    					value="${travel.phone}" required>
    			</div>
    			<div class="form-group">
    				<label>내용</label> <!-- id는 summernote에서 넘어가는 #이하와 일치해야 한다. -->
    				<textarea name="description" class="form-control" id="content" rows="10">${travel.description}</textarea>
    			</div>
    
    			<button type="submit" class="btn btn-primary">
    				<i class="fas fa-check"></i>확인</button>
    			<button type="reset" class="btn btn-primary">
    				<i class="fas fa-undo"></i>취소</button>
    			<a href="${cri.getLink('get')}&no=${travel.no}" class="btn btn-primary get">
    			<i class="fas fa-list"></i>돌아가기</a>
    		</form>
    	</div>
    </div>
    
    <%@ include file="../layouts/footer.jsp"%>

    💁이쯤에서 당신 ^^!

    summernote 적용이 안 되나요?
    주소창 url에 혹시 " Controller " 가 붙어있진 않나요?^^
    톰캣 처음 등록할 때 module에서 /Controller =>   / 로 바꾸는 거 까먹지 마라 젭알
     


    📍등록하기

    register.jsp

     
    목록보기 첫 페이지로 이동하게 하기

    	@GetMapping("/register")
    	public void register() {
    	}
    
    	@PostMapping("/register")
    	public String register(TravelVO travel, RedirectAttributes rttr) {
    		service.register(travel);
    		rttr.addFlashAttribute("result", travel.getNo());
    		
    		return "redirect:/travel/list";
    	}
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
    <%@ include file="../layouts/header.jsp"%>
    
    <!-- summernote -->
    <link rel="stylesheet"
    	href="/resources/css/summernote/summernote-lite.min.css">
    <script src="/resources/js/summernote/summernote-lite.min.js"></script>
    <script src="/resources/js/summernote/lang/summernote-ko-KR.min.js"></script>
    <script>
    	$(document).ready(function() {
    		$('#content').summernote({
    			height : 300, // 에디터높이
    			focus : true, // 에디터로딩후포커스를맞출지여부
    			lang : "ko-KR",// 한글설정
    		});
    	});
    	// 기본글꼴설정
    	$('#content').summernote('fontName', 'Arial');
    </script>
    
    <%--개별페이지--%>
    <h1 class="page-header">
    	<i class="far fa-edit"></i>여행지 등록
    </h1>
    <div class="panel panel-default">
    	<div class="panel-heading">여행지를 등록하세요.</div>
    	<div class="panel-body">
    		<form role="form" method="post">
    			<div class="form-group">
    				<label>권역</label> <input name="region" class="form-control">
    			</div>
    			<div class="form-group">
    				<label>제목</label> <input name="title" class="form-control">
    			</div>
    			<div class="form-group">
    				<label>주소</label> <input name="address" class="form-control">
    			</div>
    			<div class="form-group">
    				<label>전화번호</label> <input name="phone" class="form-control">
    			</div>
    			<div class="form-group">
    				<label>내용</label> <!-- id는 summernote에서 넘어가는 #이하와 일치해야 한다. -->
    				<textarea name="description" class="form-control" id="content"></textarea>
    			</div>
    
    			<button type="submit" class="btn btn-primary">
    				<i class="fas fa-undo"></i>확인
    			</button>
    			<button type="reset" class="btn btn-primary">
    				<i class="fas fa-undo"></i>취소
    			</button>
    			<a href="javascript:history.back()" class="btn btn-primary"> <i class="fas fa-list"></i>목록
    			</a>
    		</form>
    	</div>
    </div>
    <%@ include file="../layouts/footer.jsp"%>

     

    📍삭제하기

    remove

    Controller

    	@PostMapping("/remove")
    	public String remove(
    			@RequestParam("no") Long no, 
    			@ModelAttribute("cri") Criteria cri, 
    			RedirectAttributes rttr) {
    		
    		service.remove(no);
    		return "redirect:/travel/list" + cri.getLink();
    
    	}

     
    후 완성!! ^-ㅜ 
     
     

    더 다듬어야 한다 어차피

     
    🌱디렉토리 참고용 + zip 파일

    src/main/java + src/main/resources

    src/test/java & resources

    css, js, jsp

    저는 일단 오류가 안 나는데 보실 분들은 보십시오.

    *한글 인코딩이 깨질 수 있습니다 ㅜㅜ

    ex02-05(수정본).zip
    3.96MB

Designed by Tistory.