zoukankan      html  css  js  c++  java
  • Servlet第一天

    1.Servlet简介
    • servlet是sun公司提供的一门用于开发动态web资源的技术
    • servlet技术基于Resquest-Response编程模型
    • sun公司在其API中提供了一个Servlet接口,编写一个servlet需要两步骤 
    1. 编写一个Java类实现Servlet接口
    2. 把Java类部署到web服务器中

    学习目标:手动编写一个Servlet

    Servlet支持Java包 tomcat\lib\servlet-api.jar

    2.注册Servlet

    在Web.xml文件中,一个<servlet>元素用于注册一个Servlet,<servlet>元素中包含有两个主要的子元素:<servlet-name>和<servlet-class>它们分别用于设置Servlet的注册名称和指定Servlet的完整类名,如下所示:

    <servlet>
        <servlet-name>ServletDemo1</servlet-name>
        <servlet-class>com.malinkang.web.ServletDemo1</servlet-class>
      </servlet>
    3.映射Servlet
    <servlet-mapping>
        <servlet-name>ServletDemo1</servlet-name>
        <url-pattern>/ServletDemo1</url-pattern>
      </servlet-mapping>

    url-pattern三种匹配方式:
    1.完整路径配置(不含通配符*,以/开始)

    2.目录匹配(含通配符*,必须以/开始,以/*结尾)

    3.扩展名匹配(含有通配符*、必须不以/开始,以*.xxx结尾):例如*.do

    匹配优先级:完整路径匹配>目录匹配>扩展名

    缺省Servlet:如果某个Servlet映射路径仅仅为一个正斜杠,那么这个Servlet就是当前web应用的缺省Servlet。

    作用:凡是在web.xml文件中找不到匹配的资源,它们的访问请求都将交给缺省Servlet。

    所有服务器端 静态web资源 都是由缺省Servlet 返回给客户端

    默认缺省Servlet 在tomcat/conf/web.xml 

    <servlet>
            <servlet-name>default</servlet-name>
            <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <init-param>
                <param-name>listings</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
            <servlet-name>default</servlet-name>
            <url-pattern>/</url-pattern>
    </servlet-mapping>


    将上面的listings值改为true访问某个资源目录,则以列表显示。

    4.Sevlet生命周期

      1.浏览器访问Servlet的过程

    1.浏览器根据用户的请求生成http请求消息,并将其发给web容器

    2.Web容器检查内存中是否存在负责处理当前请求Servlet程序的实例对象,如果不存在,则加载和创建该Servlet对象。

    3.web服务器创建针对本次访问的请求对象和响应对象。请求对象包含了http的请求消息,从它里面可以获取http请求消息的内容:响应对象用于封装将要回送给浏览器的http响应信息,响应对象中的初始化内容为空,但是以后可以调用各种方法来生成http响应消息的各个部分。

    4.web服务器调用Servlet的service方法,并将请求对象和响应对象传递给该方法。

    5.Servlet对象的service方法从请求对象中读取该请求消息,并向响应对象中写入响应头和响应体消息。

    6.service方法执行完毕

    7.web服务器从响应对象中读取响应消息。

    2.Servlet生命周期

    第一次访问创建Servlet对象,调用init方法和service方法

    第二次访问只调用service方法,没有创建Servlet对象也没有调用init方法。在Servlet整个生命周期中Servlet对象只创建一次,init方法也只调用一次。

    当服务器正常关闭时,调用destory方法

    3.Servlet自动加载

    默认情况下Servlet在第一次访问时,创建对象和执行init。如果希望服务器启动时创建Servlet对象、执行init,则要配置web.xml添加<load-on-startup>

      <servlet>
        <servlet-name>InitServlet</servlet-name>
        <servlet-class>cn.itcast.servlet.InitServlet</servlet-class>
        <!-- 配置Servlet 随服务器启动时 进行创建初始化 -->
        <!-- 中间值可以 0-9 代表加载优先级 0 最高 -->
        <load-on-startup>0</load-on-startup>
      </servlet>
    5.ServletConfig

     ServletConfig:在Servlet初始化阶段,向Servlet传递数据。

      当Servlet配置了初始化参数后,当web容器创建了Servlet的实例对象会自动将这些初始化参数封装到ServletConfig对象,调用init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet.getServletConfig()方法必须返回init(ServletConfig config)方法传递进来的这个ServletConfig对象的引用。

    应用:1.在web.xml进行初始化参数的配置

        <init-param>
        <param-name>company</param-name>
        <param-value>google</param-value>
        </init-param>
        <init-param>
        <param-name>city</param-name>
        <param-value>北京</param-value>
        </init-param>
    public class ServletTest2 extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //根据初始化参数名字获取初始化值
            String value = this.getServletConfig().getInitParameter("company");
            response.getOutputStream().write(value.getBytes());
            //获取所有初始化名字
            Enumeration<String> e = this.getServletConfig().getInitParameterNames();
            while (e.hasMoreElements()) {
                response.getOutputStream().write(e.nextElement().getBytes());
            }
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }
    1.ServletContext

     Web容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

    ServletConfig对象中维护了ServletContext对象的引用,开发人员在创建servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。由于一个web应用中的所有Servlet共享同一个ServletContext对象,所以多个Servlet通过ServletContext对象实现数据共享。ServletContext对象通常被称为context域对象

     ServletContext应用

    1.提供全局初始化参数

        <!-- 全局初始化参数 -->
        <context-param>
        <param-name>name</param-name>
        <param-value>zhangsan</param-value>
        </context-param>
    public class ServletTest extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // ServletContext context=this.getServletConfig().getServletContext();可以简化为下面代码
            ServletContext context = this.getServletContext();
            String value = context.getInitParameter("name");
            response.getOutputStream().write(value.getBytes());
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        }
    
    }

    ServletContext与ServletConfig区别:
    ServletConfig每个Servlet对象对应一个,用来在Servlet的init方法进行初始化,传递Servlet私有初始化信息。

    ServletContext 每个web应用对应一个,提供全局初始化参数,所有Servlet都可以访问。

    2.案例二:通过文件扩展名 获得文件MIME类型

    MIME类型:MIME协议中规定文件书写格式

    tomcat/conf/web.xml 配置了文件扩展名和MIME类型对应关系

    ServletContext对象 提供 API : String getMimeType(String file)  根据文件名获得MIME类型

        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String file = "QQ.exe";
            String mime = this.getServletContext().getMimeType(file);
            System.out.println(mime);//application/octet-stream
        }

    3.案例三:获取日志信息
    public void log(String msg):将特定信息写入servlet日志文件(通常是一个事件日志)。servlet日志文件的名称和类型是特定于servlet容器的。

    public void log(String message,Throwable throwable):将给定异常的解释性信息和堆栈跟踪写入servlet日志文件。

    注:MyEclipse情动tomcat,无法写入日志文件

    public class ServletTest extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            ServletContext context = getServletContext();
            context.log("记录普通信息");
            try {
                int a = 5 / 0;
            } catch (Exception e) {
                context.log("记录异常信息", e);
            }
        }

    案例四 : 统计Servlet的访问次数

    作为数据域,保存整个web应用数据

    void setAttribute(String name, Object object)  将一个数据保存ServletContext中

    Object getAttribute(String name) 从ServletContext对象中取出数据

    ServletContext因为全局唯一的,所以在多个Servlet之间可以共享数据

    public class ServletTest extends HttpServlet {
    
        @Override
        // 初始化访问次数为0
        public void init() throws ServletException {
            getServletContext().setAttribute("visittimes", 0);
        }
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html;utf-8");
            Integer times = (Integer) getServletContext()
                    .getAttribute("visittimes");
            // 加一并返回
            getServletContext().setAttribute("visittimes", times + 1);
            response.getOutputStream().write(
                    ("你是第" + (times + 1) + "个访问者").getBytes("utf-8"));
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        }
    
    }


    案例五:统计字母出现次数

    知识点:对请求分发。

    常见面试题:比较转发和重定向

    重定向:产生两次请求和两次响应。对于客户端来说,知道产生了重定向(URL地址会转变为B的地址);

    转发:服务器内部技术,由服务器多个资源共同处理同一个请求和响应。转发的过程对于客户端是不可见的。

    操作步骤:

    RequestDispatcher getRequestDispatcher(String path):获得转发器,完成转发。

    再使用Dispatcher的void forward(ServletRequest request,ServletRequest response):完成请求和响应转发操作。

    1.写一个html页面输入字母

    <form action="/day05/count" method="post" >
    <textarea rows="5" cols="30" name="content"></textarea>
    <input type="submit" value="提交"/>
    </form>

    2.创建一个Servlet 虚拟目录为count 用于统计字母个数

    public class Demo extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获得请求的内容
            String content = request.getParameter("content");
            // 索引代表字母
            int[] arr = new int[26];
            for (int i = 0; i < content.length(); i++) {
                char ch = content.charAt(i);
                if (Character.isLetter(ch)) {
                    // 转换为小写
                    ch = Character.toLowerCase(ch);
                    arr[ch - 'a']++;
                }
            }
            getServletContext().setAttribute("arr", arr);
            RequestDispatcher dispatcher = getServletContext()
                    .getRequestDispatcher("/Demo2");
            dispatcher.forward(request, response);
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    3.创建一个Servlet,用于输出结果

    public class Demo2 extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获得统计结果
            int arr[] = (int[]) getServletContext().getAttribute("arr");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            for (int i = 0; i < arr.length; i++) {
                char ch = (char) ('a' + i);
                out.print(ch + "出现的次数是" + arr[i] + "</br>");
            }
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }


    案例六:读取文件

    回顾Java读取文件

    public class FileReaderTest {
        public static void main(String[] args) {
            // 读取项目目录文件
            String path_1 = "1.txt";
            reader(path_1);
            // 读取src下的文件
            String path_2 = "src/2.txt";
            reader(path_2);
            // 读取WebRoot下的文件
            String path_3 = "WebRoot/5.txt";
            reader(path_3);
            // 读取WEB-INF目录下的文件
            String path_4 = "WebRoot/WEB-INF/4.txt";
            reader(path_4);
            // 读取包下的文件
            String path_5 = "src/cn/itcast/test/3.txt";
            reader(path_5);
        }
    
        public static void reader(String path) {
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(path));
                String line = null;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }


    在Web中读取文件要使用绝对路径:

    public class Demo3 extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 读取项目目录文件 因为项目下的文件没有发布
    
            // 读取src下的文件
            String path_2 = "/WEB-INF/classes/2.txt";
            String real_path_2 = getServletContext().getRealPath(path_2);
            // 使用类加载器读取src下的文件
            reader(real_path_2);
            String path = Demo3.class.getResource("/2.txt").getFile();
            reader(path);
            // 读取WebRoot下的文件
            String path_3 = "/5.txt";
            String real_path_3 = getServletContext().getRealPath(path_3);
            reader(real_path_3);
            // 读取WEB-INF目录下的文件
            String path_4 = "/WEB-INF/4.txt";
            String real_path_4 = getServletContext().getRealPath(path_4);
            reader(real_path_4);
            // 读取包下的文件
            String path_5 = "/WEB-INF/classes/cn/itcast/test/3.txt";
            String real_path_5 = getServletContext().getRealPath(path_5);
            reader(real_path_5);
        }
    
        public static void reader(String path) {
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(path));
                String line = null;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }
  • 相关阅读:
    全程记录:今天尝试安装SharePoint Server 2007过程 ,安装成功了,但是开始使用碰到权限问题,应该算是BUg吧 无为而为
    IT人看《国富论》系列:第一篇之第九章:论资本利润,暴利或许意味着市场的调节已经失效了,比如房地产 无为而为
    组建InfoPath/SharePoint/WebParts项目组,已收到项目意向,欢迎每周至少有20小时左右的空余时间有项目经验者加入。 无为而为
    我有问题请教各位硬件高手:电脑呈现这个症状是不是电源的输出功率不够? 无为而为
    使用VS2005新功能的Tips:this.Validate();这一句话,让我找了好久。 无为而为
    MSF for CMMI Process Improvement项目体验: Work Items : Requirement (更新版) 无为而为
    等待新产品还是自己开发,这是个两难的问题 无为而为
    在播放器战争爆发之前:比较苹果的iTunes 6和微软Media Player 10 无为而为
    LCS管理员的工具:Live Communications Server 2005 with Service Pack 1 Resource Kit,比如追踪登陆过程 无为而为
    Ms sql 等待一定时间后取数据
  • 原文地址:https://www.cnblogs.com/malinkang/p/2706284.html
Copyright © 2011-2022 走看看