zoukankan      html  css  js  c++  java
  • Javaweb之 servlet 开发详解1

    1.1  Tip:Servlet简介

    Servlet是sun公司提供的一门用于开发动态web资源的技术。

    Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:

    1、编写一个Java类,实现servlet接口。

    2、把开发好的Java类部署到web服务器中。

    编写一个Java程序,向浏览器输出“hello servlet”。

    编写这个程序需要解决的2个问题:

    在Java程序中,如何才能向IE浏览器输出数据?

    输出hello servlet的java代码应该写在程序的哪个方法内?

    阅读Servlet API,解决以上两个问题。

    1.2  Servlet在web应用中的位置

     这里写图片描述

    1.3  Tip:Servlet的运行过程(课后看)

    Servlet程序是由WEB服务器(Tomcat)调用,web服务器收到客户端的Servlet访问请求后:

    ①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,调用service()方法,否则,执行第②步。

    ②装载并创建该Servlet的一个实例对象。

    ③调用Servlet实例对象的init()方法。

    ④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servletservice()方法并将请求和响应对象作为参数传递进去。

    ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

     这里写图片描述

    1.4  Tip:在Eclipse中开发Servlet
    这里写图片描述

    1.5  Tip:Servlet接口实现类

    Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServletHttpServlet

    HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。

    HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。

    阅读HttpServlet API文档

    1.6  Tip:Servlet的一些细节(1)

    客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

    <servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

    一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如:

    <web-app>
             <servlet>
                       <servlet-name>AnyName</servlet-name>
                       <servlet-class>webdemo01.Hello</servlet-class>
             </servlet>
             <servlet-mapping>
                       <servlet-name>AnyName</servlet-name>
                       <url-pattern>/demo/hello.html</url-pattern>
             </servlet-mapping>
    </web-app>


    同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

    Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

    <servlet-mapping>

             <servlet-name>AnyName </servlet-name>

             <url-pattern>*.do</url-pattern>

    </servlet-mapping>

    <servlet-mapping>

             <servlet-name>AnyName </servlet-name>

             <url-pattern>/action/*</url-pattern>

    </servlet-mapping>

    <Context>
           <WatchedResource>WEB-INF/web.xml</WatchedResource>
    </Context>                                                            在服务器中的context.xml中有配置上下文


    对于如下的一些映射关系:

    Servlet1 映射到 /abc/*

    Servlet2 映射到 /*

    Servlet3 映射到 /abc

    Servlet4 映射到 *.do

    问题:

    URL

    都匹配

    哪个servlet响应

    /abc/a.html

    /abc/*”和“/*”

    Servlet1

    /abc

    “/abc/*”和“/abc”, /*

    Servlet3

    /abc/a.do

    /abc/*”和“*.do”, /*

    Servlet1

    /a.do

    /*”和“*.do”

    Servlet2

    /xxx/yyy/a.do

    /*”和“*.do”

    Servlet2

    以*开头的优先级最低

    Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

    针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

    Servlet的整个生命周期内,Servletinit方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

    但是根据HttpServletRequest,HttpServletResponse生命周期很短,假如不是并发,服务器就没事。

    如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

             举例:

             <servlet>
                       <servlet-name>invoker</servlet-name>
                       <servlet-class>
                                org.apache.catalina.servlets.InvokerServlet
                       </servlet-class>
                       <load-on-startup>2</load-on-startup>
             </servlet>


    是一个正整数,数字越小,先启动。

    用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据,初始化一些参数和数据。

    如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。(意思是,找不到地址,就找塔,如404返回的页面信息)

    凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

    在<tomcat的安装目录>confweb.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

    当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。

    1.7  Tip:Servlet的一些细节(7)—线程安全

    当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话(有资源共享),就有可能引发线程安全问题。

    如果某个Servlet实现了SingleThreadModel接口(但已经过时),那么Servlet引擎将以单线程模式来调用其service方法。

    SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。

    对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。

    实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,如果客户端不能访问,Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

    Synchronized方法,但是用户体验差。

    package webdemo01;

    importjava.io.IOException;
     
    importjavax.servlet.ServletException;
    importjavax.servlet.SingleThreadModel;
    importjavax.servlet.http.HttpServlet;
    importjavax.servlet.http.HttpServletRequest;
    importjavax.servlet.http.HttpServletResponse;
     
    //1、线程安全
    publicclass ServeletDemo05 extends HttpServlet implements SingleThreadModel{
             private static final long serialVersionUID= 1L;
     
             int i =0; //此时将发生线程安全
             protected void doGet(HttpServletRequestrequest, HttpServletResponse response) throws ServletException {
                       /* int i = 0;   //此时,每个线程有自己的i,不会发生线程安全*/   
                       i++;
                      
                       try {
                                Thread.sleep(1000*3);
                       } catch (InterruptedExceptione) {
                               
                                e.printStackTrace();
                       }
                       try {
                                response.getOutputStream().write((i+"").getBytes());
                       } catch (IOException e) {
                                // TODOAuto-generated catch block
                                e.printStackTrace();
                       }
                      
                       //如何解决此线程安全? 1、同步,   2 、singleThreadModel  //标记接口
                       /*synchronized (this) {
                                i++;
                               
                                try {
                                         Thread.sleep(1000*3);
                                } catch(InterruptedException e) {
                                        
                                         e.printStackTrace();
                                }
                                try {
                                         response.getOutputStream().write((i+"").getBytes());
                                } catch (IOExceptione) {
                                         // TODOAuto-generated catch block
                                         e.printStackTrace();
                                }
                               
                       }*/
                      
                      
             }
     
     
             protected voiddoPost(HttpServletRequest request, HttpServletResponse response) throwsServletException {
                       // TODO Auto-generated methodstub
             }
     
    }
     
     
    packageservletThread;
     
    publicclass Person {
             /*public int age;  //此时没有线程安全,*/
             public static int age; //此时会有线程安全问题,因为静态的资源,在类加载时,就加载进来,只有一个共享资源,供所有Servlet访问。所以要
             //谨慎使用static,如在List static list =newArrayList(); add之后,一般要remove();
    }

    //子类在覆盖福雷的方法是,不能抛出比父类更多的异常

    1.8  Tip:ServletConfig对象

    在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。

    当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

    阅读ServletConfig API,并举例说明该对象的作用:

    获得字符集编码

    获得数据库连接信息

    获得配置文件,查看struts案例的web.xml文件


    这里写图片描述


      

     <servlet>
       <servlet-name>ServeletDemo05</servlet-name>
       <servlet-class>webdemo01.ServeletDemo05</servlet-class>
         <init-param>
                 <param-name>data</param-name>
                 <param-value>xxxx</param-value>
        </init-param>
        <init-param>
                 <param-name>data2</param-name>
                 <param-value>yyyy</param-value>
        </init-param>
      </servlet>
     
     
    ----------------------------------------------------------------------------------------------------------------------------------------
    packageservletThread;
     
    importjava.io.IOException;
    importjava.util.Enumeration;
     
    importjavax.servlet.ServletConfig;
    importjavax.servlet.ServletException;
    importjavax.servlet.annotation.WebInitParam;
    importjavax.servlet.annotation.WebServlet;
    importjavax.servlet.http.HttpServlet;
    importjavax.servlet.http.HttpServletRequest;
    importjavax.servlet.http.HttpServletResponse;
     
     
    publicclass ServletDemo06 extends HttpServlet {
             private static final longserialVersionUID = 1L;
             private ServletConfig config;
     
     
             protected void doGet(HttpServletRequestrequest, HttpServletResponse response) throws ServletException, IOException {
                       String s=config.getInitParameter("data");
                      
                       //String s1=this.getServletConfig().getInitParameter("data");
                       response.getOutputStream().write(s.getBytes());
                      
                       //得到所有的
                       Enumeration<String> e=this.getInitParameterNames();
                       while (e.hasMoreElements()) {
                                String object =(String) e.nextElement();
                                String value1=this.getServletConfig().getInitParameter(object);
                                System.out.println(value1);
                       }
             }
     
     
             @Override
             public void init(ServletConfig config)throws ServletException {
                       this.config = config;
                       super.init(config);
             }
     
    
    }

    版权声明:本文为小平果原创文章,转载请注明:http://blog.csdn.net/i10630226

  • 相关阅读:
    SharePoint 2013 图文开发系列之自定义字段
    SharePoint 2013 图文开发系列之Visual Studio 创建母版页
    SharePoint 2013 图文开发系列之代码定义列表
    SharePoint 2013 图文开发系列之计时器任务
    SharePoint 2013 图文开发系列之应用程序页
    SharePoint 2013 图文开发系列之事件接收器
    SharePoint 2013 图文开发系列之可视化WebPart
    SharePoint 2013 图文开发系列之WebPart
    SharePoint 2013 对二进制大型对象(BLOB)进行爬网
    SharePoint 2013 状态机工作流之日常报销示例
  • 原文地址:https://www.cnblogs.com/dingxiaoyue/p/4948249.html
Copyright © 2011-2022 走看看