이클립스에서 boardList, SearchCriteria, PageMaker, Criteria 전부 가져오기
패키지 이름이 다르니까 고쳐주기
<a href ="<%=request.getContextPath()%>/board/boardList.aws">게시판 목록가기</a>
1. 인덱스 페이지에 경로 추가하기
package com.myaws.myapp.controller;
import java.util.ArrayList;
@Controller
@RequestMapping(value="/board/")
public class BoardController {
private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
// BoardService 타입의 객체를 자동으로 주입. 주입 실패 시에도 에러가 발생하지 않고 null로 설정됨
@Autowired(required = false)
private BoardService boardService;
// PageMaker 객체를 자동으로 주입하여 페이지 정보를 설정
@Autowired(required = false)
private PageMaker pm;
//게시글 목록을 조회하고 검색 조건에 맞는 게시글을 화면에 표시하는 메서드
@RequestMapping(value="boardList.aws", method=RequestMethod.GET)
public String boardList(SearchCriteria scri, Model model) {
// 총 게시글 수를 검색 조건(scri)을 기준으로 조회
int cnt = boardService.boardTotalCount(scri);
// PageMaker 객체에 검색 조건과 총 게시글 수를 설정하여 페이지 네비게이션을 준비
pm.setScri(scri);
pm.setTotalCount(cnt);
// boardService에서 주어진 검색 조건(scri)을 기반으로 게시글 목록을 조회
ArrayList<BoardVo> blist = boardService.boardSelectAll(scri);
// 조회된 게시글 목록을 "blist"라는 이름으로 모델에 추가하여 JSP 뷰 페이지로 전달
model.addAttribute("blist",blist);
// PageMaker 객체도 모델에 추가하여 JSP 뷰에서 페이지 정보도 접근할 수 있도록 설정
model.addAttribute("pm",pm);
//경로에 해당하는 JSP 뷰 페이지를 반환
return "WEB-INF/board/boardList";
}
}
2. BoardController 생성해서 메서드 생성
package com.myaws.myapp.service;
import java.util.ArrayList;
import com.myaws.myapp.domain.BoardVo;
import com.myaws.myapp.domain.SearchCriteria;
public interface BoardService {
public ArrayList<BoardVo> boardSelectAll(SearchCriteria scri);
public int boardTotalCount(SearchCriteria scri);
}
3.BoardService 생성하기
package com.myaws.myapp.service;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.myaws.myapp.domain.BoardVo;
import com.myaws.myapp.domain.SearchCriteria;
import com.myaws.myapp.persistance.BoardMapper;
@Service
public class BoardServiceImpl implements BoardService {
// BoardMapper 타입의 객체 생성 (MyBatis와 연동)
private BoardMapper bm;
@Autowired // SqlSession 객체를 주입받는 생성자
public BoardServiceImpl(SqlSession sqlSession) {
// 주입받은 sqlSession 객체를 이용하여 BoardMapper를 초기화
this.bm = sqlSession.getMapper(BoardMapper.class); /* 꼭 뒤에 클래스가 붙어야한다. */
}
// 게시글 목록을 검색 조건에 따라 조회하는 메서드
@Override
public ArrayList<BoardVo> boardSelectAll(SearchCriteria scri) {
// HashMap 객체를 생성하여 페이징, 검색 타입, 키워드 등의 조건을 추가
HashMap<String,Object> hm = new HashMap<String,Object>();
hm.put("startPageNum",(scri.getPage()-1)* scri.getPerPageNum()); // 시작 페이지 번호
hm.put("searchType", scri.getSearchType()); // 검색 유형
hm.put("keyword", scri.getKeyword()); // 검색 키워드
hm.put("perPageNum", scri.getPerPageNum()); // 페이지당 게시글 수
// BoardMapper를 사용해서 검색 조건에 맞는 게시글 목록 조회
ArrayList<BoardVo> blist = bm.boardSelectAll(hm);
return blist;
}
// 총 게시글 수를 검색 조건에 따라 가져오는 메서드
@Override
public int boardTotalCount(SearchCriteria scri) {
// 검색 조건을 통해 BoardMapper에서 총 게시글 수를 조회
int cnt = bm.boardTotalCount(scri);
return cnt;
}
}
4. BoardServiceImpl 생성하기
package com.myaws.myapp.persistance;
import java.util.ArrayList;
import java.util.HashMap;
import com.myaws.myapp.domain.BoardVo;
import com.myaws.myapp.domain.SearchCriteria;
public interface BoardMapper {
/* 마이바티스용 메소드. 서비스에 있는 메소드 이름을 동일하게 해서 헷갈리지 않게 한다. */
public ArrayList<BoardVo> boardSelectAll(HashMap<String,Object> hm);
public int boardTotalCount(SearchCriteria scri);
}
5. BoardMapper 생성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- Mapper의 네임스페이스 설정. 해당 인터페이스와 정확히 연결하기 위해 사용-->
<mapper namespace="com.myaws.myapp.persistance.BoardMapper">
<!-- 검색 필터링을 위한 SQL 구문 정의 -->
<sql id ="search">
<!-- 검색 조건이 'writer'일 경우 -->
<if test="searchType != null and searchType.equals('writer')"> <!-- 작성자 검색어 포함 -->
and writer like concat('%',#{keyword},'%')
</if>
<!-- 검색 조건이 'subject'일 경우 -->
<if test="searchType != null and searchType.equals('subject')"> <!-- 제목 검색어 포함 -->
and subject like concat('%',#{keyword},'%')
</if>
</sql>
<!-- 게시글 목록 조회 쿼리 -->
<select id="boardSelectAll" parameterType="HashMap" resultType="bv">
select * from board where delyn='N' <!-- 삭제되지 않은 게시글만 조회 -->
<include refid="search"/> <!-- 검색 필터링 조건 포함 -->
order by originbidx desc, depth asc limit #{startPageNum}, #{perPageNum} <!-- 페이징 처리 -->
</select>
<!-- 게시글 총 개수를 조회하는 쿼리 -->
<select id ="boardTotalCount" parameterType="scri" resultType="int">
select count(*) as cnt from board where delyn='N'
<include refid="search"/> <!-- 검색 필터링 조건 포함 -->
</select>
</mapper>
6. boardMapper.xml 생성하기
<typeAlias alias="bv" type="com.myaws.myapp.domain.BoardVo"/>
<typeAlias alias="scri" type="com.myaws.myapp.domain.SearchCriteria"/>
7. mybatis_config.xml에서 추가해주기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import = "java.util.*" %>
<%@ page import="com.myaws.myapp.domain.*" %>
<%
ArrayList<BoardVo> blist = (ArrayList<BoardVo>)request.getAttribute("blist");
//System.out.println("blist==>" + blist);
PageMaker pm = (PageMaker)request.getAttribute("pm"); //2-39. 뭐야...
// 게시물 목록 순서 나타내기
int totalCount = pm.getTotalCount(); //전체갯수를 뽑아왔어
String keyword = pm.getScri().getKeyword();
String searchType = pm.getScri().getSearchType();
String param = "keyword="+keyword+"&searchType="+searchType+"";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글목록</title>
<link href="/resources/css/style2.css" rel="stylesheet">
</head>
<body>
<header>
<h2 class="mainTitle">글목록</h2>
<form class="search" name="frm" action="<%=request.getContextPath()%>/board/boardList.aws" method="get">
<select name = "searchType"> <!-- 어떤걸 선택할래? -->
<option value = "subject">제목</option>
<option value = "writer">작성자</option>
</select>
<input type="text" name ="keyword"> <!-- 나는 키워드로 입력할거야 -->
<button type="submit" class="btn">검색</button>
</form>
</header>
<section>
<table class="listTable">
<tr>
<th>No</th>
<th>제목</th>
<th>작성자</th>
<th>조회</th>
<th>추천</th>
<th>날짜</th>
</tr> <!--스크립틀릿 : 서버에서 실행될 Java 코드를 JSP 페이지에 삽입하여 동적으로 HTML을 생성하는 역할 -->
<% int num = totalCount - (pm.getScri().getPage()-1)*pm.getScri().getPerPageNum(); // 전체갯수중에 15개를 빼면??
for(BoardVo bv : blist) { //23. 향상된 for문. blist라는 리스트를 순회하면서 각 요소를 변수에 담아 반복 작업을 수행
String lvlStr = ""; // 초기화
for(int i=1; i<=bv.getLevel_(); i++) {
lvlStr = lvlStr + " "; // html에서 띄어쓰기 기호
if(i == bv.getLevel_()) { // i가 level과 같으면 // level이 증가하면 칸을 옮기고 ㄴ자를 표시해라.
lvlStr = lvlStr + "ㄴ"; // ㄴ자 표시를 해준다.
}
}
%>
<tr>
<td><%=num %></td>
<td class="title">
<%=lvlStr %>
<a href="<%=request.getContextPath() %>/board/boardContents.aws?bidx=<%=bv.getBidx() %>"><%=bv.getSubject() %></a></td>
<td><%=bv.getWriter() %></td>
<td><%=bv.getViewcnt()%></td>
<td><%=bv.getRecom()%></td>
<td><%=bv.getWriteday() %></td>
</tr>
<%
num = num-1;
}
%>
</table>
<div class="btnBox">
<a class="btn aBtn" href="<%=request.getContextPath() %>/board/boardWrite.aws">글쓰기</a>
</div>
<!-- 2-40. 이거 다 하면 보드Dao로 가세요 -->
<div class="page">
<ul>
<%if (pm.isPrev()==true) { %>
<li><a href="<%=request.getContextPath()%>/board/boardList.aws?page=<%=pm.getStartPage()-1%>&<%=param%>">←</a></li>
<% } %>
<% for(int i = pm.getStartPage(); i<=pm.getEndPage(); i++) { %>
<li <%if (i==pm.getScri().getPage()) {%> class="on"<%}%> >
<a href="<%=request.getContextPath()%>/board/boardList.aws?page=<%=i%>&<%=param%>"><%=i%> <!-- 해당 검색어가 있으면 그 다음페이지에도 있어야 하니까? -->
</a>
</li>
<% }%>
<%if(pm.isNext()==true && pm.getEndPage()>0){ %>
<li><a href="<%=request.getContextPath()%>/board/boardList.aws?page=<%=pm.getEndPage()+1%>&<%=param%>">→</a></li>
<% } %>
</ul>
</div>
</section>
</body>
</html>
8. boardList.jsp
HashMap은 Java의 java.util 패키지에 있는 클래스 중 하나로, 키-값 쌍으로 데이터를 저장하는 자료구조입니다. HashMap은 다음과 같은 특징을 가지고 있습니다:
키-값 쌍 저장: 각 데이터는 고유한 키와 그에 대응하는 값으로 저장됩니다. 키를 통해 빠르게 값을 검색할 수 있습니다.
중복 키 허용하지 않음: 동일한 키를 가진 값을 추가하면 기존의 값이 새로운 값으로 덮어씌워집니다.
null 허용: HashMap은 null 키와 null 값을 허용합니다. 다만, null 키는 하나만 저장할 수 있습니다.
정렬되지 않은 순서: HashMap은 데이터가 저장된 순서나 특정 기준에 따라 정렬되지 않으며, 해시 함수에 의해 위치가 결정됩니다.
비동기적: 기본적으로 HashMap은 스레드에 안전하지 않습니다. 여러 스레드에서 동시에 접근할 경우 ConcurrentHashMap을 사용하는 것이 좋습니다.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
// 데이터 추가
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
// 데이터 조회
System.out.println("apple의 값: " + map.get("apple")); // 결과: apple의 값: 1
// 데이터 삭제
map.remove("banana");
// 키가 존재하는지 확인
System.out.println("banana가 존재하나요? " + map.containsKey("banana")); // 결과: false
}
}
HashMap은 사전처럼 작동하는 자료구조입니다. 마치 영어 사전에서 단어(키)를 입력하면 해당 단어의 뜻(값)을 찾을 수 있는 것처럼, HashMap도 키-값 쌍으로 데이터를 저장하고, 키를 사용해 값을 빠르게 찾을 수 있습니다.
HashMap의 기본 개념
키와 값(Key-Value): HashMap에 저장된 각각의 항목은 키와 값으로 이루어져 있어요.
예를 들어, "apple"이라는 키와 1이라는 값을 저장한다고 하면, HashMap에선 ("apple", 1) 이런 식으로 저장됩니다.
map.get("apple")을 호출하면 1이라는 값을 쉽게 찾을 수 있습니다.
고유한 키: 각 키는 고유해야 해요. 같은 키를 두 번 저장하려고 하면, 이전 값이 새 값으로 바뀝니다. 예를 들어, "apple" 키에 1을 저장한 후 다시 "apple"에 2를 저장하면, 최종적으로 "apple"의 값은 2가 됩니다.
빠른 검색과 추가: HashMap은 내부적으로 해시 함수를 사용해 키의 위치를 빠르게 찾아갑니다. 덕분에 데이터를 찾거나 추가하는 작업이 매우 빠릅니다.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
// 학생의 이름과 점수를 저장하는 HashMap
HashMap<String, Integer> scores = new HashMap<>();
// 데이터 추가
scores.put("철수", 85);
scores.put("영희", 92);
scores.put("민수", 76);
// 철수의 점수를 찾기
System.out.println("철수의 점수: " + scores.get("철수")); // 결과: 철수의 점수: 85
// 민수의 점수를 변경하기
scores.put("민수", 80);
System.out.println("민수의 새로운 점수: " + scores.get("민수")); // 결과: 민수의 새로운 점수: 80
// 특정 학생이 있는지 확인하기
System.out.println("영희가 있나요? " + scores.containsKey("영희")); // 결과: 영희가 있나요? true
// 학생의 점수 목록을 출력하기
for (String key : scores.keySet()) {
System.out.println(key + "의 점수: " + scores.get(key));
}
}
}
데이터 추가: scores.put("철수", 85);를 호출하면, "철수"라는 이름을 키로 하고 85를 값으로 하여 HashMap에 저장합니다.
데이터 조회: scores.get("철수");를 사용하면 "철수"라는 키로 저장된 값, 즉 85를 얻을 수 있습니다.
데이터 수정: scores.put("민수", 80);을 통해 "민수"의 점수를 80으로 수정할 수 있습니다.
키 존재 여부 확인: scores.containsKey("영희");를 통해 "영희"라는 이름이 HashMap에 있는지 확인할 수 있습니다.
이렇게 HashMap을 사용하면 빠르게 데이터를 추가하고 찾을 수 있습니다. 그래서 HashMap은 데이터를 많이 다루면서 빠른 검색이 필요할 때 매우 유용합니다.