Skip to content

Commit

Permalink
[๐Ÿฑ Tomcat ๊ตฌํ˜„ํ•˜๊ธฐ 1๋‹จ๊ณ„] ์ œ์šฐ์Šค(์‹ ์žฌ์šฐ) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค. (#552)
Browse files Browse the repository at this point in the history
* fix: remove implementation logback-classic on gradle (#501)

* fix: add threads min-spare configuration on properties (#502)

* fix: javax -> jakarta ๋ณ€๊ฒฝํ•˜์—ฌ ์ปดํŒŒ์ผ ์—๋Ÿฌ ํ•ด๊ฒฐ

* test: FileTest ํ•™์Šต

* test: IOStreamTest ํ•™์Šต

* feat: GET `index.html` ์‘๋‹ตํ•˜๊ธฐ

* refactor: http request ํด๋ž˜์Šค ๋ถ„๋ฆฌ

* feat: CSS ์ง€์›ํ•˜๊ธฐ

* feat: Query String ํŒŒ์‹ฑ

* feat: HTTP ํ™œ์šฉํ•˜๊ธฐ ํ•™์Šตํ…Œ์ŠคํŠธ

* refactor: ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค ์‚ญ์ œ

---------

Co-authored-by: Gyeongho Yang <[email protected]>
  • Loading branch information
zeus6768 and geoje authored Sep 9, 2024
1 parent 0b698a2 commit badca13
Show file tree
Hide file tree
Showing 18 changed files with 408 additions and 46 deletions.
6 changes: 6 additions & 0 deletions docs/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ

## 1๋‹จ๊ณ„ - HTTP ์„œ๋ฒ„ ๊ตฌํ˜„ํ•˜๊ธฐ
- [x] 1\. GET `index.html` ์‘๋‹ตํ•˜๊ธฐ
- [x] 2\. CSS ์ง€์›ํ•˜๊ธฐ
- [x] 3\. Query String ํŒŒ์‹ฑ
2 changes: 1 addition & 1 deletion study/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'ch.qos.logback:logback-classic:1.5.7'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.apache.commons:commons-lang3:3.14.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1'
implementation 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.4.1'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cache.com.example;

import jakarta.servlet.http.HttpServletResponse;

import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import jakarta.servlet.http.HttpServletResponse;

@Controller
public class GreetingController {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cache.com.example.cachecontrol;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class CacheControlInterceptor implements HandlerInterceptor {

@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable ModelAndView modelAndView
) {
response.setHeader("Cache-Control", "no-cache, private");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ public class CacheWebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(new CacheControlInterceptor())
.addPathPatterns("/**");
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package cache.com.example.etag;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.ShallowEtagHeaderFilter;

@Configuration
public class EtagFilterConfiguration {

// @Bean
// public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
// return null;
// }
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new ShallowEtagHeaderFilter());
filterRegistrationBean.addUrlPatterns("/etag");
filterRegistrationBean.addInitParameter("tag", "etag");
return filterRegistrationBean;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package cache.com.example.version;

import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand All @@ -20,6 +23,8 @@ public CacheBustingWebConfig(ResourceVersion version) {
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler(PREFIX_STATIC_RESOURCES + "/" + version.getVersion() + "/**")
.addResourceLocations("classpath:/static/");
.addResourceLocations("classpath:/static/")
.setEtagGenerator(__ -> version.getVersion())
.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import jakarta.annotation.PostConstruct;

@Component
public class ResourceVersion {

Expand Down
4 changes: 4 additions & 0 deletions study/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ handlebars:
suffix: .html

server:
compression:
enabled: true
min-response-size: 10
tomcat:
accept-count: 1
max-connections: 1
threads:
min-spare: 2
max: 2
24 changes: 13 additions & 11 deletions study/src/test/java/study/FileTest.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package study;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
* ์›น์„œ๋ฒ„๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ html ํŒŒ์ผ์„ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
Expand All @@ -27,8 +28,9 @@ class FileTest {
void resource_๋””๋ ‰ํ„ฐ๋ฆฌ์—_์žˆ๋Š”_ํŒŒ์ผ์˜_๊ฒฝ๋กœ๋ฅผ_์ฐพ๋Š”๋‹ค() {
final String fileName = "nextstep.txt";

// todo
final String actual = "";
final var classLoader = getClass().getClassLoader();
final var url = classLoader.getResource(fileName);
final String actual = url.toString();

assertThat(actual).endsWith(fileName);
}
Expand All @@ -40,14 +42,14 @@ class FileTest {
* File, Files ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ์ฝ์–ด๋ณด์ž.
*/
@Test
void ํŒŒ์ผ์˜_๋‚ด์šฉ์„_์ฝ๋Š”๋‹ค() {
void ํŒŒ์ผ์˜_๋‚ด์šฉ์„_์ฝ๋Š”๋‹ค() throws IOException {
final String fileName = "nextstep.txt";

// todo
final Path path = null;
final var classLoader = getClass().getClassLoader();
final var url = classLoader.getResource(fileName);
final Path path = Path.of(url.getPath());

// todo
final List<String> actual = Collections.emptyList();
final List<String> actual = Files.readAllLines(path);

assertThat(actual).containsOnly("nextstep");
}
Expand Down
44 changes: 34 additions & 10 deletions study/src/test/java/study/IOStreamTest.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
package study;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.io.*;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

/**
* ์ž๋ฐ”๋Š” ์ŠคํŠธ๋ฆผ(Stream)์œผ๋กœ๋ถ€ํ„ฐ I/O๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
* ์ž…์ถœ๋ ฅ(I/O)์€ ํ•˜๋‚˜์˜ ์‹œ์Šคํ…œ์—์„œ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ ์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
Expand Down Expand Up @@ -54,6 +66,7 @@ class OutputStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* OutputStream ๊ฐ์ฒด์˜ write ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ์‹œํ‚จ๋‹ค
*/

outputStream.write(bytes);
final String actual = outputStream.toString();

assertThat(actual).isEqualTo("nextstep");
Expand All @@ -78,6 +91,7 @@ class OutputStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* flush๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ์‹œํ‚จ๋‹ค.
* ByteArrayOutputStream๊ณผ ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ์„๊นŒ?
*/
outputStream.flush();

verify(outputStream, atLeastOnce()).flush();
outputStream.close();
Expand All @@ -96,6 +110,7 @@ class OutputStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* try-with-resources๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
* java 9 ์ด์ƒ์—์„œ๋Š” ๋ณ€์ˆ˜๋ฅผ try-with-resources๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
*/
try (outputStream) {}

verify(outputStream, atLeastOnce()).close();
}
Expand Down Expand Up @@ -128,7 +143,8 @@ class InputStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* todo
* inputStream์—์„œ ๋ฐ”์ดํŠธ๋กœ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟ€๊นŒ?
*/
final String actual = "";
byte[] stream = inputStream.readAllBytes();
final String actual = new String(stream, StandardCharsets.UTF_8);

assertThat(actual).isEqualTo("๐Ÿคฉ");
assertThat(inputStream.read()).isEqualTo(-1);
Expand All @@ -148,6 +164,7 @@ class InputStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* try-with-resources๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
* java 9 ์ด์ƒ์—์„œ๋Š” ๋ณ€์ˆ˜๋ฅผ try-with-resources๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
*/
try (inputStream) {}

verify(inputStream, atLeastOnce()).close();
}
Expand All @@ -169,12 +186,12 @@ class FilterStream_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฒ„ํผ์˜ ๊ธฐ๋ณธ ์‚ฌ์ด์ฆˆ๋Š” ์–ผ๋งˆ์ผ๊นŒ?
*/
@Test
void ํ•„ํ„ฐ์ธ_BufferedInputStream๋ฅผ_์‚ฌ์šฉํ•ด๋ณด์ž() {
void ํ•„ํ„ฐ์ธ_BufferedInputStream๋ฅผ_์‚ฌ์šฉํ•ด๋ณด์ž() throws IOException {
final String text = "ํ•„ํ„ฐ์— ์—ฐ๊ฒฐํ•ด๋ณด์ž.";
final InputStream inputStream = new ByteArrayInputStream(text.getBytes());
final InputStream bufferedInputStream = null;
final InputStream bufferedInputStream = new BufferedInputStream(inputStream);

final byte[] actual = new byte[0];
final byte[] actual = bufferedInputStream.readAllBytes();

assertThat(bufferedInputStream).isInstanceOf(FilterInputStream.class);
assertThat(actual).isEqualTo("ํ•„ํ„ฐ์— ์—ฐ๊ฒฐํ•ด๋ณด์ž.".getBytes());
Expand All @@ -197,16 +214,23 @@ class InputStreamReader_ํ•™์Šต_ํ…Œ์ŠคํŠธ {
* ํ•„ํ„ฐ์ธ BufferedReader๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด readLine ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž์—ด(String)์„ ํ•œ ์ค„ ์”ฉ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
*/
@Test
void BufferedReader๋ฅผ_์‚ฌ์šฉํ•˜์—ฌ_๋ฌธ์ž์—ด์„_์ฝ์–ด์˜จ๋‹ค() {
void BufferedReader๋ฅผ_์‚ฌ์šฉํ•˜์—ฌ_๋ฌธ์ž์—ด์„_์ฝ์–ด์˜จ๋‹ค() throws IOException {
final String emoji = String.join("\r\n",
"๐Ÿ˜€๐Ÿ˜ƒ๐Ÿ˜„๐Ÿ˜๐Ÿ˜†๐Ÿ˜…๐Ÿ˜‚๐Ÿคฃ๐Ÿฅฒโ˜บ๏ธ๐Ÿ˜Š",
"๐Ÿ˜‡๐Ÿ™‚๐Ÿ™ƒ๐Ÿ˜‰๐Ÿ˜Œ๐Ÿ˜๐Ÿฅฐ๐Ÿ˜˜๐Ÿ˜—๐Ÿ˜™๐Ÿ˜š",
"๐Ÿ˜‹๐Ÿ˜›๐Ÿ˜๐Ÿ˜œ๐Ÿคช๐Ÿคจ๐Ÿง๐Ÿค“๐Ÿ˜Ž๐Ÿฅธ๐Ÿคฉ",
"");
final InputStream inputStream = new ByteArrayInputStream(emoji.getBytes());
final var inputStreamReader = new InputStreamReader(inputStream);
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

final StringBuilder actual = new StringBuilder();

while (bufferedReader.ready()) {
actual.append(bufferedReader.readLine())
.append("\r\n");
}

assertThat(actual).hasToString(emoji);
}
}
Expand Down
Loading

0 comments on commit badca13

Please sign in to comment.