Servlet入門和ServletConfig、ServletContext


Servlet是一門用於開發動態web資源的技術。

若想開發一個動態web資源,需要完成以下2個步驟:

1)編寫一個Java類,實現servlet接口;

2)把開發好的Java類部署到web服務器中。

Servlet快速入門案例

1.建立一個標准的JavaWeb應用目錄

FirstApp

------ WEB-INF

--------------classess

--------------lib

--------------web.xml

2.進入classes目錄,建立一個文本文件

package cn.lsl.servlet;

import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class FirstServlet extends GenericServlet {

    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        OutputStream out = res.getOutputStream();
        out.write("Hello Servlet".getBytes());
        out.close();
    }
}

3.進入classes目錄,對FirstServlet進行編譯:

前提:把servlet-api.jar加入到你的構建路徑中.

            set classpath=%classpath%;C:\apache-tomcat-6.0.35\lib\servlet-api.jar

執行:javac -d . FirstServlet.java

4.修改web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>cn.lsl.servlet.FirstServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

5.部署應用到Tomcat中

6.訪問地址:http://localhost:8080/FirstApp/hello

7.Servlet的執行原理和過程圖

 

Servlet的生命周期

容器最終要調用service方法為客戶端進行服務

1.Servlet接口中的常用方法:

public void init(ServletConfig config):初始化。Servlet類被實例化之后就會執行,且執行一次。 由容器進行調用

public void destroy():銷毀Servlet對象。由容器進行調用。

2.內存中一個Servlet只有一個實例。針對不同的用戶請求,容器采用多線程的機制調用service方法。

3.希望在應用被Tomcat加載完畢后(此時還沒有任何人訪問),就實例化並完成初始化Servlet的工作?

在<Servlet>中配置上<load-on-startup>2</load-on-startup>

<servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>cn.lsl.servlet.FirstServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

Servelt接口實現類

1.Servlet接口定義了兩個默認實現類

GenericServlet和HttpServlet

2.HttpServlet指能夠處理HTTP請求的servlet,它在原有Servlet接口上添加了一些與HTTP協議處理方法,它比Servlet接口的功能更為強大。應該在編寫Servlet時,通過應該去繼承這個類。

3.HttpServlet在實現Servlet接口時,覆寫了service方法,該方法體內的代碼會自動判斷用戶的請求方式,如為GET請求,則調用HttpServlet的doGet方法,如為Post請求,則調用doPost方法。因此在編寫Servlet時,通常只需要覆蓋doGet或doPost方法,而不要去覆寫service方法。

eg:

package cn.lsl.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo extends HttpServlet {
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getOutputStream().write("hello servlet".getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

Servlet的映射

1.一個Servlet可以被映射到多個URL地址上

2.URL地址映射還支持通配符*

         方式一:以*開頭,以擴展名結尾<url-pattern>*.do</url-pattern>

方式二:以/前綴開頭,以*結尾。比如<url-pattern>/action/*</url-pattern>

2. 多個Servlet使用通配符時,有可能有多種

以"/"開頭(方式二)要比"*"開頭(方式一)優先級高

都以"/"開頭,還是有多個匹配,找最匹配的

3. 如果一個Servlet的映射為一個"/",就稱之為默認的Servlet,它負責處理沒有映射路徑的URL請求的響應。

4.在<tomcat的安裝目錄>\conf\web.xml文件中,注冊了一個名稱為org.apache.catalina.servlets.DefaultServlet的Servlet,並將這個Servlet設置為了缺省Servlet。5.當訪問Tomcat服務器中的某個靜態HTML文件和圖片時,實際上是在訪問這個缺省Servlet。

Servlet線程安全問題

當多個客戶端並發訪問同一個Servlet時,web服務器會為每一個客戶端的訪問請求創建一個線程,並在這個線程上調用Servlet的service方法,因此service方法內如果訪問了同一個資源的話,就有可能引發線程安全問題。

解決辦法:

1.在Servlet中定義變量,除非特殊要求,盡量使用局部變量

2.如果有需要實例變量,應做同步處理,且同步代碼塊盡量包圍少的代碼。

ServletConfig

作用:代表了Servlet配置中的參數信息。

eg:在web.xml中的參數配置如下信息

<servlet>
    <servlet-name>ServletDemo1</servlet-name>
    <servlet-class>cn.lsl.servlet.ServletDemo1</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>zhangsan</param-value>
    </init-param>
    <init-param>
        <param-name>age</param-name>
        <param-value>23</param-value>
    </init-param>
  </servlet>
package cn.lsl.servlet;

import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo1 extends HttpServlet {
    private ServletConfig config;
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        test3();
    }
    
    //獲取指定參數username的值
    private void test1(){
        String value = config.getInitParameter("username");
        System.out.println(value);
    }
    
    //獲取所有的參數和參數的值
    private void test2(){
        Enumeration e = config.getInitParameterNames();
        while(e.hasMoreElements()){
            String paramName = (String)e.nextElement();
            System.out.println(paramName+"="+config.getInitParameter(paramName));
        }
    }
    
    //得到servlet的名字
    private void test3(){
        String name = config.getServletName();
        System.out.println(name);
    }

    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
    }
}

ServletContext

1.在應用被服務器加載時就創建ServletContext對象的實例。每一個JavaWeb應用都有唯一的一個ServletContext對象,它就代表着當前應用。

2.如何得到ServletContext對象:ServletConfig.getServletContext();

3.作用

1)ServletContext對象是一個域對象(域對象就是說其內部維護了一個Map<String,Object>)

Object getAttribute(String name):根據名稱獲取綁定的對象

Enumeration getAttributeNames():獲取ServletContex域中的所有名稱

void removeAttribute(String name):根據名稱移除對象

void setAttribute(String name, Object value):添加或修改對象

2)實現多個Servlet之間的數據共享

eg:

實現ServletDemo2和ServletDemo3之間的數據共享

package cn.lsl.servlet;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc = getServletContext();
        sc.setAttribute("username", "zhangsan");
        response.getOutputStream().write("OK".getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }

}
package cn.lsl.servlet;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo3 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc = getServletContext();
        String name = (String)sc.getAttribute("username");
        response.getOutputStream().write(name.getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

3)獲取WEB應用的初始化參數(應用的全局參數)

eg:

在web.xml中

<context-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
</context-param>
package cn.lsl.servlet;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc = getServletContext();
        String value = sc.getInitParameter("encoding");
        response.getOutputStream().write(value.getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

4.讀取資源文件的三種方式

1)利用ServletContext.getRealPath():

特點:讀取應用中任何文件。只能在web環境下用

文件下載案例:

package cn.lsl.servlet;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        test2(response);
    }
    
    //英文名文件下載
    private void test1(HttpServletResponse response) throws IOException{
        //得到要下載的文件
        ServletContext sc = getServletContext();
        String path = sc.getRealPath("/f.jpg");
        //構建輸入流
        InputStream in = new FileInputStream(path);
        //通知客戶端以下載的方式打開
        response.setHeader("Content-Disposition", "attachment;filename=f.jpg");
        response.setHeader("Content-Type", "application/octet-stream");    //二進制流
        OutputStream out = response.getOutputStream();
        int len = -1;
        byte b[] = new byte[1024];
        while((len=in.read(b))!=-1){
            out.write(b, 0, len);
        }
        in.close();
        out.close();
    }
    
    //中文名文件下載
    private void test2(HttpServletResponse response) throws IOException{
        //得到要下載的文件
        ServletContext sc = getServletContext();
        String path = sc.getRealPath("/美女.jpg");
        //截取文件名
        String filename = path.substring(path.lastIndexOf("\\")+1);
        System.out.println(filename);
        //構建輸入流
        InputStream in = new FileInputStream(path);
        //通知客戶端以下載的方式打開
        //中文文件名此處要進行URL編碼
        response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename, "UTF-8"));
        response.setHeader("Content-Type", "application/octet-stream");
        OutputStream out = response.getOutputStream();
        int len = -1;
        byte b[] = new byte[1024];
        while((len = in.read(b))!=-1){
            out.write(b, 0, len);
        }
        in.close();
        out.close();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

2)利用ResourceBundle讀取配置文件

特點:可以在非web環境下。但是只能讀取類路徑中的properties文件。

3)利用類加載器讀取配置文件

特點:可以用在非web環境下。可以讀取類路徑下的任何文件。

eg:

package cn.lsl.servlet;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.ResourceBundle;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//讀取資源文件的三種方式
//a1.properties在WEB-INF下
//a2.properties在src下
//a3.properties在src/cn/lsl/resources下
public class ServletDemo6 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        test7();
    }
    
    //利用ServletContext讀取a1.properties
    private void test1() throws FileNotFoundException, IOException{
        ServletContext sc = getServletContext();
        String path = sc.getRealPath("/WEB-INF/a1.properties");
        Properties props = new Properties();
        props.load(new FileInputStream(path));
        String value = props.getProperty("username");
        System.out.println(value);
    }
    //利用ServletContext讀取a2.properties
    private void test2() throws FileNotFoundException, IOException{
        ServletContext sc = getServletContext();
        String path = sc.getRealPath("/WEB-INF/classes/a2.properties");
        Properties props = new Properties();
        props.load(new FileInputStream(path));
        String value = props.getProperty("username");
        System.out.println(value);
    }
    
    //利用ServletContext讀取a3.properties
    private void test3() throws FileNotFoundException, IOException{
        ServletContext sc = getServletContext();
        String path = sc.getRealPath("/WEB-INF/classes/cn/lsl/resources/a3.properties");
        Properties props = new Properties();
        props.load(new FileInputStream(path));
        String value = props.getProperty("username");
        System.out.println(value);
    }
    
    //--------------------------------------
    //利用ResourceBundle讀取配置文件a2.properties
    private void test4(){
        ResourceBundle rb = ResourceBundle.getBundle("a2");    //基名
        String value = rb.getString("username");
        System.out.println(value);
    }
    //利用ResourceBundle讀取配置文件a3.properties
    private void test5(){
        ResourceBundle rb = ResourceBundle.getBundle("cn.lsl.resources.a3");
        String value = rb.getString("username");
        System.out.println(value);
    }
    
    //--------------------------
    //利用類加載器讀取配置文件a2.properties
    public void test6() throws IOException{
        ClassLoader cl = ServletDemo6.class.getClassLoader();
        InputStream in = cl.getResourceAsStream("a2.properties");
        Properties props = new Properties();
        props.load(in);
        String value = props.getProperty("username");
        System.out.println(value);
    }
    
    //利用類加載器讀取配置文件a3.properties
    private void test7() throws IOException{
        ClassLoader cl = ServletDemo6.class.getClassLoader();
        InputStream in = cl.getResourceAsStream("cn/lsl/resources/a3.properties");
        Properties props = new Properties();
        props.load(in);
        String value = props.getProperty("username");
        System.out.println(value);
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM