From 8ab9c4125bd8da2debb41091b19e525b2dcda881 Mon Sep 17 00:00:00 2001 From: Elex Date: Sun, 8 Aug 2021 20:15:27 +0900 Subject: [PATCH] 2021-08-08 --- i18n/build.gradle.kts | 27 ++++++++ .../java/kr/pe/elex/examples/Application.java | 20 ++++++ .../elex/examples/CustomLocaleResolver.java | 64 +++++++++++++++++++ .../java/kr/pe/elex/examples/I18nAdvice.java | 30 +++++++++ .../kr/pe/elex/examples/MyController.java | 35 ++++++++++ .../java/kr/pe/elex/examples/WebConfig.java | 54 ++++++++++++++++ .../kr/pe/elex/examples/package-info.java | 8 +++ i18n/src/main/resources/application.yaml | 9 +++ i18n/src/main/resources/banner.txt | 10 +++ i18n/src/main/resources/i18n_en.properties | 1 + i18n/src/main/resources/i18n_ko.properties | 1 + i18n/src/main/resources/logback-spring.xml | 48 ++++++++++++++ .../main/resources/templates/main.mustache | 2 + logback.xml => logback-spring.xml | 0 mvc/build.gradle.kts | 27 ++++++++ .../java/kr/pe/elex/examples/Application.java | 20 ++++++ .../kr/pe/elex/examples/MyController.java | 47 ++++++++++++++ .../java/kr/pe/elex/examples/MyService.java | 14 ++++ .../main/java/kr/pe/elex/examples/Person.java | 12 ++++ .../kr/pe/elex/examples/package-info.java | 8 +++ mvc/src/main/resources/application.yaml | 9 +++ mvc/src/main/resources/banner.txt | 10 +++ mvc/src/main/resources/logback-spring.xml | 48 ++++++++++++++ .../main/resources/templates/main.mustache | 15 +++++ .../java/kr/pe/elex/examples/WebConfig.java | 1 - settings.gradle.kts | 2 +- 26 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 i18n/build.gradle.kts create mode 100644 i18n/src/main/java/kr/pe/elex/examples/Application.java create mode 100644 i18n/src/main/java/kr/pe/elex/examples/CustomLocaleResolver.java create mode 100644 i18n/src/main/java/kr/pe/elex/examples/I18nAdvice.java create mode 100644 i18n/src/main/java/kr/pe/elex/examples/MyController.java create mode 100644 i18n/src/main/java/kr/pe/elex/examples/WebConfig.java create mode 100644 i18n/src/main/java/kr/pe/elex/examples/package-info.java create mode 100644 i18n/src/main/resources/application.yaml create mode 100644 i18n/src/main/resources/banner.txt create mode 100644 i18n/src/main/resources/i18n_en.properties create mode 100644 i18n/src/main/resources/i18n_ko.properties create mode 100644 i18n/src/main/resources/logback-spring.xml create mode 100644 i18n/src/main/resources/templates/main.mustache rename logback.xml => logback-spring.xml (100%) create mode 100644 mvc/build.gradle.kts create mode 100644 mvc/src/main/java/kr/pe/elex/examples/Application.java create mode 100644 mvc/src/main/java/kr/pe/elex/examples/MyController.java create mode 100644 mvc/src/main/java/kr/pe/elex/examples/MyService.java create mode 100644 mvc/src/main/java/kr/pe/elex/examples/Person.java create mode 100644 mvc/src/main/java/kr/pe/elex/examples/package-info.java create mode 100644 mvc/src/main/resources/application.yaml create mode 100644 mvc/src/main/resources/banner.txt create mode 100644 mvc/src/main/resources/logback-spring.xml create mode 100644 mvc/src/main/resources/templates/main.mustache diff --git a/i18n/build.gradle.kts b/i18n/build.gradle.kts new file mode 100644 index 0000000..b6071fc --- /dev/null +++ b/i18n/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +plugins { + id("elex-spring-boot") + + id("org.springframework.boot") version "2.5.3" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-mustache") + + compileOnly("org.projectlombok:lombok") + developmentOnly("org.springframework.boot:spring-boot-devtools") + + annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") + annotationProcessor("org.projectlombok:lombok") + + testImplementation("org.springframework.boot:spring-boot-starter-test") + +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/Application.java b/i18n/src/main/java/kr/pe/elex/examples/Application.java new file mode 100644 index 0000000..7ff4bbf --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/Application.java @@ -0,0 +1,20 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/CustomLocaleResolver.java b/i18n/src/main/java/kr/pe/elex/examples/CustomLocaleResolver.java new file mode 100644 index 0000000..f09ac52 --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/CustomLocaleResolver.java @@ -0,0 +1,64 @@ +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Locale; + +/** + * 로케일 리졸버 + * AcceptHeaderLocaleResolver를 기본 정책으로하되, GET 파라미터로 로캐일 변환이 가능하도록 한다. + * @author Elex + */ +@Slf4j +public class CustomLocaleResolver implements LocaleResolver { + + /** + * 지원되는 로캐일 목록. 첫 번째 로캐일은 기본 로캐일로 사용된다. + */ + private static final List supportedLocales = List + .of(Locale.ENGLISH, Locale.KOREAN); + + private Locale locale = null; + private final AcceptHeaderLocaleResolver acceptHeaderLocaleResolver; + + public CustomLocaleResolver() { + super(); + + acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver(); + acceptHeaderLocaleResolver.setSupportedLocales(supportedLocales); + acceptHeaderLocaleResolver.setDefaultLocale(supportedLocales.get(0)); + } + + @Override + public @NotNull Locale resolveLocale(@NotNull HttpServletRequest request) { + if (null == locale) { + return acceptHeaderLocaleResolver.resolveLocale(request); + } else { + for (Locale loc : supportedLocales) { + if (locale.equals(loc)) return loc; + } + for (Locale loc : supportedLocales) { + if (locale.getLanguage().equals(loc.getLanguage())) return loc; + } + return supportedLocales.get(0); + } + } + + /** + * 안터셉터에서 처리될껄? + * @param request + * @param response + * @param locale + */ + @Override + public void setLocale(@NotNull HttpServletRequest request, HttpServletResponse response, + Locale locale) { + this.locale = locale; + } +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/I18nAdvice.java b/i18n/src/main/java/kr/pe/elex/examples/I18nAdvice.java new file mode 100644 index 0000000..1e6f4b1 --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/I18nAdvice.java @@ -0,0 +1,30 @@ +package kr.pe.elex.examples; + +import com.samskivert.mustache.Mustache; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; + +import java.util.Locale; + +/** + * Mustache 템플릿에 국제화 문자열을 끼워넣기 위해 사용된다. + */ +@Slf4j +@ControllerAdvice +public class I18nAdvice { + @Autowired + private MessageSource messageSource; + + @ModelAttribute("i18n") + public Mustache.Lambda i18n(Locale locale){ + return (frag, out) -> { + String body = frag.execute(); + String message = this.messageSource.getMessage(body, new String[]{}, locale); + log.debug("User Locale: {} -> {}", locale, message); + out.write(message); + }; + } +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/MyController.java b/i18n/src/main/java/kr/pe/elex/examples/MyController.java new file mode 100644 index 0000000..bcab714 --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/MyController.java @@ -0,0 +1,35 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.ContentDisposition; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.util.HashMap; + +@Slf4j +@Controller +public class MyController { + + @GetMapping(path = {"/"}) + public String index() throws Exception { + + return "main"; + } + +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/WebConfig.java b/i18n/src/main/java/kr/pe/elex/examples/WebConfig.java new file mode 100644 index 0000000..b7ced2b --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/WebConfig.java @@ -0,0 +1,54 @@ +package kr.pe.elex.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Value("${spring.messages.basename:i18n}") + String messagesBasename = null; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } + + /** + * Locale resolver, 디폴트 로캐일을 지정한다. + */ + @Bean + public LocaleResolver localeResolver() { + /* + SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver(); + sessionLocaleResolver.setDefaultLocale(Locale.US); + return sessionLocaleResolver; + */ + return new CustomLocaleResolver(); + } + + /** + * Locale change interceptor, 요청 파라미터에 따른 로케일 변경 + */ + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("language"); + return localeChangeInterceptor; + } + + @Bean + public MessageSource messageSource() { + ReloadableResourceBundleMessageSource messageSource + = new ReloadableResourceBundleMessageSource(); + messageSource.setBasename("classpath:/" + messagesBasename); + messageSource.setDefaultEncoding("UTF-8"); + return messageSource; + } +} diff --git a/i18n/src/main/java/kr/pe/elex/examples/package-info.java b/i18n/src/main/java/kr/pe/elex/examples/package-info.java new file mode 100644 index 0000000..ce9cc62 --- /dev/null +++ b/i18n/src/main/java/kr/pe/elex/examples/package-info.java @@ -0,0 +1,8 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; diff --git a/i18n/src/main/resources/application.yaml b/i18n/src/main/resources/application.yaml new file mode 100644 index 0000000..b65dcf3 --- /dev/null +++ b/i18n/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + application: + name: My spring-boot project + mustache: + expose-request-attributes: true + messages: + basename: i18n +server: + port: 8080 diff --git a/i18n/src/main/resources/banner.txt b/i18n/src/main/resources/banner.txt new file mode 100644 index 0000000..f7a35db --- /dev/null +++ b/i18n/src/main/resources/banner.txt @@ -0,0 +1,10 @@ + ('-. ('-. ) (`-. + _( OO) _( OO) ( OO ). +(,------.,--. (,------.(_/. \_)-. + | .---'| |.-') | .---' \ `.' / + | | | | OO ) | | \ /\ +(| '--. | |`-' |(| '--. \ \ | + | .--'(| '---.' | .--' .' \_) + | `---.| | | `---. / .'. \ + `------'`------' `------''--' '--' +powered by ELEX diff --git a/i18n/src/main/resources/i18n_en.properties b/i18n/src/main/resources/i18n_en.properties new file mode 100644 index 0000000..cdca0dc --- /dev/null +++ b/i18n/src/main/resources/i18n_en.properties @@ -0,0 +1 @@ +hello.text = Hello diff --git a/i18n/src/main/resources/i18n_ko.properties b/i18n/src/main/resources/i18n_ko.properties new file mode 100644 index 0000000..7a98a2d --- /dev/null +++ b/i18n/src/main/resources/i18n_ko.properties @@ -0,0 +1 @@ +hello.text = 안녕 diff --git a/i18n/src/main/resources/logback-spring.xml b/i18n/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..19f023b --- /dev/null +++ b/i18n/src/main/resources/logback-spring.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + UTF-8 + ${FILE_LOG_PATTERN} + + ${LOG_PATH} + + ${LOG_DIR}/sebastian_%d{yyyy-MM-dd}_%i.log.gz + + 10MB + + 60 + + + + + + + + + + + + + diff --git a/i18n/src/main/resources/templates/main.mustache b/i18n/src/main/resources/templates/main.mustache new file mode 100644 index 0000000..f622c0e --- /dev/null +++ b/i18n/src/main/resources/templates/main.mustache @@ -0,0 +1,2 @@ +

i18n

+

{{#i18n}}hello.text{{/i18n}}

diff --git a/logback.xml b/logback-spring.xml similarity index 100% rename from logback.xml rename to logback-spring.xml diff --git a/mvc/build.gradle.kts b/mvc/build.gradle.kts new file mode 100644 index 0000000..b6071fc --- /dev/null +++ b/mvc/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +plugins { + id("elex-spring-boot") + + id("org.springframework.boot") version "2.5.3" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-mustache") + + compileOnly("org.projectlombok:lombok") + developmentOnly("org.springframework.boot:spring-boot-devtools") + + annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") + annotationProcessor("org.projectlombok:lombok") + + testImplementation("org.springframework.boot:spring-boot-starter-test") + +} diff --git a/mvc/src/main/java/kr/pe/elex/examples/Application.java b/mvc/src/main/java/kr/pe/elex/examples/Application.java new file mode 100644 index 0000000..7ff4bbf --- /dev/null +++ b/mvc/src/main/java/kr/pe/elex/examples/Application.java @@ -0,0 +1,20 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/mvc/src/main/java/kr/pe/elex/examples/MyController.java b/mvc/src/main/java/kr/pe/elex/examples/MyController.java new file mode 100644 index 0000000..d2eb0b4 --- /dev/null +++ b/mvc/src/main/java/kr/pe/elex/examples/MyController.java @@ -0,0 +1,47 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@Controller +@RequestMapping({"/my"}) +public class MyController { + @Autowired + private MyService service; + + @GetMapping({"/"}) + public String index() { + return "main"; + } + + @GetMapping({"/path/{id}"}) + public String withPathVar(@PathVariable String id) { + return "main"; + } + + @GetMapping({"/request"}) + public String withReqVar(@RequestParam String id) { + return "main"; + } + + @PostMapping({"/post"}) + public String withPostBody(@RequestBody Person person) { + return "main"; + } + + @GetMapping({"/request/header"}) + public String withReqHeader(@RequestHeader MultiValueMap headers) { + return "main"; + } +} diff --git a/mvc/src/main/java/kr/pe/elex/examples/MyService.java b/mvc/src/main/java/kr/pe/elex/examples/MyService.java new file mode 100644 index 0000000..c68c036 --- /dev/null +++ b/mvc/src/main/java/kr/pe/elex/examples/MyService.java @@ -0,0 +1,14 @@ +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class MyService { + public String doSomething(String param) throws IllegalArgumentException, Exception { + if ("illegal" == param) throw new IllegalArgumentException("Oops~"); + if ("exception" == param) throw new Exception("Oops~"); + return "Hello"; + } +} diff --git a/mvc/src/main/java/kr/pe/elex/examples/Person.java b/mvc/src/main/java/kr/pe/elex/examples/Person.java new file mode 100644 index 0000000..660718c --- /dev/null +++ b/mvc/src/main/java/kr/pe/elex/examples/Person.java @@ -0,0 +1,12 @@ +package kr.pe.elex.examples; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class Person { + @JsonProperty + private String name; + @JsonProperty + private int age; +} diff --git a/mvc/src/main/java/kr/pe/elex/examples/package-info.java b/mvc/src/main/java/kr/pe/elex/examples/package-info.java new file mode 100644 index 0000000..ce9cc62 --- /dev/null +++ b/mvc/src/main/java/kr/pe/elex/examples/package-info.java @@ -0,0 +1,8 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; diff --git a/mvc/src/main/resources/application.yaml b/mvc/src/main/resources/application.yaml new file mode 100644 index 0000000..8448219 --- /dev/null +++ b/mvc/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + application: + name: My spring-boot project + servlet: + multipart: + max-file-size: 128KB + max-request-size: 128KB +server: + port: 8080 diff --git a/mvc/src/main/resources/banner.txt b/mvc/src/main/resources/banner.txt new file mode 100644 index 0000000..f7a35db --- /dev/null +++ b/mvc/src/main/resources/banner.txt @@ -0,0 +1,10 @@ + ('-. ('-. ) (`-. + _( OO) _( OO) ( OO ). +(,------.,--. (,------.(_/. \_)-. + | .---'| |.-') | .---' \ `.' / + | | | | OO ) | | \ /\ +(| '--. | |`-' |(| '--. \ \ | + | .--'(| '---.' | .--' .' \_) + | `---.| | | `---. / .'. \ + `------'`------' `------''--' '--' +powered by ELEX diff --git a/mvc/src/main/resources/logback-spring.xml b/mvc/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..19f023b --- /dev/null +++ b/mvc/src/main/resources/logback-spring.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + UTF-8 + ${FILE_LOG_PATTERN} + + ${LOG_PATH} + + ${LOG_DIR}/sebastian_%d{yyyy-MM-dd}_%i.log.gz + + 10MB + + 60 + + + + + + + + + + + + + diff --git a/mvc/src/main/resources/templates/main.mustache b/mvc/src/main/resources/templates/main.mustache new file mode 100644 index 0000000..811061b --- /dev/null +++ b/mvc/src/main/resources/templates/main.mustache @@ -0,0 +1,15 @@ +

File Upload Example!!!

+
+ + +
+ +
+
+

Uploaded Files

+

Click to download.

+
    + {{#files}} +
  • {{.}}
  • + {{/files}} +
diff --git a/security-with-jwt/src/main/java/kr/pe/elex/examples/WebConfig.java b/security-with-jwt/src/main/java/kr/pe/elex/examples/WebConfig.java index 6b7389a..8da9150 100644 --- a/security-with-jwt/src/main/java/kr/pe/elex/examples/WebConfig.java +++ b/security-with-jwt/src/main/java/kr/pe/elex/examples/WebConfig.java @@ -20,7 +20,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Slf4j @Configuration -@EnableWebMvc public class WebConfig implements WebMvcConfigurer { //@Autowired //private JwtInterceptor jwtInterceptor; diff --git a/settings.gradle.kts b/settings.gradle.kts index 813a454..65f7d21 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,5 +9,5 @@ rootProject.name = "spring-boot-examples" include( "file-upload", "security", "security-with-jpa", "validation", "testing", "mqtt", "websocket", "restful", "swing", "rest-doc", - "cache", "security-with-jwt", "exception" + "cache", "security-with-jwt", "exception", "i18n", "mvc" )