1.Tomcat(Http服務器,Http Container)
1.對下,實現了HTTP協議,服務器端,可以通過網絡和客戶端進行通信
2.對上,是實現了java規定的Servlet協議(Java 規定了幾個interface)Tomcat定義了這些接口的實現類
2.Web應用的文件結構(docBase) 404 問題
WEB-INF web應用下的配置,類文件,依賴文件
—web.xml --XML格式的,用於web應用的配置
class\ 用戶自定義類(業務類)的ClassPath
.calss
lib\一類是.class文件 一類是.jar文件
3.Tomcat(Servlet)中如何區分不同的web應用(webapp)
1.web app | Context | ServletContext
Tomcat通過URL中的第一部份 Http://127.0.0.1:8080/hello/login
Tomcat通過URL中的後面部份 Http://127.0.0.1:8080/hello/login
Servlet對象(動態文檔 | 動態文檔)
1.根據web.xml中的配置去查找
—1.根據url找到對應的servlet-mapping(映射關係)->servlet
—2.根據servlet名字找到對應的Servlet的類
2.靜態文檔
直接在docBase爲相對路徑查找
4.請求是如何從瀏覽器到你的Servlet的代碼的(動態的說是Servlet的對象)
1.結合網絡2.結合Tomcat的分用邏輯
Tomcat和Servlet的其他重要信息:
1.Servlet(interface)(主要用於TCP|UDP業務的)
–Servlet(interface)下的一個HttpServlet(abstract class)
2.Servlet
init()初始化用的
service()每次提供服務是調用的
destroy()銷燬是使用
Servlrt對象的生命週期:
Tomcat:啓動流程
1.讀取conf下的配置文件
2.監聽8080端口(server.xml)
3.掃描目錄(webapps)
讀取並解析zhaoyanlong\WEB-INF\web-xml
4.進行Servlet對象的初始化
(每一個Servlet類在進程運行過程中有且僅有一個對象:單例模式)
調用Servlet對象的init()方法
5.定義了Map<url,Servlet名稱>
Map<Servlet名稱,Servlet對象>
先使用url獲取,名稱然後再換取到對象。
6.Socket socket =ss.accpet();
爲了併發能力,Tomcat使用了多線程處理各個請求
7.每個線程中
1.從socket的inputStream讀取內容
2. 按照HTTP協議,解析請求
3.構造一個HttpServletRequest對象
4.構造一個HttpServletResponse對象
5.根據url找對應的Servlet對象去處理
0.根據url中的第一部分,先確定哪一個context(ROOT)無前綴
1.看是否能根據兩個Map找到對應的Servlet對象
2.再給一個靜態資源的機會,(就是在docBase找文件)
找不到就404了
6.去調用該Servlet對象的service()方法
HttpServlet實現了service方法,根據HTTP方法分別調用
doGET/doPost/doPut/doDelete
7.我們自己做的Servlet中填充response的內容
8.把response按照HTTP協議,發送給socket.outputStream
8.當退出時
遍歷所有的的Servlet對象,調用他們的destroy()方法
總結:對於Servlet對象的生命週期(只有一個Servlet對象)
init()/destroy()只會被調用一次
service()每次服務就會調用一次(會被調用多次)
2.使用service的時候,是在多線程環境下工作(考慮線程安全)
Annotation 註解:@WebServlet()
public @interface MyAnnotation {
}
@MyAnnotation
public class MyMain {
}
使用註解後就可以不需要的web.xml文件中配置,會直接獲取註解中信息。
Servlet API有以下三個java包:
javax.servlet(重點):其中包含定義Servlet和Servlet容器之間的類和接口
javax.servlet.http(重點):其中包含定義HTTP Servlet和Servlet容器之間的類和接口
javax.servlet.annotation:其中包含標註Servlet,Filter,Listener的註解
disable cache 爲了減少服務器的訪問量,會在瀏覽器中有一個緩存池,訪問相同連接,會直接從池中讀信息,需要注意ctrl+F5
如果使用GET方法不能有請求體個人輸入的信息會隨着QueryString一起顯示出來。
使用post的話,會出現在正文中。
測試代碼:
FirstServlet
package com.zhaoyanlong;
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;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.println("<table>");
out.println("<thead>");
out.println("<tr>");
out.println("<th>名稱</th>");
out.println("<th>值</th>");
out.println("</tr>");
out.println("</thead>");
out.println("<tbody>");
String method=req.getMethod();
tr(out, "Method", method);
String pathInfo = req.getPathInfo();
tr(out, "PathInfo",pathInfo);
String pathTranslated = req.getPathTranslated();
tr(out, "PathTranslated",pathTranslated);
String contextPath = req.getContextPath();
tr(out, "ContextPath",contextPath);
String queryString = req.getQueryString();
tr(out,"QueryString" ,queryString);
String requestURI = req.getRequestURI();
tr(out,"RequestURL" ,requestURI );
Map<String, String[]> parameterMap = req.getParameterMap();
for (Map.Entry<String,String[]> entry:parameterMap.entrySet()) {
for (String val:entry.getValue()) {
tr(out, entry.getKey(),val);
}
}
System.out.println(req.getParameter("你好"));
System.out.println(Arrays.toString(req.getParameterValues("你好")));
Enumeration<String> headerNames = req.getHeaderNames();
//只要有更多元素就去遍歷
while (headerNames.hasMoreElements()){
//我們可以拿到name
String name=headerNames.nextElement();
//通過name拿到val 現在拿到的還是數組
Enumeration<String>heads=req.getHeaders(name);
while (heads.hasMoreElements()){
//拿到每一個val
String val=heads.nextElement();
tr(out, name,val);
}
}
out.println("</tbody>");
out.println("</table>");
}
private void tr(PrintWriter out,String name,String val){
out.println("<tr>");
out.printf("<td>%s</td>",name);
out.printf("<td>%s</td>",val);
out.println("</tr>");
}
}
LoginServlet
package com.zhaoyanlong;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicInteger;
public class LoginServlet extends HttpServlet {
//統計接口被調用此時
//結合Servlet的生命週期理解多線程中存在共享變量
//private int count=0;錯誤
private AtomicInteger count=new AtomicInteger();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//請求就是告訴編碼返回時以同類型返回
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter out=resp.getWriter();
out.println("<h1>2020</h1>");
out.printf("<p>被訪問次數:%d</p>",count.getAndIncrement());
}
}
SecondServlet
package com.zhaoyanlong;
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("/second")
public class SecondServlet extends HttpServlet {
//通過表單來提交
private void run(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter out=resp.getWriter();
String username=req.getParameter("username");
String password=req.getParameter("password");
out.println("<h1>"+req.getMethod()+"</h1>");
out.println("<p>用戶名:"+username+"</p>");
out.println("<p>密碼:"+password+"</p>");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
run(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
run(req,resp);
}
}
index.css
h1{
font-size: 50px;
color: aqua;
background: blue;
}
index.js
alert("wansui")
web.xml
<?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_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.zhaoyanlong.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
index.html
<!DOCTYPE html>
<html>
<head>
<title>中華人民</title>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html: char; charset=utf-8"/>
<script src="js/index.js"charset="UTF-8"></script>
<link rel="stylesheet"type="text/css"href="css/index.css">
</head>
<body>
<h1>成立l</h1>
<a href="login">站起來</a>
</body>
</html>
Login.html
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<form method="post"action="/second">
<label for="username">用戶名:</label>
<input type="text"name="username" placeholder="請填寫用戶名"/>
<label for="password">密碼:</label>
<input type="password" name="password" placeholder="請輸入密碼"/>
<input type="submit"value="登錄"/>
</form>
</body>
</html>
table.html
<meta charset="UTF-8"/>
<table>
<thead>
<tr>
<th>姓名</th>
<th>趙</th>
</tr>
</thead>
<tbody>
<tr>
<td>年齡</td>
<td>18</td>
</tr>
<tr>
<td>生日</td>
<td>0101</td>
</tr>
<tr>
<td>愛好</td>
<td>籃球</td>
</tr>
</tbody>
</table>