그날그날메모

블레이드 – 완벽한 사용방법(예제) 북

Java

블레이드 – 완벽한 사용방법(예제) 북

그날그날메모 2021. 4. 21. 20:51

1. 개요

Blade 는 몇 가지 명확한 목표를 염두에두고 처음부터 구축 된 작은 Java 8+ MVC 프레임 워크입니다. 즉, 독립적이고 생산적이며 우아하고 직관적이며 매우 빠릅니다.

Node 's Express , Python 's Flask , Golang의 Macaron / Martini 등 다양한 프레임 워크가 디자인에 영감을주었습니다 .

Blade는 또한 야심 차게 큰 프로젝트 인 Let 's Blade의 일부입니다 . 여기에는 템플릿에서 간단한 데이터베이스 연결에 이르기까지 Captcha 생성에서 JSON 변환에 이르기까지 다른 작은 라이브러리의 이기종 컬렉션이 포함됩니다.

그러나이 예제에서는 MVC에만 초점을 맞출 것입니다.

2. 시작하기

먼저 빈 Maven 프로젝트를 만들고 pom.xml최신 Blade MVC 의존성추가해 보겠습니다 .

<dependency>
    <groupId>com.bladejava</groupId>
    <artifactId>blade-mvc</artifactId>
    <version>2.0.14.RELEASE</version>
</dependency>

2.1. 블레이드 애플리케이션 번들링

우리의 앱은 JAR로 생성되므로 WAR에서와 같이 / lib 폴더 가 없습니다 . 결과적으로 이로 인해 우리가 필요로 할 수있는 다른 JAR과 함께 blade-mvc JAR을 앱 에 제공하는 방법에 대한 문제가 발생합니다 .

이 작업을 수행하는 다양한 방법은 각각 장단점이 있으며 Maven을 사용하여 실행 가능한 JAR을 만드는 방법 사용방법(예제)에 설명되어 있습니다.

간단하게 하기 위해 Maven Assembly Plugin 기술을 사용합니다.이 기술pom.xml 에서 가져온 모든 JAR을 분해 한 다음 모든 클래스를 단일 uber-JAR에 함께 묶습니다.

2.2. 블레이드 애플리케이션 실행

Blade는 놀라운 비동기 이벤트 기반 네트워크 애플리케이션 프레임 워크 인 Netty를 기반으로합니다 . 따라서 블레이드 기반 애플리케이션을 실행하기 위해 외부 애플리케이션 서버 나 서블릿 컨테이너가 필요하지 않습니다. JRE이면 충분합니다.

java -jar target/sample-blade-app.jar

그 후 http : // localhost : 9000 URL 에서 애플리케이션에 액세스 할 수 있습니다 .

3. 아키텍처 이해

Blade의 아키텍처는 매우 간단합니다.

항상 동일한 수명주기를 따릅니다.

  1. Netty는 요청을받습니다.
  2. 미들웨어가 실행 됨 (선택 사항)
  3. WebHooks가 실행됩니다 (선택 사항).
  4. 라우팅이 수행됩니다.
  5. 응답이 클라이언트로 전송됩니다.
  6. 대청소

다음 섹션에서 위의 기능을 살펴 보겠습니다.

4. 라우팅

간단히 말해 MVC의 라우팅은 URL과 컨트롤러 간의 바인딩을 만드는 데 사용되는 메커니즘입니다.

Blade는 기본 경로와 어노테이션이 추가 된 경로의 두 가지 유형을 제공합니다.

4.1. 기본 경로

기본 경로는 마이크로 서비스 또는 최소 웹 애플리케이션과 같은 매우 작은 소프트웨어를위한 것입니다.

Blade.of()
  .get("/basic-routes-example", ctx -> ctx.text("GET called"))
  .post("/basic-routes-example", ctx -> ctx.text("POST called"))
  .put("/basic-routes-example", ctx -> ctx.text("PUT called"))
  .delete("/basic-routes-example", ctx -> ctx.text("DELETE called"))
  .start(App.class, args);

경로를 등록하는 데 사용되는 메서드의 이름은 요청을 전달하는 데 사용되는 HTTP 동사에 해당합니다. 저것과 같이 쉬운.

이 경우 텍스트를 반환하지만이 사용방법(예제)의 뒷부분에서 볼 수 있듯이 페이지를 렌더링 할 수도 있습니다.

4.2. 어노테이션이 달린 경로

물론보다 현실적인 사용 사례를 위해 어노테이션을 사용하여 필요한 모든 경로를 정의 할 수 있습니다. 이를 위해 별도의 클래스를 사용해야합니다.

먼저 @Path 어노테이션을 통해 컨트롤러를 생성해야합니다.이 어노테이션은 시작하는 동안 Blade에서 스캔됩니다.

그런 다음 인터셉트하려는 HTTP 메서드와 관련된 경로 어노테이션을 사용해야합니다.

@Path
public class RouteExampleController {    
    
    @GetRoute("/routes-example") 
    public String get(){ 
        return "get.html"; 
    }
    
    @PostRoute("/routes-example") 
    public String post(){ 
        return "post.html"; 
    }
    
    @PutRoute("/routes-example") 
    public String put(){ 
        return "put.html"; 
    }
    
    @DeleteRoute("/routes-example") 
    public String delete(){ 
        return "delete.html"; 
    }
}

간단한 @Route 어노테이션을 사용하고 HTTP 메서드를 매개 변수로 지정할 수도 있습니다 .

@Route(value="/another-route-example", method=HttpMethod.GET) 
public String anotherGet(){ 
    return "get.html" ; 
}

반면에 메소드 매개 변수를 입력하지 않으면 경로는 동사에 관계없이 해당 URL 에 대한 모든 HTTP 호출을 가로 챕니다 .

4.3. 매개 변수 주입

경로에 매개 변수를 전달하는 방법에는 여러 가지가 있습니다. 문서의 몇 가지 예 들어 살펴 보겠습니다 .

  • 양식 매개 변수 :
@GetRoute("/home")
public void formParam(@Param String name){
    System.out.println("name: " + name);
}
  • 편안한 매개 변수 :
@GetRoute("/users/:uid")
public void restfulParam(@PathParam Integer uid){
    System.out.println("uid: " + uid);
}
  • 파일 업로드 매개 변수 :
@PostRoute("/upload")
public void fileParam(@MultipartParam FileItem fileItem){
    byte[] file = fileItem.getData();
}
  • 헤더 매개 변수 :
@GetRoute("/header")
public void headerParam(@HeaderParam String referer){
    System.out.println("Referer: " + referer);
}
  • 쿠키 매개 변수 :
@GetRoute("/cookie")
public void cookieParam(@CookieParam String myCookie){
    System.out.println("myCookie: " + myCookie);
}
  • 본문 매개 변수 :
@PostRoute("/bodyParam")
public void bodyParam(@BodyParam User user){
    System.out.println("user: " + user.toString());
}
  • 라우트에 속성을 전송하여 호출되는 값 오브젝트 매개 변수 :
@PostRoute("/voParam")
public void voParam(@Param User user){
    System.out.println("user: " + user.toString());
}
<form method="post">
    <input type="text" name="age"/>
    <input type="text" name="name"/>
</form>

5. 정적 리소스

Blade는 필요한 경우 단순히 / resources / static 폴더에 넣어서 정적 리소스를 제공 할 수도 있습니다 .

예를 들어  src / main / resources / static / app.csshttp : // localhost : 9000 / static / app.css 에서 사용할 수 있습니다  .

5.1. 경로 사용자 지정

프로그래밍 방식으로 하나 이상의 정적 경로를 추가하여이 동작을 조정할 수 있습니다.

blade.addStatics("/custom-static");

src / main / resources / application.properties 파일을 편집하여 구성을 통해 동일한 결과를 얻을 수 있습니다 .

mvc.statics=/custom-static

5.2. 자원 List 활성화

Security상의 이유로 기본적으로 해제 된 기능인 정적 폴더의 콘텐츠 List을 허용 할 수 있습니다.

blade.showFileList(true);

또는 구성에서 :

mvc.statics.show-list=true

이제 http : // localhost : 9000 / custom-static /열어  폴더의 내용을 표시 할 수 있습니다.

5.3. WebJars 사용

WebJars 소개 사용방법(예제) 에서 볼 수 있듯이 JAR로 패키지 된 정적 리소스도 실행 가능한 옵션입니다.

Blade는 / webjars / 경로 아래에 자동으로 노출됩니다 .

예를 들어 pom.xml 에서 Bootstrap가져 오겠습니다 .

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.2.1</version>
</dependency>

결과적으로 http : // localhost : 9000 / webjars / bootstrap / 4.2.1 / css / bootstrap.css에서 사용할 수 있습니다.

6. HTTP 요청

Blade는 Servlet Specification을 기반으로하지 않기 때문에 인터페이스 Request 및 클래스 HttpRequest같은 객체 는 우리가 익숙한 객체와 약간 다릅니다.

6.1. 양식 매개 변수

양식 매개 변수를 읽을 때 Blade는 쿼리 메소드의 결과에서 Java의 Optional잘 활용 합니다 (아래의 모든 메소드는 Optional  객체를 반환  합니다).

  • query (문자열 이름)
  • queryInt (문자열 이름)
  • queryLong (문자열 이름)
  • queryDouble (문자열 이름)

대체 값으로도 사용할 수 있습니다.

  • 문자열 쿼리 (문자열 이름, 문자열 defaultValue)
  • int queryInt (문자열 이름, int defaultValue)
  • long queryLong (문자열 이름, long defaultValue)
  • double queryDouble (문자열 이름, double defaultValue)

automapped 속성을 통해 양식 매개 변수를 읽을 수 있습니다.

@PostRoute("/save")
public void formParams(@Param String username){
    // ...
}

또는 Request 객체에서 :

@PostRoute("/save")
public void formParams(Request request){
    String username = request.query("username", "Baeldung");
}

6.2. JSON 데이터

이제 JSON 객체를 POJO에 매핑하는 방법을 살펴 보겠습니다.

curl -X POST http://localhost:9000/users -H 'Content-Type: application/json' \ 
  -d '{"name":"Baeldung","site":"baeldung.com"}'

POJO ( 가독성을 위해 Lombok 으로 어노테이션 달기 ) :

public class User {
    @Getter @Setter private String name;
    @Getter @Setter private String site;
}

다시,이 값은 주입 된 속성으로 사용할 수 있습니다.

@PostRoute("/users")
public void bodyParams(@BodyParam User user){
    // ...
}

그리고 요청에서 :

@PostRoute("/users")
public void bodyParams(Request request) {
    String bodyString = request.bodyToString();
}

6.3. RESTful 매개 변수

localhost : 9000 / user / 42 와 같은 예쁜 URL의 RESTFul 매개 변수 도 일류 시민입니다.

@GetRoute("/user/:id")
public void user(@PathParam Integer id){
    // ...
}

평소와 같이 필요할 때 Request 객체를 사용할 수 있습니다.

@GetRoute("/user")
public void user(Request request){
    Integer id = request.pathInt("id");
}

분명히 LongString 유형에도 동일한 방법을 사용할 수 있습니다.

6.4. 데이터 바인딩

Blade는 JSON 및 양식 바인딩 매개 변수를 모두 지원하며이를 모델 객체에 자동으로 연결합니다.

@PostRoute("/users")
public void bodyParams(User user){}

6.5. 요청 및 세션 속성

요청 및  세션 에서 개체를 읽고 쓰기위한 API  는 명확합니다.

키와 값을 나타내는 두 개의 매개 변수가있는 메서드는 다른 컨텍스트에 값을 저장하는 데 사용할 수있는 뮤 테이터입니다.

Session session = request.session();
request.attribute("request-val", "Some Request value");
session.attribute("session-val", 1337);

반면에 key 매개 변수 만 받아들이는 동일한 메서드가 접근 자입니다.

String requestVal = request.attribute("request-val");
String sessionVal = session.attribute("session-val"); //It's an Integer

흥미로운 기능은 Generic return type <T> T 이며 결과를 캐스팅 할 필요가 없습니다.

6.6. 헤더

반대로 요청 헤더는 요청에서만 읽을 수 있습니다.

String header1 = request.header("a-header");
String header2 = request.header("a-safe-header", "with a default value");
Map<String, String> allHeaders = request.headers();

6.7. 유용

다음 유틸리티 메서드도 즉시 사용할 수 있으며 추가 설명이 필요하지 않을 정도로 분명합니다.

  • 부울 isIE ()
  • 부울 isAjax ()
  • 문자열 contentType ()
  • 문자열 userAgent ()

6.8. 쿠키 읽기

특히 Optional <Cookie>를 읽을 때 Request 개체가 쿠키를 처리하는 데 어떻게 도움이  되는지 살펴 보겠습니다 .

Optional<Cookie> cookieRaw(String name);

쿠키가없는 경우 적용 할 기본값을 지정 하여 문자열 로 가져올 수도  있습니다.

String cookie(String name, String defaultValue);

마지막으로 모든 쿠키를 한 번에 읽을 수있는 방법입니다 ( 는 쿠키의 이름이고 은 쿠키의 값입니다).

Map<String, String> cookies = request.cookies();

7. HTTP 응답

Request 로 수행 한 것과 유사하게 , 단순히 라우팅 메서드의 매개 변수로 선언 하여 Response 객체에 대한 참조를 얻을 수 있습니다 .

@GetRoute("/")
public void home(Response response) {}

7.1. 간단한 출력

200 HTTP 코드 및 적절한 Content-Type과 함께 편리한 출력 방법 중 하나를 통해 간단한 출력을 호출자에게 쉽게 보낼 수 있습니다.

첫째, 일반 텍스트를 보낼 수 있습니다.

response.text("Hello World!");

둘째, HTML을 생성 할 수 있습니다.

response.html("<h1>Hello World!</h1>");

셋째, 마찬가지로 XML을 생성 할 수 있습니다.

response.xml("<Msg>Hello World!</Msg>");

마지막으로 문자열을 사용하여 JSON을 출력 할 수 있습니다 .

response.json("{\"The Answer\":42}");

그리고 POJO에서도 자동 JSON 변환을 활용합니다.

User user = new User("Baeldung", "baeldung.com"); 
response.json(user);

7.2. 파일 출력

서버에서 파일을 다운로드하는 것은 이보다 쉬울 수 없습니다.

response.download("the-file.txt", "/path/to/the/file.txt");

첫 번째 매개 변수는 다운로드 할 파일의 이름을 설정하고 두 번째 매개 변수 ( 여기서는 String으로 구성된 File 객체 )는 서버의 실제 파일에 대한 경로를 나타냅니다.

7.3. 템플릿 렌더링

블레이드는 템플릿 엔진을 통해 페이지를 렌더링 할 수도 있습니다.

response.render("admin/users.html");

템플릿 기본 디렉토리는 src / main / resources / templates / 이므로 이전 한 줄짜리 파일은  src / main / resources / templates / admin / users.html 파일을 찾습니다 .

나중에 템플릿 섹션 에서 이에 대해 자세히 알아볼 것 입니다.

7.4. 리디렉션

리디렉션이란 302 HTTP 코드를 두 번째 GET을 따르는 URL과 함께 브라우저에 보내는 것을 의미합니다.

다른 경로 또는 외부 URL로 리디렉션 할 수도 있습니다.

response.redirect("/target-route");

7.5. 쿠키 작성

이 시점에서 Blade의 단순함에 익숙해 져야합니다. 따라서 한 줄의 코드로 만료되지 않는 쿠키를 작성하는 방법을 살펴 보겠습니다.

response.cookie("cookie-name", "Some value here");

실제로 쿠키를 제거하는 것도 똑같이 간단합니다.

response.removeCookie("cookie-name");

7.6. 기타 작업

마지막으로 Response 객체는 헤더 작성, Content-Type 설정, 상태 코드 설정 등과 같은 작업을 수행 할 수있는 몇 가지 다른 방법을 제공합니다.

그중 몇 가지를 간단히 살펴 보겠습니다.

  • 응답 상태 (int status)
  • 헤더 매핑 ()
  • 응답 notFound ()
  • 쿠키 매핑 ()
  • 응답 contentType (문자열 contentType)
  • void body (@NonNull byte [] 데이터)
  • 응답 헤더 (문자열 이름, 문자열 값)

8. 웹훅

WebHook은 라우팅 메서드를 실행하기 전과 후에 코드를 실행할 수있는 인터셉터 입니다.

WebHook 기능 인터페이스 를 구현 하고 before () 메서드를 재정 의하여 WebHook을 만들 수 있습니다 .

@FunctionalInterface
public interface WebHook {

    boolean before(RouteContext ctx);

    default boolean after(RouteContext ctx) {
        return true;
    }
}

보시다시피 after () 는 기본 메서드이므로 필요할 때만 재정의합니다.

8.1. 모든 요청 가로 채기

@Bean 어노테이션은 IOC의 컨테이너와 클래스를 스캔 할 수있는 프레임 워크를 알려줍니다.

어노테이션이 달린 WebHook은 결과적으로 모든 URL에 대한 요청을 가로 채 전 세계적으로 작동합니다.

@Bean
public class BaeldungHook implements WebHook {

    @Override
    public boolean before(RouteContext ctx) {
        System.out.println("[BaeldungHook] called before Route method");
        return true;
    }
}

8.2. URL로 좁히기

또한 특정 URL을 가로 채서 해당 경로 메서드 주변에서만 코드를 실행할 수 있습니다.

Blade.of()
  .before("/user/*", ctx -> System.out.println("Before: " + ctx.uri()));
  .start(App.class, args);

8.3. 미들웨어

미들웨어는 표준 WebHook보다 먼저 실행되는 우선 순위가 지정된 WebHook입니다.

public class BaeldungMiddleware implements WebHook {

    @Override
    public boolean before(RouteContext context) {
        System.out.println("[BaeldungMiddleware] called before Route method and other WebHooks");
        return true;
    }
}

@Bean 어노테이션 없이 정의한 다음 use ()를 통해 선언적으로 등록 하면됩니다 .

Blade.of()
  .use(new BaeldungMiddleware())
  .start(App.class, args);

또한 Blade에는 다음과 같은 Security 관련 내장 미들웨어가 함께 제공되며 이름은 자명해야합니다.

9. 구성

Blade에서는 모든 것이 규칙에 따라 즉시 작동하기 때문에 구성은 전적으로 선택 사항입니다. 그러나 src / main / resources / application.properties 파일 내에서 기본 설정을 사용자 정의하고 새 속성을 도입 할 수 있습니다 .

9.1. 구성 읽기

설정을 사용할 수없는 경우 기본값을 지정하거나 지정하지 않고 다른 방법으로 구성을 읽을 수 있습니다.

  • 시작하는 동안 :
Blade.of()
  .on(EventType.SERVER_STARTED, e -> {
      Optional<String> version = WebContext.blade().env("app.version");
  })
  .start(App.class, args);
  • 경로 내부 :
@GetRoute("/some-route")
public void someRoute(){
    String authors = WebContext.blade().env("app.authors","Unknown authors");
}
  • 커스텀 로더에서 BladeLoader 인터페이스 를 구현하고 load () 메서드를 재정의 하고 클래스에 @Bean 어노테이션을 추가합니다 .
@Bean
public class LoadConfig implements BladeLoader {

    @Override
    public void load(Blade blade) {
        Optional<String> version = WebContext.blade().env("app.version");
        String authors = WebContext.blade().env("app.authors","Unknown authors");
    }
}

9.2. 구성 속성

이미 구성되었지만 사용자 정의 할 준비가 된 여러 설정은 유형별로 그룹화되어이 주소 에 3 열 테이블 (이름, 설명, 기본값)로 나열됩니다 . 번역이 설정 이름을 잘못 대문자로 표시한다는 사실에주의 하면서 번역 된 페이지를 참조 할 수도 있습니다. 실제 설정은 완전히 소문자입니다.

접두사별로 구성 설정을 그룹화하면 한 번에 모두를 맵으로 읽을 수 있으므로 다음과 같이 많은 경우 유용합니다.

Environment environment = blade.environment();
Map<String, Object> map = environment.getPrefix("app");
String version = map.get("version").toString();
String authors = map.get("authors","Unknown authors").toString();

9.3. 여러 환경 처리

앱을 다른 환경에 배포 할 때 다른 설정 (예 : 데이터베이스 연결과 관련된 설정)을 지정해야 할 수 있습니다. application.properties 파일 을 수동으로 교체하는 대신 Blade는 다양한 환경에 맞게 앱을 구성하는 방법을 제공합니다. 모든 개발 설정과 함께 application.properties유지 한 다음 다른 설정 만 포함하는 application-prod.properties 와 같은 동일한 폴더에 다른 파일만들 수 있습니다 .

시작하는 동안 사용할 환경을 지정할 수 있으며 프레임 워크는 application-prod.properties 의 가장 구체적인 설정 과 기본 application.properties 파일 의 다른 모든 설정을 사용하여 파일을 병합 합니다.

java -jar target/sample-blade-app.jar --app.env=prod

10. 템플릿

Blade의 템플릿은 모듈 방식입니다. 매우 기본적인 템플릿 엔진을 통합하고 있지만 뷰를 전문적으로 사용하려면 외부 템플릿 엔진에 의존해야합니다. 그런 다음 GitHub blade-template-engines 저장소에서 사용할 수 있는 엔진 ( FreeMarker , Jetbrick , PebbleVelocity) 중에서 선택하거나 원하는 다른 템플릿을 가져 오기위한 래퍼를 만들 수도 있습니다.

Blade의 저자는 또 다른 똑똑한 중국 프로젝트 인 Jetbrick을 제안 합니다.

10.1. 기본 엔진 사용

기본 템플릿은 $ {} 표기법을 통해 다른 컨텍스트의 변수를 구문 분석하여 작동합니다 .

<h1>Hello, ${name}!</h1>

10.2. 외부 엔진 연결

다른 템플릿 엔진으로 쉽게 전환 할 수 있습니다! 엔진의 (블레이드 래퍼) 의존성을 가져옵니다.

<dependency>
    <groupId>com.bladejava</groupId>
    <artifactId>blade-template-jetbrick</artifactId>
    <version>0.1.3</version>
</dependency>

이 시점에서 프레임 워크가 해당 라이브러리를 사용하도록 지시하는 간단한 구성을 작성하는 것으로 충분합니다.

@Bean
public class TemplateConfig implements BladeLoader {

    @Override
    public void load(Blade blade) {
        blade.templateEngine(new JetbrickTemplateEngine());
    }
}

결과적으로 이제 src / main / resources / templates / 아래의 모든 파일 이 새 엔진으로 구문 분석되며, 구문은이 예제의 범위를 벗어납니다.

10.3. 새 엔진 포장

새 템플릿 엔진을 래핑하려면 단일 클래스를 만들어야합니다.이 클래스는 TemplateEngine 인터페이스를 구현 하고 render () 메서드를 재정의 해야합니다 .

void render (ModelAndView modelAndView, Writer writer) throws TemplateException;

이를 위해 실제 Jetbrick 래퍼의 코드를 살펴보고 그것이 의미하는 바를 알 수 있습니다.

11. 로깅

블레이드는 slf4j-api 를 로깅 인터페이스로 사용합니다.

여기에는 blade-log 라는 이미 구성된 로깅 구현도 포함됩니다 . 따라서 우리는 아무것도 가져올 필요가 없습니다. 로거 를 정의하기 만하면있는 그대로 작동합니다 .

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);

11.1. 통합 로거 사용자 지정

기본 구성을 수정하려면 다음 매개 변수를 시스템 속성으로 조정해야합니다.

  • 로깅 수준 ( "추적", "디버그", "정보", "경고"또는 "오류"일 수 있음) :
# Root Logger
com.blade.logger.rootLevel=info

# Package Custom Logging Level
com.blade.logger.somepackage=debug

# Class Custom Logging Level
com.blade.logger.com.baeldung.sample.SomeClass=trace
  • 표시되는 정보 :
# Date and Time
com.blade.logger.showDate=false

# Date and Time Pattern
com.blade.logger.datePattern=yyyy-MM-dd HH:mm:ss:SSS Z

# Thread Name
com.blade.logger.showThread=true

# Logger Instance Name
com.blade.logger.showLogName=true

# Only the Last Part of FQCN
com.blade.logger.shortName=true
  • 나무꾼:
# Path 
com.blade.logger.dir=./logs

# Name (it defaults to the current app.name)
com.blade.logger.name=sample

11.2. 통합 로거 제외

통합 로거가 이미 구성되어 있으면 소규모 프로젝트를 시작하는 데 매우 편리하지만 다른 라이브러리가 자체 로깅 구현을 가져 오는 경우 쉽게 끝날 수 있습니다. 그리고이 경우 충돌을 피하기 위해 통합 된 것을 제거 할 수 있습니다.

<dependency>
    <groupId>com.bladejava</groupId>
    <artifactId>blade-mvc</artifactId>
    <version>${blade.version}</version>
    <exclusions>
        <exclusion>
            <groupId>com.bladejava</groupId>
            <artifactId>blade-log</artifactId>
        </exclusion>
    </exclusions>
</dependency>

12. 사용자 정의

12.1. 사용자 지정 예외 처리

예외 처리기는 기본적으로 프레임 워크에 내장되어 있습니다. 콘솔에 예외를 인쇄하고 app.devModetrue 인 경우 스택 추적도 웹 페이지에 표시됩니다.

그러나 DefaultExceptionHandler 클래스를 확장 하는 @Bean 을 정의하여 특정 방식으로 예외를 처리 할 수 ​​있습니다 .

@Bean
public class GlobalExceptionHandler extends DefaultExceptionHandler {

    @Override
    public void handle(Exception e) {
        if (e instanceof BaeldungException) {
            BaeldungException baeldungException = (BaeldungException) e;
            String msg = baeldungException.getMessage();
            WebContext.response().json(RestResponse.fail(msg));
        } else {
            super.handle(e);
        }
    }
}

12.2. 사용자 정의 오류 페이지

마찬가지로 오류 404 – 찾을 수 없음500 – 내부 서버 오류 는 스키니 기본 페이지를 통해 처리됩니다.

다음 설정으로 application.properties 파일 에서 선언하여 프레임 워크가 자체 페이지를 사용하도록 할 수 있습니다 .

mvc.view.404=my-404.html
mvc.view.500=my-500.html

물론 이러한 HTML 페이지는 src / main / resources / templates 폴더에 있어야합니다.

500 개 내에서 특수 변수를 통해 예외 메시지stackTrace검색 할 수도 있습니다 .

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>500 Internal Server Error</title>
    </head>
    <body>
        <h1> Custom Error 500 Page </h1>
        <p> The following error occurred: "<strong>${message}</strong>"</p>
        <pre> ${stackTrace} </pre>
    </body>
</html>

13. 예약 된 작업

프레임 워크의 또 다른 흥미로운 기능은 메서드 실행을 예약 할 수 있다는 것입니다.

@Schedule 어노테이션을 사용하여 @Bean 클래스 의 메소드에 어노테이션을 작성하면 가능합니다 .

@Bean
public class ScheduleExample {

    @Schedule(name = "baeldungTask", cron = "0 */1 * * * ?")
    public void runScheduledTask() {
        System.out.println("This is a scheduled Task running once per minute.");
    }
}

실제로 고전적인 cron 표현식을 사용하여 DateTime 좌표 를 지정합니다 . A Guide to Cron Expressions 에서 더 많은 것을 읽을 수 있습니다 .

나중에 TaskManager 클래스 의 정적 메서드를 이용 하여 예약 된 작업에 대한 작업을 수행 할 수 있습니다.

  • 예약 된 모든 작업 가져 오기 :
List<Task> allScheduledTasks = TaskManager.getTasks();
  • 이름으로 작업 가져 오기 :
Task myTask = TaskManager.getTask("baeldungTask");
  • 이름으로 작업 중지 :
boolean closed = TaskManager.stopTask("baeldungTask");

14. 이벤트

9.1 절에서 이미 살펴본 것처럼 사용자 지정 코드를 실행하기 전에 지정된 이벤트를 수신 할 수 있습니다.

Blade는 다음 이벤트를 즉시 제공합니다.

public enum EventType {
    SERVER_STARTING,
    SERVER_STARTED,
    SERVER_STOPPING,
    SERVER_STOPPED,
    SESSION_CREATED,
    SESSION_DESTROY,
    SOURCE_CHANGED,
    ENVIRONMENT_CHANGED
}

처음 6 개는 추측하기 쉽지만 마지막 2 개는 몇 가지 힌트가 필요합니다. ENVIRONMENT_CHANGED를 사용하면 서버가 작동 중일 때 구성 파일이 변경되면 작업을 수행 할 수 있습니다. 대신 SOURCE_CHANGED 는 아직 구현되지 않았으며 향후 사용을 위해서만 존재합니다.

세션이 생성 될 때마다 세션에 값을 입력하는 방법을 살펴 보겠습니다.

Blade.of()
  .on(EventType.SESSION_CREATED, e -> {
      Session session = (Session) e.attribute("session");
      session.attribute("name", "Baeldung");
  })
  .start(App.class, args);

15. 세션 구현

세션에 대해 말하면 기본 구현은 세션 값을 메모리에 저장합니다.

따라서 캐시, 지속성 또는 다른 것을 제공하기 위해 다른 구현으로 전환 할 수 있습니다. 예를 들어 Redis를 살펴 보겠습니다. 먼저 HttpSession 에 대한 문서에 표시된대로 Session 인터페이스 를 구현하여 RedisSession 래퍼 를 만들어야 합니다 .

그런 다음 프레임 워크에 우리가 사용하고 싶다는 사실을 알리는 문제 일뿐입니다. 사용자 정의 템플릿 엔진에 대해했던 것과 동일한 방식으로이 작업을 수행 할 수 있습니다. 유일한 차이점은 sessionType () 메서드를 호출한다는 것입니다 .

@Bean
public class SessionConfig implements BladeLoader {
 
    @Override
    public void load(Blade blade) {
        blade.sessionType(new RedisSession());
    }
}

16. 명령 줄 인수

명령 줄에서 블레이드를 실행할 때 동작을 변경하기 위해 지정할 수있는 세 가지 설정이 있습니다.

첫째, 기본적으로 로컬 0.0.0.0 루프백 인 IP 주소를 변경할 수 있습니다 .

java -jar target/sample-blade-app.jar --server.address=192.168.1.100

둘째, 기본적으로 9000 인 포트를 변경할 수도 있습니다 .

java -jar target/sample-blade-app.jar --server.port=8080

9.3 절에서 볼 수 있듯이 마지막으로, 우리는 다른 수 있도록 환경을 변경할 수 있습니다 application-XXX.properties의 인 디폴트 하나 이상 읽을 수 있도록 파일을 application.properties :

java -jar target/sample-blade-app.jar --app.env=prod

17. IDE에서 실행

모든 최신 Java IDE는 Maven 플러그인 없이도 Blade 프로젝트를 재생할 수 있습니다. IDE에서 Blade를 실행하는 것은 프레임 워크의 기능을 보여주기 위해 명시 적으로 작성된 예제 인 Blade Demo를 실행할 때 특히 유용 합니다. 그들은 모두 부모 pom을 상속하므로 독립 실행 형 앱으로 실행되도록 수동으로 조정하는 대신 IDE에서 작업을 수행하도록하는 것이 더 쉽습니다.

17.1.

Eclipse에서는 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Run as Java Application을 시작 하고 App 클래스를 선택한 다음 OK를 누르는 것으로 충분합니다 .

그러나 Eclipse의 콘솔은 ANSI 색상을 올바르게 표시하지 않고 대신 코드를 표시합니다.

다행히도 콘솔 확장에 ANSI 이스케이프를 설치하면 문제가 해결됩니다.

17.2. IntelliJ IDEA

IntelliJ IDEA는 기본적으로 ANSI 색상으로 작동합니다. 따라서 프로젝트를 생성하고 App 파일을 마우스 오른쪽 버튼으로 클릭 한 다음 Run 'App.main ()'을 실행하는 것으로 충분합니다 ( Ctrl + Shift + F10 을 누르는 것과 동일 ).

17.3. Visual Studio 코드

이전에 Java Extension Pack을 설치하여 널리 사용되는 비 Java 중심 IDE 인 VSCode를 사용할 수도 있습니다 .

Ctrl + F5누르면 프로젝트가 실행됩니다.

18. 결론

Blade를 사용하여 작은 MVC 애플리케이션을 만드는 방법을 살펴 보았습니다.

전체 문서 는 중국어로만 제공됩니다. 주로 중국에서 확산에도 불구하고, 덕분에 자사의 중국 기원은 , 저자는 최근 API를 번역에 영어 프로젝트의 핵심 기능을 문서화 GitHub의를 .

항상 그렇듯이 GitHub 에서 예제의 소스 코드를 찾을 수 있습니다 .

참고
  • https://docs.spring.io/spring-framework/docs/current/reference/html
  • https://www.baeldung.com/blade