1. war파일을 생성 자바 애플리케이션 서버에 배포

gradle build / mvn package

배포는 서버마다 다르므로 참조할 것


2. 클라우드 파운드리에 배포

jar war groovy 혹은 어떤 형태도 가능

피보탈의 paas 플랫폼 pws http://run.pivotal.io

cf명령줄 도구를 받아서 설치한다.

organization과 space를 설정한다.

$cf login -a https://api.run.pivotal.io

$cf target -o {organization_name} -s {space_name}

$cf push sbia-readinglist -p build/libs/readinglist.war -b https://github.com/cloudfoundry/java-buildpack.git


3. jar 파일을 헤로쿠에 배포(빌드도 진행)

$git init //깃허브에 프로젝트가 없다면 

$heroku apps:create sbia-readinglist

Procfile 파일에 web: java -Dserver.port=$PORT -jar build/libs/readinglist.war

스테이지 태스크로 애플리케이션이 실행되므로 추가한다.

task stage(dependsOn: ['build']){ }

system.properties 파일에 java.runtime.version=1.8 설정

$git add -a

$git commit -am "Initial Commit"

$git push heroku master

http://{app name}.herokuapp.com에서 접속 가능(apps:create의 인자)

블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,

액추에이터를 사용하여 실행되는 어플리케이션의 내부 정보를 알수 있다.

책의 내용과 바뀐 부분이 있어서 해당 부분은 아래에서 확인하고 개발해야 한다.

기본적으로 /actuator/로 모든 액츄에이터가 이동하였다.

health info 등만 기본적으로 공개가 되어있고 프로퍼티를 설정해서 공개해야한다.

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#spring-boot-actuator

블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,

그레일즈 또한 스프링 기반에서 개발되었다.

그레일즈 3는 스프링 부트 기반이라고 한다.

그레일즈로 개발할 경우 더욱 코드가 간결해진다.

그레일즈는 그루비가 기본 개발 언어이다.

gorm(그레일즈 orm:더욱 간편)과 gsp(그레일즈서버페이지jsp와 유사)를 사용할 수 있다.

블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,

의존성과 임포트 자동화

@Grab으로 자동화되지 않는 임포트 관리

CLI 기반 테스트는 최신 버전(2.0.0과 2.1.2 확인)에선 존재하지 않는다

블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,

@ContextConfiguration 대신 @SpringApplicationConfiguration을 사용

@RunWith(SpringJUnit4ClassRunner.class)

mockMvc

웹 통합 테스트

MockMvcBuilders standAloneSetup() 수동 하나 webAppContextSetup() 자동 통합


웹 보안 테스트

testCompile('org.springframework.security:spring-security-test') springSecurity()


@WithMockUser 새로유저 생성 @WithUserDetails 기존 유저 조회


@WebIntegrationTest 실행중 애플리케이션 테스트

@WebIntegrationTest(value={"server.port=0"}) ("server.port=0") 

@WebIntegrationTest(randomPort=true) local.server.port에 설정됨


셀레늄으로 html페이지 테스트

testCompile("org.seleniumhq.selenium:selenium-java:2.53.0")

스프링 부트 1.3.6버전에서 동작하기 위해선 46.0.1버전의 파이어폭스가 필요했다

추후에 테스트하게 된다면 해당 버전에 맞게 확인하고 설정하자

블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,
애플리케이션 보안 설정하기
compile('org.springframework.boot:spring-boot-starter-security')

  org.spriingframework.boot
  spring-boot-starter-security

기본 설정시 시큐리티 패스워드가 로그에 출력되지만 실제 이용은 어렵다
WebSecurityConfigureAdapter를 확장해서 구성 클래스 구성 cofigure 메서드 오버라이드
.antMatchers("/").access("hasRole('READER')") / 경로는 유저 롤이 있을때만 허용
.antMatchers("/**).permitAll() 그외의 /** 경로는 모두 허용
어플리케이션에 WebMvcConfigurerAdapter extend
addViewControllers 컨트롤러와 뷰 매핑
addArgumentResolvers 유저 컨트롤러 매개변수 처리 리졸버 추가
요청페이지에서 사용자 정보를 얻을 수있게 모델에도 추가
사용자 유저 클래스에 UserDetails extend
resources/data.sql db 초기화할 정보 추가
insert into Reade (username,password, fullname) vlaues ('craig', 'password', 'Craig Walls');

프로퍼티를 이용해 구성하기
$java -jar build/libs/readinglist-0.0.1-SNAPSHOT.jar --spring.main.show-banner=false
spring.main.show-banner=false //application.properties
spring: //application.yml
  main:
    show-banner: false
프로퍼티 설정법과 우선순위(상단이 가장 높다)
1. 명령줄 인자 2. java:comp/env에서 얻는 JNDI속성 3. jvm 시스템 프로퍼티
4. 운영체제 환경 변수 5. random.*로 시작하는 프로퍼티 때문에 무작위로 생성된 값
6. 애플리케이션 외부에 있는 application.properties(yml) 7. 내부 application.properties(yml)
8. @PropertySource로 지정된 프로퍼티 소스 9. 기본 프로퍼티
properties yml은 하위디렉토리의 우선순위가 높고 yml이 높다

템플릿 캐싱 비활성화
$java -jar build/libs/readinglist-0.0.1-SNAPSHOT.jar --spring.thymeleaf.cache=false
spring:
  thymeleaf:
    cache: false
$export spring_thymeleaf_cache=false
프리마커 spring.freemarker.cache
그루비 템플릿 spring.groovy.template.cache
벨로시티 spring.,velocity.cache
서버포트 server.port
$keytool -keystore mykeys.jks -genkey -alias tomcat -keyalg RSA
server.ssl.key-store(위치) , server.ssl.key-store-password ,server.ssl.key-password(패스워드)
logging:
  config:
    classpath: logging-config.xml //컨피그 파일 변경
  path: /var/logs/ //로그백 위치
  file: BookWorm.log //파일이름
  level:
    root: WARN //로그 레벨
    org:
      springframework:
      security: DEBUG //스프링시큐리티 로그 레벨
spring:
  datasource:
    url: jdbc:mysql://localhost/readinglist
    username: dbuser
    password: dbpass
    driver-class-name: com.mysql.jdbc.Driver //보통은 생략 문제발생시 적용
spring:
  datasource:
    jndi-name: java:/comp/env/jdbc/readingListDS
@ConfigureProperties(prefix="amazon") //접두어가 amazon인 프로퍼티 주입

프로파일 구성
@Profile("production") 프로덕션일때만 해당 구성 사용
spring.profiles.active=production

프로파일에 특화된 프로퍼티 파일
application-production.properties파일과 application.properties 생성 yaml 여러 프로파일 구성
logging:
  level:
    root: INFO
---
spring:
  profiles: development
logging:
  level:
    root: INFO
---
spring:
  profiles: production
logging:
  level:
    root: INFO
오류 페이지 사용자 정의 error(thymeleaf->html)뷰를 만들어서 src/main/resources/templates 디렉토리에 넣는다
오류 정보 timestamp status error exception message errors trace path
이미지는 src/main/resources/static/images나 src/main/resources/public/images에 넣는다
블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,
web thymeleaf jpa h2(내장DB)를 선택하여 프로젝트 생성하기
$spring init -d=web,thymeleaf,data-jpa,h2 --groupId=com.manning  
--artifactId=readinglist --name="Reading List" --package-name=readinglist 
--description="Reading List Demo" --build gradle readinglist

@SpringBootApplication 애너테이션에는 아래 세가지 어노테이션이 모두 들어있다
@Configuration
자바 기반 구성 클래스(XML이 아닌)
@ComponentScan
컴포넌트 검색 기능으로 웹 컨트롤러 클래스나 다른 컴포넌트 클래스를 컨텍스트에 빈으로 등록
컨트롤러에는 @Controller 애너테이션 추가
@EnableAutoConfiguration
수동 구성 코드를 대체하는 자동 구성이 활성화된다

$gradle bootRun //애플리케이션 빌드 실행
$gradle build //빌드
$java -jar build/libs/readinglist-0.0.1-SNAPSHOT.jar //빌드된 jar 실행
@SpringApplicationConfiguration 애너테이션
contextLoads() 애플리케이션 구성에 문제가 없다면 정상 실행

application.properties server.port=8000 서버포트를 8000으로 변경한다

전이적 의존성 확인하기(구체적인 라이브러리 의존성)
$gradle dependencies
$mvn dependency:tree
전이적 의존성 제외하기
compile('org.springframework.boot:spring-boot-starter-web'){
    exclude group:'com.fasterxml.jackson.core'
}

  org.springframework.boot
  spring-boot-starter-web
  
    
      com.fasterxml.jackson.core
    
  

직접 버전 설정

  com.fasterxml.jackson.core
  jackson-databind
  2.4.3

compile('com.fasterxml.jackson.core:jackson-databind:2.4.3') //최신버전 

compile('org.springframework.boot:spring-boot-starter-web'){
    exclude group:'com.fasterxml.jackson.core'
}
compile('com.fasterxml.jackson.core:jackson-databind:2.3.1') //구 버전
자동구성 사용하기
클래스패스에 있는 것들을 위한 빈들과 기능등을 자동 구성한다.

도메인 정의
@Entity 클래스를 엔티티로 지정
@Id @GeneratedValue(strategy=GenerationType.AUTO) 자동으로 값을 제공하는 유니크 아이디

리포지토리 인터페이스 선언
JpaRepository를 확장하여 연산수행 <도메인타입, ID 프로퍼티 타입> 런타임에 자동으로 구현

웹 인터페이스 만들기
@Controller @RequestMapping("/")
컨텍스트 빈에 자동 등록하기 위해 @Controller
url경로 /에 메소드를 매핑 @RequestMapping("/")
@AutoWired 세터나 생성자 필드 등을 자동생성해준다
@RequestMapping(method=RequestMethod.GET) //http GET 방식으로 지정
public String readerBooks(Model model){
  List readingList = readingListRepository.findByReader(reader);
  if(readingList !=null){
    model.addAttribute("books",readingList); //html에서 사용될 books 항목을 지정해준다
  }
  return "readingList";//렌더링할 뷰의 이름을 반환한다 readingList.html
}
@RequestMapping(method=RequestMethod.POST) //http POST 방식으로 지정
public String addToReadingList(Book book){ //추가 버튼 클릭시 호출된다
  book.setReader(reader);
  readingListRepository.save(book);  //입력된 사항을 저장한다
  return "redirect:/";  //리다이렉트 하면서 반환한다(다른 컨트롤러 메서드가 처리)
}
readingList.html의 역할
주소 / 에 접속(get:readerBooks)하면 /readingList.html 에 접속되고
북을 추가(post:addToReadingList)하면 / 로 리다이렉트되면서
다시 /readingList.html에 접속하여 추가된 북을 확인한다
public class JdbcTemplateCondition implements Condition{
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
  try{
    context.getClassLoader().loadClass("org.springframework.jdbc.core.JdbcTemplate");
    return true;
  } catch(Exception e){
    return false;
  }
}

@Conditional(JdbcTemplateCondition.class)
@Bean
public MyService myService(){
  //...
}
JdbcTemplate이 클래스패스에 있을 때만 MyService 빈을 생성


 조건 애너테이션 

 구성을 적용하는 조건 

 @ConditionalOnBean

 대상 빈을 구성함 

 @ConditionalOnMissingBean

 대상 빈을 아직 구성하지 않음

 @ConditionalOnClass

 대상 클래스가 클래스 패스에 있음

 @ConditionalOnMissingClass

 대상 클래스가 클래스패스에 없음

 @ConditionalOnExpression

 스프링 표현식 언어(SpEL)가 참(true)

 @ConditionalOnJava

 자바 버전이 특정 버전 또는 범위에 맞음

 @ConditionalOnJndi

 JNDI InitailContext가 사용가능하고 

 선택적으로 지정한 JNDI 위치가 있음

 @ConditionalOnProperty

 지정한 구성 프로퍼티가 기대하는 값을 가짐

 @ConditionalOnResource

 지정한 리소스가 클래스패스에 있음

 @ConditionalOnWebApplication

 애플리케이션이 웹 애플리케이션임

 @ConditionalOnNotWebApplication

 애플리케이션이 웹 애플리케이션이 아님


블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,
스프링 부트는 스프링 환경설정이 복잡하고 다소 진입장벽이 있는 점을 보완하여
라이브러리 의존성을 스타터 의존성으로 대체하고 선택한 항목별(web, sql, 등등)로 라이브러리를 자동으로 추가해준다.
때문에 바로 사용가능한 어플리케이션을 개발할 수 있다.
그루비로 컨트럴러 클래스 하나만 작성하고 해당 파일을 바로 실행할 수 있다.

스프링 부트의 핵심

자동구성 스프링 애플리케이션에 필요한 기능을 자동 구성한다(어노테이션)
스타터 의존성 선택한 기능에 따라 필요 라이브러리가 빌드에 추가된다
명령줄 인터페이스 애플리케이션 코드만 작성해도 애플리케이션 개발이 가능하다
액추에이터 어플리케이션 실행시 내부에서 일어나는 일을 알 수 있다.

스프링 부트 시작하기

1. 스프링 부트 CLI 설치
다운로드한 배포 버전 설치 압축풀고 패스 추가해주기
(유닉스 계열은 심볼릭 링크에 패스를 거는것이 유용하다)

2. SDKMAN 소프트웨어 개발 키트 매니저로 설치(http://sdkman.io)
$curl -s get.sdkman.io | bash
$source "/Users/username/.sdkman/bin/sdkman-init.sh"

$sdk install springboot
3. Homebrew로 설치(OSX) (http://brew.sh)
$ruby -e "$(curl -fsSl https://raw.githubusercontent.com/Homebrew/install/master/install)"
$brew tap pivotal/tap //스프링 개발사 피보탈 탭을 태핑한다

$brew install springboot
4. 맥포트로 설치(https://www.macports.org/install.php 버전별로 상이)
xcode와 command line tools 설치가 필요
$sudo port -v selfupdate
$sudo port install spring-boot-cli
$spring --version //설치후 버전확인
명령 자동완성 활성화
$. ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
(sdkman설치후 bash용 현재 셸에만 적용된다)
$spring shell //스프링부트 cli셸
spring 입력하고 탭을 누르면 명령과 옵션 표시
명령 선택후 --입력 탭을 누르면 옵션표시

Spring initializr로 스프링 부트 프로젝트 구성하기
1. 웹 기반 인터페이스
http://start.spring.io
상세설정 switch to the full version

2. Spring Tool Suite(STS)
File > New > Spring Starter Project(인터넷이 가능해야 하고 방화벽 허용해야 한다)

3. IntelliJ IDEA
File > New > Project... 화면에서 Spring Initializr선택

4. 스프링 부트 CLI
$spring init -dwep,jpa,security --build gradle -p war myapp //-x
공백없이 입력해야 한다
-d 의존성 옵션(wep,jpa,security추가)
--builid 그레이들 메이븐 선택(기본 메이븐)
--packageing -p 실행 가능한 war(jar or war:독립실행가능) 파일 생성
--extract -x 생성된 프로젝트를 받아서 현재 디렉토리에 푼다
$spring help init $spring init --list init 매개변수와 지원기능 확인

스프링 부트 프로젝트 구조(myapp프로젝트)
build.gradle 그레이들 빌드 명세(maven이면 pom.xml)
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
gradlew 그레이들 래퍼
gradlew.bat 그레이들 래퍼 윈도우에서 사용
src/main/java/myapp/MyappApplication.java 애플리케이션 시작main
src/main/resources/application.properties 필요한 구성 프로퍼티
src/main/resources/static 자바스크립트, 스타일시트, 이미지 등 정적 컨텐츠
src/main/resources/templates 모델 데이터 렌더링할 템플릿
src/test/java/myapp/MyappApplicationTests.java 애플리케이션 컨텍스트 로드 JUnit 테스트 클래스
블로그 이미지

dev김

안드로이드 개발자로 만 4년이 좀 안되게 근무했었고 그 이상의 공백을 가지고 있다. 다시 현업에 복귀하기 위한 노력의 흔적을 담으려고 한다.

,