반응형
반응형

 

// File file = new File(fileImagePath); // 리사이즈할 파일 정보

public BufferedImage resize(File file, int width, int height) throws IOException {

    /** 이미지 가져오기 **/
    InputStream inputStream = new FileInputStream(file);

    /** 받은 이미지 읽기 **/
    BufferedImage inputImage = ImageIO.read(inputStream);

    /** 리사이징 **/
    BufferedImage outputImage = new BufferedImage(width, height, inputImage.getType());

    Graphics2D graphics2D = outputImage.createGraphics();
    graphics2D.drawImage(inputImage, 0, 0, width, height, null); // 그리기
    graphics2D.dispose(); // 자원해제

    return outputImage;

}

리사이징

 

public void drawBlackBox(BufferedImage blackBoxImage, int blackBoxWidth, int blackBoxHeight, HttpSession session) {

    int cutXPoint = 10; // 왼쪽 상단 X좌표
    int cutYPoint = 10; // 왼쪽 상단 Y좌표

    /** 도형 그리기 **/
    Graphics graphics = blackBoxImage.getGraphics();
    graphics.setColor(Color.BLACK); // 색상 설정
    graphics.fillRect(cutXPoint, cutYPoint, blackBoxWidth, blackBoxHeight); // 채우기 사각형
    // graphics.drawRect(cutXPoint, cutYPoint, blackBoxWidth, blackBoxHeight); // 테두리 사각형
   
    // graphics.fillOval(xPoint, yPoint, ovalWidth, ovalHeight); // 채우기 원
    // graphics.drawOval(xPoint, yPoint, ovalWidth, ovalHeight); // 테두리 원
    graphics.dispose();
}

도형 그리기

 

public BufferedImage getWhitePaper(StringImageVO customImage) {

    // 종이 크기 설정
    int width = customImage.getImageWidth();
    int height = customImage.getImageHeight();

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
	
    // 예시
    // BufferedImage mergedImage = new BufferedImage(550, 100, BufferedImage.TYPE_INT_RGB);

    return image;
}

하얀 배경 그리기

public void draw(BufferedImage image, String question) {

    Color color = new Color(255, 0, 0); // 글자 색
    Font font = new Font("TimeRoman", Font.PLAIN, 35); // 이미지 글체
    
    // 글자 이미지가 생성될 위치 선정
    int left = 240;
    int top = 300;

    // Graphics2D 와 BufferedImage는 연동 된 느낌?
    Graphics2D graphics = image.createGraphics();

    // 글자색과 글자체 설정
    graphics.setColor(color);
    graphics.setFont(font);

    // 해당 내용으로 그리기 작업
    graphics.drawString(question, left, top);
    graphics.dispose();

}

글자 그리기

public void getQuestionList(
	HttpServletRequest request, HttpServletResponse response) throws IOException {

    /** 화면 준비 **/
    OutputStream out = response.getOutputStream();

    /** 준비된 이미지 **/
    BufferedImage img = new BufferedImage(550, 100, BufferedImage.TYPE_INT_RGB);

    /** 화면에 뿌리기 **/
    response.setContentType("image/png");
    ImageIO.write(img, "png", out);
}

화면에 노출시키기

 

BufferedImage cutImage = resizedImage.getSubimage(cutXPoint, cutYPoint, cutWidth, cutHeight); // 잘린 이미지

이미지 자르기

 

반응형
반응형
public String checkReferer(HttpServletRequest request, HttpServletResponse response) {

    String referer = request.getHeader("Referer");

    if (referer.equals(rightReferer)) return "올바른 접근";
    else return "올바르지 않은 접근";

}

HTTP 리퍼러(HTTP referer)는 웹 브라우저로 월드 와이드 웹을 서핑할 때, 하이퍼링크를 통해서 

각각의 사이트로 방문시 남는 흔적을 말한다.

예를 들어 A라는 웹 페이지에 B 사이트로 이동하는 하이퍼링크가 존재한다고 하자. 

이때 웹 사이트 이용자가 이 하이퍼링크를 클릭하게 되면 웹 브라우저에서 B 사이트로 참조 주소(리퍼러)를 전송하게 된다. 

B 사이트의 관리자는 이 전송된 리퍼러를 보고 방문객이 A 사이트를 통해 자신의 사이트에 방문한 사실을 알 수 있다.

웹 사이트의 서버 관리자가 사이트 방문객이 어떤 경로로 자신의 사이트에 방문했는지 알아볼 때 유용하게 사용된다.

하지만, 리퍼러는 조작또한 가능하기 때문에 리퍼러 정보를 사용할 때에는 보안에 항상 주의해야 한다

반응형
반응형
// base64로 인코딩한 내용 받아오기
@RequestMapping(value = "/getBase64", method = RequestMethod.GET)
public @ResponseBody String getBase64(HttpServletRequest request, HttpServletResponse response) throws Exception {

    Base6430 base = new Base6430();
    String encodeBase64 = base.encodingBase64();

    return encodeBase64;

}

// 이미지 base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
// mp4 base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "video/mp4")
// pdf base64 인식
//	@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "application/pdf")
// base64 디코딩해 해석해 화면에 노출
@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] base64(HttpServletRequest request, HttpServletResponse response) throws Exception {

    String uri = "http://localhost:8080/getBase64";
    String encodeBase64 = callGetMethod(uri);

    byte decode[] = Base64.decodeBase64(encodeBase64);

    return decode;
}

StringBuffer response;
public String callGetMethod(String url) {		
    try {

        // 통신 주소  등록
        URL obj = new URL(url);

        // 통신 방식 설정
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8" );
        conn.setDoOutput(true);
        conn.setRequestMethod("GET");

        // ---- 읽어온 데이터를 담기 ----
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));

        String inputLine;
        response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

    // ---- 읽어온 데이터를 반환 ----
    String responseData =response.toString();
    return responseData; 
}

base64Controller

 

spring에서 제공하는 produces에 다양한 옵션이 존재하는데 ContentType 인식 시키는 방법에 대한 기술

(produces = MediaType.IMAGE_JPEG_VALUE → 이미지로 읽어라~)

 

package com.mycompany.myapp;

import java.io.File;
import java.io.FileInputStream;

import org.apache.commons.codec.binary.Base64;

public class Base6430 {

	public String encodingBase64() throws Exception {

		String strBase64 = "";
		String filePath = "D:\\dog.jpg";
//		String filePath = "D:\\test.mp4";
//		String filePath = "D:\\test.pdf";

		File f = new File(filePath);
		if (f.exists() && f.isFile() && f.length() > 0) {
			byte[] bt = new byte[(int) f.length()];
			FileInputStream fis = null;

			try {
				fis = new FileInputStream(f);
				fis.read(bt);
				strBase64 = new String(Base64.encodeBase64(bt));

			} catch (Exception e) {
				throw e;
			}
			fis.close();
			
		}
		return strBase64;
	}
}

base6430.java

 

해당 Path 정보를 읽어 Base64 인코딩하는 작업

 

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
</dependency>

pom.xml

반응형
반응형

📝List 정렬

public void sort(){

    /** 초기 데이터 init **/
    List<String> list = Arrays.asList("banana", "apple", "cherry");

    /** 오름차순 정렬 **/
    list.sort(Comparator.naturalOrder());
    System.out.println("오름차순: " + list);
    // 오름차순: [apple, banana, cherry]

    /** 내림차순 정렬 **/
    list.sort(Comparator.reverseOrder());
    System.out.println("내림차순: " + list);
    // 내림차순: [cherry, banana, apple]

}

 

📝Map정렬

  public void sort() {

    /** 초기 데이터 init **/
    Map<String, Integer> map = new HashMap<>();
    map.put("apple", 3);
    map.put("banana", 1);
    map.put("cherry", 2);

    /** Map.Entry 리스트로 변환 **/
    List<Map.Entry<String, Integer>> entryList = new ArrayList<>(map.entrySet());

    /** 키(key) 기준으로 오름차순 정렬 **/
    entryList.sort(Map.Entry.comparingByKey());
    System.out.println("키 기준 오름차순: " + entryList);
    // 키 기준 오름차순: [apple=3, banana=1, cherry=2]

    /** 키(key) 기준으로 내림차순 정렬 **/
    entryList.sort(Map.Entry.<String, Integer>comparingByKey().reversed());
    System.out.println("키 기준 내림차순: " + entryList);
    // 키 기준 내림차순: [cherry=2, banana=1, apple=3]

    /** 값(value) 기준으로 오름차순 정렬 **/
    entryList.sort(Map.Entry.comparingByValue());
    System.out.println("값 기준 오름차순: " + entryList);
    // 값 기준 오름차순: [banana=1, cherry=2, apple=3]

    /** 값(value) 기준으로 내림차순 정렬 **/
    entryList.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
    System.out.println("값 기준 내림차순: " + entryList);
    // 값 기준 내림차순: [apple=3, cherry=2, banana=1]

  }

Map은 직접 정렬할 수 없어서 Map.Entry로 변환한 후에 List로 담아서 사용이 가능합니다.

 

📝 JSONArray 정렬

public void sort() throws JSONException {

    /** 초기 데이터 init **/
    String jsonData = "["
        + "{\"name\":\"banana\",\"price\":1},"
        + "{\"name\":\"apple\",\"price\":3},"
        + "{\"name\":\"cherry\",\"price\":2}"
        + "]";

    JSONArray jsonArray = new JSONArray(jsonData);

    /** JSONArray -> List<JSONObject> **/
    List<JSONObject> jsonList = new ArrayList<>();
    for (int i = 0; i < jsonArray.length(); i++) {
      jsonList.add(jsonArray.getJSONObject(i));
    }

    /** 오름차순 정렬 **/
    jsonList.sort(Comparator.comparing(obj -> {
      try {
        return obj.getInt("price");
      } catch (JSONException e) {
        throw new RuntimeException(e);
      }
    }));

    /** 정렬된 List -> JSONArray로 변환 **/
    JSONArray sortedJsonArray = new JSONArray(jsonList);

    System.out.println("오름차순 정렬 JSONArray: " + sortedJsonArray);
    // 오름차순 정렬 JSONArray: [{"price":1,"name":"banana"},{"price":2,"name":"cherry"},{"price":3,"name":"apple"}]

    /** 내림차순 정렬 **/
    jsonList.sort(Comparator.comparing((JSONObject obj) -> {
      try {
        return obj.getInt("price");
      } catch (JSONException e) {
        throw new RuntimeException(e);
      }
    }).reversed());

    /** 정렬된 List -> JSONArray로 변환 **/
    JSONArray descSortedJsonArray = new JSONArray(jsonList);

    System.out.println("내림차순 정렬 JSONArray: " + descSortedJsonArray);
    // 내림차순 정렬 JSONArray: [{"price":3,"name":"apple"},{"price":2,"name":"cherry"},{"price":1,"name":"banana"}]
}

JSONArray도 바로 정렬할 수 없기 때문에 List에 담아서 처리해야합니다. 정렬할 때 정렬할 키를 기준으로 return해서 그 값을 정렬처리하게끔하면 됩니다.

반응형
반응형
package my.spring.project;

public class main {

	public static void main(String[] args) {

        String s = "1000";                     
        
        int i = Integer.parseInt(s); // int 타입 변환
        long L = Long.parseLong(s);  // long 타입 변환
        float f = Float.parseFloat(s); // float 타입 변환
        double d = Double.parseDouble(s) + 1.0; // double 타입 변환
	}

}
반응형
반응형
package com.company.aa;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

public class JsonAPI {

	public void flushJson(Object json, HttpServletResponse response) throws IOException {
		
		// 출력
		response.setContentType("application/json; charset=UTF-8");
		PrintWriter writer = null;

		writer = response.getWriter();
		writer.print(json);
		writer.flush();
	}
	
}
반응형
반응형
package com.company.aa;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.*;

public class Linux {

	public void runCommand(String userName, String password, String ip, String command)
			throws IOException, JSchException {

		Channel channel = null;

		// 1. 서버 연결
		Session session = connect(userName, password, ip);

		// 2. 리눅스 명령어 실행가능한 객체 생성
		ChannelExec channelExec = makeChannelExec(session, channel);

		// 3. 실행할 명령어 설정
		setCommand(channelExec, command);

		// 4. 응답값을 안 받아올 경우 실행하고 실행도중에 바로 연결을 끊기 때문에 그에 대한 응답값을 받아오는 과정이 필요하다
		String result = getCommandReturn(channelExec);

		// 5. 연결 끊기
		disconnect(channel, session);
	}

	public String getReturn(String userName, String password, String ip, String command)
			throws IOException, JSchException {

		Channel channel = null;

		// 1. 서버 연결
		Session session = connect(userName, password, ip);

		// 2. 리눅스 명령어 실행가능한 객체 생성
		ChannelExec channelExec = makeChannelExec(session, channel);

		// 3. 실행할 명령어 설정
		setCommand(channelExec, command);

		// 4. 명령어 결과를 읽어내는 과정
		String result = getCommandReturn(channelExec);

		// 5. 연결 끊기
		disconnect(channel, session);

		return result;
	}

	public void transferFile(String userName, String password, String ip, String sourcePath, String destinationPath)
			throws IOException, JSchException, SftpException {

		Channel channel = null;

		// 서버 연결
		Session session = connect(userName, password, ip);

		// sftp 준비
		ConnectChannelSftp(channel, session, sourcePath, destinationPath);

		// 연결 끊기
		disconnect(channel, session);

	}

	private void ConnectChannelSftp(Channel channel, Session session, String sourcePath, String destinationPath)
			throws JSchException, SftpException {

		ChannelSftp channelSftp = null;

		channel = session.openChannel("sftp");
		channel.connect();
		channelSftp = (ChannelSftp) channel;
		channelSftp.put(sourcePath, destinationPath); // 파일을 전송하는 메소드
		channelSftp.disconnect();
	}

	private ChannelExec makeChannelExec(Session session, Channel channel) throws JSchException {

		// sftp 채널을 연다.
		channel = session.openChannel("exec");

		// 채널을 SSH용 채널 객체로 캐스팅한다 → 연 채널의 명령어를 입력할 수 있는 구조로 바꾸는 과정
		ChannelExec channelExec = (ChannelExec) channel;
		channelExec = (ChannelExec) session.openChannel("exec");

		return channelExec;
	}

	private Session connect(String userName, String password, String ip) throws JSchException {

		Session session = null;

		// ssh 포트
		int port = 22;

		// JSch 객체[리눅스 연결]를 생성한다.
		JSch jsch = new JSch();
		session = jsch.getSession(userName, ip, port);

		// 패스워드를 설정한다.
		session.setPassword(password);

		// 세션과 관련된 정보를 설정한다.
		java.util.Properties config = new java.util.Properties();

		// 호스트 정보를 검사하지 않는다.
		config.put("StrictHostKeyChecking", "no");
		session.setConfig(config);

		// 접속한다.
		session.connect();

		return session;
	}

	private void disconnect(Channel channel, Session session) {
		if (channel != null)
			channel.disconnect();
		if (session != null)
			session.disconnect();
	}

	private void setCommand(ChannelExec channelExec, String command) throws IOException, JSchException {

		// 7. 명령어 실행할 명령어 설정
		channelExec.setCommand(command);
		channelExec.connect();

		channelExec.setErrStream(System.err);

	}

	public String getCommandReturn(ChannelExec channelExec) throws IOException, JSchException {

		// 8. 명령어 결과를 읽어 과정
		BufferedReader inputStream = new BufferedReader(new InputStreamReader(channelExec.getInputStream(), "utf-8"));

		StringBuilder response = new StringBuilder();
		String line;

		while ((line = inputStream.readLine()) != null) {
			response.append(line + '\n');
//			System.out.println(line);
		}

		return response.toString();
	}

}
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>
반응형
반응형
<script>
// var로 선언한 변수는 중복해서 선언이 가능하다
// Change 함수에 idx 값을 넣는다 (1)
function Change(idx) {
    // pageNum 변수에 idx 값을 저장한다. 현재 페이지 번호 = 1
    var pageNum = idx; // var pageNum = 1;
    // 한 페이지에 보여줄 게시물 수 = amount라는 id에 접근하여 value 값 가져오기 (jquery 사용)
    var amount = $("#amount").val();
    // 한 페이지에 보여줄 게시물 수 = 10 일때
    if(amount == 10) {
        // location.href = 자바스크립트 페이지 이동 기능
        // 첫 번째 페이지에 10개의 게시물을 보이기
        location.href="paging?pageNum="+pageNum+"&amount="+amount;
    } else if(amount == 15) {
        location.href="paging?pageNum="+pageNum+"&amount="+amount;
    } else if(amount == 20) {
        location.href="paging?pageNum="+pageNum+"&amount="+amount;
    }
}
</script>


<div class="form-group">
    <select id="amount" onchange="Change(1)">
        <!-- selected="selected"를 안 붙이면 셀렉트 박스가 기본값으로 초기화 됨 -->
        <option value="10" <c:if test="${pageVO.amount == 10}">selected="selected"</c:if>>10개씩 보기</option>
        <option value="15" <c:if test="${pageVO.amount == 15}">selected="selected"</c:if>>15개씩 보기</option>
        <option value="20" <c:if test="${pageVO.amount == 20}">selected="selected"</c:if>>20개씩 보기</option>
    </select>
</div>

전에 올렸던 Pagination Code에 해당 내용을 jsp에 추가하면 됩니다.

반응형
반응형
package my.spring.project;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class DB {

	// DB 연결
	public Connection connectDB(String id, String password, String url) throws ClassNotFoundException, SQLException {
		// 1. 드라이버 로딩
		Class.forName("com.mysql.cj.jdbc.Driver");

		// 2. DB 연결
		Connection conn = DriverManager.getConnection(url, "root", "1234");

		return conn;
	}
	
	// 전체 게시글 수 가져오기
	public int getTotalRecord(String tableName, Connection conn) throws SQLException {
		
		ResultSet countRs;
		

		// 쿼리 실행 준비작업
		String sql = "SELECT count(*) FROM " + tableName;
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		// 쿼리 실행
		countRs = pstmt.executeQuery();
		
		countRs.next();
		
		//쿼리 결과
		int total = countRs.getInt(1);

		return total;
	}

	// 현재 페이지 게시물 정보 가져오기
	public ArrayList<BoardVO> getRecordForPageNum(
			Connection conn, int total, int pageNum, int amount) throws SQLException {
		
		ResultSet boardRs;
		
		// 페이지에 따른 게시물 정보 가져오기
		
//		// 방법1
//		String sql = "(SELECT @junho:=0);"
//
//		// 방법1
//				
//		String sql = "select * \r\n"
//				+ "	from(SELECT @junho:=@junho+1 rn, A.* FROM mytable A ) total \r\n"
//				+ "where rn > 0 and rn <= 290;"
		
		
		// 방법2
		String sql = "select * "
				+ "from(SELECT @ROWNUM:=@ROWNUM+1 rn, A.* FROM mytable A, (SELECT @ROWNUM:=0) R order by rn desc) total "
				+ "where rn > ? and rn <= ?;";

		PreparedStatement pstmt = conn.prepareStatement(sql);

		pstmt.setInt(1, total - (pageNum * amount));		
		pstmt.setInt(2, total - ((pageNum - 1) * amount));
		
		boardRs = pstmt.executeQuery();
		
		ArrayList<BoardVO> boardList = new ArrayList();

		// 게시물 정보 가져오기
		while(boardRs.next()) {
			BoardVO dto = new BoardVO();
			
			dto.setId(boardRs.getInt(1));
			dto.setName(boardRs.getString(3));
			dto.setPhone(boardRs.getString(4));
			dto.setEmail(boardRs.getString(5));
			dto.setAddress(boardRs.getString(6));

			boardList.add(dto);
		}
		
		return boardList;
	}

	// DB 연결 끊기
	public void closeConnect(Connection conn) throws SQLException {

		conn.close();
	}
}​
package my.spring.project;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	
	@RequestMapping(value = "/paging", method = RequestMethod.GET)
	public String home(Locale locale, Model model, HttpServletRequest request, HttpServletResponse response) throws ClassNotFoundException, SQLException {

		int pageNum = 1; // default 현재 페이지
		int amount = 10; // default 한 페이지에 보여줄 게시물 수
		int paginationNum = 10; // default 페이지네이션 리스트 수
		
		// pageNum, amount 파라미터 값 가져오기
		if(request.getParameter("pageNum") != null && request.getParameter("amount") != null && request.getParameter("paginationNum") != null) {
			pageNum = Integer.parseInt(request.getParameter("pageNum"));
			amount = Integer.parseInt(request.getParameter("amount"));
			paginationNum = Integer.parseInt(request.getParameter("paginationNum"));
		}
		
		// mysql 8.0 이용 중

		// 연결할 db 정보
		String drive = "com.mysql.cj.jdbc.Driver";
		String url = "jdbc:mysql://localhost:3306/konan?useSSL=false&serverTimezone=Asia/Seoul";
		String id = "root";
		String password = "1234";

		// DB 연결
		DB db = new DB();
		Connection conn = db.connectDB(id, password, url);
		
		
		// 전체 게시물 수 
		String tableName = "mytable";
		int total = db.getTotalRecord(tableName, conn);
		
		// 현재 페이지 게시물 정보
		ArrayList<BoardVO> boardList = db.getRecordForPageNum(
				conn, total, pageNum, amount);
		
		// 페이징에 필요한 정보
		Board board = new Board();
		PageVO pageVO = new PageVO();
		pageVO = board.setPageVO(total, pageNum, amount, paginationNum);
		
		// DB 연결 끊기
		db.closeConnect(conn);
		
		// view에 사용할 데이터 model에 담아 보내주기
		model.addAttribute("pageVO",pageVO);
		model.addAttribute("boardList",boardList);
		
		return"paging";
	}
	
}
package my.spring.project;

//페이징 정보 담는 VO
public class PageVO {

	private int total; // 전체 글 수
	private int amount; // 한 페이지에 보여줄 게시글 수
	private int pageNum; // 현재 페이지 번호
	private int startPage; // 페이지네이션 시작 번호
	private int endPage; // 페이지네이션 끝 번호
	private int realEnd; // 페이제니이션 진짜 끝 번호
	private int prevPage; // 10 페이지 전 이동
	private int nextPage; // 10 페이지 후 이동
	private int paginationNum; // 페이지네이션 보여질 갯수 [1 2 3  ... 10]일경우 paginationNum = 10
	
	// 예) 전체글수가 180개이고 현재 페이지가 15이고 10개씩 보여줄시
	// startPage는 10이 되는 것이고 endPage는 20이 된다.
	// realEnd는 18이 된다.
	
	public int getStartPage() {
		return startPage;
	}
	public int getPaginationNum() {
		return paginationNum;
	}
	public void setPaginationNum(int paginationNum) {
		this.paginationNum = paginationNum;
	}
	public int getPrevPage() {
		return prevPage;
	}
	public void setPrevPage(int prevPage) {
		this.prevPage = prevPage;
	}
	public int getNextPage() {
		return nextPage;
	}
	public void setNextPage(int nextPage) {
		this.nextPage = nextPage;
	}
	public void setStartPage(int startPage) {
		this.startPage = startPage;
	}
	public int getEndPage() {
		return endPage;
	}
	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}
	public int getRealEnd() {
		return realEnd;
	}
	public void setRealEnd(int realEnd) {
		this.realEnd = realEnd;
	}
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
	public int getAmount() {
		return amount;
	}
	public void setAmount(int amount) {
		this.amount = amount;
	}
	public int getPageNum() {
		return pageNum;
	}
	public void setPageNum(int pageNum) {
		this.pageNum = pageNum;
	}
	
	
}
package my.spring.project;

// 게시글 담는 VO
public class BoardVO {

	private int id;
	private String name;
	private String phone;
	private String email;
	private String address;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	
	
}
package my.spring.project;

public class Board {

	public PageVO setPageVO(int total, int pageNum, int amount, int paginationNum) {

		PageVO pageVO = new PageVO();
		
		// 1.0을 곱하는 이유는 int형 / int형 일 경우 결과값이 int형이다 
		// 예를 들어 결과값이 0 ~ 1일 경우 올림 해도 0이 나오기 때문에 로직에 오류가 생기게 된다.
		int endPage = (int)Math.ceil(pageNum * 1.0 / paginationNum) * paginationNum; 
		// 예) (5 / 3) * 3 -> 5페이지의 끝 페이지네이션은 6
		int startPage = endPage - paginationNum + 1 ; // 예) 20페이지 - 페이지네이션갯수 + 1 -> 11
		int prevPage = startPage - 1; // 무조건 시작페이지 -1 예) 18 에서 << 클릭시 10페이지로 이동
		int nextPage = startPage + paginationNum; // 18에서 >> 클릭시 21페이지로 이동
		int realEnd = (int)Math.ceil(total * 1.0 / amount); // 실제 마지막 페이지
		
		if(endPage > realEnd) endPage = realEnd;
		// 끝 페이지 경우 endPage가 realEnd보다 크면 endPage는 realEnd값이 된다.

		pageVO.setPaginationNum(paginationNum);
		
		pageVO.setPrevPage(prevPage);
		pageVO.setNextPage(nextPage);
		
		pageVO.setAmount(amount);
		pageVO.setPageNum(pageNum);
		pageVO.setTotal(total);
		
		pageVO.setStartPage(startPage);
		pageVO.setEndPage(endPage);
		pageVO.setTotal(total);
		pageVO.setRealEnd(realEnd);
		
		return pageVO;
	}

}
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">

<title>Home</title>
</head>
<body>


	<!-- 게시글 start-->
	<table border=1>
		<thead>
			<tr>
				<th>id</th>
				<th>name</th>
				<th>phone</th>
				<th>email</th>
				<th>address</th>
			</tr>
		</thead>
		<tbody>
			<c:forEach var="item" items="${boardList}">
				<tr>
					<td>${item.id}</td>
					<td>${item.name}</td>
					<td>${item.phone}</td>
					<td>${item.email}</td>
					<td>${item.address}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>
	<!-- 게시글 end-->

	<!-- 페이징 start-->
	<nav aria-label="Page navigation example">
		<ul class="pagination">


			<!-- 페이지네이션 중 first start -->
			<c:if test="${ pageVO.pageNum > pageVO.paginationNum}">
				<li class="page-item">
					<a class="page-link"
						href="/paging?pageNum=1&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Previous"> 
						<span aria-hidden="true">first</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 first end -->


			<!-- 페이지네이션 중 << 기호 start -->
			<c:if test="${ pageVO.pageNum > pageVO.paginationNum}">
				<li class="page-item">
					<a class="page-link"
						href="/paging?pageNum=${pageVO.prevPage}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Previous"> 
						<span aria-hidden="true">&laquo;</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 << 기호 end -->

			<!-- 페이지네이션 중 < 기호 start -->
			<c:if test="${ pageVO.pageNum != 1}">
				<li class="page-item">
					<a class="page-link"
						href="/paging?pageNum=${pageVO.pageNum-1}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Previous"> 
						<span aria-hidden="true">&lt;</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 < 기호 end -->

			<!-- 페이징번호 표현 start -->
			<c:forEach var="num" begin="${pageVO.startPage}" end="${pageVO.endPage}">

				<c:if test="${ pageVO.pageNum == num}">
					<li class="page-item active">
						<a class="page-link"
							href="/paging?pageNum=${num}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}">${num}
						</a>
					</li>
				</c:if>
				
				<c:if test="${pageVO.pageNum != num}">
					<li class="page-item">
						<a class="page-link" 
							href="/paging?pageNum=${num}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}">${num}
						</a>
					</li>
				</c:if>
				
			</c:forEach>
			<!-- 페이징번호 표현 end -->

			<!-- 페이지네이션 중 > 기호 start-->
			<c:if test="${ pageVO.pageNum != pageVO.realEnd }">
				<li class="page-item">
					<a class="page-link" 
						href="/paging?pageNum=${pageVO.pageNum+1}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Next"> 
					<span aria-hidden="true">&gt;</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 > 기호 end-->

			<!-- 페이지네이션 중 >> 기호 start-->
			<c:if test="${ pageVO.endPage != pageVO.realEnd }">
				<li class="page-item">
					<a class="page-link" 
						href="/paging?pageNum=${pageVO.nextPage}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Next"> 
					<span aria-hidden="true">&raquo;</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 >> 기호 end-->
			
			<!-- 페이지네이션 중 last start-->
			<c:if test="${ pageVO.endPage != pageVO.realEnd }">
				<li class="page-item">
					<a class="page-link" 
						href="/paging?pageNum=${pageVO.realEnd}&amount=${pageVO.amount}&paginationNum=${pageVO.paginationNum}" aria-label="Next"> 
					<span aria-hidden="true">last</span>
					</a>
				</li>
			</c:if>
			<!-- 페이지네이션 중 last end-->
			
		</ul>
	</nav>
	<!-- 페이징 end-->

</body>
</html>

 

결과화면

반응형