20240226 스프링(갤러리 상세보기(detail), 갤러리 컨트롤러/서비스 상속만들기 , 공지게시판)

2024. 2. 26. 17:532023.11.21-2024.05.31

요구사항 확인-> 클라이언트 요구사항 받아서 갤러리 수정 등

 

갤러리 폴라로이드 형식으로 보이게 바꾸기

 

 

gallery.jsp > 위에 사진처럼 그리드 형식으로 나오게 변경하기, 부트스트랩 이용해서 만들었다.

<%@ 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 lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport"
	content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Trinity Company - 갤러리</title>
<!-- Favicon-->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
<link rel="shortcut icon" type="image/x-icon" href="assets/favicon.ico" />
<link rel="apple-touch-icon" sizes="57x57"
	href="assets/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60"
	href="assets/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72"
	href="assets/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76"
	href="assets/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114"
	href="assets/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120"
	href="assets/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144"
	href="assets/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152"
	href="assets/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180"
	href="assets/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192"
	href="assets/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32"
	href="assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96"
	href="assets/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16"
	href="assets/favicon-16x16.png">
<link rel="manifest" href="assets/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Font Awesome icons (free version)-->
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js"
	crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700"
	rel="stylesheet" type="text/css" />
<link
	href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700"
	rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="css/styles.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script
	src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script type="text/javascript">
        const Toast = Swal.mixin({
        	  toast: true,
        	  position: 'center-center',
        	  showConfirmButton: false,
        	  timer: 3000,
        	  timerProgressBar: true,
        	  didOpen: (toast) => {
        	    toast.onmouseenter = Swal.stopTimer;
        	    toast.onmouseleave = Swal.resumeTimer;
        	  }
        	});
        
        function galleryDetail(no){
        	location.href="./galleryDetail@" +no;
        }


</script>
</head>

<!-- 2024.02.26 sns방식으로 갤러리 만들기 -->
<body id="page-top">
	<!-- Navigation-->
	<%@ include file="menu.jsp"%>

	<!-- gallery -->
	<section class="page-section" id="gallery">
		<div class="container">
			<div class="text-center">
				<div class="row">
					<c:forEach items="${list }" var="row">
						<div class="col-md-4 col-sm-6 mb-4">

							<div class="card h-100">
								<img class="card-img-top" src="./upfile/s_${row.gfile}" onclick="galleryDetail(${row.gno})">
								<div class="card-body">
									<h5 class="card-title">${row.gtitle}</h5>
									<div class="like-btn" onclick="like(${row.glike})">
										
									</div>
								</div>
								<div class="card-footer">
									<small class="text-muted"> <img src="./img/like.png"
										alt="heart" width="20"> <span class="likes">${row.glike}</span>
										| 날짜: ${row.gdate}
									</small>
								</div>
							</div>
						</div>
					</c:forEach>
				</div>
			</div>
			<button class="btn btn-outline-secondary" type="button"
				onclick="location.href='./galleryInsert'">글쓰기</button>
			<button class="btn btn-outline-secondary" type="button"
				onclick="location.href='./board'">게시판으로</button>
		</div>
	</section>

	<!-- Bootstrap core JS-->
	<script
		src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
	<!-- Core theme JS-->
	<script src="js/scripts.js"></script>
	<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
	<!-- * *                               SB Forms JS                               * *-->
	<!-- * * Activate your form at https://startbootstrap.com/solution/contact-forms * *-->
	<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
	<script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
</body>
</html>

 

 

gallery-mapper.xml 수정

 

	<!-- 2024.02.26 sns방식으로 갤러리 만들기 -->
      <select id="galleryList" resultType="galleryDTO">
      SELECT gno, gtitle, gfile, 
      if(
      date_format(now(), '%Y-%m-%d') = date_format(gdate, '%Y-%m-%d'), 
      date_format(gdate, '%h:%i'), date_format(gdate, '%Y-%m-%d')) 
      as gdate, glike FROM gallery WHERE gdel=1 ORDER BY gno DESC
   	</select>

 

 

 

 

 

 

반응형으로 창 크기에 따라서 사진 크기가 달라짐

 

갤러리에 디테일 만들기: 사진을 누르면 상세보기 나오게 만들기

>갤러리 번호 가져가서 만들기

 

 

gallery.jsp >img 태그에 onclick 설정(row.gno 설정해서 번호 불러오기)

: 이미지를 누르면 상세보기로 이동할 거다.

 

 

<img class="card-img-top" src="./upfile/s_${row.gfile}" onclick="galleryDetail(${row.gno})">

 

 

 

gallery.jsp 상단에 get방식의 스크립트를 짜준다.

        function galleryDetail(no){
        	location.href="./galleryDetail/"+no;
        }

 

>기존에 컨트롤러로 넘어가게 쓰던 방식(주석)과 다른방식

 

 

 

galleryController에 > galleryDetail  만들어주기

 

galleryController

// 2024.02.26 galleryDetail 요구사항 확인psd
	@GetMapping("/galleryDetail@{no}")
	public String galleryDetail(@PathVariable("no") String no, Model model) {
		// System.out.println("경로ㅣ: " +no);
		if (util.intCheck(no)) {
			GalleryDTO detail = galleryService.detail(no);
			model.addAttribute("detail", detail);
			return "galleryDetail";
		} else {
			return "redirect:/error";
		}
	}

 

 

galleryDetail/번호 로 나오면 된다. 아래와 같이 콘솔창에도 경로가 뜬다.

system.out.println으로 콘솔창에 뜨는 경로

 

 

이제 boardDtail 한 것 처럼 만들어주기

< 경로에 계속 /  를 두개 붙여서 만드니 css가 꼬여서  이미지  css 를 찾아갈 수 없다.

컨트롤러와 jsp에 /를 @로 변경 ..>

 

 

갤러리 컨트롤러> 갤러리 서비스> 갤러리DAO > 매퍼 > jsp 만들기

 

 

galleryController >galleryDetail 만들기


	// 2024.02.26 galleryDetail 요구사항 확인psd
	@GetMapping("/galleryDetail@{no}")
	public String galleryDetail(@PathVariable("no") String no, Model model) {
		// System.out.println("경로ㅣ: " +no);
		if (util.intCheck(no)) {
			GalleryDTO detail = galleryService.detail(no);
			model.addAttribute("detail", detail);
			return "galleryDetail";
		} else {
			return "redirect:/error";
		}

 

 

galleryService>detail 만들기

	public GalleryDTO detail(String no) {
		GalleryDTO dto = new GalleryDTO();
		
		if(util.getSession().getAttribute("mid") != null) {
			int No = Integer.parseInt(no);
			dto.setGno(No);
		
			return galleryDAO.detail(No);
			
		}return dto;

 

 

galleryDAO에 detail 만들기

	public GalleryDTO detail(int no) {
		
		return sqlSession.selectOne("gallery.galleryDetail", no);
	}

 

gallery-mapper.xml > galleryDetail 만들기

   	<select id="galleryDetail" parameterType="Integer" resultType="galleryDTO">
   		SELECT g.gno, g.gtitle, g.gfile, g.gcontent,
   		date_format(g.gdate, '%Y년 %m월 %d일 %h시 %i분 %s초')as gdate,
   		g.glike, m.mname, m.mid
   		FROM gallery g JOIN member m on g.mno=m.mno WHERE g.gno=#{no}
   	</select>

 

만들때 DAO 부분> 리턴 값에 주의!

 

 

galleryDetail.jsp 만들기

<%@ 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 lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport"
	content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>상세보기</title>
<!-- Favicon-->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
<link rel="shortcut icon" type="image/x-icon" href="assets/favicon.ico" />
<link rel="apple-touch-icon" sizes="57x57"
	href="assets/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60"
	href="assets/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72"
	href="assets/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76"
	href="assets/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114"
	href="assets/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120"
	href="assets/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144"
	href="assets/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152"
	href="assets/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180"
	href="assets/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192"
	href="assets/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32"
	href="assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96"
	href="assets/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16"
	href="assets/favicon-16x16.png">
<link rel="manifest" href="assets/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Font Awesome icons (free version)-->
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js"
	crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700"
	rel="stylesheet" type="text/css" />
<link
	href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700"
	rel="stylesheet" type="text/css" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="css/styles.css" rel="stylesheet" />
<link href="css/board.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
	integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
	crossorigin="anonymous" referrerpolicy="no-referrer"></script>

</head>


<body id="page-top">
	<!-- Navigation-->
	<%@ include file="menu.jsp"%>


	<!-- 2024.02.26 gallery detail -->
	<section class="page-section" id="gallery">
		<div class="container">
				<hr>
				<h1 class="mt-5">갤러리 상세보기</h1>
			<div class="card mb-4">
				<div class="card-body">
				<div class="row">
				 <div class="col-12">
					<div class="h2">${detail.gno }/ ${detail.gtitle }</div>
					<div class="row p-2 bg-transparent">
						<div class="col align-middle ">
							${detail.mname }
							<c:if test="${detail.mid eq sessionScope.mid}">

								<img alt="edit" src="./img/update.png">
								<img alt="delete" src="./img/delete.png" title="글삭제"
									onclick="deletePost(${detail.gno })">
							</c:if>
						</div>
						 <div class="col align-middle text-end">${detail.gdate }</div>
                            </div>
                        </div>
                    </div>
                    <div class="row justify-content-center mt-4">
					 <div class="col-6 text-center">
						<img class="img-fluid" alt="사진" src="./upfile/${detail.gfile }">
					</div>
					</div>
					<div class="mt-4 h-auto text-center">${detail.gcontent}</div>
					
				</div>
			</div>
			</div>

		<div class="text-center">
		<button class="btn btn-success" onclick="location.href='./gallery'">갤러리</button>
		<button class="btn btn-success"
			onclick="location.href='./galleryInsert'">갤러리인서트</button>
	</div>


	</section>
	<!-- Bootstrap core JS-->
	<script
		src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
	<!-- Core theme JS-->
	<script src="js/scripts.js"></script>
	<script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
</body>
</html>

 

 

*사진 창 크기에 따라서 변하는 반응형으로 만들기,

*내용 안나오는거 수정하기

 

>반응형 img 태그 안에 img-fluid 를 넣으면 된다.

	<img class="img-fluid" alt="사진" src="./upfile/${detail.gfile }">

 

 

 

창 크기에 따라서 사진 크기도 바뀐다.

 

>내용이 안나오던건 gallery-mapper.xml 부분에 오타가 있어서 안나왔다. 수정하니까 내용도 같이 나온다.

 

 

 

 

 

이후에는 sts4 > 전자정부 사용나느 걸로

 

 

 

@Autowired 다빼버리기

부모페이지가 한개 만들어지고, 세션을 각 페이지마다 분배하기

상위라는 뜻으로 dao에 클래스 한개 만들기

 

AbstractDAO 만들기

 

 

package org.mask.dao;
//2024.02.26 psd
//부모형태로 존재할 것이다.  > @ 없음

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;

public class AbstractDAO {
	
	@Autowired
	private SqlSession sqlSession;

}

 

 

각 DATO에 상속 시켜주고 @ Autowired 삭제하기

아래는 BoardDAO 예시, 나머지 DAO도 다 삭제하고 상속 넣어줬다.

삭제하고 나면 오류가 난다.

 

일단 DAO파일 모두 변경해주면 오류가 나는데 오류는 접근제한자를 열면된다.

전부 @ Autowired  삭제한다.

 

 

부모 DAO(AbstractDAO)에서 private> public 으로 변경

package org.mask.dao;
//2024.02.26 psd
//부모형태로 존재할 것이다.  > @ 없음

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;

public class AbstractDAO {
	
	@Autowired
	public SqlSession sqlSession;

}

 

 

오류가 사라진다.

 

 

 

서비스 변경

 

AbstractService 만들기

package org.mask.service;

import org.mask.util.Util;
import org.springframework.beans.factory.annotation.Autowired;

public class AbstractService {
	@Autowired
	Util util;
}

 

galleryService > 상속해주고 @ Autowired  Util 삭제

@Service("galleryService")
public class GalleryService extends AbstractService {
	@Autowired
	private GalleryDAO galleryDAO;

 

 

 

GalleryController 변경

 

GalleryService 에 있는  @Autowired 삭제 > @Resource(name="galleryService") 로 변경

@ Autowire을 삭제한다.

 

	@Resource(name="galleryService")
	private GalleryService galleryService;

 

 

 

 

그리고 넘어가기전에 해야할 것. 나는 이게 안되있어서 임포트가 안됐다.

pom.xml > javax.annotation 추가 되어있야 @ Resource 를 쓸 수 있다.

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

 

 

 

galleryService> 이름에 Impl 붙여서 만들기

@Service("galleryService")
public class GalleryServiceImpl extends AbstractService {
	@Autowired
	private GalleryDAO galleryDAO;

 

 

new>interface 만들기> GalleryService

package org.mask.service;

public interface GalleryService {

}

객체 못만든다. 상속목적으로 강제성을 띈다.

 

 

galleryServiceImpl> 상속을 추가해 준다.

@Service 뒤 괄호에 이름 galleryService 적어준다.  이 이름이 컨트롤러 이름과 같아야한다.

GalleryController
GalleryService

 

갤러리 인터페이스에 추가(객체 없어서 끝에 ; 로 끝낸다)

package org.mask.service;

import java.util.List;

import org.mask.dto.GalleryDTO;

public interface GalleryService {
	
	public int galleryInsert(GalleryDTO dto);
	
	public List<GalleryDTO> galleryList();
	
	public GalleryDTO detail(String no);

}

> 이렇게 하고 나면 갤러리 컨트롤러에 오류가 없어진다.

 

 

 

 

전자정부로 사용하기 new>other 이거는 그냥 보는 것.

 

 

 

 

컨트롤 누르고 서비스로 들어가보자

여기 뭐 삭제 되었다...뭔지를 모르겠네/..ㅎ

 

전자정부에서는 이런식으로 다 만들어져 있다. >>그냥 이런 모양이 있다 알려주려고 찾아가 본 것.

 

 

 

 

 

내일 할 것.

*공지 게시판  notice

NoticeController

NoticeService>2

NoticeServiceImpl

NoticeDAO

NoticeDTO >1

notice-mapper.xml

 

*dto에 들어갈 내용 >1

int nno,ndel,nlike,nread

String ntitle,ncontent,ndate

*DB >2

table name : notice

column: nno(int, auto,PK),ndel(int1, 기본1), nread(int,기본1), nlike(int, 기본1),ntitle(VARCHAR 50),ncontent( VARCHAR 500), ndate(datetime, current timestamp)

 

NoticeSerive에 들어갈 추상메소드 >3 일단 서비스만 만들기

public List<NoticeDTO> noticeList();

public NoticeDTO detail(int no);

public int noticeWrite(NoticeDTO);

public int noticeDel(int no);

public int noticeUpdate(NoticeDTO);