2018년 6월 12일 화요일

패스트 캠퍼스 JAVA 웹 프로그래밍 마스터 42일차(AOP, Argumentresolver)

AOP

종단관심 : 객체란 관련된 정보를 가지고 있다.
횡단관심 : 모든 메소드의 시작 전,후에 로그 처리를 하고싶다.

AOP는 종단관심만으로 처리 할 수 없는 부분을 처리해준다.
용어

  • joinPoint : 적용할 위치(횡단관심) -> 메소드 시작,끝 / Exception / 메소드를 감싸서(위빙)
  • advice : joinPoint에서 실행 할 코드
  • pointcut : 어떤 Advice를 어떤 joinPoint에 적용할지 설정
  • Aspect : joinPoint + advice + pointcut(위빙)
  • target

Argumentresolver

interceptor 다음에 실행된다.
메소드 안에 있는 파라미터의 타입을 지원해주는지 확인하여 값을 알아서 넣어주는 기능을 한다.
Handlermethodargumentresolver를 implements하면 메소드 2개를 오버라이딩 한다.
  • Handlermethodargumentresolver를 구현하는 클래스를 생성 후 설정에서 ArgumentResolvers를 추가한다.
  • supportsParameter 메소드는 지원을 하는지 안하는지 여부를 확인하는 메소드이다.
  • resolveArgument 메소드는 supportsParameter 메소드에서 return값이 true일 때만 실행되며 사용할 Argument를 셋팅하면 다른 클래스 파일에서 Argument를 사용하면 자동으로 값을 넣어준다.
  • 클래스 정보는 메모리에 1번만 올라가기 떄문에 '=='로 비교가 가능하다.
public class LoginUserInfoArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        Class clazz = methodParameter.getParameterType();
        if(clazz == LoginUserInfo.class)
            return true;
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        LoginUserInfo loginUserInfo = (LoginUserInfo)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return loginUserInfo;
    
@SpringBootApplication
public class LoginApplication{

   public static void main(String[] args) {
      SpringApplication.run(LoginApplication.class, args);
   }

   @Override
   public void addArgumentResolvers(List resolvers) {
      resolvers.add(new LoginUserInfoArgumentResolver());
   }

}
Share:

Spring Boot에서 정적, 동적 파일 실시간 반영

설정을 통해 파일에 변경이 있을때 자동 Realod 

1. POM.xml 에서 spring-boot-devtools를 추가한다.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>true</scope>
</dependency>

2. livereload enable 및 cache 옵션을 false ( application property )

Intellij 에서는 3~5번 추가로 설정

3. Action을 찾는 단축키 ctrl+shift+A로 registry를 검색 후 선택한다.

4. compiler.automake.allow.when.app.running를 선택

5. Settings -> Build -> Compiler에서 Build project automatically를 체크(파일 수정시 자동 빌드)

6, 프로젝트 재 시작

7. 파일 수정시 자동 반영 (5번 항목을 안했을 경우는 수동으로 빌드)

spring-loaded 플러그인으로 Realod(Spring boot 1.3 미만)

1. POM.xml 에서 Plugin springloaded 를 추가한다.

<plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>springloaded</artifactId>
   <version>1.2.8.RELEASE</version>
  </dependency>
 </dependencies>
</plugin>

2. 템플릿 캐시 끄기( application property )

3. Maven 패널에서 Spring-boot:run을 실행한다.(터미널 명령어는 mvn spring-boot:run)

4. 파일 적용

  • 정적 파일은 서버 재시작 없이 적용 
  • 동적 파일은 Build Project 실행후 확인

TIP

크롬 LiveReload 설치를 통해 변경이 있을때 브라우저 자동 Reload

https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei?hl=ko












Share:

2018년 6월 11일 월요일

패스트 캠퍼스 JAVA 웹 프로그래밍 마스터 41일차(APM, 운영)

CommandLineRunner

스프링이 구동되는 시점에 실행하고 싶은 코드가 있는 있으면 CommandLineRunner을 구현한다.
스프링 컨테이너에 관리하는 객체들을 관리하기 위해서 CommandLineRunner 의 run()메소드를 오버라이딩 하여 구현한다. CommandLineRunner를 구현하면 빈들이 메모리에 모두 올라간 후에 run()메소드를 호출한다. 기존 main()메소드를 사용안하는 이유는 기본 Main 메소드는 JVM이 실행하고 static하기 때문에 빈을 사용할수 없다.

APM

SCOUTER(어플리케이션 모니터링 서비스)

JAVA agent 와 HostAgent를 통해 JAVA와 OS에 대한정보를 수집한다.
오류내용와 요청횟수를 확인할 수 있다.

운영

운영을 하려면 배포도구(젠킨스등)와 운영모니터링(스카우터) 도구는 필수
무중단 시스템을 만들자






Share:

2018년 6월 9일 토요일

Spring Security 프로젝트 생성 및 로그인

1. SPRING INITIALIZR를 통해 아래와 같이 설정하고 프로젝트를 생성한다.

Maven에서 시큐리티 설정을 추가하고 싶으면 아래 goal을 추가한다.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 서버를 실행하고 브라우저에서 http://localhost:8080 으로 접속한다.

Spring Security는 Client에서 요청이오면 FilterChainProxy 라는 Bean에 의해 Security Filter를 거치게 된다.


Spring Security에 의해 로그인 페이지를 생성하지 않아도 기본적으로 제공해주는 로그인 화면이 보인다. 
로그인 정보는 어디서 확인할 수 있을까?
아이디는 user
비밀번호는 콘솔을 확인해보면 아래와 같이 비밀번호를 알려준다. 비밀번호는 서버 구동할떄마다 변경된다.












Share:

2018년 6월 8일 금요일

패스트 캠퍼스 JAVA 웹 프로그래밍 마스터 40일차(기타)

다 잘할수는 없지만 1가지라도 잘하자

사용자가 많아질 경우 WAS가 추가 될수 있는데 nginx 웹서버를 이용하면 구성하기 쉽다.

언어의 철학에 대해 이해하자. 어떤 이유에 대해 만들어 졌는지

개발자는 요구사항을 개발한다.
  • 개발전에 Architecture를 구현한다.
  • Architecture를 재사용 하여 다른 요구사항을 개발한다.
  • 구성되어 있는 Architecture는 최적의 Architecture다.
  • Framework
스프링 시큐리티는 웹 어플리케이션에서 제일 앞에서 막는다.
서블릿필터와 디스패처서블릿은 스프링 3.0전까지는 빈으로 등록되지 않았다.(설정부분에서 등록하기 때문)
스프링 3.0 이후에는 빈으로 가지고 올 수 있게 변경되었다.

프레임워크란 내가 개발한 것이 무언가에 의해서 컨트롤 당할때
라이브러리는 내가 이용해서 무언가를 컨트롤할떄

메소드 안의 구현을 보지말고 어떻게 인터페이스를 설계와 클래스의 관계등 설계를 보자.

추상화가 높은 부분부터 공부하고 나중에 낮은 부분까지 공부하자.

누군가 어려웠던 개발을 물어보면?
해본사람만 알수 있는 구조적인 부분을 설명하자.

누구한테 물어볼때 내가 시행착오를 겪은 내용을 정리해서 물어보자.

JPA에서 N+1쿼리 일때는 fetch join을 하자



Share:

2018년 6월 5일 화요일

[ERROR] null value was assigned to a property of primitive type setter of

필드에 @Column(nullable = true) 옵셥을 주고 값을 가지고 올때 해당 필드에 null인 값이 있는 데이터가 있으면 에러가 발생한다. 기본 유형에 null값을 할당 할 수 없어서 wrapper class를 변경해서 사용하여야한다.

stackoverflow 참고
https://stackoverflow.com/questions/3154582/why-do-i-get-a-null-value-was-assigned-to-a-property-of-primitive-type-setter-o/3154585#3154585
Share:

2018년 6월 4일 월요일

패스트 캠퍼스 JAVA 웹 프로그래밍 마스터 39일차(JPA)

Spring Boot JPA

Spring DATA JPA를 사용한다.
Spring DATA JPA ----> JPA ---> Entity Manager가 포함되어있어서 Entity Manager 객체를 만들어서 사용하지 않아도 된다.

엔티티 매니저도 객체이다. Heap메모리에 올라가 있다.

persist하거나 JQPL,Find(),을 사용하면 1차캐시에 저장된다.
요청을 할때 DB에서 읽어온 데이터는 1차캐시에 저장되어 있다. 같은 요청을 하면 1차 캐시에 데이터가 있는 데이터를 반환한다. 그래서 상황에 따라 LAZY로딩이 더 빠를수도 있다.

엔티티 작업은 트랜잭선 안에서 일어나야 한다.
스프링 부트에서는  @Transactional을 통해 트랜잭션을 관리한다.

엔티티는 SQL을 최대한 늦게 실행하려고 한다. 트랜잭션이 끝날때 실행한다.

실행 순서

1. 영속성을 부여하면 그 순간에 엔티티에 대한 스냅샷이 저장된다.
2. 그 상태에서 엔티티에 대한 데이터를 수정한다.
3. 트랜잭션이 종료될 때 스냅샷의 상태와 객체의 상태를 값이 변경된게 있으면 update가 실행된다. 값이 같으면 update가 실행되지 않는다.
4. remove를 실행하면 사라질 객체이기 때문에 중간에 update문이 있어도 생략된다.

엔티티 매핑

1:1 관계는 하나로 합쳐도 되는 관계이다.(성능이나 관리떄문에 나누는 경우도 있다)
어디에 FK가 있든지 상관없다 하지만 FK를 가지고 있는 테이블에서 나중에 N관계를 가질 수 있다.

N : N
데이터베이스 에서는 N:N관계는 없다. 데이터베이스에서는 중간에 관계테이블이 있어야 한다.

FK가 있는 엔티티가 주인인다.
@JoinColumn을 적어야 한다. @JoinColumn이 들어가면 단방향 관계이다.
FK에 참조 당하고 있는 엔티티에서 MappedBy옵션은 FK가 있는 엔티티의 정의된것을 이용해서 찾겠다는 뜻이다.

N;1관계에서
@JoinColumn만 사용하는 것은 단방향
MappedBy옵션까지 사용하면 양방향 참조다.

N:N관계에서
@JoinTable를 사용한다.

cascade옵션은 참조하고 있는 엔티티도 같이 영속성을 부여하는 것이다.

단방향
한쪽에서만 참조한다.

양방향
서로가 서로를 참조한다.

fetch조인은 한번에 쿼리를 실행하지만 중복된 데이터가 나올수 있어서 중복된 데이터를 없애는 distinct 를 사용한다.

내부적인 구현보다는 논리적인 구조에 대해 이해하자.
다른사람의 소스코드에서 메소드안의 코딩 보다는 클래스,인터페이스의 대한 관계(설계)를 보자

Share: