首頁>技術>

1. 前置知識

1.1.java註解、反射

1.2.java網路程式設計

1.2.servlet基礎

2. 本章重點

2.1. 回顧tomcat

2.2. 建立xml版本servelt

2.3. 自建xml版本tomcat1.0

2.4. 建立註解版本servlet

2.5. 自建註解版本tomcat2.0

3. 具體內容

3.1. 回顧tomcat

3.1.1. tomcat的概念

Tomcat 伺服器是一個免費的開放原始碼的Web 應用伺服器,屬於輕量級應用,在中小型系統和併發訪問使用者不是很多的場合下被普遍使用,是開發和除錯JSP 程式的首選。對於一個初學者來說,可以這樣認為,當在一臺機器上配置好Apache 伺服器,可利用它響應(下的一個應用)頁面的訪問請求。實際上Tomcat是Apache 伺服器的擴充套件,但執行時它是獨立執行的,所以當你執行tomcat 時,它實際上作為一個與Apache 獨立的程序單獨執行的。訣竅是,當配置正確時,Apache 為HTML頁面服務,而Tomcat 實際上執行JSP 頁面和Servlet。

3.1.2. 建立一個web工程

3.1.2.1. 步驟一:配置tomcat伺服器

3.1.2.2. 建立web工程

3.1.2.3. 補齊工程

3.2. 建立xml版本servelt

3.2.1. 建立一個servlet

package com.aaa.servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/*** @author :Teacher陳* @date :Created in 2021/1/20 9:26* @description:測試一個servlet* @modified By:* @version: 1.0*/public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//業務邏輯System.out.println("HelloServlet is running!");StringBuffer sb= new StringBuffer();sb.append("<html>");sb.append("<body>");sb.append("<h1>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</h1>");sb.append("</body>");sb.append("</html>");resp.getWriter().write(sb.toString());}}

3.2.2. 配置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-name>hello</servlet-name><servlet-class>com.aaa.servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/xxx</url-pattern></servlet-mapping></web-app>

3.2.3. 測試servlet

可以發現,tomcat正常的接收了瀏覽器傳送的請求

tomcat根據請求對映到響應的servlet

抓包工具顯示的請求原始資訊如下:

GET /aaa/xxx HTTP/1.1Host: localhost:8080User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: keep-aliveCookie: JSESSIONID=6E593EFE70D7DE906671505FDBAEEAAC; Hm_lvt_d214947968792b839fd669a4decaaffc=1603700593,1603779032; Idea-661643a5=d5722ef7-628d-418c-960f-6f353393ba3b; cookie_lang=1Upgrade-Insecure-Requests: 1Cache-Control: max-age=0

HelloServelt做出響應,回傳到瀏覽器端

HTTP/1.1 200

Content-Length: 66

Date: Wed, 20 Jan 2021 01:39:37 GMT

3.3. 自建xml版本tomcatv1.0

3.3.1. 思路分析

根據上面的思路,需要設計一下幾個java類

tomcat啟動類

請求實體類

響應實體類

servlet抽象類

servlet的具體實現類

3.3.2. 建立maven專案,引入相關jar

3.3.3. 建立請求類

package com.aaa.tomcat;import lombok.Data;import java.io.IOException;import java.io.InputStream;/*** @author :Teacher陳* @date :Created in 2021/1/20 10:22* @description:自定義的請求類* @modified By:* @version: 1.0*/@Datapublic class RequestAAA {private String method;private String url;private InputStream inputStream;public RequestAAA(InputStream inputStream) throws Exception {byte[] buf= new byte[1024];//定義一個請求字串String requestStr="";//處理inputStream,獲取請求方式和請求地址int count=0;if((count=inputStream.read(buf))>0){requestStr= new String(buf,0,count);}/*** GET /aaa/xxx HTTP/1.1* Host: localhost:8080*///獲取第一行String head = requestStr.split("\n")[0];this.method = head.split("\\s")[0];this.url=head.split("\\s")[1];}}

3.3.4. 建立響應類

package com.aaa.tomcat;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.IOException;import java.io.OutputStream;/*** @author :Teacher陳* @date :Created in 2021/1/20 10:35* @description:自創響應類* @modified By:* @version: 1*/@Data@AllArgsConstructor@NoArgsConstructorpublic class ResponseAAA {private OutputStream outputStream;/*** @create by: Teacher陳* @description:將內容寫回瀏覽器* @create time: 2021/1/20 10:37* @param context* @return void*/public void write(String context) throws IOException {StringBuffer stringBuffer = new StringBuffer();stringBuffer.append("HTTP/1.1 200\r\n");stringBuffer.append("Content-Type: text/html\r\n");stringBuffer.append("\r\n");stringBuffer.append("<html>");stringBuffer.append("<body>");stringBuffer.append(context);stringBuffer.append("</body>");stringBuffer.append("</html>");outputStream.write(stringBuffer.toString().getBytes());outputStream.flush();outputStream.close();}}

3.3.5. 建立servlet對映類

package com.aaa.tomcat;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;/*** @author :Teacher陳* @date :Created in 2021/1/20 10:45* @description:servlet對映類* @modified By:* @version: 1*/@Data@AllArgsConstructor@NoArgsConstructorpublic class ServletMappingAAA {/*** 對應web.xml中的servlet url-pattern*/private String url;/***對應web.xml中的servlet-class*/private String clazz;}

3.3.6. 建立servlet抽象類

package com.aaa.tomcat;import java.io.IOException;/*** @author :Teacher陳* @date :Created in 2021/1/20 10:48* @description:我自己的servlet* @modified By:* @version: 1*/public abstract class ServletAAA {/*** @create by: Teacher陳* @description: 處理get請求* @create time: 2021/1/20 10:51* @return*/public abstract void doGet(RequestAAA req, ResponseAAA resp) ;/*** @create by: Teacher陳* @description: 處理post請求* @create time: 2021/1/20 10:51* @return*/public abstract void doPost(RequestAAA req, ResponseAAA resp);/*** @create by: Teacher陳* @description: 根據請求方式,去進入不同的處理方法* @create time: 2021/1/20 10:55* @param req, resp*/public void service(RequestAAA req, ResponseAAA resp){if("GET".equalsIgnoreCase(req.getMethod())){doGet(req,resp);}else if("POST".equalsIgnoreCase(req.getMethod())){doPost(req,resp);}}}

3.3.7. 建立servlet實現類

package com.aaa.tomcat;import java.io.IOException;/*** @author :Teacher陳* @date :Created in 2021/1/20 10:56* @description:測試servlet* @modified By:* @version: 1*/public class HelloServlet extends ServletAAA {@Overridepublic void doGet(RequestAAA req, ResponseAAA resp) {this.doPost(req,resp);}@Overridepublic void doPost(RequestAAA req, ResponseAAA resp) {System.out.println("HelloServlet is called");try {resp.write(" I love you ");} catch (IOException e) {e.printStackTrace();}}}

3.3.8. 建立tomcat類

package com.aaa.tomcat;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;/*** @author :Teacher陳* @date :Created in 2021/1/20 11:00* @description:AAA的tomcat* @modified By:* @version: 1*/public class TomcatAAA {/*** 1:透過serverSoket啟動一個監聽程式,監聽8080埠* 2:socket物件可以獲取inputstream請求位元組流,還可以獲取響應outputStream* 3:從請求中解析http報文,獲取請求方式和請求地址* 4:根據請求地址獲取servlet類,然後根據請求方式執行servlet中對應的邏輯處理方法* 5:構建響應物件,響應給瀏覽器*/private int port = 9090;/*** 定義一個servlet對映集合*/private Map<String, String> urlServletMap = new HashMap();public TomcatAAA(int port) {this.port = port;}public TomcatAAA() {}/*** @return* @create by: Teacher陳* @description: 啟動tomcat* @create time: 2021/1/20 11:04*/public void start() {ServerSocket serverSocket = null;Socket socket = null;try {serverSocket = new ServerSocket(this.port);System.out.println("tomcat is running");while (true) {//等待客戶端請求socket = serverSocket.accept();//獲取客戶端傳送的資訊InputStream inputStream = socket.getInputStream();//響應客戶端的資訊OutputStream outputStream = socket.getOutputStream();//構建請求和響應RequestAAA requestAAA = new RequestAAA(inputStream);ResponseAAA responseAAA = new ResponseAAA(outputStream);//獲取servletServletMappingAAA servletMappingAAA = new ServletMappingAAA("/yyy", "com.aaa.tomcat.TestServlet");Class<ServletAAA> servletAAAClass = (Class<ServletAAA>) Class.forName(servletMappingAAA.getClazz());ServletAAA servletAAA = servletAAAClass.newInstance();servletAAA.service(requestAAA, responseAAA);}} catch (Exception e) {e.printStackTrace();} finally {try {socket.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {TomcatAAA tomcatAAA = new TomcatAAA();tomcatAAA.start();}}

3.3.9. 建立tomcatv1.1類,支援讀取web.xml中單個servlet

web.xml<web-app><servlet><servlet-name>hello</servlet-name><servlet-class>com.aaa.tomcat.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/ooo</url-pattern></servlet-mapping></web-app>//在tomcat啟動的時候載入所有的url和servlet的對映關係Document docResult= XmlUtil.readXML("web.xml");Object clazz = XmlUtil.getByXPath("//web-app/servlet/servlet-class", docResult, XPathConstants.STRING);Object url = XmlUtil.getByXPath("//web-app/servlet-mapping/url-pattern", docResult, XPathConstants.STRING);urlServletMap.put(url.toString(),clazz.toString());

3.3.10. 建立tomcatV1.2,讀取web.xml中多個servlet

上面的案例可以讀取單個servlet配置資訊,真實的web.xml中包含多個servlet配置。

web.xml

<web-app><servlet><servlet-name>hello</servlet-name><servlet-class>com.aaa.tomcat.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/ooo</url-pattern></servlet-mapping><servlet><servlet-name>test</servlet-name><servlet-class>com.aaa.tomcat.TestServlet</servlet-class></servlet><servlet-mapping><servlet-name>test</servlet-name><url-pattern>/zzz</url-pattern></servlet-mapping></web-app>

建立讀取web.xml的工具類

package com.aaa.tomcat;import cn.hutool.core.collection.SpliteratorUtil;import cn.hutool.core.util.XmlUtil;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import javax.xml.xpath.XPathConstants;import java.util.*;/*** @author :Teacher陳* @date :Created in 2021/1/20 14:59* @description:我自己的xml工具類* @modified By:* @version: 1.0*/public class MyXmlUtil {/*** @create by: Teacher陳* @description: 讀取web.xml檔案* @create time: 2021/1/20 16:41* @return map*/public static Map<String, String> loadWebXml() {//載入web.xmlDocument docResult = XmlUtil.readXML("web.xml");//將Document轉換成ElementElement element = docResult.getDocumentElement();//按照元素名稱servlet查詢所有的元素List<Element> elementList = XmlUtil.getElements(element, "servlet");//key servletName value clazzMap<String, String> servletMap = new HashMap();//遍歷servlet元素for (Element elementServlet : elementList) {//獲取單個servlet元素的所有孩子NodeList childNodes = elementServlet.getChildNodes();List<String> tempList = new ArrayList<String>();//遍歷所有孩子節點for (int i = 0; i < childNodes.getLength(); i++) {//去除多餘的特殊字元和空格String textContent = childNodes.item(i).getTextContent().trim().replace("\\n", "").replace("\\t", "");if (textContent != "" && textContent.length() > 0) {tempList.add(textContent);}}//key servletName value clazz 封裝map集合servletMap.put(tempList.get(0), tempList.get(1));}//key servletName value urlMap<String, String> servletMappingMap = new HashMap();List<Element> elementListMapping = XmlUtil.getElements(element, "servlet-mapping");for (Element elementMapping : elementListMapping) {NodeList childNodes = elementMapping.getChildNodes();List<String> tempList = new ArrayList<String>();for (int i = 0; i < childNodes.getLength(); i++) {String textContent = childNodes.item(i).getTextContent().trim().replace("\\n", "").replace("\\t", "");if (textContent != "" && textContent.length() > 0) {tempList.add(textContent);}}servletMappingMap.put(tempList.get(0), tempList.get(1));}//合併兩個mapSet<String> keySet = servletMappingMap.keySet();Map<String, String> finalMap = new HashMap();for (String s : keySet) {finalMap.put(servletMappingMap.get(s), servletMap.get(s));}System.out.println(finalMap.toString());return finalMap;}}

tomcat啟動類

TomcatAAA

package com.aaa.tomcat;import cn.hutool.core.util.XmlUtil;import org.w3c.dom.Document;import javax.xml.xpath.XPathConstants;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;/*** @author :Teacher陳* @date :Created in 2021/1/20 11:00* @description:AAA的tomcat* @modified By:* @version: 1*/public class TomcatAAA {/*** 1:透過serverSoket啟動一個監聽程式,監聽8080埠* 2:socket物件可以獲取inputstream請求位元組流,還可以獲取響應outputStream* 3:從請求中解析http報文,獲取請求方式和請求地址* 4:根據請求地址獲取servlet類,然後根據請求方式執行servlet中對應的邏輯處理方法* 5:構建響應物件,響應給瀏覽器*/private int port = 9090;/*** 定義一個servlet對映集合,key url , value clazz*/private Map<String, String> urlServletMap = new HashMap();public TomcatAAA(int port) {this.port = port;}public TomcatAAA() {}/*** @return* @create by: Teacher陳* @description: 啟動tomcat* @create time: 2021/1/20 11:04*/public void start() {//載入所有的url和servlet的對映關係urlServletMap = MyXmlUtil.loadWebXml();ServerSocket serverSocket = null;Socket socket = null;try {serverSocket = new ServerSocket(this.port);System.out.println("tomcat is running");while (true) {//等待客戶端請求socket = serverSocket.accept();//獲取客戶端傳送的資訊InputStream inputStream = socket.getInputStream();//響應客戶端的資訊OutputStream outputStream = socket.getOutputStream();//構建請求和響應RequestAAA requestAAA = new RequestAAA(inputStream);ResponseAAA responseAAA = new ResponseAAA(outputStream);//獲取servletfor (Map.Entry<String, String> entry : urlServletMap.entrySet()) {if (entry.getKey().equals(requestAAA.getUrl())) {Class<ServletAAA> servletAAAClass = (Class<ServletAAA>) Class.forName(entry.getValue());ServletAAA servletAAA = servletAAAClass.newInstance();servletAAA.service(requestAAA, responseAAA);}}}} catch (Exception e) {e.printStackTrace();} finally {try {socket.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {TomcatAAA tomcatAAA = new TomcatAAA();tomcatAAA.start();}}

3.4. 建立註解版本servlet

3.4.2. 在servlet上添加註解

package com.aaa.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;/*** @author :Teacher陳* @date :Created in 2021/1/20 9:26* @description:測試一個servlet* @modified By:* @version: 1.0*/@WebServlet(urlPatterns = "/xxx")public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//業務邏輯System.out.println("HelloServlet is running!");StringBuffer sb= new StringBuffer();sb.append("<html>");sb.append("<body>");sb.append("<h1>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</h1>");sb.append("</body>");sb.append("</html>");resp.getWriter().write(sb.toString());}}

3.5. 自建註解版本tomcatV2.0

3.5.1. 建立servlet註解

package com.aaa.tomcat;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @create by: Teacher陳* @description: 自定義的servlet註解* @create time: 2021/1/20 16:51* @return*/@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface MyWebServlet {/*** 需要攔截的url,可以是多個* @return*/String[] urlPatterns() default {};}

3.5.2. 建立servlet

package com.aaa.servlet;import com.aaa.tomcat.MyWebServlet;import com.aaa.tomcat.RequestAAA;import com.aaa.tomcat.ResponseAAA;import com.aaa.tomcat.ServletAAA;import java.io.IOException;/*** @author :Teacher陳* @date :Created in 2021/1/20 16:54* @description:註解的servlet* @modified By:* @version: 1*/@MyWebServlet(urlPatterns = "/aaa")public class AnnServlet extends ServletAAA {@Overridepublic void doGet(RequestAAA req, ResponseAAA resp) {this.doPost(req,resp);}@Overridepublic void doPost(RequestAAA req, ResponseAAA resp) {System.out.println("AnnServlet is called");try {System.out.println("response is running ");resp.write(" I miss you ");} catch (IOException e) {e.printStackTrace();}}}

3.5.3. 掃描並解析註解

/*** @create by: Teacher陳* @description: 掃描所有的sevlet註解* @create time: 2021/1/20 16:58* @param packageName* @return*/public static Map<String, String> loadServletAnn(String packageName) {if(packageName==null||packageName.equals("")){packageName="com.aaa.servlet";}Reflections reflections= new Reflections(packageName);Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(MyWebServlet.class);Map<String,String> map = new HashMap<String, String>();for (Class<?> aClass : classSet) {MyWebServlet annotation = aClass.getAnnotation(MyWebServlet.class);map.put(annotation.urlPatterns()[0],aClass.getName());}return map;}

3.5.4. 測試

4. 本章總結

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 剖析一站式分散式事務方案SeataFescar-Server