CMU 95702 Project 1

95 – 702 分布式系统代写

Distributed Systems

这个项目有五个目标:
第一,介绍 IntelliJ 和 TomEE。你已经对这些有了一些实践。在这个作业中,你将构建几个 Web 应用程序以获得更多经验。
第二,构建你的第一套分布式系统。这是两个使用 Servlet 和 Java Server Pages 的小型 Web 应用程序。
第三,介绍网页抓取、API 处理和 JSON 记录。
第四,如果你之前没有使用过,将介绍 MVC 模式。
第五,与本学期的所有项目一样,你应该反思解决方案的功能和非功能特性(例如安全性、可扩展性、故障处理、互操作性)。期末考试将有关于这些特性的问题。你应该能够展示对课程内容的细致理解,并能够解释与潜在实际应用相关的技术方面。对于每个项目任务,都需要软件文档。你编写的软件(Java 文件等)必须包含注释,描述每个重要代码段的意图。如果代码没有良好的文档记录,将扣分。阅读课程表(第 1 节课)上提供的与文档相关的链接,以了解预期的内容。确保查阅评分标准以了解评分细节。
并且第六可选地,你可以在任务 3 中使用 ChatGPT 和 Copilot 来创建一些代码。任务 1 和任务 2 必须自己完成。考试中将有关于所有三个任务中代码的具体问题。虽然你可以使用 AI 工具来帮助完成任务 3,但这完全是可选的。也会有关于此代码的问题。同时注意更一般的问题,例如,什么是 MVC 以及使用它的好处是什么?网页抓取意味着什么?

交付物

有两部分需要交付,全部压缩成一个文件上传,文件名为 Project1_andrewID.zip,其中“andrewID”替换为你的实际 andrew ID:

  • 一个 PDF,包含所有部分的相关屏幕截图,后面跟着生成截图中显示结果的代码片段(相对而言:包含多少内容由你决定每个部分)。PDF 的每个部分必须清晰标记。
  • 你的三个项目,每个都压缩成一个 zip 文件,所有三个任务压缩在一起。
    请参阅末尾的更多详细信息,但首先阅读项目任务描述,以便了解详细信息所涉及的内容。

任务 1

使用 IntelliJ 项目名称:Project1Task1

创建一个 index.jsp 页面,要求用户输入一串文本数据,并使用单选按钮选择两个哈希函数。哈希函数的选择应该是 MD5 和 SHA – 256,默认是 MD5。当按下提交按钮时,会向一个 servlet 发送请求。该 servlet 必须命名为 ComputeHashes.java。servlet 将根据浏览器传输的文本计算请求的加密哈希值(MD5 或 SHA – 256)。你需要使用 Java 加密 API 来计算文本的哈希值。原始文本将与哈希名称和哈希值一起回显到浏览器。发送回浏览器的哈希值应以两种形式显示:十六进制文本和 Base64 表示。我们将在课程后面讨论此类哈希值的使用。要计算 MD5 和 SHA – 256 哈希值,请使用以下标准 Java 包:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
要打印 Base64 编码,请使用以下方法:
jakarta.xml.bind.DatatypeConverter.printBase64Binary()
要打印十六进制编码,请使用以下方法:
jakarta.xml.bind.DatatypeConverter.printHexBinary()
要将 DatatypeConverter 类包含到你的项目中,请使用:
import jakarta.xml.bind.DatatypeConverter;
并将以下行添加到你的 pom.xml 文件中,然后刷新 Maven:

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.1</version>
</dependency>

确保提供一个简单且用户友好的界面。如果你不熟悉 HTML 表单,可以在以下网址找到简单的解释:
http://www.w3schools.com/html/html_forms.asp
因为任务 1 相当简单,你不必使用 MVC 来完成它。尽可能做最简单的事情(但是,如果你愿意,也可以使用 MVC)。
确保创建你的工作应用程序的屏幕截图,并按照本文档末尾的“提交”部分所述提交它们。

任务 2

使用 IntelliJ 项目名称:Project1Task2

创建一个 Web 应用程序,实现一个简单的桌面和移动“点击器”用于课堂。你的应用程序应该允许用户提交课堂上提出问题的答案,并应该提供一个单独的 URL 端点来获取提交响应的结果。你的应用程序的欢迎页面应类似于图 1。你可以根据自己的喜好使其更具风格,但这不是必需的。

图 1
当用户做出选择并点击“提交”时,他们的答案应该存储在你的 MVC 模型中。响应应类似于图 2 的第一行。请注意,必须向用户提供关于他们所做选择的反馈(例如,在这个例子中是“D”)。
用户还应该能够提交另一个答案,如图所示。

图 2
你可以通过反复提交答案并让你的模型统计结果来测试应用程序。你的 Web 应用程序还应该有一个 URL 路径“/getResults”(如图 3 所示)来列出用户投票的结果。

图 3

“/getResults”路径的要求:

  1. 列出每个已给出的答案以及用户提交该答案的次数。
  2. 你不必列出被选择零次的选项。
  3. 结果应按字母顺序显示。
  4. “/getResults”还应清除存储的结果,以便可以提出新的问题。
  5. 如果没有可用的结果,则按图 4 所示报告。

    图 4
    请注意,要求 4 不符合 GET 请求的 HTTP 标准。你应该理解为什么根据标准这是不良行为,以及你如何修复它(可能会在考试中出现)。
    Web 应用程序应该与移动浏览器兼容。对于这个项目,你可以使用类似于在 InterestingPicture 中使用的简单检查,然后使用适当的移动 doctype。检查你的 Web 应用程序是否适用于移动设备的一种简单方法是使用 Google Chrome DevTools。使用 Google Chrome 浏览器:
  • 在 Chrome 中浏览到你的 Web 应用程序。
  • 访问 Chrome DevTools(https://developers.google.com/web/tools/chrome-devtools/?hl=en#access-devtools)。
  • 切换到设备模式为移动设备,并选择 Android 或 iPhone 设备(https://developers.google.com/web/tools/chrome-devtools/iterate/device-mode/?hl=en)。
  • 重新加载页面。
  • 除了测试之外,你还可以使用此方法生成屏幕截图,显示你的 Web 应用程序在移动设备上的工作情况。如果你的页面看起来像图 4 所示,即使重新加载后,那么 doctype 没有设置正确。
    图 5 是如果 doctype 设置正确,Web 应用程序在移动设备上的样子。

    图 5

整体 Web 应用程序要求:

  • 你必须使用 MVC 来分离关注点。
  • 仅实现一个 HttpServlet

提示:

  • 你可以在 WebServlet 注释中拥有多个 URL 模式。例如,你可以指示一个 servlet 可以通过两个路径调用,例如:urlPatterns = {“/submit”, “/getResults”}
  • 为了在 servlet 中确定实际请求的是哪个路径,你可以使用 request.getServletPath();
    生成你的应用程序的屏幕截图:
  • 带有桌面答案选项的截图。
  • 带有桌面 getResults 的截图。
  • 带有移动答案选项的截图。
  • 带有移动 getResults 的截图。

任务 3

使用 IntelliJ 项目名称:Project1Task3

任务 3 旨在让你练习几件事情:servlet 编程、网页抓取、API、JSON 和 MVC。
对于此作业,你可以可选地使用 ChatGPT 和/或 Copilot 来帮助你生成解决方案;这不是必需的,你应该能够自己进行设计和编码。请记住:

  • 生成的代码并不总是正确的。
  • 你的 ChatGPT 提示越精确,解决方案可能越好。
  • 你生成解决方案的方式应该是可重复和可解释的。
  • 如果被问到,你必须能够完全解释由 AI 或你自己生成的解决方案。
  • 必须记录你对 AI 工具的使用。展示你用于生成代码部分的提示以及你使用的工具。还要注意你在哪里编辑(如果有)任何生成的代码以及为什么这样做。

狗狗!应用程序

使用关于常见犬种的信息创建一个 Web 应用程序。你选择显示的信息(在一定程度上)由你决定,但需满足以下要求。
你的程序将呈现一个欢迎屏幕,包含标题、“创建者”引用(即你)、一个有限数量犬种的下拉菜单和一个提交按钮,如图 6 和图 7 所示。仅使用图 7 中显示的犬种。提交按钮用于记录用户的选择。请注意,你需要自己学习 HTML 下拉菜单。接下来,它将向用户展示来自下面列表的一些数据选择。

图 7:下拉菜单
你的应用程序必须满足这些标准:

  1. 显示所选犬种的狗狗图片。图片必须来自网站 https://dog.ceo/dog – api/。API 返回 JSON 数据。你需要查看他们的示例以了解查询格式和答案格式。从返回的 jpg 列表中随机选择一张图片;还需显示有多少张图片以及你选择了哪一张(例如,“返回 40 张图片,使用 #7”)。将网站引用作为输出的一部分;见图 8 关于狗狗图片和来源的示例。

    图 8:输出屏幕。谁是好孩子?
    请参阅下面关于使用 JSON 和设置正确 Maven 依赖项的部分。你必须使用 gson 库来处理 JSON 记录。
  2. 提供关于该犬种的其他信息。这必须包括至少三个关于该犬种的事实。你必须进行网页抓取此数据。并且你不能使用 Flickr 进行网页抓取。你必须使用 HTML 复选框来实现此目的;它允许用户选择一个或多个选项;你需要弄清楚如何使用这些。为每个事实包含参考引用(它们可能来自不同的网站或同一个网站)。
  3. 包含至少一张其他关于狗狗的图片,通过抓取或某些 API 获得。此图片不能是静态的 – 也就是说,不要在每次迭代犬种或每次执行程序时使用相同的图片。你不得使用 Flickr 或 dog.ceo(第 1 点中的网站)来获取此图片。
    由于第 2 和第 3 部分由你决定,因此这里没有显示示例输出。注意不要与其他学生使用完全相同的输出;你不允许共享代码!
  4. 主要用 Java 和 JSP 编码。如果你使用其他东西,请给出一个简短但有说服力的理由,说明为什么这是必要的,而不仅仅是为了方便(例如,你从 github 复制了代码,或者你让 ChatGPT 生成了它,这些都不是好理由)。
  5. 使用一个页面进行输入,至少使用两个网页进行输出 – 一个用于狗狗图片,一个用于显示三个(或更多)事实。
  6. 使用模型 – 视图 – 控制器(MVC)模式和良好的关注点分离。
  7. 以“合理”的方式处理错误情况。
  8. 有良好的文档记录 – 代码、应用程序的使用、应用程序的结构/设计、任何与 AI 相关的事情,如上所述。
    你使用哪些网站来获取状态取决于你(除了所需的狗狗图片) – 但要小心不要抄袭其他学生的想法;这必须是你自己的工作。Web 应用程序的整体设计取决于你(符合上述标准)。如果你对网站、引用或输出有疑问,提问
    同样,你必须在任务 3 中使用 MVC 模式。

注意事项和提示

屏幕抓取

屏幕抓取是通过编程方式处理通常由浏览器显示的 HTML,当你的数据源没有提供结构化数据的 API 时,它可以是一个有用的工具。相反,你可以搜索或解析 HTML 以查找和提取你需要的数据。更多信息,请参阅

https://en.wikipedia.org/wiki/Web_scraping
你的应用程序应该与 InterestingPicture 类似地工作,但不是搜索 Flickr,而是使用上面提到的网站。

  • 你可以并且被鼓励基于课堂上提供的 InterestingPicture 代码构建你的解决方案。但是,你必须重构它,使其具有对你的应用程序有意义的项目、变量和类名。例如,如果你仍然将类命名为 InterestingPictureServlet,你将失去分数
  • 你不需要,但欢迎使用 jsoup(https://jsoup.org/),它是一个 Java HTML 解析器,来进行抓取。它是 Python 中 Beautiful Soup 的 Java 版本。使用 jsoup 的缺点是你首先需要了解文档对象模型(DOM)和 CSS 选择器。这些都是很有用的知识。使用 jsoup 的优点是它使从 HTML 中查找和选择内容(即屏幕抓取)变得更加容易。请参阅下面关于 JSON Maven 的注释;添加 jsoup 将需要类似的过程。

HTML

请参考 http://www.w3schools.com 以获取关于此任务所需的基本 HTML 的良好帮助。这里有下拉框的示例。

JSON 和 gson

JSON 记录是包含标签 – 值对的文本记录,其中标签是字段名称 – 可以将其视为具有嵌套的字典或映射。它比 XML 短得多。为了找到你需要的东西,请使用 JSON 库 GSON。要使用 GSON,将 gson v.2.11.0 jar 文件下载到你记得的地方。要将其添加到你的项目中,请转到 File -> Project Structure -> Modules,选择 Dependencies 选项卡,点击底部的 + 图标,选择 Jars 或 Directories,导航到你放置 jar 文件的位置,点击它,然后 Apply 和 OK。它应该在你的 pom.xml 文件中作为中的最后一项显示为:

  <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.11.0</version>
  </dependency>

如果没有出现,请手动将上述行添加到 pom.xml 中。
最后,重新加载 Maven 依赖项以使这个新依赖项生效 – pom.xml 窗口中可能会出现一个图标,但如果你没有看到,请转到 Project View 窗口,找到 pom.xml 条目(它应该在树的底部附近),右键单击它,选择 Maven -> Reload Project。(顺便说一下,Maven 是一个构建管理工具,与通常的 Gradle 构建不同;Maven 使用项目对象模型(pom)文件来跟踪属性和依赖项。)
请使用 gson,而不是其他 JSON 库。

SSLHandshakeException

大多数现代网站要求你进行 https,而不是 http 请求。当你从你的 Java 程序中这样做时,你会遇到 SSLHandshakeException。我们将在几周内涵盖 SSL 和相关主题。与此同时,你将不得不处理这个异常。
如果你使用 jsoup,你应该使用 validateTLSCertificates(false)。(在需要时参考 jsoup API 来理解这一点。)
如果你不使用 jsoup,这里是一个代码来替换 InterestingPictureModel 中的 fetch 方法以忽略异常。参数“certType”应设置为字符串“TLSV1.3”。
“`
private String fetch(String searchURL, String certType) {
try {
// 创建信任管理器,允许你忽略 SSLHandshakeExceptions
createTrustManager(certType);
} catch (KeyManagementException ex) {
System.out.println(“不应该到这里:”);
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
System.out.println(“不应该到这里:”);
ex.printStackTrace();
}
String response = “”;
try {
URL url = new URL(searchURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 读取服务器返回的所有文本
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), “UTF – 8”));
String str;
// 读取“in”中的每一行,直到完成,将每一行添加到“response”中
while ((str = in.readLine())!= null) {
// str 是 readLine() 读取的一行文本,会去除换行符
response += str;
}
in.close();
} catch (IOException e) {
System.err.println(“URL 有问题”);
return null;
}
return response;
}
private void createTrustManager(String certType) throws KeyManagementException, NoSuchAlgorithmException{