1. 개요
Blade 는 작은 Java 8+ MVC 프레임워크로, 독립적이고 생산적이며 우아하고 직관적이며 초고속이라는 몇 가지 명확한 목표를 염두에 두고 처음부터 구축되었습니다.
Node의 Express , Python의 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을 만드는 방법 에 설명되어 있습니다 .
간단히 하기 위해 pom.xml 에서 가져온 모든 JAR을 분해한 다음 모든 클래스를 단일 uber-JAR에 함께 묶는 Maven 어셈블리 플러그인 기술을 사용합니다 .
2.2. 블레이드 애플리케이션 실행
Blade는 놀라운 비동기 이벤트 기반 네트워크 애플리케이션 프레임워크인 Netty를 기반으로 합니다 . 따라서 블레이드 기반 애플리케이션을 실행하기 위해 외부 애플리케이션 서버나 서블릿 컨테이너가 필요하지 않습니다. JRE로 충분합니다.
java -jar target/sample-blade-app.jar
그 후에 응용 프로그램은 http://localhost:9000 URL에서 액세스할 수 있습니다.
3. 아키텍처 이해
Blade의 아키텍처는 매우 간단합니다.
항상 동일한 수명 주기를 따릅니다.
- Netty가 요청을 받습니다.
- 미들웨어가 실행됩니다(선택 사항).
- WebHook이 실행됩니다(선택 사항).
- 라우팅이 수행됩니다.
- 응답이 클라이언트로 전송됩니다.
- 대청소
다음 섹션에서 위의 기능을 살펴보겠습니다.
4. 라우팅
요컨대 MVC의 라우팅은 URL과 컨트롤러 간의 바인딩을 만드는 데 사용되는 메커니즘입니다.
블레이드는 기본 경로와 어노테이션이 있는 경로의 두 가지 유형의 경로를 제공합니다.
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. 정적 리소스
블레이드는 필요한 경우 정적 리소스를 /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. WebJar 사용
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 요청
블레이드는 서블릿 사양을 기반으로 하지 않기 때문에 인터페이스 Request 및 클래스 HttpRequest 와 같은 개체는 우리가 익숙한 것과 약간 다릅니다.
6.1. 양식 매개변수
양식 매개변수를 읽을 때 Blade는 쿼리 메소드의 결과에서 Java의 Optional을 최대한 활용합니다 (아래의 모든 메소드는 Optional 객체를 반환함).
- 쿼리(문자열 이름)
- queryInt(문자열 이름)
- queryLong(문자열 이름)
- queryDouble(문자열 이름)
대체 값으로도 사용할 수 있습니다.
- 문자열 쿼리(문자열 이름, 문자열 defaultValue)
- int queryInt(문자열 이름, int defaultValue)
- 긴 queryLong(문자열 이름, 긴 defaultValue)
- double queryDouble(문자열 이름, double defaultValue)
automapped 속성을 통해 양식 매개변수를 읽을 수 있습니다.
@PostRoute("/save")
public void formParams(@Param String username){
// ...
}
또는 요청 개체에서:
@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. 데이터 바인딩
블레이드는 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);
반면 키 매개변수만 받는 동일한 메서드는 접근자입니다.
String requestVal = request.attribute("request-val");
String sessionVal = session.attribute("session-val"); //It's an Integer
흥미로운 기능은 Generic 반환 유형 <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()
- 문자열 콘텐츠 유형()
- 문자열 사용자 에이전트()
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>");
마지막으로 String을 사용하여 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. 템플릿 렌더링