반응형

이제 거의 다왔습니다.. 

 

실제로 개발의 기반이되는 (이론 따위 필요없고 개발 하고 싶으면 이것만 보면된다.)

 

근데 개발만 할껀아니잖아요.. 앞에 이론도 좀 봐야함...

 

 

아무튼!

 

우리의 Spring의 흐름은 간단하게 얘기하면

1. Dispatcher-Servlet

2. Controller

3. Service(impl)

4. DAO(impl)

5. Mybatis

6. 다시 Controller로 돌아와 -> JSP 호출(동적페이지)

 

이런식으로 흐른다고 보면된다. 실제로 개발을 할 때에 해당 프로세스는 숙지하고 있어야하며 다 알아야한다.

안그러면 힘들다... 그래서 하나하나 살펴보려고 한다.

 

1, 2번 Dispatcher-servlet 이 받은 요청 처리해주기.

(Dispatcher-Servlet-Controller)

자. 첫단추를 끼워야한다.

 

@RequestMapping , @Controller 이라는 어노테이션만 알면 끝난다. 위치와 소스는 다음과 같다. 

위치는 보통 com/kitao/kr 까지만 생성되있을 껀데, 본인은 구분을 쉽게하기 위해 co, coa 까지 생성해 주었다.

controller의 위치

package com.kitao.kr.co.coa.controller;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.kitao.kr.co.coe.service.BoardService;
import com.kitao.kr.co.coe.vo.BoardVO;

/**
 * Handles requests for the application home page.
 */

@Controller
public class HomeController {
	@Value("#{properties['ACTION_NAME']}")
	public String ACTION_NAME;
	
	@Resource(name="boardService")
	private BoardService boardService;
		
	@RequestMapping(value = "/")
	public ModelAndView home(ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
		request.setCharacterEncoding("UTF-8");
		List <BoardVO> boardVO = boardService.selectBoardList();

		ModelAndView mv = new ModelAndView("co/coa/home");
		mv.addObject("serverTime", "이거 넣을껀데?");
		mv.addObject("boardVO", boardVO);
		
		return mv;
	}
}

 

소스는 이렇게 하나하나 차례로 살펴보자...

@Controller는 여기가 컨트롤러단이다! 라는걸 의미한다.

또한, @RequestMapping(value = "/") 의 의미는 가장 쉽게 말해서 Home에 접근하면 여기를 와라 라는 것이다.

즉, https://wwwhttp://localhost:9122/kr/ 이게 호출되면 해당 Controller를 탈 것이다.

 

여기서 부터 시작인 셈이다. 다음 class home을 봐보자.

return 형이 ModelAndView인건 아직 신경쓰지말자 다음에 얘기할 때가 오겠지..

 

아무튼 다시 돌아오면,

그리고 그 다음 단계인 Service 비스.. 무리한 애가 보인다. 전에 배웠던, 의존성 역전의 법칙을 사용하여(@Resoure) 먼저 의존성을 주입하고, Service단이 실행되는 것으로 보인다. 아마 Service 단에서 실행된 애가 boardVO형의 리스트에 넣어지는 것으로 보인다. 그러면 Service 단을 먼저 살펴보자.

 

service의 의치

저기에서 service는 coe쪽에 있지만, 뭐 상관없다. 어디에 위치해 있든, @Service 이노테이션을 통해 얘가 service단이다! 라는걸 선언해주면 된다. 그럼 안에 소스를 봐보자. 아 보기전에. VO를 봐보겠다.

 

BoardVO.java

package com.kitao.kr.co.coe.vo;

import java.util.Date;

public class BoardVO {
	private String boardId;
	private String boardContents;
	private String boardTitle;
	private Date boardRegDtm;
	
	public String getBoardId() {
		return boardId;
	}
	public void setBoardId(String boardId) {
		this.boardId = boardId;
	}
	public String getBoardContents() {
		return boardContents;
	}
	public void setBoardContents(String boardContents) {
		this.boardContents = boardContents;
	}
	public String getBoardTitle() {
		return boardTitle;
	}
	public void setBoardTitle(String boardTitle) {
		this.boardTitle = boardTitle;
	}
	public Date getBoardRegDtm() {
		return boardRegDtm;
	}
	public void setBoardRegDtm(Date boardRegDtm) {
		this.boardRegDtm = boardRegDtm;
	}
	
	
}

보면 그냥.. 맴버변수에 메소드변수가 들어가있는 것이다. 이게 끝이다. 다음 Service단을 보겠다.

 

BoardService.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

public interface BoardService {
	List<BoardVO> selectBoardList() throws Exception;
}

 

아니 이건 뭐 설명할 필요도 없다. 그냥 Service의 부모가 되는 빈 인터페이스가 선언 되어 있다.

그다음 BoardServiceImpl이 중요하다.

 

3번 Service(impl)

 

BoardServiceImpl.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kitao.kr.co.coe.dao.COEBoardDAO;
import com.kitao.kr.co.coe.memory.test;
import com.kitao.kr.co.coe.vo.BoardVO;

@Service("boardService")
public class BoardServiceImpl implements BoardService {
    @Autowired    
	private COEBoardDAO boardDAO;
    
	@Override
	public List<BoardVO> selectBoardList() throws Exception {
	    // 비즈니스 로직 수행
		return boardDAO.boardSearch();
	} 
}

자 여기 다있다.. @Servce("boardService") 라는 애는 얘가 서비스이다! 라는걸알려준다. 따라서, Controller에서

호출된 서비스는 여기로 올 수 있었던 것이다. 실제로 구현도 여기서 다 이루어져 있다.

엄~청 간단한 impl단이지만, 실제로 비즈니스 로직을 수행하는 곳이기도 하다.

 

이제 쿼리를 실행하는 Mybatis를 실행하는 DAO를 보겠다.

 

 

4번, 5번 DAO(impl)과 Mybatis

 

COEBoardDAO.java

DAO 위치

package com.kitao.kr.co.coe.dao;

import java.util.List;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class COEBoardDAO {
	@Inject 
	private SqlSession session; 
	private static String namespace = "com.kitao.kr.boardListSearch";

	public List<BoardVO> boardSearch() throws Exception {
		return session.selectList(namespace+".selectBoardSearch");
	}
}

 

자 이제. Mybatis를 실행하기 위해 여기 까지 왔다.. 쿼리를 실행하면 된다.

본인은 DAO, DAOImp로 나누지 않고 DAO에 선언과 구현을 동시에 하였다. 본인이 편한걸로 하면된다.

여기서 선언과 동시에 return으로 쿼리를 반환하는 것을 볼 수 있다.

본인의 쿼리문은 com.kitao.kr.boardListSearch에 있다는 것을 어느정도 유추할 수 있다.

다음단계 쿼리문 작성하는 곳을 가보자.

 

 

ds.COEBoardList_sql.xml

xml 위치

자 낚시 조심하다 위치는 java가 아니라 resources/mappers에 있다. 여기에 생성해 주어야한다. 또한 파일명은 상관없다.

<?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.kitao.kr.boardListSearch">
	<select id='selectBoardSearch' resultType="com.kitao.kr.co.coe.vo.BoardVO"> 
		SELECT 
			BOARD_ID,
			BOARD_TITLE,
			BOARD_CONTENTS,
			BOARD_REG_DTM
		  FROM
		  	BOARD_MST
	</select> 
</mapper>

자 소스는 다음과 같다. 오.. 뭔가 쿼리문이 보이지 않는가....여........

아~까 session.selectList("com.kitao.kr.boardListSearch"); 이게 여기를 찾아 온다고 생각하면된다..

근데 어떻게 찾아오냐고 물으신다면... 조~기 위에 보이는 mapper로 인해서 여기로 찾아 올 수 있게 된다.

그래서 여기서 실행된 쿼리문에 의해서 Controller에 존재하는 BoardVO에 담기는 것이다!!!! ...

신기하지 않은가?...

 

근데 하나의문이 있는게 쿼리문에서 실행 된 결과는 다음과 같다.

본인이 임의로 넣은 데이터

이런식인데 컬럼명은 BOARD_ID 인데.. BoardVO의 한 변수를 보면 boardId로 선언 되어 있을 것이다..

조금 규칙이 보이지 않는가? 우리는 여기서 '카멜케이스'라는걸 사용해야한다. (모르면 찾아보세요...ㅎ)

이 카멜케이스라는 것을 설정해주면 자바스프링에서는 자동으로 매칭 해 줄 수 있다.

예를들어..

boardVO.boardPw <-> BOARD_PW

boardVO.boardTitle<-> BOARD_TITLE

boardVO.boardContents<-> BOARD_CONTENTS

이런식으로 자동으로 매칭된다는 것이다. 설정은 다음과 같이 할 수 있다.

 

mybatis-config.xml

mybatis-config.xml 위치

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
		<setting name="callSettersOnNulls" value="true"/>
		<setting name="jdbcTypeForNull" value="NULL"/>
	</settings>
</configuration>

전에 mybatis사용하려고 만든 mybatis-config.xml에 설정을 하고 소스는 상단과 같다.

여기서 카멜케이스를 사용하여 자동 매핑하는 세팅은 setting에 mapUnderscoreToCamelCase라는 친구이다.

callSettersOnNulls, jdbcTypeForNull 얘는 몬지모르겠다. 구글링했는데 뭐 같이 딸려온애 같은데.

 

나중에 배울꺼지만 callSettersOnNulls 얘는 Mybatis ResultMap을 동적으로 받기위해 HashMap으로 받을 시

value 값이 Null 일때 칼럼이 누락되는 현상을 방지하기 위에 존재한다.

 

jdbcTypeForNull 이 아이는.. Oracle을 사용할 때, Null을 넣을 수 있는 컬럼값에 Null을 넣게 되면 부적합반 열 유형이라는 에러를 뱉게 되는데, 이걸 방지하기 위해 선언한 것이라고 생각하면 된다.

 

 

6. 다시 Controller로 돌아와 -> JSP 호출(동적페이지)

자 이제 그럼 다시 Controller단을 봐보자.

package com.kitao.kr.co.coa.controller;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.kitao.kr.co.coe.service.BoardService;
import com.kitao.kr.co.coe.vo.BoardVO;

/**
 * Handles requests for the application home page.
 */

@Controller
public class HomeController {
	@Value("#{properties['ACTION_NAME']}")
	public String ACTION_NAME;
	
	@Resource(name="boardService")
	private BoardService boardService;
		
	@RequestMapping(value = "/")
	public ModelAndView home(ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
		request.setCharacterEncoding("UTF-8");
		List <BoardVO> boardVO = boardService.selectBoardList();

		ModelAndView mv = new ModelAndView("co/coa/home");
		mv.addObject("serverTime", "이거 넣을껀데?");
		mv.addObject("boardVO", boardVO);
		
		return mv;
	}
}

 

자 여기를 보면, List <BoardVO> boardVO에 자동으로 매핑되어(카멜케이스 이용) 쿼리문 결과를 넣어준다. 그 다음,

ModelAndview mv = new ModelAndView("co/coa/home"); <- 이건 마지막단계인 jsp가 어디있는지 넣고

jsp로 갈 때 같이 넘기고 싶은 변수를 설정해서(mv.addObject 사용) jsp에 넘겨준다.

 

그러면 JSP가 실행 되는 것이다. jsp 위치와 소스를 봐보자.

 

home.jsp

home.jsp

home.jsp는 기본적으로 src/main/webapp/WEB-INF/views에 있다.

여기서 WEB-INF/views 위치 설정은 servlet-context.xml에서 설정할 수 있다. (전에 봤었다..)

 

소스는 다음과 같다.

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1>${serverTime}</h1>
	<c:forEach var="cw" items="${boardVO}">
		<p>번호 : ${cw.boardId}</p>
		<p>번호 : ${cw.boardTitle}</p>
		<p>번호 : ${cw.boardContents}</p>
		<p>번호 : ${cw.boardRegDtm}</p>
		<br><br><br>
	</c:forEach>
</body>
</html>

 

 

이렇게 jsp의 동적페이지 생성으로 끝난다. 그러면 결과를 보자.

결과물

자... 감격스럽다... 이렇게 사용자가 이 화면을 보는 것이다. 비전공자는 모를것이다. 페이지가 이렇게 많은 단계를 거치고 걸쳐서 사용자를 위해 제공 되는지.. 원래 아는 만큼 보이는 것이다.

 

 

이로써 1~6단계 Controller에서 시작해서 Mybatis-JSP 까지 가는 과정이 끝나게 된다.

사실, 프로세스적으로도 중요하지만, 가장 중요한건 HTML, CSS, JS, JAVA, 쿼리문 작성 능력도 중요하다.

프로세스를 다 알고있는 가정하에, 해당 언어로 누가 더 좋은 로직을 짜느냐, 효율성 있는 로직을 짜느냐, 보안이슈를

다 틀어 막느냐, 유지보수를 가정하고 코드를 짜느냐, 스파게티(?) 코드를 덜짜느냐의 문제로 나아가는 것이다.

 

 

 

도움이 되셨다면 아래 공감 버튼 눌러주세요.(로그인 필요없어요!)

반응형
반응형

Servlet에 대해서 알아보려고 한다.

 

사실 Servlet은 JSP/Servlet이라고 하긴하는데, Java Spring에서도 기반이 되는 이론이니 짚어보고 가려고 한다.

 

이 전에 사실 Dispatcher-servlet이라는 아이를 배웠다.

 

Dispatcher-servlet은 간단하게, 모든 요청을 받아들이고, Controller로 가는 전단계이며, Dispatcher-servlet의 등장으로 인해 web.xml의 역할을 굉장히 많이 축소시켜 줬다고 설명했다. 

 

그래서 Servlet이뭔데? 다음 그림을 보면 쉽게 이해가 갈 것이다.

 

Servlet 구조

 

뭐 javax.servlet에서 가장상위가 Servlet 하위는 HttpServlet 그것을 다시상속 받아서 DispatcherServlet이 된 셈이다.

부모와 자식 이라고 생각하면 편할 것이다.

 

Servlet -> Servlet 관련 추상 메소드를 선언

GenericServlet -> Service 메소드를 제외, Servlet 인터페이스를 구현, 추상 클래스, Servlet 기능관련 추상메소드 선언

HttpServlet -> 실제로 Http 요청에 필요한 Service 메소드를 구현

대충 감이 오지 않아?.. Dispatcher-servlet은 Http요청에 관한 Service 메소드도 있겠고.. 뭐 그런 셈이다.

 

Servlet 구조는 다음과 같이 구조되어 있다고 생각하면 된다.

1. Servlet(할아머니) - 추상클래스

    - Init()

    - Service()

    - Destroy()

 

2. GenericServlet (엄빠) - 추상클래스

 

3. HttpServlet (자식) - 인터페이스 한다.

 

 

 

사실 Servlet은 JSP/Servlet이라고 하긴하는데, Java Spring에서도 기반이 되는 이론이니 짚어보고 가려고 한다.

 

 

 

이 전에 사실 Dispatcher-servlet이라는 아이를 배웠다.

 

 

 

Dispatcher-servlet은 간단하게, 모든 요청을 받아들이고, Controller로 가는 전단계이며, Dispatcher-servlet의 등장으로 인해 web.xml의 역할을 굉장히 많이 축소시켜 줬다고 설명했다. 

 

 

 

그래서 Servlet이뭔데? 다음 그림을 보면 쉽게 이해가 갈 것이다.

 

 

 

Servlet 구조

 

 

뭐 javax.servlet에서 가장상위가 Servlet 하위는 HttpServlet 그것을 다시상속 받아서 DispatcherServlet이 된 셈이다.

 

부모와 자식 이라고 생각하면 편할 것이다.

 

 

 

Servlet -> Servlet 관련 추상 메소드를 선언

 

GenericServlet -> Service 메소드를 제외, Servlet 인터페이스를 구현, 추상 클래스, Servlet 기능관련 추상메소드 선언

 

HttpServlet -> 실제로 Http 요청에 필요한 Service 메소드를 구현

 

대충 감이 오지 않아?.. Dispatcher-servlet은 Http요청에 관한 Service 메소드도 있겠고.. 뭐 그런 셈이다.

 

 

 

Servlet 구조는 다음과 같이 구조되어 있다고 생각하면 된다.

 

1. Servlet(할아머니) - 추상클래스

    - Init() 선언

    - Service() 선언

    - Destroy() 선언

    - getServletConfig() 선언

    - getServletInfo() 선언

 

2. GenericServlet (엄빠) - 추상클래스

     - Server() 구현

 

3. HttpServlet (자식) - 인터페이스

    - doGet() 구현

    - doPost() 구현

    - getServletConfig() 구현

    - getServletInfo() 구현

 

 

그 다음 Servlet 동작 과정을 살펴보겠다.

Servlet 동작 과정

위는 Servlet의 동작 과정이다.

1. 사용자 요청을 받는다.

2. Servlet Container는 HttpServletRequest, HttpServletResponse를 생성한다.

3. 사용자 URL을 분석하여 어느 Servlet인지 구분한다.

(web.xml에 mapping된 것을 확인한다. @WebServlet("/myservlet");

4. Service(), doGet(), doPost()가 차례로 실행된다. 이때, doGet() 혹은 doPost()는 동적 페이지(JSP) 생성후,

HttpServletResponse객체에 응답을 받아 보낸다.

(Post 방식이면 doPost, Get 방식이면 doGet)

5. 응답을 끝내면 HttpServletRequest, HttpServletResponse는 자동 소멸된다.

(그래서 항상 RequestMapping 쪽 메소드 인자보면 HttpServletRequest, HttpServletResponse를 넣을 수 있다.)

 

 

그래서 우리가 생각하는 WAS = Tomcat = Servlet Container 라고 생각하면 편하다.

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern> <!-- 모든 요청을 DispatcherServlet이 처리한다. -->
	</servlet-mapping>

위의 내용은 전에 봤던, web.xml에 들어 있는 태그값들이다.

여기서 appServlet 은 web.xml 다음단계인 Servlet을 의미한다.

간단하게 정리하면,

1. Tomcat(Servlet Container)가 실행되면서 web.xml이 실행되면서, Servlet Container객체가 생성 될 수 있는 기반 마련

2. 실제로 사용자 요청이 들어오면 클라이언트로 부터 /요청(모든 요청)을 받는다.

3. /(모든요청) 클래스를 찾아 객체 생성 doGet()메소드 호출 후 결과를 Client로 전송.

참쉽죵?

 

 

그 다음으로 Servlet의 생명주기를 봐보자.

Servlet Life Cycle

1. 객체 생성(Servlet Container)가 생성 되고, 최초 실행시에 init()이 실행된다.

2. 컨테이너에서 전달되는 요청이 있을 시, service()메소드 호출. service는 알아서 doGet(), doPost() 호출

[요청이 들어올 때 마다 service() 메소드 호출]

3. 오랜 시간 아무런 요청이 들어오지 않거나 애플리케이션이 종료되면 destory() 메소드가 호출 된다.

 

다음은 Servlet 생명주기 테스트를 해보겠다.

https://localhost:9128/kr/board/BoardList.do 를 호출 했을때,

다음과 같은 결과가 나온다.

 

init() -> 최초실행

doGet() -> 상단 주소 실행했을때(여러번 나온 이유는 여러번 호출했기 때문 광클했다...)

이로써 알수 있는건 최초 실행때만 init() 메소드 실행 그 이후는 doGet이나 doPost가 실행된다는 것이다.

여기서 이제 요청이 오래 안들어오거나 웹어플리케이션이 종료되면 destroy() 메소드도 호출될 것이다.

 

결과 값

 

 

소스는 다음과 같다.

package com.kitao.kr.servlet;

import java.io.IOException;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/*")
public class ServletTestCode extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
     * @see HttpServlet#HttpServlet()
     */
    public ServletTestCode() {
        super();
        // TODO Auto-generated constructor stub
    }
 
    @Override
    public void init() throws ServletException {
        // TODO Auto-generated method stub
        super.init();
        System.out.println("init( )");
    }
    
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        super.destroy();
        System.out.println("destroy( )");
    }

    
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("HowToServletEx : doGet");
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
        System.out.println("HowToServletEx : doPost");
    }
}

 

이걸 어떻게 생성해야하는지.. 모르면 다음과같이 하면 된다.

저기 kr 하위에 servlet 패키지를 만들고.

 

저기 보이지는 않지만, servlet 패키지 우클릭 -> New -> Servlet 클릭을 한다.

 

이름은 아무렇게나 누르고 Finish누르면 생성이 된다.

 

그리고 안에 내용에서 @WebServlet("/*") 얘를 썼는데, import도 안되고.. 에러가 난다면 다음과 같이 해결하면 된다.

 

해결 방법 !

1. Project -> Properties -> Java Build Path : Libraries 탭 
2. 우측에 나오는 Add Library 

3. Server Runtime 선택 후 Next

4. 설치된 Server 선택 (본인은 Tomcat v9.0) 후 Finish

 

 

 

 

 

맨날, 개발만 할 줄 알지 .. 이렇게 자세하게 볼 시간은 없었다. 사실 입사하고나서 자바스프링프레임워크는 처음 접했기 때문에, 일단 개발하는데 급선무였다.. 근데.. 돌이켜보니 아무것도 모르고 복사/붙여넣기 수준의 개발은 전혀 실력향상에 도움이 되질 않는다고 생각한다. 지나고나니 그렇다. 그렇게 느낀다. 그렇기에 지금이라도 기초부터 차근차근 해야겠다..

퇴사각

 

 

 

 

도움 되셨으면 아래 공감 꾹!(로그인 필요 없어요! :>)

반응형
반응형

저번엔 pom.xml을 봤는데.. 이번엔 web.xml이다. context.xml도 알아보겠다.

 

가장 먼저 web.xml이란 Deployment Descriptor(배포 서술자)로 각 어플리케이션의 환경을 설정하는 부분을 담당한다.

 

뭐 간단하게.. 설명하면 설정을 위한 설정파일이라는거?

최초로 WAS(Tomcat)이 구동될 때, 각종 설정을 정의해주는 것이다.


WAR 파일이 패키지 될 때 같이 포함되며(pom에서 packing 설정 가능했었음) root directory 밑에 /WEB-INF 디렉토리에 위치한다. 일단 .. 하나의 프로젝트에는 무조건! 하나의 web.xml이 있어야 한다. 아래와 같이 존재한다.

 

web.xml 위치

 

졸리다.. 내일써야겠다.

자고왔다. 다시써야겠다.

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern> <!-- 모든 요청을 DispatcherServlet이 처리한다. -->
	</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> 
	    <init-param>
	        <param-name>forceEncoding</param-name>
	        <param-value>true</param-value>
	    </init-param>
	</filter>
	<filter-mapping>
	    <filter-name>characterEncodingFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

 

뭐 본인의 web.xml은 이렇다. 차근차근 봐보자.

 

(1) <context-param>

STS에서 기본적으로 제공해주는 설정 파일외에, 사용자가가 직접 컨트롤 하는 XML파일을 지정해주는 역할을 한다.

'

(2) <listener>

스프링 설정 정보를 읽어주는 역할을 한다.

 

(3) <servlet>

전에 포스팅에서도 말했듯이, servlet-mapping을 통해 모든 요청을 받아들이고(본인은 모든 요청을 받게 설정),

servlet-class 를 사용하여 dispatcher가 모든 요청을 받아들이는 역할을 담당할 것이며, param-value를 통해 dispatcher-serlvet의 설정 값을 넣을 수 있다.(~~~식으로 진행해 라는 꼴)

 

(4) <filter>

- 한글 깨짐문제를 CharacterEncoding을 사용하여 인코딩 해준다.

<url-pattern>/*</url-pattern> -> / 이하의 모든 요청에 대해 설정 적용

 

또한 본인은 설정하지 않았지만 추가적인 태그도 있다.

 

ㅁ web.xml 제목과 설명을 넣을 수 있는 태그

- <display-name>, <description>

ㅁ 세션을 설정할 수 있는 태그

- <session-config>

ㅁ error page 설정할 수 있는 태그(오류가 발생한다면 error 페이지를 보이게 할 수 있음)

- <error-page>

ㅁ 첫화면 설정, 시작페이지 설정(주의할 점은 컨트롤러에 /가 있더라도 welcom-file-list가 우선순위다)

- <welcome-file-list>

 

 

그 다음 root-context.xml이다.

root-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:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/beans https://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
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	<util:properties id="properties" location="classpath:properties-local/config.local.properties"/>
	
	<!-- Root Context: defines shared resources visible to all other web components -->

	<!-- 오라클 접속 -->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
        <property name="url" value="jdbc:log4jdbc:oracle:thin:@localhost:1521/xe"/>
        <property name="username" value="**"/>
        <property name="password" value="**"/>
    </bean>
   
    <!-- Mybatis 연동 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         <property name="dataSource" ref="dataSource"></property>
         <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
         <property name="mapperLocations" value="classpath*:mappers/**/**/*sql.xml"/>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
    </bean>
</beans>

 

뭐 이런식으로 되어있다. 보면 오라클을 접속하고, Mybats 연동하고.. 뭐이런코드가 들어있지않은가?

그래서 비즈니스 로직을 위한 xml파일이라고 생각하면 편하다.

 

즉, 데이터베이스를 처리하고 db에 관한 bean들에 대한 주 설정이 이루어진다고 생각하면 된다.

 

 

 

오늘까지 해서 xml 정리는 끝난것 같다.

다음엔 뭐하지.. 뭐 하려고 했는데 기억이 안난다.

반응형
반응형

이거에 대해 포스팅하게 된 계기는 아니 자바스프링에 xml이 적당히 많아야지.

 

가장먼저 pom.xml에 대해서 살펴보겠다.

 

pom.xml 의 용도

-> 간단히 말해서, 자바 스프링의 빌드/배포, maven, 자바, 스프링 버전 등 프로젝트의 중요한 정보

를 담고있는 장소라고 생각하면 된다.

Maven이란 자바 스프링을 빌드를 자동화 해주는 도구 라고 생각하면 편할 것이다.

POM은 "Project Object Model"의 약자이다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.kitao</groupId>
	<artifactId>kr</artifactId>
	<name>kitao</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>4.3.8.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<!-- 오라클 -->
	<repositories>
		<repository>
			<id>oracle</id>
			<url>http://maven.jahia.org/maven2</url>
		</repository>
	</repositories>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>$</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>$</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>$</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>$</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>$</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>$</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>

   

오우.. 너무 길다... 일단 maven에 대해서 알고가야할 것 같다.

 

태그를 하나하나 살펴보기로 하자.

1) <project>

그냥뭐 프로젝트를 설정해주는 태그라고 생각하면된다. 본인은 kitao라는 프로젝트를 생성하고 자바스프링을 하고 있는데 그 kitao에 대한 프로젝트를 설정하는 태그 정도로 보면된다.

 

2) <modelversion>

그냥 pom`s version 이라고 생각하면 된다. 4.0.0 버전인 것이다.

 

3) <groupId>

처음에 프로젝트 생성할 때, 식별할 수 있는 회사명이나 그런걸 넣었을 것이다. 그런것을 선언해주는 곳

 

4) <artifactId>

프로젝트에 할당된 고유 ID

 

-> 본인은 com.kitao.kr 이런식으로 생성했을 거임. 그래서 groupId : com.kitao, artifactId : kr 이런식..

 

5) <version>

프로그램 버전이다. 본인 프로그램 버전이라고 생각하면 편함.

 

6) <packing>

패키징 유형(jar, war, zip 등)

 

7) <properties>

pom.xml에서 중복해서 사용되는 설정(상수) 값들을 지정해놓은 부분.

다른 위치에서 ${...}로 표기해서 사용할 수 있다.

    • ex) java.version에 1.8을 적용하고 다른 위치에서 $이라고 쓰면 "1.8"이라고 쓴 것과 같다

8) <profiles>

dev, prod 이런식으로 개발할 때, 릴리즈할 때를 나눠야 할 필요가 있는 설정 값을 profiles로 설정할 수 있음

 

 

그렇기에 maven만 잘 관리해서 pom에 넣고 있다면, jar를 관리하지 않아도. 문제가 생겨도.. 다시 지우고 받고 뭐 이런식으로 할 수 있다는 얘기가 된다!

즉, 빌드/배포와 관련된 모든 설정을 담고 있고 maven 이라는 유틸리티에서 메타 정보로 사용하는 설정파일 인셈!

 

 

도움 되셨으면 밑에 공감 꾹!(로그인 필요없어요.)

반응형
반응형

Dispatcher-servlet 이란 무엇인가?

진짜 간단하게 이야기 하면, "모든 요청을 거치는 가장 앞단에서의 문지기 역할을 하고 마지막을 책임지는 역할"

이라고 할 수 있다. 이게 무슨 의미냐하면... 그림을 보면서 하는게 나아보인다.

여기서 1번을 보면 URL로 접근하여 정보를 요청은 전 포스팅에서 설명한. url-pattern으로 설정을 해준 것이다.

 

DispatcherServlet과 MVC2 Model

 

여기서 1번부터 10번까지 쉬운말(?)로 설명 해보겠다.

 

가정) 어떠한 사용자가 구글에 접속한다고 가정해보자.(https://www.google.com)

1. 가장 먼저 해당 URL을 Front Controller(DispatcherServlet)이 받아준다.

2. Front Controller : 아니.. 이거 Database도 접근해야할 것 같고.. 나 혼자만으로 힘든거같은데 비즈니스 로직 담당! 컨트롤러가 해줘야할 것 같다. 내가 HandlerMapping 통해서 Controller로 던질께!

3. Controller : 이거 뭐.. 나혼자로 힘든데.. 이거 .. Database접근하기위해서 선언된 Service쪽 접근해야할듯.. DB조회는 너가 좀 부탁해!!

4. Service : 야.. 나도 Database 그냥 가지고만있지 실제 코드는 나한테 없거든? 다시 DAO로 던질께! 

5. DAO : 나도 코드 나한테 없어 ... 마지막단계인 Mysql(.xml 확장자)가 가지고 있단말이야.. 넘겨야해

6. Mysql : 후후 드뎌 나한테 왔네 내가 쿼리문 실행해서 결과값좀 리턴해줄께!!!! 기다려봐!

7-1. Mysql(여기 쿼리 받아)

7-2. DAO(고마워)

7-3. Service(고맙다? 컨트롤러야 여기 최종본이야)

7-4. Controller(와 고맙다 이제 Front Controller에게 전송만하면되 그러면 알아서 다해줄꺼야!!!! 받아라)

7-5. Front Controller(오 고마웡 ㅎ 이제 알아서 할께~)

8. Front Controller : 이제 받은 내용을 가지고 JSP쪽에 뭐가 있나 View Resource쪽에 탐색해볼까?? 있니?

9. View Resolver : 응 있어! View야 너가 좀 리턴해주라

10.1 : View : 응 알았어 : 여깄다 FrontController야 ! JSP이다~

10.2 : Front Controller : 휴.. 힘들었다. 고객님 여기있습니다~~~ 즐건 서비스되세용!

 

뭐 이런 과정을 거친다... 최대한 쉽게하려고 했는데 이해가 됐는진 모르겠다.

 

Dispatcher-servlet(Front Controller)의 등장으로 Web.xml의 역할을 확! 줄여주었다고 생각하면 된다.

 

반응형
반응형

자 Server를 Tomcat이라고 가정하고, Tomcat이 구동되면 web.xml이라는 것을 실행시킨다.

여기서 우리가 중요하게 Tomcat이 어떻게 구동이 되고, web.xml은 뭔가.. 살펴볼 것이다.

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern> <!-- 모든 요청을 DispatcherServlet이 처리한다. -->
	</servlet-mapping>

</web-app>

 

이 코드는 web.xml 에 있는 한 내용이다. 간단하게 설명을 하면 다음과 같다.

 

1. servlet-mapping에 url-pattern : 모든 요청을 처리하겠다!

2. servlet에서의 servlet-class : url 요청은 dispatcherservlet이 처리를 해줄께!

3. servlet에서의 init-param의 param-value : 처리 방법은 servlet-context.xml에 써놨으니 거기서 확인해봐!

-> 즉, 모든 URL 요청을 dispatcherservlet이 담당하며, 처리방법은 servlet-context.xml에 기술해놨으니 확인해!

라는 꼴이 된것이다.

 

 

 

이제 servlet-context.xml을 한번 확인해 보자.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.kitao.kr" />
	
	
	
</beans:beans>

 뭐 이런식으로 되어있다.

 

저기서 주목할 건 <resources mapping ~~ 부분인데, 저게 뭘의미하냐면 만약 resources 폴더 아래 부분에

사진파일(*jpg 등) 이나 *.css, *.js 등등 URL로 접근이 가능한 정적파일 등에 접근할 때에는 DispatcherServlet을 거쳐서 Controller에 갔다가 다시 JSP에 가는게 아니라, 바로 저쪽으로 접근하겠다. 는 것입니다. 

 

DIspatcher-servlet이 정적소스인지, 동적소스인지 판단하에 나눠준다고 생각하면 된다.

 

또한 prefix와 suffix는 Controller의 처리 방식에 대해 나와있는데. 추후에 살펴보겠지만 Controller의 마지막 부분에서 리턴할 때에, return "/WEB-INF/views/co.jsp" 의 형태로 하지는 않는다.

 

컨트롤러에서 항상 리턴한다면 얼마나 불편하겠는가.. 그래서! prefix(접두사), suffix(접미사)를 넣어주어 다 생략하고

return "co" 의 형태가 되도록 한다는 것이다.

 

 

 

 

 

반응형

'Java Spring' 카테고리의 다른 글

[Java Spring] pom.xml  (0) 2021.04.04
[Java Spring] dispatcher-servlet과 MVC2 Model  (0) 2021.04.04
[Java Spring] 의존성 주입(DI, Dependency Inject)  (0) 2021.03.28
[Java Spring] Annotation(2)  (0) 2021.03.28
[Java Spring] Annotation(1)  (0) 2021.03.25
반응형

의존성 주입(DI, Dependency Injection)

 

저번에 Service Annotation에서 봤던 것 처럼 new라는 Keyword를 통해서 객체를 생성하는 것이아니라,

@Qualifire, @Resource, @Inject Annotation으로 의존성을 주입하는 것을 의미한다.

여기서 왜 의존성 주입인지 살펴보기로 한다.

 

기존에 Java에서는 class를 구현하고 실제로 객체를 생성할 때, new라는 키워드로 해주었다. 이게 정상적인 의존성 방향이라고 생각하면 된다. 하지만, 해당 Annotation들은, 정상적인 의존성 방향을 깨는 흐름이라고 보면된다.

즉, IoC(Inversion of Control, 의존성 역전) 원칙을 하에 객체 간의 결합을 약하게 해주고 유지보수가 좋은 코드를 만들어 준다.


가장먼저, new 객체로 생성하는 형태를 보자.

Gun.java

public class Gun {
	....
}

people1.java

public class people1 {
    private Gun gun;

    public people1() {
        gun = new Gun();
    }
}

이런식으로 new객체를 통해서 생성하는 형태는, people1 클래스 내부에서 Gun 객체를 생성하였기 때문에 의존성을 주입받은것이 아닌, 의존성을 스스로 만든 것이라고 볼 수 있다. 이게 올바른 흐름이다.(정상적인 흐름)

 

하지만, 제어의 역전 법칙(Inversion of Control)에 의해 이런식으로 바꿀 수 있다.

Gun.java

@Repository
public class Gun {
	....
}

people1.java

public class people1 {
    @Autowired
    private Gun gun;
}

 

제어의 역전(IOC : Inversion of Control)

IOC는 제어 흐름의 개념을 거꾸로 뒤집는 개념이다.

  • Object는 자신이 사용할 오브젝트를 스스로 생성하거나 선택하지 않는다.
  • 모든 제어의 권한을 자신이 아닌 다른 대상에게 위임한다.(Spring이 해준다.)

즉, 이의 장점은 Spring인 내가 제어해주고 클리스 만들고 다 해줄테니, 너는 비즈니스 로직에만 신경써~ 라는 꼴이된것이다.

아니 프로그래머인 내가 new로 생성해야하는데, 뭔 스프링이 대신 의존성을 주입해주고 있네? 뭐 이런 개념이다.

또한, 유지보수가 쉽다는 장점도 있을 것이다. 코드간 결합성도 낮아지게 될 것이다.

 

가장 큰 특징이다. 꼭 알아두자.

아놔 어렵네

반응형
반응형

오늘은 어노테이션 

@Inject @AutoWired @Resource @Repository @Service Annotation에 대해서 알아보겠다.

 

1. @Service

다음에 얘기하긴 하겠지만 간단하게 Spring MVC 구조는

Controller - Service - Impl - DAO - Mybatis - SQL 이런식으로 흘러간다.

여기서 Service에 해당하는 녀석이라고 보면된다.

 

실제로 Service단에서는 선언만 이루어지고

Impl단에서 implements를 통해 구현이 이루어지기 때문에 Impl 단에서 @Service를 사용한다.

다음과 같다.

package com.kitao.kr.co.coe.service;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import com.kitao.kr.co.coe.dao.COEBoardDAO;
import com.kitao.kr.co.coe.vo.BoardVO;

@Service("boardService")
public class BoardServiceImpl implements BoardService {
	@Inject
	private COEBoardDAO boardDAO;
	
	@Override
	public List<BoardVO> selectBoardList() throws Exception {
		return boardDAO.boardSearch();
	} 
}

위 처럼 구조는 저렇게 보면 되고, 

실제로 구현한곳에서 @Service("boardService") 라고 선언해주는데 이건 boardService 서비스를

의미하며, 실제로 파일명과 따옴표 안에 값은 일치하게 된다.

여기서는안나와 있지만 BoardService 파일 안에 들어가보면 class는 BoardService로 선언이 되어있다. 또한 따옴표 안에 값은 boardService인데 여기서 규칙은 첫번째 글자는 소문자 라고 보면 된다.

이런식으로 구현하면 된다.

참고로, Controller에서 Service, impl 단으로 넘어가서 Mybatis까지 사용하게 되면 Impl단에서도 코딩이 된걸 볼 수 있는데 보통 데이터를 oracle로만 제어하기 힘들때, 자바단에서도 작업이 이루어지기도 한다. 추후에 볼 내용이다.

 

2. @Autowired 

Autowired Annotation이다.

구조를 보면

이고 BoardServiceImpl의 구현은 다음과 같다.

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kitao.kr.co.coe.dao.COEBoardDAO;
import com.kitao.kr.co.coe.vo.BoardVO;

@Service("boardService")
public class BoardServiceImpl implements BoardService {
	@Autowired
	private COEBoardDAO boardDAO;
	
	@Override
	public List<BoardVO> selectBoardList() throws Exception {
		return boardDAO.boardSearch();
	} 
}

 

혹시 대충 감이 오나..요?

COEBoardDAO라는 class가 선언 되어 있을 것입니다. 여기서 COEBoardBAO가 있는 클래스를 한번 보겠습니다.

package com.kitao.kr.co.coe.dao;

import java.util.List;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class COEBoardDAO {
	@Inject 
	private SqlSession session; 
	private static String namespace = "com.kitao.kr.boardListSearch";

	public List<BoardVO> boardSearch() throws Exception {
		return session.selectList(namespace+".selectBoardSearch");
	}
}

 

이런식으로 되어있습니다. Autowired란 선언되어 있는 class를 new 객체로 생성하는게아니라 의존성 주입이라는 녀석으로 객체를 생성하는 역할을 함.

@Repository가 없다면 작동이 안한다. @Auutowired는 의존 객체의 타입에 해당하는 bean을 찾아 주입하기 때문이다. bean으로 등록되어 있지 않으면 스프링은 bean을 찾지못해 의존성 주입이 불가능하다.

그렇기 때문에.. @Autowired를 사용할 때에 클래스위에 @Repository라는 어노테이션을 붙여야 자바스프링에서는 자동으로 매칭이 될 수 있다는 걸 알고 있으면 된다.

 

근데 @Autowired를 사용할 수 있는 방법은 총 3가지이다.

1. 이미 했던 것 처럼 선언과 동시에 넣어버리는 것이다.

	@Autowired
	private COEBoardDAO boardDAO;

2. set함수에 넣어주는 것이다.

	private COEBoardDAO boardDAO;
	
	@Autowired
	public void setCOEBoardDAO(COEBoardDAO boardDAO) {
		this.boardDAO = boardDAO;
	}

3. 생성자에 넣어주는 것이다.

@Service("boardService")
public class BoardServiceImpl implements BoardService {
	private COEBoardDAO boardDAO;
	
	@Autowired
	public BoardServiceImpl(COEBoardDAO boardDAO) {
		this.boardDAO = boardDAO;
	}
	
	@Override
	public List<BoardVO> selectBoardList() throws Exception {
		return boardDAO.boardSearch();
	} 
}

 

이렇게 3가지 방법이 있다.

본인이 원하는 방법을 찾아서 사용하면된다.

또한 @Autowired Annotation은 찾는 순서가 다음과 같다.

타입 -> 이름 -> @Qualifier -> 실패

여기서 @Qualifier를 간단하게 설명하면, 다음과 같다.

 

테스트를 위해 Test class생성 후. testimplements1, testimlements2에서 구현하게 했다.

코드는 다음과 같다.

test.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;

import com.kitao.kr.co.coe.vo.BoardVO;

public interface test {
	void a() throws Exception;
}

testimlements1.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class testimplements1 implements test {
	@Override
	public void a() {
		System.out.println("testimplements1");
	}
}

testimlements2.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class testimplements2 implements test {
	@Override
	public void a() {
		System.out.println("testimplements2");
	}
}

 

이 상태에서 @Autowired를 사용하여 의존성 주입을 하게 된다면.... 에러를 뱉어낸다.

따라서 특정 class를 선언해주어야한다. 소스는 다음과 같다.

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import com.kitao.kr.co.coe.dao.COEBoardDAO;
import com.kitao.kr.co.coe.vo.BoardVO;

@Service("boardService")
public class BoardServiceImpl implements BoardService {
    @Autowired    
	private COEBoardDAO boardDAO;
    
    @Autowired
    @Qualifier("testimplements2")
    private test test;

	@Override
	public List<BoardVO> selectBoardList() throws Exception {
	    test.a();
	    
		return boardDAO.boardSearch();
	} 
}

저기 위에 보면 @Qualifier("testimlements2") 가 보인다.

이는 @Qualifier("클래스명") 인 구조이다. 따라서, testimlements2의 class를 주입하게 되는

것이다.

 

또한, @Primary 어노테이션은 있는데, 이는 2개 이상의 implements가 있으면, 지정해주는 것

가수 프라이머리

2개이상의 구현이 있을때, 내가 원하는 class위에만 지정해주면 된다.

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
@Primary
public class testimplements1 implements test {
	@Override
	public void a() {
		System.out.println("testimplements1");
	}
}

이런식으로 @Repository아래에 @Primary만 사용해주면 된다.

 

3. @Inject

@Autowired와 똑같다. 다른점이 거~의 없다 사용 방법도  동일하고..

필드, 생성자, setter에서 사용하는 것도 동일하고 Bean검색 우선순위도

타임 -> 이름 -> Qualifier(Inject는 Named으로 변경된다 이게 다른점) -> 실패 순이다.

@Named("클래스명");

또 다른 다른점이 있긴한데, 조금 뒤에 살펴보겠다.

 

4. Resource

이것도 사용 방법은 비슷하다. 하지만 사용 가능 위치는 필드, 파라미터가 한 개인 setter이다.

또한, Bean 검색 우선 순위는 @Inject와 @Qualifier 와 다르게 이름 -> 타입 -> name -> 실패

이 형태로 간다.

 

예제는 다음과 같다.

@Service("boardService")
public class BoardServiceImpl implements BoardService {
    @Autowired    
	private COEBoardDAO boardDAO;
    
    @Resource(name="testimplements2")
    private test test;

	@Override
	public List<BoardVO> selectBoardList() throws Exception {
	    test.a();
	    
		return boardDAO.boardSearch();
	} 
}

test.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;

import com.kitao.kr.co.coe.vo.BoardVO;

public interface test {
	void a() throws Exception;
}

testimlements1.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class testimplements1 implements test {
	@Override
	public void a() {
		System.out.println("testimplements1");
	}
}

testimlements2.java

package com.kitao.kr.co.coe.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.kitao.kr.co.coe.vo.BoardVO;

@Repository
public class testimplements2 implements test {
	@Override
	public void a() {
		System.out.println("testimplements2");
	}
}

이렇게 되면 testimplements2가 실행된다.

참참고로, @Resource 단독으로 사용할 수 있으며, @Primary도 동일하게 사용가능하다.

 

자 이제 정리는 끝났고, 마지막 표를 보면서 익혀보자!

  @Resource @Inject @Autowired
의존 JSR (자바 표준 어노테이션) JSR (자바 표준 어노테이션) Java Spring에서 지원
검색 방식 이름 -> 타입 타입 -> 이름 타입 -> 이름
강제 연결(구현 2개 이상) @Resource(name="클래스명") @Named("클래스명") @Qualifier("클래스명")
사용 위치 멤버변수, setter 메소드, 일반 메소드 필드, setter 메소드, 생성자, 일반메소드 필드, setter 메소드, 생성자, 일반메소드

 

오늘은 여기까지하고.. 좀 어려운 내용일수도 있다.

하지만 그렇게 어렵다고는 생각안한다.

다음엔 의존성 주입이 정확히 뭔지 포스팅하는 시간을 가지도록 해야겠다.

 

 

아디오스~

반응형

+ Recent posts