Servlet技術(shù)

一、JavaWeb概述

1. 什么是Javaweb

JavaWeb是指所有通過Java語言編寫,可以通過瀏覽器訪問的程序的總稱。

JavaWeb是基于請求和響應(yīng)來開發(fā)的。

請求:Request

響應(yīng):Response

客戶端(瀏覽器) 服務(wù)器(Tomcat等)

2. Web資源分類

  • 靜態(tài)資源:HTML,CSS,JS,txt,mp4,jpg等等
  • 動態(tài)資源:jsp頁面,servlet程序

3. 常用Web服務(wù)器

  • Tomcat:提供對jsp和servlet的支持,是一種輕量級的JavaWeb容器
  • Jboss
  • GlassFish
  • Resin
  • WebLogic

4. Tomcat的使用

①Tomcat目錄中的webapps文件夾存放部署的Web工程

②啟動Tomcat,找到bin目錄下的startup.bat文件?;蛘吖芾韱T權(quán)限下的cmd,輸入startup。

③測試是否啟動成功,訪問本機(jī)真實(shí)地址或者(localhost:8080)

④停止Tomcat的方式:找到tomcat的bin目錄下的shutdown.bat按鈕

⑤如何修改Tomcat的端口號:
mysql默認(rèn)3306,Tomcat默認(rèn)8080
server.xml配置文件下的Connector標(biāo)簽,修改port屬性,修改完端口號之后要重啟Tomcat

⑥HTTP協(xié)議默認(rèn)端口是80

部署Web工程到Tomcat服務(wù)器

Tomcat是一個服務(wù)器,供客戶端訪問Web工程。

  • 直接把Web工程拷貝到Tomcat的webapps下如何訪問Web工程。先localhost:8080(這一步就相當(dāng)于切入到webapps文件夾下)然后再加上這里面某個html文件的路徑即可
image-20200608100549501.png

IDEA整合Tomcat服務(wù)器

  • 全局添加服務(wù)器
image-20200608100326929.png
  • 單個工程添加服務(wù)器

Server&Deployment

  • 配置工程輸出路徑
image-20200608100828701.png
  • 解決服務(wù)器控制臺輸出亂碼
image-20200608100929905.png

二、Servlet

1. 什么是Servlet

  1. Servlet是JavaEE規(guī)范之一,規(guī)范就是接口
  2. Servlet是JavaWeb三大組件之一,三大組件分別是Servlet程序,F(xiàn)ilter過濾器,Listener監(jiān)聽器
  3. Servlet是運(yùn)行在服務(wù)器上的一個Java小程序它可以接收客戶端發(fā)送過來的請求,并響應(yīng)客戶的請求。Tomcat等服務(wù)器相當(dāng)于容器,里面裝了許多Servlet。

2. 實(shí)現(xiàn)Servlet程序

  1. 編寫一個類去實(shí)現(xiàn)Servlet接口

  2. 實(shí)現(xiàn)service方法,處理請求并響應(yīng)請求得到數(shù)據(jù)(抽象類HttpServlet中service方法就包含了doGet,doPost,doDelete等等所有請求類型的方法

  3. 到web.xml文件中去配置Servlet程序的訪問地址

    <-- servlet標(biāo)簽:給Tomcat配置Servlet程序-->
    <servlet>
        <-- servlet-name標(biāo)簽:給servlet程序起一個別名(別名一般是該servlet實(shí)現(xiàn)類的類名)-->
        <servlet-name>MyServletImpl</servlet-name>
        <-- 上面那個servlet的全限定類名-->
        <servlet-class>com.zt.MyServletImpl</servlet-class>
    </servlet>
    
    <-- servlet-mapping標(biāo)簽:給servlet程序配置一個訪問地址-->
    <servlet-mapping>
        <-- 該處servlet-name標(biāo)簽作用是:告訴服務(wù)器,當(dāng)前mapping標(biāo)簽配置的地址給哪個servlet程序用
        一般和上面那個一致,就表示該地址就給該servlet程序用-->
        <servlet-name>MyServletImpl</servlet-name>
        <-- url-pattern標(biāo)簽:用來配置訪問地址
        /:"/"在服務(wù)器解析的時(shí)候,被解析為:http://ip:port/工程路徑/。其中工程路徑就是配置Tomcat時(shí)的Deployment中的context
        /hello:這表示http://ip:port/工程路徑/hello,即該servlet程序要去訪問這個地址,然后執(zhí)行service方法
        -->
        <url-pattern>/hello</url-pattern>  //在開發(fā)的時(shí)候一般遵守習(xí)慣:/xxx,xxx的內(nèi)容與類名有關(guān)聯(lián)
    </servlet-mapping>
    

3. Servlet生命周期

  1. 執(zhí)行Servlet構(gòu)造方法
  2. 執(zhí)行init()初始化方法
  3. 執(zhí)行service()方法,每次調(diào)用Servlet都會調(diào)用該方法
  4. 執(zhí)行destroy()方法

4. 通過繼承HttpServlet實(shí)現(xiàn)Servlet程序

一般實(shí)際開發(fā)項(xiàng)目中,都是使用繼承HttpServlet類(它實(shí)現(xiàn)了Servlet接口,它是個抽象類)去實(shí)現(xiàn)Servlet程序

①編寫一個類繼承HttpServlet

②根據(jù)業(yè)務(wù)需要重寫doGet()doPost()等方法

③到web.xml文件中配置Servlet程序的訪問地址


ServletConfig類

Servlet程序的配置類,它是某個servlet應(yīng)用程序的config,不是全局的config

作用:

(1)可以獲取Servlet程序的別名servlet-name

(2)獲取初始化參數(shù)init-param

(3)獲取ServletContext對象

ServletContext類

這是一個全局的對象,作用域?yàn)檎麄€Web工程,可以用它去做一些全局性的配置,也可以獲得全局的屬性

image-20200608105748297.png
  1. ServletContex是一個接口,它表示Servlet上下文對象

  2. 一個Web工程只有一個ServletContext對象實(shí)例,相對于每個servlet程序而言

  3. ServletContext對象是一個域?qū)ο?/p>

  4. ServletContext在web工程部署的時(shí)候創(chuàng)建,在web工程停止的時(shí)候銷毀

    存數(shù)據(jù) 取數(shù)據(jù) 刪除數(shù)據(jù)
    Map put get remove
    域?qū)ο?/strong> setAttribute getAttribute removeAttribute
HttpServletRequest類(實(shí)現(xiàn)ServletRequest接口)
  • 作用
    每次只要有請求進(jìn)入Tomcat服務(wù)器,Tomcat服務(wù)器就會把請求過來的HTTP協(xié)議信息解析好封裝到HttpServletRequest對象中,然后傳遞到service方法(doGet,doPost)中給我們使用。我們可以通過HttpServletRequest對象,獲取到請求的所有信息

  • HttpServletRequest常用API

    String getContextPath():獲取Web工程相對路徑(Tomcat服務(wù)器中除去http://ip:port) 
    System.out.println(req.getContextPath());
    /Temp
    
    URI getRequestURI():獲取請求的資源路徑,相對路徑,某Web工程下的路徑
    System.out.println(req.getRequestURI());
    /Temp/hello
    
    URL getRequestURL():獲取請求的統(tǒng)一資源定位符(絕對路徑)
    System.out.println(req.getRequestURL());
    http://localhost:8080/Temp/hello
    
    String getRemoteHost():獲取客戶端的ip地址
    String getParameter():獲取請求的參數(shù)
    String getParameterValues():獲取請求的參數(shù)(多個值時(shí))  可以用于獲取用戶輸入的值,如用戶名。
    String getHeader():獲取請求頭
    String getMethod():獲取請求的方式GET或POST
    setAttribute(key,value):設(shè)置域數(shù)據(jù)
    Object getAttribute(key):獲取域數(shù)據(jù)
    getRequestDispatcher("/+servlet名"):獲取下一個轉(zhuǎn)發(fā)對象。必須以斜杠開頭
    RequestDispatcher rd = servletRequest.getRequestDispatcher("Two");
    rd.forward(servletRequest,servletResponse); //獲取之后進(jìn)入到下一個servlet總
    req.setCharacterEncoding("UTF-8")
    
HttpServletResponse類
  • 每次請求進(jìn)來,Tomcat服務(wù)器都會創(chuàng)建一個Response對象傳遞給Servlet程序去使用,HttpServletResponse表示所有響應(yīng)的信息。如果需要設(shè)置返回給客戶端的信息,都可以通過HttpServletResponse對象來進(jìn)行設(shè)置

  • 兩個輸出流

    1. 字節(jié)流:getOutputStream(),常用于下載(傳遞二進(jìn)制數(shù)據(jù))

    2. 字符流:getWriter(),常用于回傳字符串(常用)

      resp.setContentType("text/html; charset=UTF-8");  //同時(shí)設(shè)置服務(wù)器和客戶端的字符集為UTF-8
      PrintWriter writer = resp.getWriter();
      writer.write("Hello World");
      
請求重定向

請求重定向是指,客戶端給服務(wù)器發(fā)送請求,然后服務(wù)器給客戶端一個新地址,客戶端轉(zhuǎn)發(fā)到新地址。

resp.sendRedirect("http://www.sina.com");

注意

  1. 不能重定向到自己,否則瀏覽器會報(bào)錯
  2. 瀏覽器地址會發(fā)生變化,請求次數(shù)為兩次,而不是請求轉(zhuǎn)發(fā)的一次
  3. 兩個servlet程序不共享HttpServletRequest域中的數(shù)據(jù),因?yàn)槊總€HttpServletRequest只屬于一個Servlet
  4. 不能訪問WEB-INF下的內(nèi)容
  5. 可以訪問工程外的資源

三、HTTP協(xié)議

1. GET請求

  • 請求的方式 GET
  • 請求的資源路徑
  • 請求的協(xié)議版本號 HTTP/1.1
  • 請求頭 key:value 組成

2. POST請求

  • 請求方式POST
  • 請求資源路徑
  • 請求的協(xié)議版本號 HTTP/1.1
  • 請求頭 key:value
  • 請求體:發(fā)送給服務(wù)器的數(shù)據(jù)
<常見的GET請求和POST請求>
GET請求:
①<form>標(biāo)簽,method=get
②<a>標(biāo)簽
③<link>標(biāo)簽引入css
④<Script>標(biāo)簽引入js文件
⑤<img>標(biāo)簽引入圖片
⑥<iframe>標(biāo)簽引入html頁面
⑦在瀏覽器地址欄中輸入地址后敲回車
POST請求:
<form>標(biāo)簽,method=post
3. 常用請求頭
  • Accept:表示客戶端可以接收的數(shù)據(jù)類型
  • Accpet_language:表示客戶端可以接收的語言類型
  • User-Agent:表示客戶端瀏覽器的信息
  • Host:表示請求時(shí)的服務(wù)器ip和端口號
4. 響應(yīng)的HTTP格式
  • 響應(yīng)的協(xié)議和版本號
  • 響應(yīng)狀態(tài)碼
  • 響應(yīng)狀態(tài)描述符
  • 響應(yīng)頭:key:value
  • 響應(yīng)體 :回傳給客戶端的數(shù)據(jù)
5. 響應(yīng)碼
  • 200:表示請求成功
  • 302:表示請求重定向()
  • 404:表示請求服務(wù)器已經(jīng)收到了,但是數(shù)據(jù)不存在(請求地址錯誤或數(shù)據(jù)不存在)
  • 500:表示服務(wù)器已經(jīng)收到請求,但是服務(wù)器內(nèi)部錯誤(代碼錯誤)
6. MIME類型
  • 格式:大類型/小類型如:
    image/jpg video/mp4

四、監(jiān)聽器

  • 作用:監(jiān)聽某種事物的變化,回調(diào)函數(shù),反饋給客戶做一些響應(yīng)的處理
  • ServletContextListener監(jiān)聽器

五、文件上傳與下載

1. 上傳

  • 導(dǎo)入依賴
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
  • form表單設(shè)置
<form action="http://localhost:8080/day01_2_war_exploded/photo" method="post" enctype="multipart/form-data">
    用戶名:<input type="text" name="username"><br/>
    密碼:<input type="password" name="password"><br/>
    頭像:<input type="file" name="image"><br/>
    <input type="submit" value="上傳頭像">
</form>
  • ServletFileUpload獲得文件對象
// 1、判斷上傳的數(shù)據(jù)是否是多段數(shù)據(jù),只有是多段數(shù)據(jù)才能解析
if(ServletFileUpload.isMultipartContent(req)){
    // 2、創(chuàng)建fileItemFactory工廠實(shí)現(xiàn)類
    FileItemFactory fileItemFactory = new DiskFileItemFactory();
    // 3、創(chuàng)建用于解析上傳數(shù)據(jù)的工具類ServletFileUpload類
    ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
    // 4、解析數(shù)據(jù),得到每一個FileItem
    try {
    //解析request,得到文件項(xiàng)
    List<FileItem> fileItems = servletFileUpload.parseRequest(req);
    for (FileItem f : fileItems){
        // 如果每個fileItem是普通表單項(xiàng)
        if (f.isFormField()){
            // 獲得表單項(xiàng)的name屬性值
            System.out.println(f.getFieldName());
            // 獲得表單項(xiàng)的value值
            System.out.println(f.getString("UTF-8"));
       }
        // 否則上傳的是文件
        else {
            // 獲得表單中的各項(xiàng)input里的name屬性名稱以及他們的值
            System.out.println(f.getFieldName());
            // 獲得文件名,因?yàn)樯蟼鞯氖俏募?,則要獲取名稱不能用getFiledName
            System.out.println(f.getName());
            // 保存在服務(wù)器,參數(shù)為地址
            f.write(new File("E:\\"+f.getName()));
        }
    }
    } catch (FileUploadException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2. 下載

  • form表單
<form action="http://localhost:8080/day01_2_war_exploded/download" method="get">
    用戶名:<input type="text" name="username"><br/>
    密碼:<input type="password" name="password"><br/>
    <input type="submit" value="下載文件">
</form>
  • 客戶端
// 1、獲取要下載的文件名
String downloadFileName = "picture.png";
// 2、獲取讀取要下載的文件內(nèi)容的對象(ServletContext)
ServletContext sc = getServletContext();
// 獲取要下載的文件類型
String mimeType = sc.getMimeType("/download/" + downloadFileName);
// 在回傳數(shù)據(jù)之前,告訴客戶端要返回的數(shù)據(jù)類型
resp.setContentType(mimeType);
// 告訴客戶端收到的數(shù)據(jù)是用在直接使用(在瀏覽器打開)還是保存在本地
// Content-Disposition響應(yīng)頭,表示收到的數(shù)據(jù)怎么處理
// attachment:表示附件,表示下載使用 filename=表示指定下載的文件名
// 將文件名進(jìn)行url編碼,防止下載時(shí)客戶端出現(xiàn)中文亂碼
resp.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(downloadFileName,"UTF-8"));
// 獲取下載文件的輸入流
InputStream resource = sc.getResourceAsStream("/download/"+downloadFileName);
// 3、獲取響應(yīng)的輸出流,用于下載
OutputStream os = resp.getOutputStream();
// 4、讀取輸入流中全部的數(shù)據(jù),復(fù)制給輸出流,輸出給客戶端
IOUtils.copy(resource,os);

六、Cookie

1. 什么是Cookie

Cookie是服務(wù)器通知客戶端保存鍵值對的一種技術(shù),客戶端有了cookie后,每次請求都發(fā)送給服務(wù)器,每個cookie的大小不超過4kB。cookie如果要支持中文,必須對值進(jìn)行Base64編碼

2. 設(shè)置Cookie

創(chuàng)建

// 創(chuàng)建cookie對象
Cookie cookie1 = new Cookie("key1", "value1"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie1);
Cookie cookie2 = new Cookie("key2", "value2"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie2);

? 流程

image-20200608121314714.png

獲取

Cookie[] cookies = req.getCookies();
for (Cookie c : cookies)
System.out.println(c.getName() + " " + c.getValue());

修改

//覆蓋cookie的value屬性,類似Map,key不變。
// 創(chuàng)建cookie對象
Cookie cookie1 = new Cookie("key1", "newValue1"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie1);

存活時(shí)間

// 默認(rèn)為-1,負(fù)數(shù)表示瀏覽器一關(guān)閉(即一個session結(jié)束),cookie就刪除
cookie1.setMaxAge(-1);

// 0表示馬上刪除,都不需要等待瀏覽器關(guān)閉
cookie1.setMaxAge(0);

// 以秒為單位,設(shè)置1小時(shí)后刪除
cookie1.setMaxAge(60*60);

有效路徑

// 只有當(dāng)訪問的url是以下url時(shí),才會創(chuàng)建cookie
cookie1.setPath("url");

3. 練習(xí)

免用戶名登錄

<form action="login" method="get">
    用戶名:<input type="text" name="username" value="${cookie.username.value}"/><br/> //將保存的cookie顯示到頁面上
    密碼:<input type="password" name="password" value="${cookie.password.value}"/><br/>
    <input type="submit" value="登錄">
</form>
resp.setContentType("text/html; Charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("abcd")&&password.equals("1234")){
    Cookie cookie = new Cookie(username,password);
    cookie.setMaxAge(60*60);
    resp.addCookie(cookie);
    resp.getWriter().write("登錄成功");
}else {
    resp.getWriter().write("登錄失敗");
}

七、Session

1. 什么是Session

  • session是一個接口(HttpSession),它用來維護(hù)一個客戶端和服務(wù)器之間關(guān)聯(lián)的一種技術(shù)
  • 每個客戶端都有自己的一個session會話
  • session會話中,經(jīng)常用來保存用戶登錄之后的信息。(一個session就是客戶端與服務(wù)器之間的一次會話,關(guān)閉客戶端就結(jié)束一次會話)
  • cookie是保存在客戶端,session保存在服務(wù)器端

2. 設(shè)置Session

創(chuàng)建和獲取

// 創(chuàng)建Session會話對象
HttpSession session = req.getSession();
// 判斷當(dāng)前Session是否是新創(chuàng)建的
System.out.println(session.isNew());
// 獲取Session的唯一標(biāo)識id
System.out.println(session.getId());
// 取得key1的值
session.getAttribute("key1");

超時(shí)時(shí)間

超時(shí)時(shí)間指的是客戶端兩次請求之間的最大間隔

// 設(shè)置當(dāng)前session的超時(shí)時(shí)間,以秒為單位,超過超時(shí)時(shí)間就銷毀
// 默認(rèn)的超時(shí)時(shí)間為:1800秒,因?yàn)門omcat服務(wù)器的默認(rèn)設(shè)置為30分鐘
session.setMaxInactiveInterval(60);

3. Session和Cookie的關(guān)系

session技術(shù),底層其實(shí)是基于cookie技術(shù)實(shí)現(xiàn)的

沒有cookie的時(shí)候,getSession()獲得一個session,把session的id給cookie的value。以后有了cookie,再getSession()時(shí)就獲得session的id與cookie的value值相同的session。

image-20200608123228273.png

八、過濾器

1. 概述

  • 用于攔截請求,過濾響應(yīng),攔截請求的常見應(yīng)用場景:權(quán)限檢查、日記操作、事務(wù)操作等
  • 要求:在web工程下新建一個admin目錄,目錄下的所有資源必須是用于登錄之后才允許訪問
  • 思路:用戶登錄后的信息保存在服務(wù)器的session域中,檢查session域中是否包含有用于登錄的信息即可

Filter的生命周期

  1. 構(gòu)造器方法
  2. init初始化方法
  3. doFilter過濾方法
  4. destroy銷毀方法

實(shí)現(xiàn)filter接口,運(yùn)行doFilter方法

HttpSession session = ((HttpServletRequest) request).getSession();
Object user = session.getAttribute("user");
if (user==null){
    // 如果user=null,則權(quán)限檢查沒有通過,就轉(zhuǎn)到登錄頁面
    request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
    // 權(quán)限檢查通過,放行,讓客戶端訪問目標(biāo)資源
    chain.doFilter(request,response);
}

Session域保存用戶數(shù)據(jù)

resp.setContentType("text/html; charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");

if (username.equals("abcd")&&password.equals("1234")){
    req.getSession().setAttribute("user",username);
    System.out.println(username);
    resp.getWriter().write("登錄成功");
}else {
    req.getRequestDispatcher("/login.jsp").forward(req,resp);
}

web.xml配置過濾器

<!--filter標(biāo)簽配置一個filter過濾器-->
<filter>
    <!--給filter起一個別名-->
    <filter-name>MyFilter</filter-name>
    <!--配置filter的全限定類名-->
    <filter-class>com.zt.MyFilter</filter-class>
</filter>
<!--filter-mapping配置filter過濾器的攔截路徑-->
<filter-mapping>
    <!--filter-name表示當(dāng)前的攔截路徑給哪個filter使用-->
    <filter-name>MyFilter</filter-name>
    <!--/斜杠表示當(dāng)前的請求地址為:http://ip:port/工程路徑/ 映射到idea的webapp目錄下
    /admin/*表示攔截訪問路徑為admin目錄下的全部url-->
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

2. FilterConfig類

  • 它是filter過濾器的配置文件類,Tomcat每次創(chuàng)建Filter的時(shí)候也會創(chuàng)建一個FilterConfig類的對象,包含了Filter配置文件的配置信息。作用是獲取filter過濾器的配置內(nèi)容
  • 過濾鏈FilterChain
    FilterChain.doFilter()方法的作用:
    ①如果有filter,執(zhí)行下一個Filter過濾器
    ②執(zhí)行目標(biāo)資源(沒有Filter過濾器)
  • **多級Filter執(zhí)行順序


    image-20200608125441552.png

3. Filter的攔截路徑

  1. 精確匹配

    <url-pattern>/admin/demo1.jsp</url-pattern>
    
  2. 目錄匹配

    <url-pattern>/admin/*</url-pattern>
    
  3. 后綴名匹配

    <表示以.html結(jié)尾的都被攔截,這個后綴名不是說必須這種文件,而是所有字符串都可以,只要有這種字符串,都會被攔截
    filter過濾器只關(guān)心請求的地址是否匹配,不關(guān)心請求的地址是否存在。>
    <url-pattern>*.html</url-pattern>
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容