JavaWeb中Servlet的深入講解
Servlet
1 Servlet 簡介
Servlet就是Sun 公司開發(fā)動態(tài)web的一門技術(shù)
Sun在這些API中提供一個(gè)接口叫做:Servlet ,如果你向開發(fā)一個(gè)Servlet程序,只需要完成兩個(gè)小步驟
- 編寫一個(gè)類,實(shí)現(xiàn)Servlet接口
- 把開發(fā)好的Java類部署到web服務(wù)器中
把實(shí)現(xiàn)Servlet接口的Java程序叫做 Servlet
2 HelloServlet
構(gòu)建一個(gè)普通的Maven項(xiàng)目,刪除里面的src目錄。這個(gè)空的工程就是Maven主工程
關(guān)于Maven父子工程的理解:
父項(xiàng)目中會有
<modules> <module>servlet-02</module> </modules>
子項(xiàng)目中會有
<parent> <artifactId>javaweb-02-servlet</artifactId> <groupId>com.srx</groupId> <version>1.0-SNAPSHOT</version> </parent>
父項(xiàng)目中的Java子項(xiàng)目可以直接使用
son extends father
Maven環(huán)境優(yōu)化
- 修改web.xmd為最新的
- 將maven的結(jié)構(gòu)搭建完整
編寫一個(gè)Servlet程序
編寫Servlet的映射
為什么需要映射,我們系的是java程序,但是要通過瀏覽器訪問,而瀏覽器需要連接web服務(wù)器,所以我們需要再web服務(wù)中注冊我們寫的Servlet 還需要給他一個(gè)瀏覽器 能夠訪問的路徑
<!-- 注冊servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.srx.HellowServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>hello</url-pattern> </servlet-mapping>
配置Tomcat
注意:配置項(xiàng)目發(fā)布的路徑就可以了
啟動測試 歐克
3 Servlet 原理
servlet 是由web服務(wù)器調(diào)用,wev服務(wù)器在收到瀏覽器請求之后 會:
4 Mapping 問題
一個(gè)Servlet 可以指定一個(gè)映射路徑
一個(gè)Servlet 可以指定多個(gè)映射路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <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>
一個(gè)Servlet 可以指定通用映射路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
默認(rèn)請求路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
指定一些后綴或者前綴等等…
<!-- 可以自定義后綴實(shí)現(xiàn)請求映射 注意點(diǎn): *前面不能加項(xiàng)目映射路徑 --> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.abc</url-pattern> </servlet-mapping>
優(yōu)先級問題
指定了固有的映射路徑優(yōu)先級最高,如果找不到就會走默認(rèn)的處理請求;
<!--404--> <servlet> <servlet-name>error</servlet-name> <servlet-class>com.srx.Error</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
5 servletContext
web容器在啟動的時(shí)候,它會為每個(gè)web程序都創(chuàng)建一個(gè)對應(yīng)的ServletContext 對象,它代表了當(dāng)前web應(yīng)用。
1.共享數(shù)據(jù)
我在這個(gè)Servlet中保存的數(shù)據(jù),可以在另外一個(gè)servlet中拿到
存放數(shù)據(jù)的類
public class test extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //this.getInitParameter(); //初始化參數(shù) //this.getServletContext(); // servlet 上下文 //this.getServletConfig(); servlet 配置 ServletContext servletContext = this.getServletContext(); String username="我愛學(xué)習(xí)"; //將一個(gè)數(shù)據(jù)保存在ServletContext中 名字為 uesrname 值為 username servletContext.setAttribute("username",username); System.out.println("hello"); } }
輸出的類
public class show extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); String username = (String) servletContext.getAttribute("username"); resp.getWriter().print("姓名:"+username); } }
配置的文件
<servlet> <servlet-name>test</servlet-name> <servlet-class>com.srx.test</servlet-class> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping> <servlet> <servlet-name>getc</servlet-name> <servlet-class>com.srx.show</servlet-class> </servlet> <servlet-mapping> <servlet-name>getc</servlet-name> <url-pattern>/getc</url-pattern> </servlet-mapping>
測試訪問結(jié)果
2.獲取初始化參數(shù)
<!-- 配置一些web的初始化參數(shù)--> <context-param> <param-name>url</param-name> <param-value>JDBC:mysql//localhost:3306/mybatis</param-value> </context-param>
測試類
public class context extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext Context = this.getServletContext(); String url = Context.getInitParameter("url"); resp.getWriter().print(url); } }
路徑
<servlet> <servlet-name>url</servlet-name> <servlet-class>com.srx.context</servlet-class> </servlet> <servlet-mapping> <servlet-name>url</servlet-name> <url-pattern>/url</url-pattern> </servlet-mapping>
3.請求轉(zhuǎn)發(fā)
public class ServletDemo extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("進(jìn)入了這個(gè)方法"); ServletContext context = this.getServletContext(); // RequestDispatcher zf = context.getRequestDispatcher("zf"); //轉(zhuǎn)發(fā)的路徑 // zf.forward(req,resp); //調(diào)用forward 方法 實(shí)現(xiàn)轉(zhuǎn)發(fā) //簡寫 context.getRequestDispatcher("/getc").forward(req,resp); } }
<servlet> <servlet-name>zzz</servlet-name> <servlet-class>com.srx.ServletDemo</servlet-class> </servlet> <servlet-mapping> <servlet-name>zzz</servlet-name> <url-pattern>/zzz</url-pattern> </servlet-mapping>
4.讀取資源文件
properties
- 在java目錄中新建properties
- zairesource目錄下新建properties
發(fā)現(xiàn):都被打包到了同一個(gè)路徑下;classes 我們俗稱這個(gè)路徑為classpath;
思路: 需要一個(gè)文件流
public class ServletDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username"); String pwd = prop.getProperty("password"); resp.getWriter().print(user+":"+pwd); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
映射
<servlet> <servlet-name>bbb</servlet-name> <servlet-class>com.srx.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>bbb</servlet-name> <url-pattern>/bbb</url-pattern> </servlet-mapping>
6、HttpServletResponse
web服務(wù)器接收到客戶端的http請求,針對這個(gè)請求,反別創(chuàng)建一個(gè)代表請求的HttpServletRequest對象,代表響應(yīng)的一個(gè)HttpServletResponse;
- 如果獲取客戶端請求過來的參數(shù) 找 httpServletRequest
- 如果要給客戶端響應(yīng)一些信息:找HttpServletResponse
1下載文件
向?yàn)g覽器輸出信息
2 下載文件
- 要獲取下載文件的路徑
- 下載的文件名是啥
- 設(shè)置想辦法讓瀏覽器支持下載我們所需要的東西
- 獲取下載文件的輸入流
- 創(chuàng)建緩沖區(qū)
- 獲得OutputStream對象
- 將FileOutputStream流寫入到Buffer緩沖區(qū)
- 使用OutputStream將緩沖區(qū)中的數(shù)據(jù)輸出到客戶端。
案例
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // - 要獲取下載文件的路徑 String realPath = "D:\\軟件安裝路徑\\javaweb-02-servlet\\response\\target\\classes\\111.png"; System.out.println("文件的下載路徑"+realPath); // - 下載的文件名是啥 String substring = realPath.substring(realPath.lastIndexOf("\\") + 1); // - 設(shè)置想辦法讓瀏覽器支持下載我們所需要的東西 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(substring,"utf-8")); // - 獲取下載文件的輸入流 FileInputStream in = new FileInputStream(realPath); // - 創(chuàng)建緩沖區(qū) int len = 0; byte[] buffer=new byte[1024]; // - 獲得OutputStream對象 ServletOutputStream outputStream = resp.getOutputStream(); // - 將FileOutputStream流寫入到Buffer緩沖區(qū) 使用OutputStream將緩沖區(qū)中的數(shù)據(jù)輸出到客戶端 while ((len=in.read(buffer))>0){ outputStream.write(buffer,0,len); } in.close(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
3 隨機(jī)刷新的驗(yàn)證碼圖片
public class ImgServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //使瀏覽器2秒刷新一次; resp.setHeader("refresh","0.5"); //在內(nèi)存中創(chuàng)建一個(gè)圖片 BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB); //得到圖片 Graphics2D g = (Graphics2D) image.getGraphics(); //筆 //設(shè)置圖片的背景顏色 g.setColor(Color.white); g.fillRect(0,0,80,20); //給圖片寫數(shù)據(jù) g.setColor(Color.BLUE); g.setFont(new Font(null,Font.BOLD,20)); g.drawString(makeNum(),0,20); //告訴瀏覽器 請求圖片的方式打開 resp.setContentType("image/jpeg"); //網(wǎng)站存在緩存,不讓瀏覽器緩存 resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache"); //把圖片寫給瀏覽器 ImageIO.write(image,"jpg", resp.getOutputStream()); } private String makeNum() { Random random = new Random(); String num=random.nextInt(9999999)+""; StringBuffer sb = new StringBuffer(); for (int i = 0; i <7-num.length(); i++) { sb.append("0"); } num =sb.toString()+num; return num; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
4 重定向
b一個(gè)web資源收到客戶端a請求后,b他回通知a客戶端去訪問另一個(gè)web資源c,這個(gè)過程叫重定向
常見場景:
用戶登錄
void sendRedirect(String var1) throws IOException;
測試:
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // //具體實(shí)現(xiàn) // resp.setHeader("Location","/rr/img"); // resp.setStatus(302); //重定向 resp.sendRedirect("/rr/img"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
面試題:請你聊一聊重定向和轉(zhuǎn)發(fā)的區(qū)別?
相同點(diǎn):
- 頁面都會實(shí)現(xiàn)跳轉(zhuǎn)
不同點(diǎn):
- 請求轉(zhuǎn)發(fā)的時(shí)候 url不會產(chǎn)生變化
- 重定向時(shí)候,url地址欄回發(fā)生變化
總結(jié)
到此這篇關(guān)于JavaWeb中Servlet的文章就介紹到這了,更多相關(guān)JavaWeb中Servlet內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java學(xué)生信息管理系統(tǒng)設(shè)計(jì)(數(shù)據(jù)庫版)
這篇文章主要為大家詳細(xì)介紹了數(shù)據(jù)庫版的Java學(xué)生信息管理系統(tǒng)設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11java.lang.AbstractMethodError: org.apache.xerces.dom.Documen
這篇文章主要介紹了java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion問題解決方法,導(dǎo)致本文問題的原因是缺少一個(gè)xerces.jar jar包,需要的朋友可以參考下2015-03-03Java實(shí)現(xiàn)經(jīng)典游戲泡泡堂的示例代碼
這篇文章將利用Java制作經(jīng)典游戲——泡泡堂,游戲設(shè)計(jì)為雙人pk積分賽模式,在這個(gè)模式里面,玩家只要率先達(dá)到一定分?jǐn)?shù)既可以贏得比賽。感興趣的可以了解一下2022-04-04Spring Security基本架構(gòu)與初始化操作流程詳解
這篇文章主要介紹了Spring Security基本架構(gòu)與初始化操作流程,Spring Security是一個(gè)能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架2023-03-03BCryptPasswordEncoder加密與MD5加密的區(qū)別及說明
這篇文章主要介紹了BCryptPasswordEncoder加密與MD5加密的區(qū)別及說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08java根據(jù)方法名稱取得反射方法的參數(shù)類型示例
利用java反射原理調(diào)用方法時(shí),常先需要傳入方法參數(shù)數(shù)組才能取得方法。該方法參數(shù)數(shù)組采用動態(tài)取得的方式比較合適2014-02-02