2018-12-07 수업 내용 정리

UML

  • 클래스와 클래스 사이의 관계

상속

상속 받은 B는 상속한 A를 확장한다.

의존 관계

특정 메서드에서만 일시적으로 사용되는 관계

img

연관 관계, 직접 연관

나는 친구와 연관되어 있다.

집합 연관

컴퓨터는 마우스를 포함한다.

합성 연관

컴퓨터는 메인보드를 포함한다. (집합 연관보다 더 강하게 종속)

컴퓨터가 버려지면 메인보드도 같이 버려진다.

img

Mybatis의 ResultMap 다루기 - 포함 관계에 있는 객체를 vo에서 함께 이용하는 방법

1
2
3
4
5
// vo에 포함 관계에 있는 객체 자료형의 필드를 만든다

private 객체 필드명

// 마찬가지로 getter, setter 메서드를 만들어준다
1
2
3
4
5
6
7
8
9
<!--xml resultMap을 만들 때, 만약에 있다면 실행하라는 뜻-->

<association property="vo에 만들어둔 프로퍼티명" javaType="클래스 경로">
<id column="쿼리문의 칼럼명" property="vo에 만들어둔 프로퍼티 vo의 프로퍼티명"/>
<!-- 항상 pk를 포함해야 한다, 만약 pk를 쓰지 않는다고 하더라도!
pk는 resultMap에서 쓰듯 id로 써야 한다.
또한 pk 지정은 association 안 뿐만 아니라 resultMap 안에서 지정할 때도 써야 한다 -->
<result colum="쿼리문의 칼럼명" property="vo에 만들어둔 프로퍼티 vo의 프로퍼티명"/>
</association>
1
2
<!-- jsp -->
${board.vo자료형의 프로퍼티명.칼럼명}

mybatis에 구현체 자동 생성하기

AppConfig.java (xml에서 설정할 것들을 대체해 설정했던 class) @MapperScan 어노테이션을 설정해두기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@PropertySource("classpath:/com/....properties")
// mybatis의 dao 인터페이스 구현체를 자동 생성하는 도우미를 추가

@MapperScan("dao 인터페이스가 들어있는 패키지 경로")

// 자동 생성된 dao 구현체는 sql를 찾을 때 인터페이스의 전체 이름으로 찾는다
// 즉 dao 인터페이스가 들어있는 패키지 경로/dao명
// 따라서 sql 매퍼 파일의 네임스페이스 이름은 인터페이스의 전체 이름과 같아야 한다.

// 인터페이스의 메서드 파라미터, 리턴 타입은 sql 매퍼의 파라미터 타입과 리턴 타입이 같아야 한다.
// 인터페이스의 메서드 이름과 매퍼 id는 같아야 한다.
public class AppConfig {
..
}

dispatcherServlet

  • 프론트 컨트롤러

  • 요청을 받으면 jsp 인크루드, 포워딩을 맡거나 페이지 컨트롤러로 요청을 보낸다. 응답이 돌아오면 응답을 전달함

  • 페이지 컨트롤러 : 특정 페이지에 대해서만 제어하는 것
  • 디스패처와 jsp는 톰캣이 관리한다
  • 그러나 페이지 컨트롤러와 dao는 ioc Container 관리

dispatcherServlet 직접 만들기

dispatcherServlet

  • webServlet("/app/*") 어노테이션 살려두고

  • 클라이언트가 요청한 명령 추출

    request.getServletPath() 메서드를 호출하면 /app이 오고,

    request.getPathInfo()메서드를 호출하면 /app다음의/**이 오므로 getPathInfo()를 이용한다.

  • ioc Container를 얻어 iocContainer.getBean(request.getPathInfo()) 실행

  • 즉 ico Container에서 요청을 처리할 객체를 getPathInfo()를 이용해 찾으면 해당 페이지를 담당하는 컨트롤러 객체가 넘어온다.

    이 때 호출의 일관성을 위해 페이지 컨트롤러들의 인터페이스를 정의하고, 개별적인 페이지 컨트롤러가 이를 상속 받도록 조치한다.

    iocContainer.getBean(request.getPathInfo())에서 돌아오는 리턴 값도 페이지 컨트롤러들의 인터페이스로 한다.

    인터페이스에 공통으로 정의할 메서드, 예제에서는 execute()메서드였는데 이 메서드는 파라미터로 httpServletRequesthttpServletResponse를 가지게끔 한다.

    String execute(httpServeltRequest request, HttpServletResponse response)

page Controller

  • @Component("경로") 어노테이션을 기입해준다.

  • 생성자에서 사용할 객체를 주입 받는 식으로 전역 변수를 선언한다. 보통 이 전역 변수는 dao가 많다.

    (생성자에서 파라미터로 받는 객체는 마찬가지로 스프링 ioc container에 있으므로 따로 지정하지 않아도 자동으로 들어간다)

  • dao의 메서드를 호출해 db 도달 처리를 하고, db에서 받은 것들을 set한 후, utf-8로 맞추는 등의 설정을 한다.

  • 도달해야하는 jsp 경로를 리턴한다.

  • 만약 리턴하지 않으면 요청했던 url로 넘어간다.

    return "redirect:경로"or return "경로"

다시 dispatcherServlet

  • 페이지 컨트롤러의 메서드, 예제의 execute()메서드를 호출한다.
  • 리턴받은 url을 include하던가 forward한다.
  • 페이지 컨트롤러가 redirect로 보냈을 가능성을 대비해 dispatcher 단에서는 startWith()를 이용해서 어떤 url인지 확인하고, redirect로 왔다면 replace() 메서드를 이용해 redirect 제거 후 response.sendRedirect("경로")로 보낸다. 만약 redirect가 아니라면 include하던가 forward한다.

Spring WebMVC 프레임워크 도입

  • spring-webmvc 의존 설정

  • springframework 의존 설정을 지워도 된다. 어차피 spring-webmvc의 의존 라이브러리이기 때문에 spring-webmvc를 가져올 때 같이 가져오기 때문

  • 웹 어플리케이션이 시작될 때 SpringContextContainerInitializer를 부르고, 이것이 WebApplicationInitializer 구현체를 부른다.

  • WebApplicationInitializer 구현체는 웹 어플리케이션이 시작될 때 호출되어 시작된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public void onStartup(ServletContext servletContext) throws ServletException {
    // 만약 web.xml에서 java 파일로 설정한 것들이 기재되어 있다면 java 파일은 실행되지 않는다.
    // 만약 스프링 설정 파일을 java 파일로도 한다면,
    // @Configuration이란 어노테이션을 붙여줘야 IOC Container가 인지한다.
    // 또한 어노테이션을 읽기 위해서는 xml에서 태그를 붙여줘야 한다.

    // 프론트 컨트롤러가 사용할 Spring IOC Container 준비
    AnnotationConfigWebApplicationContext ac
    = new AnnotationConfigWebApplicationContext();
    ac.register(AppConfig.class);
    ac.refresh();

    // 프론트 컨트롤러를 서블릿 컨테이너에 등록한다.
    // 프론트 컨트롤러를 생성할 때 이 객체가 사용할 Spring IOC Container를 알려준다
    DispatcherServlet servlet = new DispatcherServlet();

    // 서블릿 컨테이너에 위에서 만든 프론트 컨트롤러 서블릿을 등록한다.
    ServletRegistration.Dynamic registration
    = servlet.addServlet("app", servlet);

    // 등록한 서블릿에 정보를 설정한다.
    // 웹 어플리케이션이 시작될 때 프론트 컨트롤러를 생성하라고 지정한다
    // 프론트 컨트롤러의 url을 지정한다
    registration.setLoadOnStartup(1);
    registration.addMapping("/app/*");
    }

    상속해 반드시 구현해야하는 이 메서드가 실행된다.

  • 기존의 dispatcherServlet을 제거하고 Spring IOC Container에서 제공하는 dispatcherServlet을 사용할 것

  • 기존의 contextloaderlistener들도 제거

    어차피 Spring IOC Container에서 다루기 때문

  • 페이지 컨트롤러들의 인터페이스를 삭제한다. 디스패처가 페이지 컨트롤러를 실행할 때는 다른 규칙에 따라 실행하기 때문. 기존에 사용자가 만든 규칙은 필요치 않다.

  • 페이지 컨트롤러의 어노테이션 @Component("경로")@Controller로 바꾼다.

  • 페이지 컨트롤러의 메서드에 @RequestMapping("경로") 어노테이션을 붙여준다.

    컴포턴트 옆의 경로를 붙여준다. 메서드 이름 또한 사용자가 정의 가능

CharacterEncodingFilter 사용

  • WEB-INF/web.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/app-servlet.xml</param-value>
    </init-param>
    -->
    <load-on-startup>1</load-on-startup>
    </servlet>

    <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>
    <!-- 기재하게되면 더이상 java 단에서 encoding을 지정하지 않아도 된다 -->

    <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/app/*</url-pattern>
    </filter-mapping>

    app-servlet.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.eomcs.lms"/>

    <!-- Spring WebMVC 관련 애노테이션을 처리해주는 도우미 객체를
    추가한다. -->
    <mvc:annotation-driven enable-matrix-variables="true"/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    </bean>
    </beans>
  • 원래 어노테이션을 이용한 필터도 사용 가능한데, 구현해야하는 메서드가 많아서 .xml로 처리

  • dispatcherServlet만 초기화하는 추상 클래스 AbstractDispatcherServletInitializer를 상속 받아 추상 메서드 `getServletFilter()를 재정의

    1
    2
    3
    4
    5
    @Override
    protected Filter[] getServletFilters() {
    return new Filter[] {new CharacherEncodingFilter("utf-8");}
    }
    // 왜인지 에러나고 잘 안되어서 수업 중 실행 여부 확인 못함

JSP 파일 감추기

  • 클라이언트로부터 jsp 파일을 감춘다

  • 외부에서 jsp를 직접 접근하지 못하게 WEB-INF/jsp폴더로 옮긴다.

    appConfig.java에서 Spring WebMVC에 기본으로 설정되어 있는 ViewResolverInternalResourceViewResolver로 교체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Bean
public ViewResolver viewResolver() {
// viewResolver 인터페이스의 구현체 객체 생성 메서드

InternalResourceViewResolver vs
= new InternalResourceViewResolver();
vs.setPrefix("/WEB-INF/jsp/");
// 리턴되는 url에 앞에 자동으로 이것을 붙인다.
vs.setSuffix(".jsp");
// 뒤에 이것을 붙여라
vs.setViewClass(JstlView.class);
// viewClass는 jstlview이다.
return vs;
}
  • 페이지 컨트롤러의 return 값을 바꾼다.

스프링 자동화

  • request, responese를 굳이 파라미터로 가져오지 않고, 원하는 값은 파라미터로 가져와 처리한다.
  • httpSession도 가져올 수 있다.
  • request.set으로 객체를 담지 않고, Model에 담는다.

다시 공부해야 할 것 같아…