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의 아키텍처는 매우 간단합니다.
![](https://www.baeldung.com/wp-content/uploads/2019/01/architecture.png)
항상 동일한 수명주기를 따릅니다.
- Netty는 요청을받습니다.
- 미들웨어가 실행 됨 (선택 사항)
- WebHooks가 실행됩니다 (선택 사항).
- 라우팅이 수행됩니다.
- 응답이 클라이언트로 전송됩니다.
- 대청소
다음 섹션에서 위의 기능을 살펴 보겠습니다.
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.css 는 http : // 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");
}
분명히 Long 및 String 유형에도 동일한 방법을 사용할 수 있습니다.
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 , Pebble 및 Velocity) 중에서 선택하거나 원하는 다른 템플릿을 가져 오기위한 래퍼를 만들 수도 있습니다.
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.devMode 가 true 인 경우 스택 추적도 웹 페이지에 표시됩니다.
그러나 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 색상을 올바르게 표시하지 않고 대신 코드를 표시합니다.
![](https://www.baeldung.com/wp-content/uploads/2019/01/Screenshot-from-2019-01-08-23-43-10.png)
다행히도 콘솔 확장에 ANSI 이스케이프를 설치하면 문제가 해결됩니다.
![](https://www.baeldung.com/wp-content/uploads/2019/01/Screenshot-from-2019-01-08-23-44-25.png)
17.2. IntelliJ IDEA
IntelliJ IDEA는 기본적으로 ANSI 색상으로 작동합니다. 따라서 프로젝트를 생성하고 App 파일을 마우스 오른쪽 버튼으로 클릭 한 다음 Run 'App.main ()'을 실행하는 것으로 충분합니다 ( Ctrl + Shift + F10 을 누르는 것과 동일 ).
![](https://www.baeldung.com/wp-content/uploads/2019/01/Screenshot-from-2019-01-12-00-44-01.png)
17.3. Visual Studio 코드
이전에 Java Extension Pack을 설치하여 널리 사용되는 비 Java 중심 IDE 인 VSCode를 사용할 수도 있습니다 .
Ctrl + F5 를 누르면 프로젝트가 실행됩니다.
![](https://www.baeldung.com/wp-content/uploads/2019/01/Screenshot-from-2019-01-12-00-59-43.png)
18. 결론
Blade를 사용하여 작은 MVC 애플리케이션을 만드는 방법을 살펴 보았습니다.
전체 문서 는 중국어로만 제공됩니다. 주로 중국에서 확산에도 불구하고, 덕분에 자사의 중국 기원은 , 저자는 최근 API를 번역에 영어 프로젝트의 핵심 기능을 문서화 GitHub의를 .