原文: http://zetcode.com/articles/javaservletweld/

Java Servlet Weld 教程展示了如何在带有 Weld 的 Java Servlet 中使用依赖注入。 我们将 Weld 与 Tomcat Web 服务器一起使用。

依赖注入

依赖项注入(DI)是一种技术,其中一个对象提供另一个对象的依赖项。 对于 Java 应用,它是一个特定的库,可以将依赖项注入到类中。 DI 的主要优点是耦合松散且易于使用。 DI 使类更具凝聚力,因为它们的职责更少。

Java EE 通过引入上下文和依赖注入(CDI)规范来标准化依赖注入。 它是依赖项注入和上下文生命周期管理的标准。

@Inject注解

@Inject注解用于将依赖项注入 Java 类。 可以使用@ManagedBean注解来装饰要注入的依赖项。

焊接

Weld 是 Java EE 平台的 CDI 的参考实现。 Weld 已集成到许多 Java EE 应用服务器中,例如 WildFly,JBoss,GlassFish 等。 Weld 也可以在普通的 servlet 容器(Tomcat,Jetty)或 Java SE 中使用。

Java Servlet Weld 示例

在以下 Web 应用中,我们创建一个 servlet,该 servlet 返回 HTML 文件中的城市对象列表。 在应用中,我们在 Weld 库的帮助下使用依赖项注入。

  1. $ tree
  2. .
  3. ├── nb-configuration.xml
  4. ├── pom.xml
  5. └── src
  6. ├── main
  7. ├── java
  8. └── com
  9. └── zetcode
  10. ├── bean
  11. └── City.java
  12. ├── dao
  13. ├── CityDao.java
  14. └── ICityDao.java
  15. ├── service
  16. ├── CityService.java
  17. └── ICityService.java
  18. └── web
  19. └── GetCities.java
  20. └── webapp
  21. ├── index.html
  22. ├── listCities.jsp
  23. ├── META-INF
  24. └── context.xml
  25. └── WEB-INF
  26. └── beans.xml
  27. └── test
  28. └── java

这是项目结构。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <groupId>com.zetcode</groupId>
  8. <artifactId>JavaServletWeld</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>war</packaging>
  11. <name>JavaServletWeld</name>
  12. <properties>
  13. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  14. <maven.compiler.source>1.8</maven.compiler.source>
  15. <maven.compiler.target>1.8</maven.compiler.target>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>javax.servlet</groupId>
  20. <artifactId>javax.servlet-api</artifactId>
  21. <version>4.0.0</version>
  22. <scope>provided</scope>
  23. </dependency>
  24. <dependency>
  25. <groupId>javax.servlet</groupId>
  26. <artifactId>jstl</artifactId>
  27. <version>1.2</version>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.jboss.weld.servlet</groupId>
  31. <artifactId>weld-servlet-shaded</artifactId>
  32. <version>3.0.2.Final</version>
  33. </dependency>
  34. </dependencies>
  35. <build>
  36. <plugins>
  37. <plugin>
  38. <groupId>org.apache.maven.plugins</groupId>
  39. <artifactId>maven-war-plugin</artifactId>
  40. <version>3.2.0</version>
  41. <configuration>
  42. <failOnMissingWebXml>false</failOnMissingWebXml>
  43. </configuration>
  44. </plugin>
  45. </plugins>
  46. </build>
  47. </project>

这是 Maven POM 文件。 javax.servlet-api工件用于 servlet。 weld-servlet-shaded依赖项使 Weld 可以在 Servlet 容器中运行。 jstl将 JSTL 库添加到项目中。 JSTL 包括一组用于 JSP 应用的有用标签。 maven-war-plugin负责收集 Web 应用的所有工件依赖项,类和资源,并将它们打包到 Web 应用存档(WAR)中。

context.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Context path="/JavaServletWeld">
  3. <Resource name="BeanManager"
  4. auth="Container"
  5. type="javax.enterprise.inject.spi.BeanManager"
  6. factory="org.jboss.weld.resources.ManagerObjectFactory" />
  7. </Context>

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

City.java

  1. package com.zetcode.bean;
  2. import java.util.Objects;
  3. public class City {
  4. private Long id;
  5. private String name;
  6. private int population;
  7. public City(Long id, String name, int population) {
  8. this.id = id;
  9. this.name = name;
  10. this.population = population;
  11. }
  12. public Long getId() {
  13. return id;
  14. }
  15. public void setId(Long id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public int getPopulation() {
  25. return population;
  26. }
  27. public void setPopulation(int population) {
  28. this.population = population;
  29. }
  30. @Override
  31. public int hashCode() {
  32. int hash = 3;
  33. hash = 97 * hash + Objects.hashCode(this.id);
  34. hash = 97 * hash + Objects.hashCode(this.name);
  35. hash = 97 * hash + this.population;
  36. return hash;
  37. }
  38. @Override
  39. public boolean equals(Object obj) {
  40. if (this == obj) {
  41. return true;
  42. }
  43. if (obj == null) {
  44. return false;
  45. }
  46. if (getClass() != obj.getClass()) {
  47. return false;
  48. }
  49. final City other = (City) obj;
  50. if (this.population != other.population) {
  51. return false;
  52. }
  53. if (!Objects.equals(this.name, other.name)) {
  54. return false;
  55. }
  56. return Objects.equals(this.id, other.id);
  57. }
  58. }

City bean 保存城市对象的数据。 它具有三个属性:idnamepopulation

beans.xml

  1. <?xml version="1.0"?>
  2. <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  5. http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
  6. version="1.1" bean-discovery-mode="all">
  7. </beans>

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

ICityService.java

  1. package com.zetcode.service;
  2. import com.zetcode.bean.City;
  3. import java.util.List;
  4. public interface ICityService {
  5. public List<City> getCities();
  6. }

ICityService包含getCities()合同方法。

CityService.java

  1. package com.zetcode.service;
  2. import com.zetcode.bean.City;
  3. import com.zetcode.dao.ICityDao;
  4. import java.util.List;
  5. import javax.annotation.ManagedBean;
  6. import javax.inject.Inject;
  7. @ManagedBean
  8. public class CityService implements ICityService {
  9. @Inject
  10. private ICityDao cityDao;
  11. @Override
  12. public List<City> getCities() {
  13. return cityDao.findAll();
  14. }
  15. }

CityService包含ICityService接口的实现。 服务类调用 DAO 对象的方法,该方法是数据库的中间层。

  1. @ManagedBean
  2. public class CityService implements ICityService {

@ManagedBean是一个可选注解,指示CityService将由 Weld 管理。

  1. @Inject
  2. private ICityDao cityDao;

使用@Inject注解,将CityDao注入cityDao属性。

ICityDao.java

  1. package com.zetcode.dao;
  2. import com.zetcode.bean.City;
  3. import java.util.List;
  4. public interface ICityDao {
  5. public List<City> findAll();
  6. }

这里我们有 DAO findAll()合约方法。

CityDao.java

  1. package com.zetcode.dao;
  2. import com.zetcode.bean.City;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import javax.annotation.ManagedBean;
  6. @ManagedBean
  7. public class CityDao implements ICityDao {
  8. @Override
  9. public List<City> findAll() {
  10. List<City> cities = new ArrayList<>();
  11. cities.add(new City(1L, "Bratislava", 432000));
  12. cities.add(new City(2L, "Budapest", 1759000));
  13. cities.add(new City(3L, "Prague", 1280000));
  14. cities.add(new City(4L, "Warsaw", 1748000));
  15. cities.add(new City(5L, "Los Angeles", 3971000));
  16. cities.add(new City(6L, "New York", 8550000));
  17. cities.add(new City(7L, "Edinburgh", 464000));
  18. cities.add(new City(8L, "Berlin", 3671000));
  19. return cities;
  20. }
  21. }

CityDao包含findAll() DAO 方法的实现。 为简单起见,我们不连接数据库,而只是返回City对象的列表。

  1. @ManagedBean
  2. public class CityDao implements ICityDao {

CityDao也是一个托管 bean。

GetCities.java

  1. package com.zetcode.web;
  2. import com.zetcode.bean.City;
  3. import com.zetcode.service.ICityService;
  4. import java.io.IOException;
  5. import java.util.List;
  6. import javax.inject.Inject;
  7. import javax.servlet.RequestDispatcher;
  8. import javax.servlet.ServletException;
  9. import javax.servlet.annotation.WebServlet;
  10. import javax.servlet.http.HttpServlet;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. @WebServlet(name = "GetCities", urlPatterns = {"/GetCities"})
  14. public class GetCities extends HttpServlet {
  15. @Inject
  16. ICityService cityService;
  17. @Override
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  19. throws ServletException, IOException {
  20. response.setContentType("application/html;charset=UTF-8");
  21. List<City> cities = cityService.getCities();
  22. request.setAttribute("cities", cities);
  23. RequestDispatcher dispatcher = request.getRequestDispatcher("listCities.jsp");
  24. dispatcher.forward(request, response);
  25. }
  26. }

GetCities servlet 调用城市服务的getCities()方法和响应与包含在 HTML 表中的所有城市中的 HTML 页面。

  1. @WebServlet(name = "GetCities", urlPatterns = {"/GetCities"})

Java 类用@WebServlet注解修饰。 它映射到GetCities URL 模式。

  1. @Inject
  2. ICityService cityService;

使用@Inject注解,将CityService注入CityService属性。

  1. response.setContentType("application/html;charset=UTF-8");

Servlet 将以 HTML 输出数据,并且数据的编码设置为 UTF-8。

  1. List<City> cities = cityService.getCities();
  2. request.setAttribute("cities", cities);

使用CityServicegetCities()检索所有城市。

  1. request.setAttribute("cities", cities);

我们将列表设置为请求。

  1. RequestDispatcher dispatcher = request.getRequestDispatcher("listCities.jsp");
  2. dispatcher.forward(request, response);

使用RequestDispatcher将处理发送到listCities.jsp页面。 它是一个模板文件,该模板文件将数据与 HTML 结合在一起并向客户端生成最终输出。

listCities.jsp

  1. <%@page contentType="text/html" pageEncoding="UTF-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>Cities</title>
  8. </head>
  9. <body>
  10. <h2>Cities</h2>
  11. <table>
  12. <thead>
  13. <tr>
  14. <th>Id</th>
  15. <th>Name</th>
  16. <th>Population</th>
  17. </tr>
  18. </thead>
  19. <tbody>
  20. <c:forEach items="${cities}" var="city">
  21. <tr>
  22. <td>${city.id}</td>
  23. <td>${city.name}</td>
  24. <td>${city.population}</td>
  25. </tr>
  26. </c:forEach>
  27. </tbody>
  28. </table>
  29. </body>
  30. </html>

listCities.jsp使用c:forEach标签从提供的数据生成 HTML 表。

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Home page</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. </head>
  8. <body>
  9. <a href="GetCities">GetCities</a>
  10. </body>
  11. </html>

这是主页。 它包含一个调用 servlet 的链接。

在本教程中,我们展示了如何在 Java Servlet Web 应用中包含 Weld 库以及如何使用它来管理依赖项。

您可能也对以下相关教程感兴趣: Java Servlet 服务 XML 教程Java Servlet 上传文件Java Log4j 教程Java HttpServletMappingJava Servlet RESTful 客户端Java RequestDispatcher从 Java Servlet 提供纯文本Java Servlet 图像教程Java 教程