# Java MVC 教程

原文：http://zetcode.com/java/mvc/

Java MVC 教程是 Java MVC 框架的入门教程。 我们使用 Java MVC 创建一个简单的 Web 应用，并将其部署在 Tomcat 和 Glassfish 上。

## MVC

模型视图控制器（MVC）体系结构模式将应用分为三个部分：模型，视图和控制器。 该模型表示应用中的数据，视图是数据的可视表示，控制器处理并响应事件（通常是用户操作），并且可以调用模型上的更改。 这个想法是通过引入一个中间组件：控制器，将数据访问和业务逻辑与数据表示和用户交互分开。

## Java MVC

Java MVC 是针对新的基于 Java 动作的 Web 框架的规范（JSR-371）。 它是传统的基于组件的 JSF 的替代方案。 MVC API 位于 JAX-RS 之上，并与现有的 Java EE 技术（如 CDI 和 Bean 验证）集成。 Eclipse Ozark 是 Java MVC 的实现。 它当前包含对 RESTEasy，Jersey 和 Apache CXF 的支持。

MVC 控制器是由`@Controller`装饰的 JAX-RS 资源方法。 MVC 控制器负责组合数据模型和视图（模板）以生成 Web 应用页面。 模型承载在视图中显示的数据。 使用`@Named`注解或通过注入`Models`接口创建模型。

视图定义了输出页面的结构，可以引用一个或多个模型。 视图引擎的责任是通过提取模型中的信息并生成输出页面来呈现视图。

## Tomcat 中的 Java MVC 示例

我们使用 Java MVC 创建一个简单的 Web 应用，并将其部署在 Tomcat 上。 在 JAX-RS 库中，我们选择了 Jersey。

```java
$ tree
.
├── nb-configuration.xml
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── conf
    │   │           │   └── ApplicationConfig.java
    │   │           ├── controller
    │   │           │   └── HelloController.java
    │   │           └── model
    │   │               └── Message.java
    │   ├── resources
    │   └── webapp
    │       ├── index.html
    │       ├── META-INF
    │       │   └── context.xml
    │       └── WEB-INF
    │           ├── beans.xml
    │           └── views
    │               └── hello.jsp
    └── test
        └── java

```

这是项目结构。

`pom.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>JavaMvcTomcatEx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>JavaMvcTomcatEx</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>2.26</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>    

    <dependencies>

        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>            

        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
        </dependency>       

        <dependency>
            <groupId>org.glassfish.jersey.ext.cdi</groupId>
            <artifactId>jersey-cdi1x</artifactId>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-bean-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0-EDR1</version>
        </dependency>

        <dependency>
            <groupId>org.jboss.weld.servlet</groupId>
            <artifactId>weld-servlet-shaded</artifactId>
            <version>3.0.2.Final</version>
        </dependency>              

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.2.Final</version>
        </dependency>     

        <dependency>
            <groupId>javax.mvc</groupId>
            <artifactId>javax.mvc-api</artifactId>
            <version>1.0-pr</version>
        </dependency>

        <dependency>
            <groupId>org.mvc-spec.ozark</groupId>
            <artifactId>ozark-core</artifactId>
            <version>1.0.0-m03</version>
        </dependency>        

        <dependency>
            <groupId>org.mvc-spec.ozark</groupId>
            <artifactId>ozark-jersey</artifactId>
            <version>1.0.0-m03</version>
        </dependency>          

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

```

为了在 Tomcat 上运行 Java MVC，我们需要包括 Java MVC，Jersey，Bean Validation 和 CDI 的多个依赖项。

`context.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/JavaMvcTomcatEx">

    <Resource name="BeanManager" 
              auth="Container"
              type="javax.enterprise.inject.spi.BeanManager"
              factory="org.jboss.weld.resources.ManagerObjectFactory" />

</Context>

```

在 Tomcat 的`context.xml`文件中，我们定义上下文路径并注册`Weld`的`BeanManager`工厂。

`beans.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">

</beans>

```

在`WEB-INF`目录中，我们有一个空的`beans.xml`文件。 它是 CDI 的部署描述符。 它可用于配置拦截器，装饰器和其他内容。 即使没有配置，我们也需要添加一个空的`beans.xml`来注册 CDI。

`ApplicationConfig.java`

```java
package com.zetcode.conf;

import com.zetcode.controller.HelloController;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("mvc")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> set = new HashSet<>();
        set.add(HelloController.class);
        return set;
    }
}

```

`ApplicationConfig`是应用配置类。 从 Servlet 3.0 开始，可以省略`web.xml`文件。 在 Jersey 中，我们创建一个配置类来扩展抽象`Application`并使用`@ApplicationPath`注解。 `Application`定义 JAX-RS 应用的组件并提供其他元数据。 在这里，我们注册应用所需的资源类，提供程序或属性。

```java
set.add(HelloController.class);

```

我们注册`HelloController`。

`Message.java`

```java
package com.zetcode.model;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named("message")
@RequestScoped
public class Message {

    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

```

这是一个模型类。 它保存该视图的数据。 `@Named`注解为模型命名。 我们将在视图中引用该模型。 `@RequestScoped`使模型在请求期内有效。

`HelloController.java`

```java
package com.zetcode.controller;

import com.zetcode.model.Message;
import javax.inject.Inject;
import javax.mvc.annotation.Controller;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("hello")
@Controller
public class HelloController {

    @Inject
    private Message message;

    @GET
    public String hello() {

        message.setText("Today is a sunny day");

        return "hello.jsp";
    }
}

```

用`@Controller`装饰的类是 Java MVC 控制器。 使用`@Path`，它绑定到`hello`路径段。

```java
@Inject
private Message message;

```

使用`@Inject`，我们注入了模型对象。 它将数据从控制器传送到视图。

```java
@GET
public String hello() {

    message.setText("Today is a sunny day");

    return "hello.jsp";
}

```

`hello()`方法对 GET 请求作出反应。 它将数据设置到模型并返回视图。 从控制器方法返回的字符串被解释为视图路径。 视图引擎的默认视图目录为`WEB-INF/views`。

`hello.jsp`

```java
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <p>
           The message: ${message.text}
        </p>
    </body>
</html>

```

这是视图。 它使用`${}`语法显示数据。

`index.html`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Home Page</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <p>
            <a href="mvc/hello">Get message</a>
        </p>
    </body>
</html>

```

这是一个主页。 它包含一个调用控制器的链接。

## Glassfish 中的 Java MVC 示例

要在 Glassfish 上运行该示例，我们不需要`context.xml`文件，并且需要以下三个依赖项：

```java
<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>javax.mvc</groupId>
        <artifactId>javax.mvc-api</artifactId>
        <version>1.0-pr</version>
    </dependency>
    <dependency>
        <groupId>org.mvc-spec.ozark</groupId>
        <artifactId>ozark-jersey</artifactId>
        <version>1.0.0-m03</version>
    </dependency>    
</dependencies>

```

Glasfish 已经包含许多 Tomcat 中不存在的库。 无需其他修改。

在本教程中，我们介绍了 Java MVC 框架。 您可能也对相关教程感兴趣： [Java 教程](/lang/java/)， [Java MVC Thymeleaf 教程](/articles/javamvcthymeleaf/)，[游戏简介](/java/play/)，[Stripes 简介](/java/stripes/)， 或 [Java Spark 教程](/java/spark/)。