1. 程式人生 > 其它 >Servlet基礎知識

Servlet基礎知識

1.Servlet是什麼?

(1)執行在伺服器端的java程式

(2)作用:

++ 1.處理接收客戶端的請求
++ 2.處理請求後呼叫java程式中的程式碼,並給客戶端做出響應

++ 響應:HTML程式碼段、JSON 機制:IO輸出流,將服務端的資料輸出到客戶端

(1)HTML: 輸出的就是HTML程式碼段

(2) 使用json引入:阿里 fast-json

<!-- Fastjoson JSON處理工具 -->
<dependency>   
    <groupId>com.alibaba</groupId>    
    <artifactId>fastjson</artifactId>    
    <version>1.2.78</version>
</dependency>

告訴客戶端我是什麼資料/客戶端傳送給服務端的資料型別: Content-type (mime型別)

(3)實時執行的容器(隨時監聽客戶端傳送的請求,隨時準備給客戶端傳送響應)

2.瞭解兩個JAVA WEB(J2EE)開發中常用的元件

(1)Maven

作用:

++管理專案包

++構建專案,打包專案

++管理專案之間程式碼的依賴

安裝方法:

1.官網下載軟體,地址:http://maven.apache.org/download.cgi

2.解壓

3.配置環境變數”MAVEN_HOME”為maven解壓的根目錄路徑

4.環境變數”path”新增,%MAVEN_HOME%\bin

5.測試maven配置是否成功,cmd>mvn - v ,有版本輸出則安裝配置完成

結構解析:

++ conf: 配置檔案路徑

(1)settings.xml : maven構建目錄配置檔案

       ```xml

E:\GjbSVN\maven倉庫
```

<!-- 配置阿里雲倉庫 -->
<mirror>
            <id>nexus-aliyun</id>
            <mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </mirror>

(2)Tomcat

是一個輕量的伺服器端WEB程式容器

作用

++ 在伺服器端執行一個服務用於接收所有客戶端的請求轉發給Java容器程式碼(Servlet)

++ 可以部署多個java程式在服務端執行,且提供埠號和專案名進行訪問

++ 可以配置請求相關的內容,如:https(SSL證書加密的請求)

++ 請求網路相關的策略和Java程式碼解耦

安裝方法:

1.官網下載https://tomcat.apache.org/download-80.cgi

2.解壓

3.執行-》 執行:bin> startup程式(sh檔案:linux執行 bat:windows執行)

4.訪問:在瀏覽器導航窗體中輸入: http://tomcat所在的伺服器ip地址或域名: Tomcat的埠號 / 專案名

  1. 停止:執行:bin> shutdown程式(sh檔案:linux執行 bat:windows執行)

    ++ 在開啟的tomcat視窗 按 ctrl+C停止

結構解析:

++bin:Tomcat的執行檔案目錄(啟動 startup、停止 shutdown)

++conf:Tomcat配置檔案路徑

(1)server.xml : 配置容器服務配置項(Tomcat埠、Https配置、專案路徑配置...)

  **(2) web.xml  :   Tomcat啟動專案配置檔案(不要修改,啟動的是Tomcat內建的專案)**

++ webapps : Tomcat要部署的專案資料夾

3.Servlet專案的構建(IDEA)

(1)使用idea構建專案

1.新建專案-》 Java Enterprise -》

++ name: 專案名

++ location: 專案檔案位置

++ Project Template:專案模板(選擇Web Application)

++ Application server:服務執行容器(TomEE)

++ bulid system : Maven

++ Group: 根包結構 (公司域名反寫)

++ Artfiact: 打包的專案名稱

點選OK

2.選擇依賴

++ 只選擇Servlet就可以

點選OK

(2)專案的結構

  1. src>main>java: java原始碼目錄

  2. src>main>resource :資原始檔夾(配置檔案)

  3. src>main>webapp: 包含專案的靜態資原始檔、web動態配置檔案(Servlet執行配置)

    ++ WEB-INF》 web.xml : Servlet執行配置

    1. 和SRC目錄同級的pom.xml : maven依賴配置檔案

(3)IDEA 啟動專案的方式

1.在idea下配置Tomcat的方式

注意:idea下選擇服務容器選擇 Tomcat Server

(1)右上角-》找到Tomcat窗體點選-》 Edit Configuration.. 開啟窗體

(2)修改URL,點選Deployment-》Application context : 修改路徑

2.啟動點選Tomcat窗體右側的執行按鈕或者debug按鈕

3.停止點選紅色方塊停止

2.IDEA中maven的配置方式

4.Servlet第一個Demo

(1)編寫Servlet原始檔

public class ServletDemo1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //設定mime型別為html
        resp.setContentType("text/html;charset=UTF-8");

        //準備返回給客戶端的html程式碼段
        String str = "<span style='color:red;'>你好客戶端,我是伺服器!</span>";

        //從響應物件獲取一個輸出流
        PrintWriter writer = resp.getWriter();

        //輸出客戶端
        writer.write(str);

        //輸出、關閉流
        writer.flush();
        writer.close();

    }
}

(2)配置Servlet

在webapp資料夾下得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_4_0.xsd"
         version="4.0">

    <!-- 註冊Servlet類到容器中 -->
    <servlet>
        <!-- 給Servlet取個名字 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- 註冊的servlet類的全包名路徑位置 -->
        <servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
    </servlet>

    <!-- 配置請求URL路徑與Servlet的對映關係 -->
    <servlet-mapping>
        <!-- 要給哪個名字的Servlet配置對映 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- url路徑與Servlet對映 -->
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

(3)編譯執行Tomcat

直接執行即可

(4)訪問Servlet

如:在瀏覽器位址列中輸入:

http://localhost:8080/JavaServletDemo/login

其中:

++localhost : Tomcat執行的計算機IP地址

++ 8080 : Tomcat的埠號

++ /JavaServletDemo : 專案名稱

++ /login : Servlet 的對映url-pattern

5.Servlet的生命週期方法

5.1 Servlet初始化-init()方法

定義在Servlet介面中,在GenericServlet類中重寫了這個方法,提供了一個過載的init方法

public void init(ServletConfig config) throws ServletException

在HttpServlet類中就沒有init方法了,我們需要重寫

/**
     * Servlet初始化方法
     * @throws ServletException
     */
    @Override
    public void init() throws ServletException {
        System.out.println("Servlet初始化");
    }

作用:

當請求訪問Servlet容器時,如果沒有建立Servlet例項,就會呼叫init方法,如果有例項則不會呼叫(Servlet單例模式)

5.2 請求響應處理-service()方法

作用:處理請求和響應

注意:如果是繼承了HttpServlet的Servlet例項,不要重寫service方法,因為在HttpServlet類內部已經重寫了該方法

HttpServlet中重寫的方法:

public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);  //  呼叫了自定義的過載的service方法
    }

HttpServlet中過載的方法:

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();  //獲取請求的型別進行判斷

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

5.3 Servlet銷燬-destroy() 方法

作用:

當Servlet容器停止或者Servlet容器覺得你的Servlet例項應該銷燬就會被呼叫,自動化過程

@Override
    public void destroy() {
        System.out.println("銷燬!");
    }

6.HTTP請求、響應

(1)請求組成

請求行/狀態行
頭資訊
實體

請求行:
GET /sample.jsp HTTP/1.1

請求頭:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate

引數:
username=chaidapeng&password=123456


(2)請求狀態碼

200 -》 請求成功

404 -》 請求資源不存在

403 -》請求方式不對

500 -》 後端程式碼異常

501 -》後端不支援RESTful介面

7.Servlet封裝的請求和響應物件

1.請求物件ServletRequest常用方法

(1)getParameter(String parameterName)查詢指定請求引數值

http://localhost:8080/JavaServletDemo/login?name=%E8%80%81%E6%9D%8E&age=18

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String name = req.getParameter("name");

        String age = req.getParameter("age");

        System.out.println("引數name="+name);

        System.out.println("引數age="+age);


    }

(2)getParameterMap() 獲取請求引數的map集合

Map<String, String[]> parameterMap = req.getParameterMap();

        Set<String> strings = parameterMap.keySet();

        for(String key:strings){

            String[] strings1 = parameterMap.get(key);

            System.out.println("key:"+key+"    value:"+ Arrays.toString(strings1));

        }

(3)獲取客戶端請求的mime型別

String contentType = req.getContentType();

        System.out.println(contentType);

(4)獲取客戶端的輸入流進行讀取getInputStream

ServletInputStream inputStream = req.getInputStream();

            int available = inputStream.available();

            byte [] arr = new byte[available];
            System.out.println(available);
            inputStream.read(arr);

            System.out.println(new String(arr));

(5)獲取客戶端的ip、主機名、埠

//客戶端IP地址
        String remoteAddr = req.getRemoteAddr();
        //返回客戶端主機名
        String remoteHost = req.getRemoteHost();
        //客戶端埠號
        int remotePort = req.getRemotePort();

        System.out.println(remoteAddr+" "+remoteHost+" "+remotePort);

(6)獲取請求頭中得引數

請求頭引數如下:

請求頭:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate

String host = req.getHeader("Host");

        System.out.println(host);

(7)在請求物件中新增或取得引數值(自定義)

//給請求物件新增引數
        req.setAttribute("keyName","123");
        //取得請求物件攜帶的引數
        Object keyName = req.getAttribute("keyName");

2.響應物件ServletResponse

(1)獲取輸出流,向客戶端輸出資料getOutputStream

ServletOutputStream outputStream = resp.getOutputStream();

        outputStream.print("123");
        outputStream.println("789");
        outputStream.print("456");
        outputStream.println("<h1>4444</h1>");//如果不設定contentType則按照字串輸出

        outputStream.flush();

        outputStream.close();

(2)返回可以向客戶端傳送字元資料的PrintWriter物件

同上,輸出htmldemo 在單元4

(3)設定請求和響應的字元編碼集

//設定請求、響應內容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

(4)設定響應的mime型別

//設定請求、響應內容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

比如:輸出一個json字串

 //設定請求、響應內容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        PrintWriter writer = resp.getWriter();

        //設定響應的mime型別   json型別
        resp.setContentType("application/json;charset=UTF-8");

        User u1 = new User("高靖博",28);

        //json字串轉換為物件
        String u2 = "{name:'王丘',age:18}";

        User parse = JSONObject.parseObject(u2,User.class);

        System.out.println(parse.name+" "+parse.age);

        //java物件轉為json字串
        String s = JSON.toJSONString(u1);

        System.out.println(s);
		
		writer.print(s);

        writer.flush();

        writer.close();

8.ServletConfig 配置物件

作用:

++ 在Servlet例項的時候新增一些引數,然後通過servletConfig物件呼叫getInitParameter方法取得初始化引數

(1)配置初始化引數

在web.xml中對應的servlet標籤下配置init-param標籤

<!-- 註冊Servlet類到容器中 -->
    <servlet>
        <!-- 給Servlet取個名字 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- 註冊的servlet類的全包名路徑位置 -->
        <servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
        <!-- servletConfig初始化配置引數 -->
        <init-param>
            <param-name>userName</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>pwd</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>

(2)獲取servletConfig物件,獲取初始化引數值

方法一:重寫init方法,引數寫上ServletConfig物件引數

/**
     * 重寫servlet中的init方法,且要帶上引數(ServletConfig config)
     * 初始化方法
     * @param config  初始化時例項ServletConfig引數物件
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;

        System.out.println("初始化");

        //獲取servlet初始化引數
        String userName = this.config.getInitParameter("userName");

        System.out.println("userName:"+userName);

    }

方法二:通過Servlet當前物件呼叫getServletConfig()方法獲取物件

ServletConfig servletConfig = this.getServletConfig();

        System.out.println(servletConfig.getInitParameter("userName"));

(3)獲取所有的初始化引數名稱

//獲取初始化引數名稱的列舉物件
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();

        //迭代器遍歷列舉值
        String s1 = initParameterNames.nextElement();

9.ServletContext 物件 Servlet上下文物件

獲取方式主要使用兩種:

//1.通過ServletConfig物件獲取
ServletContext servletContext = servletConfig.getServletContext();

//2.通過當前Servlet物件呼叫getServletContext獲取
ServletContext servletContext1 = this.getServletContext();

(1) 給上下文物件新增引數能夠在多個Servlet例項之間共享

如:在Servlet1中給ServletContext物件設定引數

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletConfig servletConfig = this.getServletConfig();

        System.out.println(servletConfig.getInitParameter("userName"));

        //1.通過ServletConfig物件獲取
        ServletContext servletContext = servletConfig.getServletContext();

        //2.通過當前Servlet物件呼叫getServletContext獲取
        ServletContext servletContext1 = this.getServletContext();

        //設定引數
        servletContext.setAttribute("qqNumber","123456789");


    }

在Servlet2中獲取設定的引數

System.out.println("Servlet2被呼叫");

        ServletContext servletContext = this.getServletContext();

        System.out.println("在Servlet2中獲取:"+servletContext.getAttribute("qqNumber"));

10.Http請求響應

1.請求型別

(1)GET請求:

如:http://192.168.1.100:8080?name=高靖博&age=18

出現的情況:

++ 瀏覽器地址框請求是GET

++ 請求查詢指定伺服器資源是GET(獲取css、js、頁面、圖片、視訊..)

特點:

++ 請求引數是跟在請求url後面的

++ GET請求沒有請求體

(2)POST請求

如:表單提交 <form method="post"> 當表單提交時就是POST請求

出現的情況:

++ 需要加密請求引數

++ 請求引數很多很長

特點:

++ 請求引數是在請求體重

++ 請求引數長度不限制

11.HttpServlet提供的請求(HttpServletRequest)和響應物件(HttpServletResponse)

httpservlet提供的請求和響應物件分別都繼承了servlet的請求和響應物件

1.HttpServletRequest 請求物件

(1)獲取客戶端的Cookie

/**
         * Cookie客戶端會話儲存技術
         */
        //服務端獲取Cookie的方法
        Cookie[] cookies = req.getCookies();
        if(cookies!=null){
            for(int i=0;i< cookies.length;i++){
                Cookie cookie = cookies[i];
                String name = cookie.getName();
                String value = cookie.getValue();
                System.out.println("name:"+name);
                System.out.println("value"+value);
            }
        }

(2)獲取客戶端請求的URI和URL

//獲取客戶端請求的URI
        String requestURI = req.getRequestURI();
//獲取客戶端請求的URL
        StringBuffer requestURL = req.getRequestURL();
        // /JavaServletDemo/login
        System.out.println("requestURI"+requestURI);
        // http://localhost:8080/JavaServletDemo/login
        System.out.println("requestURL"+requestURL);

(3) 請求的查詢引數字串

 //如請求: http://localhost:8080/JavaServletDemo/login?name=hhh&age=12
        String queryString = req.getQueryString();
        //name=hhh&age=12
        System.out.println(queryString);

(4) 獲取請求的型別

String method = req.getMethod();
        // GET
        System.out.println(method);

2.HttpServletResponse 響應物件

(1) 給客戶端新增一個Cookie

//伺服器端可以建立一個cookie返回給客戶端
        Cookie c = new Cookie("token","123456789");
        c.setMaxAge(9999);//設定Cookie過期時間,單位秒
        resp.addCookie(c);

(2) 獲取響應頭資訊和設定響應頭資訊

//覆蓋設定
resp.setHeader(“屬性名”,"屬性值");
//追加
resp.addHeader("屬性名","屬性值");
注意:只有響應物件可以取值和賦值,請求物件只能取得請求頭的值,不能設定