Java EE MVC 是一个新的基于动作的 MVC 框架,计划用于 Java EE 8 并在 JSR-371 中指定。这是我的 Java EE 8 MVC 教程的第二篇文章。第一篇文章介绍了基础知识,并展示了如何 开始使用 Ozark (Java EE 8 MVC 参考实现)。
在这篇文章中,我们将更详细地了解 MVC 控制器。
MVC 控制器
控制器负责处理传入的请求。它调用业务逻辑、更新模型并返回应呈现的视图。 MVC 控制器是一种使用@Controller 注释的JAX-RS 资源方法。如果一个类被@Controller注解,那么这个类的所有资源方法都被视为控制器。
以下示例显示了一个简单的控制器,它呈现给定产品 ID 的产品详细信息页面:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
此控制器使用 ProductService 将产品 ID(作为 id 请求参数传递)解析为产品。将获得的产品添加到模型中,并返回视图的路径。然后使用存储在模型中的信息呈现视图。
与在 JAX-RS 中一样,@Path 注释用于定义 URL 路径。可以通过如下所示的 URL 访问此控制器:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
以下示例显示了一个具有一个 MVC 控制器方法和一个传统 JAX-RS 资源方法的混合类:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
控制器方法的工作方式与 JAX-RS 资源方法非常相似。但是,有两个小区别:
- Controller 方法的返回类型 String 被解释为视图路径。使用 JAX-RS 资源方法,返回的字符串被解释为文本内容。
- Controller 方法的默认响应媒体类型是 text/html。与 JAX-RS 一样,可以使用 @Produces 注释更改媒体类型。
MVC 控制器类和具有 MVC 控制器方法的混合类需要是 CDI 管理的 bean。与 JAX-RS 资源类一样,MVC 控制器类是根据请求实例化的。对于每个请求,都会创建一个新的 Controller 类实例。
与 JAX-RS 一样,受支持的 HTTP 动词由注释定义。如果一个控制器方法应该监听 HTTP POST 请求,它需要用 @POST 而不是 @Get 注释。
例如:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
控制器返回类型
MVC 控制器方法支持四种不同的返回类型:
- String - 返回的字符串值被解释为视图路径。
- void - 在这种情况下,需要使用 @View 注释定义视图
- 可查看 - 包含有关视图、模型和使用的视图引擎的信息的抽象。
- 响应 - JAX-RS 响应。响应的实体类型需要是 String、void 或 Viewable。
下面的类定义了四种使用不同返回类型的控制器方法。所有方法都返回相同的响应:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
返回 JAX-RS 响应是最灵活的方式。这样,JAX-RS 响应构建器可用于修改 HTTP 状态代码、响应标头等。
如果使用 void 作为返回类型,则需要使用 @View 注释定义视图。 @View 可以应用于方法(如前面的示例)和类。如果一个类被@View注解,视图将被应用到这个类中的所有控制器方法。类级别的 @View 注释可以被方法级别上更具体的视图定义覆盖,如以下示例所示:
@Path("product")
@Controller
public class ProductController {
@Inject
private Models models;
@Inject
private ProductService productService;
@GET
public String getProductDetailPage(@QueryParam("id") long productId) {
Product product = this.productService.getProduct(productId);
models.put("product", product);
return "/WEB-INF/jsp/productDetailPage.jsp";
}
}
概括
@Controller 注解可以用在方法和类上。在类上使用时,该类的所有方法都被视为控制器。控制器方法调用业务逻辑并确定应呈现的视图。具有 Controller 方法的类是 CDI 管理的 bean。对于每个请求,都会创建一个新的类实例。传统的 JAX-RS 资源方法可以与同一个类中的 MVC 控制器方法组合。
在下一篇关于 Java EE 8 MVC 的文章中,我们将了解参数绑定和验证。
您可以在 GitHub 上找到示例源代码。