MongoDB Java Servlet Web应用程序示例教程

时间:2020-02-23 14:40:51  来源:igfitidea点击:

欢迎使用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