Servlet入門和ServletConfig、ServletContext

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

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

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

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

Servlet快速入門案例tomcat

1.創建一個標準的JavaWeb應用目錄安全

FirstApp服務器

------ WEB-INF多線程

--------------classess併發

--------------libapp

--------------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);
    }
}
相關文章
相關標籤/搜索