详细了解 Java EE 8 MVC 中的控制器
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2800+ 小伙伴加入学习 ,欢迎点击围观
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 上找到示例源代码。