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

