2018년 4월 17일 화요일

패스트 캠퍼스 JAVA 웹 프로그래밍 마스터 18일차(Docker, ViewResolver, profile, CTIP, ThreadLocal)

  • 운영
    • 로컬서버
      • 개발자 컴퓨터 - 로컬 DB
    • 개발서버
      • 개발 서버 - 개발 DB
    • 운영서버
      • 운영 서버 - 운영 DB
    • maven profile, spring profile
  • profile 설정
    • Spring, Maven, Gradle 
    • 차이점은??
  • CTIP
    • 지속적인 통합, 지속적인 TEST, 지속적인 Build
    • jenkins를 통해 GitHub에서 소스의 변경여부를 파악하고 테스트,빌드, report생성, error를 파악하고 사용자에게 mail, slack을 통해 통보할수 있으며 개발서버에 결과물(war, jar)파일을 deploy(배치)하며 서버를 재시작을 자동으로 해준다.
  • Docker
    • 개발환경 운영환경 같은 방법으로 관리할 수 있다.
    • 운영체제의 자원을 사용한다.
    • 설정파일만 있으면 어디서든 똑같은 환경으로 구성할 수 있다.
    • 설치 (Docker compose도 포함되어 있다.)
    • docker ps (목록)
    • https://store.docker.com/editions/community/docker-ce-desktop-mac
  • Reference architecture
    • 로드밸런싱
    • 이중화, 확장유연
    • 대용량 서비스면 관계맺어야 할 테이블이 DB가 서로 다른곳에 있을 수 있다. 개발자가 버그에 대해 생각하고 롤백처리 해야한다.
    • 분산 트랜잭션, 2단계 커밋등으로 처리할 수 있다.(서버를 사야한다. 비싸다.)
    • DB와 많은 Connection을 맺고 있으면 문제가 생길수 있다. 그래서 이중화 NUIX(웹서버) ,WAS(REST API SERVER)를 DB와 연결하고 REST API 서버와 통신하게 만든 후  REST API SERVER와 통신을 통해 DB정보를 얻어온다.
  • Connection pool
    • DB와 연결을 미리 연결을 한 상태를 말한다. Datasource를 통해 연결한다.
  • 샤딩(Sharding) 전략
    • 나누기 전략 : DB가 늘어나면 마이그레이션 해야한다.
    • 하나의 DB에서 특정한 카페의 데이터가 많을시에는 다른 카페의 속도가 느려질수 있으니 특정 카페만의 DB를 따로 구성하여 마이그레이션한다.
  • Srping Boot 2.0
  • redis
  • rabbitmq
  • JPA
  • 언어 설정
    • Locale
    • I18N
    • 지역화
    • 하드코딩으로 적지말고 properties를 통해 사용해야 한다. 
  • ThreadLocal
    • static한 객체 한테 thread별로 같은 쓰레드 안에서는 값을 유지해 준다.
    • 파라미터로 넘기지않아도 값을 꺼낼 수 있다. 같은 쓰레드라면
    • static이 아니면 매번 필드가 메모리에 만들어 진다.
    • ThreadLocal을 사용하려면 static으로 사용한다.
  • DispatcherServlet 내부 동작흐름 상세 -요청 선처리 작업
    • 요청 -> Locale 결정(언어설정) -> RequestContextHolder에 요청 저장(ThreadLocal로 구성되어있음) -> FlashMap복원(Redirect) -> 멀티파트 요청(파일관련) -> 아니요 : 핸들러 결과와 실행 / 예 : MultipartResolver가 멀티파트 결졍 -> 핸들러 결과와 실행 
    • RequestContextHolder에는 HttpServletRequest등을 포함하고 있다.
    • MultipartResolver가 작동할 떄 확장된 HttpServletRequest를 사용한다. 기존 HttpServletRequest 는 파일관련 작업을 지원하지 않는다.
  • Redirect FlashMap
    • FlashMap을 통해 값을 읽을 수 있다. 
    • 1번만 사용가능하다. 
    • 새로고침하면 사라진다.
  • ViewResolver
    • View객체에서 제일 중요한것은 render 메소드다.
    • ViewResolver객체에서 제일 중요 한 것은 resolveViewName 메소드다.
    • InternalResourceViewResolver는 내부적으로 JstlView 를 사용하고 forward 해준다.
    • 사용자가 요청한 타입에 따라서 다른 결과를 보여주고 싶을때는 ContentNegotiationManager 를 사용한다.(pdf, json등)
    • @Bean
          public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager contentNegotiationManager) {
              ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
              resolver.setContentNegotiationManager(contentNegotiationManager);
      
              // Define all possible view resolvers
              List resolvers = new ArrayList();
      
              resolvers.add(new HtmlViewResolver());
              resolvers.add(new JsonViewResolver()); // http://localhost:8080/guestbooks.json
      
              resolver.setViewResolvers(resolvers);
      
              return resolver;
          }
      
          @Bean
          public ContentNegotiationManager contentNegotiationManager(){
              ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean();
              contentNegotiationManager.setFavorPathExtension(true);
              contentNegotiationManager.setIgnoreAcceptHeader(true);
              contentNegotiationManager.setUseJaf(false);
              contentNegotiationManager.setDefaultContentType(MediaType.TEXT_HTML);
              contentNegotiationManager.addMediaType("html", MediaType.TEXT_HTML);
              contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON);
              return contentNegotiationManager.getObject();
          }
      
      
      import org.springframework.web.servlet.View;
      import org.springframework.web.servlet.ViewResolver;
      
      import java.util.Locale;
      
      
      public class JsonViewResolver implements ViewResolver {
          @Override
          public View resolveViewName(String s, Locale locale) throws Exception {
              return new JsonView();
          }
      }
      
      
      import org.springframework.web.servlet.View;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.PrintWriter;
      import java.util.Map;
      
      public class JsonView implements View{
          @Override
          public String getContentType() {
              return "application/json";
          }
      
          @Override
          public void render(Map map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
              httpServletResponse.setContentType("application/json");
              PrintWriter out = httpServletResponse.getWriter();
              out.println("{\"name\":\"urstory\"}");
          }
      }
      
      
      import org.springframework.web.servlet.View;
      import org.springframework.web.servlet.ViewResolver;
      
      import java.util.Locale;
      
      
      public class HtmlViewResolver implements ViewResolver {
          @Override
          public View resolveViewName(String s, Locale locale) throws Exception {
              return new HtmlView();
          }
      }
      
      
      import org.springframework.web.servlet.View;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.PrintWriter;
      import java.util.Map;
      
      public class HtmlView implements View{
          @Override
          public String getContentType() {
              return "text/html";
          }
      
          @Override
          public void render(Map map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
              httpServletResponse.setContentType("text/html");
              PrintWriter out = httpServletResponse.getWriter();
              out.println("hello!!!");
          }
      }
      
Share:

0 개의 댓글:

댓글 쓰기