MongoDB Java Servlet Web应用程序示例教程
欢迎使用MongoDB Web应用程序示例。
在前面的MongoDB Java示例中,我们学习了如何在独立应用程序中使用MongoDB Java驱动程序。
今天,我们正在努力将MongoDB集成到Java Servlet Web应用程序中。
MongoDB Web应用程序
我们将创建一个Web应用程序,在此我们将管理Person数据并将其存储在MongoDB数据库中。
我们将能够从用户界面创建,读取,更新和删除人员记录,并将对MongoDB数据库执行相应的操作。
第一步是在Eclipse中创建一个动态Web应用程序,然后将其转换为Maven项目,以使基于maven的Web应用程序框架代码准备就绪。
下图显示了最终的项目结构及其不同的组成部分。
让我们逐一研究每个组件。
MongoDB Web应用程序Maven依赖关系
我们最终的pom.xml文件如下所示。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>MongoDBWebapp</groupId> <artifactId>MongoDBWebapp</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <build> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> <finalName>${project.artifactId}</finalName> </build> <dependencies> <!-- MongoDB Java Driver --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.12.3</version> </dependency> <!-- JSTL libraries for JSP pages --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- Servlet-API jar, only for compile time --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> </project>
请注意,我们具有MongoDB java驱动程序依赖项来连接到MongoDB服务器,在JSP页面中使用JSTL标记需要JSTL和标准jar。
部署描述符
这是我们的部署描述符web.xml文件的详细信息。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>MongoDBWebapp</display-name> <context-param> <param-name>MONGODB_HOST</param-name> <param-value>localhost</param-value> </context-param> <context-param> <param-name>MONGODB_PORT</param-name> <param-value>27017</param-value> </context-param> <welcome-file-list> <welcome-file>persons.jsp</welcome-file> </welcome-file-list> </web-app>
MongoDB服务器的主机和端口详细信息配置为上下文参数,而不是在代码中的某些地方对其进行硬编码。
为了查看目的,我们只有一个JSP页面,我在欢迎文件列表中添加了它,以避免Web应用程序主页出现空白页面。
Bean或者POJO类模型
我们有Person.java类作为Model类,此bean将作为Mongo DBObject保存到数据库中。
Person.java
package com.theitroad.mongodb.model; public class Person { //id will be used for primary key in MongoDB //We could use ObjectId, but I am keeping it //independent of MongoDB API classes private String id; private String name; private String country; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
请注意,它具有id属性,该属性将由MongoDB生成,并且用户无法对其进行编辑。
这将用作MongoDB对象的主键。
请注意,MongoDB记录主键与" _id"键存储在一起,当我们检索它时,它将作为" ObjectId"实例返回。
对于松散耦合,我使用的是String,但我们也可以使用ObjectId类型。
由于我们没有将" ObjectId"用作主键,因此我们需要在多个位置将其转换为ObjectId,反之亦然。
Java Bean到MongoDB DBObject转换器
我们有一个帮助程序类,用于将Person对象转换为MongoDB DBObject,反之亦然。
PersonConverter.java
package com.theitroad.mongodb.converter; import org.bson.types.ObjectId; import com.theitroad.mongodb.model.Person; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; public class PersonConverter { //convert Person Object to MongoDB DBObject //take special note of converting id String to ObjectId public static DBObject toDBObject(Person p) { BasicDBObjectBuilder builder = BasicDBObjectBuilder.start() .append("name", p.getName()).append("country", p.getCountry()); if (p.getId() != null) builder = builder.append("_id", new ObjectId(p.getId())); return builder.get(); } //convert DBObject Object to Person //take special note of converting ObjectId to String public static Person toPerson(DBObject doc) { Person p = new Person(); p.setName((String) doc.get("name")); p.setCountry((String) doc.get("country")); ObjectId id = (ObjectId) doc.get("_id"); p.setId(id.toString()); return p; } }
转换非常简单,只需注意将id属性转换为ObjectId,反之亦然。
MongoDB DAO实施
我们可以创建一个Person DAO接口并提供MongoDB实现,但为简单起见,我们有一个简单的MongoDB DAO实现,以展示我们可以对MongoDB数据库中的Person对象执行的不同操作。
MongoDBPersonDAO.java
package com.theitroad.mongodb.dao; import java.util.ArrayList; import java.util.List; import org.bson.types.ObjectId; import com.theitroad.mongodb.converter.PersonConverter; import com.theitroad.mongodb.model.Person; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; //DAO class for different MongoDB CRUD operations //take special note of "id" String to ObjectId conversion and vice versa //also take note of "_id" key for primary key public class MongoDBPersonDAO { private DBCollection col; public MongoDBPersonDAO(MongoClient mongo) { this.col = mongo.getDB("theitroad").getCollection("Persons"); } public Person createPerson(Person p) { DBObject doc = PersonConverter.toDBObject(p); this.col.insert(doc); ObjectId id = (ObjectId) doc.get("_id"); p.setId(id.toString()); return p; } public void updatePerson(Person p) { DBObject query = BasicDBObjectBuilder.start() .append("_id", new ObjectId(p.getId())).get(); this.col.update(query, PersonConverter.toDBObject(p)); } public List<Person> readAllPerson() { List<Person> data = new ArrayList<Person>(); DBCursor cursor = col.find(); while (cursor.hasNext()) { DBObject doc = cursor.next(); Person p = PersonConverter.toPerson(doc); data.add(p); } return data; } public void deletePerson(Person p) { DBObject query = BasicDBObjectBuilder.start() .append("_id", new ObjectId(p.getId())).get(); this.col.remove(query); } public Person readPerson(Person p) { DBObject query = BasicDBObjectBuilder.start() .append("_id", new ObjectId(p.getId())).get(); DBObject data = this.col.findOne(query); return PersonConverter.toPerson(data); } }
任何MongoDB操作都需要MongoClient实例,因此我创建了一个构造函数,我们需要将其传递给它。
我们的MongoDB操作设置类已经准备就绪,我们现在可以将其与Web应用程序集成。
MongoDB ServletContextListener
MongoClient是线程安全的,并在内部管理其自己的连接池。
最佳实践是创建它的实例并重用它。
我们应该在应用程序关闭时关闭它,这使ServletContextListener实现成为初始化和销毁它的最佳选择。
MongoDBContextListener.java
package com.theitroad.mongodb.listener; import java.net.UnknownHostException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import com.mongodb.MongoClient; @WebListener public class MongoDBContextListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent sce) { MongoClient mongo = (MongoClient) sce.getServletContext() .getAttribute("MONGO_CLIENT"); mongo.close(); System.out.println("MongoClient closed successfully"); } @Override public void contextInitialized(ServletContextEvent sce) { try { ServletContext ctx = sce.getServletContext(); MongoClient mongo = new MongoClient( ctx.getInitParameter("MONGODB_HOST"), Integer.parseInt(ctx.getInitParameter("MONGODB_PORT"))); System.out.println("MongoClient initialized successfully"); sce.getServletContext().setAttribute("MONGO_CLIENT", mongo); } catch (UnknownHostException e) { throw new RuntimeException("MongoClient init failed"); } } }
请注意,我正在使用@WebListener批注将其配置为侦听器类,您的servlet容器应支持它,否则您将不得不使用基于XML的配置。
我正在使用支持Servlet API批注的Apache Tomcat 7,因此请确保使用兼容的servlet容器或者将代码更改为使用基于XML的配置。
我们正在创建MongoClient
的实例,并将其添加为上下文属性,以便可以在应用程序中的任何位置访问它。
Servlet类
我们有三个用于CRUD操作的servlet类,它们具有一些验证逻辑来确保输入数据有效。
如果一切顺利,都可以使用请求参数,那么它将使用MongoDB DAO实现来执行数据库操作,并在设置正确的属性后将请求转发到JSP页面。
AddPersonServlet.java
package com.theitroad.mongodb.servlets; import java.io.IOException; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.theitroad.mongodb.dao.MongoDBPersonDAO; import com.theitroad.mongodb.model.Person; import com.mongodb.MongoClient; @WebServlet("/addPerson") public class AddPersonServlet extends HttpServlet { private static final long serialVersionUID = -7060758261496829905L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String country = request.getParameter("country"); if ((name == null || name.equals("")) || (country == null || country.equals(""))) { request.setAttribute("error", "Mandatory Parameters Missing"); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } else { Person p = new Person(); p.setCountry(country); p.setName(name); MongoClient mongo = (MongoClient) request.getServletContext() .getAttribute("MONGO_CLIENT"); MongoDBPersonDAO personDAO = new MongoDBPersonDAO(mongo); personDAO.createPerson(p); System.out.println("Person Added Successfully with id="+p.getId()); request.setAttribute("success", "Person Added Successfully"); List<Person> persons = personDAO.readAllPerson(); request.setAttribute("persons", persons); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } } }
EditPersonServlet.java
package com.theitroad.mongodb.servlets; import java.io.IOException; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.theitroad.mongodb.dao.MongoDBPersonDAO; import com.theitroad.mongodb.model.Person; import com.mongodb.MongoClient; @WebServlet("/editPerson") public class EditPersonServlet extends HttpServlet { private static final long serialVersionUID = -6554920927964049383L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); if (id == null || "".equals(id)) { throw new ServletException("id missing for edit operation"); } System.out.println("Person edit requested with id=" + id); MongoClient mongo = (MongoClient) request.getServletContext() .getAttribute("MONGO_CLIENT"); MongoDBPersonDAO personDAO = new MongoDBPersonDAO(mongo); Person p = new Person(); p.setId(id); p = personDAO.readPerson(p); request.setAttribute("person", p); List<Person> persons = personDAO.readAllPerson(); request.setAttribute("persons", persons); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); //keep it non-editable in UI if (id == null || "".equals(id)) { throw new ServletException("id missing for edit operation"); } String name = request.getParameter("name"); String country = request.getParameter("country"); if ((name == null || name.equals("")) || (country == null || country.equals(""))) { request.setAttribute("error", "Name and Country Can't be empty"); MongoClient mongo = (MongoClient) request.getServletContext() .getAttribute("MONGO_CLIENT"); MongoDBPersonDAO personDAO = new MongoDBPersonDAO(mongo); Person p = new Person(); p.setId(id); p.setName(name); p.setCountry(country); request.setAttribute("person", p); List<Person> persons = personDAO.readAllPerson(); request.setAttribute("persons", persons); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } else { MongoClient mongo = (MongoClient) request.getServletContext() .getAttribute("MONGO_CLIENT"); MongoDBPersonDAO personDAO = new MongoDBPersonDAO(mongo); Person p = new Person(); p.setId(id); p.setName(name); p.setCountry(country); personDAO.updatePerson(p); System.out.println("Person edited successfully with id=" + id); request.setAttribute("success", "Person edited successfully"); List<Person> persons = personDAO.readAllPerson(); request.setAttribute("persons", persons); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } } }
DeletePersonServlet.java
package com.theitroad.mongodb.servlets; import java.io.IOException; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.theitroad.mongodb.dao.MongoDBPersonDAO; import com.theitroad.mongodb.model.Person; import com.mongodb.MongoClient; @WebServlet("/deletePerson") public class DeletePersonServlet extends HttpServlet { private static final long serialVersionUID = 6798036766148281767L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); if (id == null || "".equals(id)) { throw new ServletException("id missing for delete operation"); } MongoClient mongo = (MongoClient) request.getServletContext() .getAttribute("MONGO_CLIENT"); MongoDBPersonDAO personDAO = new MongoDBPersonDAO(mongo); Person p = new Person(); p.setId(id); personDAO.deletePerson(p); System.out.println("Person deleted successfully with id=" + id); request.setAttribute("success", "Person deleted successfully"); List<Person> persons = personDAO.readAllPerson(); request.setAttribute("persons", persons); RequestDispatcher rd = getServletContext().getRequestDispatcher( "/persons.jsp"); rd.forward(request, response); } }
注意使用@WebServlet批注为每个servlet配置URI模式。
在JSP页面中将使用它来发送请求以更正servlet。
JSP查看页面
该项目的最后一块是视图页面,我正在使用JSTL标签来呈现响应html页面。
persons.jsp
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Persons Manage Page</title> <style> table,th,td { border: 1px solid black; } </style> </head> <body> <%-- Person Add/Edit logic --%> <c:if test="${requestScope.error ne null}"> <strong style="color: red;"><c:out value="${requestScope.error}"></c:out> </c:if> <c:if test="${requestScope.success ne null}"> <strong style="color: green;"><c:out value="${requestScope.success}"></c:out> </c:if> <c:url value="/addPerson" var="addURL"></c:url> <c:url value="/editPerson" var="editURL"></c:url> <%-- Edit Request --%> <c:if test="${requestScope.person ne null}"> <form action='<c:out value="${editURL}"></c:out>' method="post"> ID: <input type="text" value="${requestScope.person.id}" readonly="readonly" name="id"><br> Name: <input type="text" value="${requestScope.person.name}" name="name"><br> Country: <input type="text" value="${requestScope.person.country}" name="country"><br> <input type="submit" value="Edit Person"> </form> </c:if> <%-- Add Request --%> <c:if test="${requestScope.person eq null}"> <form action='<c:out value="${addURL}"></c:out>' method="post"> Name: <input type="text" name="name"><br> Country: <input type="text" name="country"><br> <input type="submit" value="Add Person"> </form> </c:if> <%-- Persons List Logic --%> <c:if test="${not empty requestScope.persons}"> <table> <tbody> <tr> <th>ID</th> <th>Name</th> <th>Country</th> <th>Edit</th> <th>Delete</th> </tr> <c:forEach items="${requestScope.persons}" var="person"> <c:url value="/editPerson" var="editURL"> <c:param name="id" value="${person.id}"></c:param> </c:url> <c:url value="/deletePerson" var="deleteURL"> <c:param name="id" value="${person.id}"></c:param> </c:url> <tr> <td><c:out value="${person.id}"></c:out></td> <td><c:out value="${person.name}"></c:out></td> <td><c:out value="${person.country}"></c:out></td> <td><a href='<c:out value="${editURL}" escapeXml="true"></c:out>'>Edit</a></td> <td><a href='<c:out value="${deleteURL}" escapeXml="true"></c:out>'>Delete</a></td> </tr> </c:forEach> </tbody> </table> </c:if> </body> </html>
推荐阅读:JSTL教程,JSP EL和JSP隐式对象。
MongoDB Java Web应用程序测试
我们的应用程序已准备好进行测试驱动,通过不同CRUD操作将会对应一些响应页面。
您还将在服务器日志文件中找到以下日志。
MongoClient initialized successfully Person Added Successfully with id=53ea76e70364b0028f507802 Person Added Successfully with id=53ea76fd0364b0028f507803 Person edit requested with id=53ea76e70364b0028f507802 Person edited successfully with id=53ea76e70364b0028f507802 Person deleted successfully with id=53ea76fd0364b0028f507803 MongoClient closed successfully