728x90
반응형

📖 컨트롤러의 기본 사용

 

spring 프로젝트의 파일을 살펴보면 src/main/java 밑에 패키지가 하나 있는 것을 볼 수 있다.

 

 

 

 

 

동일한 위치에 controller만을 모아둘 수 있는 패키지를 만들고, 작업을 원하는 컨트롤러를 생성한다.(class 생성)

 

 

 

 

 

 

<FilmController.java>

package com.practice.fjdkslvn.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class FilmController {
	
	@GetMapping("/film") 
	public String filmList() {
		System.out.println("FilmController.test()실행");
		
		return "/WEB-INF/jsp/filmList.jsp";
	}
}

클래스 위에 @Controller 어노테이션을 작성하여 컨트롤러 작동이 가능하게 한다.

 

@GetMappint("/film") 어노테이션을 작성하여 '/film'으로 get 요청을 받았을 경우 처리할 수 있도록 filmList 메서드를 생성하였다. spring은 아주 편리하게도 return 값으로 jsp의 경로를 반환하면 자동으로 forward 해준다.

 

여기서, forward를 위해 return하는 jsp경로를 더욱 편리하게 반환하는 방법이 있다.

 

 

 

 

 

 

<FilmController.java>

@Controller
public class FilmController {
	
	@GetMapping("/film") 
	public String filmList() {
		System.out.println("FilmController.test()실행");
		
		return "filmList";
	}
}

- return값으로 jsp 이름만 반환하는 방법

 

 

@Controller
public class FilmController {
	
	@GetMapping("/film") 
	public void filmList() {
		System.out.println("FilmController.test()실행");
        // 반환값이 없으면 메서드 명을 사용하여 forward 진행
	}
}

- return값이 없기 때문에 메서드 명을 사용하여 forward가 진행되는 방법

 

=> 2개의 방법 모두 이전과 달리 /WEB-INF/jsp/.jsp를 생략하고 사용하는 방법이다. 다만, 이렇게 사용하기 위한 설정이 필요하다.

 

 

 

 

 

 

src/main/resources를 열면, 애플리케이션을 구동할 때 자동으로 실행되는 application.properties를 확인할 수 있다.

 

 

 

 

 

<application.properties>

#server config
server.port=80

# db config
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3307/sakila (//호스트명:포트번호/DB)
spring.datasource.username=사용자명
spring.datasource.password=비밀번호

# jsp config
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

server.port=80을 통해 사용할 포트번호를 80으로 변경한다. 변경 전에는 보통 8080으로 설정 되어있는데, 80으로 변경하면 http://localhost:8080/film -> http://localhost/film 과 같이 간편하게 접근 가능하다.

 

본인은 mariaDB를 사용하기 때문에 관련 코드를 작성해주었다. 자신이 사용하고 있는 설정에 맞게 입력해주면 될 것 이다.

 

마지막으로 forward를 위한 jsp경로를 간단하게 return하기 위해 사용되는 부분이다. 여기서 prefix는 접두어로 사용되고 suffix는 접미어로 사용된다. 해당 설정으로 인해 간단하게 jsp명만 return하는 경우 "WEB-INF/jsp/리턴값.jsp"과 같은 경로로 forwarding이 진행된다. return값이 없어서 메서드명이 전달되는 경우도 마찬가지다.

 

 

 

 

 

 

이제 jsp를 만들어야 한다. 실제로는 webapp까지밖에 없을것이다.

 

webapp 밑에 WEB-INF파일을 만들고 그 아래에는 jsp를 모아둘 파일을 생성한 뒤, 원하는 jsp파일을 생성한다.

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>영화 목록 출력 예정</h1>
</body>
</html>

jsp화면은 간단하게 제목만 출력하도록 했다.

 

 

 

 

 

🎵실행

프로젝트 우클릭 -> Run As -> Spring Boot App을 클릭하여 서버를 실행한다.

 

 

 

 

 

 

localhost/film을 입력하여 get방식으로 요청하면, filmList.jsp가 forward되어 나오고 console에 컨트롤러가 실행되었음을 나타내는 system.out.print가 출력된다.

 

 

 

 

 

 

 

🔖<FilmController.java> =>  값 받는 방법

@Controller
public class FilmController {
	
	@GetMapping("/film") 
	public String filmList(int filmId, String title) {
		System.out.println("FilmController.test()실행");
		System.out.println("영화번호 : " + filmId);
		System.out.println("제목 : "+title);
		
		return "filmList";
	}
}

@GetMapping 어노테이션을 사용한 경우에 get방식으로 데이터를 전달하면, 메서드 입력변수로 해당 값들을 받을 수 있다.

 

 

위와 같이 ?filmId=1&title="강철의 연금술사" 값을 넘긴다.

 

 

 

 

 

console을 확인하면 값이 넘어온 것을 확인할 수 있다.

728x90
반응형
728x90
반응형

Spring | Tools

 

Spring Tools 4 is the next generation of Spring tooling

Largely rebuilt from scratch, Spring Tools 4 provides world-class support for developing Spring-based enterprise applications, whether you prefer Eclipse, Visual Studio Code, or Theia IDE.

spring.io

 

 

💾 Spring 환경설정

위 링크에 들어가서 해당 파일을 다운로드 받고 실행한다.

 

 

 

 

 

 

 

SpringToolSuite4를 더블클릭하여 이클립스를 실행할 수 있다.

 

 

 

 

 

 

 

 

프로그램을 실행한 후, Help -> Eclipse Marketplace를 클릭하여 마켓을 연다.

 

 

 

 

 

 

 

 

eclipse web 검색 -> Eclipse Web Developer Tools 3.23 설치

mybatis 검색 -> MyBatipse 1.2.4 설치

 

동의 또는 다음을 모두 누르고, restart now가 나오면 눌러주면 된다.

 

 

 

 

 

 

새로운 프로젝트를 생성하기 위해 New -> Spring Starter Project를 클릭한다. (없다면 Project에서 찾기)

 

 

 

 

 

 

java Version과 같은 설정등은 본인에게 맞는걸로 선택하고, package에는 Group + Artifact를 작성해준다.

 

Next를 누른 후, 그림과 같이 4개의 dependency를 선택한 후 Finish를 눌러 프로젝트를 생성한다.

 

 

 

 

 

 

 

 

		<!--  JSP -->
        <dependency>
           <groupId>org.apache.tomcat.embed</groupId>
           <artifactId>tomcat-embed-jasper</artifactId>
           <version>9.0.45</version>
        </dependency>
	    <!--  JSTL -->
	    <dependency>
	       <groupId>javax.servlet</groupId>
	       <artifactId>jstl</artifactId>
	       <version>1.2</version>
	    </dependency>

생성된 spring 프로젝트를 열고, pom.xml의 dependency안에 해당 코드를 넣는다.

 

JSP와 JSTL을 사용할 수 있도록 한다.

 

728x90
반응형
728x90
반응형

💾 설치 : Maven Repository: com.jfinal » cos » 2020.4 (mvnrepository.com)

* \웹프로젝트\WebContent\WEB-INF\lib 위치에 설치한 jar 파일을 넣기 *

 

 

 

📂 파일 업로드

강철의 연금술사 사진을 성공적으로 추가한 모습

 

form.jsp

<body>
	<form id="Action" action="<%=request.getContextPath()%>/action.jsp" method="post" enctype="multipart/form-data">
		<div class="form-group">
	        사진 : 
	        <input type="file" name="image">
	    </div>
	    
	    <button id="btn" type="buttion" onclick="clickBtn()">추가</button>
	</form>
	<script>
		function clickBtn() {
			$('#Action').submit();	
		}
	</script>
</body>

 

<form enctype="multipart/form-data">의 형태로 생성한다.

 

<input type="file" name="image">와 같이 type을 file로 지정한다.

 

버튼을 클릭하면 action.jsp로 이동한다. (action.jsp에서 사진 업로드 처리)

 

 

 

 

 

action.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.MultipartRequest" %> <!-- request 대신 -->
<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %> <!-- 파일이름 중복을 피할 수 있도록 -->

<%
	// 웹 프로젝트 위치에 넣어도 된다 (이클립스에서 사진 추가되는 것을 실시간으로 확인 가능)
	// MultipartRequest mr = new MultipartRequest(request, "C:/Users/fjdks/Desktop/erp/WebContent/image", 1024*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	MultipartRequest mr = new MultipartRequest(request, request.getRealPath("/image"), 1024*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	System.out.println("저장되는 경로(실제 서버) : "+request.getRealPath("/image"));
	
	String fileName = mr.getFilesystemName("image");
	System.out.println("사진 이름 : "+fileName);
%>

MultipartRequest를 통해 사진을 저장한다. (웹 프로젝트 위치 or 서버 위치)

 

request.getRealPath()로 실제 서버 위치에 접근할 수 있다.

(이클립스에서는 사진이 추가되는 것이 보이지 않는다. 웹 프로젝트 위치로 접근하면 사진이 추가되는 것을 실시간으로 확인할 수 있다)

 

form.jsp에서 enctype="multipart/form-data"으로 받아왔기 때문에, request.getParameter()를 사용할 수 없다.

 

파일명은 mr.getFilesystemName()을 사용하여 받고, 일반적인 값은 mr.getParameter()를 통해 받아온다.

 

 

 

 

* request.getRealPath("/image")가 작동되도록 WebContent 아래에 image 파일을 생성했다 *

 

 

 

 

 

 

 

 

📂 이전 파일 삭제

강연 사진이 사라지고 새로운 사진이 추가된 것을 볼 수 있다

 

 

action.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.MultipartRequest" %> <!-- request 대신 -->
<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %> <!-- 파일이름 중복을 피할 수 있도록 -->
<%@ page import="java.io.File" %>

<%
	// 이렇게 원하는 위치를 직접 넣어도 되긴 함(프로젝트 파일에 실시간으로 추가되는거 볼 수 있음 ㅋㅋ)
	// MultipartRequest mr = new MultipartRequest(request, "C:/Users/fjdks/Desktop/erp/WebContent/image", 1024*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	MultipartRequest mr = new MultipartRequest(request, request.getRealPath("/image"), 1024*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	System.out.println("저장되는 경로(실제 서버) : "+request.getRealPath("/image"));
	
	String fileName = mr.getFilesystemName("image");
	System.out.println("저장된 사진 이름 : "+fileName);
	
	// 실제로는 이전 사진 이름을 DB에서 불러온다
	String beforeImg = "fullmetalAlchemist.PNG";
	
	// 이전 사진명을 통해 실제로 삭제될 사진을 가져온다
    	String deleteImgName = request.getRealPath("/image/") + beforeImg;
    	File deleteImg = new File (deleteImgName);
    
    	// 이전 사진이 경로에 존재한다면 삭제한다
    	if (deleteImg.exists() && deleteImg.isFile()){
    	    deleteImg.delete();// 사진 삭제
    	    System.out.println("삭제된 이전 사진 : "+beforeImg);
    }
	
%>

임시로 이전 사진의 이름을 "fullmetalAlchemist.PNG"로 설정하였지만 실제로는 DB에서 값을 받아와야 한다.

 

경로 + 사진 이름까지 담겨진 deleteImgName 변수를 File 형태로  만든다.

 

만약 deleteImg의 경로에 파일이 존재하고 deleteImg가 파일이라면, 해당 사진(이전 사진)을 삭제한다.

 

이전 사진이 삭제되었다.

 

728x90
반응형
728x90
반응형

* 부트스트랩 연동 코드가 존재하면 아래 사진처럼 나옵니다*

 

index.jsp

	<!-- 상품 목록 출력 -->
      <%
      // 페이지
      int currentPage = 1;
      if(request.getParameter("currentPage")!=null){
         currentPage = Integer.parseInt(request.getParameter("currentPage"));
      }
      System.out.println(currentPage+" <--selectEbookList currentPage");
      
      final int ROW_PER_PAGE = 10; // 페이지에 보일 주문 개수
      int beginRow = (currentPage-1)*ROW_PER_PAGE; // 리스트 목록 시작 부분
      
      // 전체 목록
      EbookDao ebookDao = new EbookDao();
      // 화면에 보일 리스트를 추출해오는 함수(리스트 시작 부분, 받아올 리스트 개수)
      ArrayList<Ebook> ebookList = ebookDao.selectEbookList(beginRow, ROW_PER_PAGE);
      %>
      
      <h2>전체 상품 목록</h2>
   <!-- 상품 목록 출력 -->
   <table class="table" border="1">
      <tr>
         <%
            int i = 0;
         
            // 반복을 통해 카테고리 목록을 표로 출력
            for(Ebook e : ebookList){
         %>
               <td>
                  <div><a href=""><img src="<%=request.getContextPath() %>/image/<%=e.getEbookImg() %>" width="200" height="200"></a></div>
                  <div><a href=""><%=e.getEbookTitle()  %></a></div>
                  <div>₩ <%=e.getEbookPrice() %></div>
               </td>
         <%
               i+=1; // for문 끝날때마다 i는 1씩 증가
               if(i%5==0){
         %>
                  </tr><tr> <!-- 줄바꿈 -->
         <%
               }
            }
         %>
      </tr>
   </table>
   
   <div></div>
   
   <!-- 페이지 -->
   <%	
   	   // 페이징을 위해 구해야 할 마지막 페이지 연산
       int lastPage;
   	   int currentnumPage=0; // 현재 페이지가 몇번째 묶음인지(이전,다음 구현을 위함)
   	   int lastnumPage=0; // 마지막 페이지가 몇번째 묶음인지(마지막 페이지에서 다음이 나오지 않도록 하기 위함)
   	   
   	   lastPage = ebookDao.selectEbookListLastPage(ROW_PER_PAGE); // 상품의 개수를 통해 마지막 페이지가 몇번인지 추출
	   
   %>
    <ul class="pagination body-back-color">
    <%
    	if(currentPage!=1){
    %>
    		<li class="page-item"><a class="page-link" href="<%=request.getContextPath() %>/index.jsp?currentPage=<%=1 %>">처음</a></li>
    <%	
    	}
    	if(currentPage%ROW_PER_PAGE==0){ // 현재 페이지가 몇번째 묶음인지
    		currentnumPage =(currentPage/ROW_PER_PAGE)-1;
    	} else{
    		currentnumPage = currentPage/ROW_PER_PAGE;
    	}
   	%>
    <%
    	if((currentnumPage)>0){ // 이전
    %>
    		<li class="page-item"><a class="page-link" href="<%=request.getContextPath() %>/index.jsp?currentPage=<%=ROW_PER_PAGE*(currentnumPage-1)+1 %>">이전</a></li>
    <%
    	}
    
    	for(int i=0;i<ROW_PER_PAGE;i++){ // 중간 번호들
    		if(lastPage>=(ROW_PER_PAGE*currentnumPage)+i+1){
   	    %>
   		  <li class="page-item"><a class="page-link" href="<%=request.getContextPath() %>/index.jsp?currentPage=<%=(ROW_PER_PAGE*currentnumPage)+i+1 %>"><%=(ROW_PER_PAGE*currentnumPage)+i+1 %></a></li>
   	   <%
    		}
    	}
    	if(lastPage%ROW_PER_PAGE==0){ // 마지막 페이지가 몇번째 묶음인지
    		lastnumPage =(lastPage/ROW_PER_PAGE)-1;
    	} else{
    		lastnumPage = lastPage/ROW_PER_PAGE;
    	}
    	
    	if(lastnumPage>currentnumPage){
    %>
    		<li class="page-item"><a class="page-link" href="<%=request.getContextPath() %>/index.jsp?currentPage=<%=ROW_PER_PAGE*(currentnumPage+1)+1 %>">다음</a></li>
    <%
    	}
    	if(currentPage!=lastPage && lastPage!=0){
    %>
    		<li class="page-item"><a class="page-link" href="<%=request.getContextPath() %>/index.jsp?currentPage=<%=lastPage %>">맨끝</a></li>
    <%
    	}
    %>
	</ul>

- currentPage(현재페이지), beginRow(리스트 시작 위치), ROW_PER_PAGE(화면에 보일 리스트 개수 및 하단 페이징 단위), lastPage(마지막 페이지), currentNumPage(현재 페이지가 위치한 묶음 단위<이전, 다음을 위함>), lastnumPage(마지막 페이지가 위치한 묶음 단위<다음 버튼의 오류 방지>)

 

- 각 변수들의 사용 목적을 숙지하면 코드를 이해하기 좋습니다.

 

 

 

EbookDao.java

// [관리자 & 고객] 전자책 목록 전체 출력
   public ArrayList<Ebook> selectEbookList(int beginRow, int rowPerPage) throws ClassNotFoundException, SQLException{
      ArrayList<Ebook> list = new ArrayList<>();
      
      // mariaDB 연동
      Class.forName("org.mariadb.jdbc.Driver");
	Connection conn = DriverManager.getConnection("jdbc:mariadb://127.0.01:3307/shop", "root", "java1004");
      String sql = "select ebook_no ebookNo, category_name categoryName, ebook_title ebookTitle, ebook_img ebookImg, ebook_price ebookPrice, ebook_state ebookState from ebook order by create_date desc limit ?,?";
      PreparedStatement stmt = conn.prepareStatement(sql);
      stmt.setInt(1, beginRow);
      stmt.setInt(2, rowPerPage);
      System.out.println("ebook 목록 출력 stmt : "+stmt);
      ResultSet rs = stmt.executeQuery();
      
      // 각 전자책의 정보를 리스트에 담는다
      while(rs.next()) {
         Ebook ebook = new Ebook();
         ebook.setEbookNo(Integer.parseInt(rs.getString("ebookNo")));
         ebook.setCategoryName(rs.getString("categoryName"));
         ebook.setEbookTitle(rs.getString("ebookTitle"));
         ebook.setEbookImg(rs.getString("ebookImg"));
         ebook.setEbookPrice(rs.getInt("ebookPrice"));
         ebook.setEbookState(rs.getString("ebookState"));
         list.add(ebook);
      }
      rs.close();
      stmt.close();
      conn.close();
      return list;
   }
   
   
   // [관리자] 전자책 마지막 페이지 연산
   public int selectEbookListLastPage(int rowPerPage) throws ClassNotFoundException, SQLException {
      DBUtil dbUtil = new DBUtil();
       Connection conn = dbUtil.getConnection();
    
      // 전체 페이지수 구하기
       PreparedStatement stmt;
         String sql = "select count(*) from ebook";
        stmt = conn.prepareStatement(sql);
        System.out.println("전체 전자책 수 stmt : "+stmt);
      ResultSet rs = stmt.executeQuery();
      rs.next();
      int totalData = rs.getInt("count(*)");
      int lastPage= totalData/rowPerPage; // 마지막 페이지 번호
      if(totalData%rowPerPage!=0){
         lastPage +=1;
      }
      
      rs.close();
      stmt.close();
      conn.close();
      
      return lastPage;
   }

[전자책 목록 전체 출력]

- 전자책 목록을 mariaDB에서 받아온 후, ArrayList에 담는 메서드 입니다. 쿼리에서 중요한 부분은 limit입니다.

 

- limit ?,? => 첫번째 물음표에 테이블에서 추출할 리스트의 시작부분을 넣고, 두번째 물음표에 시작부분 부터 몇개의 리스트를 추출할 것인지를 넣는 것 입니다.

 

 

[마지막 페이지 연산]

- 추출할 요소의 수를 받아온 후 rowPerPage를 통해 마지막 페이지가 몇인지 구합니다.

 

 

728x90
반응형
728x90
반응형

1. 도구 -> 데이터베이스를 SQL로 내보내기를 누른다.

 

 

 

 

 

2. 원하는 데이터베이스와 테이블을 선택하고 각종 설정을 마친 후 내보내기를 누른다.

- 데이터베이스와 테이블의 삭제를 체크하면 생성도 자동으로 체크되는데, 이미 존재한다면 삭제하고 다시 생성한다는 것이다.

- 데이터는 DELETE + INSERT로 설정하여 저장하면 데이터가 삽입된 채로 저장되고, 데이터없음으로 저장하면 테이블만 저장된다.

- 파일명은 ???.sql로 설정하고 내보내기를 누르면 된다.

 

 

 

 

 

 

3. sql 형태로 저장된 파일을 잘 보관한다.

 

 

 

 

728x90
반응형

'Web > DB' 카테고리의 다른 글

DB에 값 자동으로 넣기 / Mockaroo , mariaDB  (0) 2021.08.27
HeidiSQL 사용하기 / mariaDB  (1) 2021.08.25
728x90
반응형

1. 깃허브 로그인 후 프로젝트를 저장할 레파지토리를 생성한다.

new 버튼 클릭

 

레파지토리 이름을 작성해주시고 공개여부는 원하는대로 public이나 private를 설정해줍니다. 그리고 생성하시면 됩니다. 요즘은 private도 무료라고 합니다만.. 저는 public으로 했습니다.

 

 

 

 

 

 

2. 깃에 올릴 파일 우클릭 -> Team -> Share Project 클릭

 

 

 

 

 

 

3. Create를 누르고 원하는 위치 선택 후 Finish 클릭

 

모양이 이렇게 변경될겁니다.

 

 

 

 

 

 

 

 

4. 깃허브에 만들어놨던 레파지토리의 <>Code에 들어가서 해당 링크를 복사한다.

복사해둔 상태가 필요한겁니다. 오른쪽 복사 버튼을 직접 누르시는게 더 안전한것같습니다.

 

 

 

 

 

 

 

5. 변경된 프로젝트 우클릭 -> Team -> Commit클릭 후 Unstaged Changes에 있는 모든 것을 Staged Changes로 넘기고 Commit and Push를 클릭한다.

오른쪽 큰 메모장 같은 곳에는 commit 기록을 남겨주시면 됩니다. 이게 어떤 커밋인지...ㅎㅎ

 

 

이렇게 빈 화면이 나온다면 4번 작업을 놓치신겁니다. 여기가 자동으로 채워져야합니다. 자동으로 채워졌다면 Preview를 누르세요.

 

 

 

 

 

 

 

6. 로그인 화면이 나오면 User에는 깃허브 아이디, Password에는 토큰을 넣는다.

 

깃허브 토큰 생성 방법은 인터넷에 쳐보면 또 나올겁니다. 자동 로그인 원하시면 Store in Secure Store 체크해주세요.

 

비밀번호 잊었을때 사용할 질문같은거 설정 간단하게 하시면 되고, push가 정상적으로 되었는지 확인합니다.

 

 

 

 

 

 

7. 정상적으로 Push된 것을 확인할 수 있습니다.

728x90
반응형

+ Recent posts