• 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.35libservlet-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的安装目录>confweb.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);
        }
    }
  • 相关阅读:
    多校第四场
    codechef 两题
    Topcoder 多校T-shirt场
    状态压缩DP
    LUCAS 定理
    HDU 1104 Remainder
    HDU4542 小明系列故事——未知剩余系
    Codeforces Round #256 (Div. 2)
    Codeforces Round #FF (Div. 2)
    2016年川师大软件工程学生博客打分
  • 原文地址:https://www.cnblogs.com/EvanLiu/p/3695312.html
Copyright © 2020-2023  润新知