열심히 끝까지
디바이스 융합 자바(Java) day73 - 2-Layered 아키텍쳐 본문
디바이스 융합 자바(Java) day73 - 2-Layered 아키텍쳐
노유림 2022. 9. 26. 17:35[오늘 진도]
[ 2-Layered 아키텍쳐 ]
- 입사지원서에 구조를 이해하고 있다고 어필 가능
Spring MVC를 기반으로한 프로젝트 순서
1. xxx.do 요청
2. 서블릿 컨테이너 구동
== DispatcherServlet을 생성한다는 뜻
>> DS-servlet.xml(설정 파일)를 참고(로드)해서 생성
: 현재의 계층(Layer)을 "프레젠테이션 레이어"라고 함
3. 스프링컨테이너 구동
: Controller 객체들 생성
: @, requestMapping 해줄 것들
: 이 때, Controller 객체로 DAO 객체를 사용함
-> DAO2를 사용하고 싶었으나 잘 안됨! @Autowired(의존성 주입)가 미리 되어 있어야 함!!!
☆ Controller의 모든 메서드는 DAO 객체를 직접 이용하고 있음!
☆ Spring(일반적인 프레임워크)에서는 DAO 객체를 직접 이용하지 않고,
반드시 "비즈니스 컴포넌트(ServiceImpl)"를 이용해서 DAO 객체를 다룰 수 있게끔 구성해야 함!!!!
★ 반드시 "비즈니스 컴포넌트"를 사용해야하는 이유?
1) DAO 클래스 교체 등의 유지보수 유리 및 용이
"비즈니스 컴포넌트"의 입장에서는 자신을 이용하는 클라이언트는 Controller!
클라이언트인 Controller는 ServiceImpl를 멤버변수로 사용하면 ServiceImpl가 변경되어도 Controller 자체는 변화 없음
== 낮은 결합도
2) AOP 적용 용이
횡단관심(어드바이스)이 동작하려면 Service 클래스(ex. pointcut.java)의 비즈니스 메서드가 실행되어야 함
결론 ) Controller 클래스는 "비즈니스 컴포넌트"를 멤버변수로 사용해야하며,
해당 객체에게 "의존성 주입(DI)"을 해야 함
★오늘의 핵심★
> 비즈니스 컴포넌트를 이용하려면??'
Controller가 Service를 멤버변수로 가지고 있고,
Service는 DAO를 멤버변수로 가지고 있음
>> Controller보다 ServiceImpl가 먼저 생성되어 있어야 함!!!
: Controller에 SI가 의존성 주입 될 예정이기 때문!!!!!
: ServiceImpl(비즈니스 컴포넌트)는 스프링 컨테이너가 생성해줘야하는 "객체"
== ServiceImpl를 생성하는 스프링컨테이너를 C를 생성하는
스프링컨테이너보다 먼저 구동시켜야 함!!
현재까지 진행순서
서블릿컨테이너 -> 스프링 컨테이너
앞으로의 진행순서
스프링컨테이너? -> 서블릿 컨테이너 -> 스프링 컨테이너?->스프링컨테이너
결론 ) 기존의 구조에서 스프링컨테이너가 1개 더 필요하고, 이 스프링컨테이너는
기존의 스프링컨테이너보다 먼저 구동되어야 함
기존의 구조 + 스프링컨테이너x1
>> [ 2-Layered 아키텍쳐 ]
기존의 Presentation Layer(MVC Layer : 책에서는 이렇게 등장)보다 "먼저 구동"되는
Business Layer(스프링 컨테이너)를 추가한 것
>> 먼저 구동되어야 하기 때문에 ContextLoaderListener 등록할 것
== 무조건 "web.xml"에 등록할 것
1. Listener는 Servlet
2. 기존의 스프링 컨테이너보다 먼저 구동 되어야 하기 때문에
기존의 스프링컨테이너보다 우선 적용되는 것에 등록
== /WEB-INF/applicationContext.xml 설정 파일이 없기 때문!!
applicationContext.xml은 JAVA 관련 설정파일이기 때문에
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
설정을 추가해서 사용할 것
1. BoardController에
@Autowired private BoardService boardService;
작성
2. BoardController에 BoardDAO를 지우고 boardService로 변경
[과거 코드는 디바이스 융합 자바 day72 참고]
--------BoardController.java
package com.ryo.biz.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
//import org.springframework.web.servlet.ModelAndView;
import com.ryo.biz.board.BoardService;
import com.ryo.biz.board.BoardVO;
import com.ryo.biz.board.impl.BoardDAO;
@Controller
@SessionAttributes("data") // "data"라는 이름의 데이터가 Model 객체에 세팅이 된다면, 그 것을 session에 기억시키겠다.
public class BoardController{
@Autowired
private BoardService boardService; // 비즈니스 컴포넌트, DAO를 직접 이용하지 않을 것!
// main에 넣을 구분값
@ModelAttribute("scMap")
public Map<String,String> searchConditionMap(){
// 인자 없고 맵 반환 예정
// 검색 조건에 들어가야 할 맵
Map<String,String> scMap = new HashMap<String,String>();
// 옵션에 들어갈 내용 관리 : View에 어떻게 보여야 할지 Model이 어떤 값을 받아야 할지
scMap.put("제목", "TITLE");
scMap.put("작성자", "WRITER");
// modeladdattribute 된 상태
return scMap;
}
// main
// API 분석 때 필요할 것, VO에 넣는 것이 좋음
@RequestMapping("/main.do")
public String main(@RequestParam(value="searchCondition", defaultValue="TITLE", required=false)String searchCondition, @RequestParam(value="searchContent", defaultValue="", required=false)String searchContent,BoardVO bVO, Model model){
// 검색하는 것의 값을 자동매핑 불가(커맨드 객체에는 없기 때문에 불가)
// java에서만 사용할 목적으로 BoardVO에 추가
// >> 하지만 전체에서 딱 한번 쓰는 등의 너무 비효율적일 때, 사용하는 @
// ==> @RequestParam
// : 커맨드 객체에는 없는 파라미터를 Controller 클래스에 전달해주기 위해 사용
System.out.println("검색조건: "+searchCondition);
System.out.println("검색어: "+searchContent);
List<BoardVO> datas = boardService.selectAllBoard(bVO);
model.addAttribute("datas", datas);
// mVO = mDAO.selectOneMember(mVO);
// model.addAttribute("userName", mVO.getName());
return "main.jsp";
}
// 글 하나 선택
@RequestMapping("/board.do")
public String board(BoardVO bVO, Model model){
bVO=boardService.selectOneBoard(bVO);
// mav.addObject("data", bVO);
model.addAttribute("data", bVO);
return "board.jsp";
}
/*
@RequestMapping("/board.do")
public ModelAndView board(BoardVO bVO, BoardDAO bDAO,ModelAndView mav){
bVO=bDAO.selectOneBoard(bVO);
mav.addObject("data", bVO);
mav.setViewName("board.jsp");
return mav;
}
*/
// 글 추가.jsp로 이동
@RequestMapping(value="/binsert.do", method=RequestMethod.GET)
public String binsertin() {
return "insertBoard.jsp";
}
// 글 추가
// get과 post일 때로 나눌 것 get은 이동 post일 때는
@RequestMapping(value="/binsert.do", method=RequestMethod.POST)
public String binsert(BoardVO bVO) {
boardService.insertBoard(bVO);
return "redirect:main.do";
}
// 글 삭제
@RequestMapping("/bdelete.do")
public String bdelete(BoardVO bVO) {
boardService.deleteBoard(bVO);
return "redirect:main.do";
}
// 글 업데이트
@RequestMapping("/bupdate.do")
public String bupdate(@ModelAttribute("data")BoardVO bVO) {
boardService.updateBoard(bVO);
return "redirect:main.do";
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
BoardVO bVO = new BoardVO();
bVO.setBid(Integer.parseInt(request.getParameter("bid")));
BoardDAO bDAO = new BoardDAO();
bVO=bDAO.selectOneBoard(bVO);
HttpSession session = request.getSession();
session.setAttribute("data", bVO);
ModelAndView mav = new ModelAndView();
mav.addObject("data", bVO);
mav.setViewName("board.jsp");
return mav;
}
*/
// @Override
// public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
// BoardVO bVO = new BoardVO();
// bVO.setBid(Integer.parseInt(request.getParameter("bid")));
//
// BoardDAO bDAO = new BoardDAO();
// bVO=bDAO.selectOneBoard(bVO);
//
// HttpSession session = request.getSession();
// session.setAttribute("data", bVO);
//
// return "board";
// }
}
memberController.java---------------
package com.ryo.biz.controller;
import javax.servlet.http.HttpServletRequest;
// import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.SessionAttributes;
//import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.ryo.biz.member.MemberService;
import com.ryo.biz.member.MemberVO;
import com.ryo.biz.member.impl.MemberDAO;
@Controller
@SessionAttributes("member")
public class MemberController {
@Autowired
private MemberService memberService;
// 로그인으로 들어가는 index
@RequestMapping(value="/login.do", method=RequestMethod.GET)
public String index() {
// 로그인 화면을 보여줘!
// 기본이 포워드 방식
// 데이터를 넣어서 보낼 때는 그냥 쓰면 됨
return "login.jsp";
}
// POST 요청에서만 할 수 있게 가능
// 로그인 및 세션에 정보 저장
@RequestMapping(value="/login.do", method=RequestMethod.POST)
public String selectOneMember(MemberVO mVO, HttpSession session) {
System.out.println("로그 : 로그인컨트롤러 들어옴");
//ModelAndView mav = new ModelAndView();
mVO = memberService.selectOneMember(mVO);
if(mVO == null){
return "login.jsp";
}
else {
// mav.addObject("member", mVO);
// mav.setViewName("main.do");
session.setAttribute("user", mVO);
return "redirect:main.do";
}
}
// 데이터를 넣으려면 ModelAndView 사용해야 함
/*
@RequestMapping(value="/login.do", method=RequestMethod.POST)
public ModelAndView selectOneMember(MemberVO mVO, MemberDAO mDAO, ModelAndView mav) {
System.out.println("로그 : 로그인컨트롤러 들어옴");
mVO = mDAO.selectOneMember(mVO);
return "login.jsp";
}
*/
// 로그아웃
@RequestMapping("/logout.do")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
//view Resolver는 기본이 forward 방식이구나!
return "redirect:login.do";
}
// 회원가입
@RequestMapping("/signin.do")
public String signin(MemberVO mVO) {
memberService.insertMember(mVO);
return "redirect:login.do";
}
// 멤버 삭제
@RequestMapping("/mdelete.do")
public String mdelete(HttpServletRequest request,MemberVO mVO) {
System.out.println(mVO.getMid());
System.out.println("삭제하려는 mVO의 값 : " + mVO.getMid());
memberService.deleteMember(mVO);
HttpSession session = request.getSession();
session.invalidate();
return "redirect:login.do";
}
// 멤버 업데이트
@RequestMapping("/mupdate.do")
public String mupdate(@ModelAttribute("member")MemberVO mVO) { // MemberVO mVO, MemberDAO mDAO,HttpSession session
System.out.println("데이터 확인 : " + mVO);
memberService.updateMember(mVO);
// session.setAttribute("user", mVO);
return "redirect:main.do";
}
// 마이페이지
@RequestMapping("/mypage.do")
public String mypage(HttpSession session, Model model) { // (MemberVO mVO, MemberDAO mDAO)
// mVO = mDAO.selectOneMember(mVO);
model.addAttribute("member",session.getAttribute("user"));
return "mypage.jsp";
}
// public ModelAndView mypage(MemberVO mVO, MemberDAO mDAO, ModelAndView mav) {
//
// mVO = mDAO.selectOneMember(mVO);
// mav.addObject("member", mVO);
// mav.setViewName("mypage.jsp");
// return mav;
// }
}
3. web.xml에
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
위 코드 추가
== 먼저 구동되어야 하기 때문에 web.xml에 작성할 것
web.xml 전체 코드-----------------
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<!-- 사용하는 디스패쳐 서블릿 관련 작성 -->
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 인코딩 필터 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!-- 언어 적용되는 곳 필터 -->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
4. applicationContext.xml를 찾기 위해서 web.xml에
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
위 코드 추가할 것
> 추가하는 이유
: /WEB-INF/applicationContext.xml 설정 파일이 없기 때문!!
applicationContext.xml은 JAVA 관련 설정파일이기 때문에 위처럼 작성해줄 것
[정리]
1. 서버(tomcat) 시작
2. web.xml 파일 로딩, 서블릿 컨테이너 구동
3. 서블릿 컨테이너는 web.xml에 등록된 ContextLoaderListener 객체를 가장 먼저 생성
-> Pre-loading 방식
4. 생성되는 ContextLoaderListener 객체는 src/main/resources의 applicationContext.xml을 로딩하여
스프링 컨테이너를 구동하라고 설정
-> 먼저 실행되는 스프링 컨테이너를 "Root 컨테이너"라고 함
5. ServiceImpl, DAO 객체들을 메모리에 생성
6. 원래 하던 내용 실행
7. xxx.do 요청
8. 서블릿 컨테이너 구동
== DispatcherServlet을 생성한다는 뜻
>> DS-servlet.xml(설정 파일)를 참고(로드)해서 생성
: 현재의 계층(Layer)을 "프레젠테이션 레이어"라고 함
9. 스프링컨테이너 구동
: Controller 객체들 생성
: @, requestMapping 해줄 것들
: 이 때, Controller 객체로 DAO 객체를 사용함
-> DAO2를 사용하고 싶었으나 잘 안됨! @Autowired(의존성 주입)가 미리 되어 있어야 함!!!
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day75 - 에러 페이지 설정 (0) | 2022.09.28 |
---|---|
디바이스 융합 자바(Java) day74 - 파일 업로드 및 파일 미리보기 추가 (0) | 2022.09.27 |
디바이스 융합 자바(Java) day72 - Spring MVC 관련 코드 정리(CRUD) (1) | 2022.09.23 |
디바이스 융합 자바(Java) day71 - @RequestParam, @ModelAttribute, @SessionAttributes (1) | 2022.09.22 |
디바이스 융합 자바(Java) day70 - Spring에 @(어노테이션) 걸기 (0) | 2022.09.21 |