블로그를 변경하였습니다.

해당 블로그는 더 이상 추가 포스팅 없을 예정입니다.

👉 새 블로그 방문하기


[KH정보교육원 당산] 72일 ( 어노테이션 방식)

2021. 6. 23. 16:33
728x90
반응형

어제 완성했던 XML방식의 Spring MVC를 이번에는 어노테이션 방식으로 변경

 

어노테이션을 사용하는 이유는 XML문서에 대한 과도한 설정을 방지하기 위해서 사용한다.

먼저 XML문서에서 context xml namespace를 추가한 후에 base-package지정

 

xmlns:context="http://www.springframework.org/schema/context" <--xml상단에 추가되었다.

<context:component-scan base-package="com.jdh.spring"></context:component-scan>

어노테이션을 이용하기에 등록해놨던 모든 bean들을 지워주고 

context:component-scan 태그만 남겨놓는다.

 

base-package="기본패키지"  <-- 지정한 패키지의 하위까지 검색하여 자동으로 객체를 등록

 

컨트롤러 역할을 담당하는 모든 클래스 선언부에 @Controller 어노테이션 부여

=> DispatcherServlet이 인식할 수 있는 컨트롤러 객체로 만들어준다.

 

** 만약 @Controller 어노테이션을 사용하지 않을 경우에는 스프링이 제공하는 Controller 인터페이스를 구현받아

handlerRequest() 메서드를 제정의 받아야한다.!!

 

 

 

InsertBoardController 클래스 수정

@Controller
public class InsertBoardController {
	
	//<prop key="/insert.do">insertBoard</prop>와 같은 의미
	@RequestMapping(value="/insertBoard.do")
	public void insertBoard(HttpServletRequest request) {
    
    String title = request.getParameter("title");
		String content = request.getParameter("content");
		String writer = request.getParameter("writer");
		
		BoardVO vo = new BoardVO();
		vo.setTitle(title);
		vo.setContent(content);
		vo.setWriter(writer);
		
		BoardDAO dao = new BoardDAO();
		dao.insertBoard(vo);
		
	}

}

Controller 인터페이스 대신 어노테이션을 사용

 

@RequestMapping(value="/insertBoard.do") 

** value 속성은 생략해도 무방하지만 정확한 경로를 알기위해서는 명시해줘야한다.

정확한 경로를 명시해줘서 검색시간을 최소화시킨다.

 

/insertBoard.do 요청이 들어왔을 때 해당 메서드가 호출될 수 있도록 매핑

이 때 사용자로부터 입력된 값은 매개변수인 HttpServletRequest request의 param 영역으로 전달된다.

 

일반적으로 사용자의 입력 값이 고정적일 경우에는 VO객체를 이용하여 DAO와 주고 받지만,

 

사용자의 입력값이 다양할 경우 VO객체를 여러가지 선언해야하는 단점이 발생한다.

이 단점을 보안하기 위하여 제공되는 객체가 Command객체

insertBoard()의 매개변수 타입을 BoardVO 타입으로 변경하여 스프링 컨테이너가 insertBoard()를 호출할 때 사용자 입력값들을 Command 객체에 넘겨주고 이 Command 객체를 insertBoard(BoardVO vo)의 매개변수인 vo 변수에게 전달하여 자동 매핑이 되도록 한다.

 

@Controller
public class InsertBoardController {
	
	//<prop key="/insert.do">insertBoard</prop>와 같은 의미
	@RequestMapping(value="/insertBoard.do")
	public void insertBoard(BoardVO vo) {
		
		BoardDAO dao = new BoardDAO();
		
		dao.insertBoard(vo);
		
	}

}

기존 타입의 request에서 BoardVO 타입으로 변경 후 코드가 짧아진것을 알수 있다.

BoardVO vo 매개변수 : 사용자 입력값과 자동 매핑 처리 => command객체

 

흐름)

클라이언트 요청(파라미터값으러 넘어감)   ->   Spring Container   ->   Command   ->   해당 파라미터 보유한 VO클래스 검색    ->   VO클래스 이용하여 VO객체 생성   ->   VO객체의 setter메서드를 이용하여 값 저장

->   VO 객체를 해당 메서드의 매개변수한테 전달

 

**** 전달되는 파라미터 명과 VO클래스의 멤버변수명 반드시 일치해야한다.!!

 

데이터가 정상적으로 들어가는지 확인

데이터가 들어간후 어느페이지로 갈지 정하지 않았기 때문에 404에러는 당연한거다.

@Controller
public class InsertBoardController {
	
	//<prop key="/insert.do">insertBoard</prop>와 같은 의미
	@RequestMapping(value="/insertBoard.do")
	public String insertBoard(BoardVO vo,BoardDAO dao) {
		
		dao.insertBoard(vo);
        
		return "redirect:getBoardList.do";
	}

}

값이 넘어올때 dao 객체도 자동 생성

 

Controller 메서드가 실행되고 View 경로를 리턴하면 기본이 포워딩 방식

포워딩 방식으로 전달 되기 때문에 URL창을 확인해보면 URL이 변경되지 않는다.

=> 게시글 리스트 목록(getBoardList.do) 으로 넘어가도 URL상에서는 getBoard.do

 

그렇기에 포워딩이 아닌 리다이렉트로 전달할때는 redirect: 를 붙여서 경로를 반환한다.

페이지 전환 => return "redirect:getBoardList.do";

 

 

 

게시글 목록

@Controller
public class GetBoardListController {

	@RequestMapping(value="/getBoardList.do")
	public ModelAndView getBoardList(BoardVO vo, BoardDAO dao, ModelAndView mav) {
		System.out.println("게시글 불러오기");
		
		mav.addObject("board",dao.getBoardList(vo));
		mav.setViewName("getBoardList.jsp"); //resolver가 없기때문에 정확히 명시
		return mav;
	}
}

마찬가지로 컨트롤러 어노테이션 사용

 

게시글 등록과 다른 부분은 getBoardList는 3개의 매개 변수를 가진다.

객체를 받을 vo, 데이터 접근을 위한 dao, 다음 저장한 값을 전달하기 위한 ModelAndView 객체

 

기존에는 List<BoardVO> 객체를 생성하여 그 안에 값을 담았는데

이번에는 굳이 그러지 않고 바로 값을 꺼낸 후에 boardList라는 변수명으로 담아서 전달.

 

 

다른 컨트롤러도 이와같이 해주면 된다.

 

 


위에서 했던 각각의 컨트롤러를 통합

 

BoardController 클래스 생성

@Controller
public class BoardController {

	// 글등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo, BoardDAO dao) {

		dao.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	//게시글 목록
	@RequestMapping(value="/getBoardList.do")
	public ModelAndView getBoardList(BoardVO vo, BoardDAO dao,ModelAndView mav) {
		System.out.println("게시글 불러오기");
		
		mav.addObject("board",dao.getBoardList(vo));
		mav.setViewName("getBoardList.jsp"); //resolver가 없기때문에 정확히 명시
		return mav;
	}
	
	//상세보기
	@RequestMapping(value="/getBoard.do")
	public ModelAndView getBoard(BoardVO vo, BoardDAO dao, ModelAndView mav){
		
		mav.addObject("board",dao.detailBoard(vo));
		mav.setViewName("getBoard.jsp");
        
        return mav;
	}
	
	//글 수정
	@RequestMapping(value="/updateBoard.do")
	public String updateBoard(BoardVO vo, BoardDAO dao){
		
		dao.updateBoard(vo);
		
		return "redirect:getBoardList.do";
	}
	
	//글 삭제
	@RequestMapping(value="/deleteBoard.do")
	public String deleteBoard(BoardVO vo, BoardDAO dao){
		
		dao.deleteBoard(vo);
		
		return "redirect:getBoardList.do";
		
	}
}

 

UserController클래스 생성

@Controller
public class UserController {

	@RequestMapping(value = "/login.do")
	public String handleRequest(UserVO vo, UserDAO dao) throws Exception {
		System.out.println("로그인");

		UserVO user = dao.getUser(vo);

		if (user != null) {
			return "redirect:getBoardList.do";
		} else {
			return "redirect:login.jsp";
		}
	}

	@RequestMapping(value = "/logout.do")
	public String logout(HttpSession session) {

		session.invalidate();

		return "login.jsp";

	}
}

 

 

코드를 보면 반환타입이 String타입 또는 ModelAndView로  되어있다.

 

이 코드를 String타입으로 통일시킬것이다.

 

기존 상세보기에서 반환타입이 ModelAndView로 되어있었다.

ModelAndView -> String으로 바꾸면 문제점이 return타입으로 경로만 넘어가고 값을 담은 board라는 객체는 넘어가지않는다. 이를 해결하기 위하여 Model 객체 생성하여 값을 저장 한 후에 넘기면 된다.

 

//상세보기
	@RequestMapping(value="/getBoard.do")
	public String getBoard(BoardVO vo, BoardDAO dao, Model model){
		
		model.addAttribute("board",dao.detailBoard(vo));
		
		return "getBoard.jsp";
	}

 

 


검색 기능

 

게시글 목록을 나타내는 getBoardList.jsp 상단에 제목 또는 본문내용 검색을 통하여 게시글을 불러오는 기능 추가

<h2> 로그인 성공</h2> <a href="logout.do">로그아웃</a>
	<form action="getBoardList.do" method="post">
		<table border="1">
			<tr>
				<td align="center">
					<select name="searchCondition">
						<option value="title"> 제목
						<option value="content"> 본문
					</select>
					<input type="text" name="searchKeyword" />
					<input type="submit" value="검색" />
				</td>
			</tr>
		</table>
	</form>

넘어가는 파라미터명 : Select 태그의 seachCondition

                             option 태그의 title 또는 content

 

해당 파라미터명은 BoardVO에 멤버 변수로 설정되어있지 않다.

 

@RequestParam 어노테이션을 통하여 파라미터값을 직접 받을 것이다.

 

 

public ModelAndView getBoardList(@RequestParam(value="searchCondition", defaultValue="title") String condition,
				@RequestParam(value="searchKeyword", defaultValue="") String keyword,
				BoardVO vo, BoardDAO dao,ModelAndView mav) {

(@RequestParam(value="넘어오는파라미터명", defaultValue="값이없을때초기값") String 변수명) <--- 넘어온 값을 저장받을 변수

 

어노테이션 말고 기존방법대로 사용할려면 BoardVO에 해당 파라미터명의 멤버변수를 선언해서 사용하면된다.

 

 

검색 조건

@ModelAttribute("conditionMap")
	public Map<String,String> seachConditionMap(){
		Map<String,String> conditionMap = new HashMap<String,String>();
		
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		
		return conditionMap;
	}

 

@ModelAttribute("~~") => JSP 에서 사용될 변수명

 

검색 조건 메서드에 HashMap을 통하여 값을 설정 하였으므로 getBoardList.jsp 의 검색 창부분을 JSTL로 표현이 가능하다.

 

<select name="searchCondition">
	<c:forEach items="${conditionMap }" var="option">
		<option value="${option.value }">${option.key }</option>
	</c:forEach>
</select>

이와같이 표현가능

Map이 가지고 있는 key와 value를 꺼낸다.

 

값을 추가할때는 Map에서 put메서드를 통하여 값을 넣어주면된다. 

 

 

클래스 선언부에

@SessionAttributes("~~") 

ex) @SessionAttributes("board") => 세션값 설정

해당 클래스에서 board라는 객체명으로 값이 전달 되면 세션선언 부분에 (board)라고 설정해놨기 때문에

세션으로 생성된다.

 

 

 


728x90
반응형

BELATED ARTICLES

more