使用 Java 语言实现服务端应用的企业占比很大,特别是现今 Web 应用大展异彩的时刻。作为 web 前端开发,掌握 Java 的开发有利于你的职业更进一步。为了让你快速入门 Java,今天纳撸多要分享的是如何快速开发部署一个 Java web 后端简单应用。
文章大纲:
一个 web 应用简单考虑由三部分组成:浏览器作为客户端,Java 应用作为服务端,通信协议是 HTTP。我们要实现的效果是:在浏览器地址栏,访问应用地址,在页面中打印出 “Hello, naluduo" 文字,为此我们需要使用 Java 编写一个 HTTP 服务器响应浏览器端的访问请求。
编写 HTTP 服务器其实不难,在 Java 中只需要先编写给予多线程的 TCP 服务器,然后在一个 TCP 连接中读取 HTTP 请求,发送 HTTP 响应即可,可以看到下图中的客户端应用与服务端应用通信结构:
┌───────────┐ ┌───────────┐
│Application│ │Application│
├───────────┤ ├───────────┤
│ Socket │ │ Socket │
├───────────┤ ├───────────┤
│ TCP │ │ TCP │
├───────────┤ ┌──────┐ ┌──────┐ ├───────────┤
│ IP │<────>│Router│<─────>│Router│<────>│ IP │
└───────────┘ └──────┘ └──────┘ └───────────┘
现在我们使用 Java 代码编写一个 HTTP 服务器,这块代码理解下传统的开发流程,相对底层。不想看,可以直接跳过。
import java.io.BufferedReader; // 缓冲读取
import java.io.BufferedWriter; // 缓冲写入
import java.io.IOException; // 异常
import java.io.InputStream; // 输入流
import java.io.InputStreamReader; // 输入流读取
import java.io.OutputStream; // 输出流
import java.io.OutputStreamWriter; // 输出
import java.net.ServerSocket; // socket 包
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5050); // 监听指定端口
System.out.println("server is running...");
for (;;) {
Socket sock = ss.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
Thread t = new Handler(sock); // 新建线程
t.start();
}
}
}
class Handler extends Thread {
Socket sock;
public Handler(Socket sock) {
this.sock = sock;
}
@Override
public void run() {
try (InputStream input = this.sock.getInputStream()) {
try (OutputStream output = this.sock.getOutputStream()) {
handle(input, output);
}
} catch (Exception e) {
try {
this.sock.close();
} catch (IOException ioe) {
}
System.out.println("client disconnected.");
}
}
private void handle(InputStream input, OutputStream output) throws IOException {
System.out.println("Process new http request...");
var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
// 读取HTTP请求:
boolean requestOk = false;
String first = reader.readLine();
if (first.startsWith("GET / HTTP/1.")) {
requestOk = true;
}
for (;;) {
String header = reader.readLine();
if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
break;
}
System.out.println(header);
}
System.out.println(requestOk ? "Response OK" : "Response Error");
if (!requestOk) {
// 发送错误响应:
writer.write("404 Not Found\r\n");
writer.write("Content-Length: 0\r\n");
writer.write("\r\n");
writer.flush();
} else {
// 发送成功响应:
String data = "Hello, Jecyu!
";
int length = data.getBytes(StandardCharsets.UTF_8).length;
writer.write("HTTP/1.0 200 OK\r\n");
writer.write("Connection: close\r\n");
writer.write("Content-Type: text/html\r\n");
writer.write("Content-Length: " + length + "\r\n");
writer.write("\r\n"); // 空行标识Header和Body的分隔
writer.write(data);
writer.flush();
}
}
}
由上述代码可见,要编写一个完善的 HTTP 服务器,以 HTTP/1.1 为例,需要考虑的包括:
为了简单起见,我们可以把处理 TCP 连接,解析 HTTP 协议这些底层工作统统交给现成的服务器去做,我们只需要把自己的应用程序跑在 Web 服务器上。为了实现这一目的,JavaEE 提供了 Servlet API,我们只需使用 Servlet API 编写自己的 Servlet 来处理 HTTP 请求,Web 服务器实现 Servlet API 接口(比如 Tomcat 服务器),实现底层功能:
┌───────────┐
│My Servlet │
├───────────┤
│Servlet API│
┌───────┐ HTTP ├───────────┤
│Browser│<──────>│Web Server │
└───────┘ └───────────┘
综上,我们整体的开发部署步骤如下:
当然,在实践上述步骤之前,请确保你已经在电脑上安装了 Java 的运行环境,下载好 IntelliJ IDEA 编辑器,配置好 Java 版本环境。
在编写 Servlet 代码之前,为了提升开发效率,我们可以使用 Maven 构建开发环境。
Maven 是一个优秀的项目构建工具,可以很方便的对项目进行分模块构建,这样在开发和测试打包部署时,效率会提高很多。其次,Maven 进行依赖的管理,可以将不同系统的依赖进行统一管理,并且可以进行依赖之间的传递和继承。
Maven 遵循约定 》 配置 》编码,Maven 要负责项目的自动化构建,以编译为例,Maven 要想自动进行编译,那么它必须知道 Java 的源文件保存在哪里,这样约定之后,不用我们手动指定位置,Maven 能知道位置,从而帮我们完成自动编译。
要安装Maven,可以从Maven官网下载最新的Maven 3.6.x,然后在本地解压,设置几个环境变量:
M2_HOME=/path/to/maven-3.6.x
PATH=$PATH:$M2_HOME/bin
然后,打开命令行窗口,输入mvn -version,应该看到Maven的版本信息:
Java version: 1.8.0_251, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.7", arch: "x86_64", family: "mac"
本应用中,主要依赖为 javax.servlet 4.0.0 版本的 API,以及依赖的 java 版本为 1.8。注意到
4.0.0
org.example
spring-framework-projects
1.0-SNAPSHOT
UTF-8
UTF-8
1.8
1.8
1.8
javax.servlet
javax.servlet-api
4.0.0
provided
引入对应的 servlet 包,编写代码如下,可以看到代码比前面没使用 Servlet 时简洁不少。
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 java.io.IOException;
import java.io.PrintWriter;
// WebServlet注解表示这是一个Servlet,并映射到地址/:
@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应类型:
resp.setContentType("text/html");
// 获取输出流:
PrintWriter pw = resp.getWriter();
// 写入响应:
pw.write("Hello, naluduo!
");
// 最后不要忘记flush强制输出:
pw.flush();
}
}
一个 Servlet 总是继承自HttpServlet,然后覆写doGet()或doPost()方法。注意到doGet()方法传入了HttpServletRequest和HttpServletResponse两个对象,分别代表 HTTP 请求和响应。我们使用 Servlet API 时,并不直接与底层 TCP 交互,也不需要解析 HTTP协议,因为 HttpServletRequest 和 HttpServletResponse 就已经封装好了请求和响应。以发送响应为例,我们只需要设置正确的响应类型,然后获取 PrintWriter ,写入响应即可。
无论使用哪个服务器,只要它支持 Servlet API 4.0(因为我们引入的Servlet版本是4.0),我们的 war 包都可以在上面运行,这里我们使用开源免费的 Tomcat 服务器。
点击 Tomcat 官网,选择对应的安装包进行下载,由于我本机上已经安装了一个 Tomcat 10 的版本,就不再重新安装。
安装好 Tomcat 后,目录如下,本指南只需要关注 bin 和 webapps、conf 目录。
首先赋予启动 Catalia 权限,然后启动 Tomcat 服务器。
$ cd bin
chmod +x catalina.sh
sh startup.sh
如无意外,即可在 http://localhost:8080/ 进行访问如下页面:
接下来,我们要了解部署的容器的规范。
一个标准的应用目录如下:
使用 maven 可以把源代码打包输出如上文件。
war
Archetype Created Web Application
直接将 war 包放到 webapps下,会自动解压为项目条件 server.xml 中。
按照 3.1 的部署方式,正常来说是没问题的。但是纳撸多还是踩了个坑,在手动复制 war 文件 webapps,并进行访问
http://localhost:8080/spring-framework-projects-1.0-SNAPSHOT/时出现 404 问题,经过多方排查,最终发现是自己安装的 Tomcat 版本 10 问题,不支持 Javax.servlet 4.0 接口规范,导致访问失败。
解决方案:重新安装 Tomcat 9 版本:apache-tomcat-9.0.4 ,重新进行部署即可。
本文通过实现一个 Hello 级别的应用,让你快速了解一个 Java Web 应用的开发、构建、部署的最简单流程,助你敲开服务端开发的大门。
说明:本文限于篇幅,故而只展示部分的面试内容,完整的Java面试学习文档小编已经帮你整理好了,有需要的朋友点赞+关注私信我111免费领取Java、大厂面试学习资料哦!