https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/
ㅁ 내장 웹 서버 응용 1부 : 컨테이너와 포트
- pom.xml 에서 tomcat을 exclusion으로 빼고, jetty 넣기
- application.properties 에 spring.main.web-application-type=none 입력하면 자동으로 프로그램으로 실행
> server.port=7070 도 마찬가지 ( 0으로하면 random )
- application.properties 에 server.ssl 로 써서 지정
ex)
server.ssl.key-store= keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=123456
server.ssl.key-alias=spring
- 커넥터를 생성하여 8080 과 8443 동시에 연결 받기
@Bean
public ServletWebServerFactory serverFactory() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8080);
return connector;
}
- http2 적용의 경우, tomcat은 8.5.x는 적용 어려움
- properties 통해 tomcat 버전 변경 가능
ㅁ 독립적으로 실행 가능한 JAR
- mvn package -DskipTests
(테스트 생략하고 jar로 빌드)
> 이후 jar파일 실행하면 바로 웹서비스가 진행됨
- 수많은 의존성들은 어떻게 되었을까?
> 압축 풀면 모두 포함되어있음
> JarLauncher 등을 사용하여 jar 파일을 읽음
- 스프링 부트는 standalone 어플리케이션을 만들수있다. ( 큰 특징 )
CH4. 스프링 부트 활용
ㅁ Spring Application
- vmOption : Ddebug
기본적으로 info인데, debug 로 변경하면 자동으로 세팅되는것까지 다 나옴
- resource/banner.txt
> 여러 옵션이 있다.
> SpringApplication 에서 setBanner , setBannerMode 등 가능
- 다만 txt파일이 setBanner를 이긴다.
- new SpringApplicationBuilder().soruce(xxx.class).run(args) 등으로도 어플리케이션 실행 가능
- ApplicationListener<ApplicationStartingEvent> 를 implements 하여 클래스를 만들고, bean으로 등록했으나
구동 시 이벤트가 발생하지 않는다
> applicationContext가 만들어 진 후, 발생한 이벤트는 위 bean이 인식할 수 있으나, 그렇지 못했다.
> 수동으로 등록해줘야한다
- webapplicationType 은 servlet -> webflux -> none 순으로 있는게 기동됨
- vm option, argument
-> vm option은 argument가 아님 ( --Dxx 로 입력 )
- ApplicationRunner(추천), CommandLineRunner : 애플리케이션 실행 뒤 뭔가 실행하고 싶을때
ㅁ 외부 설정
- application.properties 는 컨벤션 (규약 ) 임
> 자동으로 여기 있는 속성을 읽음
> 이것의 우선순위는 15위
- Application.properties 위치 우선 순위
1. file:/config/
2. file:./
3. classpath:/config/
4. classpath:/
- 프로퍼티 타입 컨버전은 융통성있게 변경됨
- Duration (초) 로 컨버전도 가능
>25s 등과 같이 입력도 가능
- @NotEmpty,
- @ConfigurationProperties(" xxx" ) 는
application.properties에 있는 xxx의 속성들을 가져와서, 변수에 컨버전함 (@Value를 안써도됨)
- @Value
> SpEL을 사용할 수 있지만, @ConfigurationProperties로 땡겨오는건 SpEl 못씀
ㅁ 프로파일
- application.properties 에 spring.profiles.active 에 설정 (prod, test)
- 패키징 하여 java 실행시 argument로 주는 방법도 있음
- application-prod or test .properties가 application.properties 보다 우선순위가 높음
ㅁ 로깅
- 로깅 퍼사드는 로거 (JUL, Log4J2, Logback ) 를 원하는걸 쓸 수 있도록 바꿔줌
> Commons Logging, SLF4j
- Commons Logging 은 클래스로더 에서 메모리 leak등의 이슈로 안쓰는 움직임이 있었음
- 스프링 부트는 Commons Logging 을 씀
> 그러나 결과적으로 SLF4j 로깅퍼사드를 쓰게되고, SLF4j는 LogBack을 로거로 써서 로깅하게됨
> logback 은 slf4j의 구현체
> jul, lo4j2 => slf4j 로 전달하게 됨
- debug, trace, logging.path 등 여러 옵션이 있음
- logback-spring.xml 을 만들어서 설정파일로 관리도 가능
( 특정 패키지만 어느방식으로 기록 등)
ㅁ 테스트
- spring-boot-starter-test dependency 추가
- 아래 작성
package me.defian.springtestdemo.sample;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//@AutoConfigureMockMvc
public class SampleControllerTest {
// @Autowired
// MockMvc mockMvc;
@Autowired
WebTestClient webTestClient;
@Autowired
TestRestTemplate testRestTemplate;
@MockBean
SampleService mockSampleService;
@Rule
public OutputCapture outputCapture = new OutputCapture();
@Test
public void hello() throws Exception {
// mockMvc.perform(get("/hello"))
// .andExpect(status().isOk())
// .andExpect( content().string("Hello HyungChul"))
// .andDo(print());
when(mockSampleService.getName()).thenReturn("defian");
webTestClient.get().uri("/hello").exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello defian");
// String result = testRestTemplate.getForObject("/hello",String.class);
// assertThat(result).isEqualTo("Hello defian");
assertThat(outputCapture.toString()).contains("Holoman").contains("skip");
}
}
- mocking이란 모방하는건데, 특정 서비스까지 가서 풀로직을 돌고싶지않을때, 모킹하여 리턴값을 간단히 설정하여 테스트한다
- 랜덤포트 쓰는걸 추천
- spring 5 부터 생긴 건데, WebTestClient는 Async하게 동작하여 테스트 체크함
> pom.xml 에 추가하여 사용
- json : jacksonTester 등 여러 테스터가 존재한다 (@JsonTest)
- @WebMvcTest(SampleController.class) : 특정 mvc 빈만 테스트
- OutputCapture 를 통해 특정 로그 (logger , sysout 등) 이 찍히는지도 확인할 수 있다.
ㅁ Spring-Boot-Devtools
- 의존성 설치 필요
- springboot 실행 시 base classloader , restart classloader 두개를 실행함
- 빌드만 하면 자동으로 코드 변경 및 브라우저도 리로딩함 ( 플러그인 설치 시 )
ㅁ 스프링 Thymeleaf
- 뷰를 만들때 쓰는 템플릿 엔진
> FreeMarker , Groovy, Thymeleaf, Mustache
- JSP 는 권장하지 않음
> jar 대신 war로 패키징 해야함 (물론 war로 패킹하여 java로 실행가능하긴 하나 권장하지 않음)
> undertow는 jsp를 지원하지 않음
- 실제 서블릿 컨테이너 개입 없이 rendering된 화면을 볼 수 있다.
> mockmvc는 실제 서블릿 컨테이너가 아니고, mocking하는것임
> thymeleaf로 뷰의 결과까지 확인 할 수 있음
- thymeleaf 사용
> html 에 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 추가
> <h1 th:text="${name}">Name</h1> 으로 호출
ㅁ 스프링 HtmlUnit
- Html을 단위테스트 하기위한 툴
- xpath 통해서도 테스트 가능
- 어떤 단어가 포함되었는지 테스트 진행함
ㅁ ExceptionHandler
- 특정 컨트롤러 안에서의 ExceptionHandler
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SampleController {
@GetMapping("/hello")
public String hello(){
throw new SampleExeption();
}
@ExceptionHandler(SampleExeption.class)
public @ResponseBody AppError sampleError(SampleExeption e ){
AppError appError = new AppError();
appError.setMessage("error.app.key");
appError.setReason("IDK IDK IDK");
return appError;
}
}
- @ControllerAdvice 통해서 전체 컨트롤러에서 설정 가능
- BasicErrorController.java 참고하여 커스터마이징하여 구성
- 기본으로 나오는 에러 페이지는 가장 마지막에 나옴 (BasicErrorController가 구성)
- resources/static/error 폴더에 번호.html 만들면 그게 나옴
ㅁ Hypermedia As The Engine Of Application State
- 연관된 링크 정보 (Relation , Hypertext Reference) 를 전달해주면 이걸 바탕으로 접근함
- ObjectMapper 와 LinkDiscovers 제공
> Jackson 에서 제공해주는 클래스
- ObjectMapper는 자동으로 bean으로 등록이 되어있다.
> application.properties에 spring.jackson.옵션으로 커스터마이징 가능
ㅁ CORS
- Origin ? URI 스키마 (http, https) / hostname / 포트
- Single-Origin Policy
- @CrossOrigin(origins="http://localhost:18080") 컨트롤러 안에 매핑에 태그 작성
- 위 어노테이션 설정이 힘들면 글로벌하게 아래 설정 작성
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:18080");
}
}
'Spring' 카테고리의 다른 글
[Spring] 스프링 부트 개념과 활용 - 4 (0) | 2021.07.19 |
---|---|
[Spring] 스프링 부트 개념과 활용 - 3 (0) | 2021.07.19 |
[Spring] 스프링 부트 개념과 활용 - 1 (0) | 2021.07.10 |
[Spring] 스프링 프레임워크 핵심 기술 정리 - 2 (0) | 2021.07.05 |
[Spring] 스프링 프레임워크 핵심 기술 정리 - 1 (0) | 2021.07.04 |