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类部署到webserver中。

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

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

    在Java程序中,怎样才干向IE浏览器输出数据?

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

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

    1.2  Servlet在web应用中的位置

     这里写图片描写叙述

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

    Servlet程序是由WEBserver(Tomcat)调用,webserver收到client的Servlet訪问请求后:

    ①Webserver首先检查是否已经装载并创建了该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)

    client是通过URL地址訪问webserver中的资源。所以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>                                                            在server中的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引擎来控制和调度。

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

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

    可是依据HttpServletRequest,HttpServletResponse生命周期非常短,假如不是并发。server就没事。

    假设在<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。

    当訪问Tomcatserver中的某个静态HTML文件和图片时,实际上是在訪问这个缺省Servlet。

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

    当多个client并发訪问同一个Servlet时。webserver会为每个client的訪问请求创建一个线程,并在这个线程上调用Servlet的service方法。因此service方法内假设訪问了同一个资源的话(有资源共享),就有可能引发线程安全问题。

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

    SingleThreadModel接口中未定义不论什么方法,仅仅要在Servlet类的定义中添加实现SingleThreadModel接口的声明就可以。

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

    实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题。假设client不能訪问,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);
             }
     
    
    }

  • 相关阅读:
    《C# to IL》第一章 IL入门
    multiple users to one ec2 instance setup
    Route53 health check与 Cloudwatch alarm 没法绑定
    rsync aws ec2 pem
    通过jvm 查看死锁
    wait, notify 使用清晰讲解
    for aws associate exam
    docker 容器不能联网
    本地运行aws lambda credential 配置 (missing credential config error)
    Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6849040.html
Copyright © 2011-2022 走看看