目錄
一、背景
- Spring生態的強大與完善,使得大多數的Java程式設計師,在剛剛接觸Java Web應用開發時,往往依賴於SSM、SpringBoot等各種高階框架。
- Java Web的基礎的體系結構是什麼?到底是怎麼運作的?這些高階的框架與基礎的體系結構之間是什麼關係?
- 只有真正理清了這些底層基礎的結構,才能完全理解高階框架的設計原理,在使用框架開發專案時做到事半功倍。
- 本文旨在暫時拋開這些高階框架,重走Java Web底層之路。
二、Web應用
- Web應用的基礎模型
- 使用者通過Web瀏覽器向某個Web應用發出一個請求
- Web伺服器得到請求後,處理並查詢資源,並向Web瀏覽器返回一個響應結果。
2.1 HTML
-
Web伺服器需要對客戶端的請求提供響應內容,Web瀏覽器需要將這些響應內容呈現給使用者。兩者需要形成統一的對話語言,Web應用中形成的共同的語言被稱為HTML(HyperText Markup Language:超文字標記語言)。
-
HTML包含數十個標記,數千種標記屬性,能過這些標記定義了網頁內容的含義和結構;正是無數個具有相互連結的HTML網頁構成了我們現在的網際網路世界。
標記 | 描述 |
---|---|
html | 定義HTML文件的邊界 |
head | 定義HTML文件頭部的邊界 |
body | 定義HTML文件本體的邊界 |
tile | 定義HTML文件本體的標題 |
form | 定義一個表單 |
a | 定義一個超連結 |
... | ... |
<!-- HTML基礎 -->
<html>
<head>
<title>歡迎</title>
</head>
<body>
<a href="https://www.baidu.com">百度</a>
</body>
</html>
2.2 HTTP
- Web瀏覽器與Web伺服器之間相互通訊同樣需要建立統一的協議:Web應用的標準協議被稱為HTTP(Hyper Text Transfer Protocol)超文字傳輸協議。
- HTTP協議規定了超文字傳輸所要遵守的規則:HTTP請求可發起常用的GET或者POST請求;HTTP的響應中可以包含HTML內容。
curl https://www.baidu.com -v
<!-- 通過HTTP向URL地址www.baidu.com發起 GET請求-->
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com
> Accept: */*
<!-- Web伺服器HTTP響應-->
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: keep-alive
< Content-Length: 2443
< Content-Type: text/html
< Date: Tue, 25 Aug 2020 04:04:01 GMT
< Etag: "588603eb-98b"
< Last-Modified: Mon, 23 Jan 2017 13:23:55 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
<!DOCTYPE html>
<!--STATUS OK-->
<html>
<head>
...
<title>百度一下,你就知道</title>
</head>
<body link=#0000cc>
...
</body>
</html>
2.3 URL
- Web應用上的每個資源都有唯一的地址進行定位,被稱為URL(Uniform Resource Locatiors)統一資源定位符。
- URL中可包含額外的引數,會追加到URL的最後,以?開頭,以&分隔各個引數,如:http://www.web.com:8080/welcome/hello.html?name=jack&age=20
- Web伺服器中的應用一般預設在80埠執行,埠號為80的在URL中可省略不書寫。
2.4 Servlet
- Servlet是Server Applet的簡寫,也被稱為執行在服務端的小程式,通過Servlet程式可以生成動態Web內容,實現Java Web伺服器功能的擴充套件。
- Servlet需要依付於Servlet容器(比如Tomcat等)才能執行
2.4.1 編寫第一個Servlet程式
-
Java Servlet是一個介面,定義了Java類被瀏覽器訪問到的規則。
-
Java程式設計師自定義一個類,實現Servlet介面並重寫介面中的方法,Web伺服器(如Tomcat等)就可以識別並執行這個程式。
-
建立JavaEE專案
-
定義一個類,實現Servlet介面,實現或重寫介面中的方法
/**
* HttpServlet
*
* @author zhuhuix
* @date 2020-08-25
*/
public class HttpServletDemo extends HttpServlet {
// 重寫Get請求方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 業務邏輯處理
LocalDate date = LocalDate.now();
// 動態輸出HTML頁面
PrintWriter out = resp.getWriter();
out.println("<html>" +
"<body>" +
"<h1>"+date.toString()+"</h1> " +
"<h2>hello world</h2> " +
"</body>" +
"</html>"
);
}
}
- 在web.xml配置Servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置Servlet -->
<servlet>
<servlet-name>http-demo</servlet-name>
<servlet-class>demo.servlet.HttpServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>http-demo</servlet-name>
<url-pattern>/http-demo</url-pattern>
</servlet-mapping>
</web-app>
- 執行
- 訪問http://localhost:8080/servlet_war_exploded/http-demo路徑
2.5 JSP
- JSP(Java Server Pages)也是一種Java servlet,主要用於實現Java web應用程式的使用者介面部分。通過結合HTML程式碼、XHTML程式碼、XML元素以及嵌入JSP操作和命令來編寫JSP。簡而言之,就是在HTML網頁中嵌入了Java。
- JSP頁面可以與處理業務邏輯的 Servlet 一起使用,這種模式被Java servlet 模板引擎所支援
<%@ page import="java.time.LocalDate" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h1><%= LocalDate.now()%></h1>
<h2>hello world!!!</h2>
</body>
</html>
public class HttpServletDemo extends HttpServlet {
// 重寫Get請求方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 呼叫jsp頁面
req.getRequestDispatcher("/index.jsp").forward(req,resp);
}
}
2.6 容器
- 容器就是程式執行時需要的環境;比如Tomcat就是一個Servlet/JSP的容器。
- Servlet 容器具備管理Servlet物件的功能。
- 通訊支援:利用容器提供的方法,可以輕鬆實現Web伺服器與Servlet進行通訊,無需自己建立ServerSocket、監聽埠,位元組流傳輸等底層協議。
- 生命週期管理: 容器會負責Servlet的例項化、初始化、呼叫方法、釋放資源等控制。
- 多執行緒支援:容器接收到每個Servlet請求時建立新的執行緒,並協調執行緒執行。
- 配置式管理:利用容器支援的xml進行配置式管理,在環境改變時,無需硬性修改程式及編譯程式。
2.7 URL對映到Servlet
- 通過JavaEE的XML配置部署檔案中的元素〈servlet〉及 〈servlet-mapping〉,把URL對映到對應的Servlet上。
三、一個完整的Java Web基礎應用
/**
* HttpServlet
*
* @author zhuhuix
* @date 2020-08-25
*/
public class HttpServletDemo extends HttpServlet {
// 重寫Get請求方法,返回一個表單頁面
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.getRequestDispatcher("/form.jsp").forward(req, resp);
}
// 重寫Post請求方法,提交表單上的資料,並返回結果頁面
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
Integer age = Integer.parseInt(req.getParameter("age"));
if (name != null && age != null) {
User user = new User(name, age);
req.setAttribute("name", name);
req.setAttribute("age", age);
if (user.checkName()) {
req.setAttribute("result","登記成功");
}else {
req.setAttribute("result","登記失敗:名稱中包含非法字元");
}
RequestDispatcher view = req.getRequestDispatcher("/result.jsp");
view.forward(req, resp);
}
}
}
/**
* 使用者類
*/
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
// 判斷名稱是否非法
public Boolean checkName() {
return !this.name.contains("admin");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>http-demo</servlet-name>
<servlet-class>demo.servlet.HttpServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>http-demo</servlet-name>
<url-pattern>/http-demo</url-pattern>
</servlet-mapping>
</web-app>
<!--表單頁面-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登記使用者</title>
</head>
<body>
<form method="post" action="http-demo">
姓名:<input name="name" type="text"/><br>
年齡:<input name="age" type="text"/><br>
<input type="submit" title="提交" >
</form>
</body>
</html>
<!--結果頁面-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登記結果</title>
</head>
<body>
<h2>姓名:${name} 年齡:${age} ${result} </h2><br>
</body>
</html>
四、小結
- 以上三個小節,只對Java Web中的基礎要素及這些要素組成的最小體系結構做了回顧。
- Java EE中Web開發的要點還有很多,比如Servlet的請求與響應的具體細節、JSTL語法,過濾器與監聽器,Session與Cookie等。
- 在重度依賴各種框架開發的今天,謹以此文拋磚引玉,讓我們先拋開框架,重拾基礎。