来谈谈Servlet~~
目錄
- 1、Servlet簡介
- 2、第一個Servlet程序
- 3、Servlet原理
- 4、servlet-mapping的配置
- 5、關于ServletContext
- 1、共享數據
- 2、獲取初始化參數
- 3、請求轉發
- 4、讀取資源文件
- 6、HttpServletResponse
- 1、簡單分類
- 2、常見應用
- 7、HttpServletRequest
1、Servlet簡介
- Servlet就是sun公司開發動態web的一門技術
- Java Servlet 是運行在 Web 服務器或應用服務器上的程序,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 服務器上的數據庫或應用程序之間的中間層。
- Sun在這些API提供了一個接口叫做:Servlet,如果你想開發一個Servlet程序,只需要完成兩個小步驟:
- 編寫一個類,實現Servlet接口
- 把開發好的Java類部署web服務器中
把實現了Servlet接口的Java程序叫做 Servlet
2、第一個Servlet程序
Servlet接口SUN公司定義了兩個默認實現類,分別為:GenericServlet、HttpServlet。
-
構建一個maven項目,刪掉里面的src目錄,以后就在這里面建立Moudel;這個空的工程就是Maven的主工程
-
關于Maven父子工程的理解
父項目中會有
<modules><module>servlet_01</module> </modules>子項目中會有
<parent><artifactId>HelloServlet</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version> </parent>父項目中的jar包子項目可以直接使用,但子項目中的jar包父項目不能直接使用
-
Maven環境優化
-
修改子工程web.xml為最新的,默認版本太老,我們替換為webapp4.0版本和tomcat一致!
<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app> -
將maven的結構搭建完整(添加java目錄和resource目錄,并做相關標記)
-
-
編寫一個Servlet程序
- 編寫一個普通類實現Servlet接口,這里我們直接繼承HttpServlet
package com.zsr.servlet;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;public class HelloServlet extends HttpServlet {//由于get或者post只是請求實現的不同方式,可以相互調用,業務邏輯都一樣@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {PrintWriter writer = resp.getWriter();//響應流writer.print("Hello,Servlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);} } -
編寫Servlet映射
- 為什么需要映射??
- 因為我們寫的是Java程序,但是要通過瀏覽器訪問,而瀏覽器需要連接web服務器,所以我們需要在web服務器中注冊我們寫的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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><!--注冊Servlet--><servlet><servlet-name>hello</servlet-name><servlet-class>com.zsr.servlet.HelloServlet</servlet-class></servlet><!--Servlet請求路徑--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping> </web-app> - 為什么需要映射??
-
配置Tomcat
-
啟動測試
3、Servlet原理
4、servlet-mapping的配置
-
一個Servlet可以指定一個映射路徑
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping> -
一個Servlet可以指定多個映射路徑
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello1</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello3</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello4</url-pattern> </servlet-mapping> -
一個Servlet可以指定通用映射路徑
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello/*</url-pattern> </servlet-mapping> -
默認請求路徑(盡量不用)
<!--默認請求路徑--> <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/*</url-pattern> </servlet-mapping> -
指定一些后綴或者前綴登等…
<!--自定義后綴實現請求路徑注意!!*前面不能加映射的路徑hello/sfasgs.zsr以.zsr結尾即可--> <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>*.zsr</url-pattern> </servlet-mapping> -
優先級問題
指定了固有映射路徑的優先級最高,如果找不到就會走默認的處理請求
5、關于ServletContext
web容器在啟動的時候,它會為每一個web程序創建一個對應的ServletContext對象,它代表了當前的web應用;
ServletContext實例是通過 **getServletContext()**方法獲得
-
是一個域對象
-
域對象是服務器在內存上創建的存儲空間,用于在不同動態資源(servlet)之間傳遞與共享數據。
-
凡是域對象都有如下3個方法:
setAttribute(name,value);//name是String類型,value是Object類型;往域對象里面添加數據,添加時以key-value形式添加getAttribute(name);//根據指定的key讀取域對象里面的數據removeAttribute(name);//根據指定的key從域對象里面刪除數據
-
-
可以讀取全局配置參數
-
getServletContext().getInitParameter(name);//根據指定的參數名獲取參數值getServletContext().getInitParameterNames();//獲取所有參數名稱列表
-
-
可以搜索當前工程目錄下面的資源文件
-
getServletContext().getRealPath(path);//根據相對路徑獲取服務器上資源的絕對路徑getServletContext().getResourceAsStream(path);//根據相對路徑獲取服務器上資源的輸入字節流
-
-
可以獲取當前工程名字
-
getServletContext().getContextPath();//獲取當前工程名字
-
1、共享數據
? 我在這個Servlet中保存的數據,可以在另外一個Servlet中拿到;
- 放置數據的類 HellowServlet:
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter() 初始化參數
// this.getServletConfig() Servlet配置
// this.getServletContext() Servlet上下文參數ServletContext context = this.getServletContext();String name = "zsr";context.setAttribute("username", name);//將一個數據放在了ServletContext中,名字為username,值為name}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
- 讀取數據的類 GetServlet:
public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("名字" + username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
- 配置web.xml,對HelloServlet和GetServlet添加對應的注冊和請求路徑
<!--對HelloServlet添加注冊和請求路徑-->
<servlet><servlet-name>hello</servlet-name><servlet-class>com.zsr.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping><!--對GetServlet添加注冊和請求路徑-->
<servlet><servlet-name>getusername</servlet-name><servlet-class>com.zsr.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>getusername</servlet-name><url-pattern>/username</url-pattern>
</servlet-mapping>
- 測試訪問結果:
? 打開瀏覽器,先訪問localhost:8080/s1/hello,在訪問localhost:8080/s1/username,就可以獲取名字
2、獲取初始化參數
- 在web.xml里配置以下web應用的初始化參數
<!--配置一些web應用的初始化參數-->
<context-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
- 獲取初始化參數的類Servlet03:
public class Servlet03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String url = context.getInitParameter("url");resp.getWriter().print(url);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
- 配置web.xml,給Servlet03類添加注冊和請求路徑
<!--Servlet03類-->
<servlet><servlet-name>initial</servlet-name><servlet-class>com.zsr.servlet.Servlet03</servlet-class>
</servlet>
<servlet-mapping><servlet-name>initial</servlet-name><url-pattern>/initial</url-pattern>
</servlet-mapping>
- 測試訪問結果:
? 打開瀏覽器,訪問localhost:8080/s1/initial,獲取到初始參數
3、請求轉發
- 請求轉發的類Servlet04
public class Servlet04 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();System.out.println("進入了s4");
// RequestDispatcher requestDispatcher = context.getRequestDispatcher("/initial");//轉發請求路徑
// requestDispatcher.forward(req, resp);//調用forward方法請求轉發context.getRequestDispatcher("/initial").forward(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
- 配置web.xml,對Servlet04添加對應的注冊和請求路徑
<!--Servlet04類-->
<servlet><servlet-name>dispatch</servlet-name><servlet-class>com.zsr.servlet.Servlet04</servlet-class>
</servlet>
<servlet-mapping><servlet-name>dispatch</servlet-name><url-pattern>/dispatch</url-pattern>
</servlet-mapping>
- 測試訪問結果:
? 打開瀏覽器,訪問localhost:8080/s1/dispatch,顯示與localhost:8080/s1/initial同樣的頁面,實現了請求與轉發(路徑不用改變,重定向的路徑需要改變!!!)
4、讀取資源文件
Properties
- 在java目錄下新建properties
- 在resources目錄下新建properties
發現:都被打包到了同一個路徑下:classes,我們俗稱這個路徑為類路徑(classpath)
思路:需要一個文件流
db.properties/db1.properties:
username=zsr
password=200024
public class Servlet05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//第一個/代表當前web項目InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/zsr/servlet/db1.properties");Properties prop = new Properties();prop.load(is);String user = prop.getProperty("username");String pwd = prop.getProperty("password");resp.getWriter().print(user + ":" + pwd);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
添加對應的注冊和請求路徑,訪問測試即可;
6、HttpServletResponse
web服務區接收到客戶端http請求,針對這個請求,分別創建一個代表請求的HttpServletRequest對象,代表響應的一個HttpServletResponse;
- 我們如果要獲取客戶端請求過來的參數:找HttpServletRequest
- 如果要給客戶端響應一些信息:找HttpServletResponse
1、簡單分類
負責向瀏覽器發送數據的方法:
ServletOutputStream getOutputStream() throws IOException;PrintWriter getWriter() throws IOException;
負責向瀏覽器發送響應頭的方法:
void setCharacterEncoding(String var1);void setContentLength(int var1);void setContentLengthLong(long var1);void setContentType(String var1);void setDateHeader(String var1, long var2);void addDateHeader(String var1, long var2);void setHeader(String var1, String var2);void addHeader(String var1, String var2);void setIntHeader(String var1, int var2);void addIntHeader(String var1, int var2);
響應的狀態碼:
int SC_CONTINUE = 100;int SC_SWITCHING_PROTOCOLS = 101;int SC_OK = 200;int SC_CREATED = 201;int SC_ACCEPTED = 202;int SC_NON_AUTHORITATIVE_INFORMATION = 203;int SC_NO_CONTENT = 204;int SC_RESET_CONTENT = 205;int SC_PARTIAL_CONTENT = 206;int SC_MULTIPLE_CHOICES = 300;int SC_MOVED_PERMANENTLY = 301;int SC_MOVED_TEMPORARILY = 302;int SC_FOUND = 302;int SC_SEE_OTHER = 303;int SC_NOT_MODIFIED = 304;int SC_USE_PROXY = 305;int SC_TEMPORARY_REDIRECT = 307;int SC_BAD_REQUEST = 400;int SC_UNAUTHORIZED = 401;int SC_PAYMENT_REQUIRED = 402;int SC_FORBIDDEN = 403;int SC_NOT_FOUND = 404;int SC_METHOD_NOT_ALLOWED = 405;int SC_NOT_ACCEPTABLE = 406;int SC_PROXY_AUTHENTICATION_REQUIRED = 407;int SC_REQUEST_TIMEOUT = 408;int SC_CONFLICT = 409;int SC_GONE = 410;int SC_LENGTH_REQUIRED = 411;int SC_PRECONDITION_FAILED = 412;int SC_REQUEST_ENTITY_TOO_LARGE = 413;int SC_REQUEST_URI_TOO_LONG = 414;int SC_UNSUPPORTED_MEDIA_TYPE = 415;int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;int SC_EXPECTATION_FAILED = 417;int SC_INTERNAL_SERVER_ERROR = 500;int SC_NOT_IMPLEMENTED = 501;int SC_BAD_GATEWAY = 502;int SC_SERVICE_UNAVAILABLE = 503;int SC_GATEWAY_TIMEOUT = 504;int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2、常見應用
-
向瀏覽器輸出消息
-
下載文件
- 獲取文件下載的路徑
- 獲取下載的文件名
- 設置瀏覽器支持我們所下載的東西
- 獲取下載文件的輸入流
- 創建緩沖區
- 獲取OutputStream對象
- 將FileOutputStream寫出到緩沖區
- 使用OutputStream將緩沖區的數據輸出到客戶端
public class FileServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1、獲取下載文件的路徑String path = "D:/學習/IDEA project/HelloServlet/response/src/main/resources/鐘嗣儒.jpg";System.out.println("下載的文件路徑為:" + path);//2、獲取下載的文件名String fileName = path.substring(path.lastIndexOf("\\") + 1);//3、設置讓瀏覽器支持下載我們所需要的東西,中文文件名URLEncoder.encode編碼,否則有可能亂碼resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));//4、獲取下載文件到輸入流FileInputStream in = new FileInputStream(path);//5、創建緩沖區int len = 0;byte b[] = new byte[1024];//6、獲取OutputStream對象ServletOutputStream out = resp.getOutputStream();//7、將FileOutputStream流寫入到buffer緩沖區,使用OutputStream將緩沖區中的數據輸出到客戶端while ((len = in.read(b)) != -1) {out.write(b, 0, len);}out.close();in.close();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
- 驗證碼功能
驗證怎么來的?
- 前端實現
- 后端實現,需要用到Java的圖片類,生成一個圖片
public class ImageServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//如何讓瀏覽器3秒自動刷新一次resp.setHeader("refresh", "3");//在內存中創建一個圖片BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);//得到圖片Graphics2D g = (Graphics2D) image.getGraphics();//筆//設置圖片的背景顏色g.setColor(Color.white);g.fillRect(0, 0, 80, 20);//給圖片寫數據g.setColor(Color.blue);g.setFont(new Font(null, Font.BOLD, 20));g.drawString(makeNum(), 0, 20);//告訴瀏覽器,這個請求用圖片的方式打開resp.setContentType("image/jpeg");//網站存在緩存,不讓瀏覽器緩存resp.setDateHeader("expires", -1);resp.setHeader("Cache-Control", "no-cache");resp.setHeader("Pragma", "no-cache");//把圖片交給瀏覽器ImageIO.write(image, "jpg", resp.getOutputStream());}public String makeNum() {Random random = new Random();String num = random.nextInt(9999999) + "";StringBuilder sb = new StringBuilder();for (int i = 0; i < 7 - num.length(); i++) {sb.append("0");}num = sb.toString() + sb;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
- 實現重定向
一個web資源收到客戶端請求,他會通知客戶端會訪問另外一個web資源,這個過程叫做重定向
常見場景:
- 用戶登錄
public void sendRedirect(String location) throws IOException;
- 測試代碼
public class RedirectServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.sendRedirect("/imageServlet");//重定向/*** 等價于兩步* resp.setHeader("Location", "/imageServlet");* resp.setStatus(302);*/}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
面試題:請你聊聊重定向和轉發的區別?
- 相同點:
- 頁面都會跳轉
- 不同點
- 請求轉發的時候,url不會發生變化
- 重定向的時候,url地址欄會發生變化
案例:表單提交,獲取用戶名和密碼
index.jsp:
<html>
<body>
<h2>Hello World!</h2>
<%--這里提交的路徑,需要找到項目的路徑--%>
<%--${pageContext.request.contextPath}代表當前項目--%>
<form action="${pageContext.request.contextPath}/login" method="get">用戶名: <input type="text" name="username"> <br>密碼: <input type="password" name="password"><input type="submit">
</form>
</body>
</html>
success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Success</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>
RequestTest.java:
public class RequestTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//處理請求String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username + ":" + password);//重定向的時候一定要注意路徑問題,否則404resp.sendRedirect("/success.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
在web.xml添加對應的注冊
<servlet><servlet-name>Request</servlet-name><servlet-class>com.zsr.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping><servlet-name>Request</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>
測試:
7、HttpServletRequest
代表客戶端的請求,用戶通過Http協議訪問服務器,Http請求中的所有信息會被封裝到HttpServletRequest中,通過這個HttpServletRequest的方法,可以獲取客戶端的所有信息
獲取前端傳遞的參數,并且請求轉發
index.jsp:(通過Post方式請求)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>登錄</h1>
<div style="text-align: center"><%--這里表單表示的意思:以post的方式提交表單,提交到我們的login請求--%><form action="${pageContext.request.contextPath}/login" method="post">用戶名:<input type="text" name="username">登錄:<input type="password" name="password">愛好:<input type="checkbox" name="hobbies" value="Coding">Coding<input type="checkbox" name="hobbies" value="Sing">Sing<input type="checkbox" name="hobbies" value="Playing">Playing<input type="checkbox" name="hobbies" value="Guitar">Guitar<input type="submit"></form>
</div>
</body>
</html>
重定向頁面success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>你成功啦!</title>
</head>
<body>
<h1>SUCCESS~</h1>
</body>
</html>
獲取前端傳遞的參數,并且請求轉發的類:LoginServlet
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");String hobbies[] = req.getParameterValues("hobbies");System.out.println(username);System.out.println(password);System.out.println(Arrays.toString(hobbies));//通過請求轉發req.getRequestDispatcher("/success.jsp").forward(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
總結
以上是生活随笔為你收集整理的来谈谈Servlet~~的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新Maven及Tomcat配置~(ID
- 下一篇: 你想了解的Cookie和Session就