Spring

장민우·2021년 11월 1일
0

Spring

목록 보기
5/5
post-thumbnail

Spring Paging


@EnableWebMvc
public class ListControl implements Controller {
	
	@Autowired
	private BbsDAO b_dao;
	
	// 페이징 기법을 위한 상수들
	public final int BLOCK_LIST = 10; // 한 페이지당 보여질 게시물의 수
	
	public final int BLOCK_PAGE = 5; // 한 블럭당 보여질 페이지 수
	
	int nowPage; // 현재 페이지 값
	int rowTotal; // 전체 게시물의 수
	String pageCode; // 페이징 처리된 HTML코드가 저장될 곳
	
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 사용자가 브라우저에서 list.mo라고 요청했을때 수행하는 곳!
		
		// 반환객체 생성
		ModelAndView mv = new ModelAndView();
		
		// 현재 페이지 값 파라미터로 받기
		String c_page = request.getParameter("cPage");
		if(c_page == null)
			nowPage = 1;
		else
			nowPage = Integer.parseInt(c_page);
		
		// 게시판 종류를 구별하기 위해 이것 또한 파라미터로 
		String bname = request.getParameter("bname");
		if(bname == null)
			bname = "BBS"; // 일반 게시판
		
		// 총 게시물의 수를 얻어낸다.
		rowTotal = b_dao.getTotalCount(bname);
		
		// 페이징 처리를 위한 객체 생성(Paging)
		Paging page = new Paging(nowPage, rowTotal,BLOCK_LIST,BLOCK_PAGE);
		
		// 페이징 HTML코드 가져오기
		pageCode = page.getSb().toString();
		
		// JSP에서 표현할 게시물들의 목록을 받아내기 위해 begin과 end값이 필요하다.
        // 이들은 page에 있다.
		int begin = page.getBegin();
		int end = page.getEnd();
		
		BbsVO[] ar = b_dao.getList(begin, end, bname);
		
		// JSP에서 사용해야 할 값들을 모두 ModelAndView에 저장하자!
		mv.addObject("ar",ar);
		mv.addObject("nowPage",nowPage);
		mv.addObject("rowTotal",rowTotal);
		mv.addObject("blockList",BLOCK_LIST);
		mv.addObject("pageCode", pageCode);
		
		mv.setViewName("list"); // WEB-INF/jsp/list.jsp를 의미한다.
		
		return mv;
	}

}
  1. 멤버속성으로 페이지당 보여질 게시물의 수, 블럳당 보여질 페이지 수, 현재페이지 값, 전체게시물의 수
    페이징 처리된 HTML코드가 저장될 곳을 준비를 한다.
  2. 반환객체 생성 이후 현재 페이지 값을 파라미터로 받아 현재 페이지가 만약 null 이라면 1을 넣어준다.
    만약 그렇지 않다면 현재 페이지 값을 넣어준다.
  3. 게시판 종류를 구별하기 위해 파라미터로 값을 받아서 비교를 해준다. (만약 null 이라면 기본 게시판의 의미가 담긴 BBS를 넣어준다.)
  4. 총 게시물의 수를 얻어낸다. DAO를 호출해 총 게시물의 수를 구한뒤 그 값을 rowTotal에 담아준다.
  5. 이제 가장 중요한 페이징 처리를 위한 객체를 생성하자(Paging)
package spring.util;

public class Paging {
	
	private int nowPage,   // 현재 페이지
				rowTotal,  // 총 게시물 수
				blockList, // 한 페이지에 표현될 게시물 수 
				blockPage, // 한 블록당 표현할 페이지 수
				totalPage, // 전체 페이지 수
				startPage, // 시작페이지값
				endPage,   // 마지막 페이지값
				begin,     // 한 페이지의 표현할 시작레코드의 값
				end;       // 한 페이지의 표현할 마지막레코드의 값
	
	private boolean isPrePage;  // 이전 기능 가능여부(true일 때 이전기능 활성화)
	private boolean isNextPage; // 다음 기능 가능여부(true일 때 다음기능 활성화)
	
	// JSP에서 표현할 페이징 HTML코드를 저장할 곳!
	private StringBuffer sb;
	// 생성할때 인자를 4개를 받아 객체를 생성함과 동시에 모든 연산을 끝낸다.
	public Paging(int nowPage, int rowTotal, int blockList, int blockPage) {
		this.nowPage = nowPage;
		this.rowTotal = rowTotal;
		this.blockList = blockList;
		this.blockPage = blockPage;
		
		// 이전기능과 다음기능을 초기화 시킨다.
		isPrePage = false; // 나중에 구분을 위해서 먼저false로 기능을 초기화 했다.
		isNextPage = false;
		
		// 입력된 전체 게시물의 수를 통해 전체 페이지 값을 구하자!
		totalPage = (int)Math.ceil((double)rowTotal/blockList);
		// (double형으로 값을 받으면 소수점 자리가 나오기 때문에 int형으로 캐스팅을 해 절삭했다!)
        
		// 현재 페이지의 값이 전체페이지의 값보다 크다면 전체 페이지값을 현재 페이지 값으로 지정
		if(nowPage > totalPage)
			nowPage = totalPage;
		
		// 현재 블럭의 시작페이지 값과 마지막페이지 값을 구하자!
		startPage = (int)((nowPage - 1)/blockPage)*blockPage+1;
		endPage = startPage + blockPage - 1;
		
		// 마지막 페이지의 값이 전체 페이지의 값보다 크다면 마지막 페이지 값을 
        // 전체 페이지 값으로 지정
		if(endPage > totalPage)
			endPage = totalPage;
		
		// 현재 페이지 값에 의해 시작 게시물의 행번호와 마지막 게시물의 행번호를 지정하여 
        // 현재 페이지의 보여질 게시물 목록을 얻을 준비를 하자!
		begin = (nowPage - 1)*blockList + 1;
		end = nowPage * blockList;
		
		// 이전기능 가능여부 확인
		if(startPage > 1) // 이전 기능이 1보다 크다면 startpage는 1..6..11..16 순으로 증가하기
            			// 때문에 1보다 크면 기능을 부여한 것이다.
			isPrePage = true;
		
		// 다음기능 가능여부 확인
		if(endPage < totalPage)
			isNextPage = true;
		
		// 이제 현재페이지 값도 알고, 시작페이지와 마지막 페이지 값을 알았으니 
        // 페이징 기법에 사용할 코드를 작성하여 StringBuffer에 저장하자!
		sb = new StringBuffer("<ol class='paging'>");
		
		if(isPrePage) {
			sb.append("<li><a href='list.mo?cPage=");
			sb.append(nowPage-blockPage);
			sb.append("'>&lt;</a></li>");
		}else 
			sb.append("<li class='disable'>&lt;</li>");
		
		for(int i=startPage; i<= endPage; i++) {
			// i의 값이 현재 페이지의 값과 같을 때는 a태그를 지정하지 않고 숫자만 출력하자!
			if(i == nowPage) {
				sb.append("<li class='now'>");
				sb.append(i);
				sb.append("</li>");
			}else {
                // <li><a href="list.jsp?cPage=<%=i%>"><%=i%></a></li>
				sb.append("<li><a href='list.mo?cPage="); 
				sb.append(i); // 파라미터로 보내는 값
				sb.append("'>");
				sb.append(i); // 화면에 표현되는 페이지 값
				sb.append("</a></li>");
			}
				
		}// for의끝
		// 다음 기능 가능여부를 확인
		if(isNextPage) {
			sb.append("<li><a href='list.mo?cPage = ");
			sb.append(nowPage+blockPage);
			sb.append("'>&gt;</a></li>");
		}else
			sb.append("<li class='disable'>&gt;</li>");
		
		sb.append("</ol>");
	}
    // getter setter는 제외하겠다!! (너무 길어요,,)
-----------------------------------------------------------------------------------------
    
  1. 페이징 객체 생성을 완료 했으면 안에 있는 HTML코드를 가져오자.
  2. JSP에서 표현한 게시물들의 목록을 받아내기 위해 begin과 end값이 필요하다. page에서 가져오자.
  3. DAO를 호출하여 원하는 begin,end,bname을 인자로 넘겨줘 원하는 값들만 있는 BbsVO[]로 받았다.
  4. 모든 것을 완료 했으니 ModelAndView를 통해 반환을 해준다.(단 여기서 현재페이지,총게시물의수,한페이지당 보여질 게시물의 수, HTML코드도 같이 보내준다.)
  5. 여기서 총게시물의수,한페이지당 보여질 게시물의 수를 가져온 이유는 행번호를 순차적으로 번호값을 주기 위해서 이다. b_idx라는 기본키를 사용하면 번호가 너무 난잡한데 총게시물의 수의 맞게 순차적으로 하나씩 줄여들게 해주기 위해 사용되는 변수들이기 때문에 가져갔다.👇👇👇
<td> <%-- 순차적인 번호를 만들어서 표현하자! --%>
	${rowTotal - ((nowPage -1)*blockList+st.index)}
</td>
정의된 변수들을 표현할 JSP가서 EL태그로 정의만 해주면 상황에 맞게 페이징 기법과 다음으로 이전으로 기능까지 한번에 얻어낼 수 있는 복합적인 기능을 가진 클래스를 정의한 것 이다.

Spring STS

👇

main/java = 자바파일안에는 자바 관련만 정의 한다.
main/resources = 자바 파일이 아닌 xml파일등 정리하는 공간이다
이것을 꼭 지켜야한다.
test/java, test/resources : 이곳은 테스트를 해보는 공간이다.

Spring STS 에서 평소 우리가 지정했던 Controller-servlet.xml 파일이 WEB-INF/ 들어가 있는데

STS에서는 src/main/webapp/WEB-INF/spring/appServlet/ 안에 servlet-context.xml이 Controller-servlet.xml 와 같다.

applicationContext.xml 파일은 src/main/webapp/WEB-INF/spring/ 안에 root-context.xml와 같다.

STS Resolver 설정

<!-- 현재 springsts 버전이 3.X.X 이기 때문에 비동기식 통신을 위한 구문과 라이브러리 또한 다르다. -->
<beans:bean id="jsonHttpMessageConverter"
			class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
		<beans:bean
			class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
			<beans:property name="messageConverters">
				<beans:list>
					<beans:ref bean="jsonHttpMessageConverter" />
				</beans:list>
			</beans:property>
		</beans:bean>

원래 지정했던 방법이 아닌 bean객체를 등록을 해줄때 앞에 "beans:" 를 붙여서 등록을 해줘야한다.

STS Lib 설정

Ex: 비동기식 통신을 위한 라이브러리 설정
<!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
		<dependency>
		    <groupId>org.codehaus.jackson</groupId>
		    <artifactId>jackson-mapper-asl</artifactId>
		    <version>1.9.13</version>
		</dependency>
pom.xml 파일 안에 라이브러리를 다운받아 두는 것이 아닌 dependency를 지정을 해야한다.
spring STS를 사용할때 모든 라이브러리는 메이븐을 사용해서 dependency를 등록을 해줘야 한다.
👇👇👇 DB연결시 필요한 라이브러리 추가한 내용(파일업로드시 필요한 라이브러리는 추가하지 않았다.)
<!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
		<dependency>
		    <groupId>org.codehaus.jackson</groupId>
		    <artifactId>jackson-mapper-asl</artifactId>
		    <version>1.9.13</version>
		</dependency>
		       
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-tx</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		
		<dependency>
		    <groupId>commons-logging</groupId>
		    <artifactId>commons-logging</artifactId>
		    <version>1.2</version>
		</dependency>
		
		<dependency>
		    <groupId>commons-dbcp</groupId>
		    <artifactId>commons-dbcp</artifactId>
		    <version>1.4</version>
		</dependency>
		
		<dependency>
		    <groupId>commons-pool</groupId>
		    <artifactId>commons-pool</artifactId>
		    <version>1.6</version>
		</dependency>
		
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.5.7</version>
		</dependency>
				
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis-spring</artifactId>
		    <version>1.3.2</version>
		</dependency>

interceptor

Controller로 진행시 그전에 interceptor라는 곳을 들려 false일때는 기능 정지 true일때 수행하는 공간이다!
![화면 캡처 2021-11-01 100656](C:\Users\PC\Desktop\블로그\화면 캡처 2021-11-01 100656.png)@Overrid
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		// 먼저 HttpSession얻기
		HttpSession session = request.getSession(true); // true의 의미는 만약!
        				//세션이 삭제된 상태라면  새로운 새션을 생성해준다는 얘기이다!!
					// 삭제가 안된 상태라면 사용하고 있던 session을 그대로 전달해 준다.
		
		// 로그인 시 저장했던 객체를 얻어낸다.
		Object obj = session.getAttribute("mvo");
		
		if(obj == null) {
			// 로그인을 하지 않은 경우를 잡아낸 상태!!
			response.sendRedirect("/login");
			return false;
		}
		// 로그인이 된 상태인 경우.. 이때 해야할 일들이 있으면 여기쯤에서 구현하면 된다.
		
		return true;
	}

interceptor는 servlet이 호출될때 같이 호출 되기 때문에 servlet-context.xml에서 먼저 등록을 해줘야 한다.__(상속은 HandlerInterceptor를 받아야한다.)
<interceptors> <!-- 위치를 타는 곳 이다!! -->
		<interceptor>
			<mapping path="/sub/*"/>
			<beans:ref bean="log_inter"/>
		</interceptor>
	</interceptors>
위와 같이 정의를 꼭 해줘야 한다. mapping이 요청이 "/sub"로 들어오는 모든 경로는 interceptor를 거쳐서 간다라고 지정한 것이다 이 mapping은 하나말고 여러가지도 동시에 가능하다!

JDOM

@RequestMapping("/test")
	public String test(Model m) throws Exception { // 이게 파싱이다.
		
		SAXBuilder builder = new SAXBuilder(); // 로더 인식하고 읽어오는 SAXBuilder 생성
		
		String realPath = application.getRealPath(Path); // xml문서객체
		
		Document doc = builder.build(realPath+"/pm/data/member.xml"); // xml에 전체는 document다.
		
		Element root = doc.getRootElement(); // members
		
		List<MemVO> m_list = new ArrayList<MemVO>();
		
		// 루트의 자식들중 이름이 member인 요소들을 모두 가져온다
		List<Element> list = root.getChildren("member");
		for(Element item : list) { // item 하나가 member 요소를 의미한다.
			
			// member의 자식증 중 이름이 name인 요소의 문자열을 얻어낸다.
			String m_name = item.getChildText("name");
			String m_email = item.getChildText("email");
			MemVO mvo = new MemVO( m_name, m_email );
			m_list.add(mvo);
			//mvo.setEmail(m_email);
			//mvo.setName(m_name); // 이런 방식으로 객체를 생성하고 xml에서 파일로 넘어온 정보들을 저장이 가능해 객체화가 가능하다
		}
		System.out.println(m_list.size());
		System.out.println(m_list.get(1).getName());
		return "test";
	}
(위의 방식은 xml파일의 정보를 읽어 자바가 이해할 수 있는 자바객체로 객체화를 시키는 과정이다.)

  1. xml파일의 정보를 읽기 위해 SAXBuilder라는 xml을 읽을 수 있는 객체를 생성한다
  2. 파일을 읽기 위해서는 경로가 필요한데 그 경로는 절대경로로 지정을 해줘야 접근이 가능하다
  3. xml문서 안에 있는 내용의 전체는 document라고 한다 그 객체를 생성해서 build를 통해 파일을 읽어야 한다.
  4. Document를 얻어냈다면 이제 rootElement를 가져올 수 있다. (xml상에서 RootElement 단 한개만 존재할 수 있으므로 얻어낸다.)
  5. 이제 루투의 자식들 중 이름이 member인 요소들을 모두 가져온다(이때 반환은 List로 받는데 여기서 제네릭 타입은 xml이기 때문에 Element로 받아준다.)
  6. 원하는 값들을 가져와서 앞서 만들어둔 객체의 멤버변수 안에다가 넣어줌으로써 객체화를 시켜 사용이 가능하게 만들었다!(List형식으로 적재하여 쌓아두었다.)

중요 함수들

👆 SAXBuilder builder = new SAXBuilder(); : xml파일을 인식하고 읽어오는 객체이다.

✌ Document doc = builder.build("xml파일의 경로") : xml파일의 정보들을 읽어서 담는 객체이다.

👌 Element root = doc.getRootElement(); : 현재 rootElement의 이름을 가져오는 방법이다.

🖖 List list = root.getChildren("member"); : 루트의 자식들중 이름이 member인
요소들 을 모두 가져온다.

🖐 String m_name = item.getChildText("name"); : member의 자식증 중 이름이 name인
요소의문자열을 얻어낸다.

(이 처럼 xml파싱도 하나의 객체로부터 연결되어 값들을 가져와서 객체화를 시키는 것 이기 때문에 순서가 매우 중요하다!!)
profile
꿈틀대는꼬마개발자

0개의 댓글