1. 소개

MVC(Model View Controller)는 웹 애플리케이션을 구축하는 데 널리 사용되는 디자인 패턴입니다. 몇 년 동안 현대 웹 기반 애플리케이션을 구축하기 위한 사실상의 설계 원칙이었습니다.

이 사용방법(예제)에서는 웹 페이지 및 REST API와 함께 Jakarta EE MVC 2.0을 사용하여 웹 애플리케이션을 빌드하는 방법에 대해 알아봅니다.

2. JSR-371

Jakarta MVC 2.0(이전의 JSR 371 MVC 1.0)은 Jakarta RESTful 웹 서비스 또는 JAX-RS(이전의 RESTful 웹 서비스용 Java API ) 에 구축된 작업 기반 웹 프레임워크입니다 . JSR-371은 웹 애플리케이션 구축을 보다 편리하게 만드는 추가 어노테이션으로 JAX-RS를 보완합니다.

JSR 371 또는 Jakarta MVC는 Java로 웹 애플리케이션을 개발하는 방법을 표준화합니다. 또한 주요 목표는 기존 CDI(Contexts and Dependency Injections)Bean Validation을 활용하고 JSPFacelet을 뷰 기술로 지원하는 것 입니다.

현재 Jakarta MVC 2.1 사양 작업이 진행 중이며 아마도 Jakarta EE 10 릴리스와 함께 출시될 것입니다.

3. JSR-371 어노테이션

JSR-371은 JAX-RS 어노테이션 외에 몇 가지 추가 어노테이션을 정의합니다. 이러한 모든 어노테이션은 jakarta.mvc.* 패키지 의 일부입니다 .

3.1. 자카르타.mvc.컨트롤러

@Controller 어노테이션은 리소스 MVC 컨트롤러로 표시합니다. 클래스에 사용될 때 클래스의 모든 리소스 메서드는 컨트롤러가 됩니다. 마찬가지로 리소스 메서드에서 이 어노테이션을 사용하면 해당 메서드가 컨트롤러가 됩니다. 일반적으로 메서드에서 @Controller를 정의하는 것은 동일한 클래스에서 MVC 컨트롤러와 REST API를 정의하려는 경우에 유용합니다.

예를 들어 컨트롤러를 정의해 보겠습니다.

@Path("user")
public class UserController {
    @GET
    @Produces("text/html")
    @Controller
    public String showUserForm(){
        return "user.jsp";
    }
    @GET
    @Produces("application/json")    
    public String getUserDetails(){
        return getUserDetails();
    }
}

이 클래스에는 사용자 양식( showUserForm )을 렌더링하는 @Controller 와 사용자 세부 정보 JSON( getUserDetails ) 을 반환하는 REST API가 있습니다 .

3.2. jakarta.mvc.보기

@Controller 와 마찬가지로 리소스 클래스 또는 리소스 메서드를 @View 어노테이션으로 표시할 수 있습니다. 일반적으로 void를 반환하는 리소스 메서드에는 @View가 있어야 합니다 . @View 가 있는 클래스는 void 유형 이 있는 클래스의 컨트롤러에 대한 기본 보기를 나타냅니다 .

예를 들어 @View를 사용하여 컨트롤러를 정의해 보겠습니다 .

@Controller
@Path("user")
@View("defaultModal.jsp")
public class UserController {
    @GET
    @Path("void")
    @View("userForm.jsp")
    @Produces("text/html")
    public void showForm() {
        getInitFormData();
    }

    @GET
    @Path("string")
    @Produces("text/html")
    public void showModal() {
        getModalData();
    }
}

여기서 리소스 클래스와 리소스 메서드에는 모두 @View 어노테이션이 있습니다. 컨트롤러 showForm은 보기 userForm.jsp를 렌더링합니다. 마찬가지로 showModal 컨트롤러는 리소스 클래스에 정의된 defaultModal.jsp를 렌더링합니다 .

3.3. 자카르타.mvc.binding.MvcBinding

Jakarta RESTful Webservices는 바인딩 및 유효성 검사 오류가 있는 요청을 거부합니다. 유사한 설정은 웹 페이지와 상호 작용하는 사용자에게 적합하지 않을 수 있습니다. 다행스럽게도 Jakarta MVC는 바인딩 및 유효성 검사 오류가 발생하더라도 컨트롤러를 호출합니다. 일반적으로 사용자는 데이터 바인딩 오류에 대해 잘 알고 있어야 합니다.

컨트롤러는 사람이 읽을 수 있는 유효성 검사 및 바인딩 오류 메시지를 사용자에게 표시하기 위해 BindingResult를 주입합니다. 예를 들어 @MvcBinding을 사용하여 컨트롤러를 정의해 보겠습니다 .

@Controller
@Path("user")
public class UserController {
    @MvcBinding
    @FormParam("age")
    @Min(18)
    private int age;
    @Inject
    private BindingResult bindingResult;
    @Inject
    private Models models;
    @POST
    public String processForm() {
        if (bindingResult.isFailed()) {
            models.put("errors", bindingResult.getAllMessages());
            return "user.jsp";
        }
    }
}

여기에서 사용자가 18세 미만의 연령을 입력하면 사용자는 바인딩 오류가 있는 동일한 페이지로 다시 보내집니다. EL(Expression Language)을 사용하는 user.jsp 페이지 요청 속성 오류를 검색하여 페이지에 표시할 수 있습니다.

3.4. jakarta.mvc.RedirectScoped

사용자가 데이터를 채우고 제출하는 양식(HTTP POST)을 고려하십시오. 서버는 데이터를 처리하고 사용자를 성공 페이지(HTTP GET)로 리디렉션합니다. 이 패턴은 PRG(Post-Redirect-Get) 패턴 으로 널리 알려져 있습니다 . POST와 GET 사이에 데이터를 보유하고 싶은 몇 가지 시나리오가 있습니다. 이러한 시나리오에서 모델/beans의 범위는 단일 요청을 넘어섭니다.

빈이 @RedirectScoped 로 어노테이션되면 빈의 상태는 단일 요청을 넘어선다. 그럼에도 불구하고 POST, 리디렉션 및 Get이 완료되면 상태가 소멸됩니다. @RedirectScoped 로 구분된 빈은 POST, Redirect 및 GET이 완료된 후 소멸됩니다.

예를 들어 빈 사용자에 @RedirectScoped 어노테이션이 있다고 가정합니다 .

@RedirectScoped
public class User
{
    private String id;
    private String name;
    // getters and setters
}

다음으로 이 bean을 컨트롤러에 삽입합니다.

@Controller
@Path("user")
public class UserController {
    @Inject
    private User user;
    @POST
    public String post() {
        user.setName("John Doe");
        return "redirect:/submit";
    }
    @GET
    public String get() {
        return "success.jsp";
    }
}

여기에서 bean User는 POST 및 후속 리디렉션 및 GET에 사용할 수 있습니다. 따라서 success.jsp는 EL을 사용하여 bean의 이름 속성에 액세스할 수 있습니다.

3.5. 자카르타.mvc.UriRef

리소스 메서드에만 @UriRef 어노테이션을 사용할 수 있습니다 . @UriRef를 사용하면 리소스 메서드에 이름을 제공할 수 있습니다. 컨트롤러 경로 URI 대신 이러한 이름을 사용하여 뷰에서 컨트롤러를 호출할 수 있습니다.

href 가 있는 사용자 양식이 있다고 가정합니다 .

<a href="/app/user">Clich Here</a>

Click Here를 클릭하면 GET /app/user 에 매핑된 컨트롤러가 호출됩니다  .

@GET
@UriRef("user-details")
public String getUserDetails(String userId) {
    userService.getUserDetails(userId);
} 

여기에서 컨트롤러 이름을 user-details 로 지정했습니다 . 이제 뷰에서 URI 대신 이 이름을 참조할 수 있습니다.

<a href="${mvc.uri('user-details')}">Click Here</a>

3.6. 자카르타.mvc.security.CsrfProtected

이 어노테이션은 자원 메소드를 호출하기 위해 CSRF 유효성 검증이 필요함을 지시합니다. CSRF 토큰이 잘못된 경우 클라이언트는 ForbiddenException (HTTP 403) 예외를 수신합니다. 리소스 메서드만 이 어노테이션을 가질 수 있습니다.

컨트롤러를 고려하십시오.

@POST
@Path("user")
@CsrfProtected
public String saveUser(User user) {
    service.saveUser(user);
}

컨트롤러에 @CsrfProtected 어노테이션이 있는 경우 유효한 CSRF 토큰이 포함된 경우에만 요청이 컨트롤러에 도달합니다.

4. MVC 애플리케이션 구축

다음으로 REST API와 컨트롤러를 사용하여 웹 애플리케이션을 빌드해 보겠습니다. 마지막으로 최신 버전의 Eclipse Glassfish 에 웹 애플리케이션을 배포해 보겠습니다 .

4.1. 프로젝트 생성

먼저 Maven archetype:generate를 사용하여 Jakarta MVC 2.0 프로젝트를 생성해 보겠습니다.

mvn archetype:generate 
  -DarchetypeGroupId=org.eclipse.krazo
  -DarchetypeArtifactId=krazo-jakartaee9-archetype
  -DarchetypeVersion=2.0.0 -DgroupId=com.baeldung
  -DartifactId=krazo -DkrazoImpl=jersey

위의 원형은 다음과 같이 필요한 아티팩트가 있는 maven 프로젝트를 생성합니다.

폴더 구조

또한 생성된 pom.xml 에는 jakarta.platform , jakarta.mvcorg.eclipse.krazo 의존성이 포함되어 있습니다 .

<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-web-api</artifactId>
    <version>9.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>jakarta.mvc</groupId>
    <artifactId>jakarta.mvc-api</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.krazo</groupId>
    <artifactId>krazo-jersey</artifactId>
    <version>2.0.0</version>
</dependency>

4.2. 컨트롤러

다음으로 양식을 표시하고 사용자 세부 정보를 저장하기 위한 컨트롤러와 사용자 세부 정보를 가져오기 위한 API를 정의해 보겠습니다. 그러나 먼저 애플리케이션 경로를 정의해 보겠습니다.

@ApplicationPath("/app")
public class UserApplication extends Application {
}

애플리케이션 경로는 /app 로 정의됩니다 . 다음으로 사용자를 사용자 세부 정보 양식으로 전달하는 컨트롤러를 정의해 보겠습니다.

@Path("users")
public class UserController {
    @GET
    @Controller
    public String showForm() {
        return "user.jsp";
    }
}

다음으로 WEB-INF/views 에서 user.jsp 보기를 만들고 애플리케이션을 빌드 및 배포할 수 있습니다.

mvn clean install glassfish:deploy

Glassfish Maven 플러그인은 포트 8080에서 빌드, 배포 및 실행됩니다. 성공적으로 배포한 후 브라우저를 열고 URL을 누를 수 있습니다.

http://localhost:8080/mvc-2.0/app/users :

양식 데이터

다음으로 양식 제출 작업을 처리하는 HTTP POST를 정의해 보겠습니다.

@POST
@Controller
public String saveUser(@Valid @BeanParam User user) {   
    return "redirect:users/success";
}

이제 사용자가 만들기 버튼을 클릭하면 컨트롤러가 POST 요청을 처리하고 사용자를 성공 페이지로 리디렉션합니다.

성공

Jakarta Validations, CDI 및 @MvcBinding을 사용하여 양식 유효성 검사를 제공합니다.

@Named("user")
public class User implements Serializable {

    @MvcBinding
    @Null
    private String id;

    @MvcBinding
    @NotNull
    @Size(min = 1, message = "Name cannot be blank")
    @FormParam("name")
    private String name;
    // other validations with getters and setters 
}

양식 유효성 검사가 완료되면 바인딩 오류를 확인하겠습니다. 바인딩 오류가 있는 경우 유효성 검사 메시지를 사용자에게 표시해야 합니다. 이를 위해 BindingResult를 주입하여 잘못된 양식 매개변수를 처리해 보겠습니다. saveUser 메서드를 업데이트해 보겠습니다 .

@Inject
private BindingResult bindingResult;

public String saveUser(@Valid @BeanParam User user) {
    if (bindingResult.isFailed()) {
        models.put("errors", bindingResult.getAllErrors());
        return "user.jsp";
    }  
    return "redirect:users/success";
}

검증이 완료된 상태에서 사용자가 필수 매개변수 없이 양식을 제출하면 검증 오류가 표시됩니다.

검증

다음으로 @CsrfProtected 를 사용하여 CSRF 공격으로부터 POST 메서드를 보호해 보겠습니다 . saveUser 메서드에 @CsrfProtected를 추가합니다 .

@POST
@Controller
@CsrfProtected
public String saveUser(@Valid @BeanParam User user) {
}

다음으로 만들기 버튼을 클릭해 보겠습니다 .

403

컨트롤러가 CSRF 공격으로부터 보호되면 클라이언트는 항상 CSRF 토큰을 전달해야 합니다. 따라서 모든 요청에 ​​CSRF 토큰을 추가하는 숨겨진 필드를 user.jsp 에 추가해 보겠습니다 .

<input type="hidden" name="${mvc.csrf.name}" value="${mvc.csrf.token}"/>

마찬가지로 지금 REST API를 개발해 보겠습니다 .

@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getUsers() {
    return users;
}

이 HTTP GET API는 사용자 List을 반환합니다.

5. 결론

이 기사에서는 Jakarta MVC 2.0에 대해 알아보고 Eclipse Krazo를 사용하여 웹 애플리케이션 및 REST API를 개발하는 방법에 대해 알아보았습니다. 우리는 MVC 2.0이 Java에서 MVC 기반 웹 애플리케이션을 구축하는 방식을 어떻게 표준화하는지 살펴보았습니다.

항상 그렇듯이 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .

res – REST with Spring (eBook) (everywhere)