Servlet入门和ServletConfig、ServletContext

原文链接:http://www.cnblogs.com/EvanLiu/p/3695312.html

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入门和ServletConfig、ServletContext

 

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);
    }
}

 

 

 

 

转载于:https://www.cnblogs.com/EvanLiu/p/3695312.html

上一篇:浅学Filter&Listener


下一篇:项目实战之干掉Web.xml