본문 바로가기

programming/Gukbi

국비 교육 78일차 - spring mvc 게시판 만들기, mvc 프로젝트 셋팅

728x90
반응형

드디어 스프링으로 mvc 게시판을 만들어 봤다. 이제 이걸 토대로 2차 팀 프로젝트를 진행하게 될 것 같다. 

 

 파일 구성은 이렇게 되어 있다. 

java 에는 DAO, VO, Controller, mapper 파일들이 있고 

src 폴더에는 view에 해당하는 jsp 파일들과 스프링 컨테이너 파일에 해당하는 application-context,datasource 파일들을 저장해준다. 

 

 이거는 내가 나름대로 정리해본 스프링 mvc 구조도이다. 

 

사용자가 request를 보내면 dispatcherServlet을 통해 model 클래스들에게 필요한 데이터를 전송한다. 

Model 클래스들은DAO로부터 데이터베이스에서 받아온 값을 받아와 다시 dispatcherServlet에 전달한다. 

 

그러면 받은 데이터를 viewResolver로 보내주고, viewResolver는 jsp파일명을 찾아서 전송해준다. 

dispatcherservlet이 model를 request로 변환하여 jsp로 전송하면 jsp에서 처리한 화면을 response와 함께 사용자의 화면에 띄워준다.

 

이런 원리로 mvc 구조가 완성되어 있다. 

 

그럼 먼저 spring container 부분을 보면, 

<!-- Controller등록(DispatcherServlet) 
         브라우저를 통해서(웹프로그램) 요청을 받는 경우 사용기술 : 서블릿 , JSP =>  일반 자바는 요청을 받을 수 없다 
         = 서블릿이나 JSP는 구동을 톰캣이 한다 : 톰켓에 등록 (등록하는 파일 : web.xml) 
    -->
    <!-- 
                  클래스 등록 분리
          1) 사용자 정의 클래스 등록 : application-context.xml
          2) 라이브러리 클래스 등록  : application-datasource.xml 
          3) 웹 : http , 웹소켓 : ws : application-socket.xml
          4) 보안    application-security.xml
     -->

 

클래스를 모아주는 컨테이너에서도 클래스를 파일마다 분리해서 등록해주어야 한다. 

사용자 정의 클래스는 application-context.xml, 

라이브러리 클래스는 application-datasource.xml 에 각각 등록해준다. 

아래 2개는 아직 배우지 않아서 다음에 배우면 다시 정리하도록 하겠다. 

 

 

사용자 정의 클래스를 모아주는  application-context.xml 파일

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!-- 사용자가 만든 모든 클래스를 메모리 할당 요청  -->
    <context:component-scan base-package="com.sist.*"/>
    <!-- ViewResolver에 경로명,확장자 전송 
                 스프링은 자바전용이 아니다 
         1) 경로명
         2) 확장자 
         
         => return "board/list";  => 스픵에서는 전송시에 확장자를 사용하면 안됩니다 
            => /board/list.jsp
    -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/"
          p:suffix=".jsp"
     />
</beans>

 사용자가 만든 모든 클래스의 메모리 할당을 요청하고, viewresolver에 경로명과 확장자를 전송한다. 

 

그리고 라이브러리 클래스를 등록하는 application-datasource.xml 파일

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 오라클 정보를 모아둔다 : BasicDataSource -->
    <!-- mybatis : dbcp (maxActive:8,maxIdle:8) -->
    <bean id="ds"
         class="org.apache.commons.dbcp.BasicDataSource"
         p:driverClassName="oracle.jdbc.driver.OracleDriver"
         p:url="jdbc:oracle:thin:@localhost:1521:XE"
         p:username="hr"
         p:password="happy"
         p:maxActive="10"
         p:maxIdle="10"
         p:maxWait="-1"
    />
    <!-- 마이바티스로 전송 : SqlSessionFactoryBean:getConnection(),disConnection() -->
    <bean id="ssf"
        class="org.mybatis.spring.SqlSessionFactoryBean"
        p:dataSource-ref="ds"
        p:configLocation="/WEB-INF/config/Config.xml"
    />
</beans>

 여기서는 mybatis 라이브러리를 사용할 클래스들의 메모리 할당을 요청한다. BaiscDataSource, SqlSessionFactoryBean 클래스의 메모리 할당을 요청해서 오라클에 연결할 준비를 완료한다. 

 

그리고 VO와 mapper 클래스를 모아두는 config.xml 파일을 생성해준다. 

<?xml version="1.0" encoding="UTF-8"?>
<!-- VO와 mapper.xml파일 모아 두는곳 -->
<!DOCTYPE configuration
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <typeAlias type="com.sist.dao.BoardVO" alias="BoardVO"/>
  </typeAliases>
  <mappers>
    <mapper resource="com/sist/dao/board-mapper.xml"/><!-- xml에서 include -->
  </mappers>
</configuration>

 

그리고 mapper.xml에서 dao에 전송해줄 sql문장을 적어준다. 

 

<?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 namespace="com.sist.dao.board-mapper">
  <!-- 목록 출력 : 페이징 -->
  <!-- 
       public List<BoardVO> boardListData(int page)  ==> selectList()
       {
            List<BoardVO> list=new ArrayList<BoardVO>();
            try
            {
                 getConnection();
                 String sql="~~ WHERE num BETWEEN ? AND ?"; ==> 1
                             <select>SQL문장</select>
                 ps=conn.preparedStatement(sql);
                 ==================== 2  ==> parameterType
                 ps.setInt(1,start);
                 ps.setInt(2,end);
                 ====================
                 ResultSet rs=ps.executeQuery();
                 while(rs.next())
                 {
                    ============================== 3 ==> resultType
                     BoardVO vo=new BoardVO();
                     vo.setNo(rs.getInt(1);
                     vo.setName(rs.getString(2));
                     
                     ...
                     ...
                     ==============================
                     list.add(vo);
                 }
            }catch(Exception ex)
            {
                 ex.printStackTrace();
            }
            finally
            {
                disConnection();
            }
            
            return list;
       }
   -->
   <!-- 
        resultType="BoardVO" parameterType="hashmap" => 한번만 사용이 가능 
        SELECT no,title FROM recipe
              ==========
              resultType="RecipeVO"
              resultType="hashmap"
    -->
  <select id="boardListData" resultType="BoardVO" parameterType="hashmap">
    SELECT no,subject,name,TO_CHAR(regdate,'YYYY-MM-DD') as dbday,hit,num
    FROM (SELECT no,subject,name,regdate,hit,rownum as num 
    FROM (SELECT no,subject,name,regdate,hit 
    FROM webboard ORDER BY no DESC))
    WHERE num BETWEEN #{start} AND #{end}
  </select>
  <select id="boardTotalpage" resultType="int">
    SELECT CEIL(COUNT(*)/10.0) FROM webboard
  </select>
  <!-- 상세보기  -->
  <select id="boardDetailData" resultType="BoardVO" parameterType="int">
    SELECT no,name,subject,content,regdate,hit 
    FROM webboard
    WHERE no=#{no}
  </select>
  <!-- 조회수 증가 -->
  <update id="boardHitIncrement" parameterType="int">
    UPDATE webboard SET
    hit=hit+1
    WHERE no=#{no}
  </update>
  <!-- 글쓰기  -->
  <insert id="boardInsert" parameterType="BoardVO">
    INSERT INTO webboard VALUES(
      (SELECT NVL(MAX(no)+1,1) FROM webboard),
      #{name},
      #{subject},
      #{content},
      #{pwd},
      SYSDATE,
      0
    )
  </insert>
  <!-- 수정 -->
  <select id="boardGetPassword" resultType="String" parameterType="int">
    SELECT pwd FROM webboard
    WHERE no=#{no}
  </select>
  <update id="boardUpdate" parameterType="BoardVO">
    UPDATE webboard SET
    name=#{name},subject=#{subject},content=#{content}
    WHERE no=#{no}
  </update>
  <!-- 삭제 -->
  <delete id="boardDelete" parameterType="int">
    DELETE FROM webboard
    WHERE no=#{no}
  </delete>
  <!-- 찾기 -->
</mapper>

 

그리고 controller

 

package com.sist.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.sist.dao.*;

// DispatcherServlet와 연결 => DAO에서 결과값을 전송(ViewResolver)
/*
 *   1. 요청 
 *   2. DispatcherServlet 
 *   3. 요청과 관련된 데이터를 받는다 Model
 *   4. 요청 <==> DAO
 *   5. 결과값을 ViewResolver로 전송 
 */
import java.util.*;
@Controller
public class BoardController {
   // 데이터베이스 연결 => DAO의 객체 얻기
   @Autowired // 자동 주입 => 스프링에서 BoardDAO객체주소를 찾아서 자동으로 주입
   private BoardDAO dao;
   /*
    *   GET  ==> GetMapping()
    *   POST ==> PostMapping()
    *   ======================= +
    *      RequestMapping()
    */
   // 기능 출력 
   @GetMapping("board/list.do")
   public String board_list(String page,Model model)
   {
	   if(page==null)
		   page="1"; // default 
	   int curpage=Integer.parseInt(page);
	   // start,end
	   Map map=new HashMap();
	   int rowSize=10;
	   int start=(rowSize*curpage)-(rowSize-1);
	   int end=rowSize*curpage;
	   map.put("start", start);
	   map.put("end", end);
	   // WHERE num BETWEEN #{start} AND #{end} => Map을 지정하는 경우에는 반드시 키명을 설정
	   List<BoardVO> list=dao.boardListData(map);
	   int totalpage=dao.boardTotalpage();
	   // ViewResolver로 데이터를 전송 
	   model.addAttribute("list", list); // => request.setAttribute("list", list)
	   model.addAttribute("curpage", curpage);// => request.setAttribute("curpage", curpage)
	   model.addAttribute("totalpage", totalpage);// => request.setAttribute("totalpage", totalpage)
	   return "board/list";
   }
   @GetMapping("board/detail.do")
   public String board_detail(int no,Model model)
   {
	   BoardVO vo=dao.boardDetailData(no);
	   model.addAttribute("vo", vo);
	   return "board/detail";
   }
   @GetMapping("board/insert.do")
   public String board_insert()
   {
	   return "board/insert";
   }
   @PostMapping("board/insert_ok.do")
   public String board_insert_ok(BoardVO vo)
   {
	   dao.boardInsert(vo);
	   return "redirect:list.do"; // 목록
   }
   @GetMapping("board/update.do")
   public String board_update(int no,Model model)
   {
	   //DAO연동 
	   BoardVO vo=dao.boardUpdateData(no);
	   model.addAttribute("vo", vo);
	   return "board/update";
   }
   // @Controller => return시 반드시 파일명,.do ==> @RestController를 사용해서 스크립트 전송
   @PostMapping("board/update_ok.do")
   public String board_update_ok(BoardVO vo,Model model)
   {
	   // 결과값 전송 => 비밀번호 체크 
	   boolean bCheck=dao.boardUpdate(vo);
	   model.addAttribute("no", vo.getNo());
	   model.addAttribute("bCheck", bCheck);
	   return "board/update_ok";
   }
   @GetMapping("board/delete.do")
   public String board_delete(int no, Model model)
   {
	   model.addAttribute("no", no);
	   return "board/delete";
   }
   @PostMapping("board/delete_ok.do")
   public String board_delete_ok(int no, String pwd, Model model)
   {
	   boolean bCheck=dao.boardDelete(no, pwd);
	   model.addAttribute("bCheck", bCheck);
	   return "board/delete_ok";
   }
}

 이전 프로젝트와 다른 점은 post 방식과 get 방식을 각각 다른 어노테이션을 쓰고 있다는 점이다. 어떤 방식으로 데이터를 보내주고 있는지를 잘 확인해야한다. 

 

이 외에는 jsp를 이용한 프로젝트와 다른점이 없어 생략하겠다.

 

위에 적은 spring mvc구조와 셋팅, get/post 방식 구분만 잘 신경써주면 될 것 같다. 

728x90
반응형